aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xact.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xact.c')
-rw-r--r--src/backend/access/transam/xact.c136
1 files changed, 32 insertions, 104 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 02b064179f2..1b16f7111b2 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.249 2007/09/07 20:59:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.250 2007/09/08 20:31:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -233,7 +233,7 @@ static void CallSubXactCallbacks(SubXactEvent event,
SubTransactionId parentSubid);
static void CleanupTransaction(void);
static void CommitTransaction(void);
-static void RecordTransactionAbort(bool isSubXact);
+static TransactionId RecordTransactionAbort(bool isSubXact);
static void StartTransaction(void);
static void RecordSubTransactionCommit(void);
@@ -748,13 +748,17 @@ AtSubStart_ResourceOwner(void)
/*
* RecordTransactionCommit
*
+ * Returns latest XID among xact and its children, or InvalidTransactionId
+ * if the xact has no XID. (We compute that here just because it's easier.)
+ *
* This is exported only to support an ugly hack in VACUUM FULL.
*/
-void
+TransactionId
RecordTransactionCommit(void)
{
TransactionId xid = GetTopTransactionIdIfAny();
bool markXidCommitted = TransactionIdIsValid(xid);
+ TransactionId latestXid = InvalidTransactionId;
int nrels;
RelFileNode *rels;
bool haveNonTemp;
@@ -930,6 +934,9 @@ RecordTransactionCommit(void)
END_CRIT_SECTION();
}
+ /* Compute latestXid while we have the child XIDs handy */
+ latestXid = TransactionIdLatest(xid, nchildren, children);
+
/* Reset XactLastRecEnd until the next transaction writes something */
XactLastRecEnd.xrecoff = 0;
@@ -939,6 +946,8 @@ cleanup:
pfree(rels);
if (children)
pfree(children);
+
+ return latestXid;
}
@@ -1084,11 +1093,15 @@ RecordSubTransactionCommit(void)
/*
* RecordTransactionAbort
+ *
+ * Returns latest XID among xact and its children, or InvalidTransactionId
+ * if the xact has no XID. (We compute that here just because it's easier.)
*/
-static void
+static TransactionId
RecordTransactionAbort(bool isSubXact)
{
TransactionId xid = GetCurrentTransactionIdIfAny();
+ TransactionId latestXid;
int nrels;
RelFileNode *rels;
int nchildren;
@@ -1108,7 +1121,7 @@ RecordTransactionAbort(bool isSubXact)
/* Reset XactLastRecEnd until the next transaction writes something */
if (!isSubXact)
XactLastRecEnd.xrecoff = 0;
- return;
+ return InvalidTransactionId;
}
/*
@@ -1186,6 +1199,9 @@ RecordTransactionAbort(bool isSubXact)
END_CRIT_SECTION();
+ /* Compute latestXid while we have the child XIDs handy */
+ latestXid = TransactionIdLatest(xid, nchildren, children);
+
/*
* If we're aborting a subtransaction, we can immediately remove failed
* XIDs from PGPROC's cache of running child XIDs. We do that here for
@@ -1193,7 +1209,7 @@ RecordTransactionAbort(bool isSubXact)
* main xacts, the equivalent happens just after this function returns.
*/
if (isSubXact)
- XidCacheRemoveRunningXids(xid, nchildren, children);
+ XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
/* Reset XactLastRecEnd until the next transaction writes something */
if (!isSubXact)
@@ -1204,6 +1220,8 @@ RecordTransactionAbort(bool isSubXact)
pfree(rels);
if (children)
pfree(children);
+
+ return latestXid;
}
/*
@@ -1481,6 +1499,7 @@ static void
CommitTransaction(void)
{
TransactionState s = CurrentTransactionState;
+ TransactionId latestXid;
ShowTransactionState("CommitTransaction");
@@ -1552,7 +1571,7 @@ CommitTransaction(void)
/*
* Here is where we really truly commit.
*/
- RecordTransactionCommit();
+ latestXid = RecordTransactionCommit();
PG_TRACE1(transaction__commit, MyProc->lxid);
@@ -1560,47 +1579,8 @@ CommitTransaction(void)
* Let others know about no transaction in progress by me. Note that
* this must be done _before_ releasing locks we hold and _after_
* RecordTransactionCommit.
- *
- * Note: MyProc may be null during bootstrap.
*/
- if (MyProc != NULL)
- {
- if (TransactionIdIsValid(MyProc->xid))
- {
- /*
- * We must lock ProcArrayLock while clearing MyProc->xid, so
- * that we do not exit the set of "running" transactions while
- * someone else is taking a snapshot. See discussion in
- * src/backend/access/transam/README.
- */
- LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
-
- MyProc->xid = InvalidTransactionId;
- MyProc->lxid = InvalidLocalTransactionId;
- MyProc->xmin = InvalidTransactionId;
- MyProc->inVacuum = false; /* must be cleared with xid/xmin */
-
- /* Clear the subtransaction-XID cache too while holding the lock */
- MyProc->subxids.nxids = 0;
- MyProc->subxids.overflowed = false;
-
- LWLockRelease(ProcArrayLock);
- }
- else
- {
- /*
- * If we have no XID, we don't need to lock, since we won't
- * affect anyone else's calculation of a snapshot. We might
- * change their estimate of global xmin, but that's OK.
- */
- MyProc->lxid = InvalidLocalTransactionId;
- MyProc->xmin = InvalidTransactionId;
- MyProc->inVacuum = false; /* must be cleared with xid/xmin */
-
- Assert(MyProc->subxids.nxids == 0);
- Assert(MyProc->subxids.overflowed == false);
- }
- }
+ ProcArrayEndTransaction(MyProc, latestXid);
/*
* This is all post-commit cleanup. Note that if an error is raised here,
@@ -1824,20 +1804,8 @@ PrepareTransaction(void)
* Let others know about no transaction in progress by me. This has to be
* done *after* the prepared transaction has been marked valid, else
* someone may think it is unlocked and recyclable.
- *
- * We can skip locking ProcArrayLock here, because this action does not
- * actually change anyone's view of the set of running XIDs: our entry
- * is duplicate with the gxact that has already been inserted into the
- * ProcArray.
*/
- MyProc->xid = InvalidTransactionId;
- MyProc->lxid = InvalidLocalTransactionId;
- MyProc->xmin = InvalidTransactionId;
- MyProc->inVacuum = false; /* must be cleared with xid/xmin */
-
- /* Clear the subtransaction-XID cache too */
- MyProc->subxids.nxids = 0;
- MyProc->subxids.overflowed = false;
+ ProcArrayClearTransaction(MyProc);
/*
* This is all post-transaction cleanup. Note that if an error is raised
@@ -1921,6 +1889,7 @@ static void
AbortTransaction(void)
{
TransactionState s = CurrentTransactionState;
+ TransactionId latestXid;
/* Prevent cancel/die interrupt while cleaning up */
HOLD_INTERRUPTS();
@@ -1987,7 +1956,7 @@ AbortTransaction(void)
* Advertise the fact that we aborted in pg_clog (assuming that we got as
* far as assigning an XID to advertise).
*/
- RecordTransactionAbort(false);
+ latestXid = RecordTransactionAbort(false);
PG_TRACE1(transaction__abort, MyProc->lxid);
@@ -1995,49 +1964,8 @@ AbortTransaction(void)
* Let others know about no transaction in progress by me. Note that this
* must be done _before_ releasing locks we hold and _after_
* RecordTransactionAbort.
- *
- * Note: MyProc may be null during bootstrap.
*/
- if (MyProc != NULL)
- {
- if (TransactionIdIsValid(MyProc->xid))
- {
- /*
- * We must lock ProcArrayLock while clearing MyProc->xid, so
- * that we do not exit the set of "running" transactions while
- * someone else is taking a snapshot. See discussion in
- * src/backend/access/transam/README.
- */
- LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
-
- MyProc->xid = InvalidTransactionId;
- MyProc->lxid = InvalidLocalTransactionId;
- MyProc->xmin = InvalidTransactionId;
- MyProc->inVacuum = false; /* must be cleared with xid/xmin */
- MyProc->inCommit = false; /* be sure this gets cleared */
-
- /* Clear the subtransaction-XID cache too while holding the lock */
- MyProc->subxids.nxids = 0;
- MyProc->subxids.overflowed = false;
-
- LWLockRelease(ProcArrayLock);
- }
- else
- {
- /*
- * If we have no XID, we don't need to lock, since we won't
- * affect anyone else's calculation of a snapshot. We might
- * change their estimate of global xmin, but that's OK.
- */
- MyProc->lxid = InvalidLocalTransactionId;
- MyProc->xmin = InvalidTransactionId;
- MyProc->inVacuum = false; /* must be cleared with xid/xmin */
- MyProc->inCommit = false; /* be sure this gets cleared */
-
- Assert(MyProc->subxids.nxids == 0);
- Assert(MyProc->subxids.overflowed == false);
- }
- }
+ ProcArrayEndTransaction(MyProc, latestXid);
/*
* Post-abort cleanup. See notes in CommitTransaction() concerning
@@ -3863,7 +3791,7 @@ AbortSubTransaction(void)
s->parent->subTransactionId);
/* Advertise the fact that we aborted in pg_clog. */
- RecordTransactionAbort(true);
+ (void) RecordTransactionAbort(true);
/* Post-abort cleanup */
if (TransactionIdIsValid(s->transactionId))