From 0d78e8c1124cb7f44f17dec2d313c2ac4b871195 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Sat, 1 Aug 1998 15:26:38 +0000 Subject: [PATCH] Lmgr cleanup, new locking modes for LLL. --- src/backend/storage/buffer/bufmgr.c | 12 +- src/backend/storage/lmgr/lmgr.c | 335 ++---------------------------------- src/backend/storage/lmgr/multi.c | 58 ++++++- src/backend/utils/cache/relcache.c | 5 +- src/include/storage/buf_internals.h | 19 +- src/include/storage/lmgr.h | 44 ++--- src/include/storage/lock.h | 8 +- src/include/storage/multilev.h | 22 ++- 8 files changed, 124 insertions(+), 379 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 97664f76f6..cffe640e2c 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.39 1998/07/13 16:34:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.40 1998/08/01 15:26:12 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -114,18 +114,18 @@ RelationGetBufferWithBuffer(Relation relation, Buffer buffer) { BufferDesc *bufHdr; - LockRelId lrelId; if (BufferIsValid(buffer)) { if (!BufferIsLocal(buffer)) { + LockRelId *lrelId = &(((LockInfo)(relation->lockInfo))->lockRelId); + bufHdr = &BufferDescriptors[buffer - 1]; - lrelId = RelationGetLockRelId(relation); SpinAcquire(BufMgrLock); if (bufHdr->tag.blockNum == blockNumber && - bufHdr->tag.relId.relId == lrelId.relId && - bufHdr->tag.relId.dbId == lrelId.dbId) + bufHdr->tag.relId.relId == lrelId->relId && + bufHdr->tag.relId.dbId == lrelId->dbId) { SpinRelease(BufMgrLock); return (buffer); @@ -1282,7 +1282,7 @@ BufferGetRelation(Buffer buffer) Assert(!BufferIsLocal(buffer)); /* not supported for local buffers */ /* XXX should be a critical section */ - relid = LockRelIdGetRelationId(BufferDescriptors[buffer - 1].tag.relId); + relid = BufferDescriptors[buffer - 1].tag.relId.relId; relation = RelationIdGetRelation(relid); RelationDecrementReferenceCount(relation); diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 5cea3b2e1f..cebbce364c 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.15 1998/07/26 04:30:41 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.16 1998/08/01 15:26:24 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -51,220 +51,48 @@ #include "storage/bufmgr.h" #include "access/transam.h" /* for AmiTransactionId */ -static void LockRelIdAssign(LockRelId *lockRelId, Oid dbId, Oid relId); - -/* ---------------- - * - * ---------------- - */ -#define MaxRetries 4 /* XXX about 1/4 minute--a hack */ - -#define IntentReadRelationLock 0x0100 -#define ReadRelationLock 0x0200 -#define IntentWriteRelationLock 0x0400 -#define WriteRelationLock 0x0800 -#define IntentReadPageLock 0x1000 -#define ReadTupleLock 0x2000 - -#define TupleLevelLockCountMask 0x000f - -#define TupleLevelLockLimit 10 - extern Oid MyDatabaseId; -LockRelId VariableRelationLockRelId = { - RelOid_pg_variable, - InvalidOid -}; - -/* - * LockRelIdGetDatabaseId -- - * Returns database identifier for a "lock" relation identifier. - */ -/* ---------------- - * LockRelIdGetDatabaseId - * - * Note: The argument may not be correct, if it is not used soon - * after it is created. - * ---------------- - */ -#ifdef NOT_USED -Oid -LockRelIdGetDatabaseId(LockRelId lockRelId) -{ - return (lockRelId.dbId); -} - -#endif - -/* - * LockRelIdGetRelationId -- - * Returns relation identifier for a "lock" relation identifier. - */ -Oid -LockRelIdGetRelationId(LockRelId lockRelId) -{ - return (lockRelId.relId); -} - -/* - * DatabaseIdIsMyDatabaseId -- - * True iff database object identifier is valid in my present database. - */ -#ifdef NOT_USED -bool -DatabaseIdIsMyDatabaseId(Oid databaseId) -{ - return (bool) - (!OidIsValid(databaseId) || databaseId == MyDatabaseId); -} - -#endif - -/* - * LockRelIdContainsMyDatabaseId -- - * True iff "lock" relation identifier is valid in my present database. - */ -#ifdef NOT_USED -bool -LockRelIdContainsMyDatabaseId(LockRelId lockRelId) -{ - return (bool) - (!OidIsValid(lockRelId.dbId) || lockRelId.dbId == MyDatabaseId); -} - -#endif - /* * RelationInitLockInfo -- * Initializes the lock information in a relation descriptor. */ -/* ---------------- - * RelationInitLockInfo - * - * XXX processingVariable is a hack to prevent problems during - * VARIABLE relation initialization. - * ---------------- - */ void RelationInitLockInfo(Relation relation) { - LockInfo info; - char *relname; - Oid relationid; - bool processingVariable; - extern Oid MyDatabaseId; /* XXX use include */ - extern GlobalMemory CacheCxt; + LockInfo info; + char *relname; + MemoryContext oldcxt; + extern Oid MyDatabaseId; /* XXX use include */ + extern GlobalMemory CacheCxt; - /* ---------------- - * sanity checks - * ---------------- - */ Assert(RelationIsValid(relation)); Assert(OidIsValid(RelationGetRelationId(relation))); - /* ---------------- - * get information from relation descriptor - * ---------------- - */ info = (LockInfo) relation->lockInfo; + + if (LockInfoIsValid(info)) + return; + relname = (char *) RelationGetRelationName(relation); - relationid = RelationGetRelationId(relation); - processingVariable = (strcmp(relname, VariableRelationName) == 0); - - /* ---------------- - * create a new lockinfo if not already done - * ---------------- - */ - if (!PointerIsValid(info)) - { - MemoryContext oldcxt; - oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); - info = (LockInfo) palloc(sizeof(LockInfoData)); - MemoryContextSwitchTo(oldcxt); - } - else if (processingVariable) - { - if (IsTransactionState()) - { - TransactionIdStore(GetCurrentTransactionId(), - &info->transactionIdData); - } - info->flags = 0x0; - return; /* prevent an infinite loop--still true? */ - } - else if (info->initialized) - { - /* ------------ - * If we've already initialized we're done. - * ------------ - */ - return; - } + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + info = (LockInfo) palloc(sizeof(LockInfoData)); + MemoryContextSwitchTo(oldcxt); - /* ---------------- - * initialize lockinfo.dbId and .relId appropriately - * ---------------- - */ + info->lockRelId.relId = RelationGetRelationId(relation); if (IsSharedSystemRelationName(relname)) - LockRelIdAssign(&info->lockRelId, InvalidOid, relationid); + info->lockRelId.dbId = InvalidOid; else - LockRelIdAssign(&info->lockRelId, MyDatabaseId, relationid); + info->lockRelId.dbId = MyDatabaseId; - /* ---------------- - * store the transaction id in the lockInfo field - * ---------------- - */ - if (processingVariable) - TransactionIdStore(AmiTransactionId, - &info->transactionIdData); - else if (IsTransactionState()) - TransactionIdStore(GetCurrentTransactionId(), - &info->transactionIdData); - else - StoreInvalidTransactionId(&(info->transactionIdData)); +#ifdef LowLevelLocking + memset(info->lockHeld, 0, sizeof(info->lockHeld)); +#endif - /* ---------------- - * initialize rest of lockinfo - * ---------------- - */ - info->flags = 0x0; - info->initialized = (bool) true; relation->lockInfo = (Pointer) info; } -/* ---------------- - * RelationDiscardLockInfo - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_20 \ -elog(DEBUG, "DiscardLockInfo: NULL relation->lockInfo") -#else -#define LOCKDEBUG_20 -#endif /* LOCKDEBUG */ - -/* - * RelationDiscardLockInfo -- - * Discards the lock information in a relation descriptor. - */ -#ifdef NOT_USED -void -RelationDiscardLockInfo(Relation relation) -{ - if (!LockInfoIsValid(relation->lockInfo)) - { - LOCKDEBUG_20; - return; - } - - pfree(relation->lockInfo); - relation->lockInfo = NULL; -} - -#endif - /* * RelationSetLockForDescriptorOpen -- * Sets read locks for a relation descriptor. @@ -337,7 +165,6 @@ RelationSetLockForRead(Relation relation) { RelationInitLockInfo(relation); lockinfo = (LockInfo) relation->lockInfo; - lockinfo->flags |= ReadRelationLock; MultiLockReln(lockinfo, READ_LOCK); return; } @@ -433,7 +260,6 @@ RelationSetLockForWrite(Relation relation) { RelationInitLockInfo(relation); lockinfo = (LockInfo) relation->lockInfo; - lockinfo->flags |= WriteRelationLock; MultiLockReln(lockinfo, WRITE_LOCK); return; } @@ -485,120 +311,6 @@ RelationUnsetLockForWrite(Relation relation) } /* ---------------- - * RelationSetLockForTupleRead - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_80 \ -elog(DEBUG, "RelationSetLockForTupleRead(%s[%d,%d], 0x%x) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, \ - itemPointer) -#define LOCKDEBUG_81 \ - elog(DEBUG, "RelationSetLockForTupleRead() escalating") -#else -#define LOCKDEBUG_80 -#define LOCKDEBUG_81 -#endif /* LOCKDEBUG */ - -/* - * RelationSetLockForTupleRead -- - * Sets tuple level read lock. - */ -#ifdef NOT_USED -void -RelationSetLockForTupleRead(Relation relation, ItemPointer itemPointer) -{ - LockInfo lockinfo; - TransactionId curXact; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - LOCKDEBUG_80; - - /* --------------------- - * If our lock info is invalid don't bother trying to short circuit - * the lock manager. - * --------------------- - */ - if (!LockInfoIsValid(relation->lockInfo)) - { - RelationInitLockInfo(relation); - lockinfo = (LockInfo) relation->lockInfo; - lockinfo->flags |= - IntentReadRelationLock | - IntentReadPageLock | - ReadTupleLock; - MultiLockTuple(lockinfo, itemPointer, READ_LOCK); - return; - } - else - lockinfo = (LockInfo) relation->lockInfo; - - /* ---------------- - * no need to set a lower granularity lock - * ---------------- - */ - curXact = GetCurrentTransactionId(); - if ((lockinfo->flags & ReadRelationLock) && - TransactionIdEquals(curXact, lockinfo->transactionIdData)) - return; - - /* ---------------- - * If we don't already have a tuple lock this transaction - * ---------------- - */ - if (!((lockinfo->flags & ReadTupleLock) && - TransactionIdEquals(curXact, lockinfo->transactionIdData))) - { - - lockinfo->flags |= - IntentReadRelationLock | - IntentReadPageLock | - ReadTupleLock; - - /* clear count */ - lockinfo->flags &= ~TupleLevelLockCountMask; - - } - else - { - if (TupleLevelLockLimit == (TupleLevelLockCountMask & - lockinfo->flags)) - { - LOCKDEBUG_81; - - /* escalate */ - MultiLockReln(lockinfo, READ_LOCK); - - /* clear count */ - lockinfo->flags &= ~TupleLevelLockCountMask; - return; - } - - /* increment count */ - lockinfo->flags = - (lockinfo->flags & ~TupleLevelLockCountMask) | - (1 + (TupleLevelLockCountMask & lockinfo->flags)); - } - - TransactionIdStore(curXact, &lockinfo->transactionIdData); - - /* ---------------- - * Lock the tuple. - * ---------------- - */ - MultiLockTuple(lockinfo, itemPointer, READ_LOCK); -} - -#endif - -/* ---------------- * RelationSetLockForReadPage * ---------------- */ @@ -902,12 +614,3 @@ RelationUnsetLockForExtend(Relation relation) #endif -/* - * Create an LockRelid --- Why not just pass in a pointer to the storage? - */ -static void -LockRelIdAssign(LockRelId *lockRelId, Oid dbId, Oid relId) -{ - lockRelId->dbId = dbId; - lockRelId->relId = relId; -} diff --git a/src/backend/storage/lmgr/multi.c b/src/backend/storage/lmgr/multi.c index 7fbd738b74..606ee4f560 100644 --- a/src/backend/storage/lmgr/multi.c +++ b/src/backend/storage/lmgr/multi.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/Attic/multi.c,v 1.20 1998/07/13 16:34:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/Attic/multi.c,v 1.21 1998/08/01 15:26:26 vadim Exp $ * * NOTES: * (1) The lock.c module assumes that the caller here is doing @@ -36,6 +36,55 @@ static bool MultiRelease(LOCKMETHOD lockmethod, LOCKTAG *tag, LOCKMODE lockmode, PG_LOCK_LEVEL level); +#ifdef LowLevelLocking + +static MASK MultiConflicts[] = { + (int) NULL, + +/* RowShareLock */ + (1 << ExclusiveLock), + +/* RowExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock), + +/* ShareLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | + (1 << RowExclusiveLock), + +/* ShareRowExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | + (1 << ShareLock) | (1 << RowExclusiveLock), + +/* ExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) | + (1 << RowExclusiveLock) | (1 << RowShareLock), + +/* ObjShareLock */ + (1 << ObjExclusiveLock), + +/* ObjExclusiveLock */ + (1 << ObjExclusiveLock) | (1 << ObjShareLock), + +/* ExtendLock */ + (1 << ExtendLock) + +}; + +/* + * write locks have higher priority than read locks and extend locks. May + * want to treat INTENT locks differently. + */ +static int MultiPrios[] = { + (int) NULL, + 2, + 1, + 2, + 1, + 1 +}; + +#else + /* * INTENT indicates to higher level that a lower level lock has been * set. For example, a write lock on a tuple conflicts with a write @@ -43,7 +92,7 @@ MultiRelease(LOCKMETHOD lockmethod, LOCKTAG *tag, LOCKMODE lockmode, * WRITE conflict between the tuple's intent lock and the relation's * write lock. */ -static int MultiConflicts[] = { +static MASK MultiConflicts[] = { (int) NULL, /* All reads and writes at any level conflict with a write lock */ (1 << WRITE_LOCK) | (1 << WRITE_INTENT) | (1 << READ_LOCK) | (1 << READ_INTENT), @@ -74,6 +123,8 @@ static int MultiPrios[] = { 1 }; +#endif /* !LowLevelLocking */ + /* * Lock table identifier for this lock table. The multi-level * lock table is ONE lock table, not three. @@ -91,7 +142,8 @@ InitMultiLevelLocks() { int lockmethod; - lockmethod = LockMethodTableInit("MultiLevelLockTable", MultiConflicts, MultiPrios, 5); + lockmethod = LockMethodTableInit("MultiLevelLockTable", + MultiConflicts, MultiPrios, MAX_LOCKMODES - 1); MultiTableId = lockmethod; if (!(MultiTableId)) elog(ERROR, "InitMultiLocks: couldnt initialize lock table"); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 4a17d5e0f0..e039e2bfdc 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.44 1998/07/27 19:38:23 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.45 1998/08/01 15:26:29 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -1101,6 +1101,8 @@ formrdesc(char *relationName, */ RelationCacheInsert(relation); + RelationInitLockInfo(relation); + /* * Determining this requires a scan on pg_class, but to do the scan * the rdesc for pg_class must already exist. Therefore we must do @@ -2021,6 +2023,7 @@ init_irels(void) ird->rd_support = support; RelationCacheInsert(ird); + RelationInitLockInfo(ird); } } diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 0a419784f1..03d249195d 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: buf_internals.h,v 1.24 1998/07/20 16:57:10 momjian Exp $ + * $Id: buf_internals.h,v 1.25 1998/08/01 15:26:34 vadim Exp $ * * NOTE * If BUFFERPAGE0 is defined, then 0 will be used as a @@ -65,24 +65,9 @@ struct buftag #define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \ ( \ (a)->blockNum = xx_blockNum, \ - (a)->relId = RelationGetLockRelId(xx_reln) \ + (a)->relId = ((LockInfo)(xx_reln->lockInfo))->lockRelId \ ) -#ifdef NOT_USED -#define COPY_BUFFERTAG(a,b) \ -( \ - (a)->blockNum = (b)->blockNum, \ - LockRelIdAssign(*(a),*(b)) \ -) - -#define EQUAL_BUFFERTAG(a,b) \ -( \ - ((a)->blockNum == (b)->blockNum && \ - OID_Equal((a)->relId.relId,(b)->relId.relId)) \ -) - -#endif - #define BAD_BUFFER_ID(bid) ((bid<1) || (bid>(NBuffers))) #define INVALID_DESCRIPTOR (-3) diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index 818a2f09e5..0ee5334472 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: lmgr.h,v 1.13 1998/07/13 16:34:56 momjian Exp $ + * $Id: lmgr.h,v 1.14 1998/08/01 15:26:36 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -27,45 +27,23 @@ typedef struct LockRelId Oid dbId; /* a database identifier */ } LockRelId; +#ifdef LowLevelLocking typedef struct LockInfoData { - bool initialized; LockRelId lockRelId; - TransactionId transactionIdData; - uint16 flags; + bool lockHeld[MAX_LOCKMODES]; /* on table level */ } LockInfoData; -typedef LockInfoData *LockInfo; - -#define LockInfoIsValid(lockinfo) \ - ((PointerIsValid(lockinfo)) && ((LockInfo) lockinfo)->initialized) +#else +typedef struct LockInfoData +{ + LockRelId lockRelId; +} LockInfoData; +#endif -extern LockRelId VariableRelationLockRelId; - -/* - * RelationGetLockRelId -- - * Returns "lock" relation identifier for a relation. - */ -/* ---------------- - * final condition is a hack to prevent problems during - * VARIABLE relation initialization - * ---------------- - */ -#define RelationGetLockRelId(relation) \ -( \ - AssertMacro(RelationIsValid(relation)), \ - (!LockInfoIsValid((LockInfo)(relation)->lockInfo)) ? \ - RelationInitLockInfo(relation) \ - : \ - (void)NULL, \ - (strcmp(RelationGetRelationName(relation)->data, \ - VariableRelationName) == 0) ? \ - VariableRelationLockRelId \ - : \ - ((LockInfo)(relation)->lockInfo)->lockRelId \ -) +typedef LockInfoData *LockInfo; +#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo) -extern Oid LockRelIdGetRelationId(LockRelId lockRelId); extern void RelationInitLockInfo(Relation relation); extern void RelationSetLockForDescriptorOpen(Relation relation); extern void RelationSetLockForRead(Relation relation); diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index 48ac1ae553..fd1f95aab9 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: lock.h,v 1.15 1998/06/30 02:33:33 momjian Exp $ + * $Id: lock.h,v 1.16 1998/08/01 15:26:37 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -40,7 +40,11 @@ typedef int LOCKMODE; typedef int LOCKMETHOD; /* MAX_LOCKMODES cannot be larger than the bits in MASK */ -#define MAX_LOCKMODES 6 +#ifdef LowLevelLocking +#define MAX_LOCKMODES 9 +#else +#define MAX_LOCKMODES 6 +#endif /* * MAX_LOCK_METHODS corresponds to the number of spin locks allocated in diff --git a/src/include/storage/multilev.h b/src/include/storage/multilev.h index ced76b9f42..7d3a3c983a 100644 --- a/src/include/storage/multilev.h +++ b/src/include/storage/multilev.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: multilev.h,v 1.11 1998/07/13 16:34:58 momjian Exp $ + * $Id: multilev.h,v 1.12 1998/08/01 15:26:38 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,24 @@ #include +#ifdef LowLevelLocking + +/* DML locks */ +#define RowShareLock 1 /* SELECT FOR UPDATE */ +#define RowExclusiveLock 2 /* INSERT, UPDATE, DELETE */ +#define ShareLock 3 +#define ShareRowExclusiveLock 4 +#define ExclusiveLock 5 + +/* DDL locks */ +#define ObjShareLock 6 +#define ObjExclusiveLock 7 + +/* Special locks */ +#define ExtendLock 8 + +#else + #define READ_LOCK 2 #define WRITE_LOCK 1 @@ -31,6 +49,8 @@ #define EXTEND_LOCK 5 +#endif /* !LowLevelLocking */ + #define SHORT_TERM 1 #define LONG_TERM 2 #define UNLOCK 0 -- 2.11.0