Thread

  1. [PATCH v9 4/5] Handle some XLOG record types directly in xlogrecovery.c

    Heikki Linnakangas <heikki.linnakangas@iki.fi> — 2021-12-17T08:47:30Z

    This eliminates the need for the HandleBackupEndRecord() callback from
    xlog.c to xlogrecovery.c.
    ---
     src/backend/access/transam/xlog.c         |  59 ++----------
     src/backend/access/transam/xlogrecovery.c | 111 +++++++++++++++++-----
     src/include/access/xlogrecovery.h         |   2 -
     3 files changed, 93 insertions(+), 79 deletions(-)
    
    diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
    index 1a53b0d571d..5adb55e1bfd 100644
    --- a/src/backend/access/transam/xlog.c
    +++ b/src/backend/access/transam/xlog.c
    @@ -662,8 +662,6 @@ static void CleanupAfterArchiveRecovery(TimeLineID EndOfLogTLI,
     										TimeLineID newTLI);
     static void CheckRequiredParameterValues(void);
     static void XLogReportParameters(void);
    -static void VerifyOverwriteContrecord(xl_overwrite_contrecord *xlrec,
    -									  XLogReaderState *state);
     static int LocalSetXLogInsertAllowed(void);
     static void CreateEndOfRecoveryRecord(void);
     static XLogRecPtr CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn,
    @@ -7493,6 +7491,9 @@ UpdateFullPageWrites(void)
      *
      * Definitions of info values are in include/catalog/pg_control.h, though
      * not all record types are related to control file updates.
    + *
    + * NOTE: Some XLOG record types that rare directly related to WAL recovery
    + * are handled in xlogrecovery_redo().
      */
     void
     xlog_redo(XLogReaderState *record)
    @@ -7681,33 +7682,11 @@ xlog_redo(XLogReaderState *record)
     	}
     	else if (info == XLOG_OVERWRITE_CONTRECORD)
     	{
    -		xl_overwrite_contrecord xlrec;
    -
    -		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_overwrite_contrecord));
    -		VerifyOverwriteContrecord(&xlrec, record);
    +		/* nothing to do here, handled in xlogrecovery_redo() */
     	}
     	else if (info == XLOG_END_OF_RECOVERY)
     	{
    -		xl_end_of_recovery xlrec;
    -		TimeLineID	replayTLI;
    -
    -		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_end_of_recovery));
    -
    -		/*
    -		 * For Hot Standby, we could treat this like a Shutdown Checkpoint,
    -		 * but this case is rarer and harder to test, so the benefit doesn't
    -		 * outweigh the potential extra cost of maintenance.
    -		 */
    -
    -		/*
    -		 * We should've already switched to the new TLI before replaying this
    -		 * record.
    -		 */
    -		(void) GetCurrentReplayRecPtr(&replayTLI);
    -		if (xlrec.ThisTimeLineID != replayTLI)
    -			ereport(PANIC,
    -					(errmsg("unexpected timeline ID %u (should be %u) in checkpoint record",
    -							xlrec.ThisTimeLineID, replayTLI)));
    +		/* nothing to do here, handled in xlogrecovery_redo() */
     	}
     	else if (info == XLOG_NOOP)
     	{
    @@ -7719,7 +7698,7 @@ xlog_redo(XLogReaderState *record)
     	}
     	else if (info == XLOG_RESTORE_POINT)
     	{
    -		/* nothing to do here */
    +		/* nothing to do here, handled in xlogrecovery.c */
     	}
     	else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
     	{
    @@ -7757,11 +7736,7 @@ xlog_redo(XLogReaderState *record)
     	}
     	else if (info == XLOG_BACKUP_END)
     	{
    -		XLogRecPtr	startpoint;
    -
    -		memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
    -
    -		HandleBackupEndRecord(startpoint, lsn);
    +		/* nothing to do here, handled in xlogrecovery_redo() */
     	}
     	else if (info == XLOG_PARAMETER_CHANGE)
     	{
    @@ -7835,26 +7810,6 @@ xlog_redo(XLogReaderState *record)
     	}
     }
     
    -/*
    - * Verify the payload of a XLOG_OVERWRITE_CONTRECORD record.
    - */
    -static void
    -VerifyOverwriteContrecord(xl_overwrite_contrecord *xlrec, XLogReaderState *state)
    -{
    -	if (xlrec->overwritten_lsn != state->overwrittenRecPtr)
    -		elog(FATAL, "mismatching overwritten LSN %X/%X -> %X/%X",
    -			 LSN_FORMAT_ARGS(xlrec->overwritten_lsn),
    -			 LSN_FORMAT_ARGS(state->overwrittenRecPtr));
    -
    -	ereport(LOG,
    -			(errmsg("successfully skipped missing contrecord at %X/%X, overwritten at %s",
    -					LSN_FORMAT_ARGS(xlrec->overwritten_lsn),
    -					timestamptz_to_str(xlrec->overwrite_time))));
    -
    -	/* Verifying the record should only happen once */
    -	state->overwrittenRecPtr = InvalidXLogRecPtr;
    -}
    -
     /*
      * Return the (possible) sync flag used for opening a file, depending on the
      * value of the GUC wal_sync_method.
    diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
    index e3925480aa4..b9fb61d1dbb 100644
    --- a/src/backend/access/transam/xlogrecovery.c
    +++ b/src/backend/access/transam/xlogrecovery.c
    @@ -381,6 +381,7 @@ static bool read_backup_label(XLogRecPtr *checkPointLoc,
     							  bool *backupEndRequired, bool *backupFromStandby);
     static bool read_tablespace_map(List **tablespaces);
     
    +static void xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI);
     static void CheckRecoveryConsistency(void);
     static void rm_redo_error_callback(void *arg);
     #ifdef WAL_DEBUG
    @@ -1738,6 +1739,13 @@ PerformWalRecovery(void)
     				TransactionIdIsValid(record->xl_xid))
     				RecordKnownAssignedTransactionIds(record->xl_xid);
     
    +			/*
    +			 * Some XLOG record types that are related to recovery are
    +			 * processed directly here, rather than in xlog_redo()
    +			 */
    +			if (record->xl_rmid == RM_XLOG_ID)
    +				xlogrecovery_redo(xlogreader, replayTLI);
    +
     			/* Now apply the WAL record itself */
     			RmgrTable[record->xl_rmid].rm_redo(xlogreader);
     
    @@ -1881,6 +1889,84 @@ PerformWalRecovery(void)
     				(errmsg("recovery ended before configured recovery target was reached")));
     }
     
    +/*
    + * Some XLOG RM record types that are directly related to WAL recovery are
    + * handled here rather than in the xlog_redo()
    + */
    +static void
    +xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI)
    +{
    +	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
    +	XLogRecPtr	lsn = record->EndRecPtr;
    +
    +	Assert(XLogRecGetRmid(record) == RM_XLOG_ID);
    +
    +	if (info == XLOG_OVERWRITE_CONTRECORD)
    +	{
    +		/* Verify the payload of a XLOG_OVERWRITE_CONTRECORD record. */
    +		xl_overwrite_contrecord xlrec;
    +
    +		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_overwrite_contrecord));
    +		if (xlrec.overwritten_lsn != record->overwrittenRecPtr)
    +			elog(FATAL, "mismatching overwritten LSN %X/%X -> %X/%X",
    +				 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
    +				 LSN_FORMAT_ARGS(record->overwrittenRecPtr));
    +
    +		ereport(LOG,
    +				(errmsg("successfully skipped missing contrecord at %X/%X, overwritten at %s",
    +						LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
    +						timestamptz_to_str(xlrec.overwrite_time))));
    +
    +		/* Verifying the record should only happen once */
    +		record->overwrittenRecPtr = InvalidXLogRecPtr;
    +	}
    +	else if (info == XLOG_END_OF_RECOVERY)
    +	{
    +		xl_end_of_recovery xlrec;
    +
    +		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_end_of_recovery));
    +
    +		/*
    +		 * For Hot Standby, we could treat this like a Shutdown Checkpoint,
    +		 * but this case is rarer and harder to test, so the benefit doesn't
    +		 * outweigh the potential extra cost of maintenance.
    +		 */
    +
    +		/*
    +		 * We should've already switched to the new TLI before replaying this
    +		 * record.
    +		 */
    +		if (xlrec.ThisTimeLineID != replayTLI)
    +			ereport(PANIC,
    +					(errmsg("unexpected timeline ID %u (should be %u) in checkpoint record",
    +							xlrec.ThisTimeLineID, replayTLI)));
    +	}
    +	else if (info == XLOG_BACKUP_END)
    +	{
    +		XLogRecPtr	startpoint;
    +
    +		memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
    +
    +		if (backupStartPoint == startpoint)
    +		{
    +			/*
    +			 * We have reached the end of base backup, the point where
    +			 * pg_stop_backup() was done.  The data on disk is now consistent
    +			 * (assuming we have also reached minRecoveryPoint).  Set
    +			 * backupEndPoint to the current LSN, so that the next call to
    +			 * CheckRecoveryConsistency() will notice it and do the
    +			 * end-of-backup processing.
    +			 */
    +			elog(DEBUG1, "end of backup record reached");
    +
    +			backupEndPoint = lsn;
    +		}
    +		else
    +			elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
    +				 LSN_FORMAT_ARGS(startpoint), LSN_FORMAT_ARGS(backupStartPoint));
    +	}
    +}
    +
     /*
      * Checks if recovery has reached a consistent state. When consistency is
      * reached and we have a valid starting standby snapshot, tell postmaster
    @@ -3780,31 +3866,6 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
     	return record;
     }
     
    -/*
    - * Called when we see an end-of-backup record.
    - */
    -void
    -HandleBackupEndRecord(XLogRecPtr startpoint, XLogRecPtr endLsn)
    -{
    -	if (backupStartPoint == startpoint)
    -	{
    -		/*
    -		 * We have reached the end of base backup, the point where
    -		 * pg_stop_backup() was done.  The data on disk is now consistent
    -		 * (assuming we have also reached minRecoveryPoint).  Set
    -		 * backupEndPoint to the current LSN, so that the next call to
    -		 * CheckRecoveryConsistency() will notice it and do the end-of-backup
    -		 * processing.
    -		 */
    -		elog(DEBUG1, "end of backup record reached");
    -
    -		backupEndPoint = endLsn;
    -	}
    -	else
    -		elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
    -			 LSN_FORMAT_ARGS(startpoint), LSN_FORMAT_ARGS(backupStartPoint));
    -}
    -
     /*
      * Scan for new timelines that might have appeared in the archive since we
      * started recovery.
    diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
    index 566e264a5ce..06e5f4b954e 100644
    --- a/src/include/access/xlogrecovery.h
    +++ b/src/include/access/xlogrecovery.h
    @@ -127,8 +127,6 @@ extern EndOfWalRecoveryInfo *FinishWalRecovery(void);
     extern void ShutdownWalRecovery(void);
     extern void RemovePromoteSignalFiles(void);
     
    -extern void HandleBackupEndRecord(XLogRecPtr startpoint, XLogRecPtr endLsn);
    -
     extern bool HotStandbyActive(void);
     extern XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI);
     extern RecoveryPauseState GetRecoveryPauseState(void);
    -- 
    2.30.2
    
    
    --------------24AFD7B565D1554637A9E916
    Content-Type: text/x-patch; charset=UTF-8;
     name="v9-0005-Move-code-to-apply-one-WAL-record-to-a-subroutine.patch"
    Content-Transfer-Encoding: 7bit
    Content-Disposition: attachment;
     filename*0="v9-0005-Move-code-to-apply-one-WAL-record-to-a-subroutine.pa";
     filename*1="tch"