diff options
Diffstat (limited to 'src/backend/storage/lmgr')
-rw-r--r-- | src/backend/storage/lmgr/lmgr.c | 20 | ||||
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 45 | ||||
-rw-r--r-- | src/backend/storage/lmgr/lwlock.c | 6 | ||||
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 34 |
4 files changed, 74 insertions, 31 deletions
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index e4e52b16abf..45305b4dea2 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.63 2004/05/28 05:13:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.64 2004/07/01 00:50:59 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/subtrans.h" #include "access/transam.h" #include "access/xact.h" #include "catalog/catalog.h" @@ -333,19 +334,21 @@ XactLockTableInsert(TransactionId xid) * XactLockTableWait * * Wait for the specified transaction to commit or abort. + * We actually wait on the topmost transaction of the transaction tree. */ void XactLockTableWait(TransactionId xid) { LOCKTAG tag; TransactionId myxid = GetCurrentTransactionId(); + TransactionId waitXid = SubTransGetTopmostTransaction(xid); - Assert(!TransactionIdEquals(xid, myxid)); + Assert(!SubTransXidsHaveCommonAncestor(waitXid, myxid)); MemSet(&tag, 0, sizeof(tag)); tag.relId = XactLockTableId; tag.dbId = InvalidOid; - tag.objId.xid = xid; + tag.objId.xid = waitXid; if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false)) @@ -355,8 +358,13 @@ XactLockTableWait(TransactionId xid) /* * Transaction was committed/aborted/crashed - we have to update - * pg_clog if transaction is still marked as running. + * pg_clog if transaction is still marked as running. If it's a + * subtransaction, we can update the parent status too. */ - if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid)) - TransactionIdAbort(xid); + if (!TransactionIdDidCommit(waitXid) && !TransactionIdDidAbort(waitXid)) + { + TransactionIdAbort(waitXid); + if (waitXid != xid) + TransactionIdAbort(xid); + } } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index c04f3b5c88a..6b7f43440e6 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.133 2004/06/05 19:48:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.134 2004/07/01 00:50:59 tgl Exp $ * * NOTES * Outside modules can create a lock table and acquire/release @@ -23,7 +23,7 @@ * Interface: * * LockAcquire(), LockRelease(), LockMethodTableInit(), - * LockMethodTableRename(), LockReleaseAll, + * LockMethodTableRename(), LockReleaseAll(), * LockCheckConflicts(), GrantLock() * *------------------------------------------------------------------------- @@ -1129,19 +1129,25 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag, } /* - * LockReleaseAll -- Release all locks in a process's lock list. + * LockReleaseAll -- Release all locks of the specified lock method that + * are held by the specified process. * - * Well, not really *all* locks. + * Well, not necessarily *all* locks. The available behaviors are: * - * If 'allxids' is TRUE, all locks of the specified lock method are - * released, regardless of transaction affiliation. + * which == ReleaseAll: release all locks regardless of transaction + * affiliation. * - * If 'allxids' is FALSE, all locks of the specified lock method and - * specified XID are released. + * which == ReleaseAllExceptSession: release all locks with Xid != 0 + * (zero is the Xid used for "session" locks). + * + * which == ReleaseGivenXids: release only locks whose Xids appear in + * the xids[] array (of length nxids). + * + * xids/nxids are ignored when which != ReleaseGivenXids. */ bool LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc, - bool allxids, TransactionId xid) + LockReleaseWhich which, int nxids, TransactionId *xids) { SHM_QUEUE *procHolders = &(proc->procHolders); PROCLOCK *proclock; @@ -1190,8 +1196,25 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc, if (LOCK_LOCKMETHOD(*lock) != lockmethodid) goto next_item; - /* If not allxids, ignore items that are of the wrong xid */ - if (!allxids && !TransactionIdEquals(xid, proclock->tag.xid)) + if (which == ReleaseGivenXids) + { + /* Ignore locks with an Xid not in the list */ + bool release = false; + + for (i = 0; i < nxids; i++) + { + if (TransactionIdEquals(proclock->tag.xid, xids[i])) + { + release = true; + break; + } + } + if (!release) + goto next_item; + } + /* Ignore locks with Xid=0 unless we are asked to release All locks */ + else if (TransactionIdEquals(proclock->tag.xid, InvalidTransactionId) + && which != ReleaseAll) goto next_item; PROCLOCK_PRINT("LockReleaseAll", proclock); diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index d1410d04a05..e48531c10ac 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -15,13 +15,14 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.20 2004/06/11 16:43:24 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.21 2004/07/01 00:50:59 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "access/clog.h" +#include "access/subtrans.h" #include "storage/lwlock.h" #include "storage/proc.h" #include "storage/spin.h" @@ -111,6 +112,9 @@ NumLWLocks(void) /* clog.c needs one per CLOG buffer + one control lock */ numLocks += NUM_CLOG_BUFFERS + 1; + /* subtrans.c needs one per SubTrans buffer + one control lock */ + numLocks += NUM_SUBTRANS_BUFFERS + 1; + /* Perhaps create a few more for use by user-defined modules? */ return numLocks; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index dbf5b414153..abe44e808ad 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.148 2004/05/29 22:48:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.149 2004/07/01 00:50:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -380,26 +380,34 @@ LockWaitCancel(void) /* * ProcReleaseLocks() -- release locks associated with current transaction - * at transaction commit or abort + * at main transaction and subtransaction commit or abort * - * At commit, we release only locks tagged with the current transaction's XID, - * leaving those marked with XID 0 (ie, session locks) undisturbed. At abort, - * we release all locks including XID 0, because we need to clean up after - * a failure. This logic will need extension if we ever support nested - * transactions. + * The options for which locks to release are the same as for the underlying + * LockReleaseAll() function. * - * Note that user locks are not released in either case. + * Notes: + * + * At main transaction commit, we release all locks except session locks. + * At main transaction abort, we release all locks including session locks; + * this lets us clean up after a VACUUM FULL failure. + * + * At subtransaction commit, we don't release any locks (so this func is not + * called at all); we will defer the releasing to the parent transaction. + * At subtransaction abort, we release all locks held by the subtransaction; + * this is implemented by passing in the Xids of the failed subxact and its + * children in the xids[] array. + * + * Note that user locks are not released in any case. */ void -ProcReleaseLocks(bool isCommit) +ProcReleaseLocks(LockReleaseWhich which, int nxids, TransactionId *xids) { if (!MyProc) return; /* If waiting, get off wait queue (should only be needed after error) */ LockWaitCancel(); /* Release locks */ - LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, - !isCommit, GetCurrentTransactionId()); + LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, which, nxids, xids); } @@ -432,11 +440,11 @@ ProcKill(int code, Datum arg) LockWaitCancel(); /* Remove from the standard lock table */ - LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, true, InvalidTransactionId); + LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, ReleaseAll, 0, NULL); #ifdef USER_LOCKS /* Remove from the user lock table */ - LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId); + LockReleaseAll(USER_LOCKMETHOD, MyProc, ReleaseAll, 0, NULL); #endif SpinLockAcquire(ProcStructLock); |