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

View File

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

View File

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

View File

@ -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;
#else
typedef struct LockInfoData
{
LockRelId lockRelId;
} LockInfoData;
#endif
typedef LockInfoData *LockInfo;
#define LockInfoIsValid(lockinfo) \
((PointerIsValid(lockinfo)) && ((LockInfo) lockinfo)->initialized)
#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo)
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 \
)
extern Oid LockRelIdGetRelationId(LockRelId lockRelId);
extern void RelationInitLockInfo(Relation relation);
extern void RelationSetLockForDescriptorOpen(Relation relation);
extern void RelationSetLockForRead(Relation relation);

View File

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

View File

@ -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 <storage/lmgr.h>
#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