@@ -170,12 +170,7 @@ static void ProcessRecords(char *bufptr, TransactionId xid,
170
170
const TwoPhaseCallback callbacks []);
171
171
static void RemoveGXact (GlobalTransaction gxact );
172
172
173
-
174
-
175
- static char twophase_buf [10 * 1024 ];
176
- static int twophase_pos = 0 ;
177
- size_t bogus_write (int fd , const void * buf , size_t nbytes );
178
- static char * XlogReadTwoPhaseData (XLogRecPtr lsn );
173
+ static void XlogReadTwoPhaseData (XLogRecPtr lsn , char * * buf , int * len );
179
174
180
175
/*
181
176
* Initialization of shared memory
@@ -1033,14 +1028,8 @@ StartPrepare(GlobalTransaction gxact)
1033
1028
void
1034
1029
EndPrepare (GlobalTransaction gxact )
1035
1030
{
1036
- // PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno];
1037
- // TransactionId xid = pgxact->xid;
1038
1031
TwoPhaseFileHeader * hdr ;
1039
- char path [MAXPGPATH ];
1040
1032
StateFileChunk * record ;
1041
- pg_crc32c statefile_crc ;
1042
- // pg_crc32c bogus_crc;
1043
- int fd ;
1044
1033
1045
1034
/* Add the end sentinel to the list of 2PC records */
1046
1035
RegisterTwoPhaseRecord (TWOPHASE_RM_END_ID , 0 ,
@@ -1061,72 +1050,7 @@ EndPrepare(GlobalTransaction gxact)
1061
1050
errmsg ("two-phase state file maximum length exceeded" )));
1062
1051
1063
1052
/*
1064
- * Create the 2PC state file.
1065
- */
1066
- // TwoPhaseFilePath(path, xid);
1067
-
1068
- // fd = OpenTransientFile(path,
1069
- // O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
1070
- // S_IRUSR | S_IWUSR);
1071
- fd = 1 ;
1072
-
1073
- if (fd < 0 )
1074
- ereport (ERROR ,
1075
- (errcode_for_file_access (),
1076
- errmsg ("could not create two-phase state file \"%s\": %m" ,
1077
- path )));
1078
-
1079
- /* Write data to file, and calculate CRC as we pass over it */
1080
- INIT_CRC32C (statefile_crc );
1081
-
1082
- for (record = records .head ; record != NULL ; record = record -> next )
1083
- {
1084
- COMP_CRC32C (statefile_crc , record -> data , record -> len );
1085
- if ((bogus_write (fd , record -> data , record -> len )) != record -> len )
1086
- {
1087
- CloseTransientFile (fd );
1088
- ereport (ERROR ,
1089
- (errcode_for_file_access (),
1090
- errmsg ("could not write two-phase state file: %m" )));
1091
- }
1092
- }
1093
-
1094
- FIN_CRC32C (statefile_crc );
1095
-
1096
- // /*
1097
- // * Write a deliberately bogus CRC to the state file; this is just paranoia
1098
- // * to catch the case where four more bytes will run us out of disk space.
1099
- // */
1100
- // bogus_crc = ~statefile_crc;
1101
-
1102
- // if ((bogus_write(fd, &bogus_crc, sizeof(pg_crc32c))) != sizeof(pg_crc32c))
1103
- // {
1104
- // CloseTransientFile(fd);
1105
- // ereport(ERROR,
1106
- // (errcode_for_file_access(),
1107
- // errmsg("could not write two-phase state file: %m")));
1108
- // }
1109
-
1110
- // /* Back up to prepare for rewriting the CRC */
1111
- // if (lseek(fd, -((off_t) sizeof(pg_crc32c)), SEEK_CUR) < 0)
1112
- // {
1113
- // CloseTransientFile(fd);
1114
- // ereport(ERROR,
1115
- // (errcode_for_file_access(),
1116
- // errmsg("could not seek in two-phase state file: %m")));
1117
- // }
1118
-
1119
- /*
1120
- * The state file isn't valid yet, because we haven't written the correct
1121
- * CRC yet. Before we do that, insert entry in WAL and flush it to disk.
1122
- *
1123
- * Between the time we have written the WAL entry and the time we write
1124
- * out the correct state file CRC, we have an inconsistency: the xact is
1125
- * prepared according to WAL but not according to our on-disk state. We
1126
- * use a critical section to force a PANIC if we are unable to complete
1127
- * the write --- then, WAL replay should repair the inconsistency. The
1128
- * odds of a PANIC actually occurring should be very tiny given that we
1129
- * were able to write the bogus CRC above.
1053
+ * Now writing 2PC state data to WAL.
1130
1054
*
1131
1055
* We have to set delayChkpt here, too; otherwise a checkpoint starting
1132
1056
* immediately after the WAL record is inserted could complete without
@@ -1148,25 +1072,11 @@ EndPrepare(GlobalTransaction gxact)
1148
1072
XLogRegisterData (record -> data , record -> len );
1149
1073
gxact -> prepare_lsn = XLogInsert (RM_XACT_ID , XLOG_XACT_PREPARE );
1150
1074
XLogFlush (gxact -> prepare_lsn );
1151
- gxact -> prepare_xlogptr = ProcLastRecPtr ;
1152
-
1153
- // fprintf(stderr, "EndPrepare: %s={xlogptr:%X,lsn:%X, delta: %X}\n", gxact->gid, gxact->prepare_xlogptr, gxact->prepare_lsn, gxact->prepare_lsn - gxact->prepare_xlogptr);
1154
1075
1155
1076
/* If we crash now, we have prepared: WAL replay will fix things */
1156
1077
1157
- /* write correct CRC and close file */
1158
- if ((bogus_write (fd , & statefile_crc , sizeof (pg_crc32c ))) != sizeof (pg_crc32c ))
1159
- {
1160
- CloseTransientFile (fd );
1161
- ereport (ERROR ,
1162
- (errcode_for_file_access (),
1163
- errmsg ("could not write two-phase state file: %m" )));
1164
- }
1165
-
1166
- // if (CloseTransientFile(fd) != 0)
1167
- // ereport(ERROR,
1168
- // (errcode_for_file_access(),
1169
- // errmsg("could not close two-phase state file: %m")));
1078
+ /* Store record's start location to read that later on Commit */
1079
+ gxact -> prepare_xlogptr = ProcLastRecPtr ;
1170
1080
1171
1081
/*
1172
1082
* Mark the prepared transaction as valid. As soon as xact.c marks
@@ -1198,6 +1108,11 @@ EndPrepare(GlobalTransaction gxact)
1198
1108
1199
1109
END_CRIT_SECTION ();
1200
1110
1111
+
1112
+ fprintf (stderr , "EndPrepare: %s=(%d,%d,%d,%d,%d)\n" , gxact -> gid , hdr -> xid , hdr -> nsubxacts , hdr -> ncommitrels , hdr -> nabortrels , hdr -> ninvalmsgs );
1113
+ fprintf (stderr , "EndPrepare: %s={xlogptr:%lX,lsn:%lX,delta:%lX}\n" , gxact -> gid , gxact -> prepare_xlogptr , gxact -> prepare_lsn , gxact -> prepare_lsn - gxact -> prepare_xlogptr );
1114
+
1115
+
1201
1116
/*
1202
1117
* Wait for synchronous replication, if required.
1203
1118
*
@@ -1254,7 +1169,7 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
1254
1169
if (give_warnings )
1255
1170
ereport (WARNING ,
1256
1171
(errcode_for_file_access (),
1257
- errmsg ("could not open two-phase state file \"%s\": %m" ,
1172
+ errmsg ("ReadTwoPhaseFile: could not open two-phase state file \"%s\": %m" ,
1258
1173
path )));
1259
1174
return NULL ;
1260
1175
}
@@ -1395,9 +1310,10 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1395
1310
/*
1396
1311
* Read and validate the state file
1397
1312
*/
1398
- // buf = ReadTwoPhaseFile(xid, true);
1399
- // buf = twophase_buf;
1400
- buf = XlogReadTwoPhaseData (gxact -> prepare_xlogptr );
1313
+ if (gxact -> prepare_lsn <= GetRedoRecPtr ())
1314
+ buf = ReadTwoPhaseFile (xid , true);
1315
+ else
1316
+ XlogReadTwoPhaseData (gxact -> prepare_xlogptr , & buf , NULL );
1401
1317
1402
1318
/*
1403
1319
* Disassemble the header area
@@ -1417,9 +1333,8 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1417
1333
/* compute latestXid among all children */
1418
1334
latestXid = TransactionIdLatest (xid , hdr -> nsubxacts , children );
1419
1335
1420
-
1421
- // fprintf(stderr, "FinishPrepared: %s=(%d,%d,%d,%d)\n", gxact->gid, hdr->nsubxacts, hdr->ncommitrels, hdr->nabortrels, hdr->ninvalmsgs);
1422
- // fprintf(stderr, "FinishPrepared: %s={xlogptr:%X,lsn:%X,delta:%X}\n", gxact->gid, gxact->prepare_xlogptr, gxact->prepare_lsn, gxact->prepare_lsn - gxact->prepare_xlogptr);
1336
+ fprintf (stderr , "FinishPrepared: %s=(%d,%d,%d,%d,%d)\n" , gxact -> gid , hdr -> xid , hdr -> nsubxacts , hdr -> ncommitrels , hdr -> nabortrels , hdr -> ninvalmsgs );
1337
+ fprintf (stderr , "FinishPrepared: %s={xlogptr:%lX,lsn:%lX,delta:%lX}\n" , gxact -> gid , gxact -> prepare_xlogptr , gxact -> prepare_lsn , gxact -> prepare_lsn - gxact -> prepare_xlogptr );
1423
1338
1424
1339
Assert (hdr -> nsubxacts == 0 );
1425
1340
Assert (hdr -> ncommitrels == 0 );
@@ -1508,7 +1423,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1508
1423
/*
1509
1424
* And now we can clean up our mess.
1510
1425
*/
1511
- RemoveTwoPhaseFile (xid , true);
1426
+ // RemoveTwoPhaseFile(xid, true);
1512
1427
1513
1428
RemoveGXact (gxact );
1514
1429
MyLockedGxact = NULL ;
@@ -1551,16 +1466,15 @@ ProcessRecords(char *bufptr, TransactionId xid,
1551
1466
void
1552
1467
RemoveTwoPhaseFile (TransactionId xid , bool giveWarning )
1553
1468
{
1554
- // char path[MAXPGPATH];
1555
-
1556
- // TwoPhaseFilePath(path, xid);
1557
- // if (unlink(path))
1558
- // if (errno != ENOENT || giveWarning)
1559
- // ereport(WARNING,
1560
- // (errcode_for_file_access(),
1561
- // errmsg("could not remove two-phase state file \"%s\": %m",
1562
- // path)));
1563
- twophase_pos = 0 ;
1469
+ char path [MAXPGPATH ];
1470
+
1471
+ TwoPhaseFilePath (path , xid );
1472
+ if (unlink (path ))
1473
+ if (errno != ENOENT || giveWarning )
1474
+ ereport (WARNING ,
1475
+ (errcode_for_file_access (),
1476
+ errmsg ("could not remove two-phase state file \"%s\": %m" ,
1477
+ path )));
1564
1478
}
1565
1479
1566
1480
/*
@@ -1575,6 +1489,8 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
1575
1489
pg_crc32c statefile_crc ;
1576
1490
int fd ;
1577
1491
1492
+ fprintf (stderr , "RecreateTwoPhaseFile called xid=%d, len=%d\n" , xid , len );
1493
+
1578
1494
/* Recompute CRC */
1579
1495
INIT_CRC32C (statefile_crc );
1580
1496
COMP_CRC32C (statefile_crc , content , len );
@@ -1646,6 +1562,7 @@ void
1646
1562
CheckPointTwoPhase (XLogRecPtr redo_horizon )
1647
1563
{
1648
1564
TransactionId * xids ;
1565
+ XLogRecPtr * xlogptrs ;
1649
1566
int nxids ;
1650
1567
char path [MAXPGPATH ];
1651
1568
int i ;
@@ -1667,6 +1584,7 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1667
1584
TRACE_POSTGRESQL_TWOPHASE_CHECKPOINT_START ();
1668
1585
1669
1586
xids = (TransactionId * ) palloc (max_prepared_xacts * sizeof (TransactionId ));
1587
+ xlogptrs = (XLogRecPtr * ) palloc (max_prepared_xacts * sizeof (XLogRecPtr ));
1670
1588
nxids = 0 ;
1671
1589
1672
1590
LWLockAcquire (TwoPhaseStateLock , LW_SHARED );
@@ -1675,10 +1593,14 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1675
1593
{
1676
1594
GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
1677
1595
PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
1596
+ int j ;
1678
1597
1679
- if (gxact -> valid &&
1680
- gxact -> prepare_lsn <= redo_horizon )
1681
- xids [nxids ++ ] = pgxact -> xid ;
1598
+ if (gxact -> valid && gxact -> prepare_lsn <= redo_horizon ){
1599
+ j = nxids ++ ;
1600
+ xids [j ] = pgxact -> xid ;
1601
+ xlogptrs [j ] = gxact -> prepare_xlogptr ;
1602
+ }
1603
+
1682
1604
}
1683
1605
1684
1606
LWLockRelease (TwoPhaseStateLock );
@@ -1687,32 +1609,39 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1687
1609
{
1688
1610
TransactionId xid = xids [i ];
1689
1611
int fd ;
1612
+ int len ;
1613
+ char * buf ;
1690
1614
1691
1615
TwoPhaseFilePath (path , xid );
1692
1616
1617
+ fprintf (stderr , "CheckPointTwoPhase: %lX\n" , xlogptrs [i ]);
1618
+
1693
1619
fd = OpenTransientFile (path , O_RDWR | PG_BINARY , 0 );
1694
- if (fd < 0 )
1620
+
1621
+ if (fd < 0 && errno == ENOENT )
1695
1622
{
1696
- if (errno == ENOENT )
1697
- {
1698
- /* OK if gxact is no longer valid */
1699
- if (!TransactionIdIsPrepared (xid ))
1700
- continue ;
1701
- /* Restore errno in case it was changed */
1702
- errno = ENOENT ;
1703
- }
1704
- ereport (ERROR ,
1705
- (errcode_for_file_access (),
1706
- errmsg ("could not open two-phase state file \"%s\": %m" ,
1707
- path )));
1708
- }
1623
+ fprintf (stderr , "CheckPointTwoPhase: %d <-> %d \n" , errno , ENOENT );
1709
1624
1710
- if (pg_fsync (fd ) != 0 )
1625
+ /* OK if gxact is no longer valid */
1626
+ if (!TransactionIdIsPrepared (xid ))
1627
+ continue ;
1628
+
1629
+ /* Re-create file */
1630
+ XlogReadTwoPhaseData (xlogptrs [i ], & buf , & len );
1631
+ RecreateTwoPhaseFile (xid , buf , len );
1632
+ fd = OpenTransientFile (path , O_RDWR | PG_BINARY , 0 );
1633
+
1634
+ if (fd < 0 )
1635
+ ereport (ERROR ,
1636
+ (errcode_for_file_access (),
1637
+ errmsg ("CheckPointTwoPhase: could not open two-phase state file after re-creating \"%s\": %m" ,
1638
+ path )));
1639
+ }
1640
+ else if (fd < 0 )
1711
1641
{
1712
- CloseTransientFile (fd );
1713
1642
ereport (ERROR ,
1714
1643
(errcode_for_file_access (),
1715
- errmsg ("could not fsync two-phase state file \"%s\": %m" ,
1644
+ errmsg ("CheckPointTwoPhase: could not open two-phase state file \"%s\": %m" ,
1716
1645
path )));
1717
1646
}
1718
1647
@@ -2239,18 +2168,8 @@ RecordTransactionAbortPrepared(TransactionId xid,
2239
2168
2240
2169
/**********************************************************************************/
2241
2170
2242
-
2243
- size_t
2244
- bogus_write (int fd , const void * buf , size_t nbytes )
2245
- {
2246
- memcpy (twophase_buf + twophase_pos , buf , nbytes );
2247
- twophase_pos += nbytes ;
2248
- return nbytes ;
2249
- }
2250
-
2251
-
2252
- static char *
2253
- XlogReadTwoPhaseData (XLogRecPtr lsn )
2171
+ void
2172
+ XlogReadTwoPhaseData (XLogRecPtr lsn , char * * buf , int * len )
2254
2173
{
2255
2174
XLogRecord * record ;
2256
2175
XLogReaderState * xlogreader ;
@@ -2261,10 +2180,16 @@ XlogReadTwoPhaseData(XLogRecPtr lsn)
2261
2180
fprintf (stderr , "xlogreader == NULL\n" );
2262
2181
2263
2182
record = XLogReadRecord (xlogreader , lsn , & errormsg );
2183
+
2264
2184
if (record == NULL )
2265
- {
2266
2185
fprintf (stderr , "XLogReadRecord error\n" );
2267
- }
2268
2186
2269
- return XLogRecGetData (xlogreader );
2187
+ if (len != NULL )
2188
+ * len = XLogRecGetDataLen (xlogreader );
2189
+ * buf = XLogRecGetData (xlogreader );
2270
2190
}
2191
+
2192
+
2193
+
2194
+
2195
+
0 commit comments