aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-08-08 11:52:02 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-08-08 11:52:02 -0400
commitdb108349bf7fe7fe82e2ff32e42436cfbc4f37dc (patch)
tree16969ff44a50288ce8d9fc48a69454cd1239aca3 /src
parent5ebaaa49445eb1ba7b299bbea3a477d4e4c0430b (diff)
downloadpostgresql-db108349bf7fe7fe82e2ff32e42436cfbc4f37dc.tar.gz
postgresql-db108349bf7fe7fe82e2ff32e42436cfbc4f37dc.zip
Fix TwoPhaseGetDummyBackendId().
This was broken in commit ed0b409d22346b1b027a4c2099ca66984d94b6dd, which revised the GlobalTransactionData struct to not include the associated PGPROC as its first member, but overlooked one place where a cast was used in reliance on that equivalence. The most effective way of fixing this seems to be to create a new function that looks up the GlobalTransactionData struct given the XID, and make both TwoPhaseGetDummyBackendId and TwoPhaseGetDummyProc rely on that. Per report from Robert Ross.
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/twophase.c76
1 files changed, 46 insertions, 30 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 7f198c2e3e0..2a60c62dd4d 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -108,8 +108,8 @@ int max_prepared_xacts = 0;
typedef struct GlobalTransactionData
{
- GlobalTransaction next;
- int pgprocno; /* dummy proc */
+ GlobalTransaction next; /* list link for free list */
+ int pgprocno; /* ID of associated dummy PGPROC */
BackendId dummyBackendId; /* similar to backend id for backends */
TimestampTz prepared_at; /* time of preparation */
XLogRecPtr prepare_lsn; /* XLOG offset of prepare record */
@@ -203,10 +203,13 @@ TwoPhaseShmemInit(void)
sizeof(GlobalTransaction) * max_prepared_xacts));
for (i = 0; i < max_prepared_xacts; i++)
{
- gxacts[i].pgprocno = PreparedXactProcs[i].pgprocno;
+ /* insert into linked list */
gxacts[i].next = TwoPhaseState->freeGXacts;
TwoPhaseState->freeGXacts = &gxacts[i];
+ /* associate it with a PGPROC assigned by InitProcGlobal */
+ gxacts[i].pgprocno = PreparedXactProcs[i].pgprocno;
+
/*
* Assign a unique ID for each dummy proc, so that the range of
* dummy backend IDs immediately follows the range of normal
@@ -301,7 +304,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
errhint("Increase max_prepared_transactions (currently %d).",
max_prepared_xacts)));
gxact = TwoPhaseState->freeGXacts;
- TwoPhaseState->freeGXacts = (GlobalTransaction) gxact->next;
+ TwoPhaseState->freeGXacts = gxact->next;
proc = &ProcGlobal->allProcs[gxact->pgprocno];
pgxact = &ProcGlobal->allPgXact[gxact->pgprocno];
@@ -680,40 +683,25 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
}
/*
- * TwoPhaseGetDummyProc
- * Get the dummy backend ID for prepared transaction specified by XID
- *
- * Dummy backend IDs are similar to real backend IDs of real backends.
- * They start at MaxBackends + 1, and are unique across all currently active
- * real backends and prepared transactions.
+ * TwoPhaseGetGXact
+ * Get the GlobalTransaction struct for a prepared transaction
+ * specified by XID
*/
-BackendId
-TwoPhaseGetDummyBackendId(TransactionId xid)
-{
- PGPROC *proc = TwoPhaseGetDummyProc(xid);
-
- return ((GlobalTransaction) proc)->dummyBackendId;
-}
-
-/*
- * TwoPhaseGetDummyProc
- * Get the PGPROC that represents a prepared transaction specified by XID
- */
-PGPROC *
-TwoPhaseGetDummyProc(TransactionId xid)
+static GlobalTransaction
+TwoPhaseGetGXact(TransactionId xid)
{
- PGPROC *result = NULL;
+ GlobalTransaction result = NULL;
int i;
static TransactionId cached_xid = InvalidTransactionId;
- static PGPROC *cached_proc = NULL;
+ static GlobalTransaction cached_gxact = NULL;
/*
* During a recovery, COMMIT PREPARED, or ABORT PREPARED, we'll be called
* repeatedly for the same XID. We can save work with a simple cache.
*/
if (xid == cached_xid)
- return cached_proc;
+ return cached_gxact;
LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
@@ -724,7 +712,7 @@ TwoPhaseGetDummyProc(TransactionId xid)
if (pgxact->xid == xid)
{
- result = &ProcGlobal->allProcs[gxact->pgprocno];
+ result = gxact;
break;
}
}
@@ -732,14 +720,42 @@ TwoPhaseGetDummyProc(TransactionId xid)
LWLockRelease(TwoPhaseStateLock);
if (result == NULL) /* should not happen */
- elog(ERROR, "failed to find dummy PGPROC for xid %u", xid);
+ elog(ERROR, "failed to find GlobalTransaction for xid %u", xid);
cached_xid = xid;
- cached_proc = result;
+ cached_gxact = result;
return result;
}
+/*
+ * TwoPhaseGetDummyProc
+ * Get the dummy backend ID for prepared transaction specified by XID
+ *
+ * Dummy backend IDs are similar to real backend IDs of real backends.
+ * They start at MaxBackends + 1, and are unique across all currently active
+ * real backends and prepared transactions.
+ */
+BackendId
+TwoPhaseGetDummyBackendId(TransactionId xid)
+{
+ GlobalTransaction gxact = TwoPhaseGetGXact(xid);
+
+ return gxact->dummyBackendId;
+}
+
+/*
+ * TwoPhaseGetDummyProc
+ * Get the PGPROC that represents a prepared transaction specified by XID
+ */
+PGPROC *
+TwoPhaseGetDummyProc(TransactionId xid)
+{
+ GlobalTransaction gxact = TwoPhaseGetGXact(xid);
+
+ return &ProcGlobal->allProcs[gxact->pgprocno];
+}
+
/************************************************************************/
/* State file support */
/************************************************************************/