mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
Initial MVCC code.
New code for locking buffer' context.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
}
|
||||
|
@@ -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... */
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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,215 +161,44 @@ 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);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* RelationUnsetLockForRead --
|
||||
* Unsets relation level read lock.
|
||||
*/
|
||||
void
|
||||
RelationUnsetLockForRead(Relation relation)
|
||||
{
|
||||
LockInfo lockinfo;
|
||||
|
||||
/* ----------------
|
||||
* 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,
|
||||
"Releasing a lock on %s with invalid lock information",
|
||||
RelationGetRelationName(relation));
|
||||
}
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = lockinfo->lockRelId.relId;
|
||||
tag.dbId = lockinfo->lockRelId.dbId;
|
||||
tag.objId.blkno = InvalidBlockNumber;
|
||||
|
||||
MultiReleaseReln(lockinfo, READ_LOCK);
|
||||
LockAcquire(LockTableId, &tag, lockmode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* RelationSetLockForWrite --
|
||||
* Sets relation level write lock.
|
||||
* UnlockRelation
|
||||
*/
|
||||
void
|
||||
RelationSetLockForWrite(Relation relation)
|
||||
UnlockRelation(Relation relation, 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);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* RelationUnsetLockForWrite --
|
||||
* Unsets relation level write lock.
|
||||
*/
|
||||
void
|
||||
RelationUnsetLockForWrite(Relation relation)
|
||||
{
|
||||
LockInfo lockinfo;
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
if (LockingDisabled())
|
||||
return;
|
||||
|
||||
@@ -303,309 +211,127 @@ 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 = InvalidBlockNumber;
|
||||
|
||||
LockRelease(LockTableId, &tag, lockmode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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.
|
||||
* LockPage
|
||||
*/
|
||||
void
|
||||
RelationSetLockForWritePage(Relation relation,
|
||||
ItemPointer itemPointer)
|
||||
LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
|
||||
{
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
if (LockingDisabled())
|
||||
return;
|
||||
LockInfo lockinfo;
|
||||
LOCKTAG tag;
|
||||
|
||||
/* ---------------
|
||||
* Make sure lockinfo is initialized
|
||||
* ---------------
|
||||
*/
|
||||
if (!LockInfoIsValid(relation->lockInfo))
|
||||
RelationInitLockInfo(relation);
|
||||
|
||||
/* ----------------
|
||||
* attempt to set lock
|
||||
* ----------------
|
||||
*/
|
||||
MultiLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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)
|
||||
{
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
if (LockingDisabled())
|
||||
return;
|
||||
|
||||
if (!LockInfoIsValid(relation->lockInfo))
|
||||
RelationInitLockInfo(relation);
|
||||
|
||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, !UNLOCK);
|
||||
lockinfo = (LockInfo) relation->lockInfo;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = lockinfo->lockRelId.relId;
|
||||
tag.dbId = lockinfo->lockRelId.dbId;
|
||||
tag.objId.blkno = blkno;
|
||||
|
||||
LockAcquire(LockTableId, &tag, lockmode);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unset a single level write page lock
|
||||
* UnlockPage
|
||||
*/
|
||||
void
|
||||
RelationUnsetSingleWLockPage(Relation relation,
|
||||
ItemPointer itemPointer)
|
||||
UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
|
||||
{
|
||||
LockInfo lockinfo;
|
||||
LOCKTAG tag;
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
if (LockingDisabled())
|
||||
return;
|
||||
|
||||
if (!LockInfoIsValid(relation->lockInfo))
|
||||
lockinfo = (LockInfo) relation->lockInfo;
|
||||
|
||||
if (!LockInfoIsValid(lockinfo))
|
||||
{
|
||||
elog(ERROR,
|
||||
"Releasing a lock on %s with invalid lock information",
|
||||
RelationGetRelationName(relation));
|
||||
}
|
||||
|
||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, UNLOCK);
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = lockinfo->lockRelId.relId;
|
||||
tag.dbId = lockinfo->lockRelId.dbId;
|
||||
tag.objId.blkno = blkno;
|
||||
|
||||
LockRelease(LockTableId, &tag, lockmode);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
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, READ_LOCK, !UNLOCK);
|
||||
LockAcquire(LockTableId, &tag, ExclusiveLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unset a single level read page lock.
|
||||
*/
|
||||
void
|
||||
RelationUnsetSingleRLockPage(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));
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = XactLockTableId;
|
||||
tag.dbId = InvalidOid;
|
||||
tag.objId.xid = xid;
|
||||
|
||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, UNLOCK);
|
||||
LockRelease(LockTableId, &tag, ExclusiveLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
XactLockTableWait(TransactionId xid)
|
||||
{
|
||||
/* -----------------
|
||||
* Sanity check
|
||||
* -----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
LOCKTAG tag;
|
||||
|
||||
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);
|
||||
}
|
||||
LockAcquire(LockTableId, &tag, ShareLock);
|
||||
|
||||
/*
|
||||
* Unset a read intent lock on a relation
|
||||
*/
|
||||
void
|
||||
RelationUnsetRIntentLock(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 (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
|
||||
TransactionIdAbort(xid);
|
||||
|
||||
if (!LockInfoIsValid(relation->lockInfo))
|
||||
RelationInitLockInfo(relation);
|
||||
|
||||
SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, UNLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a write intent lock on a relation. For a more complete explanation
|
||||
* see RelationSetRIntentLock()
|
||||
*/
|
||||
void
|
||||
RelationSetWIntentLock(Relation relation)
|
||||
{
|
||||
/* -----------------
|
||||
* Sanity check
|
||||
* -----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
if (LockingDisabled())
|
||||
return;
|
||||
|
||||
if (!LockInfoIsValid(relation->lockInfo))
|
||||
RelationInitLockInfo(relation);
|
||||
|
||||
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);
|
||||
|
||||
SingleLockReln((LockInfo) relation->lockInfo, WRITE_LOCK + INTENT, UNLOCK);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* -----------------
|
||||
*/
|
||||
Assert(RelationIsValid(relation));
|
||||
if (LockingDisabled())
|
||||
return;
|
||||
|
||||
if (!LockInfoIsValid(relation->lockInfo))
|
||||
RelationInitLockInfo(relation);
|
||||
|
||||
MultiLockReln((LockInfo) relation->lockInfo, EXTEND_LOCK);
|
||||
}
|
||||
|
||||
#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
|
||||
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user