1 /*-------------------------------------------------------------------------
4 * POSTGRES lock manager code
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.41 2000/06/08 22:37:24 momjian Exp $
13 *-------------------------------------------------------------------------
18 #include "access/transam.h"
19 #include "catalog/catalog.h"
20 #include "miscadmin.h"
21 #include "utils/inval.h"
24 static LOCKMASK LockConflicts[] = {
28 (1 << AccessExclusiveLock),
31 (1 << ExclusiveLock) | (1 << AccessExclusiveLock),
33 /* RowExclusiveLock */
34 (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
35 (1 << AccessExclusiveLock),
38 (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) |
39 (1 << RowExclusiveLock) | (1 << AccessExclusiveLock),
41 /* ShareRowExclusiveLock */
42 (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) |
43 (1 << ShareLock) | (1 << RowExclusiveLock) | (1 << AccessExclusiveLock),
46 (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
47 (1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock),
49 /* AccessExclusiveLock */
50 (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
51 (1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock) |
52 (1 << AccessShareLock),
56 static int LockPrios[] = {
67 LOCKMETHOD LockTableId = (LOCKMETHOD) NULL;
68 LOCKMETHOD LongTermTableId = (LOCKMETHOD) NULL;
71 * Create the lock table described by LockConflicts and LockPrios.
78 lockmethod = LockMethodTableInit("LockTable",
79 LockConflicts, LockPrios, MAX_LOCKMODES - 1);
80 LockTableId = lockmethod;
83 elog(ERROR, "InitLockTable: couldnt initialize lock table");
88 * Allocate another tableId for long-term locks
90 LongTermTableId = LockMethodTableRename(LockTableId);
91 if (!(LongTermTableId))
94 "InitLockTable: couldn't rename long-term lock table");
102 * RelationInitLockInfo
103 * Initializes the lock information in a relation descriptor.
105 * relcache.c must call this during creation of any reldesc.
108 RelationInitLockInfo(Relation relation)
112 Assert(RelationIsValid(relation));
113 Assert(OidIsValid(RelationGetRelid(relation)));
115 relname = (char *) RelationGetPhysicalRelationName(relation);
117 relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
119 if (IsSharedSystemRelationName(relname))
120 relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
122 relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
129 LockRelation(Relation relation, LOCKMODE lockmode)
133 if (LockingDisabled())
136 MemSet(&tag, 0, sizeof(tag));
137 tag.relId = relation->rd_lockInfo.lockRelId.relId;
138 tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
139 tag.objId.blkno = InvalidBlockNumber;
141 if (!LockAcquire(LockTableId, &tag, lockmode))
142 elog(ERROR, "LockRelation: LockAcquire failed");
145 * Check to see if the relcache entry has been invalidated while we
146 * were waiting to lock it. If so, rebuild it, or elog() trying.
147 * Increment the refcount to ensure that RelationFlushRelation will
148 * rebuild it and not just delete it.
150 RelationIncrementReferenceCount(relation);
152 RelationDecrementReferenceCount(relation);
159 UnlockRelation(Relation relation, LOCKMODE lockmode)
163 if (LockingDisabled())
166 MemSet(&tag, 0, sizeof(tag));
167 tag.relId = relation->rd_lockInfo.lockRelId.relId;
168 tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
169 tag.objId.blkno = InvalidBlockNumber;
171 LockRelease(LockTableId, &tag, lockmode);
178 LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
182 if (LockingDisabled())
185 MemSet(&tag, 0, sizeof(tag));
186 tag.relId = relation->rd_lockInfo.lockRelId.relId;
187 tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
188 tag.objId.blkno = blkno;
190 if (!LockAcquire(LockTableId, &tag, lockmode))
191 elog(ERROR, "LockPage: LockAcquire failed");
198 UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
202 if (LockingDisabled())
205 MemSet(&tag, 0, sizeof(tag));
206 tag.relId = relation->rd_lockInfo.lockRelId.relId;
207 tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
208 tag.objId.blkno = blkno;
210 LockRelease(LockTableId, &tag, lockmode);
214 XactLockTableInsert(TransactionId xid)
218 if (LockingDisabled())
221 MemSet(&tag, 0, sizeof(tag));
222 tag.relId = XactLockTableId;
223 tag.dbId = InvalidOid;
226 if (!LockAcquire(LockTableId, &tag, ExclusiveLock))
227 elog(ERROR, "XactLockTableInsert: LockAcquire failed");
232 XactLockTableDelete(TransactionId xid)
236 if (LockingDisabled())
239 MemSet(&tag, 0, sizeof(tag));
240 tag.relId = XactLockTableId;
241 tag.dbId = InvalidOid;
244 LockRelease(LockTableId, &tag, ExclusiveLock);
249 XactLockTableWait(TransactionId xid)
253 if (LockingDisabled())
256 MemSet(&tag, 0, sizeof(tag));
257 tag.relId = XactLockTableId;
258 tag.dbId = InvalidOid;
261 if (!LockAcquire(LockTableId, &tag, ShareLock))
262 elog(ERROR, "XactLockTableWait: LockAcquire failed");
264 LockRelease(LockTableId, &tag, ShareLock);
267 * Transaction was committed/aborted/crashed - we have to update
268 * pg_log if transaction is still marked as running.
270 if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
271 TransactionIdAbort(xid);