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]

Reply via email to