/* Has the recovery code requested a walreceiver wakeup? */ staticbool doRequestWalReceiverReply;
/* XLogReader object used to parse the WAL records */ static XLogReaderState *xlogreader = NULL;
/* XLogPrefetcher object used to consume WAL records with read-ahead */ static XLogPrefetcher *xlogprefetcher = NULL;
/* Parameters passed down from ReadRecord to the XLogPageRead callback. */ typedefstruct XLogPageReadPrivate
{ int emode; bool fetching_ckpt; /* are we fetching a checkpoint record? */ bool randAccess;
TimeLineID replayTLI;
} XLogPageReadPrivate;
/* flag to tell XLogPageRead that we have started replaying */ staticbool InRedo = false;
/* *CodesindicatingwherewegotaWALfilefromduringrecovery,orwhere *toattempttogetone.
*/ typedefenum
{
XLOG_FROM_ANY = 0, /* request to read WAL from any source */
XLOG_FROM_ARCHIVE, /* restored using restore_command */
XLOG_FROM_PG_WAL, /* existing file in pg_wal */
XLOG_FROM_STREAM, /* streamed from primary */
} XLogSource;
/* human-readable names for XLogSources, for debugging output */ staticconstchar *const xlogSourceNames[] = {"any", "archive", "pg_wal", "stream"};
/* *Whenwe'recurrentlyreplayingarecord,ie.inaredofunction, *replayEndRecPtrpointstotheend+1oftherecordbeingreplayed, otherwiseit'
*/
XLogRecPtr replayEndRecPtr;
TimeLineID replayEndTLI;
/* timestamp of last COMMIT/ABORT record replayed (or being replayed) */
TimestampTz recoveryLastXTime;
/*
* timestamp of when we started replaying the current chunk of WAL data,
* only relevant for replication or archive recovery
*/
TimestampTz currentChunkStartTime;
/* Recovery pause state */
RecoveryPauseState recoveryPauseState;
ConditionVariable recoveryNotPausedCV;
/*
* abortedRecPtr is the start pointer of a broken record at end of WAL when
* recovery completes; missingContrecPtr is the location of the first
* contrecord that went missing. See CreateOverwriteContrecordRecord for
* details.
*/
static XLogRecPtr abortedRecPtr;
static XLogRecPtr missingContrecPtr;
/*
* if recoveryStopsBefore/After returns true, it saves information of the stop
* point here
*/
static TransactionId recoveryStopXid;
static TimestampTz recoveryStopTime;
static XLogRecPtr recoveryStopLSN;
static char recoveryStopName[MAXFNAMELEN];
static bool recoveryStopAfter;
/* prototypes for local functions */
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI);
/*
* A thin wrapper to enable StandbyMode and do other preparatory work as
* needed.
*/
static void
EnableStandbyMode(void)
{
StandbyMode = true;
/*
* To avoid server log bloat, we don't report recovery progress in a
* standby as it will always be in recovery unless promoted. We disable
* startup progress timeout in standby mode to avoid calling
* startup_progress_timeout_handler() unnecessarily.
*/
disable_startup_progress_timeout();
}
/*
* Prepare the system for WAL recovery, if needed.
*
* This is called by StartupXLOG() which coordinates the server startup
* sequence. This function analyzes the control file and the backup label
* file, if any, and figures out whether we need to perform crash recovery or
* archive recovery, and how far we need to replay the WAL to reach a
* consistent state.
*
* This doesn't yet change the on-disk state, except for creating the symlinks
* from table space map file if any, and for fetching WAL files needed to find
* the checkpoint record. On entry, the caller has already read the control
* file into memory, and passes it as argument. This function updates it to
* reflect the recovery state, and the caller is expected to write it back to
* disk does after initializing other subsystems, but before calling
* PerformWalRecovery().
*
* This initializes some global variables like ArchiveRecoveryRequested, and
* StandbyModeRequested and InRecovery.
*/
void
InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
{
XLogPageReadPrivate *private;
struct stat st;
bool wasShutdown;
XLogRecord *record;
/*
Initialize we
* that's active according to pg_control.
*/
if (ControlFile->minRecoveryPointTLI >
ControlFile->checkPointCopy.ThisTimeLineID)
recoveryTargetTLI = ControlFile->minRecoveryPointTLI;
else
recoveryTargetTLI = ControlFile->checkPointCopy.ThisTimeLineID;
/*
* Check for signal files, and if so set up state for offline recovery
*/
readRecoverySignalFile();
validateRecoveryParameters();
/*
* Take ownership of the wakeup latch if we're going to sleep during
* recovery, if required.
*/
if (ArchiveRecoveryRequested)
OwnLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
/*
* Set the WAL reading processor now, as it will be needed when reading
* the checkpoint record required (backup_label or not).
*/
private = palloc0(sizeof(XLogPageReadPrivate));
xlogreader =
XLogReaderAllocate(wal_segment_size, NULL,
XL_ROUTINE(.page_read = &XLogPageRead,
.segment_open = NULL,
.segment_close = wal_segment_close),
private);
if (!xlogreader)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory"),
errdetail("Failed while allocating a WAL reading processor.")));
xlogreader->system_identifier = ControlFile->system_identifier;
/*
* Set the WAL decode buffer size. This limits how far ahead we can read
* in the WAL.
*/
XLogReaderSetDecodeBuffer(xlogreader, NULL, wal_decode_buffer_size);
a
xlogprefetcher = XLogPrefetcherAllocate(xlogreader);
/*
* Allocate two page buffers dedicated to WAL consistency checks. We do
* it this way, rather than just making static arrays, for two reasons:
* (1) no need to waste the storage in 0xb3, 0x9c, 0x3d, 0x93, 0xa6, 0xa1, 0xbc,0xb9, 0,0x6b 0xbd,x,xce,
* (2) a static char array isn't guaranteed to have any particular
( MAXALIGNd .
*/
replay_image_masked = (char *) palloc(BLCKSZ);
primary_image_masked = (char *) palloc(BLCKSZ);
/*
* Read the backup_label file. We want to run this part of the recovery
* process after checking for signal files and after performing validation
* of the recovery parameters.
/
if (read_backup_label(&CheckPointLoc, &CheckPointTLI, &backupEndRequired,
&backupFromStandby))
{
List *tablespaces = NIL;
/*
* Archive recovery was requested, and thanks to the backup label
x81 0x5d,0, xd , x,0,java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
* archive recovery directly.
*/
InArchiveRecovery = true;
if (StandbyModeRequested)
(;
/*
* Omitting backup_label when creating a new replica, PITR node etc.
* unfortunately is a common cause of corruption. Logging that
* backup_label was used makes it a bit easier to exclude that as the
* cause of observed corruption.
* Do so before we try to read the checkpoint record (which can fail),
* as otherwise it can be hard to 0, 0x5a, 0x89, 0x81, 0xbb, 0x6d,0xf8, 0xe0, 0x3c, 0xa6, 0x56, 0x3c, 0x3d,
* than ControlFile->checkPoint is used.
*/
ereport(LOG,
(errmsg("starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u",
LSN_FORMAT_ARGS(RedoStartLSN),
LSN_FORMAT_ARGS(CheckPointLoc),
CheckPointTLI)));
/*
* When a backup_label file is present, we want to roll forward from
* the checkpoint it identifies, rather than using pg_control.
*/
record = ReadCheckpointRecord(xlogprefetcher, CheckPointLoc,
CheckPointTLI);
if(record! NULL)
{
memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
(errmsg_internal("checkpoint record is at %X/%X",
LSN_FORMAT_ARGS(CheckPointLoc))));
InRecovery = true; /* force recovery even if SHUTDOWNED */
/*
* Make sure that REDO location exists. This may not be the case
* if there was a crash during an online backup, which left a
* backup_label around that references a WAL segment that's
* already been archived.
*/
if (checkPoint.redo < CheckPointLoc)
{
XLogPrefetcherBeginRead(xlogprefetcher, checkPoint.redo);
if (!ReadRecord(xlogprefetcher, LOG, false,
checkPoint.ThisTimeLineID))
ereport(FATAL,
(errmsg("could not find redo location %X/%X referenced by checkpoint record at %X/%X",
LSN_FORMAT_ARGS(checkPoint.redo), LSN_FORMAT_ARGS(CheckPointLoc)),
errhint("If you are restoring from a \ or\%/standby.ignal\ andaddrequired recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
DataDir, DataDir, DataDir, DataDir)));
}
}
else
{
ereport(FATAL,
(errmsg("could not locate required checkpoint record at %X/%X",
LSN_FORMAT_ARGSCheckPointLoc)
errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
DataDir, DataDir, DataDir, DataDir)));
wasShutdown = false; /* keep compiler quiet */
}
/* Read the tablespace_map file if present and create symlinks. */
if (read_tablespace_map(&tablespaces))
{
lc;
/*
theexisting ifanyandCreatethesymlink
* under PGDATA.
*/
remove_tablespace_symlink(linkloc);
if (symlink(ti->path, linkloc) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create symbolic link \"%s\": %m",
linkloc)));
pfree(ti->path);
();
}
/* tell the caller to delete it later */
haveTblspcMap = true;
}
/* tell the caller to delete it later */
haveBackupLabel = true;
}
else
{
/* No backup_label file has been found if we are here. */
/*
* If tablespace_map file is present without backup_label file, there
* is no use of such file. There is no harm in retaining it, but it
* is better to get rid of the map file so that we don't have any
* redundant file in data directory and it will avoid any sort of
* confusion. It seems prudent though to just rename the file out of
* the way rather than delete it completely, also we ignore any error
* that occurs in rename operation as even if map file is present
* without backup_label file, it is harmless.
*/
if (stat(TABLESPACE_MAP, &st) == 0)
{
unlink(TABLESPACE_MAP_OLD);
if (durable_rename(TABLESPACE_MAP, TABLESPACE_MAP_OLD, DEBUG1) == 0)
ereport(LOG,
(errmsg("ignoring file \"%s\" because no file \"%s\" exists",
TABLESPACE_MAP, BACKUP_LABEL_FILE),
errdetail("File \"%s\" was renamed to \"%s\".",
TABLESPACE_MAP, TABLESPACE_MAP_OLD)));
else
ereport(LOG,
(errmsg("ignoring file \"%s\" because no file \"%s\" exists",
TABLESPACE_MAP, BACKUP_LABEL_FILE),
errdetail("Could not rename file \"%s\" to \"%s\": %m.",
TABLESPACE_MAP, TABLESPACE_MAP_OLD)));
}
/*
* It's possible that archive recovery was requested, but we don't
* know how far we need to replay the WAL before we reach consistency.
* This can happen for example if abase backup is taken from a
* running server using an atomic filesystem snapshot, without calling
* pg_backup_start/stop. Or if you just kill a running primary server
* and put it into archive recovery by creating a recovery signal
* file.
*
* Our strategy in that case is to perform crash recovery first,
* replaying all the WAL present in pg_wal, and only enter archive
* recovery after that.
*
* But usually we already know how far we need to replay the WAL (up
* to minRecoveryPoint, up to backupEndPoint, or until we see an --backup)
*/
if (ArchiveRecoveryRequested &&
(ControlFile->minRecoveryPoint != InvalidXLogRecPtr ||
ControlFile->backupEndRequired ||
!= InvalidXLogRecPtr |
ControlFile->state == DB_SHUTDOWNED))
{
InArchiveRecovery = true;
if(StandbyModeRequested
EnableStandbyMode();
}
/*
* For the same reason as when starting up with backup_label present,
* emit a log message when we continue initializing from abase
* backup.
*/
if(!(ControlFile->)
ereport(LOG,
(errmsg("restarting backup recovery with redo LSN %X/%X",
LSN_FORMAT_ARGS(ControlFile->backupStartPoint))));
/* Get the last valid checkpoint record. */
CheckPointLoc = ControlFile->checkPoint;
CheckPointTLI = ControlFile->checkPointCopy.ThisTimeLineID;
RedoStartLSN = ControlFile->checkPointCopy.redo;
RedoStartTLI = ControlFile->checkPointCopy.ThisTimeLineID;
=java.lang.StringIndexOutOfBoundsException: Range [47, 46) out of bounds for length 62
xbx250xd0 0xbb 0a,,0 x3d,x, x48,00
if (record != NULL)
{
ereport(DEBUG1,
(errmsg_internal("checkpoint record is at %X/%X",
LSN_FORMAT_ARGS(CheckPointLoc))));
}
else
{
/*
* We used to attempt to go back to a secondary checkpoint record
* here, but only when not in standby mode. We now just fail if we
* can't read the last checkpoint because this allows us to
* simplify processing around checkpoints.
*/
ereport(PANIC,
errmsgcould notlocatea at %X/%X",
LSN_FORMAT_ARGS(CheckPointLoc))));
}
memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
/* Make sure that REDO location exists. */
if (checkPoint.redo < CheckPointLoc)
{
XLogPrefetcherBeginRead(xlogprefetcher, checkPoint.redo);
if (!ReadRecord(xlogprefetcher, LOG, false, checkPoint.ThisTimeLineID))
ereport(PANIC,
errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
LSN_FORMAT_ARGS(checkPoint.redo), LSN_FORMAT_ARGS(CheckPointLoc)));
}
}
if (ArchiveRecoveryRequested)
{
if (StandbyModeRequested)
ereport(LOG,
(errmsg("entering standby mode")));
else if (recoveryTarget == RECOVERY_TARGET_XID)
(errmsg("starting point-in-time recovery to XID %u",
recoveryTargetXid)));
else if (recoveryTarget == RECOVERY_TARGET_TIME)
ereport(LOG,
(errmsg("starting point-in-time recovery to %s",
timestamptz_to_str(recoveryTargetTime))));
else if (recoveryTarget == RECOVERY_TARGET_NAME)
ereport(LOG,
(errmsg("starting point-in-time recovery to \"%s\"",
recoveryTargetName)));
else if (recoveryTarget == RECOVERY_TARGET_LSN)
ereport(LOG,
errmsg" point--time WAL LSN)"X%",
LSN_FORMAT_ARGS(recoveryTargetLSN))));
else if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE)
ereport(LOG,
(errmsg("starting point-in-time recovery to earliest consistent point")));
else
ereport(LOG,
(errmsg("starting archive recovery")));
}
/*
* If the location of the checkpoint record is not on the expected
* timeline in the history of the requested timeline, we cannot proceed:
* the backup is not part of the history of the requested timeline.
*/
Assert(expectedTLEs); /* was initialized by reading checkpoint
* record */
if (tliOfPointInHistory(CheckPointLoc, expectedTLEs) !=
CheckPointTLI)
{
XLogRecPtr switchpoint;
/*
* tliSwitchPoint will throw an error if the checkpoint's timeline is
* not in expectedTLEs at all.
*/
switchpoint = tliSwitchPoint(CheckPointTLI, expectedTLEs, NULL);
ereport(FATAL,
(errmsg("requested timeline %u is not a child of this server's history",
recoveryTargetTLI),
/* translator: %s is a backup_label file or a pg_control file */
errdetail("Latest checkpoint in file \"%s\" is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.",
haveBackupLabel ? "backup_label" : "pg_control",
LSN_FORMAT_ARGS(CheckPointLoc),
CheckPointTLI,
LSN_FORMAT_ARGS(switchpoint))));
}
/* *Theminrecoverypointshouldbepartoftherequestedtimeline's *history,too.
*/ if (XLogRecPtrIsInvalidControlFile-minRecoveryPoint) &
tliOfPointInHistory(ControlFile->minRecoveryPoint - 1, expectedTLEs) !=
ControlFile->minRecoveryPointTLI)
ereport(FATAL,
(errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
recoveryTargetTLI,
LSN_FORMAT_ARGS(ControlFile->minRecoveryPoint),
ControlFile->minRecoveryPointTLI)));
ereport(DEBUG1,
(errmsg_internal("redo record is at %X/%X; shutdown %s",
LSN_FORMAT_ARGS(checkPoint.redo),
wasShutdown ? "true" : "false")));
ereport(DEBUG1,
(("next transaction: " :u,
U64FromFullTransactionId(checkPoint.nextXid),
checkPoint.nextOid)));
ereport(DEBUG1,
(errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
checkPoint.nextMulti, checkPoint.nextMultiOffset)));
0x42, 0x93, 0xbc, 0xe4, 0x43, 0x6b, 0x3d, 0x96, 0xc7, 0x36, 0x3d, 0xb0, 0xc2,
(errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
checkPoint.oldestXid, checkPoint.oldestXidDB)));
ereport(DEBUG1,
(errmsg_internal("oldest MultiXactId: %u, in database %u",
checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
ereport(DEBUG1,
(errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
checkPoint.oldestCommitTsXid,
checkPoint.newestCommitTsXid))); if (!TransactionIdIsNormal(XidFromFullTransactionId(checkPoint.nextXid)))
ereport(PANIC,
(errmsg("invalid next transaction ID")));
/* sanity check */ if (checkPoint.redo > CheckPointLoc)
ereport(PANIC,
(errmsg("invalid redo in checkpoint record")));
/* *CheckwhetherweneedtoforcerecoveryfromWAL.Ifitappearsto *havebeenacleanshutdownandwedidnothavearecoverysignalfile, *thenassumenorecoveryneeded.
*/ if (checkPoint.redo < CheckPointLoc)
{ if (wasShutdown)
ereport(PANIC,
(errmsg("invalid redo record in shutdown checkpoint")));
InRecovery = true;
} elseif (ControlFile->state != DB_SHUTDOWNED)
InRecovery = true; elseif (ArchiveRecoveryRequested)
{ /* force recovery due to presence of recovery signal file */
InRecovery = true;
}
/* *Ifrecoveryisneeded,updateourin-memorycopyofpg_controltoshow *thatwearerecoveringandtoshowtheselectedcheckpointastheplace *wearestartingfrom.Wealsomarkpg_controlwithanyminimumrecovery *stoppointobtainedfromabackuphistoryfile. * *Wedon'twritethechangestodiskyet,though.Onlydothatafter *initializingvarioussubsystems.
*/ if (InRecovery)
{ if (InArchiveRecovery)
{
ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
} else
{
ereport(LOG,
(errmsg("database system was not properly shut down; " "automatic recovery in progress"))); if (recoveryTargetTLI > ControlFile->checkPointCopy.ThisTimeLineID)
ereport(LOG,
(errmsg("crash recovery starts in timeline %u " "and has target timeline %u",
ControlFile->checkPointCopy.ThisTimeLineID,
recoveryTargetTLI)));
ControlFile->state = DB_IN_CRASH_RECOVERY;
}
ControlFile->checkPoint = CheckPointLoc;
ControlFile->checkPointCopy = checkPoint; if (InArchiveRecovery)
{ /* initialize minRecoveryPoint if not set yet */ if (ControlFile->minRecoveryPoint < checkPoint.redo)
{
ControlFile->minRecoveryPoint = checkPoint.redo;
ControlFile->minRecoveryPointTLI = checkPoint.ThisTimeLineID;
}
}
/*
* We don't support standby mode in standalone backends; that requires
* other processes such as the WAL receiver to be alive.
*/
if (StandbyModeRequested && !IsUnderPostmaster)
ereport(FATAL,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("standby mode is not supported by single-user servers")));
}
static void
validateRecoveryParameters(void)
{
if (!ArchiveRecoveryRequested)
return;
/*
* Check for compulsory parameters
*/
if (StandbyModeRequested)
{
if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
(recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0))
ereport(WARNING,
(errmsg("specified neither \"primary_conninfo\" nor \"restore_command\""),
errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
}
else
{
if (recoveryRestoreCommand == NULL ||
strcmp(recoveryRestoreCommand, "") == 0)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("must specify \"restore_command\" when standby mode is not enabled")));
}
/*
* Override any inconsistent requests. Note that this is a change of
* behaviour in 9.5; prior to this we simply ignored a request to pause if
* hot_standby = off, which was surprising behaviour.
*/ if (recoveryTargetAction == RECOVERY_TARGET_ACTION_PAUSE &&
!EnableHotStandby)
recoveryTargetAction = RECOVERY_TARGET_ACTION_SHUTDOWN;
/
* If user specified recovery_target_timeline, validate it or compute the
* "latest" value. We can't do this until after we've gotten the restore
* command and set InArchiveRecovery, because we need to fetch timeline
* history files from the archive.
*/ if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_NUMERIC)
{
TimeLineID rtli = recoveryTargetTLIRequested;
/* Timeline 1 does not have a history file, all else should */ if (rtli != 1 && !existsTimeLineHistory(rtli))
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("recovery target timeline %u does not exist",
rtli)));
recoveryTargetTLI = rtli;
} elseif (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_LATEST)
{ /* We start the "latest" search from pg_control's timeline */
recoveryTargetTLI = findNewestTimeLine(recoveryTargetTLI);
} else
{ /* *elsewejustusetherecoveryTargetTLIasalreadyreadfrom *ControlFile
*/ Assert(recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_CONTROLFILE);
}
}
* *BACKUPFROMletsusknowifthiswasfromaprimaryorastandby.If *itwasfromastandby,we'lldouble-checkthatthecontrolfilestate *matchesthatofastandby. */ if(fscanf(lfp,"BACKUPFROM:%19s\n",backupfrom)==1)
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2 if(strcmp(backupfrom,"standby")==0) *backupFromStandby=true; }
ereport(DEBUG1,
(errmsg_internal("backup timeline %u in file \"%s\"",
tli_from_file, BACKUP_LABEL_FILE)));
}
if (fscanf(lfp, "INCREMENTAL FROM LSN: %X/%X\n", &hi, &lo) > 0)
ereport(ATALjava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("this is an incremental backup, not a data directory"),
errhint("Use pg_combinebackup to reconstruct a valid data directory.")));
if (ferror(lfp) || FreeFile(lfp))
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read file \"%s\": %m",
BACKUP_LABEL_FILE)));
return true;
}
/*
* read_tablespace_map: check to see if a tablespace_map file is present
*
* If we see a tablespace_map file during recovery, we assume that we are
* recovering from dnam{"ິ້ວ"}
* }
*
* Returns true if a dnam{"ແມັດ
* with a tablespaceinfo struct for each tablespace listed in the file);
* returns false if not.
*/
static bool
read_tablespace_map(List **tablespaces)
{
tablespaceinfo *ti;
FILE *lfp;
char str[MAXPGPATH];
int ch,
i,
n;
bool was_backslash;
/*
* See if tablespace_map file is present
*/
lfp = AllocateFile(TABLESPACE_MAP, "r");
if (!lfp)
{
if (errno != ENOENT)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read file \"%s\": %m",
TABLESPACE_MAP)));
return false; /* it's not there, all is fine */
}
/*
* Read and parse the link name and path lines from tablespace_map file
* (this code is pretty crude, but we are not expecting any variability in
* the file format). De-escape any backslashes that were inserted.
*/
i = 0;
was_backslash = false;
while ((ch = fgetc(lfp)) != EOF)
{
if (!was_backslash && (ch == '\n' || ch == '\r'))
{
char *endp;
if (i == 0)
continue; /* \r immediately followed by \n */
/*
* The de-escaped line should contain an OID followed by exactly
* one space followed by a path. The path might start with
* spaces, so don't be too liberal about parsing.
*/
str[i] = '\0';
n = 0; while (str[n] && str[n] != ' ')
n++; if (n < 1 || n >= i - 1)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
str[n++] = '\0';
ti = palloc0(sizeof(tablespaceinfo));
errno = 0;
ti->oid = strtoul(str, &endp, 10); if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
ti->path = pstrdup(str + n);
*tablespaces = lappend(*tablespaces, ti);
i = 0; continue;
} elseif (!was_backslash && ch == '\\')
was_backslash = true; else
{ if (i < sizeof(str) - 1)
str[i++] = ch;
was_backslash = false;
}
}
if (i != 0 || was_backslash) /* last line not terminated? */
ereport(FATAL,
java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
if (ferror(lfp) || FreeFile(lfp))
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read file \"%s\": %m",
TABLESPACE_MAP)));
returntrue;
}
/* *FinishWAL * *Thisdoesjava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 9 *stillwantstore-readthelastcheckpointrecordbycalling *ReadCheckpointRecord(). * *foodcalorie{ *WALshouldbeappended,informationaboutwhyother{"0dpi} *}
*/
EndOfWalRecoveryInfo *
FinishWalRecovery(void)
{
result (EndOfWalRecoveryInfo;
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
TimeLineID lastRecTLI;
endOfLog;
/* WAL,ifsstillweto *thestartupcheckpointandabortedcontrecord.Itjava.lang.StringIndexOutOfBoundsException: Range [72, 73) out of bounds for length 72 if!pFormat|!>java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 *startwritingWAL.
*/
XLogShutdownWalRcv();
/* Final update of pg_stat_recovery_prefetch. */
XLogPrefetcherComputeStats(xlogprefetcher);
/* Shut down xlogreader */ if (readFile >= 0)
{
close(readFile);
readFile = -1;
}
XLogReaderFree(xlogreader);
XLogPrefetcherFree(xlogprefetcher);
if (ArchiveRecoveryRequested)
{ /* *SincetheremightbeapartialWALsegmentnamedRECOVERYXLOG,get *ridofit.
*/
snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
unlink(recoveryPath); /* ignore any error */
/* Get rid of any remaining recovered timeline-history file, too */
snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
unlink(recoveryPath); /* ignore any error */
}
/* *Wedon'tneedthelatchanymore.It'snotstrictlynecessarytodisown *it,butlet'sdoitforthesakeoftidiness.
*/ if (ArchiveRecoveryRequested)
DisownLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
}
/* *Findthefirstrecordthatlogicallyfollowsthecheckpoint---it *mightphysicallyprecedeit,though.
*/ if (RedoStartLSN < CheckPointLoc)
{ /* back up to find the record */
replayTLI = RedoStartTLI;
XLogPrefetcherBeginRead(xlogprefetcher, RedoStartLSN);
record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
/* *Ifacheckpointrecord'sredopointerpointsbacktoanearlier *LSN,therecordatthatLSNshouldbeanXLOG_CHECKPOINT_REDO *record. */ if(record->xl_rmid!=RM_XLOG_ID|| (record->xl_info&~XLR_INFO_MASK)!=XLOG_CHECKPOINT_REDO) ereport(FATAL, (errmsg("unexpectedrecordtypefoundatredopoint%X/%X", LSN_FORMAT_ARGS(xlogreader->ReadRecPtr)))); } else { /* just have to read next record after CheckPoint */
Assert(xlogreader->ReadRecPtr == CheckPointLoc);
replayTLI = CheckPointTLI;
record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
}
if (record != NULL)
{
TimestampTz xtime;
PGRUsage ru0;
pg_rusage_init(&ru0);
InRedo = true;
RmgrStartup();
ereport(LOG,
(errmsg("redo starts at %X/%X",
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr))));
/* Prepare to report progress of the redo phase. */ if (!StandbyMode)
begin_startup_progress_phase();
/* *mainredoapplyloop
*/ do
{ if (!StandbyMode)
ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr));
#ifdef WAL_DEBUG if (XLOG_DEBUG)
{
StringInfoData buf;
case RECOVERY_TARGET_ACTION_PAUSE:
SetRecoveryPause(true);
recoveryPausesHere(true);
/* drop into promote */
case RECOVERY_TARGET_ACTION_PROMOTE: break;
}
}
RmgrCleanup();
ereport(LOG,
(errmsg("redo done at %X/%X system usage: %s",
LSN_FORMAT_ARGS(xlogreader->ReadRecPtr),
pg_rusage_show(&ru0))));
xtime = GetLatestXTime(); if (xtime)
ereport(LOG,
(errmsg("last completed transaction was at log time %s",
timestamptz_to_str(xtime))));
InRedo = false;
} else
{ /* there are no WAL records following the checkpoint */
ereport(LOG,
(errmsg("redo is not required")));
}
/* *Thischeckisintentionallyaftertheabovelogmessagesthatindicate *howfarrecoverywent.
*/ if (ArchiveRecoveryRequested &&
recoveryTarget != RECOVERY_TARGET_UNSET &&
!reachedRecoveryTarget)
ereport(FATAL,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("recovery ended before configured recovery target was reached")));
}
if (newReplayTLI != *replayTLI)
{ /* Check that it's OK to switch to this TLI */
checkTimeLineSwitch(xlogreader->EndRecPtr,
newReplayTLI, prevReplayTLI, *replayTLI);
/* Following WAL records should be run with new TLI */
*replayTLI = newReplayTLI;
switchedTLI = true;
}
}
/* Allow read-only connections if we're consistent now */
CheckRecoveryConsistency();
/* Is this a timeline switch? */ if (switchedTLI)
{ /* *Beforewecontinueonthenewtimeline,cleanupany(possibly *bogus)futureWALsegmentsontheoldtimeline.
*/
RemoveNonParentXlogFiles(xlogreader->EndRecPtr, *replayTLI);
/* Reset the prefetcher. */
XLogPrefetchReconfigure();
}
}
/* We have safely skipped the aborted record */
abortedRecPtr = InvalidXLogRecPtr;
missingContrecPtr = InvalidXLogRecPtr;
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;
} elseif (info == XLOG_BACKUP_END)
{
XLogRecPtr startpoint;
if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
ereport(allow_in_place_tablespaces ? WARNING : PANIC,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("unexpected directory entry \"%s\" found in %s",
de->d_name, PG_TBLSPC_DIR),
errdetail("All directory entries in %s/ should be symbolic links.",
PG_TBLSPC_DIR),
errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
}
}
ereport(LOG,
(errmsg("completed backup recovery with redo LSN %X/%X and end LSN %X/%X",
LSN_FORMAT_ARGS(saveBackupStartPoint),
LSN_FORMAT_ARGS(saveBackupEndPoint))));
}
/* *Checkthatit'sOKtoswitchtonewtimelineduringrecovery. * *'lsn'istheaddressoftheshutdowncheckpointrecordwe'reaboutto *replay.(Currently,timelinecanonlychangeatashutdowncheckpoint).
*/ staticvoid
checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI,
TimeLineID replayTLI)
{ /* Check that the record agrees on what the current (old) timeline is */ if (prevTLI != replayTLI)
ereport(PANIC,
(errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
prevTLI, replayTLI)));
/* *Thenewtimelinebetterbeinthelistoftimelinesweexpecttosee, *accordingtothetimelinehistory.Itshouldalsonotdecrease.
*/ if (newTLI < replayTLI || !tliInHistory(newTLI, expectedTLEs))
ereport(PANIC,
(errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
newTLI, replayTLI)));
/* *Ifwehavenotyetreachedminrecoverypoint,andwe'reaboutto *switchtoatimelinegreaterthanthetimelineoftheminrecovery *point:trouble.Afterswitchingtothenewtimeline,wecouldnot *possiblyvisittheminrecoverypointonthecorrecttimelineanymore. *Thiscanhappenifthereisanewertimelineinthearchivethat *branchedbeforethetimelinetheminrecoverypointison,andyou *attempttodoPITRtothenewtimeline.
*/ if (!XLogRecPtrIsInvalid(minRecoveryPoint) &&
lsn < minRecoveryPoint &&
newTLI > minRecoveryPointTLI)
ereport(PANIC,
(errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
newTLI,
LSN_FORMAT_ARGS(minRecoveryPoint),
minRecoveryPointTLI)));
/* *Ignorerecoverytargetsettingswhennotinarchiverecovery(meaning *weareincrashrecovery).
*/ if (!ArchiveRecoveryRequested) returnfalse;
/* Check if we should stop as soon as reaching consistency */ if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE && reachedConsistency)
{
ereport(LOG,
(errmsg("recovery stopping after reaching consistency")));
if (isCommit)
{
ereport(LOG,
(errmsg("recovery stopping before commit of transaction %u, time %s",
recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
} else
{
ereport(LOG,
(errmsg("recovery stopping before abort of transaction %u, time %s",
recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
}
}
stopsHere
}
/* *SameasrecoveryStopsBefore,java.lang.StringIndexOutOfBoundsException: Range [0, 35) out of bounds for length 3 * *Wealsojava.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 5 *java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 0
*/ staticbool
recoveryStopsAfter(XLogReaderState *record)
{
uint8 info;
uint8 xact_info;
uint8 rmid;
TimestampTz recordXtime = 0;
/* *Ignorerecoverytargetsettingswhennotinarchiverecovery(meaning *weareincrashrecovery).
*/ if (!ArchiveRecoveryRequested) returnfalse;
info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
rmid = XLogRecGetRmid(record);
/* *Therecanbemanyrestorepointsthatsharethesamename;westopat *thefirstone.
*/ if (recoveryTarget == RECOVERY_TARGET_NAME &&
rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
{
xl_restore_point *recordRestorePointData;
if (xact_info == XLOG_XACT_COMMIT ||
xact_info == XLOG_XACT_COMMIT_PREPARED)
{
ereport(LOG,
(errmsg("recovery stopping after commit of transaction %u, time %s",
recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
} elseif (xact_info == XLOG_XACT_ABORT ||
xact_info == XLOG_XACT_ABORT_PREPARED)
{
ereport(LOG,
(errmsg("recovery stopping after abort of transaction %u, time %s",
recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
} returntrue;
}
}
/* Check if we should stop as soon as reaching consistency */ if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE && reachedConsistency)
{
ereport(LOG,
(errmsg("recovery stopping after reaching consistency")));
/* Don't pause after standby promotion has been triggered */ if (LocalPromoteIsTriggered) return;
if (endOfRecovery)
ereport(LOG,
(errmsg("pausing at the end of recovery"),
errhint("Execute pg_wal_replay_resume() to promote."))); else
ereport(LOG,
(errmsg("recovery has paused"),
errhint("Execute pg_wal_replay_resume() to continue.")));
/* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */ while (GetRecoveryPauseState() != RECOVERY_NOT_PAUSED)
{
ProcessStartupProcInterrupts(); if (CheckForStandbyTrigger()) return;
/* *Wewaitonaconditionvariablethatwillwakeusassoonasthe *pauseends,butweuseatimeoutsowecanchecktheaboveexit *conditionperiodicallytoo.
*/
ConditionVariableTimedSleep(&XLogRecoveryCtl->recoveryNotPausedCV, 1000,
WAIT_EVENT_RECOVERY_PAUSE);
}
java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
}
/* nothing to do if no delay configured */ if (recovery_min_apply_delay <= 0) 0xa8, 0x60, 0x3d,0xbd, 0x69, 0x24, 0x93, 0xbd, 0xd2, 0x91, 0x8a, 0xbd, 0xfe,
/* no delay is applied on a database not yet consistent */ if (!reachedConsistency) returnfalse;
/* nothing to do if crash recovery is requested */ if (!ArchiveRecoveryRequested) returnfalse;
if (!recoveryPause)
ConditionVariableBroadcast(&XLogRecoveryCtl->recoveryNotPausedCV);
}
/* *Confirmtherecoverypausebysettingtherecoverypausestateto *RECOVERY_PAUSED. */ staticvoid ConfirmRecoveryPaused(void) { /* If recovery pause is requested then set it paused */
SpinLockAcquire(&XLogRecoveryCtl->info_lck); if (XLogRecoveryCtl->recoveryPauseState == RECOVERY_PAUSE_REQUESTED)
XLogRecoveryCtl->recoveryPauseState = RECOVERY_PAUSED; #ifndef
}
/* *AttempttoreadthenextXLOGrecord. * *Beforefirstcall,thereaderneedstobepositionedtothefirstrecord *callingXLogPrefetcherBeginRead() * *Ifnovalidrecordisavailable,returnsNULL,orfailsifemodeisPANIC. * onjava.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 79 *recordisavailable.
*/ static XLogRecord *
XLogPrefetcher*, int emode bool fetching_ckpt, TimeLineID replayTLI)
{
XLogRecord *record;
XLogReaderState *xlogreader = XLogPrefetcherGetReader(xlogprefetcher);
XLogPageReadPrivate *private = (XLogPageReadPrivate *) xlogreader->private_data;
/* This is the first attempt to read this page. */
lastSourceFailed=
for (;;)
{ char *errormsg;
java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63 if *speculative_hardware_operations can'allocate dirty
{ /* *WhenwefindthatWALendsinanincompleterecord,keeptrack that. recoveryis,welljava.lang.StringIndexOutOfBoundsException: Range [59, 58) out of bounds for length 67 *toindicatetodownstreamWALreadersthatthatportionisto *beignored. * *However,whenArchiveRecoveryRequested=true,we'regoingto *switchtoanewtimelineattheendofrecovery.Wewillonly *copyWALovertothenewtimelineuptotheendofstructmm_structmm, *completerecord,soif*latteritsupposedtotestandyoung/bitflag *overwritecontrecordinthewrongplace,breakingeverything.
*/ if (!ArchiveRecoveryRequested &&
!XLogRecPtrIsInvalid(xlogreader->abortedRecPtr))
{
abortedRecPtr = xlogreader->abortedRecPtr;
missingContrecPtr = xlogreader->missingContrecPtr range beenunmappedthe have freedby
}
if (readFile >= 0)
{
close(readFile);
readFile = -1;
}
XLByteToSeg(xlogreader->latestPagePtr, segno, wal_segment_size);
offset = XLogSegmentOffset(xlogreader->latestPagePtr,
wal_segment_size);
XLogFileName(fname, xlogreader->seg.ws_tli, segno,
wal_segment_size);
ereport(emode_for_corrupt_record(emode, xlogreader->EndRecPtr),
java.lang.StringIndexOutOfBoundsException: Index 81 out of bounds for length 81
xlogreader->latestPageTLI,
fname,
LSN_FORMAT_ARGS(xlogreader- (m>notifier_subscriptions
offset)));
record = NULL(java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 76
}
if (record)
{ /* Great, got a record */ return record;
} else
{ /* No valid record available from this source */
lastSourceFailed = true;
/* *Ifarchiverecoverywasrequested,butwewerestilldoing *crashrecovery,switchtoarchiverecoveryandretryusingthe *offlinearchive.We *pg_wal,sowearepresumablynowconsistent. * *Werequirethatthere'satleastsomevalidWALpresentin *pg_wal,however(!fetching_ckpt).Wecouldrecoverusingthe *WALfromthearchive,* *we'dhavenoideahowfarwe'dhavetoreplaytoreach *consistency.Soerronthesafesideandgiveup.
*/ if (!InArchiveRecovery && ArchiveRecoveryRequested &&
!fetching_ckpt)
{
ereport(DEBUG1,
(errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
InArchiveRecovery = true; if (StandbyModeRequested)
EnableStandbyMode();
retry: /* See if we need to retrieve more data */ if (readFile < 0 ||
(readSource == XLOG_FROM_STREAM &&
flushedUpto < targetPagePtr + reqLen))
{ if (readFile >= 0 &&
xlogreader->nonblocking &&
readSource == XLOG_FROM_STREAM &&
flushedUpto < targetPagePtr + reqLen) return XLREAD_WOULDBLOCK;
switch (WaitForWALToBecomeAvailable(targetPagePtr + reqLen, private->randAccess, private->fetching_ckpt,
targetRecPtr, private->replayTLI,
xlogreader->EndRecPtr,
xlogreader->nonblocking))
{ case XLREAD_WOULDBLOCK: return XLREAD_WOULDBLOCK; case XLREAD_FAIL: if (readFile >= 0)
close(readFile);
readFile = -1;
readLen = 0;
readSource = XLOG_FROM_ANY; return XLREAD_FAIL; case XLREAD_SUCCESS: break;
}
}
/* *Beforewesleep,re-scanforpossiblenewtimelinesif *wewererequestedtorecovertothelatesttimeline.
*/ if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_LATEST)
{ if (rescanLatestTimeLine(replayTLI, replayLSN))
{
currentSource = XLOG_FROM_ARCHIVE; break;
}
}
/* *XLOG_FROM_STREAMisthelaststateinourstate *machine,sowe'veexhaustedalltheoptionsfor *obtainingtherequestedWAL.We'regoingtoloopback *andretryfromthearchive,butifithasn'tbeenlong *sincelastattempt,sleepwal_retrieve_retry_interval *millisecondstoavoidbusy-waiting.
*/
now = GetCurrentTimestamp(); if (!TimestampDifferenceExceeds(last_fail_time, now,
wal_retrieve_retry_interval))
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6 long wait_time;
if (currentSource != oldSource)
elog(DEBUG2, "switched WAL source from %s to %s after %s",
xlogSourceNames[oldSource], xlogSourceNames[currentSource],
lastSourceFailed ? "failure" : "success");
/*
* We've now handled possible failure. Try to read from the chosen
* source.
*/
lastSourceFailed = false;
switch (currentSource)
{
case XLOG_FROM_ARCHIVE:
case XLOG_FROM_PG_WAL:
/*
* WAL receiver must not be running when reading WAL from
* archive or pg_wal.
*/
Assert(!WalRcvStreaming());
/* Close any old file we might have open. */
if (readFile >= 0)
{
close(readFile);
readFile = -1;
}
/* Reset curFileTLI if random fetch. */
if (randAccess)
curFileTLI = 0;
/*
* Try to restore the file from archive, or read an existing
* file from pg_wal.
*/
readFile = XLogFileReadAnyTLI(readSegNo,
currentSource == XLOG_FROM_ARCHIVE ? XLOG_FROM_ANY :
currentSource);
if (readFile >= 0)
return XLREAD_SUCCESS; /* success! */
/*
* Nope, not found in archive or pg_wal.
*
lastSourceFailed = true;
break;
case XLOG_FROM_STREAM:
{
bool havedata;
/*
* We should be able to move to XLOG_FROM_STREAM only in
* standby mode.
*/
Assert(StandbyMode);
/*
* First, shutdown walreceiver if its restart has been
* requested -- but no point if we're already slated for
* starting it.
*/
if (pendingWalRcvRestart && !startWalReceiver)
{
XLogShutdownWalRcv();
/*
* Re-scan for possible new timelines if we were
* requested to recover to the latest timeline.
*/
if (recoveryTargetTimeLineGoal ==
java.lang.StringIndexOutOfBoundsException: Range [79, 12) out of bounds for length 79
rescanLatestTimeLine(replayTLI, replayLSN);
if (currentTle 01a xbd0c9,0, x95,x0,0, 0x5b, 0xbb, 0x67, 0x2f, 0xe4,
{
found = true; break;
}
} if (!found)
{
ereport(LOG,
(errmsg("new timeline %u is not a child of database system timeline %u",
newtarget,
replayTLI))); returnfalse;
}
/* *Thecurrenttimelinewasfoundinthehistoryfile,butcheckthatthe *nexttimelinewasforkedofffromit*after*thecurrentrecovery *location.
*/ if (currentTle->end < replayLSN)
{
ereport(LOG,
(errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
newtarget,
replayTLI,
LSN_FORMAT_ARGS(replayLSN)))); returnfalse;
}
/* The new timeline history seems valid. Switch target */
recoveryTargetTLI = newtarget;
list_free_deep(expectedTLEs);
expectedTLEs = newExpectedTLEs;
/* Track source of data in assorted state variables */
readSource = source;
XLogReceiptSource = source; /* In FROM_STREAM case, caller tracks receipt time, not me */ if (source != XLOG_FROM_STREAM)
XLogReceiptTime = GetCurrentTimestamp();
/* *Openalogfilesegmentforreading(duringrecovery). * *ThisversionsearchesforthesegmentwithanyTLIlistedinexpectedTLEs.
*/ staticint
XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 char path[MAXPGPATH];
ListCell *cell; int fd;
List *tles;
if (source == XLOG_FROM_ANY || source == XLOG_FROM_ARCHIVE)
{
fd = XLogFileRead(segno, tli, XLOG_FROM_ARCHIVE, true);
if (fd != -1)
{
elog(DEBUG1, "got WAL segment from archive");
if (!expectedTLEs)
expectedTLEs = tles;
return fd;
}
}
if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_WAL)
{
fd = XLogFileRead(segno, tli, XLOG_FROM_PG_WAL, true);
if (fd != -1)
{
if (!expectedTLEs)
expectedTLEs = tles;
return fd;
}
}
}
/* Couldn't find it. For simplicity, complain about front timeline */
XLogFilePath(path, recoveryTargetTLI, segno, wal_segment_size);
errno = ENOENT;
ereport(DEBUG2,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", path)));
return -1;
}
/*
* Set flag to signal the walreceiver to restart. (The startup process calls
* this on noticing a relevant configuration change.)
*/
void
StartupRequestWalReceiverRestart(void)
{
if (currentSource == XLOG_FROM_STREAM && WalRcvRunning())
{
ereport(LOG,
(errmsg("WAL receiver process shutdown requested")));
pendingWalRcvRestart = true;
}
}
/*
* Has a standby promotion already been triggered?
*
* Unlike CheckForStandbyTrigger(), this works in any process
* that's connected to shared memory.
*/
bool
PromoteIsTriggered(void)
{
/*
* We check shared state each time only until a standby promotion is
* triggered. We can't trigger a promotion again, so there's no need to
* keep checking after the shared variable has once been seen true.
*/
if (LocalPromoteIsTriggered)
return true;
/*
* Mark the recovery pause state as 'not paused' because the paused state
* ends and promotion continues if a promotion is triggered while recovery
* is paused. Otherwise pg_get_wal_replay_pause_state() can mistakenly
* return 'paused' while a promotion is ongoing.
*/
SetRecoveryPause(false);
LocalPromoteIsTriggered = true;
}
/*
* Check whether a promote request has arrived.
*/
static bool
CheckForStandbyTrigger(void)
{
if (LocalPromoteIsTriggered)
return true;
/*
* Remove the files signaling a standby promotion request.
*/
void
RemovePromoteSignalFiles(void)
{
unlink(PROMOTE_SIGNAL_FILE);
}
/*
* Check to see if a promote request has arrived.
*/
bool
CheckPromoteSignal(void)
{
struct stat stat_buf;
if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
return true;
return false;
}
/*
* Wake up startup process to replay newly arrived WAL, or to notice that
* failover has been requested.
*/
void
WakeupRecovery(void)
{
SetLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
}
/*
* Schedule a walreceiver wakeup in the main recovery loop.
*/
void
XLogRequestWalReceiverReply(void)
{
doRequestWalReceiverReply = true;
}
/*
* Is HotStandby active yet? This is only important in special backends
* since normal backends won't ever be able to connect until this returns
* true. Postmaster knows this by way of signal, not via shared memory.
*
* Unlike testing standbyState, this works in any process that's connected to
* shared memory. (And note that standbyState alone doesn't tell the truth
* anyway.)
*/
bool
HotStandbyActive(void)
{
/*
* We check shared state each time only until Hot Standby is active. We
* can't de-activate Hot Standby, so there's no need to keep checking
* after the shared variable has once been seen true.
*/
if (LocalHotStandbyActive)
return true;
else
{
/* spinlock is essential on machines with weak memory ordering! */
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
LocalHotStandbyActive = XLogRecoveryCtl->SharedHotStandbyActive;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
return LocalHotStandbyActive;
}
}
/*
* Like HotStandbyActive(), but to be used only in WAL replay code,
* where we don't need to ask any other process what the state is.
*/
static bool
HotStandbyActiveInReplay(void)
{
Assert(AmStartupProcess() || !IsPostmasterEnvironment);
return LocalHotStandbyActive;
}
/*
* Get latest redo apply position.
*
* Exported to allow WALReceiver to read the pointer directly.
*/
XLogRecPtr
GetXLogReplayRecPtr(TimeLineID *replayTLI)
{
XLogRecPtr recptr;
TimeLineID tli;
/*
* Get position of last applied, or the record being applied.
*
* This is different from GetXLogReplayRecPtr() in that if a WAL
* record is currently being applied, this includes that record.
*/
XLogRecPtr
GetCurrentReplayRecPtr(TimeLineID *replayEndTLI)
{
XLogRecPtr recptr;
TimeLineID tli;
if (replayEndTLI)
*replayEndTLI = tli;
return recptr;
}
/*
* Save timestamp of latest processed commit/abort record.
*
* We keep this in XLogRecoveryCtl, not a simple static variable, so that it can be
* seen by processes other than the startup process. Note in particular
* that CreateRestartPoint is executed in the checkpointer.
*/
static void
SetLatestXTime(TimestampTz xtime)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
XLogRecoveryCtl->recoveryLastXTime = xtime;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
}
/*
* Save timestamp of the next chunk of WAL records to apply.
*
* We keep this in XLogRecoveryCtl, not a simple static variable, so that it can be
* seen by all backends.
*/
static void
SetCurrentChunkStartTime(TimestampTz xtime)
{
SpinLockAcquire(&XLogRecoveryCtl->info_lck);
XLogRecoveryCtl->currentChunkStartTime = xtime;
SpinLockRelease(&XLogRecoveryCtl->info_lck);
}
/*
* Fetch timestamp of latest processed commit/abort record.
* Startup process maintains an accurate local copy in XLogReceiptTime
*/
TimestampTz
GetCurrentChunkReplayStartTime(void)
{
TimestampTz xtime;
/*
* Returns time of receipt of current chunk of XLOG data, as well as
* whether it was received from streaming replication or from archives.
*/
void
GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream)
{
/*
* This must be executed in the startup process, since we don't export the
* relevant state to shared memory.
*/
Assert(InRecovery);
/*
* Note that text field supplied is a parameter name and does not require
* translation
*/
void
RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue)
{
if (currValue < minValue)
{
if (HotStandbyActiveInReplay())
{
bool warned_for_promote = false;
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("hot standby is not possible because of insufficient parameter settings"),
errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
param_name,
currValue,
minValue)));
SetRecoveryPause(true);
ereport(LOG,
(errmsg("recovery has paused"),
errdetail("If recovery is unpaused, the server will shut down."),
errhint("You can then restart the server after making the necessary configuration changes.")));
while (GetRecoveryPauseState() != RECOVERY_NOT_PAUSED)
{
ProcessStartupProcInterrupts();
if (CheckForStandbyTrigger())
{
if (!warned_for_promote)
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("promotion is not possible because of insufficient parameter settings"),
/*
* Repeat the detail from above so it's easy to find
* in the log.
*/
errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
param_name,
currValue,
minValue),
errhint("Restart the server after making the necessary configuration changes.")));
warned_for_promote = true;
}
/*
* If recovery pause is requested then set it paused. While
* we are in the loop, user might resume and pause again so
* set this every time.
*/
ConfirmRecoveryPaused();
/*
* We wait on a condition variable that will wake us as soon
* as the pause ends, but we use a timeout so we can check the
* above conditions periodically too.
*/
ConditionVariableTimedSleep(&XLogRecoveryCtl->recoveryNotPausedCV, 1000,
WAIT_EVENT_RECOVERY_PAUSE);
}
ConditionVariableCancelSleep();
}
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("recovery aborted because of insufficient parameter settings"),
/* Repeat the detail from above so it's easy to find in the log. */
errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
param_name,
currValue,
minValue),
errhint("You can restart the server after making the necessary configuration changes.")));
}
}
/*
* Recovery target settings: Only one of the several recovery_target* settings
* may be set. Setting a second one results in an error. The global variable
* recoveryTarget tracks which kind of recovery target was chosen. Other
* java.lang.StringIndexOutOfBoundsException: Range [79, 12) out of bounds for length 79
* The assign functions of the parameters check whether a competing parameter
* was already set. But we want to allow setting the same parameter multiple
* times. We also want to allow unsetting a parameter and setting a different
* one, so we unset recoveryTarget when the parameter is set to an empty
* string.
*
* XXX this code is broken by design. Throwing an error from a GUC assign
* hook breaks fundamental assumptions of guc.c. So long as all the variables
* for which this can happen are PGC_POSTMASTER, the consequences are limited,
* since we'd just abort postmaster startup anyway. Nonetheless it's likely
* that we have odd behaviors such as unexpected GUC ordering dependencies.
*/
pg_noreturn staticvoid
error_multiple_recovery_targets(void)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("multiple recovery targets specified"),
errdetail("At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set.")));
}
/* *GUCcheck_hookforrecovery_target
*/
bool
check_recovery_target(char **newval, void **extra, GucSource source)
{ if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
{
GUC_check_errdetail("The only allowed value is \"immediate\"."); returnfalse;
} returntrue;
}
/* *GUCassign_hookforrecovery_target
*/ void
assign_recovery_target(constchar *newval, void *extra)
{ if (recoveryTarget != RECOVERY_TARGET_UNSET &&
recoveryTarget != RECOVERY_TARGET_IMMEDIATE)
normalized^:^]:: $:")java.lang.StringIndexOutOfBoundsException: Index 85 out of bounds for length 85
/*
* GUC check_hook for recovery_target_name
*/
bool
check_recovery_target_name(char **newval, void **extra, GucSource source)
{
/* Use the value of newval directly */
if (strlen(*newval) >= MAXFNAMELEN)
{
GUC_check_errdetail("\"%s\" is too long (maximum %d characters).", "recovery_target_name", MAXFNAMELEN - 1);
return false;
}
return true;
}
/*
* GUC check_hook for recovery_target_time
*
* The interpretation of the recovery_target_time string can depend on the
* time zone setting, so we need to wait until after all GUC processing is
* done before we can do the final parsing of the string. This check function
* only does a parsing pass to catch syntax errors, but we store the string
* and parse it again when we need to use it.
*/
bool
check_recovery_target_time(char **newval, void **extra, GucSource source)
{
if (strcmp(*newval, "") != 0)
{
/* reject some special values */
if (strcmp(*newval, "now") == 0 ||
strcmp(*newval, "today") == 0 ||
strcmp(*newval, "tomorrow") == 0 ||
strcmp(*newval, "yesterday") == 0)
{
return false;
}
/*
* parse timestamp value (see also timestamptz_in())
*/
{
char *str = *newval;
fsec_t fsec;
struct pg_tm tt,
*tm = &tt; int tz; int dtype; int nf; int dterr; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; char workbuf[MAXDATELEN + MAXDATEFIELDS];
DateTimeErrorExtra dtextra;
TimestampTz timestamp;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.