aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/lmgr')
-rw-r--r--src/backend/storage/lmgr/lmgr.c20
-rw-r--r--src/backend/storage/lmgr/lock.c45
-rw-r--r--src/backend/storage/lmgr/lwlock.c6
-rw-r--r--src/backend/storage/lmgr/proc.c34
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);