@@ -113,7 +113,8 @@ int max_prepared_xacts = 0;
113
113
114
114
typedef struct GlobalTransactionData
115
115
{
116
- PGPROC proc ; /* dummy proc */
116
+ GlobalTransaction next ;
117
+ int pgprocno ; /* dummy proc */
117
118
BackendId dummyBackendId ; /* similar to backend id for backends */
118
119
TimestampTz prepared_at ; /* time of preparation */
119
120
XLogRecPtr prepare_lsn ; /* XLOG offset of prepare record */
@@ -207,7 +208,8 @@ TwoPhaseShmemInit(void)
207
208
sizeof (GlobalTransaction ) * max_prepared_xacts ));
208
209
for (i = 0 ; i < max_prepared_xacts ; i ++ )
209
210
{
210
- gxacts [i ].proc .links .next = (SHM_QUEUE * ) TwoPhaseState -> freeGXacts ;
211
+ gxacts [i ].pgprocno = PreparedXactProcs [i ].pgprocno ;
212
+ gxacts [i ].next = TwoPhaseState -> freeGXacts ;
211
213
TwoPhaseState -> freeGXacts = & gxacts [i ];
212
214
213
215
/*
@@ -243,6 +245,8 @@ MarkAsPreparing(TransactionId xid, const char *gid,
243
245
TimestampTz prepared_at , Oid owner , Oid databaseid )
244
246
{
245
247
GlobalTransaction gxact ;
248
+ PGPROC * proc ;
249
+ PGXACT * pgxact ;
246
250
int i ;
247
251
248
252
if (strlen (gid ) >= GIDSIZE )
@@ -274,7 +278,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
274
278
TwoPhaseState -> numPrepXacts -- ;
275
279
TwoPhaseState -> prepXacts [i ] = TwoPhaseState -> prepXacts [TwoPhaseState -> numPrepXacts ];
276
280
/* and put it back in the freelist */
277
- gxact -> proc . links . next = ( SHM_QUEUE * ) TwoPhaseState -> freeGXacts ;
281
+ gxact -> next = TwoPhaseState -> freeGXacts ;
278
282
TwoPhaseState -> freeGXacts = gxact ;
279
283
/* Back up index count too, so we don't miss scanning one */
280
284
i -- ;
@@ -302,32 +306,36 @@ MarkAsPreparing(TransactionId xid, const char *gid,
302
306
errhint ("Increase max_prepared_transactions (currently %d)." ,
303
307
max_prepared_xacts )));
304
308
gxact = TwoPhaseState -> freeGXacts ;
305
- TwoPhaseState -> freeGXacts = (GlobalTransaction ) gxact -> proc . links . next ;
309
+ TwoPhaseState -> freeGXacts = (GlobalTransaction ) gxact -> next ;
306
310
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 ;
311
319
/* 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 ;
326
334
for (i = 0 ; i < NUM_LOCK_PARTITIONS ; i ++ )
327
- SHMQueueInit (& (gxact -> proc . myProcLocks [i ]));
335
+ SHMQueueInit (& (proc -> myProcLocks [i ]));
328
336
/* 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 ;
331
339
332
340
gxact -> prepared_at = prepared_at ;
333
341
/* initialize LSN to 0 (start of WAL) */
@@ -358,17 +366,19 @@ static void
358
366
GXactLoadSubxactData (GlobalTransaction gxact , int nsubxacts ,
359
367
TransactionId * children )
360
368
{
369
+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
370
+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
361
371
/* We need no extra lock since the GXACT isn't valid yet */
362
372
if (nsubxacts > PGPROC_MAX_CACHED_SUBXIDS )
363
373
{
364
- gxact -> proc . subxids . overflowed = true;
374
+ pgxact -> overflowed = true;
365
375
nsubxacts = PGPROC_MAX_CACHED_SUBXIDS ;
366
376
}
367
377
if (nsubxacts > 0 )
368
378
{
369
- memcpy (gxact -> proc . subxids .xids , children ,
379
+ memcpy (proc -> subxids .xids , children ,
370
380
nsubxacts * sizeof (TransactionId ));
371
- gxact -> proc . subxids . nxids = nsubxacts ;
381
+ pgxact -> nxids = nsubxacts ;
372
382
}
373
383
}
374
384
@@ -389,7 +399,7 @@ MarkAsPrepared(GlobalTransaction gxact)
389
399
* Put it into the global ProcArray so TransactionIdIsInProgress considers
390
400
* the XID as still running.
391
401
*/
392
- ProcArrayAdd (& gxact -> proc );
402
+ ProcArrayAdd (& ProcGlobal -> allProcs [ gxact -> pgprocno ] );
393
403
}
394
404
395
405
/*
@@ -406,6 +416,7 @@ LockGXact(const char *gid, Oid user)
406
416
for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
407
417
{
408
418
GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
419
+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
409
420
410
421
/* Ignore not-yet-valid GIDs */
411
422
if (!gxact -> valid )
@@ -436,7 +447,7 @@ LockGXact(const char *gid, Oid user)
436
447
* there may be some other issues as well. Hence disallow until
437
448
* someone gets motivated to make it work.
438
449
*/
439
- if (MyDatabaseId != gxact -> proc . databaseId )
450
+ if (MyDatabaseId != proc -> databaseId )
440
451
ereport (ERROR ,
441
452
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
442
453
errmsg ("prepared transaction belongs to another database" ),
@@ -483,7 +494,7 @@ RemoveGXact(GlobalTransaction gxact)
483
494
TwoPhaseState -> prepXacts [i ] = TwoPhaseState -> prepXacts [TwoPhaseState -> numPrepXacts ];
484
495
485
496
/* and put it back in the freelist */
486
- gxact -> proc . links . next = ( SHM_QUEUE * ) TwoPhaseState -> freeGXacts ;
497
+ gxact -> next = TwoPhaseState -> freeGXacts ;
487
498
TwoPhaseState -> freeGXacts = gxact ;
488
499
489
500
LWLockRelease (TwoPhaseStateLock );
@@ -518,8 +529,9 @@ TransactionIdIsPrepared(TransactionId xid)
518
529
for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
519
530
{
520
531
GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
532
+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
521
533
522
- if (gxact -> valid && gxact -> proc . xid == xid )
534
+ if (gxact -> valid && pgxact -> xid == xid )
523
535
{
524
536
result = true;
525
537
break ;
@@ -642,6 +654,8 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
642
654
while (status -> array != NULL && status -> currIdx < status -> ngxacts )
643
655
{
644
656
GlobalTransaction gxact = & status -> array [status -> currIdx ++ ];
657
+ PGPROC * proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
658
+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
645
659
Datum values [5 ];
646
660
bool nulls [5 ];
647
661
HeapTuple tuple ;
@@ -656,11 +670,11 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
656
670
MemSet (values , 0 , sizeof (values ));
657
671
MemSet (nulls , 0 , sizeof (nulls ));
658
672
659
- values [0 ] = TransactionIdGetDatum (gxact -> proc . xid );
673
+ values [0 ] = TransactionIdGetDatum (pgxact -> xid );
660
674
values [1 ] = CStringGetTextDatum (gxact -> gid );
661
675
values [2 ] = TimestampTzGetDatum (gxact -> prepared_at );
662
676
values [3 ] = ObjectIdGetDatum (gxact -> owner );
663
- values [4 ] = ObjectIdGetDatum (gxact -> proc . databaseId );
677
+ values [4 ] = ObjectIdGetDatum (proc -> databaseId );
664
678
665
679
tuple = heap_form_tuple (funcctx -> tuple_desc , values , nulls );
666
680
result = HeapTupleGetDatum (tuple );
@@ -711,10 +725,11 @@ TwoPhaseGetDummyProc(TransactionId xid)
711
725
for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
712
726
{
713
727
GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
728
+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
714
729
715
- if (gxact -> proc . xid == xid )
730
+ if (pgxact -> xid == xid )
716
731
{
717
- result = & gxact -> proc ;
732
+ result = & ProcGlobal -> allProcs [ gxact -> pgprocno ] ;
718
733
break ;
719
734
}
720
735
}
@@ -841,7 +856,9 @@ save_state_data(const void *data, uint32 len)
841
856
void
842
857
StartPrepare (GlobalTransaction gxact )
843
858
{
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 ;
845
862
TwoPhaseFileHeader hdr ;
846
863
TransactionId * children ;
847
864
RelFileNode * commitrels ;
@@ -865,7 +882,7 @@ StartPrepare(GlobalTransaction gxact)
865
882
hdr .magic = TWOPHASE_MAGIC ;
866
883
hdr .total_len = 0 ; /* EndPrepare will fill this in */
867
884
hdr .xid = xid ;
868
- hdr .database = gxact -> proc . databaseId ;
885
+ hdr .database = proc -> databaseId ;
869
886
hdr .prepared_at = gxact -> prepared_at ;
870
887
hdr .owner = gxact -> owner ;
871
888
hdr .nsubxacts = xactGetCommittedChildren (& children );
@@ -913,7 +930,8 @@ StartPrepare(GlobalTransaction gxact)
913
930
void
914
931
EndPrepare (GlobalTransaction gxact )
915
932
{
916
- TransactionId xid = gxact -> proc .xid ;
933
+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
934
+ TransactionId xid = pgxact -> xid ;
917
935
TwoPhaseFileHeader * hdr ;
918
936
char path [MAXPGPATH ];
919
937
XLogRecData * record ;
@@ -1021,7 +1039,7 @@ EndPrepare(GlobalTransaction gxact)
1021
1039
*/
1022
1040
START_CRIT_SECTION ();
1023
1041
1024
- MyProc -> inCommit = true;
1042
+ MyPgXact -> inCommit = true;
1025
1043
1026
1044
gxact -> prepare_lsn = XLogInsert (RM_XACT_ID , XLOG_XACT_PREPARE ,
1027
1045
records .head );
@@ -1069,7 +1087,7 @@ EndPrepare(GlobalTransaction gxact)
1069
1087
* checkpoint starting after this will certainly see the gxact as a
1070
1088
* candidate for fsyncing.
1071
1089
*/
1072
- MyProc -> inCommit = false;
1090
+ MyPgXact -> inCommit = false;
1073
1091
1074
1092
END_CRIT_SECTION ();
1075
1093
@@ -1242,6 +1260,8 @@ void
1242
1260
FinishPreparedTransaction (const char * gid , bool isCommit )
1243
1261
{
1244
1262
GlobalTransaction gxact ;
1263
+ PGPROC * proc ;
1264
+ PGXACT * pgxact ;
1245
1265
TransactionId xid ;
1246
1266
char * buf ;
1247
1267
char * bufptr ;
@@ -1260,7 +1280,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1260
1280
* try to commit the same GID at once.
1261
1281
*/
1262
1282
gxact = LockGXact (gid , GetUserId ());
1263
- xid = gxact -> proc .xid ;
1283
+ proc = & ProcGlobal -> allProcs [gxact -> pgprocno ];
1284
+ pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
1285
+ xid = pgxact -> xid ;
1264
1286
1265
1287
/*
1266
1288
* Read and validate the state file
@@ -1309,7 +1331,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1309
1331
hdr -> nsubxacts , children ,
1310
1332
hdr -> nabortrels , abortrels );
1311
1333
1312
- ProcArrayRemove (& gxact -> proc , latestXid );
1334
+ ProcArrayRemove (proc , latestXid );
1313
1335
1314
1336
/*
1315
1337
* In case we fail while running the callbacks, mark the gxact invalid so
@@ -1540,10 +1562,11 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1540
1562
for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
1541
1563
{
1542
1564
GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
1565
+ PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
1543
1566
1544
1567
if (gxact -> valid &&
1545
1568
XLByteLE (gxact -> prepare_lsn , redo_horizon ))
1546
- xids [nxids ++ ] = gxact -> proc . xid ;
1569
+ xids [nxids ++ ] = pgxact -> xid ;
1547
1570
}
1548
1571
1549
1572
LWLockRelease (TwoPhaseStateLock );
@@ -1972,7 +1995,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
1972
1995
START_CRIT_SECTION ();
1973
1996
1974
1997
/* See notes in RecordTransactionCommit */
1975
- MyProc -> inCommit = true;
1998
+ MyPgXact -> inCommit = true;
1976
1999
1977
2000
/* Emit the XLOG commit record */
1978
2001
xlrec .xid = xid ;
@@ -2037,7 +2060,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
2037
2060
TransactionIdCommitTree (xid , nchildren , children );
2038
2061
2039
2062
/* Checkpoint can proceed now */
2040
- MyProc -> inCommit = false;
2063
+ MyPgXact -> inCommit = false;
2041
2064
2042
2065
END_CRIT_SECTION ();
2043
2066
0 commit comments