When we ExpireOldKnownAssignedTransactionIds() we must also remove any locks that...
authorSimon Riggs <[email protected]>
Thu, 1 Oct 2009 15:37:59 +0000 (16:37 +0100)
committerSimon Riggs <[email protected]>
Thu, 1 Oct 2009 15:37:59 +0000 (16:37 +0100)
src/backend/storage/ipc/procarray.c
src/backend/utils/cache/inval.c
src/include/storage/sinval.h

index 61d63d37d8fdd9c0a0eb5be936bb9070a930a40e..cc552d81b583f1e3d4960f6f78ec3e730d06d049 100644 (file)
@@ -448,6 +448,7 @@ ProcArrayApplyRecoveryInfo(XLogRecPtr lsn, xl_xact_running_xacts *xlrec)
         * Remove stale transactions, if any.
         */
        ExpireOldKnownAssignedTransactionIds(xlrec->oldestRunningXid);
+       RelationReleaseOldRecoveryLocks(xlrec->oldestRunningXid);
 
        /*
         * If our snapshot is already valid, nothing else to do...
index 9241f8a8736437fae4b4888331bd32335de1add8..b1d546ce8dd947a3d2f8229f963fdd67fd70bafb 100644 (file)
@@ -1767,6 +1767,50 @@ RelationReleaseAllRecoveryLocks(void)
        RelationReleaseRecoveryLocks(InvalidTransactionId);
 }
 
+void
+RelationReleaseOldRecoveryLocks(TransactionId removeXid)
+{
+       ListCell   *l;
+       LOCKTAG         locktag;
+       List            *deletionList = NIL;
+
+       /*
+        * Release all matching locks and identify list elements to remove
+        */
+       foreach(l, RecoveryLockList)
+       {
+               xl_rel_lock *lock = (xl_rel_lock *) lfirst(l);
+
+
+               if (TransactionIdPrecedes(removeXid, lock->xid))
+               {
+                       elog(trace_recovery(DEBUG4),
+                                       "releasing recovery lock: xid %u db %d rel %d",
+                                                       lock->xid, lock->dbOid, lock->relOid);
+                       SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
+                       if (!LockRelease(&locktag, AccessExclusiveLock, true))
+                               elog(trace_recovery(LOG),
+                                       "RecoveryLockList contains entry for lock "
+                                       "no longer recorded by lock manager "
+                                       "xid %u database %d relation %d",
+                                               lock->xid, lock->dbOid, lock->relOid);
+                       deletionList = lappend(deletionList, lock);
+               }
+       }
+
+       /*
+        * Now remove the elements from RecoveryLockList. We can't navigate
+        * the list at the same time as deleting multiple elements from it.
+        */
+       foreach(l, deletionList)
+       {
+               xl_rel_lock *lock = (xl_rel_lock *) lfirst(l);
+
+               RecoveryLockList = list_delete_ptr(RecoveryLockList, lock);
+               pfree(lock);
+       }
+}
+
 /*
  * --------------------------------------------------
  *             Recovery handling for Rmgr RM_RELATION_ID
index 46e42434338e9408074255121eb23ba9be02fc81..850bed66b40630e7a937575abbc13ecf0927da73 100644 (file)
@@ -113,6 +113,8 @@ extern int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs
 extern void RelationReleaseRecoveryLockTree(TransactionId xid,
                                                                                int nsubxids, TransactionId *subxids);
 extern void RelationReleaseAllRecoveryLocks(void);
+extern void RelationReleaseOldRecoveryLocks(TransactionId removeXid);
+
 
 /* Recovery handlers for the Relation Rmgr (RM_RELATION_ID) */
 extern void relation_redo(XLogRecPtr lsn, XLogRecord *record);