Ok, new version of this patch, adjusted per your comments. Thanks.
--
Alvaro Herrera (<alvherre[a]surnet.cl>)
"Hay que recordar que la existencia en el cosmos, y particularmente la
elaboraci�n de civilizaciones dentre de �l no son, por desgracia,
nada id�licas" (Ijon Tichy)
Index: contrib/userlock/user_locks.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/contrib/userlock/user_locks.c,v
retrieving revision 1.16
diff -c -r1.16 user_locks.c
*** contrib/userlock/user_locks.c 17 May 2005 21:46:09 -0000 1.16
--- contrib/userlock/user_locks.c 19 May 2005 01:30:55 -0000
***************
*** 44,50 ****
SET_LOCKTAG_USERLOCK(tag, id1, id2);
! return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId,
lockmode);
}
int
--- 44,52 ----
SET_LOCKTAG_USERLOCK(tag, id1, id2);
! LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
!
! return true;
}
int
***************
*** 75,79 ****
int
user_unlock_all(void)
{
! return LockReleaseAll(USER_LOCKMETHOD, true);
}
--- 77,83 ----
int
user_unlock_all(void)
{
! LockReleaseAll(USER_LOCKMETHOD, true);
!
! return true;
}
Index: src/backend/storage/lmgr/lock.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/lock.c,v
retrieving revision 1.151
diff -c -r1.151 lock.c
*** src/backend/storage/lmgr/lock.c 11 May 2005 01:26:02 -0000 1.151
--- src/backend/storage/lmgr/lock.c 19 May 2005 01:22:46 -0000
***************
*** 166,171 ****
--- 166,173 ----
int *myHolding);
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
PROCLOCK *proclock, LockMethod
lockMethodTable);
+ static void RemoveProcLock(LOCKMETHODID lockmethodid, PROCLOCK *proclock,
+ LOCK *lock, bool wakeupNeeded);
/*
***************
*** 792,797 ****
--- 794,840 ----
}
/*
+ * Subroutine to unlink and free a proclock entry, and garbage
+ * collect the lock object.
+ *
+ * The locktable's masterLock must be held at entry, and will be
+ * held at exit.
+ */
+ static void
+ RemoveProcLock(LOCKMETHODID lockmethodid, PROCLOCK *proclock, LOCK *lock,
+ bool wakeupNeeded)
+ {
+ PROCLOCK_PRINT("RemoveProcLock: deleting", proclock);
+ SHMQueueDelete(&proclock->lockLink);
+ SHMQueueDelete(&proclock->procLink);
+ proclock = (PROCLOCK *)
hash_search(LockMethodProcLockHash[lockmethodid],
+
(void *) &(proclock->tag),
+
HASH_REMOVE, NULL);
+ if (!proclock)
+ elog(ERROR, "proclock table corrupted");
+
+ if (lock->nRequested == 0)
+ {
+ /*
+ * The caller just released the last lock, so garbage-collect
the
+ * lock object.
+ */
+ LOCK_PRINT("RemoveProcLock: deleting", lock, 0);
+ Assert(SHMQueueEmpty(&(lock->procLocks)));
+ lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
+ (void
*) &(lock->tag),
+
HASH_REMOVE, NULL);
+ if (!lock)
+ elog(ERROR, "lock table corrupted");
+ }
+ else if (wakeupNeeded)
+ {
+ /* There are waiters on this lock, so wake them up. */
+ ProcLockWakeup(LockMethods[lockmethodid], lock);
+ }
+ }
+
+ /*
* LockCheckConflicts -- test whether requested lock conflicts
* with those already granted
*
***************
*** 1196,1202 ****
* the waking process and any new process to
* come along and request the lock.)
*/
! bool
LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode)
{
--- 1239,1245 ----
* the waking process and any new process to
* come along and request the lock.)
*/
! void
LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode)
{
***************
*** 1221,1230 ****
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
! {
! elog(WARNING, "lockMethodTable is null in LockRelease");
! return FALSE;
! }
/*
* Find the LOCALLOCK entry for this lock and lockmode
--- 1264,1270 ----
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
! elog(ERROR, "lockMethodTable is null in LockRelease");
/*
* Find the LOCALLOCK entry for this lock and lockmode
***************
*** 1237,1253 ****
locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash[lockmethodid],
(void *) &localtag,
HASH_FIND, NULL);
-
/*
! * let the caller print its own error message, too. Do not
! * ereport(ERROR).
*/
if (!locallock || locallock->nLocks <= 0)
! {
! elog(WARNING, "you don't own a lock of type %s",
lock_mode_names[lockmode]);
- return FALSE;
- }
/*
* Decrease the count for the resource owner.
--- 1277,1289 ----
locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash[lockmethodid],
(void *) &localtag,
HASH_FIND, NULL);
/*
! * Double-check that we are actually holding a lock of the type we
! * want to release.
*/
if (!locallock || locallock->nLocks <= 0)
! elog(ERROR, "you don't own a lock of type %s",
lock_mode_names[lockmode]);
/*
* Decrease the count for the resource owner.
***************
*** 1282,1290 ****
if (i < 0)
{
/* don't release a lock belonging to another owner */
! elog(WARNING, "you don't own a lock of type %s",
lock_mode_names[lockmode]);
- return FALSE;
}
}
--- 1318,1325 ----
if (i < 0)
{
/* don't release a lock belonging to another owner */
! elog(ERROR, "you don't own a lock of type %s",
lock_mode_names[lockmode]);
}
}
***************
*** 1295,1301 ****
locallock->nLocks--;
if (locallock->nLocks > 0)
! return TRUE;
/*
* Otherwise we've got to mess with the shared lock table.
--- 1330,1336 ----
locallock->nLocks--;
if (locallock->nLocks > 0)
! return;
/*
* Otherwise we've got to mess with the shared lock table.
***************
*** 1322,1388 ****
{
PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
LWLockRelease(masterLock);
- elog(WARNING, "you don't own a lock of type %s",
- lock_mode_names[lockmode]);
RemoveLocalLock(locallock);
! return FALSE;
}
wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
/*
* If this was my last hold on this lock, delete my entry in the
! * proclock table.
*/
if (proclock->holdMask == 0)
! {
! PROCLOCK_PRINT("LockRelease: deleting proclock", proclock);
! SHMQueueDelete(&proclock->lockLink);
! SHMQueueDelete(&proclock->procLink);
! proclock = (PROCLOCK *)
hash_search(LockMethodProcLockHash[lockmethodid],
!
(void *) &(proclock->tag),
!
HASH_REMOVE, NULL);
! if (!proclock)
! {
! LWLockRelease(masterLock);
! elog(WARNING, "proclock table corrupted");
! RemoveLocalLock(locallock);
! return FALSE;
! }
! }
!
! if (lock->nRequested == 0)
! {
! /*
! * We've just released the last lock, so garbage-collect the
lock
! * object.
! */
! LOCK_PRINT("LockRelease: deleting lock", lock, lockmode);
! Assert(SHMQueueEmpty(&(lock->procLocks)));
! lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
! (void
*) &(lock->tag),
!
HASH_REMOVE, NULL);
! if (!lock)
! {
! LWLockRelease(masterLock);
! elog(WARNING, "lock table corrupted");
! RemoveLocalLock(locallock);
! return FALSE;
! }
! }
! else
! {
! /*
! * Wake up waiters if needed.
! */
! if (wakeupNeeded)
! ProcLockWakeup(lockMethodTable, lock);
! }
LWLockRelease(masterLock);
RemoveLocalLock(locallock);
- return TRUE;
}
/*
--- 1357,1379 ----
{
PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
LWLockRelease(masterLock);
RemoveLocalLock(locallock);
! elog(ERROR, "you don't own a lock of type %s",
! lock_mode_names[lockmode]);
}
wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
/*
* If this was my last hold on this lock, delete my entry in the
! * proclock table. RemoveProcLock will wake up waiters if needed.
*/
if (proclock->holdMask == 0)
! RemoveProcLock(lockmethodid, proclock, lock, wakeupNeeded);
LWLockRelease(masterLock);
RemoveLocalLock(locallock);
}
/*
***************
*** 1397,1403 ****
* allxids == false: release all locks with Xid != 0
* (zero is the Xid used for "session" locks).
*/
! bool
LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
{
HASH_SEQ_STATUS status;
--- 1388,1394 ----
* allxids == false: release all locks with Xid != 0
* (zero is the Xid used for "session" locks).
*/
! void
LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
{
HASH_SEQ_STATUS status;
***************
*** 1418,1427 ****
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
! {
! elog(WARNING, "bad lock method: %d", lockmethodid);
! return FALSE;
! }
numLockModes = lockMethodTable->numLockModes;
masterLock = lockMethodTable->masterLock;
--- 1409,1415 ----
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
! elog(ERROR, "bad lock method: %d", lockmethodid);
numLockModes = lockMethodTable->numLockModes;
masterLock = lockMethodTable->masterLock;
***************
*** 1518,1563 ****
PROCLOCK_PRINT("LockReleaseAll: deleting", proclock);
! /*
! * Remove the proclock entry from the linked lists
! */
! SHMQueueDelete(&proclock->lockLink);
! SHMQueueDelete(&proclock->procLink);
! /*
! * remove the proclock entry from the hashtable
! */
! proclock = (PROCLOCK *)
hash_search(LockMethodProcLockHash[lockmethodid],
!
(void *) &(proclock->tag),
!
HASH_REMOVE,
!
NULL);
! if (!proclock)
! {
! LWLockRelease(masterLock);
! elog(WARNING, "proclock table corrupted");
! return FALSE;
! }
!
! if (lock->nRequested == 0)
! {
! /*
! * We've just released the last lock, so
garbage-collect the
! * lock object.
! */
! LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
! Assert(SHMQueueEmpty(&(lock->procLocks)));
! lock = (LOCK *)
hash_search(LockMethodLockHash[lockmethodid],
!
(void *) &(lock->tag),
!
HASH_REMOVE, NULL);
! if (!lock)
! {
! LWLockRelease(masterLock);
! elog(WARNING, "lock table corrupted");
! return FALSE;
! }
! }
! else if (wakeupNeeded)
! ProcLockWakeup(lockMethodTable, lock);
next_item:
proclock = nextHolder;
--- 1506,1515 ----
PROCLOCK_PRINT("LockReleaseAll: deleting", proclock);
! Assert(proclock->holdMask == 0);
! /* RemoveProcLock will wake up waiters if needed. */
! RemoveProcLock(lockmethodid, proclock, lock, wakeupNeeded);
next_item:
proclock = nextHolder;
***************
*** 1569,1576 ****
if (lockmethodid == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
elog(LOG, "LockReleaseAll done");
#endif
-
- return TRUE;
}
/*
--- 1521,1526 ----
***************
*** 1622,1632 ****
/* We want to call LockRelease just
once */
lockOwners[i].nLocks = 1;
locallock->nLocks = 1;
! if (!LockRelease(DEFAULT_LOCKMETHOD,
!
&locallock->tag.lock,
!
locallock->tag.xid,
!
locallock->tag.mode))
! elog(WARNING,
"LockReleaseCurrentOwner: failed??");
}
break;
}
--- 1572,1581 ----
/* We want to call LockRelease just
once */
lockOwners[i].nLocks = 1;
locallock->nLocks = 1;
! LockRelease(DEFAULT_LOCKMETHOD,
!
&locallock->tag.lock,
!
locallock->tag.xid,
!
locallock->tag.mode);
}
break;
}
Index: src/include/storage/lock.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/storage/lock.h,v
retrieving revision 1.85
diff -c -r1.85 lock.h
*** src/include/storage/lock.h 29 Apr 2005 22:28:24 -0000 1.85
--- src/include/storage/lock.h 13 May 2005 01:05:43 -0000
***************
*** 359,367 ****
extern LOCKMETHODID LockMethodTableRename(LOCKMETHODID lockmethodid);
extern bool LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode, bool dontWait);
! extern bool LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode);
! extern bool LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids);
extern void LockReleaseCurrentOwner(void);
extern void LockReassignCurrentOwner(void);
extern int LockCheckConflicts(LockMethod lockMethodTable,
--- 359,367 ----
extern LOCKMETHODID LockMethodTableRename(LOCKMETHODID lockmethodid);
extern bool LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode, bool dontWait);
! extern void LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode);
! extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids);
extern void LockReleaseCurrentOwner(void);
extern void LockReassignCurrentOwner(void);
extern int LockCheckConflicts(LockMethod lockMethodTable,
---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]