@@ -122,7 +122,7 @@ typedef struct GlobalTransactionData
122
122
TimestampTz prepared_at ; /* time of preparation */
123
123
XLogRecPtr prepare_lsn ; /* XLOG offset of prepare record end */
124
124
XLogRecPtr prepare_xlogptr ; /* XLOG offset of prepare record start
125
- * or NULL if twophase data moved to file
125
+ * or NULL if twophase data moved to file
126
126
* after checkpoint.
127
127
*/
128
128
Oid owner ; /* ID of user that executed the xact */
@@ -587,41 +587,6 @@ RemoveGXact(GlobalTransaction gxact)
587
587
elog (ERROR , "failed to find %p in GlobalTransaction array" , gxact );
588
588
}
589
589
590
- /*
591
- * TransactionIdIsPrepared
592
- * True iff transaction associated with the identifier is prepared
593
- * for two-phase commit
594
- *
595
- * Note: only gxacts marked "valid" are considered; but notice we do not
596
- * check the locking status.
597
- *
598
- * This is not currently exported, because it is only needed internally.
599
- */
600
- static bool
601
- TransactionIdIsPrepared (TransactionId xid )
602
- {
603
- bool result = false;
604
- int i ;
605
-
606
- LWLockAcquire (TwoPhaseStateLock , LW_SHARED );
607
-
608
- for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
609
- {
610
- GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
611
- PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
612
-
613
- if (gxact -> valid && pgxact -> xid == xid )
614
- {
615
- result = true;
616
- break ;
617
- }
618
- }
619
-
620
- LWLockRelease (TwoPhaseStateLock );
621
-
622
- return result ;
623
- }
624
-
625
590
/*
626
591
* Returns an array of all prepared transactions for the user-level
627
592
* function pg_prepared_xact.
@@ -1244,6 +1209,36 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
1244
1209
return buf ;
1245
1210
}
1246
1211
1212
+
1213
+ /*
1214
+ * Reads 2PC data from xlog. During checkpoint this data will be moved to
1215
+ * twophase files and ReadTwoPhaseFile should be used instead.
1216
+ */
1217
+ static void
1218
+ XlogReadTwoPhaseData (XLogRecPtr lsn , char * * buf , int * len )
1219
+ {
1220
+ XLogRecord * record ;
1221
+ XLogReaderState * xlogreader ;
1222
+ char * errormsg ;
1223
+
1224
+ xlogreader = XLogReaderAllocate (& logical_read_local_xlog_page , NULL );
1225
+ if (xlogreader == NULL )
1226
+ elog (ERROR , "failed to open xlogreader for reading 2PC data" );
1227
+
1228
+ record = XLogReadRecord (xlogreader , lsn , & errormsg );
1229
+ if (record == NULL )
1230
+ elog (ERROR , "failed to read 2PC record from xlog" );
1231
+
1232
+ if (len != NULL )
1233
+ * len = XLogRecGetDataLen (xlogreader );
1234
+
1235
+ * buf = palloc (sizeof (char )* XLogRecGetDataLen (xlogreader ));
1236
+ memcpy (* buf , XLogRecGetData (xlogreader ), sizeof (char )* XLogRecGetDataLen (xlogreader ));
1237
+
1238
+ XLogReaderFree (xlogreader );
1239
+ }
1240
+
1241
+
1247
1242
/*
1248
1243
* Confirms an xid is prepared, during recovery
1249
1244
*/
@@ -1306,13 +1301,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1306
1301
1307
1302
/*
1308
1303
* Read and validate 2PC state data.
1309
- * State data can be stored in xlog or files depending on checkpoint
1310
- * status. One way to read that data is to delay checkpoint (delayChkpt) and
1311
- * compare gxact->prepare_lsn with current xlog horizon. But having in mind
1312
- * that most of 2PC transactions will be commited right after prepare, we
1313
- * can just try to read xlog and in case of error read file. Also that is
1314
- * happening under LockGXact, so nobody can commit our transaction between
1315
- * xlog and file reads.
1304
+ * State data can be stored in xlog or in files after xlog checkpoint.
1305
+ * While checkpointing we set gxact->prepare_lsn to NULL to signalize
1306
+ * that 2PC data is moved to files.
1316
1307
*/
1317
1308
if (gxact -> prepare_lsn )
1318
1309
{
@@ -1480,7 +1471,8 @@ RemoveTwoPhaseFile(TransactionId xid, bool giveWarning)
1480
1471
}
1481
1472
1482
1473
/*
1483
- * Recreates a state file. This is used in WAL replay.
1474
+ * Recreates a state file. This is used in WAL replay and during
1475
+ * checkpoint creation.
1484
1476
*
1485
1477
* Note: content and len don't include CRC.
1486
1478
*/
@@ -1574,12 +1566,11 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1574
1566
1575
1567
/*
1576
1568
* Here we doing whole I/O while holding TwoPhaseStateLock.
1577
- * It's also possible to move I/O out of the lock, but on
1569
+ * It's also possible to move I/O out of the lock, but on
1578
1570
* every error we should check whether somebody commited our
1579
1571
* transaction in different backend. Let's leave this optimisation
1580
- * for future, if somebody will spot that this place cause
1572
+ * for future, if somebody will spot that this place cause
1581
1573
* bottleneck.
1582
- *
1583
1574
*/
1584
1575
LWLockAcquire (TwoPhaseStateLock , LW_SHARED );
1585
1576
for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
@@ -2107,29 +2098,3 @@ RecordTransactionAbortPrepared(TransactionId xid,
2107
2098
*/
2108
2099
SyncRepWaitForLSN (recptr );
2109
2100
}
2110
-
2111
- /**********************************************************************************/
2112
-
2113
- static void
2114
- XlogReadTwoPhaseData (XLogRecPtr lsn , char * * buf , int * len )
2115
- {
2116
- XLogRecord * record ;
2117
- XLogReaderState * xlogreader ;
2118
- char * errormsg ;
2119
-
2120
- xlogreader = XLogReaderAllocate (& logical_read_local_xlog_page , NULL );
2121
- if (xlogreader == NULL )
2122
- elog (ERROR , "failed to open xlogreader for reading 2PC data" );
2123
-
2124
- record = XLogReadRecord (xlogreader , lsn , & errormsg );
2125
- if (record == NULL )
2126
- elog (ERROR , "failed to read 2PC record from xlog" );
2127
-
2128
- if (len != NULL )
2129
- * len = XLogRecGetDataLen (xlogreader );
2130
-
2131
- * buf = palloc (sizeof (char )* XLogRecGetDataLen (xlogreader ));
2132
- memcpy (* buf , XLogRecGetData (xlogreader ), sizeof (char )* XLogRecGetDataLen (xlogreader ));
2133
-
2134
- XLogReaderFree (xlogreader );
2135
- }
0 commit comments