@@ -122,7 +122,7 @@ typedef struct GlobalTransactionData
122122 TimestampTz prepared_at ; /* time of preparation */
123123 XLogRecPtr prepare_lsn ; /* XLOG offset of prepare record end */
124124 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
126126 * after checkpoint.
127127 */
128128 Oid owner ; /* ID of user that executed the xact */
@@ -587,41 +587,6 @@ RemoveGXact(GlobalTransaction gxact)
587587 elog (ERROR , "failed to find %p in GlobalTransaction array" , gxact );
588588}
589589
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-
625590/*
626591 * Returns an array of all prepared transactions for the user-level
627592 * function pg_prepared_xact.
@@ -1244,6 +1209,36 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
12441209 return buf ;
12451210}
12461211
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+
12471242/*
12481243 * Confirms an xid is prepared, during recovery
12491244 */
@@ -1306,13 +1301,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
13061301
13071302 /*
13081303 * 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.
13161307 */
13171308 if (gxact -> prepare_lsn )
13181309 {
@@ -1480,7 +1471,8 @@ RemoveTwoPhaseFile(TransactionId xid, bool giveWarning)
14801471}
14811472
14821473/*
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.
14841476 *
14851477 * Note: content and len don't include CRC.
14861478 */
@@ -1574,12 +1566,11 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
15741566
15751567 /*
15761568 * 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
15781570 * every error we should check whether somebody commited our
15791571 * 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
15811573 * bottleneck.
1582- *
15831574 */
15841575 LWLockAcquire (TwoPhaseStateLock , LW_SHARED );
15851576 for (i = 0 ; i < TwoPhaseState -> numPrepXacts ; i ++ )
@@ -2107,29 +2098,3 @@ RecordTransactionAbortPrepared(TransactionId xid,
21072098 */
21082099 SyncRepWaitForLSN (recptr );
21092100}
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