@@ -1056,6 +1056,8 @@ EndPrepare(GlobalTransaction gxact)
1056
1056
/* Store record's start location to read that later on Commit */
1057
1057
gxact -> prepare_start_lsn = ProcLastRecPtr ;
1058
1058
1059
+ fprintf (stderr , "=== Prepared tx stored at %lx : %lx \n" , gxact -> prepare_start_lsn , gxact -> prepare_end_lsn );
1060
+
1059
1061
/*
1060
1062
* Mark the prepared transaction as valid. As soon as xact.c marks
1061
1063
* MyPgXact as not running our XID (which it will do immediately after
@@ -1495,6 +1497,8 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
1495
1497
pg_crc32c statefile_crc ;
1496
1498
int fd ;
1497
1499
1500
+ fprintf (stderr , "===(%u) RecreateTwoPhaseFile called\n" , getpid ());
1501
+
1498
1502
/* Recompute CRC */
1499
1503
INIT_CRC32C (statefile_crc );
1500
1504
COMP_CRC32C (statefile_crc , content , len );
@@ -1639,6 +1643,8 @@ PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
1639
1643
int nxids = 0 ;
1640
1644
int allocsize = 0 ;
1641
1645
1646
+ fprintf (stderr , "===(%u) PrescanPreparedTransactions called\n" , getpid ());
1647
+
1642
1648
cldir = AllocateDir (TWOPHASE_DIR );
1643
1649
while ((clde = ReadDir (cldir , TWOPHASE_DIR )) != NULL )
1644
1650
{
@@ -1774,6 +1780,8 @@ StandbyRecoverPreparedTransactions(bool overwriteOK)
1774
1780
DIR * cldir ;
1775
1781
struct dirent * clde ;
1776
1782
1783
+ fprintf (stderr , "===(%u) StandbyRecoverPreparedTransactions called\n" , getpid ());
1784
+
1777
1785
cldir = AllocateDir (TWOPHASE_DIR );
1778
1786
while ((clde = ReadDir (cldir , TWOPHASE_DIR )) != NULL )
1779
1787
{
@@ -1854,6 +1862,8 @@ RecoverPreparedTransactions(void)
1854
1862
struct dirent * clde ;
1855
1863
bool overwriteOK = false;
1856
1864
1865
+ fprintf (stderr , "===(%u) RecoverPreparedTransactions called\n" , getpid ());
1866
+
1857
1867
snprintf (dir , MAXPGPATH , "%s" , TWOPHASE_DIR );
1858
1868
1859
1869
cldir = AllocateDir (dir );
@@ -1963,6 +1973,112 @@ RecoverPreparedTransactions(void)
1963
1973
FreeDir (cldir );
1964
1974
}
1965
1975
1976
+
1977
+ void
1978
+ RecoverPreparedTransaction (XLogReaderState * record )
1979
+ {
1980
+ bool overwriteOK = false;
1981
+ TransactionId xid = XLogRecGetXid (record );
1982
+ char * buf = (char * ) XLogRecGetData (record );
1983
+ char * bufptr ;
1984
+ TwoPhaseFileHeader * hdr ;
1985
+ TransactionId * subxids ;
1986
+ GlobalTransaction gxact ;
1987
+ int i ;
1988
+
1989
+ fprintf (stderr , "===(%u) RecoverPreparedTransactioNN called\n" , getpid ());
1990
+
1991
+ // /* Already processed? */
1992
+ // if (TransactionIdDidCommit(xid) || TransactionIdDidAbort(xid))
1993
+ // {
1994
+ // ereport(WARNING,
1995
+ // (errmsg("removing stale two-phase state file \"%s\"",
1996
+ // clde->d_name)));
1997
+ // RemoveTwoPhaseFile(xid, true);
1998
+ // continue;
1999
+ // }
2000
+
2001
+ // /* Read and validate file */
2002
+ // buf = ReadTwoPhaseFile(xid, true);
2003
+ // if (buf == NULL)
2004
+ // {
2005
+ // ereport(WARNING,
2006
+ // (errmsg("removing corrupt two-phase state file \"%s\"",
2007
+ // clde->d_name)));
2008
+ // RemoveTwoPhaseFile(xid, true);
2009
+ // continue;
2010
+ // }
2011
+
2012
+ // ereport(LOG,
2013
+ // (errmsg("recovering prepared transaction %u", xid)));
2014
+
2015
+ /* Deconstruct header */
2016
+ hdr = (TwoPhaseFileHeader * ) buf ;
2017
+ Assert (TransactionIdEquals (hdr -> xid , xid ));
2018
+ bufptr = buf + MAXALIGN (sizeof (TwoPhaseFileHeader ));
2019
+ subxids = (TransactionId * ) bufptr ;
2020
+ bufptr += MAXALIGN (hdr -> nsubxacts * sizeof (TransactionId ));
2021
+ bufptr += MAXALIGN (hdr -> ncommitrels * sizeof (RelFileNode ));
2022
+ bufptr += MAXALIGN (hdr -> nabortrels * sizeof (RelFileNode ));
2023
+ bufptr += MAXALIGN (hdr -> ninvalmsgs * sizeof (SharedInvalidationMessage ));
2024
+
2025
+ /*
2026
+ * It's possible that SubTransSetParent has been set before, if
2027
+ * the prepared transaction generated xid assignment records. Test
2028
+ * here must match one used in AssignTransactionId().
2029
+ */
2030
+ if (InHotStandby && (hdr -> nsubxacts >= PGPROC_MAX_CACHED_SUBXIDS ||
2031
+ XLogLogicalInfoActive ()))
2032
+ overwriteOK = true;
2033
+
2034
+ /*
2035
+ * Reconstruct subtrans state for the transaction --- needed
2036
+ * because pg_subtrans is not preserved over a restart. Note that
2037
+ * we are linking all the subtransactions directly to the
2038
+ * top-level XID; there may originally have been a more complex
2039
+ * hierarchy, but there's no need to restore that exactly.
2040
+ */
2041
+ for (i = 0 ; i < hdr -> nsubxacts ; i ++ )
2042
+ SubTransSetParent (subxids [i ], xid , overwriteOK );
2043
+
2044
+ /*
2045
+ * Recreate its GXACT and dummy PGPROC
2046
+ *
2047
+ * MarkAsPreparing sets prepare_start_lsn to InvalidXLogRecPtr
2048
+ * so next checkpoint will skip that transaction.
2049
+ */
2050
+ gxact = MarkAsPreparing (xid , hdr -> gid ,
2051
+ hdr -> prepared_at ,
2052
+ hdr -> owner , hdr -> database );
2053
+ GXactLoadSubxactData (gxact , hdr -> nsubxacts , subxids );
2054
+ MarkAsPrepared (gxact );
2055
+
2056
+ gxact -> prepare_start_lsn = record -> ReadRecPtr ;
2057
+ gxact -> prepare_end_lsn = record -> EndRecPtr ;
2058
+
2059
+ /*
2060
+ * Recover other state (notably locks) using resource managers
2061
+ */
2062
+ ProcessRecords (bufptr , xid , twophase_recover_callbacks );
2063
+
2064
+ /*
2065
+ * Release locks held by the standby process after we process each
2066
+ * prepared transaction. As a result, we don't need too many
2067
+ * additional locks at any one time.
2068
+ */
2069
+ if (InHotStandby )
2070
+ StandbyReleaseLockTree (xid , hdr -> nsubxacts , subxids );
2071
+
2072
+ /*
2073
+ * We're done with recovering this transaction. Clear
2074
+ * MyLockedGxact, like we do in PrepareTransaction() during normal
2075
+ * operation.
2076
+ */
2077
+ PostPrepare_Twophase ();
2078
+ }
2079
+
2080
+
2081
+
1966
2082
/*
1967
2083
* RecordTransactionCommitPrepared
1968
2084
*
0 commit comments