mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
The heralded `Grand Unified Configuration scheme' (GUC)
That means you can now set your options in either or all of $PGDATA/configuration, some postmaster option (--enable-fsync=off), or set a SET command. The list of options is in backend/utils/misc/guc.c, documentation will be written post haste. pg_options is gone, so is that pq_geqo config file. Also removed were backend -K, -Q, and -T options (no longer applicable, although -d0 does the same as -Q). Added to configure an --enable-syslog option. changed all callers from TPRINTF to elog(DEBUG)
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.34 2000/04/12 17:15:33 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.35 2000/05/31 00:28:26 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -48,7 +48,6 @@ long *CurTraceBuf;
|
||||
#endif /* BMTRACE */
|
||||
int ShowPinTrace = 0;
|
||||
|
||||
int NBuffers = DEF_NBUFFERS; /* default is set in config.h */
|
||||
int Data_Descriptors;
|
||||
int Free_List_Descriptor;
|
||||
int Lookup_List_Descriptor;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.56 2000/04/12 17:15:35 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.57 2000/05/31 00:28:27 petere Exp $
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
@@ -196,7 +196,10 @@ static long pg_nofile(void);
|
||||
int
|
||||
pg_fsync(int fd)
|
||||
{
|
||||
return disableFsync ? 0 : fsync(fd);
|
||||
if (enableFsync)
|
||||
return fsync(fd);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -916,7 +919,7 @@ FileSync(File file)
|
||||
/* Need not sync if file is not dirty. */
|
||||
returnCode = 0;
|
||||
}
|
||||
else if (disableFsync)
|
||||
else if (!enableFsync)
|
||||
{
|
||||
/* Don't force the file open if pg_fsync isn't gonna sync it. */
|
||||
returnCode = 0;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.47 2000/05/16 20:48:48 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.48 2000/05/31 00:28:29 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@@ -36,9 +36,9 @@
|
||||
/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
|
||||
#include <sys/sem.h>
|
||||
#include <sys/shm.h>
|
||||
#include "miscadmin.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "libpq/libpq.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
#if defined(solaris_sparc)
|
||||
#include <sys/ipc.h>
|
||||
@@ -124,7 +124,8 @@ proc_exit(int code)
|
||||
*/
|
||||
proc_exit_inprogress = true;
|
||||
|
||||
TPRINTF(TRACE_VERBOSE, "proc_exit(%d)", code);
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "proc_exit(%d)", code);
|
||||
|
||||
/* do our shared memory exits first */
|
||||
shmem_exit(code);
|
||||
@@ -143,7 +144,8 @@ proc_exit(int code)
|
||||
(*on_proc_exit_list[on_proc_exit_index].function) (code,
|
||||
on_proc_exit_list[on_proc_exit_index].arg);
|
||||
|
||||
TPRINTF(TRACE_VERBOSE, "exit(%d)", code);
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "exit(%d)", code);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
@@ -156,7 +158,8 @@ proc_exit(int code)
|
||||
void
|
||||
shmem_exit(int code)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE, "shmem_exit(%d)", code);
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "shmem_exit(%d)", code);
|
||||
|
||||
/* ----------------
|
||||
* call all the registered callbacks.
|
||||
@@ -297,18 +300,16 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
|
||||
if (semId == -1)
|
||||
{
|
||||
#ifdef DEBUG_IPC
|
||||
EPRINTF("calling semget with %d, %d , %d\n",
|
||||
semKey,
|
||||
semNum,
|
||||
IPC_CREAT | permission);
|
||||
fprintf(stderr, "calling semget(%d, %d, 0%o)\n",
|
||||
semKey, semNum, (unsigned)(IPC_CREAT|permission));
|
||||
#endif
|
||||
semId = semget(semKey, semNum, IPC_CREAT | permission);
|
||||
|
||||
if (semId < 0)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreCreate: semget failed (%s) "
|
||||
"key=%d, num=%d, permission=%o",
|
||||
strerror(errno), semKey, semNum, permission);
|
||||
fprintf(stderr, "IpcSemaphoreCreate: semget(%d, %d, 0%o) failed: %s\n",
|
||||
semKey, semNum, (unsigned)(permission|IPC_CREAT),
|
||||
strerror(errno));
|
||||
IpcConfigTip();
|
||||
return (-1);
|
||||
}
|
||||
@@ -318,8 +319,8 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
|
||||
errStatus = semctl(semId, 0, SETALL, semun);
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreCreate: semctl failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
fprintf(stderr, "IpcSemaphoreCreate: semctl(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
semctl(semId, 0, IPC_RMID, semun);
|
||||
IpcConfigTip();
|
||||
return (-1);
|
||||
@@ -330,10 +331,11 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IPC
|
||||
EPRINTF("\nIpcSemaphoreCreate, returns %d\n", semId);
|
||||
fprintf(stderr, "IpcSemaphoreCreate returns %d\n", semId);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
return semId;
|
||||
}
|
||||
|
||||
@@ -357,13 +359,11 @@ IpcSemaphoreSet(int semId, int semno, int value)
|
||||
IpcSemaphoreSet_return = errStatus;
|
||||
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreSet: semctl failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
}
|
||||
fprintf(stderr, "IpcSemaphoreSet: semctl(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* NOT_USED */
|
||||
|
||||
/****************************************************************************/
|
||||
/* IpcSemaphoreKill(key) - removes a semaphore */
|
||||
@@ -421,8 +421,8 @@ IpcSemaphoreLock(IpcSemaphoreId semId, int sem, int lock)
|
||||
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreLock: semop failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
fprintf(stderr, "IpcSemaphoreLock: semop(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
proc_exit(255);
|
||||
}
|
||||
}
|
||||
@@ -466,8 +466,8 @@ IpcSemaphoreUnlock(IpcSemaphoreId semId, int sem, int lock)
|
||||
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreUnlock: semop failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
fprintf(stderr, "IpcSemaphoreUnlock: semop(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
proc_exit(255);
|
||||
}
|
||||
}
|
||||
@@ -516,9 +516,8 @@ IpcMemoryCreate(IpcMemoryKey memKey, uint32 size, int permission)
|
||||
|
||||
if (shmid < 0)
|
||||
{
|
||||
EPRINTF("IpcMemoryCreate: shmget failed (%s) "
|
||||
"key=%d, size=%d, permission=%o",
|
||||
strerror(errno), memKey, size, permission);
|
||||
fprintf(stderr, "IpcMemoryCreate: shmget(%d, %d, 0%o) failed: %s\n",
|
||||
memKey, size, (unsigned)(IPC_CREAT|permission), strerror(errno));
|
||||
IpcConfigTip();
|
||||
return IpcMemCreationFailed;
|
||||
}
|
||||
@@ -542,9 +541,8 @@ IpcMemoryIdGet(IpcMemoryKey memKey, uint32 size)
|
||||
|
||||
if (shmid < 0)
|
||||
{
|
||||
EPRINTF("IpcMemoryIdGet: shmget failed (%s) "
|
||||
"key=%d, size=%d, permission=%o",
|
||||
strerror(errno), memKey, size, 0);
|
||||
fprintf(stderr, "IpcMemoryIdGet: shmget(%d, %d, 0) failed: %s\n",
|
||||
memKey, size, strerror(errno));
|
||||
return IpcMemIdGetFailed;
|
||||
}
|
||||
|
||||
@@ -583,8 +581,8 @@ IpcMemoryAttach(IpcMemoryId memId)
|
||||
/* if ( *memAddress == -1) { XXX ??? */
|
||||
if (memAddress == (char *) -1)
|
||||
{
|
||||
EPRINTF("IpcMemoryAttach: shmat failed (%s) id=%d",
|
||||
strerror(errno), memId);
|
||||
fprintf(stderr, "IpcMemoryAttach: shmat(id=%d) failed: %s\n",
|
||||
memId, strerror(errno));
|
||||
return IpcMemAttachFailed;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.31 2000/05/30 00:49:52 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.32 2000/05/31 00:28:29 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -268,8 +268,8 @@ SIInsertDataEntry(SISeg *segP, SharedInvalidData *data)
|
||||
if (numMsgs == (MAXNUMMESSAGES * 70 / 100) &&
|
||||
IsUnderPostmaster)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE,
|
||||
"SIInsertDataEntry: table is 70%% full, signaling postmaster");
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "SIInsertDataEntry: table is 70%% full, signaling postmaster");
|
||||
kill(getppid(), SIGUSR2);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.24 2000/04/12 17:15:37 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.25 2000/05/31 00:28:29 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "storage/proc.h"
|
||||
#include "storage/s_lock.h"
|
||||
|
||||
|
||||
/* globals used in this file */
|
||||
IpcSemaphoreId SpinLockId;
|
||||
|
||||
@@ -84,14 +85,23 @@ InitSpinLocks(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOCKDEBUG
|
||||
#define PRINT_LOCK(LOCK) \
|
||||
TPRINTF(TRACE_SPINLOCKS, \
|
||||
"(locklock = %d, flag = %d, nshlocks = %d, shlock = %d, " \
|
||||
"exlock =%d)\n", LOCK->locklock, \
|
||||
LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
|
||||
LOCK->exlock)
|
||||
#endif
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
bool Trace_spinlocks = false;
|
||||
|
||||
inline static void
|
||||
PRINT_SLDEBUG(const char * where, SPINLOCK lockid, const SLock * lock)
|
||||
{
|
||||
if (Trace_spinlocks)
|
||||
elog(DEBUG,
|
||||
"%s: id=%d (locklock=%d, flag=%d, nshlocks=%d, shlock=%d, exlock=%d)",
|
||||
where, lockid,
|
||||
lock->locklock, lock->flag, lock->nshlocks, lock->shlock, lock->exlock);
|
||||
}
|
||||
#else /* not LOCK_DEBUG */
|
||||
#define PRINT_SLDEBUG(a,b,c)
|
||||
#endif /* not LOCK_DEBUG */
|
||||
|
||||
|
||||
/* from ipc.c */
|
||||
extern SLock *SLockArray;
|
||||
@@ -103,10 +113,7 @@ SpinAcquire(SPINLOCK lockid)
|
||||
|
||||
/* This used to be in ipc.c, but move here to reduce function calls */
|
||||
slckP = &(SLockArray[lockid]);
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "SpinAcquire: %d", lockid);
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinAcquire", lockid, slckP);
|
||||
ex_try_again:
|
||||
S_LOCK(&(slckP->locklock));
|
||||
switch (slckP->flag)
|
||||
@@ -116,10 +123,7 @@ ex_try_again:
|
||||
S_LOCK(&(slckP->exlock));
|
||||
S_LOCK(&(slckP->shlock));
|
||||
S_UNLOCK(&(slckP->locklock));
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "OUT: ");
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("OUT", lockid, slckP);
|
||||
break;
|
||||
case SHAREDLOCK:
|
||||
case EXCLUSIVELOCK:
|
||||
@@ -129,9 +133,7 @@ ex_try_again:
|
||||
goto ex_try_again;
|
||||
}
|
||||
PROC_INCR_SLOCK(lockid);
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "SpinAcquire: got %d", lockid);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinAcquire/success", lockid, slckP);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -142,23 +144,16 @@ SpinRelease(SPINLOCK lockid)
|
||||
/* This used to be in ipc.c, but move here to reduce function calls */
|
||||
slckP = &(SLockArray[lockid]);
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
|
||||
/*
|
||||
* Check that we are actually holding the lock we are releasing. This
|
||||
* can be done only after MyProc has been initialized.
|
||||
*/
|
||||
if (MyProc)
|
||||
Assert(MyProc->sLocks[lockid] > 0);
|
||||
Assert(!MyProc || MyProc->sLocks[lockid] > 0);
|
||||
Assert(slckP->flag != NOLOCK);
|
||||
#endif
|
||||
|
||||
|
||||
PROC_DECR_SLOCK(lockid);
|
||||
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF("SpinRelease: %d\n", lockid);
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinRelease", lockid, slckP);
|
||||
S_LOCK(&(slckP->locklock));
|
||||
/* -------------
|
||||
* give favor to read processes
|
||||
@@ -178,13 +173,10 @@ SpinRelease(SPINLOCK lockid)
|
||||
S_UNLOCK(&(slckP->shlock));
|
||||
S_UNLOCK(&(slckP->exlock));
|
||||
S_UNLOCK(&(slckP->locklock));
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "SpinRelease: released %d", lockid);
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinRelease/released", lockid, slckP);
|
||||
}
|
||||
|
||||
#else /* HAS_TEST_AND_SET */
|
||||
#else /* !HAS_TEST_AND_SET */
|
||||
/* Spinlocks are implemented using SysV semaphores */
|
||||
|
||||
static bool AttachSpinLocks(IPCKey key);
|
||||
@@ -290,4 +282,4 @@ InitSpinLocks(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* HAS_TEST_AND_SET */
|
||||
#endif /* !HAS_TEST_AND_SET */
|
||||
|
||||
@@ -8,17 +8,10 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.39 2000/04/12 17:15:38 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.40 2000/05/31 00:28:30 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/* #define LOCKDEBUGALL 1 */
|
||||
/* #define LOCKDEBUG 1 */
|
||||
|
||||
#ifdef LOCKDEBUGALL
|
||||
#define LOCKDEBUG 1
|
||||
#endif /* LOCKDEBUGALL */
|
||||
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.67 2000/04/30 21:23:31 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.68 2000/05/31 00:28:30 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@@ -39,106 +39,11 @@
|
||||
#include "miscadmin.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode);
|
||||
|
||||
/*
|
||||
* lockDebugRelation can be used to trace unconditionally a single relation,
|
||||
* for example pg_listener, if you suspect there are locking problems.
|
||||
*
|
||||
* lockDebugOidMin is is used to avoid tracing postgres relations, which
|
||||
* would produce a lot of output. Unfortunately most system relations are
|
||||
* created after bootstrap and have oid greater than BootstrapObjectIdData.
|
||||
* If you are using tprintf you should specify a value greater than the max
|
||||
* oid of system relations, which can be found with the following query:
|
||||
*
|
||||
* select max(int4in(int4out(oid))) from pg_class where relname ~ '^pg_';
|
||||
*
|
||||
* To get a useful lock trace you can use the following pg_options:
|
||||
*
|
||||
* -T "verbose,query,locks,userlocks,lock_debug_oidmin=17500"
|
||||
*/
|
||||
#define LOCKDEBUG(lockmethod) (pg_options[TRACE_SHORTLOCKS+lockmethod])
|
||||
#define lockDebugRelation (pg_options[TRACE_LOCKRELATION])
|
||||
#define lockDebugOidMin (pg_options[TRACE_LOCKOIDMIN])
|
||||
#define lockReadPriority (pg_options[OPT_LOCKREADPRIORITY])
|
||||
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
#define LOCK_PRINT(where,lock,type) \
|
||||
if (((LOCKDEBUG(LOCK_LOCKMETHOD(*(lock))) >= 1) \
|
||||
&& (lock->tag.relId >= lockDebugOidMin)) \
|
||||
|| \
|
||||
(lockDebugRelation && (lock->tag.relId == lockDebugRelation))) \
|
||||
LOCK_PRINT_AUX(where,lock,type)
|
||||
|
||||
#define LOCK_PRINT_AUX(where,lock,type) \
|
||||
TPRINTF(TRACE_ALL, \
|
||||
"%s: lock(%x) tbl(%d) rel(%u) db(%u) obj(%u) mask(%x) " \
|
||||
"hold(%d,%d,%d,%d,%d,%d,%d)=%d " \
|
||||
"act(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", \
|
||||
where, \
|
||||
MAKE_OFFSET(lock), \
|
||||
lock->tag.lockmethod, \
|
||||
lock->tag.relId, \
|
||||
lock->tag.dbId, \
|
||||
lock->tag.objId.blkno, \
|
||||
lock->mask, \
|
||||
lock->holders[1], \
|
||||
lock->holders[2], \
|
||||
lock->holders[3], \
|
||||
lock->holders[4], \
|
||||
lock->holders[5], \
|
||||
lock->holders[6], \
|
||||
lock->holders[7], \
|
||||
lock->nHolding, \
|
||||
lock->activeHolders[1], \
|
||||
lock->activeHolders[2], \
|
||||
lock->activeHolders[3], \
|
||||
lock->activeHolders[4], \
|
||||
lock->activeHolders[5], \
|
||||
lock->activeHolders[6], \
|
||||
lock->activeHolders[7], \
|
||||
lock->nActive, \
|
||||
lock->waitProcs.size, \
|
||||
lock_types[type])
|
||||
|
||||
#define XID_PRINT(where,xidentP) \
|
||||
if (((LOCKDEBUG(XIDENT_LOCKMETHOD(*(xidentP))) >= 1) \
|
||||
&& (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId \
|
||||
>= lockDebugOidMin)) \
|
||||
|| (lockDebugRelation && \
|
||||
(((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId \
|
||||
== lockDebugRelation))) \
|
||||
XID_PRINT_AUX(where,xidentP)
|
||||
|
||||
#define XID_PRINT_AUX(where,xidentP) \
|
||||
TPRINTF(TRACE_ALL, \
|
||||
"%s: xid(%x) lock(%x) tbl(%d) pid(%d) xid(%u) " \
|
||||
"hold(%d,%d,%d,%d,%d,%d,%d)=%d", \
|
||||
where, \
|
||||
MAKE_OFFSET(xidentP), \
|
||||
xidentP->tag.lock, \
|
||||
XIDENT_LOCKMETHOD(*(xidentP)), \
|
||||
xidentP->tag.pid, \
|
||||
xidentP->tag.xid, \
|
||||
xidentP->holders[1], \
|
||||
xidentP->holders[2], \
|
||||
xidentP->holders[3], \
|
||||
xidentP->holders[4], \
|
||||
xidentP->holders[5], \
|
||||
xidentP->holders[6], \
|
||||
xidentP->holders[7], \
|
||||
xidentP->nHolding)
|
||||
|
||||
#else /* !LOCK_MGR_DEBUG */
|
||||
#define LOCK_PRINT(where,lock,type)
|
||||
#define LOCK_PRINT_AUX(where,lock,type)
|
||||
#define XID_PRINT(where,xidentP)
|
||||
#define XID_PRINT_AUX(where,xidentP)
|
||||
#endif /* !LOCK_MGR_DEBUG */
|
||||
|
||||
static char *lock_types[] = {
|
||||
static char *lock_types[] =
|
||||
{
|
||||
"INVALID",
|
||||
"AccessShareLock",
|
||||
"RowShareLock",
|
||||
@@ -149,6 +54,89 @@ static char *lock_types[] = {
|
||||
"AccessExclusiveLock"
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
|
||||
/*------
|
||||
* The following configuration options are available for lock debugging:
|
||||
*
|
||||
* trace_locks -- give a bunch of output what's going on in this file
|
||||
* trace_userlocks -- same but for user locks
|
||||
* trace_lock_oidmin-- do not trace locks for tables below this oid
|
||||
* (use to avoid output on system tables)
|
||||
* trace_lock_table -- trace locks on this table (oid) unconditionally
|
||||
* debug_deadlocks -- currently dumps locks at untimely occasions ;)
|
||||
* Furthermore, but in storage/ipc/spin.c:
|
||||
* trace_spinlocks -- trace spinlocks (pretty useless)
|
||||
*
|
||||
* Define LOCK_DEBUG at compile time to get all this enabled.
|
||||
*/
|
||||
|
||||
int Trace_lock_oidmin = BootstrapObjectIdData;
|
||||
bool Trace_locks = false;
|
||||
bool Trace_userlocks = false;
|
||||
int Trace_lock_table = 0;
|
||||
bool Debug_deadlocks = false;
|
||||
|
||||
|
||||
inline static bool
|
||||
LOCK_DEBUG_ENABLED(const LOCK * lock)
|
||||
{
|
||||
return
|
||||
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|
||||
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
|
||||
&& (lock->tag.relId >= Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
|
||||
}
|
||||
|
||||
|
||||
inline static void
|
||||
LOCK_PRINT(const char * where, const LOCK * lock, LOCKMODE type)
|
||||
{
|
||||
if (LOCK_DEBUG_ENABLED(lock))
|
||||
elog(DEBUG,
|
||||
"%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) mask(%x) "
|
||||
"hold(%d,%d,%d,%d,%d,%d,%d)=%d "
|
||||
"act(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
|
||||
where, MAKE_OFFSET(lock),
|
||||
lock->tag.lockmethod, lock->tag.relId, lock->tag.dbId,
|
||||
lock->tag.objId.blkno, lock->mask,
|
||||
lock->holders[1], lock->holders[2], lock->holders[3], lock->holders[4],
|
||||
lock->holders[5], lock->holders[6], lock->holders[7], lock->nHolding,
|
||||
lock->activeHolders[1], lock->activeHolders[2], lock->activeHolders[3],
|
||||
lock->activeHolders[4], lock->activeHolders[5], lock->activeHolders[6],
|
||||
lock->activeHolders[7], lock->nActive,
|
||||
lock->waitProcs.size, lock_types[type]);
|
||||
}
|
||||
|
||||
|
||||
inline static void
|
||||
XID_PRINT(const char * where, const XIDLookupEnt * xidentP)
|
||||
{
|
||||
if (
|
||||
(((XIDENT_LOCKMETHOD(*xidentP) == DEFAULT_LOCKMETHOD && Trace_locks)
|
||||
|| (XIDENT_LOCKMETHOD(*xidentP) == USER_LOCKMETHOD && Trace_userlocks))
|
||||
&& (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId >= Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId == Trace_lock_table))
|
||||
)
|
||||
elog(DEBUG,
|
||||
"%s: xid(%lx) lock(%lx) tbl(%d) pid(%d) xid(%u) hold(%d,%d,%d,%d,%d,%d,%d)=%d",
|
||||
where, MAKE_OFFSET(xidentP), xidentP->tag.lock, XIDENT_LOCKMETHOD(*(xidentP)),
|
||||
xidentP->tag.pid, xidentP->tag.xid,
|
||||
xidentP->holders[1], xidentP->holders[2], xidentP->holders[3], xidentP->holders[4],
|
||||
xidentP->holders[5], xidentP->holders[6], xidentP->holders[7], xidentP->nHolding);
|
||||
}
|
||||
|
||||
#else /* not LOCK_DEBUG */
|
||||
|
||||
#define LOCK_PRINT(where, lock, type)
|
||||
#define XID_PRINT(where, xidentP)
|
||||
|
||||
#endif /* not LOCK_DEBUG */
|
||||
|
||||
|
||||
|
||||
SPINLOCK LockMgrLock; /* in Shmem or created in
|
||||
* CreateSpinlocks() */
|
||||
|
||||
@@ -192,16 +180,6 @@ InitLocks()
|
||||
BITS_ON[i] = bit;
|
||||
BITS_OFF[i] = ~bit;
|
||||
}
|
||||
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
|
||||
/*
|
||||
* If lockDebugOidMin value has not been specified in pg_options set a
|
||||
* default value.
|
||||
*/
|
||||
if (!lockDebugOidMin)
|
||||
lockDebugOidMin = BootstrapObjectIdData;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -------------------
|
||||
@@ -488,18 +466,9 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
int status;
|
||||
TransactionId xid;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||
#ifdef USER_LOCKS_DEBUG
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u] %s",
|
||||
locktag->objId.blkno,
|
||||
lock_types[lockmode]);
|
||||
}
|
||||
#endif
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(DEBUG, "LockAcquire: user lock [%u] %s", locktag->objId.blkno, lock_types[lockmode]);
|
||||
#endif
|
||||
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
@@ -573,8 +542,9 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
#ifdef USE_XIDTAG_LOCKMETHOD
|
||||
item.tag.lockmethod = lockmethod;
|
||||
#endif
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
item.tag.pid = MyProcPid;
|
||||
item.tag.xid = xid = 0;
|
||||
@@ -584,10 +554,10 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
xid = GetCurrentTransactionId();
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
}
|
||||
#else
|
||||
#else /* not USER_LOCKS */
|
||||
xid = GetCurrentTransactionId();
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
#endif
|
||||
#endif /* not USER_LOCKS */
|
||||
|
||||
/*
|
||||
* Find or create an xid entry with this tag
|
||||
@@ -688,7 +658,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
* User locks are non blocking. If we can't acquire a lock we must
|
||||
* remove the xid entry and return FALSE without waiting.
|
||||
*/
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
if (!result->nHolding)
|
||||
{
|
||||
@@ -700,7 +670,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
elog(NOTICE, "LockAcquire: remove xid, table corrupted");
|
||||
}
|
||||
else
|
||||
XID_PRINT_AUX("LockAcquire: NHOLDING", result);
|
||||
XID_PRINT("LockAcquire: NHOLDING", result);
|
||||
lock->nHolding--;
|
||||
lock->holders[lockmode]--;
|
||||
LOCK_PRINT("LockAcquire: user lock failed", lock, lockmode);
|
||||
@@ -709,7 +679,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
SpinRelease(masterLock);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
#endif /* USER_LOCKS */
|
||||
|
||||
/*
|
||||
* Construct bitmask of locks we hold before going to sleep.
|
||||
@@ -737,8 +707,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
*/
|
||||
if (!((result->nHolding > 0) && (result->holders[lockmode] > 0)))
|
||||
{
|
||||
XID_PRINT_AUX("LockAcquire: INCONSISTENT ", result);
|
||||
LOCK_PRINT_AUX("LockAcquire: INCONSISTENT ", lock, lockmode);
|
||||
XID_PRINT("LockAcquire: INCONSISTENT", result);
|
||||
LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
|
||||
/* Should we retry ? */
|
||||
SpinRelease(masterLock);
|
||||
return FALSE;
|
||||
@@ -781,11 +751,6 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
|
||||
int i,
|
||||
tmpMask;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
#endif
|
||||
|
||||
numLockModes = LockMethodTable[lockmethod]->ctl->numLockModes;
|
||||
xidTable = LockMethodTable[lockmethod]->xidHash;
|
||||
|
||||
@@ -814,17 +779,14 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
|
||||
item.tag.lockmethod = lockmethod;
|
||||
#endif
|
||||
#ifdef USER_LOCKS
|
||||
is_user_lock = (lockmethod == 2);
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
item.tag.pid = MyProcPid;
|
||||
item.tag.xid = 0;
|
||||
}
|
||||
else
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
#else
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
#endif
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
|
||||
/*
|
||||
* Find or create an xid entry with this tag
|
||||
@@ -851,7 +813,7 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
|
||||
*/
|
||||
MemSet(result->holders, 0, numLockModes * sizeof(*(lock->holders)));
|
||||
result->nHolding = 0;
|
||||
XID_PRINT_AUX("LockResolveConflicts: NOT FOUND", result);
|
||||
XID_PRINT("LockResolveConflicts: NOT FOUND", result);
|
||||
}
|
||||
else
|
||||
XID_PRINT("LockResolveConflicts: found", result);
|
||||
@@ -946,7 +908,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
|
||||
* synchronization for this queue. That will not be true if/when
|
||||
* people can be deleted from the queue by a SIGINT or something.
|
||||
*/
|
||||
LOCK_PRINT_AUX("WaitOnLock: sleeping on lock", lock, lockmode);
|
||||
LOCK_PRINT("WaitOnLock: sleeping on lock", lock, lockmode);
|
||||
strcpy(old_status, PS_STATUS);
|
||||
strcpy(new_status, PS_STATUS);
|
||||
strcat(new_status, " waiting");
|
||||
@@ -965,7 +927,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
|
||||
*/
|
||||
lock->nHolding--;
|
||||
lock->holders[lockmode]--;
|
||||
LOCK_PRINT_AUX("WaitOnLock: aborting on lock", lock, lockmode);
|
||||
LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
|
||||
Assert((lock->nHolding >= 0) && (lock->holders[lockmode] >= 0));
|
||||
Assert(lock->nActive <= lock->nHolding);
|
||||
if (lock->activeHolders[lockmode] == lock->holders[lockmode])
|
||||
@@ -979,7 +941,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
|
||||
if (lock->activeHolders[lockmode] == lock->holders[lockmode])
|
||||
lock->waitMask &= BITS_OFF[lockmode];
|
||||
PS_SET_STATUS(old_status);
|
||||
LOCK_PRINT_AUX("WaitOnLock: wakeup on lock", lock, lockmode);
|
||||
LOCK_PRINT("WaitOnLock: wakeup on lock", lock, lockmode);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -1005,30 +967,15 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
HTAB *xidTable;
|
||||
TransactionId xid;
|
||||
bool wakeupNeeded = true;
|
||||
int trace_flag;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u] %d",
|
||||
locktag->objId.blkno,
|
||||
lockmode);
|
||||
}
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(DEBUG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
|
||||
#endif
|
||||
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
locktag->lockmethod = lockmethod;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
trace_flag = \
|
||||
(lockmethod == USER_LOCKMETHOD) ? TRACE_USERLOCKS : TRACE_LOCKS;
|
||||
#else
|
||||
trace_flag = TRACE_LOCKS;
|
||||
#endif
|
||||
|
||||
Assert(lockmethod < NumLockMethods);
|
||||
lockMethodTable = LockMethodTable[lockmethod];
|
||||
if (!lockMethodTable)
|
||||
@@ -1064,14 +1011,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
if (!found)
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
elog(NOTICE, "LockRelease: locktable lookup failed, no lock");
|
||||
elog(NOTICE, "LockRelease: no such lock");
|
||||
return FALSE;
|
||||
}
|
||||
LOCK_PRINT("LockRelease: found", lock, lockmode);
|
||||
@@ -1091,7 +1031,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
item.tag.lockmethod = lockmethod;
|
||||
#endif
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
item.tag.pid = MyProcPid;
|
||||
item.tag.xid = xid = 0;
|
||||
@@ -1116,8 +1056,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
#ifdef USER_LOCKS
|
||||
if (!found && is_user_lock)
|
||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
|
||||
if (!found && lockmethod == USER_LOCKMETHOD)
|
||||
elog(NOTICE, "LockRelease: no lock with this tag");
|
||||
else
|
||||
#endif
|
||||
elog(NOTICE, "LockRelease: xid table corrupted");
|
||||
@@ -1133,7 +1073,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
if (!(result->holders[lockmode] > 0))
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
XID_PRINT_AUX("LockAcquire: WRONGTYPE", result);
|
||||
XID_PRINT("LockAcquire: WRONGTYPE", result);
|
||||
elog(NOTICE, "LockRelease: you don't own a lock of type %s",
|
||||
lock_types[lockmode]);
|
||||
Assert(result->holders[lockmode] >= 0);
|
||||
@@ -1234,14 +1174,10 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
|
||||
if (wakeupNeeded)
|
||||
ProcLockWakeup(&(lock->waitProcs), lockmethod, lock);
|
||||
else
|
||||
{
|
||||
if (((LOCKDEBUG(LOCK_LOCKMETHOD(*(lock))) >= 1) \
|
||||
&&(lock->tag.relId >= lockDebugOidMin)) \
|
||||
||\
|
||||
(lockDebugRelation && (lock->tag.relId == lockDebugRelation)))
|
||||
TPRINTF(TRACE_ALL, "LockRelease: no wakeup needed");
|
||||
}
|
||||
#ifdef LOCK_DEBUG
|
||||
else if (LOCK_DEBUG_ENABLED(lock))
|
||||
elog(DEBUG, "LockRelease: no wakeup needed");
|
||||
#endif
|
||||
|
||||
SpinRelease(masterLock);
|
||||
return TRUE;
|
||||
@@ -1265,20 +1201,13 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
numLockModes;
|
||||
LOCK *lock;
|
||||
bool found;
|
||||
int trace_flag;
|
||||
int xidtag_lockmethod,
|
||||
nleft;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock_table;
|
||||
|
||||
is_user_lock_table = (lockmethod == USER_LOCKMETHOD);
|
||||
trace_flag = (lockmethod == 2) ? TRACE_USERLOCKS : TRACE_LOCKS;
|
||||
#else
|
||||
trace_flag = TRACE_LOCKS;
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
elog(DEBUG, "LockReleaseAll: lockmethod=%d, pid=%d", lockmethod, MyProcPid);
|
||||
#endif
|
||||
TPRINTF(trace_flag, "LockReleaseAll: lockmethod=%d, pid=%d",
|
||||
lockmethod, MyProcPid);
|
||||
|
||||
nleft = 0;
|
||||
|
||||
@@ -1313,7 +1242,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
|
||||
|
||||
xidtag_lockmethod = XIDENT_LOCKMETHOD(*xidLook);
|
||||
if ((xidtag_lockmethod == lockmethod) && pg_options[trace_flag])
|
||||
if (xidtag_lockmethod == lockmethod)
|
||||
{
|
||||
XID_PRINT("LockReleaseAll", xidLook);
|
||||
LOCK_PRINT("LockReleaseAll", lock, 0);
|
||||
@@ -1324,9 +1253,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
elog(NOTICE, "LockReleaseAll: xid/lock method mismatch: %d != %d",
|
||||
xidtag_lockmethod, lock->tag.lockmethod);
|
||||
#endif
|
||||
if ((xidtag_lockmethod != lockmethod) && (trace_flag >= 2))
|
||||
if (xidtag_lockmethod != lockmethod)
|
||||
{
|
||||
TPRINTF(trace_flag, "LockReleaseAll: skipping other table");
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
@@ -1338,13 +1266,15 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
Assert(xidLook->nHolding <= lock->nHolding);
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock_table)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
if ((xidLook->tag.pid == 0) || (xidLook->tag.xid != 0))
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS,
|
||||
"LockReleaseAll: skiping normal lock [%d,%d,%d]",
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Trace_userlocks)
|
||||
elog(DEBUG, "LockReleaseAll: skiping normal lock [%ld,%d,%d]",
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#endif /* LOCK_DEBUG */
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
@@ -1358,29 +1288,29 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
TPRINTF(TRACE_USERLOCKS,
|
||||
"LockReleaseAll: releasing user lock [%u] [%d,%d,%d]",
|
||||
lock->tag.objId.blkno,
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Trace_userlocks)
|
||||
elog(DEBUG, "LockReleaseAll: releasing user lock [%u] [%ld,%d,%d]",
|
||||
lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#endif /* LOCK_DEBUG */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Can't check xidLook->tag.xid, can be 0 also for normal
|
||||
* locks
|
||||
* Can't check xidLook->tag.xid, can be 0 also for normal locks
|
||||
*/
|
||||
if (xidLook->tag.pid != 0)
|
||||
{
|
||||
TPRINTF(TRACE_LOCKS,
|
||||
"LockReleaseAll: skiping user lock [%u] [%d,%d,%d]",
|
||||
lock->tag.objId.blkno,
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Trace_userlocks)
|
||||
elog(DEBUG, "LockReleaseAll: skiping user lock [%u] [%ld,%d,%d]",
|
||||
lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#endif /* LOCK_DEBUG */
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* USER_LOCKS */
|
||||
|
||||
/* ------------------
|
||||
* fix the general lock stats
|
||||
@@ -1486,12 +1416,18 @@ next_item:
|
||||
*/
|
||||
if (nleft == 0)
|
||||
{
|
||||
TPRINTF(trace_flag, "LockReleaseAll: reinitializing lockQueue");
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
elog(DEBUG, "LockReleaseAll: reinitializing lockQueue");
|
||||
#endif
|
||||
SHMQueueInit(lockQueue);
|
||||
}
|
||||
|
||||
SpinRelease(masterLock);
|
||||
TPRINTF(trace_flag, "LockReleaseAll: done");
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
elog(DEBUG, "LockReleaseAll: done");
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1753,10 +1689,7 @@ DeadLockCheck(void *proc, LOCK *findlock)
|
||||
/*
|
||||
* Blocked by others - no deadlock...
|
||||
*/
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
LOCK_PRINT("DeadLockCheck: blocked by others",
|
||||
lock, waitProc->token);
|
||||
#endif
|
||||
LOCK_PRINT("DeadLockCheck: blocked by others", lock, waitProc->token);
|
||||
waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
|
||||
continue;
|
||||
}
|
||||
@@ -1817,15 +1750,9 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
||||
/* Assume that no one will modify the result */
|
||||
static int empty_array[] = {20, 1, 0, 0, 0};
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u]",
|
||||
locktag->objId.blkno);
|
||||
}
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(DEBUG, "LockOwners: user lock tag [%u]", locktag->objId.blkno);
|
||||
#endif
|
||||
|
||||
/* This must be changed when short term locks will be used */
|
||||
@@ -1865,14 +1792,7 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
||||
if (!found)
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockOwners: no lock with this tag");
|
||||
return (ArrayType *) &empty_array;
|
||||
}
|
||||
#endif
|
||||
elog(NOTICE, "LockOwners: locktable lookup failed, no lock");
|
||||
elog(NOTICE, "LockOwners: no such lock");
|
||||
return (ArrayType *) &empty_array;
|
||||
}
|
||||
LOCK_PRINT("LockOwners: found", lock, 0);
|
||||
@@ -1974,9 +1894,9 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
||||
return array;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* NOT_USED */
|
||||
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
#ifdef LOCK_DEBUG
|
||||
/*
|
||||
* Dump all locks in the proc->lockQueue. Must have already acquired
|
||||
* the masterLock.
|
||||
@@ -2016,7 +1936,7 @@ DumpLocks()
|
||||
end = MAKE_OFFSET(lockQueue);
|
||||
|
||||
if (MyProc->waitLock)
|
||||
LOCK_PRINT_AUX("DumpLocks: waiting on", MyProc->waitLock, 0);
|
||||
LOCK_PRINT("DumpLocks: waiting on", MyProc->waitLock, 0);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -2035,8 +1955,8 @@ DumpLocks()
|
||||
done = (xidLook->queue.next == end);
|
||||
lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
|
||||
|
||||
XID_PRINT_AUX("DumpLocks", xidLook);
|
||||
LOCK_PRINT_AUX("DumpLocks", lock, 0);
|
||||
XID_PRINT("DumpLocks", xidLook);
|
||||
LOCK_PRINT("DumpLocks", lock, 0);
|
||||
|
||||
if (done)
|
||||
break;
|
||||
@@ -2078,18 +1998,18 @@ DumpAllLocks()
|
||||
xidTable = lockMethodTable->xidHash;
|
||||
|
||||
if (MyProc->waitLock)
|
||||
LOCK_PRINT_AUX("DumpAllLocks: waiting on", MyProc->waitLock, 0);
|
||||
LOCK_PRINT("DumpAllLocks: waiting on", MyProc->waitLock, 0);
|
||||
|
||||
hash_seq(NULL);
|
||||
while ((xidLook = (XIDLookupEnt *) hash_seq(xidTable)) &&
|
||||
(xidLook != (XIDLookupEnt *) TRUE))
|
||||
{
|
||||
XID_PRINT_AUX("DumpAllLocks", xidLook);
|
||||
XID_PRINT("DumpAllLocks", xidLook);
|
||||
|
||||
if (xidLook->tag.lock)
|
||||
{
|
||||
lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
|
||||
LOCK_PRINT_AUX("DumpAllLocks", lock, 0);
|
||||
LOCK_PRINT("DumpAllLocks", lock, 0);
|
||||
}
|
||||
else
|
||||
elog(DEBUG, "DumpAllLocks: xidLook->tag.lock = NULL");
|
||||
@@ -2102,4 +2022,4 @@ DumpAllLocks()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* LOCK_DEBUG */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.73 2000/05/30 00:49:52 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.74 2000/05/31 00:28:30 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -47,7 +47,7 @@
|
||||
* This is so that we can support more backends. (system-wide semaphore
|
||||
* sets run out pretty fast.) -ay 4/95
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.73 2000/05/30 00:49:52 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.74 2000/05/31 00:28:30 petere Exp $
|
||||
*/
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
@@ -66,13 +66,14 @@
|
||||
/* In Ultrix and QNX, sem.h must be included after ipc.h */
|
||||
#include <sys/sem.h>
|
||||
|
||||
#include "storage/lock.h"
|
||||
#include "storage/proc.h"
|
||||
|
||||
void HandleDeadLock(SIGNAL_ARGS);
|
||||
static void ProcFreeAllSemaphores(void);
|
||||
static bool GetOffWaitqueue(PROC *);
|
||||
|
||||
#define DeadlockCheckTimer pg_options[OPT_DEADLOCKTIMEOUT]
|
||||
int DeadlockTimeout = 1000;
|
||||
|
||||
/* --------------------
|
||||
* Spin lock for manipulating the shared process data structure:
|
||||
@@ -633,8 +634,8 @@ ins:;
|
||||
* --------------
|
||||
*/
|
||||
MemSet(&timeval, 0, sizeof(struct itimerval));
|
||||
timeval.it_value.tv_sec = \
|
||||
(DeadlockCheckTimer ? DeadlockCheckTimer : DEADLOCK_CHECK_TIMER);
|
||||
timeval.it_value.tv_sec = DeadlockTimeout / 1000;
|
||||
timeval.it_value.tv_usec = (DeadlockTimeout % 1000) * 1000;
|
||||
|
||||
SetWaitingForLock(true);
|
||||
do
|
||||
@@ -663,6 +664,7 @@ ins:;
|
||||
* ---------------
|
||||
*/
|
||||
timeval.it_value.tv_sec = 0;
|
||||
timeval.it_value.tv_usec = 0;
|
||||
if (setitimer(ITIMER_REAL, &timeval, &dummy))
|
||||
elog(FATAL, "ProcSleep: Unable to diable timer for process wakeup");
|
||||
|
||||
@@ -675,7 +677,7 @@ ins:;
|
||||
|
||||
rt:;
|
||||
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
#ifdef LOCK_DEBUG
|
||||
/* Just to get meaningful debug messages from DumpLocks() */
|
||||
MyProc->waitLock = (LOCK *) NULL;
|
||||
#endif
|
||||
@@ -723,7 +725,6 @@ ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod, LOCK *lock)
|
||||
{
|
||||
PROC *proc;
|
||||
int count = 0;
|
||||
int trace_flag;
|
||||
int last_locktype = 0;
|
||||
int queue_size = queue->size;
|
||||
|
||||
@@ -783,14 +784,13 @@ ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod, LOCK *lock)
|
||||
else
|
||||
{
|
||||
/* Something is still blocking us. May have deadlocked. */
|
||||
trace_flag = (lock->tag.lockmethod == USER_LOCKMETHOD) ? \
|
||||
TRACE_USERLOCKS : TRACE_LOCKS;
|
||||
TPRINTF(trace_flag,
|
||||
"ProcLockWakeup: lock(%x) can't wake up any process",
|
||||
MAKE_OFFSET(lock));
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
if (pg_options[trace_flag] >= 2)
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lock->tag.lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
{
|
||||
elog(DEBUG, "ProcLockWakeup: lock(%lx) can't wake up any process", MAKE_OFFSET(lock));
|
||||
if (Debug_deadlocks)
|
||||
DumpAllLocks();
|
||||
}
|
||||
#endif
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
@@ -803,7 +803,7 @@ ProcAddLock(SHM_QUEUE *elem)
|
||||
}
|
||||
|
||||
/* --------------------
|
||||
* We only get to this routine if we got SIGALRM after DEADLOCK_CHECK_TIMER
|
||||
* We only get to this routine if we got SIGALRM after DeadlockTimeout
|
||||
* while waiting for a lock to be released by some other process. If we have
|
||||
* a real deadlock, we must also indicate that I'm no longer waiting
|
||||
* on a lock so that other processes don't try to wake me up and screw
|
||||
@@ -852,8 +852,9 @@ HandleDeadLock(SIGNAL_ARGS)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
DumpAllLocks();
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Debug_deadlocks)
|
||||
DumpAllLocks();
|
||||
#endif
|
||||
|
||||
MyProc->errType = STATUS_NOT_FOUND;
|
||||
|
||||
Reference in New Issue
Block a user