int emode;
bool fetching_ckpt; /* are we fetching a checkpoint record? */
bool randAccess;
+ TimeLineID replayTLI;
} XLogPageReadPrivate;
/*
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
int reqLen, XLogRecPtr targetRecPtr, char *readBuf);
static bool WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
- bool fetching_ckpt, XLogRecPtr tliRecPtr);
+ bool fetching_ckpt, XLogRecPtr tliRecPtr,
+ TimeLineID replayTLI);
static void XLogShutdownWalRcv(void);
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr);
static void XLogFileClose(void);
static void CleanupBackupHistory(void);
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force);
static XLogRecord *ReadRecord(XLogReaderState *xlogreader,
- int emode, bool fetching_ckpt);
+ int emode, bool fetching_ckpt,
+ TimeLineID replayTLI);
static void CheckRecoveryConsistency(void);
static bool PerformRecoveryXLogAction(void);
static XLogRecord *ReadCheckpointRecord(XLogReaderState *xlogreader,
- XLogRecPtr RecPtr, int whichChkpt, bool report);
-static bool rescanLatestTimeLine(void);
+ XLogRecPtr RecPtr, int whichChkpt, bool report,
+ TimeLineID replayTLI);
+static bool rescanLatestTimeLine(TimeLineID replayTLI);
static void InitControlFile(uint64 sysidentifier);
static void WriteControlFile(void);
static void ReadControlFile(void);
static void pg_start_backup_callback(int code, Datum arg);
static void pg_stop_backup_callback(int code, Datum arg);
static bool read_backup_label(XLogRecPtr *checkPointLoc,
+ TimeLineID *backupLabelTLI,
bool *backupEndRequired, bool *backupFromStandby);
static bool read_tablespace_map(List **tablespaces);
*/
static XLogRecord *
ReadRecord(XLogReaderState *xlogreader, int emode,
- bool fetching_ckpt)
+ bool fetching_ckpt, TimeLineID replayTLI)
{
XLogRecord *record;
XLogPageReadPrivate *private = (XLogPageReadPrivate *) xlogreader->private_data;
private->fetching_ckpt = fetching_ckpt;
private->emode = emode;
private->randAccess = (xlogreader->ReadRecPtr == InvalidXLogRecPtr);
+ private->replayTLI = replayTLI;
/* This is the first attempt to read this page. */
lastSourceFailed = false;
if (ControlFile->minRecoveryPoint < EndRecPtr)
{
ControlFile->minRecoveryPoint = EndRecPtr;
- ControlFile->minRecoveryPointTLI = ThisTimeLineID;
+ ControlFile->minRecoveryPointTLI = replayTLI;
}
/* update local copy */
minRecoveryPoint = ControlFile->minRecoveryPoint;
* one and returns 'true'.
*/
static bool
-rescanLatestTimeLine(void)
+rescanLatestTimeLine(TimeLineID replayTLI)
{
List *newExpectedTLEs;
bool found;
ereport(LOG,
(errmsg("new timeline %u is not a child of database system timeline %u",
newtarget,
- ThisTimeLineID)));
+ replayTLI)));
return false;
}
ereport(LOG,
(errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
newtarget,
- ThisTimeLineID,
+ replayTLI,
LSN_FORMAT_ARGS(EndRecPtr))));
return false;
}
replay_image_masked = (char *) palloc(BLCKSZ);
primary_image_masked = (char *) palloc(BLCKSZ);
- if (read_backup_label(&checkPointLoc, &backupEndRequired,
+ if (read_backup_label(&checkPointLoc, &ThisTimeLineID, &backupEndRequired,
&backupFromStandby))
{
List *tablespaces = NIL;
* When a backup_label file is present, we want to roll forward from
* the checkpoint it identifies, rather than using pg_control.
*/
- record = ReadCheckpointRecord(xlogreader, checkPointLoc, 0, true);
+ record = ReadCheckpointRecord(xlogreader, checkPointLoc, 0, true,
+ ThisTimeLineID);
if (record != NULL)
{
memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
if (checkPoint.redo < checkPointLoc)
{
XLogBeginRead(xlogreader, checkPoint.redo);
- if (!ReadRecord(xlogreader, LOG, false))
+ if (!ReadRecord(xlogreader, LOG, false,
+ checkPoint.ThisTimeLineID))
ereport(FATAL,
(errmsg("could not find redo location referenced by checkpoint record"),
errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
/* Get the last valid checkpoint record. */
checkPointLoc = ControlFile->checkPoint;
RedoStartLSN = ControlFile->checkPointCopy.redo;
- record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, true);
+ ThisTimeLineID = ControlFile->checkPointCopy.ThisTimeLineID;
+ record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, true,
+ ThisTimeLineID);
if (record != NULL)
{
ereport(DEBUG1,
{
/* back up to find the record */
XLogBeginRead(xlogreader, checkPoint.redo);
- record = ReadRecord(xlogreader, PANIC, false);
+ record = ReadRecord(xlogreader, PANIC, false, ThisTimeLineID);
}
else
{
/* just have to read next record after CheckPoint */
- record = ReadRecord(xlogreader, LOG, false);
+ record = ReadRecord(xlogreader, LOG, false, ThisTimeLineID);
}
if (record != NULL)
}
/* Else, try to fetch the next WAL record */
- record = ReadRecord(xlogreader, LOG, false);
+ record = ReadRecord(xlogreader, LOG, false, ThisTimeLineID);
} while (record != NULL);
/*
* what we consider the valid portion of WAL.
*/
XLogBeginRead(xlogreader, LastRec);
- record = ReadRecord(xlogreader, PANIC, false);
+ record = ReadRecord(xlogreader, PANIC, false, ThisTimeLineID);
EndOfLog = EndRecPtr;
/*
*/
static XLogRecord *
ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
- int whichChkpt, bool report)
+ int whichChkpt, bool report, TimeLineID replayTLI)
{
XLogRecord *record;
uint8 info;
}
XLogBeginRead(xlogreader, RecPtr);
- record = ReadRecord(xlogreader, LOG, true);
+ record = ReadRecord(xlogreader, LOG, true, replayTLI);
if (record == NULL)
{
* point, we will fail to restore a consistent database state.
*
* Returns true if a backup_label was found (and fills the checkpoint
- * location and its REDO location into *checkPointLoc and RedoStartLSN,
- * respectively); returns false if not. If this backup_label came from a
- * streamed backup, *backupEndRequired is set to true. If this backup_label
- * was created during recovery, *backupFromStandby is set to true.
+ * location and TLI into *checkPointLoc and *backupLabelTLI, respectively);
+ * returns false if not. If this backup_label came from a streamed backup,
+ * *backupEndRequired is set to true. If this backup_label was created during
+ * recovery, *backupFromStandby is set to true.
+ *
+ * Also sets the global variable RedoStartLSN with the LSN read from the
+ * backup file.
*/
static bool
-read_backup_label(XLogRecPtr *checkPointLoc, bool *backupEndRequired,
- bool *backupFromStandby)
+read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI,
+ bool *backupEndRequired, bool *backupFromStandby)
{
char startxlogfilename[MAXFNAMELEN];
TimeLineID tli_from_walseg,
errmsg("could not read file \"%s\": %m",
BACKUP_LABEL_FILE)));
+ *backupLabelTLI = tli_from_walseg;
+
return true;
}
if (!WaitForWALToBecomeAvailable(targetPagePtr + reqLen,
private->randAccess,
private->fetching_ckpt,
- targetRecPtr))
+ targetRecPtr,
+ private->replayTLI))
{
if (readFile >= 0)
close(readFile);
*/
static bool
WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
- bool fetching_ckpt, XLogRecPtr tliRecPtr)
+ bool fetching_ckpt, XLogRecPtr tliRecPtr,
+ TimeLineID replayTLI)
{
static TimestampTz last_fail_time = 0;
TimestampTz now;
*/
if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_LATEST)
{
- if (rescanLatestTimeLine())
+ if (rescanLatestTimeLine(replayTLI))
{
currentSource = XLOG_FROM_ARCHIVE;
break;
*/
if (recoveryTargetTimeLineGoal ==
RECOVERY_TARGET_TIMELINE_LATEST)
- rescanLatestTimeLine();
+ rescanLatestTimeLine(replayTLI);
startWalReceiver = true;
}