@@ -113,7 +113,8 @@ intmax_prepared_xacts = 0;
113113
114114typedef struct GlobalTransactionData
115115{
116- PGPROC proc ;/* dummy proc */
116+ GlobalTransaction next ;
117+ int pgprocno ;/* dummy proc */
117118BackendId dummyBackendId ;/* similar to backend id for backends */
118119TimestampTz prepared_at ;/* time of preparation */
119120XLogRecPtr prepare_lsn ;/* XLOG offset of prepare record */
@@ -207,7 +208,8 @@ TwoPhaseShmemInit(void)
207208sizeof (GlobalTransaction )* max_prepared_xacts ));
208209for (i = 0 ;i < max_prepared_xacts ;i ++ )
209210{
210- gxacts [i ].proc .links .next = (SHM_QUEUE * )TwoPhaseState -> freeGXacts ;
211+ gxacts [i ].pgprocno = PreparedXactProcs [i ].pgprocno ;
212+ gxacts [i ].next = TwoPhaseState -> freeGXacts ;
211213TwoPhaseState -> freeGXacts = & gxacts [i ];
212214
213215/*
@@ -243,6 +245,8 @@ MarkAsPreparing(TransactionId xid, const char *gid,
243245TimestampTz prepared_at ,Oid owner ,Oid databaseid )
244246{
245247GlobalTransaction gxact ;
248+ PGPROC * proc ;
249+ PGXACT * pgxact ;
246250int i ;
247251
248252if (strlen (gid ) >=GIDSIZE )
@@ -274,7 +278,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
274278TwoPhaseState -> numPrepXacts -- ;
275279TwoPhaseState -> prepXacts [i ]= TwoPhaseState -> prepXacts [TwoPhaseState -> numPrepXacts ];
276280/* and put it back in the freelist */
277- gxact -> proc . links . next = ( SHM_QUEUE * ) TwoPhaseState -> freeGXacts ;
281+ gxact -> next = TwoPhaseState -> freeGXacts ;
278282TwoPhaseState -> freeGXacts = gxact ;
279283/* Back up index count too, so we don't miss scanning one */
280284i -- ;
@@ -302,32 +306,36 @@ MarkAsPreparing(TransactionId xid, const char *gid,
302306errhint ("Increase max_prepared_transactions (currently %d)." ,
303307max_prepared_xacts )));
304308gxact = TwoPhaseState -> freeGXacts ;
305- TwoPhaseState -> freeGXacts = (GlobalTransaction )gxact -> proc . links . next ;
309+ TwoPhaseState -> freeGXacts = (GlobalTransaction )gxact -> next ;
306310
307- /* Initialize it */
308- MemSet (& gxact -> proc ,0 ,sizeof (PGPROC ));
309- SHMQueueElemInit (& (gxact -> proc .links ));
310- gxact -> proc .waitStatus = STATUS_OK ;
311+ proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
312+ pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
313+
314+ /* Initialize the PGPROC entry */
315+ MemSet (proc ,0 ,sizeof (PGPROC ));
316+ proc -> pgprocno = gxact -> pgprocno ;
317+ SHMQueueElemInit (& (proc -> links ));
318+ proc -> waitStatus = STATUS_OK ;
311319/* We set up the gxact's VXID as InvalidBackendId/XID */
312- gxact -> proc . lxid = (LocalTransactionId )xid ;
313- gxact -> proc . xid = xid ;
314- gxact -> proc . xmin = InvalidTransactionId ;
315- gxact -> proc . pid = 0 ;
316- gxact -> proc . backendId = InvalidBackendId ;
317- gxact -> proc . databaseId = databaseid ;
318- gxact -> proc . roleId = owner ;
319- gxact -> proc . inCommit = false ;
320- gxact -> proc . vacuumFlags = 0 ;
321- gxact -> proc . lwWaiting = false;
322- gxact -> proc . lwExclusive = false;
323- gxact -> proc . lwWaitLink = NULL ;
324- gxact -> proc . waitLock = NULL ;
325- gxact -> proc . waitProcLock = NULL ;
320+ proc -> lxid = (LocalTransactionId )xid ;
321+ pgxact -> xid = xid ;
322+ pgxact -> xmin = InvalidTransactionId ;
323+ pgxact -> inCommit = false ;
324+ pgxact -> vacuumFlags = 0 ;
325+ proc -> pid = 0 ;
326+ proc -> backendId = InvalidBackendId ;
327+ proc -> databaseId = databaseid ;
328+ proc -> roleId = owner ;
329+ proc -> lwWaiting = false;
330+ proc -> lwExclusive = false;
331+ proc -> lwWaitLink = NULL ;
332+ proc -> waitLock = NULL ;
333+ proc -> waitProcLock = NULL ;
326334for (i = 0 ;i < NUM_LOCK_PARTITIONS ;i ++ )
327- SHMQueueInit (& (gxact -> proc . myProcLocks [i ]));
335+ SHMQueueInit (& (proc -> myProcLocks [i ]));
328336/* subxid data must be filled later by GXactLoadSubxactData */
329- gxact -> proc . subxids . overflowed = false;
330- gxact -> proc . subxids . nxids = 0 ;
337+ pgxact -> overflowed = false;
338+ pgxact -> nxids = 0 ;
331339
332340gxact -> prepared_at = prepared_at ;
333341/* initialize LSN to 0 (start of WAL) */
@@ -358,17 +366,19 @@ static void
358366GXactLoadSubxactData (GlobalTransaction gxact ,int nsubxacts ,
359367TransactionId * children )
360368{
369+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
370+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
361371/* We need no extra lock since the GXACT isn't valid yet */
362372if (nsubxacts > PGPROC_MAX_CACHED_SUBXIDS )
363373{
364- gxact -> proc . subxids . overflowed = true;
374+ pgxact -> overflowed = true;
365375nsubxacts = PGPROC_MAX_CACHED_SUBXIDS ;
366376}
367377if (nsubxacts > 0 )
368378{
369- memcpy (gxact -> proc . subxids .xids ,children ,
379+ memcpy (proc -> subxids .xids ,children ,
370380nsubxacts * sizeof (TransactionId ));
371- gxact -> proc . subxids . nxids = nsubxacts ;
381+ pgxact -> nxids = nsubxacts ;
372382}
373383}
374384
@@ -389,7 +399,7 @@ MarkAsPrepared(GlobalTransaction gxact)
389399 * Put it into the global ProcArray so TransactionIdIsInProgress considers
390400 * the XID as still running.
391401 */
392- ProcArrayAdd (& gxact -> proc );
402+ ProcArrayAdd (& ProcGlobal -> allProcs [ gxact -> pgprocno ] );
393403}
394404
395405/*
@@ -406,6 +416,7 @@ LockGXact(const char *gid, Oid user)
406416for (i = 0 ;i < TwoPhaseState -> numPrepXacts ;i ++ )
407417{
408418GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
419+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
409420
410421/* Ignore not-yet-valid GIDs */
411422if (!gxact -> valid )
@@ -436,7 +447,7 @@ LockGXact(const char *gid, Oid user)
436447 * there may be some other issues as well.Hence disallow until
437448 * someone gets motivated to make it work.
438449 */
439- if (MyDatabaseId != gxact -> proc . databaseId )
450+ if (MyDatabaseId != proc -> databaseId )
440451ereport (ERROR ,
441452(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
442453errmsg ("prepared transaction belongs to another database" ),
@@ -483,7 +494,7 @@ RemoveGXact(GlobalTransaction gxact)
483494TwoPhaseState -> prepXacts [i ]= TwoPhaseState -> prepXacts [TwoPhaseState -> numPrepXacts ];
484495
485496/* and put it back in the freelist */
486- gxact -> proc . links . next = ( SHM_QUEUE * ) TwoPhaseState -> freeGXacts ;
497+ gxact -> next = TwoPhaseState -> freeGXacts ;
487498TwoPhaseState -> freeGXacts = gxact ;
488499
489500LWLockRelease (TwoPhaseStateLock );
@@ -518,8 +529,9 @@ TransactionIdIsPrepared(TransactionId xid)
518529for (i = 0 ;i < TwoPhaseState -> numPrepXacts ;i ++ )
519530{
520531GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
532+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
521533
522- if (gxact -> valid && gxact -> proc . xid == xid )
534+ if (gxact -> valid && pgxact -> xid == xid )
523535{
524536result = true;
525537break ;
@@ -642,6 +654,8 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
642654while (status -> array != NULL && status -> currIdx < status -> ngxacts )
643655{
644656GlobalTransaction gxact = & status -> array [status -> currIdx ++ ];
657+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
658+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
645659Datum values [5 ];
646660bool nulls [5 ];
647661HeapTuple tuple ;
@@ -656,11 +670,11 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
656670MemSet (values ,0 ,sizeof (values ));
657671MemSet (nulls ,0 ,sizeof (nulls ));
658672
659- values [0 ]= TransactionIdGetDatum (gxact -> proc . xid );
673+ values [0 ]= TransactionIdGetDatum (pgxact -> xid );
660674values [1 ]= CStringGetTextDatum (gxact -> gid );
661675values [2 ]= TimestampTzGetDatum (gxact -> prepared_at );
662676values [3 ]= ObjectIdGetDatum (gxact -> owner );
663- values [4 ]= ObjectIdGetDatum (gxact -> proc . databaseId );
677+ values [4 ]= ObjectIdGetDatum (proc -> databaseId );
664678
665679tuple = heap_form_tuple (funcctx -> tuple_desc ,values ,nulls );
666680result = HeapTupleGetDatum (tuple );
@@ -711,10 +725,11 @@ TwoPhaseGetDummyProc(TransactionId xid)
711725for (i = 0 ;i < TwoPhaseState -> numPrepXacts ;i ++ )
712726{
713727GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
728+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
714729
715- if (gxact -> proc . xid == xid )
730+ if (pgxact -> xid == xid )
716731{
717- result = & gxact -> proc ;
732+ result = & ProcGlobal -> allProcs [ gxact -> pgprocno ] ;
718733break ;
719734}
720735}
@@ -841,7 +856,9 @@ save_state_data(const void *data, uint32 len)
841856void
842857StartPrepare (GlobalTransaction gxact )
843858{
844- TransactionId xid = gxact -> proc .xid ;
859+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
860+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
861+ TransactionId xid = pgxact -> xid ;
845862TwoPhaseFileHeader hdr ;
846863TransactionId * children ;
847864RelFileNode * commitrels ;
@@ -865,7 +882,7 @@ StartPrepare(GlobalTransaction gxact)
865882hdr .magic = TWOPHASE_MAGIC ;
866883hdr .total_len = 0 ;/* EndPrepare will fill this in */
867884hdr .xid = xid ;
868- hdr .database = gxact -> proc . databaseId ;
885+ hdr .database = proc -> databaseId ;
869886hdr .prepared_at = gxact -> prepared_at ;
870887hdr .owner = gxact -> owner ;
871888hdr .nsubxacts = xactGetCommittedChildren (& children );
@@ -913,7 +930,8 @@ StartPrepare(GlobalTransaction gxact)
913930void
914931EndPrepare (GlobalTransaction gxact )
915932{
916- TransactionId xid = gxact -> proc .xid ;
933+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
934+ TransactionId xid = pgxact -> xid ;
917935TwoPhaseFileHeader * hdr ;
918936char path [MAXPGPATH ];
919937XLogRecData * record ;
@@ -1021,7 +1039,7 @@ EndPrepare(GlobalTransaction gxact)
10211039 */
10221040START_CRIT_SECTION ();
10231041
1024- MyProc -> inCommit = true;
1042+ MyPgXact -> inCommit = true;
10251043
10261044gxact -> prepare_lsn = XLogInsert (RM_XACT_ID ,XLOG_XACT_PREPARE ,
10271045records .head );
@@ -1069,7 +1087,7 @@ EndPrepare(GlobalTransaction gxact)
10691087 * checkpoint starting after this will certainly see the gxact as a
10701088 * candidate for fsyncing.
10711089 */
1072- MyProc -> inCommit = false;
1090+ MyPgXact -> inCommit = false;
10731091
10741092END_CRIT_SECTION ();
10751093
@@ -1242,6 +1260,8 @@ void
12421260FinishPreparedTransaction (const char * gid ,bool isCommit )
12431261{
12441262GlobalTransaction gxact ;
1263+ PGPROC * proc ;
1264+ PGXACT * pgxact ;
12451265TransactionId xid ;
12461266char * buf ;
12471267char * bufptr ;
@@ -1260,7 +1280,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
12601280 * try to commit the same GID at once.
12611281 */
12621282gxact = LockGXact (gid ,GetUserId ());
1263- xid = gxact -> proc .xid ;
1283+ proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
1284+ pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
1285+ xid = pgxact -> xid ;
12641286
12651287/*
12661288 * Read and validate the state file
@@ -1309,7 +1331,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
13091331hdr -> nsubxacts ,children ,
13101332hdr -> nabortrels ,abortrels );
13111333
1312- ProcArrayRemove (& gxact -> proc ,latestXid );
1334+ ProcArrayRemove (proc ,latestXid );
13131335
13141336/*
13151337 * In case we fail while running the callbacks, mark the gxact invalid so
@@ -1540,10 +1562,11 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
15401562for (i = 0 ;i < TwoPhaseState -> numPrepXacts ;i ++ )
15411563{
15421564GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
1565+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
15431566
15441567if (gxact -> valid &&
15451568XLByteLE (gxact -> prepare_lsn ,redo_horizon ))
1546- xids [nxids ++ ]= gxact -> proc . xid ;
1569+ xids [nxids ++ ]= pgxact -> xid ;
15471570}
15481571
15491572LWLockRelease (TwoPhaseStateLock );
@@ -1972,7 +1995,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
19721995START_CRIT_SECTION ();
19731996
19741997/* See notes in RecordTransactionCommit */
1975- MyProc -> inCommit = true;
1998+ MyPgXact -> inCommit = true;
19761999
19772000/* Emit the XLOG commit record */
19782001xlrec .xid = xid ;
@@ -2037,7 +2060,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
20372060TransactionIdCommitTree (xid ,nchildren ,children );
20382061
20392062/* Checkpoint can proceed now */
2040- MyProc -> inCommit = false;
2063+ MyPgXact -> inCommit = false;
20412064
20422065END_CRIT_SECTION ();
20432066