diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-04-29 22:28:24 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-04-29 22:28:24 +0000 |
| commit | 3a694bb0a16fea1662f1ffd31506a72effdd4a93 (patch) | |
| tree | 50bbf16b3117aada49b2709f524b3bdcf1a36815 /src/backend/storage/lmgr/lmgr.c | |
| parent | 32d3b47e6f05c7137debddb68730a25fe1bb0cd6 (diff) | |
| download | postgresql-3a694bb0a16fea1662f1ffd31506a72effdd4a93.tar.gz | |
Restructure LOCKTAG as per discussions of a couple months ago.
Essentially, we shoehorn in a lockable-object-type field by taking
a byte away from the lockmethodid, which can surely fit in one byte
instead of two. This allows less artificial definitions of all the
other fields of LOCKTAG; we can get rid of the special pg_xactlock
pseudo-relation, and also support locks on individual tuples and
general database objects (including shared objects). None of those
possibilities are actually exploited just yet, however.
I removed pg_xactlock from pg_class, but did not force initdb for
that change. At this point, relkind 's' (SPECIAL) is unused and
could be removed entirely.
Diffstat (limited to 'src/backend/storage/lmgr/lmgr.c')
| -rw-r--r-- | src/backend/storage/lmgr/lmgr.c | 124 |
1 files changed, 74 insertions, 50 deletions
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index c1a69401ce..d527724b9a 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.71 2004/12/31 22:01:05 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.72 2005/04/29 22:28:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,7 +25,10 @@ #include "utils/inval.h" -static LOCKMASK LockConflicts[] = { +/* + * This conflict table defines the semantics of the various lock modes. + */ +static const LOCKMASK LockConflicts[] = { 0, /* AccessShareLock */ @@ -69,6 +72,7 @@ static LOCKMASK LockConflicts[] = { static LOCKMETHODID LockTableId = INVALID_LOCKMETHOD; + /* * Create the lock table described by LockConflicts */ @@ -96,11 +100,11 @@ InitLockTable(int maxBackends) #ifdef USER_LOCKS /* - * Allocate another tableId for long-term locks + * Allocate another tableId for user locks (same shared hashtable though) */ LongTermTableId = LockMethodTableRename(LockTableId); if (!LockMethodIsValid(LongTermTableId)) - elog(ERROR, "could not rename long-term lock table"); + elog(ERROR, "could not rename user lock table"); Assert(LongTermTableId == USER_LOCKMETHOD); #endif } @@ -133,10 +137,9 @@ LockRelation(Relation relation, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relation->rd_lockInfo.lockRelId.relId; - tag.dbId = relation->rd_lockInfo.lockRelId.dbId; - tag.objId.blkno = InvalidBlockNumber; + SET_LOCKTAG_RELATION(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId); if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(), lockmode, false)) @@ -167,10 +170,9 @@ ConditionalLockRelation(Relation relation, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relation->rd_lockInfo.lockRelId.relId; - tag.dbId = relation->rd_lockInfo.lockRelId.dbId; - tag.objId.blkno = InvalidBlockNumber; + SET_LOCKTAG_RELATION(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId); if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(), lockmode, true)) @@ -197,10 +199,9 @@ UnlockRelation(Relation relation, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relation->rd_lockInfo.lockRelId.relId; - tag.dbId = relation->rd_lockInfo.lockRelId.dbId; - tag.objId.blkno = InvalidBlockNumber; + SET_LOCKTAG_RELATION(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId); LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode); } @@ -222,10 +223,7 @@ LockRelationForSession(LockRelId *relid, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relid->relId; - tag.dbId = relid->dbId; - tag.objId.blkno = InvalidBlockNumber; + SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId); if (!LockAcquire(LockTableId, &tag, InvalidTransactionId, lockmode, false)) @@ -240,30 +238,65 @@ UnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relid->relId; - tag.dbId = relid->dbId; - tag.objId.blkno = InvalidBlockNumber; + SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId); LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode); } /* + * LockRelationForExtension + * + * This lock tag is used to interlock addition of pages to relations. + * We need such locking because bufmgr/smgr definition of P_NEW is not + * race-condition-proof. + * + * We assume the caller is already holding some type of regular lock on + * the relation, so no AcceptInvalidationMessages call is needed here. + */ +void +LockRelationForExtension(Relation relation, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_RELATION_EXTEND(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId); + + if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(), + lockmode, false)) + elog(ERROR, "LockAcquire failed"); +} + +/* + * UnlockRelationForExtension + */ +void +UnlockRelationForExtension(Relation relation, LOCKMODE lockmode) +{ + LOCKTAG tag; + + SET_LOCKTAG_RELATION_EXTEND(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId); + + LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode); +} + +/* * LockPage * * Obtain a page-level lock. This is currently used by some index access - * methods to lock index pages. For heap relations, it is used only with - * blkno == 0 to signify locking the relation for extension. + * methods to lock individual index pages. */ void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relation->rd_lockInfo.lockRelId.relId; - tag.dbId = relation->rd_lockInfo.lockRelId.dbId; - tag.objId.blkno = blkno; + SET_LOCKTAG_PAGE(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId, + blkno); if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(), lockmode, false)) @@ -281,10 +314,10 @@ ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relation->rd_lockInfo.lockRelId.relId; - tag.dbId = relation->rd_lockInfo.lockRelId.dbId; - tag.objId.blkno = blkno; + SET_LOCKTAG_PAGE(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId, + blkno); return LockAcquire(LockTableId, &tag, GetTopTransactionId(), lockmode, true); @@ -298,10 +331,10 @@ UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = relation->rd_lockInfo.lockRelId.relId; - tag.dbId = relation->rd_lockInfo.lockRelId.dbId; - tag.objId.blkno = blkno; + SET_LOCKTAG_PAGE(tag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId, + blkno); LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode); } @@ -318,10 +351,7 @@ XactLockTableInsert(TransactionId xid) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = XactLockTableId; - tag.dbId = InvalidOid; /* xids are globally unique */ - tag.objId.xid = xid; + SET_LOCKTAG_TRANSACTION(tag, xid); if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock, false)) @@ -341,10 +371,7 @@ XactLockTableDelete(TransactionId xid) { LOCKTAG tag; - MemSet(&tag, 0, sizeof(tag)); - tag.relId = XactLockTableId; - tag.dbId = InvalidOid; /* xids are globally unique */ - tag.objId.xid = xid; + SET_LOCKTAG_TRANSACTION(tag, xid); LockRelease(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock); } @@ -372,10 +399,7 @@ XactLockTableWait(TransactionId xid) Assert(TransactionIdIsValid(xid)); Assert(!TransactionIdEquals(xid, myxid)); - MemSet(&tag, 0, sizeof(tag)); - tag.relId = XactLockTableId; - tag.dbId = InvalidOid; - tag.objId.xid = xid; + SET_LOCKTAG_TRANSACTION(tag, xid); if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false)) elog(ERROR, "LockAcquire failed"); |
