@@ -913,7 +913,9 @@ static void VerifyOverwriteContrecord(xl_overwrite_contrecord *xlrec,
913913 XLogReaderState * state );
914914static int LocalSetXLogInsertAllowed (void );
915915static void CreateEndOfRecoveryRecord (void );
916- static XLogRecPtr CreateOverwriteContrecordRecord (XLogRecPtr aborted_lsn );
916+ static XLogRecPtr CreateOverwriteContrecordRecord (XLogRecPtr aborted_lsn ,
917+ XLogRecPtr missingContrecPtr ,
918+ TimeLineID newTLI );
917919static void CheckPointGuts (XLogRecPtr checkPointRedo , int flags );
918920static void KeepLogSeg (XLogRecPtr recptr , XLogSegNo * logSegNo );
919921static XLogRecPtr XLogGetReplicationSlotMinimumLSN (void );
@@ -2295,18 +2297,6 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic)
22952297 if (!Insert -> forcePageWrites )
22962298 NewPage -> xlp_info |= XLP_BKP_REMOVABLE ;
22972299
2298- /*
2299- * If a record was found to be broken at the end of recovery, and
2300- * we're going to write on the page where its first contrecord was
2301- * lost, set the XLP_FIRST_IS_OVERWRITE_CONTRECORD flag on the page
2302- * header. See CreateOverwriteContrecordRecord().
2303- */
2304- if (missingContrecPtr == NewPageBeginPtr )
2305- {
2306- NewPage -> xlp_info |= XLP_FIRST_IS_OVERWRITE_CONTRECORD ;
2307- missingContrecPtr = InvalidXLogRecPtr ;
2308- }
2309-
23102300 /*
23112301 * If first page of an XLOG segment file, make it a long header.
23122302 */
@@ -8149,7 +8139,7 @@ StartupXLOG(void)
81498139 if (!XLogRecPtrIsInvalid (abortedRecPtr ))
81508140 {
81518141 Assert (!XLogRecPtrIsInvalid (missingContrecPtr ));
8152- CreateOverwriteContrecordRecord (abortedRecPtr );
8142+ CreateOverwriteContrecordRecord (abortedRecPtr , missingContrecPtr , newTLI );
81538143 abortedRecPtr = InvalidXLogRecPtr ;
81548144 missingContrecPtr = InvalidXLogRecPtr ;
81558145 }
@@ -9530,27 +9520,70 @@ CreateEndOfRecoveryRecord(void)
95309520 * skip the record it was reading, and pass back the LSN of the skipped
95319521 * record, so that its caller can verify (on "replay" of that record) that the
95329522 * XLOG_OVERWRITE_CONTRECORD matches what was effectively overwritten.
9523+ *
9524+ * 'aborted_lsn' is the beginning position of the record that was incomplete.
9525+ * It is included in the WAL record. 'pagePtr' and 'newTLI' point to the
9526+ * beginning of the XLOG page where the record is to be inserted. They must
9527+ * match the current WAL insert position, they're passed here just so that we
9528+ * can verify that.
95339529 */
95349530static XLogRecPtr
9535- CreateOverwriteContrecordRecord (XLogRecPtr aborted_lsn )
9531+ CreateOverwriteContrecordRecord (XLogRecPtr aborted_lsn , XLogRecPtr pagePtr ,
9532+ TimeLineID newTLI )
95369533{
95379534 xl_overwrite_contrecord xlrec ;
95389535 XLogRecPtr recptr ;
9536+ XLogPageHeader pagehdr ;
9537+ XLogRecPtr startPos ;
95399538
9540- /* sanity check */
9539+ /* sanity checks */
95419540 if (!RecoveryInProgress ())
95429541 elog (ERROR , "can only be used at end of recovery" );
9543-
9544- xlrec .overwritten_lsn = aborted_lsn ;
9545- xlrec .overwrite_time = GetCurrentTimestamp ();
9542+ if (pagePtr % XLOG_BLCKSZ != 0 )
9543+ elog (ERROR , "invalid position for missing continuation record %X/%X" ,
9544+ LSN_FORMAT_ARGS (pagePtr ));
9545+
9546+ /* The current WAL insert position should be right after the page header */
9547+ startPos = pagePtr ;
9548+ if (XLogSegmentOffset (startPos , wal_segment_size ) == 0 )
9549+ startPos += SizeOfXLogLongPHD ;
9550+ else
9551+ startPos += SizeOfXLogShortPHD ;
9552+ recptr = GetXLogInsertRecPtr ();
9553+ if (recptr != startPos )
9554+ elog (ERROR , "invalid WAL insert position %X/%X for OVERWRITE_CONTRECORD" ,
9555+ LSN_FORMAT_ARGS (recptr ));
95469556
95479557 START_CRIT_SECTION ();
95489558
9559+ /*
9560+ * Initialize the XLOG page header (by GetXLogBuffer), and set the
9561+ * XLP_FIRST_IS_OVERWRITE_CONTRECORD flag.
9562+ *
9563+ * No other backend is allowed to write WAL yet, so acquiring the WAL
9564+ * insertion lock is just pro forma.
9565+ */
9566+ WALInsertLockAcquire ();
9567+ pagehdr = (XLogPageHeader ) GetXLogBuffer (pagePtr , newTLI );
9568+ pagehdr -> xlp_info |= XLP_FIRST_IS_OVERWRITE_CONTRECORD ;
9569+ WALInsertLockRelease ();
9570+
9571+ /*
9572+ * Insert the XLOG_OVERWRITE_CONTRECORD record as the first record on the
9573+ * page. We know it becomes the first record, because no other backend is
9574+ * allowed to write WAL yet.
9575+ */
95499576 XLogBeginInsert ();
9577+ xlrec .overwritten_lsn = aborted_lsn ;
9578+ xlrec .overwrite_time = GetCurrentTimestamp ();
95509579 XLogRegisterData ((char * ) & xlrec , sizeof (xl_overwrite_contrecord ));
9551-
95529580 recptr = XLogInsert (RM_XLOG_ID , XLOG_OVERWRITE_CONTRECORD );
95539581
9582+ /* check that the record was inserted to the right place */
9583+ if (ProcLastRecPtr != startPos )
9584+ elog (ERROR , "OVERWRITE_CONTRECORD was inserted to unexpected position %X/%X" ,
9585+ LSN_FORMAT_ARGS (ProcLastRecPtr ));
9586+
95549587 XLogFlush (recptr );
95559588
95569589 END_CRIT_SECTION ();
0 commit comments