varsup.c 3.92 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * varsup.c
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
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.41 2001/07/12 04:11:13 tgl Exp $
10 11 12
 *
 *-------------------------------------------------------------------------
 */
13

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
14
#include "postgres.h"
Marc G. Fournier's avatar
Marc G. Fournier committed
15

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
16
#include "access/transam.h"
Tom Lane's avatar
Tom Lane committed
17
#include "access/xlog.h"
18
#include "storage/proc.h"
19

20

21
/* Number of OIDs to prefetch (preallocate) per XLOG write */
Tom Lane's avatar
Tom Lane committed
22 23 24
#define VAR_OID_PREFETCH		8192

/* Spinlocks for serializing generation of XIDs and OIDs, respectively */
25 26
SPINLOCK	XidGenLockId;
SPINLOCK	OidGenLockId;
27

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
28
/* pointer to "variable cache" in shared memory (set up by shmem.c) */
29
VariableCache ShmemVariableCache = NULL;
30

31 32 33 34

/*
 * Allocate the next XID for my new transaction.
 */
35
void
36
GetNewTransactionId(TransactionId *xid)
37
{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
38
	/*
39 40
	 * During bootstrap initialization, we return the special bootstrap
	 * transaction id.
41
	 */
42 43
	if (AMI_OVERRIDE)
	{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
44
		*xid = AmiTransactionId;
45 46 47
		return;
	}

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
48
	SpinAcquire(XidGenLockId);
Tom Lane's avatar
Tom Lane committed
49

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
50
	*xid = ShmemVariableCache->nextXid;
51

Tom Lane's avatar
Tom Lane committed
52
	(ShmemVariableCache->nextXid)++;
53

54 55 56 57 58 59 60 61 62 63 64 65
	/*
	 * Must set MyProc->xid before releasing XidGenLock.  This ensures that
	 * when GetSnapshotData calls ReadNewTransactionId, all active XIDs
	 * before the returned value of nextXid are already present in the shared
	 * PROC array.  Else we have a race condition.
	 *
	 * XXX by storing xid into MyProc without acquiring SInvalLock, we are
	 * relying on fetch/store of an xid to be atomic, else other backends
	 * might see a partially-set xid here.  But holding both locks at once
	 * would be a nasty concurrency hit (and at this writing, could cause a
	 * deadlock against GetSnapshotData).  So for now, assume atomicity.
	 */
Tom Lane's avatar
Tom Lane committed
66 67
	if (MyProc != (PROC *) NULL)
		MyProc->xid = *xid;
68 69

	SpinRelease(XidGenLockId);
70 71
}

72
/*
Tom Lane's avatar
Tom Lane committed
73
 * Read nextXid but don't allocate it.
74 75 76 77
 */
void
ReadNewTransactionId(TransactionId *xid)
{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
78
	/*
79 80
	 * During bootstrap initialization, we return the special bootstrap
	 * transaction id.
81 82 83
	 */
	if (AMI_OVERRIDE)
	{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
84
		*xid = AmiTransactionId;
85 86 87
		return;
	}

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
88 89 90
	SpinAcquire(XidGenLockId);
	*xid = ShmemVariableCache->nextXid;
	SpinRelease(XidGenLockId);
91 92
}

93
/* ----------------------------------------------------------------
94
 *					object id generation support
95 96 97
 * ----------------------------------------------------------------
 */

98
static Oid	lastSeenOid = InvalidOid;
99 100

void
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
101
GetNewObjectId(Oid *oid_return)
102
{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
103
	SpinAcquire(OidGenLockId);
104

Tom Lane's avatar
Tom Lane committed
105
	/* If we run out of logged for use oids then we must log more */
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
106
	if (ShmemVariableCache->oidCount == 0)
107
	{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
108 109
		XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH);
		ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
110 111 112
	}

	if (PointerIsValid(oid_return))
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
113
		lastSeenOid = (*oid_return) = ShmemVariableCache->nextOid;
114

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
115 116 117 118
	(ShmemVariableCache->nextOid)++;
	(ShmemVariableCache->oidCount)--;

	SpinRelease(OidGenLockId);
119
}
120 121 122 123

void
CheckMaxObjectId(Oid assigned_oid)
{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
124
	if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
125 126
		return;

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
127
	SpinAcquire(OidGenLockId);
Tom Lane's avatar
Tom Lane committed
128

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
129 130 131 132 133 134
	if (assigned_oid < ShmemVariableCache->nextOid)
	{
		lastSeenOid = ShmemVariableCache->nextOid - 1;
		SpinRelease(OidGenLockId);
		return;
	}
135

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
136
	/* If we are in the logged oid range, just bump nextOid up */
137 138
	if (assigned_oid <= ShmemVariableCache->nextOid +
		ShmemVariableCache->oidCount - 1)
139
	{
140
		ShmemVariableCache->oidCount -=
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
141 142 143
			assigned_oid - ShmemVariableCache->nextOid + 1;
		ShmemVariableCache->nextOid = assigned_oid + 1;
		SpinRelease(OidGenLockId);
144 145 146
		return;
	}

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
147
	/*
148 149 150
	 * We have exceeded the logged oid range. We should lock the database
	 * and kill all other backends but we are loading oid's that we can
	 * not guarantee are unique anyway, so we must rely on the user.
151 152
	 */

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
153 154 155 156
	XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
	ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
	ShmemVariableCache->nextOid = assigned_oid + 1;

157
	SpinRelease(OidGenLockId);
158
}