1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

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.
This commit is contained in:
Tom Lane
2005-04-29 22:28:24 +00:00
parent 32d3b47e6f
commit 3a694bb0a1
14 changed files with 347 additions and 255 deletions

View File

@@ -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");