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