diff options
| author | Vadim B. Mikheev <vadim4o@yahoo.com> | 1998-12-15 12:47:01 +0000 |
|---|---|---|
| committer | Vadim B. Mikheev <vadim4o@yahoo.com> | 1998-12-15 12:47:01 +0000 |
| commit | 3f7fbf85dc5b42dfd33c803efe6c90533773576a (patch) | |
| tree | df8f84075ae7a27fa6b7ec0d063a03898e0b1bbb /src/backend/storage | |
| parent | c5a27161a188b235ce3c0afb1b12e8942ac8e963 (diff) | |
| download | postgresql-3f7fbf85dc5b42dfd33c803efe6c90533773576a.tar.gz | |
Initial MVCC code.
New code for locking buffer' context.
Diffstat (limited to 'src/backend/storage')
| -rw-r--r-- | src/backend/storage/buffer/buf_init.c | 25 | ||||
| -rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 149 | ||||
| -rw-r--r-- | src/backend/storage/buffer/s_lock.c | 21 | ||||
| -rw-r--r-- | src/backend/storage/ipc/ipci.c | 7 | ||||
| -rw-r--r-- | src/backend/storage/ipc/shmem.c | 23 | ||||
| -rw-r--r-- | src/backend/storage/large_object/inv_api.c | 18 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/Makefile | 4 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/lmgr.c | 580 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/lock.c | 49 |
9 files changed, 362 insertions, 514 deletions
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index 975e999ec2..620708aaae 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.19 1998/09/01 04:31:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.20 1998/12/15 12:46:18 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -62,13 +62,13 @@ BufferBlock BufferBlocks; #ifndef HAS_TEST_AND_SET long *NWaitIOBackendP; - #endif extern IpcSemaphoreId WaitIOSemId; long *PrivateRefCount; /* also used in freelist.c */ long *LastRefCount; /* refcounts of last ExecMain level */ +bits8 *BufferLocks; /* */ long *CommitInfoNeedsSave;/* to write buffers where we have filled * in t_infomask */ @@ -146,21 +146,6 @@ InitBufferPool(IPCKey key) foundDescs; int i; - /* check padding of BufferDesc and BufferHdr */ - - /* - * we need both checks because a sbufdesc_padded > - * PADDED_SBUFDESC_SIZE will shrink sbufdesc to the required size, - * which is bad - */ - if (sizeof(struct sbufdesc) != PADDED_SBUFDESC_SIZE || - sizeof(struct sbufdesc_unpadded) > PADDED_SBUFDESC_SIZE) - elog(ERROR, "Internal error: sbufdesc does not have the proper size, " - "contact the Postgres developers"); - if (sizeof(struct sbufdesc_unpadded) <= PADDED_SBUFDESC_SIZE / 2) - elog(ERROR, "Internal error: sbufdesc is greatly over-sized, " - "contact the Postgres developers"); - Data_Descriptors = NBuffers; Free_List_Descriptor = Data_Descriptors; Lookup_List_Descriptor = Data_Descriptors + 1; @@ -232,6 +217,7 @@ InitBufferPool(IPCKey key) buf->buf_id = i; #ifdef HAS_TEST_AND_SET S_INIT_LOCK(&(buf->io_in_progress_lock)); + S_INIT_LOCK(&(buf->cntx_lock)); #endif } @@ -252,10 +238,15 @@ InitBufferPool(IPCKey key) WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key), 1, IPCProtection, 0, 1, &status); + WaitCLSemId = IpcSemaphoreCreate(IPCKeyGetWaitCLSemaphoreKey(key), + 1, IPCProtection, + IpcSemaphoreDefaultStartValue, + 1, &status); } #endif PrivateRefCount = (long *) calloc(NBuffers, sizeof(long)); LastRefCount = (long *) calloc(NBuffers, sizeof(long)); + BufferLocks = (bits8*) calloc (NBuffers, sizeof(bits8)); CommitInfoNeedsSave = (long *) calloc(NBuffers, sizeof(long)); } diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index cab1e8084e..d5fa26b603 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.44 1998/10/08 18:29:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.45 1998/12/15 12:46:19 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -86,7 +86,6 @@ static void WaitIO(BufferDesc *buf, SPINLOCK spinlock); #ifndef HAS_TEST_AND_SET static void SignalIO(BufferDesc *buf); extern long *NWaitIOBackendP; /* defined in buf_init.c */ - #endif /* HAS_TEST_AND_SET */ static Buffer ReadBufferWithBufferLock(Relation relation, BlockNumber blockNum, @@ -583,7 +582,6 @@ BufferAlloc(Relation reln, if (buf->refcount > 1) SignalIO(buf); #endif /* !HAS_TEST_AND_SET */ - /* give up the buffer since we don't need it any more */ buf->refcount--; PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0; @@ -1096,6 +1094,7 @@ WaitIO(BufferDesc *buf, SPINLOCK spinlock) #else /* HAS_TEST_AND_SET */ IpcSemaphoreId WaitIOSemId; +IpcSemaphoreId WaitCLSemId; static void WaitIO(BufferDesc *buf, SPINLOCK spinlock) @@ -1933,3 +1932,147 @@ SetBufferCommitInfoNeedsSave(Buffer buffer) if (!BufferIsLocal(buffer)) CommitInfoNeedsSave[buffer - 1]++; } + +void +UnlockBuffers() +{ + BufferDesc *buf; + int i; + + for (i = 0; i < NBuffers; i++) + { + if (BufferLocks[i] == 0) + continue; + + Assert(BufferIsValid(i+1)); + buf = &(BufferDescriptors[i]); + +#ifdef HAS_TEST_AND_SET + S_LOCK(&(buf->cntx_lock)); +#else + IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock); +#endif + + if (BufferLocks[i] & BL_R_LOCK) + { + Assert(buf->r_locks > 0); + (buf->r_locks)--; + } + if (BufferLocks[i] & BL_RI_LOCK) + { + Assert(buf->ri_lock); + buf->ri_lock = false; + } + if (BufferLocks[i] & BL_W_LOCK) + { + Assert(buf->w_lock); + buf->w_lock = false; + } +#ifdef HAS_TEST_AND_SET + S_UNLOCK(&(buf->cntx_lock)); +#else + IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock); +#endif + BufferLocks[i] = 0; + } +} + +void +LockBuffer (Buffer buffer, int mode) +{ + BufferDesc *buf; + + Assert(BufferIsValid(buffer)); + if (BufferIsLocal(buffer)) + return; + + buf = &(BufferDescriptors[buffer-1]); + +#ifdef HAS_TEST_AND_SET + S_LOCK(&(buf->cntx_lock)); +#else + IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock); +#endif + + if (mode == BUFFER_LOCK_UNLOCK) + { + if (BufferLocks[buffer-1] & BL_R_LOCK) + { + Assert(buf->r_locks > 0); + Assert(!(buf->w_lock)); + Assert(!(BufferLocks[buffer-1] & (BL_W_LOCK | BL_RI_LOCK))) + (buf->r_locks)--; + BufferLocks[buffer-1] &= ~BL_R_LOCK; + } + else if (BufferLocks[buffer-1] & BL_W_LOCK) + { + Assert(buf->w_lock); + Assert(buf->r_locks == 0 && !buf->ri_lock); + Assert(!(BufferLocks[buffer-1] & (BL_R_LOCK | BL_RI_LOCK))) + buf->w_lock = false; + BufferLocks[buffer-1] &= ~BL_W_LOCK; + } + else + elog(ERROR, "UNLockBuffer: buffer %u is not locked", buffer); + } + else if (mode == BUFFER_LOCK_SHARE) + { + unsigned i = 0; + + Assert(!(BufferLocks[buffer-1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK))); + while (buf->ri_lock || buf->w_lock) + { +#ifdef HAS_TEST_AND_SET + S_UNLOCK(&(buf->cntx_lock)); + s_lock_sleep(i++); + S_LOCK(&(buf->cntx_lock)); +#else + IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock); + s_lock_sleep(i++) + IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock); +#endif + } + (buf->r_locks)++; + BufferLocks[buffer-1] |= BL_R_LOCK; + } + else if (mode == BUFFER_LOCK_EXCLUSIVE) + { + unsigned i = 0; + + Assert(!(BufferLocks[buffer-1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK))); + while (buf->r_locks > 0 || buf->w_lock) + { + if (buf->r_locks > 3) + { + if (!(BufferLocks[buffer-1] & BL_RI_LOCK)) + BufferLocks[buffer-1] |= BL_RI_LOCK; + buf->ri_lock = true; + } +#ifdef HAS_TEST_AND_SET + S_UNLOCK(&(buf->cntx_lock)); + s_lock_sleep(i++); + S_LOCK(&(buf->cntx_lock)); +#else + IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock); + s_lock_sleep(i++) + IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock); +#endif + } + buf->w_lock = true; + BufferLocks[buffer-1] |= BL_W_LOCK; + if (BufferLocks[buffer-1] & BL_RI_LOCK) + { + buf->ri_lock = false; + BufferLocks[buffer-1] &= ~BL_RI_LOCK; + } + } + else + elog(ERROR, "LockBuffer: unknown lock mode %d", mode); + +#ifdef HAS_TEST_AND_SET + S_UNLOCK(&(buf->cntx_lock)); +#else + IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock); +#endif + +} diff --git a/src/backend/storage/buffer/s_lock.c b/src/backend/storage/buffer/s_lock.c index a7b42bc479..439240a386 100644 --- a/src/backend/storage/buffer/s_lock.c +++ b/src/backend/storage/buffer/s_lock.c @@ -7,13 +7,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.12 1998/09/18 17:18:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.13 1998/12/15 12:46:21 vadim Exp $ * *------------------------------------------------------------------------- */ #include <stdio.h> #include <sys/time.h> +#include <unistd.h> #include "config.h" #include "c.h" @@ -52,6 +53,16 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line) } +void +s_lock_sleep(unsigned spin) +{ + struct timeval delay; + + delay.tv_sec = 0; + delay.tv_usec = s_spincycle[spin % S_NSPINCYCLE]; + (void) select(0, NULL, NULL, NULL, &delay); +} + /* * s_lock(lock) - take a spinlock with backoff @@ -59,15 +70,11 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line) void s_lock(volatile slock_t *lock, const char *file, const int line) { - int spins = 0; + unsigned spins = 0; while (TAS(lock)) { - struct timeval delay; - - delay.tv_sec = 0; - delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE]; - (void) select(0, NULL, NULL, NULL, &delay); + s_lock_sleep(spins); if (++spins > S_MAX_BUSY) { /* It's been over a minute... */ diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index f6ce9eda24..47305f3f08 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.16 1998/09/01 03:25:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.17 1998/12/15 12:46:24 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,6 @@ #include "postgres.h" #include "storage/ipc.h" -#include "storage/multilev.h" #include "storage/sinval.h" #include "storage/bufmgr.h" #include "storage/proc.h" @@ -92,7 +91,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key) * ---------------- */ InitLocks(); - if (InitMultiLevelLocks() == INVALID_TABLEID) + if (InitLockTable() == INVALID_TABLEID) elog(FATAL, "Couldn't create the lock table"); /* ---------------- @@ -145,7 +144,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key) * ---------------- */ InitLocks(); - if (InitMultiLevelLocks() == INVALID_TABLEID) + if (InitLockTable() == INVALID_TABLEID) elog(FATAL, "Couldn't attach to the lock table"); AttachSharedInvalidationState(key); diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 18b8d718d6..17416fc9ee 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.31 1998/09/01 04:31:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.32 1998/12/15 12:46:24 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -68,7 +68,8 @@ #include "utils/dynahash.h" #include "utils/hsearch.h" #include "utils/memutils.h" -#include "access/transam.h" +#include "access/xact.h" +#include "utils/tqual.h" /* shared memory global variables */ @@ -629,7 +630,6 @@ TransactionIdIsInProgress(TransactionId xid) return false; } -#ifdef LowLevelLocking /* * GetSnapshotData -- returns information about running transactions. * @@ -645,16 +645,15 @@ Snapshot GetSnapshotData(bool serialized) { Snapshot snapshot = (Snapshot) malloc(sizeof(SnapshotData)); - TransactionId snapshot->xip = (TransactionId *) - malloc(32 * sizeof(TransactionId)); ShmemIndexEnt *result; PROC *proc; TransactionId cid = GetCurrentTransactionId(); - uint count = 0; - unit free = 31; + uint32 count = 0; + uint32 have = 31; Assert(ShmemIndex); + snapshot->xip = (TransactionId *) malloc(32 * sizeof(TransactionId)); snapshot->xmax = cid; snapshot->xmin = cid; @@ -676,20 +675,20 @@ GetSnapshotData(bool serialized) continue; proc = (PROC *) MAKE_PTR(result->location); if (proc == MyProc || proc->xid < FirstTransactionId || - serialized && proc->xid >= cid) + (serialized && proc->xid >= cid)) continue; if (proc->xid < snapshot->xmin) snapshot->xmin = proc->xid; else if (proc->xid > snapshot->xmax) snapshot->xmax = proc->xid; - if (free == 0) + if (have == 0) { snapshot->xip = (TransactionId *) realloc(snapshot->xip, (count + 33) * sizeof(TransactionId)); - free = 32; + have = 32; } snapshot->xip[count] = proc->xid; - free--; + have--; count++; } @@ -699,5 +698,3 @@ GetSnapshotData(bool serialized) elog(ERROR, "GetSnapshotData: ShmemIndex corrupted"); return NULL; } - -#endif diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 740a413263..4046040419 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.43 1998/12/13 05:07:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.44 1998/12/15 12:46:26 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -203,12 +203,12 @@ inv_create(int flags) if (flags & INV_WRITE) { - RelationSetLockForWrite(r); + LockRelation(r, ExclusiveLock); retval->flags = IFS_WRLOCK | IFS_RDLOCK; } else if (flags & INV_READ) { - RelationSetLockForRead(r); + LockRelation(r, ShareLock); retval->flags = IFS_RDLOCK; } retval->flags |= IFS_ATEOF; @@ -254,12 +254,12 @@ inv_open(Oid lobjId, int flags) if (flags & INV_WRITE) { - RelationSetLockForWrite(r); + LockRelation(r, ExclusiveLock); retval->flags = IFS_WRLOCK | IFS_RDLOCK; } else if (flags & INV_READ) { - RelationSetLockForRead(r); + LockRelation(r, ShareLock); retval->flags = IFS_RDLOCK; } @@ -328,7 +328,7 @@ inv_stat(LargeObjectDesc *obj_desc, struct pgstat * stbuf) /* need read lock for stat */ if (!(obj_desc->flags & IFS_RDLOCK)) { - RelationSetLockForRead(obj_desc->heap_r); + LockRelation(obj_desc->heap_r, ShareLock); obj_desc->flags |= IFS_RDLOCK; } @@ -376,7 +376,7 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence) /* need read lock for getsize */ if (!(obj_desc->flags & IFS_RDLOCK)) { - RelationSetLockForRead(obj_desc->heap_r); + LockRelation(obj_desc->heap_r, ShareLock); obj_desc->flags |= IFS_RDLOCK; } offset += _inv_getsize(obj_desc->heap_r, @@ -458,7 +458,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) /* make sure we obey two-phase locking */ if (!(obj_desc->flags & IFS_RDLOCK)) { - RelationSetLockForRead(obj_desc->heap_r); + LockRelation(obj_desc->heap_r, ShareLock); obj_desc->flags |= IFS_RDLOCK; } @@ -516,7 +516,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes) if (!(obj_desc->flags & IFS_WRLOCK)) { - RelationSetLockForRead(obj_desc->heap_r); + LockRelation(obj_desc->heap_r, ShareLock); obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK); } diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile index 66fc25484a..88cd9d060c 100644 --- a/src/backend/storage/lmgr/Makefile +++ b/src/backend/storage/lmgr/Makefile @@ -4,7 +4,7 @@ # Makefile for storage/lmgr # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/storage/lmgr/Makefile,v 1.8 1998/07/26 04:30:40 scrappy Exp $ +# $Header: /cvsroot/pgsql/src/backend/storage/lmgr/Makefile,v 1.9 1998/12/15 12:46:29 vadim Exp $ # #------------------------------------------------------------------------- @@ -16,7 +16,7 @@ ifdef MULTIBYTE CFLAGS+= $(MBFLAGS) endif -OBJS = lmgr.o lock.o multi.o proc.o single.o +OBJS = lmgr.o lock.o proc.o all: SUBSYS.o diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 13adb8c48f..307c54e39e 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.19 1998/09/01 04:31:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.20 1998/12/15 12:46:30 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -49,6 +49,85 @@ extern Oid MyDatabaseId; +static MASK LockConflicts[] = { + (int) NULL, + +/* AccessShareLock */ + (1 << AccessExclusiveLock), + +/* RowShareLock */ + (1 << ExclusiveLock) | (1 << AccessExclusiveLock), + +/* RowExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) | + (1 << AccessExclusiveLock), + +/* ShareLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | + (1 << RowExclusiveLock) | (1 << AccessExclusiveLock), + +/* ShareRowExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | + (1 << ShareLock) | (1 << RowExclusiveLock) | (1 << AccessExclusiveLock), + +/* ExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) | + (1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock), + +/* AccessExclusiveLock */ + (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) | + (1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock) | + (1 << AccessShareLock), + +/* ExtendLock */ + (1 << ExtendLock) + +}; + +static int LockPrios[] = { + (int) NULL, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 1 +}; + +LOCKMETHOD LockTableId = (LOCKMETHOD) NULL; +LOCKMETHOD LongTermTableId = (LOCKMETHOD) NULL; + +/* + * Create the lock table described by LockConflicts and LockPrios. + */ +LOCKMETHOD +InitLockTable() +{ + int lockmethod; + + lockmethod = LockMethodTableInit("LockTable", + LockConflicts, LockPrios, MAX_LOCKMODES - 1); + LockTableId = lockmethod; + if (!(LockTableId)) + elog(ERROR, "InitLockTable: couldnt initialize lock table"); + +#ifdef USER_LOCKS + /* + * Allocate another tableId for long-term locks + */ + LongTermTableId = LockMethodTableRename(LockTableId); + if (!(LongTermTableId)) + { + elog(ERROR, + "InitLockTable: couldn't rename long-term lock table"); + } +#endif + + return LockTableId; +} + /* * RelationInitLockInfo -- * Initializes the lock information in a relation descriptor. @@ -82,130 +161,49 @@ RelationInitLockInfo(Relation relation) else info->lockRelId.dbId = MyDatabaseId; -#ifdef LowLevelLocking - memset(info->lockHeld, 0, sizeof(info->lockHeld)); -#endif - relation->lockInfo = (Pointer) info; } /* - * RelationSetLockForDescriptorOpen -- - * Sets read locks for a relation descriptor. - */ -#ifdef LOCKDEBUGALL -#define LOCKDEBUGALL_30 \ -elog(DEBUG, "RelationSetLockForDescriptorOpen(%s[%d,%d]) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId) -#else -#define LOCKDEBUGALL_30 -#endif /* LOCKDEBUGALL */ - -void -RelationSetLockForDescriptorOpen(Relation relation) -{ - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - LOCKDEBUGALL_30; - - /* ---------------- - * read lock catalog tuples which compose the relation descriptor - * XXX race condition? XXX For now, do nothing. - * ---------------- - */ -} - -/* ---------------- - * RelationSetLockForRead - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_40 \ -elog(DEBUG, "RelationSetLockForRead(%s[%d,%d]) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId) -#else -#define LOCKDEBUG_40 -#endif /* LOCKDEBUG */ - -/* - * RelationSetLockForRead -- - * Sets relation level read lock. + * LockRelation */ void -RelationSetLockForRead(Relation relation) +LockRelation(Relation relation, LOCKMODE lockmode) { LockInfo lockinfo; + LOCKTAG tag; - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; - LOCKDEBUG_40; - - /* ---------------- - * If we don't have lock info on the reln just go ahead and - * lock it without trying to short circuit the lock manager. - * ---------------- - */ if (!LockInfoIsValid(relation->lockInfo)) - { RelationInitLockInfo(relation); - lockinfo = (LockInfo) relation->lockInfo; - MultiLockReln(lockinfo, READ_LOCK); - return; - } - else - lockinfo = (LockInfo) relation->lockInfo; - MultiLockReln(lockinfo, READ_LOCK); -} + lockinfo = (LockInfo) relation->lockInfo; -/* ---------------- - * RelationUnsetLockForRead - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_50 \ -elog(DEBUG, "RelationUnsetLockForRead(%s[%d,%d]) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId) -#else -#define LOCKDEBUG_50 -#endif /* LOCKDEBUG */ + MemSet(&tag, 0, sizeof(tag)); + tag.relId = lockinfo->lockRelId.relId; + tag.dbId = lockinfo->lockRelId.dbId; + tag.objId.blkno = InvalidBlockNumber; + + LockAcquire(LockTableId, &tag, lockmode); + return; +} /* - * RelationUnsetLockForRead -- - * Unsets relation level read lock. + * UnlockRelation */ void -RelationUnsetLockForRead(Relation relation) +UnlockRelation(Relation relation, LOCKMODE lockmode) { LockInfo lockinfo; + LOCKTAG tag; - /* ---------------- - * sanity check - * ---------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; lockinfo = (LockInfo) relation->lockInfo; - /* ---------------- - * If we don't have lock info on the reln just go ahead and - * release it. - * ---------------- - */ if (!LockInfoIsValid(lockinfo)) { elog(ERROR, @@ -213,84 +211,50 @@ RelationUnsetLockForRead(Relation relation) RelationGetRelationName(relation)); } - MultiReleaseReln(lockinfo, READ_LOCK); -} + MemSet(&tag, 0, sizeof(tag)); + tag.relId = lockinfo->lockRelId.relId; + tag.dbId = lockinfo->lockRelId.dbId; + tag.objId.blkno = InvalidBlockNumber; -/* ---------------- - * RelationSetLockForWrite(relation) - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_60 \ -elog(DEBUG, "RelationSetLockForWrite(%s[%d,%d]) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId) -#else -#define LOCKDEBUG_60 -#endif /* LOCKDEBUG */ + LockRelease(LockTableId, &tag, lockmode); + return; +} /* - * RelationSetLockForWrite -- - * Sets relation level write lock. + * LockPage */ void -RelationSetLockForWrite(Relation relation) +LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { LockInfo lockinfo; + LOCKTAG tag; - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; - LOCKDEBUG_60; - - /* ---------------- - * If we don't have lock info on the reln just go ahead and - * lock it without trying to short circuit the lock manager. - * ---------------- - */ if (!LockInfoIsValid(relation->lockInfo)) - { RelationInitLockInfo(relation); - lockinfo = (LockInfo) relation->lockInfo; - MultiLockReln(lockinfo, WRITE_LOCK); - return; - } - else - lockinfo = (LockInfo) relation->lockInfo; - MultiLockReln(lockinfo, WRITE_LOCK); -} + lockinfo = (LockInfo) relation->lockInfo; -/* ---------------- - * RelationUnsetLockForWrite - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_70 \ -elog(DEBUG, "RelationUnsetLockForWrite(%s[%d,%d]) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId) -#else -#define LOCKDEBUG_70 -#endif /* LOCKDEBUG */ + MemSet(&tag, 0, sizeof(tag)); + tag.relId = lockinfo->lockRelId.relId; + tag.dbId = lockinfo->lockRelId.dbId; + tag.objId.blkno = blkno; + + LockAcquire(LockTableId, &tag, lockmode); + return; +} /* - * RelationUnsetLockForWrite -- - * Unsets relation level write lock. + * UnlockPage */ void -RelationUnsetLockForWrite(Relation relation) +UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) { LockInfo lockinfo; + LOCKTAG tag; - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; @@ -303,309 +267,71 @@ RelationUnsetLockForWrite(Relation relation) RelationGetRelationName(relation)); } - MultiReleaseReln(lockinfo, WRITE_LOCK); -} + MemSet(&tag, 0, sizeof(tag)); + tag.relId = lockinfo->lockRelId.relId; + tag.dbId = lockinfo->lockRelId.dbId; + tag.objId.blkno = blkno; -/* ---------------- - * RelationSetLockForReadPage - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_90 \ -elog(DEBUG, "RelationSetLockForReadPage(%s[%d,%d], @%d) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page) -#else -#define LOCKDEBUG_90 -#endif /* LOCKDEBUG */ - -/* ---------------- - * RelationSetLockForWritePage - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_100 \ -elog(DEBUG, "RelationSetLockForWritePage(%s[%d,%d], @%d) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page) -#else -#define LOCKDEBUG_100 -#endif /* LOCKDEBUG */ - -/* - * RelationSetLockForWritePage -- - * Sets write lock on a page. - */ -void -RelationSetLockForWritePage(Relation relation, - ItemPointer itemPointer) -{ - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - /* --------------- - * Make sure lockinfo is initialized - * --------------- - */ - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); - - /* ---------------- - * attempt to set lock - * ---------------- - */ - MultiLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK); + LockRelease(LockTableId, &tag, lockmode); + return; } -/* ---------------- - * RelationUnsetLockForReadPage - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_110 \ -elog(DEBUG, "RelationUnsetLockForReadPage(%s[%d,%d], @%d) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page) -#else -#define LOCKDEBUG_110 -#endif /* LOCKDEBUG */ - -/* ---------------- - * RelationUnsetLockForWritePage - * ---------------- - */ -#ifdef LOCKDEBUG -#define LOCKDEBUG_120 \ -elog(DEBUG, "RelationUnsetLockForWritePage(%s[%d,%d], @%d) called", \ - RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page) -#else -#define LOCKDEBUG_120 -#endif /* LOCKDEBUG */ - -/* - * Set a single level write page lock. Assumes that you already - * have a write intent lock on the relation. - */ void -RelationSetSingleWLockPage(Relation relation, - ItemPointer itemPointer) +XactLockTableInsert(TransactionId xid) { + LOCKTAG tag; - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); + MemSet(&tag, 0, sizeof(tag)); + tag.relId = XactLockTableId; + tag.dbId = InvalidOid; + tag.objId.xid = xid; - SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, !UNLOCK); + LockAcquire(LockTableId, &tag, ExclusiveLock); + return; } -/* - * Unset a single level write page lock - */ void -RelationUnsetSingleWLockPage(Relation relation, - ItemPointer itemPointer) +XactLockTableDelete(TransactionId xid) { + LOCKTAG tag; - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; - if (!LockInfoIsValid(relation->lockInfo)) - elog(ERROR, - "Releasing a lock on %s with invalid lock information", - RelationGetRelationName(relation)); - - SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, UNLOCK); -} - -/* - * Set a single level read page lock. Assumes you already have a read - * intent lock set on the relation. - */ -void -RelationSetSingleRLockPage(Relation relation, - ItemPointer itemPointer) -{ - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); - - SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, !UNLOCK); -} - -/* - * Unset a single level read page lock. - */ -void -RelationUnsetSingleRLockPage(Relation relation, - ItemPointer itemPointer) -{ - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - elog(ERROR, - "Releasing a lock on %s with invalid lock information", - RelationGetRelationName(relation)); - - SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, UNLOCK); -} - -/* - * Set a read intent lock on a relation. - * - * Usually these are set in a multi-level table when you acquiring a - * page level lock. i.e. To acquire a lock on a page you first acquire - * an intent lock on the entire relation. Acquiring an intent lock along - * allows one to use the single level locking routines later. Good for - * index scans that do a lot of page level locking. - */ -void -RelationSetRIntentLock(Relation relation) -{ - /* ----------------- - * Sanity check - * ----------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); - - SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, !UNLOCK); -} - -/* - * Unset a read intent lock on a relation - */ -void -RelationUnsetRIntentLock(Relation relation) -{ - /* ----------------- - * Sanity check - * ----------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); + MemSet(&tag, 0, sizeof(tag)); + tag.relId = XactLockTableId; + tag.dbId = InvalidOid; + tag.objId.xid = xid; - SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, UNLOCK); + LockRelease(LockTableId, &tag, ExclusiveLock); + return; } -/* - * Set a write intent lock on a relation. For a more complete explanation - * see RelationSetRIntentLock() - */ void -RelationSetWIntentLock(Relation relation) +XactLockTableWait(TransactionId xid) { - /* ----------------- - * Sanity check - * ----------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); + LOCKTAG tag; - SingleLockReln((LockInfo) relation->lockInfo, WRITE_LOCK + INTENT, !UNLOCK); -} - -/* - * Unset a write intent lock. - */ -void -RelationUnsetWIntentLock(Relation relation) -{ - /* ----------------- - * Sanity check - * ----------------- - */ - Assert(RelationIsValid(relation)); if (LockingDisabled()) return; - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); + MemSet(&tag, 0, sizeof(tag)); + tag.relId = XactLockTableId; + tag.dbId = InvalidOid; + tag.objId.xid = xid; - SingleLockReln((LockInfo) relation->lockInfo, WRITE_LOCK + INTENT, UNLOCK); -} + LockAcquire(LockTableId, &tag, ShareLock); -/* - * Extend locks are used primarily in tertiary storage devices such as - * a WORM disk jukebox. Sometimes need exclusive access to extend a - * file by a block. - */ -#ifdef NOT_USED -void -RelationSetLockForExtend(Relation relation) -{ - /* ----------------- - * Sanity check - * ----------------- + /* + * Transaction was committed/aborted/crashed - + * we have to update pg_log if transaction is still + * marked as running. */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); + if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid)) + TransactionIdAbort(xid); - MultiLockReln((LockInfo) relation->lockInfo, EXTEND_LOCK); + return; } - -#endif - -#ifdef NOT_USED -void -RelationUnsetLockForExtend(Relation relation) -{ - /* ----------------- - * Sanity check - * ----------------- - */ - Assert(RelationIsValid(relation)); - if (LockingDisabled()) - return; - - if (!LockInfoIsValid(relation->lockInfo)) - RelationInitLockInfo(relation); - - MultiReleaseReln((LockInfo) relation->lockInfo, EXTEND_LOCK); -} - -#endif diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index adc4d1a42e..7fdd8fec84 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.38 1998/10/08 18:29:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.39 1998/12/15 12:46:30 vadim Exp $ * * NOTES * Outside modules can create a lock table and acquire/release @@ -84,7 +84,7 @@ static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode, #define LOCK_PRINT_AUX(where,lock,type) \ TPRINTF(TRACE_ALL, \ - "%s: lock(%x) tbl(%d) rel(%d) db(%d) tid(%d,%d) mask(%x) " \ + "%s: lock(%x) tbl(%d) rel(%d) db(%d) obj(%u) mask(%x) " \ "hold(%d,%d,%d,%d,%d)=%d " \ "act(%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", \ where, \ @@ -92,9 +92,7 @@ static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode, lock->tag.lockmethod, \ lock->tag.relId, \ lock->tag.dbId, \ - ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+ \ - lock->tag.tupleId.ip_blkid.bi_lo), \ - lock->tag.tupleId.ip_posid, \ + lock->tag.objId.blkno, \ lock->mask, \ lock->holders[1], \ lock->holders[2], \ @@ -498,10 +496,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode) if (is_user_lock) { #ifdef USER_LOCKS_DEBUG - TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u,%u] %s", - locktag->tupleId.ip_posid, - ((locktag->tupleId.ip_blkid.bi_hi << 16) + - locktag->tupleId.ip_blkid.bi_lo), + TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u] %s", + locktag->objId.blkno, lock_types[lockmode]); #endif } @@ -550,8 +546,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode) MemSet((char *) lock->holders, 0, sizeof(int) * MAX_LOCKMODES); MemSet((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKMODES); ProcQueueInit(&(lock->waitProcs)); - Assert(BlockIdEquals(&(lock->tag.tupleId.ip_blkid), - &(locktag->tupleId.ip_blkid))); + Assert(lock->tag.objId.blkno == locktag->objId.blkno); LOCK_PRINT("LockAcquire: new", lock, lockmode); } else @@ -993,10 +988,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode) is_user_lock = (lockmethod == USER_LOCKMETHOD); if (is_user_lock) { - TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u,%u] %d", - locktag->tupleId.ip_posid, - ((locktag->tupleId.ip_blkid.bi_hi << 16) + - locktag->tupleId.ip_blkid.bi_lo), + TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u] %d", + locktag->objId.blkno, lockmode); } #endif @@ -1336,19 +1329,15 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue) { /* Should never happen */ elog(NOTICE, - "LockReleaseAll: INVALID PID: [%u,%u] [%d,%d,%d]", - lock->tag.tupleId.ip_posid, - ((lock->tag.tupleId.ip_blkid.bi_hi << 16) + - lock->tag.tupleId.ip_blkid.bi_lo), + "LockReleaseAll: INVALID PID: [%u] [%d,%d,%d]", + lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); nleft++; goto next_item; } TPRINTF(TRACE_USERLOCKS, - "LockReleaseAll: releasing user lock [%u,%u] [%d,%d,%d]", - lock->tag.tupleId.ip_posid, - ((lock->tag.tupleId.ip_blkid.bi_hi << 16) + - lock->tag.tupleId.ip_blkid.bi_lo), + "LockReleaseAll: releasing user lock [%u] [%d,%d,%d]", + lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); } else @@ -1361,10 +1350,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue) if (xidLook->tag.pid != 0) { TPRINTF(TRACE_LOCKS, - "LockReleaseAll: skiping user lock [%u,%u] [%d,%d,%d]", - lock->tag.tupleId.ip_posid, - ((lock->tag.tupleId.ip_blkid.bi_hi << 16) + - lock->tag.tupleId.ip_blkid.bi_lo), + "LockReleaseAll: skiping user lock [%u] [%d,%d,%d]", + lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); nleft++; goto next_item; @@ -1649,7 +1636,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check) */ Assert(skip_check); - Assert(MyProc->prio == 2); + Assert(MyProc->prio >= 2); lockMethodTable = LockMethodTable[1]; xidTable = lockMethodTable->xidHash; @@ -1747,10 +1734,8 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag) is_user_lock = (lockmethod == USER_LOCKMETHOD); if (is_user_lock) { - TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u,%u]", - locktag->tupleId.ip_posid, - ((locktag->tupleId.ip_blkid.bi_hi << 16) + - locktag->tupleId.ip_blkid.bi_lo)); + TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u]", + locktag->objId.blkno;, } #endif |
