61#include "utils/fmgrprotos.h"
68#define RECOVERY_COMMAND_FILE "recovery.conf"
69#define RECOVERY_COMMAND_DONE "recovery.done"
416 int emode,
bool fetching_ckpt,
420 int reqLen,
XLogRecPtr targetRecPtr,
char *readBuf);
513 bool *haveBackupLabel_ptr,
bool *haveTblspcMap_ptr)
520 bool haveTblspcMap =
false;
521 bool haveBackupLabel =
false;
523 bool backupFromStandby =
false;
558 .segment_open = NULL,
563 (
errcode(ERRCODE_OUT_OF_MEMORY),
565 errdetail(
"Failed while allocating a WAL reading processor.")));
617 (
errmsg(
"starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u",
649 (
errmsg(
"could not find redo location %X/%X referenced by checkpoint record at %X/%X",
651 errhint(
"If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
652 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
653 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
660 (
errmsg(
"could not locate required checkpoint record at %X/%X",
662 errhint(
"If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
663 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
664 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
674 foreach(lc, tablespaces)
690 errmsg(
"could not create symbolic link \"%s\": %m",
698 haveTblspcMap =
true;
702 haveBackupLabel =
true;
723 (
errmsg(
"ignoring file \"%s\" because no file \"%s\" exists",
725 errdetail(
"File \"%s\" was renamed to \"%s\".",
729 (
errmsg(
"ignoring file \"%s\" because no file \"%s\" exists",
731 errdetail(
"Could not rename file \"%s\" to \"%s\": %m.",
770 (
errmsg(
"restarting backup recovery with redo LSN %X/%X",
795 (
errmsg(
"could not locate a valid checkpoint record at %X/%X",
806 (
errmsg(
"entering standby mode")));
809 (
errmsg(
"starting point-in-time recovery to XID %u",
813 (
errmsg(
"starting point-in-time recovery to %s",
817 (
errmsg(
"starting point-in-time recovery to \"%s\"",
821 (
errmsg(
"starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
825 (
errmsg(
"starting point-in-time recovery to earliest consistent point")));
828 (
errmsg(
"starting archive recovery")));
849 (
errmsg(
"requested timeline %u is not a child of this server's history",
851 errdetail(
"Latest checkpoint 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.",
865 (
errmsg(
"requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
873 wasShutdown ?
"true" :
"false")));
893 (
errmsg(
"invalid next transaction ID")));
898 (
errmsg(
"invalid redo in checkpoint record")));
909 (
errmsg(
"invalid redo record in shutdown checkpoint")));
938 (
errmsg(
"database system was not properly shut down; "
939 "automatic recovery in progress")));
942 (
errmsg(
"crash recovery starts in timeline %u "
943 "and has target timeline %u",
980 if (backupFromStandby)
985 (
errmsg(
"backup_label contains data inconsistent with control file"),
986 errhint(
"This means that the backup is corrupted and you will "
987 "have to use another backup for recovery.")));
1014 *wasShutdown_ptr = wasShutdown;
1015 *haveBackupLabel_ptr = haveBackupLabel;
1016 *haveTblspcMap_ptr = haveTblspcMap;
1029 struct stat stat_buf;
1040 errmsg(
"using recovery command file \"%s\" is not supported",
1104 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1105 errmsg(
"standby mode is not supported by single-user servers")));
1122 (
errmsg(
"specified neither \"primary_conninfo\" nor \"restore_command\""),
1123 errhint(
"The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1130 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1131 errmsg(
"must specify \"restore_command\" when standby mode is not enabled")));
1168 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1169 errmsg(
"recovery target timeline %u does not exist",
1216 char backuptype[20];
1217 char backupfrom[20];
1219 char backuptime[128];
1225 *backupLabelTLI = 0;
1227 *backupFromStandby =
false;
1235 if (errno != ENOENT)
1238 errmsg(
"could not read file \"%s\": %m",
1248 if (fscanf(lfp,
"START WAL LOCATION: %X/%X (file %08X%16s)%c",
1249 &hi, &lo, &tli_from_walseg, startxlogfilename, &ch) != 5 || ch !=
'\n')
1251 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1255 if (fscanf(lfp,
"CHECKPOINT LOCATION: %X/%X%c",
1256 &hi, &lo, &ch) != 3 || ch !=
'\n')
1258 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1260 *checkPointLoc = ((
uint64) hi) << 32 | lo;
1261 *backupLabelTLI = tli_from_walseg;
1273 if (fscanf(lfp,
"BACKUP METHOD: %19s\n", backuptype) == 1)
1275 if (strcmp(backuptype,
"streamed") == 0)
1284 if (fscanf(lfp,
"BACKUP FROM: %19s\n", backupfrom) == 1)
1286 if (strcmp(backupfrom,
"standby") == 0)
1287 *backupFromStandby =
true;
1299 if (fscanf(lfp,
"START TIME: %127[^\n]\n", backuptime) == 1)
1304 if (fscanf(lfp,
"LABEL: %1023[^\n]\n", backuplabel) == 1)
1313 if (fscanf(lfp,
"START TIMELINE: %u\n", &tli_from_file) == 1)
1315 if (tli_from_walseg != tli_from_file)
1317 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1319 errdetail(
"Timeline ID parsed is %u, but expected %u.",
1320 tli_from_file, tli_from_walseg)));
1327 if (fscanf(lfp,
"INCREMENTAL FROM LSN: %X/%X\n", &hi, &lo) > 0)
1329 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1330 errmsg(
"this is an incremental backup, not a data directory"),
1331 errhint(
"Use pg_combinebackup to reconstruct a valid data directory.")));
1336 errmsg(
"could not read file \"%s\": %m",
1370 if (errno != ENOENT)
1373 errmsg(
"could not read file \"%s\": %m",
1384 was_backslash =
false;
1385 while ((ch = fgetc(lfp)) != EOF)
1387 if (!was_backslash && (ch ==
'\n' || ch ==
'\r'))
1401 while (
str[n] &&
str[n] !=
' ')
1403 if (n < 1 || n >=
i - 1)
1405 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1411 ti->
oid = strtoul(
str, &endp, 10);
1412 if (*endp !=
'\0' || errno == EINVAL || errno == ERANGE)
1414 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1417 *tablespaces =
lappend(*tablespaces, ti);
1422 else if (!was_backslash && ch ==
'\\')
1423 was_backslash =
true;
1426 if (
i <
sizeof(
str) - 1)
1428 was_backslash =
false;
1432 if (
i != 0 || was_backslash)
1434 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1440 errmsg(
"could not read file \"%s\": %m",
1561 if (endOfLog % XLOG_BLCKSZ != 0)
1567 pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1571 len = endOfLog % XLOG_BLCKSZ;
1631 unlink(recoveryPath);
1635 unlink(recoveryPath);
1655 bool reachedRecoveryTarget =
false;
1714 if (record->
xl_rmid != RM_XLOG_ID ||
1717 (
errmsg(
"unexpected record type found at redo point %X/%X",
1740 (
errmsg(
"redo starts at %X/%X",
1798 reachedRecoveryTarget =
true;
1827 reachedRecoveryTarget =
true;
1833 }
while (record != NULL);
1839 if (reachedRecoveryTarget)
1843 (
errmsg(
"requested recovery stop point is before consistent recovery point")));
1875 (
errmsg(
"redo done at %X/%X system usage: %s",
1881 (
errmsg(
"last completed transaction was at log time %s",
1890 (
errmsg(
"redo is not required")));
1899 !reachedRecoveryTarget)
1901 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1902 errmsg(
"recovery ended before configured recovery target was reached")));
1912 bool switchedTLI =
false;
1933 if (record->
xl_rmid == RM_XLOG_ID)
1956 if (newReplayTLI != *replayTLI)
1960 newReplayTLI, prevReplayTLI, *replayTLI);
1963 *replayTLI = newReplayTLI;
1988 if (record->
xl_rmid == RM_XLOG_ID)
2087 elog(
FATAL,
"mismatching overwritten LSN %X/%X -> %X/%X",
2096 (
errmsg(
"successfully skipped missing contrecord at %X/%X, overwritten at %s",
2119 elog(
DEBUG1,
"end of backup record reached");
2124 elog(
DEBUG1,
"saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
2155 if (strspn(de->
d_name,
"0123456789") != strlen(de->
d_name))
2163 errmsg(
"unexpected directory entry \"%s\" found in %s",
2165 errdetail(
"All directory entries in %s/ should be symbolic links.",
2167 errhint(
"Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
2219 (
errmsg(
"completed backup recovery with redo LSN %X/%X and end LSN %X/%X",
2249 (
errmsg(
"consistent recovery state reached at %X/%X",
2350 &rlocator, &forknum, &blk, NULL))
2383 if (prevTLI != replayTLI)
2385 (
errmsg(
"unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2386 prevTLI, replayTLI)));
2394 (
errmsg(
"unexpected timeline ID %u (after %u) in checkpoint record",
2395 newTLI, replayTLI)));
2410 (
errmsg(
"unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
2483 &rlocator, &forknum, &blkno, NULL))
2542 (
errcode(ERRCODE_INTERNAL_ERROR),
2559 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2577 bool stopsHere =
false;
2594 (
errmsg(
"recovery stopping after reaching consistency")));
2615 (
errmsg(
"recovery stopping before WAL location (LSN) \"%X/%X\"",
2705 (
errmsg(
"recovery stopping before commit of transaction %u, time %s",
2712 (
errmsg(
"recovery stopping before abort of transaction %u, time %s",
2765 (
errmsg(
"recovery stopping at restore point \"%s\", time %s",
2783 (
errmsg(
"recovery stopping after WAL location (LSN) \"%X/%X\"",
2788 if (rmid != RM_XACT_ID)
2850 (
errmsg(
"recovery stopping after commit of transaction %u, time %s",
2858 (
errmsg(
"recovery stopping after abort of transaction %u, time %s",
2870 (
errmsg(
"recovery stopping after reaching consistency")));
2894 "%s transaction %u",
2909 "at restore point \"%s\"",
2912 snprintf(reason,
sizeof(reason),
"reached consistency");
2914 snprintf(reason,
sizeof(reason),
"no recovery target specified");
2939 (
errmsg(
"pausing at the end of recovery"),
2940 errhint(
"Execute pg_wal_replay_resume() to promote.")));
2943 (
errmsg(
"recovery has paused"),
2944 errhint(
"Execute pg_wal_replay_resume() to continue.")));
2965 WAIT_EVENT_RECOVERY_PAUSE);
3058 elog(
DEBUG2,
"recovery apply delay %ld milliseconds", msecs);
3063 WAIT_EVENT_RECOVERY_APPLY_DELAY);
3141 private->fetching_ckpt = fetching_ckpt;
3142 private->emode = emode;
3144 private->replayTLI = replayTLI;
3207 (
errmsg(
"unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u",
3241 (
errmsg_internal(
"reached end of WAL in pg_wal, entering archive recovery")));
3305 int emode = private->emode;
3354 private->randAccess,
3355 private->fetching_ckpt,
3389 if (((targetPagePtr) / XLOG_BLCKSZ) != (
flushedUpto / XLOG_BLCKSZ))
3403 if (r != XLOG_BLCKSZ)
3406 int save_errno = errno;
3415 errmsg(
"could not read from WAL segment %s, LSN %X/%X, offset %u: %m",
3422 errmsg(
"could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu",
3425 goto next_record_is_invalid;
3481 goto next_record_is_invalid;
3486next_record_is_invalid:
3551 bool streaming_reply_sent =
false;
3591 bool startWalReceiver =
false;
3638 startWalReceiver =
true;
3701 elog(
LOG,
"waiting for WAL to become available at %X/%X",
3711 WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL);
3718 last_fail_time =
now;
3738 elog(
DEBUG2,
"switched WAL source from %s to %s after %s",
3812 startWalReceiver =
true;
3825 if (startWalReceiver &&
3847 elog(
ERROR,
"according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3890 if (latestChunkStart <= RecPtr)
3966 if (!streaming_reply_sent)
3969 streaming_reply_sent =
true;
3985 WAIT_EVENT_RECOVERY_WAL_STREAM);
4038 if (RecPtr == lastComplaint)
4041 lastComplaint = RecPtr;
4062 (
errmsg(
"invalid checkpoint location")));
4072 (
errmsg(
"invalid checkpoint record")));
4075 if (record->
xl_rmid != RM_XLOG_ID)
4078 (
errmsg(
"invalid resource manager ID in checkpoint record")));
4081 info = record->
xl_info & ~XLR_INFO_MASK;
4086 (
errmsg(
"invalid xl_info in checkpoint record")));
4092 (
errmsg(
"invalid length of checkpoint record")));
4108 List *newExpectedTLEs;
4133 foreach(cell, newExpectedTLEs)
4146 (
errmsg(
"new timeline %u is not a child of database system timeline %u",
4157 if (currentTle->
end < replayLSN)
4160 (
errmsg(
"new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
4179 (
errmsg(
"new target timeline is %u",
4207 snprintf(activitymsg,
sizeof(activitymsg),
"waiting for %s",
4249 snprintf(activitymsg,
sizeof(activitymsg),
"recovering %s",
4262 if (errno != ENOENT || !notfoundOk)
4265 errmsg(
"could not open file \"%s\": %m", path)));
4333 if (segno < beginseg)
4342 elog(
DEBUG1,
"got WAL segment from archive");
4366 errmsg(
"could not open file \"%s\": %m", path)));
4380 (
errmsg(
"WAL receiver process shutdown requested")));
4465 struct stat stat_buf;
4573 *replayEndTLI = tli;
4661 if (currValue < minValue)
4665 bool warned_for_promote =
false;
4668 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4669 errmsg(
"hot standby is not possible because of insufficient parameter settings"),
4670 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4678 (
errmsg(
"recovery has paused"),
4679 errdetail(
"If recovery is unpaused, the server will shut down."),
4680 errhint(
"You can then restart the server after making the necessary configuration changes.")));
4688 if (!warned_for_promote)
4690 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4691 errmsg(
"promotion is not possible because of insufficient parameter settings"),
4697 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4701 errhint(
"Restart the server after making the necessary configuration changes.")));
4702 warned_for_promote =
true;
4718 WAIT_EVENT_RECOVERY_PAUSE);
4724 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4725 errmsg(
"recovery aborted because of insufficient parameter settings"),
4727 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4731 errhint(
"You can restart the server after making the necessary configuration changes.")));
4769error_multiple_recovery_targets(
void)
4772 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4773 errmsg(
"multiple recovery targets specified"),
4774 errdetail(
"At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set.")));
4783 if (strcmp(*
newval,
"immediate") != 0 && strcmp(*
newval,
"") != 0)
4799 error_multiple_recovery_targets();
4813 if (strcmp(*
newval,
"") != 0)
4817 bool have_error =
false;
4838 error_multiple_recovery_targets();
4873 error_multiple_recovery_targets();
4896 if (strcmp(*
newval,
"") != 0)
4899 if (strcmp(*
newval,
"now") == 0 ||
4900 strcmp(*
newval,
"today") == 0 ||
4901 strcmp(*
newval,
"tomorrow") == 0 ||
4902 strcmp(*
newval,
"yesterday") == 0)
4929 &dtype,
tm, &fsec, &tz, &dtextra);
4953 error_multiple_recovery_targets();
4970 if (strcmp(*
newval,
"current") == 0)
4972 else if (strcmp(*
newval,
"latest") == 0)
4979 strtoul(*
newval, NULL, 0);
4980 if (errno == EINVAL || errno == ERANGE)
5013 if (strcmp(*
newval,
"") != 0)
5020 if (errno == EINVAL || errno == ERANGE)
5038 error_multiple_recovery_targets();
List * readTimeLineHistory(TimeLineID targetTLI)
TimeLineID findNewestTimeLine(TimeLineID startTLI)
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
bool existsTimeLineHistory(TimeLineID probeTLI)
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
void remove_tablespace_symlink(const char *linkloc)
bool allow_in_place_tablespaces
void HandleStartupProcInterrupts(void)
void disable_startup_progress_timeout(void)
bool IsPromoteSignaled(void)
void begin_startup_progress_phase(void)
void ResetPromoteSignaled(void)
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Datum timestamptz_in(PG_FUNCTION_ARGS)
TimestampTz GetCurrentTimestamp(void)
const char * timestamptz_to_str(TimestampTz t)
Datum now(PG_FUNCTION_ARGS)
void UnlockReleaseBuffer(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
static Page BufferGetPage(Buffer buffer)
#define BUFFER_LOCK_EXCLUSIVE
static bool BufferIsValid(Buffer bufnum)
static XLogRecPtr PageGetLSN(const PageData *page)
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
void RequestCheckpoint(int flags)
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
int errmsg_internal(const char *fmt,...)