lmgr.c 5.8 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * lmgr.c
4
 *	  POSTGRES lock manager code
5
 *
B
Add:  
Bruce Momjian 已提交
6 7
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.40 2000/05/31 00:28:30 petere Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
15

16
#include "postgres.h"
17

B
Bruce Momjian 已提交
18
#include "access/transam.h"
B
Bruce Momjian 已提交
19
#include "catalog/catalog.h"
20
#include "miscadmin.h"
21
#include "utils/inval.h"
22 23


B
Bruce Momjian 已提交
24
static LOCKMASK LockConflicts[] = {
V
Vadim B. Mikheev 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
	(int) NULL,

/* AccessShareLock */
	(1 << AccessExclusiveLock),

/* RowShareLock */
	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),

/* RowExclusiveLock */
	(1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
	(1 << AccessExclusiveLock),

/* ShareLock */
	(1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) |
	(1 << RowExclusiveLock) | (1 << AccessExclusiveLock),

/* ShareRowExclusiveLock */
	(1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) |
	(1 << ShareLock) | (1 << RowExclusiveLock) | (1 << AccessExclusiveLock),

/* ExclusiveLock */
	(1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
	(1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock),

/* AccessExclusiveLock */
	(1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
B
Bruce Momjian 已提交
51
	(1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock) |
V
Vadim B. Mikheev 已提交
52 53 54 55 56 57 58 59 60 61 62 63
	(1 << AccessShareLock),

};

static int	LockPrios[] = {
	(int) NULL,
	1,
	2,
	3,
	4,
	5,
	6,
V
Vadim B. Mikheev 已提交
64
	7
V
Vadim B. Mikheev 已提交
65 66
};

67
LOCKMETHOD	LockTableId = (LOCKMETHOD) NULL;
V
Vadim B. Mikheev 已提交
68 69 70 71 72 73 74 75 76 77 78
LOCKMETHOD	LongTermTableId = (LOCKMETHOD) NULL;

/*
 * Create the lock table described by LockConflicts and LockPrios.
 */
LOCKMETHOD
InitLockTable()
{
	int			lockmethod;

	lockmethod = LockMethodTableInit("LockTable",
B
Bruce Momjian 已提交
79
							LockConflicts, LockPrios, MAX_LOCKMODES - 1);
V
Vadim B. Mikheev 已提交
80
	LockTableId = lockmethod;
B
Bruce Momjian 已提交
81

V
Vadim B. Mikheev 已提交
82 83 84 85
	if (!(LockTableId))
		elog(ERROR, "InitLockTable: couldnt initialize lock table");

#ifdef USER_LOCKS
B
Bruce Momjian 已提交
86

V
Vadim B. Mikheev 已提交
87 88 89 90 91 92 93 94 95 96 97 98 99 100
	/*
	 * Allocate another tableId for long-term locks
	 */
	LongTermTableId = LockMethodTableRename(LockTableId);
	if (!(LongTermTableId))
	{
		elog(ERROR,
			 "InitLockTable: couldn't rename long-term lock table");
	}
#endif

	return LockTableId;
}

101
/*
B
Bruce Momjian 已提交
102
 * RelationInitLockInfo
103
 *		Initializes the lock information in a relation descriptor.
104 105
 *
 *		relcache.c must call this during creation of any reldesc.
106 107 108 109
 */
void
RelationInitLockInfo(Relation relation)
{
110
	char	   *relname;
111 112

	Assert(RelationIsValid(relation));
113
	Assert(OidIsValid(RelationGetRelid(relation)));
114

115
	relname = (char *) RelationGetPhysicalRelationName(relation);
116

117
	relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
118 119

	if (IsSharedSystemRelationName(relname))
120
		relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
121
	else
122
		relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
123 124 125
}

/*
V
Vadim B. Mikheev 已提交
126
 *		LockRelation
127 128
 */
void
V
Vadim B. Mikheev 已提交
129
LockRelation(Relation relation, LOCKMODE lockmode)
130
{
V
Vadim B. Mikheev 已提交
131
	LOCKTAG		tag;
132 133 134 135

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
136
	MemSet(&tag, 0, sizeof(tag));
137 138
	tag.relId = relation->rd_lockInfo.lockRelId.relId;
	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
V
Vadim B. Mikheev 已提交
139 140
	tag.objId.blkno = InvalidBlockNumber;

141
	if (!LockAcquire(LockTableId, &tag, lockmode))
142
		elog(ERROR, "LockRelation: LockAcquire failed");
143 144

	/*
145 146 147 148
	 * Check to see if the relcache entry has been invalidated while we
	 * were waiting to lock it.  If so, rebuild it, or elog() trying.
	 * Increment the refcount to ensure that RelationFlushRelation will
	 * rebuild it and not just delete it.
149 150 151 152
	 */
	RelationIncrementReferenceCount(relation);
	DiscardInvalid();
	RelationDecrementReferenceCount(relation);
V
Vadim B. Mikheev 已提交
153
}
154

155
/*
V
Vadim B. Mikheev 已提交
156
 *		UnlockRelation
157 158
 */
void
V
Vadim B. Mikheev 已提交
159
UnlockRelation(Relation relation, LOCKMODE lockmode)
160
{
V
Vadim B. Mikheev 已提交
161
	LOCKTAG		tag;
162 163 164 165

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
166
	MemSet(&tag, 0, sizeof(tag));
167 168
	tag.relId = relation->rd_lockInfo.lockRelId.relId;
	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
V
Vadim B. Mikheev 已提交
169
	tag.objId.blkno = InvalidBlockNumber;
170

V
Vadim B. Mikheev 已提交
171 172
	LockRelease(LockTableId, &tag, lockmode);
}
173

174
/*
V
Vadim B. Mikheev 已提交
175
 *		LockPage
176 177
 */
void
V
Vadim B. Mikheev 已提交
178
LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
179
{
V
Vadim B. Mikheev 已提交
180
	LOCKTAG		tag;
181 182 183 184

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
185
	MemSet(&tag, 0, sizeof(tag));
186 187
	tag.relId = relation->rd_lockInfo.lockRelId.relId;
	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
V
Vadim B. Mikheev 已提交
188 189
	tag.objId.blkno = blkno;

190
	if (!LockAcquire(LockTableId, &tag, lockmode))
191
		elog(ERROR, "LockPage: LockAcquire failed");
V
Vadim B. Mikheev 已提交
192
}
193

194
/*
V
Vadim B. Mikheev 已提交
195
 *		UnlockPage
196 197
 */
void
V
Vadim B. Mikheev 已提交
198
UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
199
{
V
Vadim B. Mikheev 已提交
200
	LOCKTAG		tag;
201 202 203 204

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
205
	MemSet(&tag, 0, sizeof(tag));
206 207
	tag.relId = relation->rd_lockInfo.lockRelId.relId;
	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
V
Vadim B. Mikheev 已提交
208
	tag.objId.blkno = blkno;
209

V
Vadim B. Mikheev 已提交
210
	LockRelease(LockTableId, &tag, lockmode);
211 212 213
}

void
V
Vadim B. Mikheev 已提交
214
XactLockTableInsert(TransactionId xid)
215
{
V
Vadim B. Mikheev 已提交
216
	LOCKTAG		tag;
217 218 219 220

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
221 222 223 224
	MemSet(&tag, 0, sizeof(tag));
	tag.relId = XactLockTableId;
	tag.dbId = InvalidOid;
	tag.objId.xid = xid;
225

226
	if (!LockAcquire(LockTableId, &tag, ExclusiveLock))
227
		elog(ERROR, "XactLockTableInsert: LockAcquire failed");
228 229 230
}

void
V
Vadim B. Mikheev 已提交
231
XactLockTableDelete(TransactionId xid)
232
{
V
Vadim B. Mikheev 已提交
233
	LOCKTAG		tag;
234 235 236 237

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
238 239 240 241
	MemSet(&tag, 0, sizeof(tag));
	tag.relId = XactLockTableId;
	tag.dbId = InvalidOid;
	tag.objId.xid = xid;
242

V
Vadim B. Mikheev 已提交
243
	LockRelease(LockTableId, &tag, ExclusiveLock);
244 245 246
}

void
V
Vadim B. Mikheev 已提交
247
XactLockTableWait(TransactionId xid)
248
{
V
Vadim B. Mikheev 已提交
249
	LOCKTAG		tag;
250 251 252 253

	if (LockingDisabled())
		return;

V
Vadim B. Mikheev 已提交
254 255 256 257
	MemSet(&tag, 0, sizeof(tag));
	tag.relId = XactLockTableId;
	tag.dbId = InvalidOid;
	tag.objId.xid = xid;
258

259
	if (!LockAcquire(LockTableId, &tag, ShareLock))
260 261
		elog(ERROR, "XactLockTableWait: LockAcquire failed");

262
	LockRelease(LockTableId, &tag, ShareLock);
263

V
Vadim B. Mikheev 已提交
264
	/*
B
Bruce Momjian 已提交
265 266
	 * Transaction was committed/aborted/crashed - we have to update
	 * pg_log if transaction is still marked as running.
267
	 */
V
Vadim B. Mikheev 已提交
268 269
	if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
		TransactionIdAbort(xid);
270
}