diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 7f198c2e3e0478c0719023673781e44372cd5a69..2a60c62dd4d7a233ee0a4422f5fac05b559e6727 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 */ /************************************************************************/