]> granicus.if.org Git - postgresql/blob - src/backend/access/transam/varsup.c
Remove AMI_OVERRIDE tests from tqual.c routines; they aren't necessary
[postgresql] / src / backend / access / transam / varsup.c
1 /*-------------------------------------------------------------------------
2  *
3  * varsup.c
4  *        postgres OID & XID variables support routines
5  *
6  * Copyright (c) 2000, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  *        $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.49 2002/05/25 20:00:11 tgl Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres.h"
15
16 #include "access/clog.h"
17 #include "access/transam.h"
18 #include "storage/ipc.h"
19 #include "storage/proc.h"
20
21
22 /* Number of OIDs to prefetch (preallocate) per XLOG write */
23 #define VAR_OID_PREFETCH                8192
24
25 /* pointer to "variable cache" in shared memory (set up by shmem.c) */
26 VariableCache ShmemVariableCache = NULL;
27
28
29 /*
30  * Allocate the next XID for my new transaction.
31  */
32 TransactionId
33 GetNewTransactionId(void)
34 {
35         TransactionId xid;
36
37         /*
38          * During bootstrap initialization, we return the special bootstrap
39          * transaction id.
40          */
41         if (AMI_OVERRIDE)
42                 return BootstrapTransactionId;
43
44         LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
45
46         xid = ShmemVariableCache->nextXid;
47
48         TransactionIdAdvance(ShmemVariableCache->nextXid);
49
50         /*
51          * If we have just allocated the first XID of a new page of the commit
52          * log, zero out that commit-log page before returning. We must do
53          * this while holding XidGenLock, else another xact could acquire and
54          * commit a later XID before we zero the page.  Fortunately, a page of
55          * the commit log holds 32K or more transactions, so we don't have to
56          * do this very often.
57          */
58         ExtendCLOG(xid);
59
60         /*
61          * Must set MyProc->xid before releasing XidGenLock.  This ensures
62          * that when GetSnapshotData calls ReadNewTransactionId, all active
63          * XIDs before the returned value of nextXid are already present in
64          * the shared PROC array.  Else we have a race condition.
65          *
66          * XXX by storing xid into MyProc without acquiring SInvalLock, we are
67          * relying on fetch/store of an xid to be atomic, else other backends
68          * might see a partially-set xid here.  But holding both locks at once
69          * would be a nasty concurrency hit (and in fact could cause a
70          * deadlock against GetSnapshotData).  So for now, assume atomicity.
71          * Note that readers of PROC xid field should be careful to fetch the
72          * value only once, rather than assume they can read it multiple times
73          * and get the same answer each time.
74          *
75          * A solution to the atomic-store problem would be to give each PROC its
76          * own spinlock used only for fetching/storing that PROC's xid.
77          * (SInvalLock would then mean primarily that PROCs couldn't be added/
78          * removed while holding the lock.)
79          */
80         if (MyProc != (PROC *) NULL)
81                 MyProc->xid = xid;
82
83         LWLockRelease(XidGenLock);
84
85         return xid;
86 }
87
88 /*
89  * Read nextXid but don't allocate it.
90  */
91 TransactionId
92 ReadNewTransactionId(void)
93 {
94         TransactionId xid;
95
96         LWLockAcquire(XidGenLock, LW_SHARED);
97         xid = ShmemVariableCache->nextXid;
98         LWLockRelease(XidGenLock);
99
100         return xid;
101 }
102
103 /* ----------------------------------------------------------------
104  *                                      object id generation support
105  * ----------------------------------------------------------------
106  */
107
108 static Oid      lastSeenOid = InvalidOid;
109
110 Oid
111 GetNewObjectId(void)
112 {
113         Oid                     result;
114
115         LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
116
117         /*
118          * Check for wraparound of the OID counter.  We *must* not return 0
119          * (InvalidOid); and as long as we have to check that, it seems a good
120          * idea to skip over everything below BootstrapObjectIdData too. (This
121          * basically just reduces the odds of OID collision right after a wrap
122          * occurs.)  Note we are relying on unsigned comparison here.
123          */
124         if (ShmemVariableCache->nextOid < ((Oid) BootstrapObjectIdData))
125         {
126                 ShmemVariableCache->nextOid = BootstrapObjectIdData;
127                 ShmemVariableCache->oidCount = 0;
128         }
129
130         /* If we run out of logged for use oids then we must log more */
131         if (ShmemVariableCache->oidCount == 0)
132         {
133                 XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH);
134                 ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
135         }
136
137         result = ShmemVariableCache->nextOid;
138
139         (ShmemVariableCache->nextOid)++;
140         (ShmemVariableCache->oidCount)--;
141
142         LWLockRelease(OidGenLock);
143
144         lastSeenOid = result;
145
146         return result;
147 }
148
149 void
150 CheckMaxObjectId(Oid assigned_oid)
151 {
152         if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
153                 return;
154
155         LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
156
157         if (assigned_oid < ShmemVariableCache->nextOid)
158         {
159                 lastSeenOid = ShmemVariableCache->nextOid - 1;
160                 LWLockRelease(OidGenLock);
161                 return;
162         }
163
164         /* If we are in the logged oid range, just bump nextOid up */
165         if (assigned_oid <= ShmemVariableCache->nextOid +
166                 ShmemVariableCache->oidCount - 1)
167         {
168                 ShmemVariableCache->oidCount -=
169                         assigned_oid - ShmemVariableCache->nextOid + 1;
170                 ShmemVariableCache->nextOid = assigned_oid + 1;
171                 LWLockRelease(OidGenLock);
172                 return;
173         }
174
175         /*
176          * We have exceeded the logged oid range. We should lock the database
177          * and kill all other backends but we are loading oid's that we can
178          * not guarantee are unique anyway, so we must rely on the user.
179          */
180
181         XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
182         ShmemVariableCache->nextOid = assigned_oid + 1;
183         ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
184
185         LWLockRelease(OidGenLock);
186 }