Skip to content
Snippets Groups Projects
Commit 0d78e8c1 authored by Vadim B. Mikheev's avatar Vadim B. Mikheev
Browse files

Lmgr cleanup, new locking modes for LLL.

parent 83d3626b
Branches
Tags
No related merge requests found
......@@ -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);
......
......@@ -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;
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;
if (LockInfoIsValid(info))
return;
relname = (char *) RelationGetRelationName(relation);
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;
}
/* ----------------
* 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;
}
......@@ -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;
}
......@@ -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");
......
......@@ -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);
}
}
......
......@@ -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)
......
......@@ -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)
extern LockRelId VariableRelationLockRelId;
#else
typedef struct LockInfoData
{
LockRelId lockRelId;
} LockInfoData;
#endif
/*
* 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);
......
......@@ -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 */
#ifdef LowLevelLocking
#define MAX_LOCKMODES 9
#else
#define MAX_LOCKMODES 6
#endif
/*
* MAX_LOCK_METHODS corresponds to the number of spin locks allocated in
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment