1 /*-------------------------------------------------------------------------
4 * postgres OID & XID variables support routines
6 * Copyright (c) 2000, PostgreSQL Global Development Group
9 * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.42 2001/07/16 22:43:33 tgl Exp $
11 *-------------------------------------------------------------------------
16 #include "access/transam.h"
17 #include "access/xlog.h"
18 #include "storage/proc.h"
21 /* Number of OIDs to prefetch (preallocate) per XLOG write */
22 #define VAR_OID_PREFETCH 8192
24 /* Spinlocks for serializing generation of XIDs and OIDs, respectively */
25 SPINLOCK XidGenLockId;
26 SPINLOCK OidGenLockId;
28 /* pointer to "variable cache" in shared memory (set up by shmem.c) */
29 VariableCache ShmemVariableCache = NULL;
33 * Allocate the next XID for my new transaction.
36 GetNewTransactionId(TransactionId *xid)
39 * During bootstrap initialization, we return the special bootstrap
44 *xid = AmiTransactionId;
48 SpinAcquire(XidGenLockId);
50 *xid = ShmemVariableCache->nextXid;
52 (ShmemVariableCache->nextXid)++;
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.
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.
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.)
74 if (MyProc != (PROC *) NULL)
77 SpinRelease(XidGenLockId);
81 * Read nextXid but don't allocate it.
84 ReadNewTransactionId(TransactionId *xid)
87 * During bootstrap initialization, we return the special bootstrap
92 *xid = AmiTransactionId;
96 SpinAcquire(XidGenLockId);
97 *xid = ShmemVariableCache->nextXid;
98 SpinRelease(XidGenLockId);
101 /* ----------------------------------------------------------------
102 * object id generation support
103 * ----------------------------------------------------------------
106 static Oid lastSeenOid = InvalidOid;
109 GetNewObjectId(Oid *oid_return)
111 SpinAcquire(OidGenLockId);
113 /* If we run out of logged for use oids then we must log more */
114 if (ShmemVariableCache->oidCount == 0)
116 XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH);
117 ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
120 if (PointerIsValid(oid_return))
121 lastSeenOid = (*oid_return) = ShmemVariableCache->nextOid;
123 (ShmemVariableCache->nextOid)++;
124 (ShmemVariableCache->oidCount)--;
126 SpinRelease(OidGenLockId);
130 CheckMaxObjectId(Oid assigned_oid)
132 if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
135 SpinAcquire(OidGenLockId);
137 if (assigned_oid < ShmemVariableCache->nextOid)
139 lastSeenOid = ShmemVariableCache->nextOid - 1;
140 SpinRelease(OidGenLockId);
144 /* If we are in the logged oid range, just bump nextOid up */
145 if (assigned_oid <= ShmemVariableCache->nextOid +
146 ShmemVariableCache->oidCount - 1)
148 ShmemVariableCache->oidCount -=
149 assigned_oid - ShmemVariableCache->nextOid + 1;
150 ShmemVariableCache->nextOid = assigned_oid + 1;
151 SpinRelease(OidGenLockId);
156 * We have exceeded the logged oid range. We should lock the database
157 * and kill all other backends but we are loading oid's that we can
158 * not guarantee are unique anyway, so we must rely on the user.
161 XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
162 ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
163 ShmemVariableCache->nextOid = assigned_oid + 1;
165 SpinRelease(OidGenLockId);