summaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/lmgr.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-04-29 22:28:24 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-04-29 22:28:24 +0000
commit3a694bb0a16fea1662f1ffd31506a72effdd4a93 (patch)
tree50bbf16b3117aada49b2709f524b3bdcf1a36815 /src/backend/storage/lmgr/lmgr.c
parent32d3b47e6f05c7137debddb68730a25fe1bb0cd6 (diff)
downloadpostgresql-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.c124
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");