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

Lmgr cleanup, new locking modes for LLL.

This commit is contained in:
Vadim B. Mikheev
1998-08-01 15:26:38 +00:00
parent 83d3626b1f
commit 0d78e8c112
8 changed files with 125 additions and 380 deletions

View File

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

View File

@@ -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;
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.
* ------------
*/
if (LockInfoIsValid(info))
return;
}
relname = (char *) RelationGetRelationName(relation);
/* ----------------
* initialize lockinfo.dbId and .relId appropriately
* ----------------
*/
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
info = (LockInfo) palloc(sizeof(LockInfoData));
MemoryContextSwitchTo(oldcxt);
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;
}
@@ -484,120 +310,6 @@ RelationUnsetLockForWrite(Relation relation)
MultiReleaseReln(lockinfo, WRITE_LOCK);
}
/* ----------------
* 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;
}

View File

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