]> granicus.if.org Git - postgresql/blob - src/backend/access/transam/varsup.c
Another pgindent run. Fixes enum indenting, and improves #endif
[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.48 2001/10/28 06:25:42 momjian 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         /*
97          * During bootstrap initialization, we return the special bootstrap
98          * transaction id.
99          */
100         if (AMI_OVERRIDE)
101                 return BootstrapTransactionId;
102
103         LWLockAcquire(XidGenLock, LW_SHARED);
104         xid = ShmemVariableCache->nextXid;
105         LWLockRelease(XidGenLock);
106
107         return xid;
108 }
109
110 /* ----------------------------------------------------------------
111  *                                      object id generation support
112  * ----------------------------------------------------------------
113  */
114
115 static Oid      lastSeenOid = InvalidOid;
116
117 Oid
118 GetNewObjectId(void)
119 {
120         Oid                     result;
121
122         LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
123
124         /*
125          * Check for wraparound of the OID counter.  We *must* not return 0
126          * (InvalidOid); and as long as we have to check that, it seems a good
127          * idea to skip over everything below BootstrapObjectIdData too. (This
128          * basically just reduces the odds of OID collision right after a wrap
129          * occurs.)  Note we are relying on unsigned comparison here.
130          */
131         if (ShmemVariableCache->nextOid < ((Oid) BootstrapObjectIdData))
132         {
133                 ShmemVariableCache->nextOid = BootstrapObjectIdData;
134                 ShmemVariableCache->oidCount = 0;
135         }
136
137         /* If we run out of logged for use oids then we must log more */
138         if (ShmemVariableCache->oidCount == 0)
139         {
140                 XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH);
141                 ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
142         }
143
144         result = ShmemVariableCache->nextOid;
145
146         (ShmemVariableCache->nextOid)++;
147         (ShmemVariableCache->oidCount)--;
148
149         LWLockRelease(OidGenLock);
150
151         lastSeenOid = result;
152
153         return result;
154 }
155
156 void
157 CheckMaxObjectId(Oid assigned_oid)
158 {
159         if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
160                 return;
161
162         LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
163
164         if (assigned_oid < ShmemVariableCache->nextOid)
165         {
166                 lastSeenOid = ShmemVariableCache->nextOid - 1;
167                 LWLockRelease(OidGenLock);
168                 return;
169         }
170
171         /* If we are in the logged oid range, just bump nextOid up */
172         if (assigned_oid <= ShmemVariableCache->nextOid +
173                 ShmemVariableCache->oidCount - 1)
174         {
175                 ShmemVariableCache->oidCount -=
176                         assigned_oid - ShmemVariableCache->nextOid + 1;
177                 ShmemVariableCache->nextOid = assigned_oid + 1;
178                 LWLockRelease(OidGenLock);
179                 return;
180         }
181
182         /*
183          * We have exceeded the logged oid range. We should lock the database
184          * and kill all other backends but we are loading oid's that we can
185          * not guarantee are unique anyway, so we must rely on the user.
186          */
187
188         XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
189         ShmemVariableCache->nextOid = assigned_oid + 1;
190         ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
191
192         LWLockRelease(OidGenLock);
193 }