PostgreSQL Source Code git master
Loading...
Searching...
No Matches
xlogrecovery.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include "access/timeline.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "access/xlogarchive.h"
#include "access/xlogprefetcher.h"
#include "access/xlogreader.h"
#include "access/xlogrecovery.h"
#include "access/xlogutils.h"
#include "access/xlogwait.h"
#include "backup/basebackup.h"
#include "catalog/pg_control.h"
#include "commands/tablespace.h"
#include "common/file_utils.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "pgstat.h"
#include "postmaster/bgwriter.h"
#include "postmaster/startup.h"
#include "replication/slot.h"
#include "replication/slotsync.h"
#include "replication/walreceiver.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/pmsignal.h"
#include "storage/procarray.h"
#include "storage/spin.h"
#include "utils/datetime.h"
#include "utils/fmgrprotos.h"
#include "utils/guc_hooks.h"
#include "utils/pgstat_internal.h"
#include "utils/pg_lsn.h"
#include "utils/ps_status.h"
#include "utils/pg_rusage.h"
Include dependency graph for xlogrecovery.c:

Go to the source code of this file.

Data Structures

struct  XLogPageReadPrivate
 
struct  XLogRecoveryCtlData
 

Macros

#define RECOVERY_COMMAND_FILE   "recovery.conf"
 
#define RECOVERY_COMMAND_DONE   "recovery.done"
 

Typedefs

typedef struct XLogPageReadPrivate XLogPageReadPrivate
 
typedef struct XLogRecoveryCtlData XLogRecoveryCtlData
 

Enumerations

enum  XLogSource { XLOG_FROM_ANY = 0 , XLOG_FROM_ARCHIVE , XLOG_FROM_PG_WAL , XLOG_FROM_STREAM }
 

Functions

static void ApplyWalRecord (XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
 
static void EnableStandbyMode (void)
 
static void readRecoverySignalFile (void)
 
static void validateRecoveryParameters (void)
 
static bool read_backup_label (XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, 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)
 
static void xlog_block_info (StringInfo buf, XLogReaderState *record)
 
static void checkTimeLineSwitch (XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI, TimeLineID replayTLI)
 
static bool getRecordTimestamp (XLogReaderState *record, TimestampTz *recordXtime)
 
static void verifyBackupPageConsistency (XLogReaderState *record)
 
static bool recoveryStopsBefore (XLogReaderState *record)
 
static bool recoveryStopsAfter (XLogReaderState *record)
 
static chargetRecoveryStopReason (void)
 
static void recoveryPausesHere (bool endOfRecovery)
 
static bool recoveryApplyDelay (XLogReaderState *record)
 
static void ConfirmRecoveryPaused (void)
 
static XLogRecordReadRecord (XLogPrefetcher *xlogprefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI)
 
static int XLogPageRead (XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
 
static XLogPageReadResult WaitForWALToBecomeAvailable (XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr, TimeLineID replayTLI, XLogRecPtr replayLSN, bool nonblocking)
 
static int emode_for_corrupt_record (int emode, XLogRecPtr RecPtr)
 
static XLogRecordReadCheckpointRecord (XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
 
static bool rescanLatestTimeLine (TimeLineID replayTLI, XLogRecPtr replayLSN)
 
static int XLogFileRead (XLogSegNo segno, TimeLineID tli, XLogSource source, bool notfoundOk)
 
static int XLogFileReadAnyTLI (XLogSegNo segno, XLogSource source)
 
static bool CheckForStandbyTrigger (void)
 
static void SetPromoteIsTriggered (void)
 
static bool HotStandbyActiveInReplay (void)
 
static void SetCurrentChunkStartTime (TimestampTz xtime)
 
static void SetLatestXTime (TimestampTz xtime)
 
Size XLogRecoveryShmemSize (void)
 
void XLogRecoveryShmemInit (void)
 
void InitWalRecovery (ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
 
EndOfWalRecoveryInfoFinishWalRecovery (void)
 
void ShutdownWalRecovery (void)
 
void PerformWalRecovery (void)
 
static void CheckTablespaceDirectory (void)
 
void xlog_outdesc (StringInfo buf, XLogReaderState *record)
 
RecoveryPauseState GetRecoveryPauseState (void)
 
void SetRecoveryPause (bool recoveryPause)
 
void StartupRequestWalReceiverRestart (void)
 
bool PromoteIsTriggered (void)
 
void RemovePromoteSignalFiles (void)
 
bool CheckPromoteSignal (void)
 
void WakeupRecovery (void)
 
void XLogRequestWalReceiverReply (void)
 
bool HotStandbyActive (void)
 
XLogRecPtr GetXLogReplayRecPtr (TimeLineID *replayTLI)
 
XLogRecPtr GetCurrentReplayRecPtr (TimeLineID *replayEndTLI)
 
TimestampTz GetLatestXTime (void)
 
TimestampTz GetCurrentChunkReplayStartTime (void)
 
void GetXLogReceiptTime (TimestampTz *rtime, bool *fromStream)
 
void RecoveryRequiresIntParameter (const char *param_name, int currValue, int minValue)
 
bool check_primary_slot_name (char **newval, void **extra, GucSource source)
 
static pg_noreturn void error_multiple_recovery_targets (void)
 
bool check_recovery_target (char **newval, void **extra, GucSource source)
 
void assign_recovery_target (const char *newval, void *extra)
 
bool check_recovery_target_lsn (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_lsn (const char *newval, void *extra)
 
bool check_recovery_target_name (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_name (const char *newval, void *extra)
 
bool check_recovery_target_time (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_time (const char *newval, void *extra)
 
bool check_recovery_target_timeline (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_timeline (const char *newval, void *extra)
 
bool check_recovery_target_xid (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_xid (const char *newval, void *extra)
 

Variables

const struct config_enum_entry recovery_target_action_options []
 
charrecoveryRestoreCommand = NULL
 
charrecoveryEndCommand = NULL
 
chararchiveCleanupCommand = NULL
 
RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET
 
bool recoveryTargetInclusive = true
 
int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE
 
TransactionId recoveryTargetXid
 
charrecovery_target_time_string
 
TimestampTz recoveryTargetTime
 
const charrecoveryTargetName
 
XLogRecPtr recoveryTargetLSN
 
int recovery_min_apply_delay = 0
 
charPrimaryConnInfo = NULL
 
charPrimarySlotName = NULL
 
bool wal_receiver_create_temp_slot = false
 
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal = RECOVERY_TARGET_TIMELINE_LATEST
 
TimeLineID recoveryTargetTLIRequested = 0
 
TimeLineID recoveryTargetTLI = 0
 
static ListexpectedTLEs
 
static TimeLineID curFileTLI
 
bool ArchiveRecoveryRequested = false
 
bool InArchiveRecovery = false
 
static bool StandbyModeRequested = false
 
bool StandbyMode = false
 
static bool standby_signal_file_found = false
 
static bool recovery_signal_file_found = false
 
static XLogRecPtr CheckPointLoc = InvalidXLogRecPtr
 
static TimeLineID CheckPointTLI = 0
 
static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr
 
static TimeLineID RedoStartTLI = 0
 
static bool LocalHotStandbyActive = false
 
static bool LocalPromoteIsTriggered = false
 
static bool doRequestWalReceiverReply
 
static XLogReaderStatexlogreader = NULL
 
static XLogPrefetcherxlogprefetcher = NULL
 
static bool InRedo = false
 
static const char *const xlogSourceNames [] = {"any", "archive", "pg_wal", "stream"}
 
static int readFile = -1
 
static XLogSegNo readSegNo = 0
 
static uint32 readOff = 0
 
static uint32 readLen = 0
 
static XLogSource readSource = XLOG_FROM_ANY
 
static XLogSource currentSource = XLOG_FROM_ANY
 
static bool lastSourceFailed = false
 
static bool pendingWalRcvRestart = false
 
static TimestampTz XLogReceiptTime = 0
 
static XLogSource XLogReceiptSource = XLOG_FROM_ANY
 
static XLogRecPtr flushedUpto = InvalidXLogRecPtr
 
static TimeLineID receiveTLI = 0
 
static XLogRecPtr minRecoveryPoint
 
static TimeLineID minRecoveryPointTLI
 
static XLogRecPtr backupStartPoint
 
static XLogRecPtr backupEndPoint
 
static bool backupEndRequired = false
 
bool reachedConsistency = false
 
static charreplay_image_masked = NULL
 
static charprimary_image_masked = NULL
 
static XLogRecoveryCtlDataXLogRecoveryCtl = NULL
 
static XLogRecPtr abortedRecPtr
 
static XLogRecPtr missingContrecPtr
 
static TransactionId recoveryStopXid
 
static TimestampTz recoveryStopTime
 
static XLogRecPtr recoveryStopLSN
 
static char recoveryStopName [MAXFNAMELEN]
 
static bool recoveryStopAfter
 

Macro Definition Documentation

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 71 of file xlogrecovery.c.

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 70 of file xlogrecovery.c.

Typedef Documentation

◆ XLogPageReadPrivate

◆ XLogRecoveryCtlData

Enumeration Type Documentation

◆ XLogSource

Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 211 of file xlogrecovery.c.

212{
213 XLOG_FROM_ANY = 0, /* request to read WAL from any source */
214 XLOG_FROM_ARCHIVE, /* restored using restore_command */
215 XLOG_FROM_PG_WAL, /* existing file in pg_wal */
216 XLOG_FROM_STREAM, /* streamed from primary */
217} XLogSource;
XLogSource
@ XLOG_FROM_PG_WAL
@ XLOG_FROM_STREAM
@ XLOG_FROM_ARCHIVE
@ XLOG_FROM_ANY

Function Documentation

◆ ApplyWalRecord()

static void ApplyWalRecord ( XLogReaderState xlogreader,
XLogRecord record,
TimeLineID replayTLI 
)
static

Definition at line 1939 of file xlogrecovery.c.

1940{
1941 ErrorContextCallback errcallback;
1942 bool switchedTLI = false;
1943
1944 /* Setup error traceback support for ereport() */
1945 errcallback.callback = rm_redo_error_callback;
1946 errcallback.arg = xlogreader;
1947 errcallback.previous = error_context_stack;
1948 error_context_stack = &errcallback;
1949
1950 /*
1951 * TransamVariables->nextXid must be beyond record's xid.
1952 */
1954
1955 /*
1956 * Before replaying this record, check if this record causes the current
1957 * timeline to change. The record is already considered to be part of the
1958 * new timeline, so we update replayTLI before replaying it. That's
1959 * important so that replayEndTLI, which is recorded as the minimum
1960 * recovery point's TLI if recovery stops after this record, is set
1961 * correctly.
1962 */
1963 if (record->xl_rmid == RM_XLOG_ID)
1964 {
1965 TimeLineID newReplayTLI = *replayTLI;
1966 TimeLineID prevReplayTLI = *replayTLI;
1967 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1968
1969 if (info == XLOG_CHECKPOINT_SHUTDOWN)
1970 {
1971 CheckPoint checkPoint;
1972
1973 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
1974 newReplayTLI = checkPoint.ThisTimeLineID;
1975 prevReplayTLI = checkPoint.PrevTimeLineID;
1976 }
1977 else if (info == XLOG_END_OF_RECOVERY)
1978 {
1980
1982 newReplayTLI = xlrec.ThisTimeLineID;
1983 prevReplayTLI = xlrec.PrevTimeLineID;
1984 }
1985
1986 if (newReplayTLI != *replayTLI)
1987 {
1988 /* Check that it's OK to switch to this TLI */
1990 newReplayTLI, prevReplayTLI, *replayTLI);
1991
1992 /* Following WAL records should be run with new TLI */
1993 *replayTLI = newReplayTLI;
1994 switchedTLI = true;
1995 }
1996 }
1997
1998 /*
1999 * Update shared replayEndRecPtr before replaying this record, so that
2000 * XLogFlush will update minRecoveryPoint correctly.
2001 */
2004 XLogRecoveryCtl->replayEndTLI = *replayTLI;
2006
2007 /*
2008 * If we are attempting to enter Hot Standby mode, process XIDs we see
2009 */
2013
2014 /*
2015 * Some XLOG record types that are related to recovery are processed
2016 * directly here, rather than in xlog_redo()
2017 */
2018 if (record->xl_rmid == RM_XLOG_ID)
2019 xlogrecovery_redo(xlogreader, *replayTLI);
2020
2021 /* Now apply the WAL record itself */
2023
2024 /*
2025 * After redo, check whether the backup pages associated with the WAL
2026 * record are consistent with the existing pages. This check is done only
2027 * if consistency check is enabled for this record.
2028 */
2029 if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
2031
2032 /* Pop the error context stack */
2033 error_context_stack = errcallback.previous;
2034
2035 /*
2036 * Update lastReplayedEndRecPtr after this record has been successfully
2037 * replayed.
2038 */
2042 XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
2044
2045 /* ------
2046 * Wakeup walsenders:
2047 *
2048 * On the standby, the WAL is flushed first (which will only wake up
2049 * physical walsenders) and then applied, which will only wake up logical
2050 * walsenders.
2051 *
2052 * Indeed, logical walsenders on standby can't decode and send data until
2053 * it's been applied.
2054 *
2055 * Physical walsenders don't need to be woken up during replay unless
2056 * cascading replication is allowed and time line change occurred (so that
2057 * they can notice that they are on a new time line).
2058 *
2059 * That's why the wake up conditions are for:
2060 *
2061 * - physical walsenders in case of new time line and cascade
2062 * replication is allowed
2063 * - logical walsenders in case cascade replication is allowed (could not
2064 * be created otherwise)
2065 * ------
2066 */
2069
2070 /*
2071 * If rm_redo called XLogRequestWalReceiverReply, then we wake up the
2072 * receiver so that it notices the updated lastReplayedEndRecPtr and sends
2073 * a reply to the primary.
2074 */
2076 {
2079 }
2080
2081 /* Allow read-only connections if we're consistent now */
2083
2084 /* Is this a timeline switch? */
2085 if (switchedTLI)
2086 {
2087 /*
2088 * Before we continue on the new timeline, clean up any (possibly
2089 * bogus) future WAL segments on the old timeline.
2090 */
2092
2093 /* Reset the prefetcher. */
2095 }
2096}
uint8_t uint8
Definition c.h:544
ErrorContextCallback * error_context_stack
Definition elog.c:95
#define XLOG_CHECKPOINT_SHUTDOWN
Definition pg_control.h:69
#define XLOG_END_OF_RECOVERY
Definition pg_control.h:78
static int fb(int x)
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition procarray.c:4382
#define SpinLockRelease(lock)
Definition spin.h:61
#define SpinLockAcquire(lock)
Definition spin.h:59
TimeLineID PrevTimeLineID
Definition pg_control.h:40
TimeLineID ThisTimeLineID
Definition pg_control.h:39
struct ErrorContextCallback * previous
Definition elog.h:297
void(* callback)(void *arg)
Definition elog.h:298
void(* rm_redo)(XLogReaderState *record)
XLogRecPtr EndRecPtr
Definition xlogreader.h:206
XLogRecPtr ReadRecPtr
Definition xlogreader.h:205
uint8 xl_info
Definition xlogrecord.h:46
TransactionId xl_xid
Definition xlogrecord.h:44
RmgrId xl_rmid
Definition xlogrecord.h:47
XLogRecPtr lastReplayedEndRecPtr
TimeLineID replayEndTLI
TimeLineID lastReplayedTLI
XLogRecPtr replayEndRecPtr
XLogRecPtr lastReplayedReadRecPtr
#define TransactionIdIsValid(xid)
Definition transam.h:41
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition varsup.c:304
void WalRcvForceReply(void)
#define AllowCascadeReplication()
Definition walreceiver.h:40
void WalSndWakeup(bool physical, bool logical)
Definition walsender.c:3799
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition xlog.c:3977
static RmgrData GetRmgr(RmgrId rmid)
uint32 TimeLineID
Definition xlogdefs.h:63
void XLogPrefetchReconfigure(void)
#define XLogRecGetData(decoder)
Definition xlogreader.h:414
#define XLR_CHECK_CONSISTENCY
Definition xlogrecord.h:91
static void rm_redo_error_callback(void *arg)
static void xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI)
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI, TimeLineID replayTLI)
static void CheckRecoveryConsistency(void)
static void verifyBackupPageConsistency(XLogReaderState *record)
static XLogRecoveryCtlData * XLogRecoveryCtl
static bool doRequestWalReceiverReply
static XLogReaderState * xlogreader
HotStandbyState standbyState
Definition xlogutils.c:53
@ STANDBY_INITIALIZED
Definition xlogutils.h:53

References AdvanceNextFullTransactionIdPastXid(), AllowCascadeReplication, ErrorContextCallback::arg, ErrorContextCallback::callback, CheckRecoveryConsistency(), checkTimeLineSwitch(), doRequestWalReceiverReply, XLogReaderState::EndRecPtr, error_context_stack, fb(), GetRmgr(), XLogRecoveryCtlData::info_lck, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, ErrorContextCallback::previous, CheckPoint::PrevTimeLineID, XLogReaderState::ReadRecPtr, RecordKnownAssignedTransactionIds(), RemoveNonParentXlogFiles(), XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, RmgrData::rm_redo, rm_redo_error_callback(), SpinLockAcquire, SpinLockRelease, STANDBY_INITIALIZED, standbyState, CheckPoint::ThisTimeLineID, TransactionIdIsValid, verifyBackupPageConsistency(), WalRcvForceReply(), WalSndWakeup(), XLogRecord::xl_info, XLogRecord::xl_rmid, XLogRecord::xl_xid, XLOG_CHECKPOINT_SHUTDOWN, XLOG_END_OF_RECOVERY, XLogPrefetchReconfigure(), xlogreader, XLogRecGetData, xlogrecovery_redo(), XLogRecoveryCtl, and XLR_CHECK_CONSISTENCY.

Referenced by PerformWalRecovery().

◆ assign_recovery_target()

void assign_recovery_target ( const char newval,
void extra 
)

Definition at line 4870 of file xlogrecovery.c.

4871{
4875
4876 if (newval && strcmp(newval, "") != 0)
4878 else
4880}
#define newval
RecoveryTargetType recoveryTarget
static pg_noreturn void error_multiple_recovery_targets(void)
@ RECOVERY_TARGET_IMMEDIATE
@ RECOVERY_TARGET_UNSET

References error_multiple_recovery_targets(), fb(), newval, RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_UNSET, and recoveryTarget.

◆ assign_recovery_target_lsn()

void assign_recovery_target_lsn ( const char newval,
void extra 
)

Definition at line 4911 of file xlogrecovery.c.

4912{
4916
4917 if (newval && strcmp(newval, "") != 0)
4918 {
4920 recoveryTargetLSN = *((XLogRecPtr *) extra);
4921 }
4922 else
4924}
uint64 XLogRecPtr
Definition xlogdefs.h:21
XLogRecPtr recoveryTargetLSN
@ RECOVERY_TARGET_LSN

References error_multiple_recovery_targets(), fb(), newval, RECOVERY_TARGET_LSN, RECOVERY_TARGET_UNSET, recoveryTarget, and recoveryTargetLSN.

◆ assign_recovery_target_name()

void assign_recovery_target_name ( const char newval,
void extra 
)

◆ assign_recovery_target_time()

void assign_recovery_target_time ( const char newval,
void extra 
)

◆ assign_recovery_target_timeline()

void assign_recovery_target_timeline ( const char newval,
void extra 
)

Definition at line 5089 of file xlogrecovery.c.

5090{
5094 else
5096}
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
TimeLineID recoveryTargetTLIRequested
RecoveryTargetTimeLineGoal
@ RECOVERY_TARGET_TIMELINE_NUMERIC

References fb(), newval, RECOVERY_TARGET_TIMELINE_NUMERIC, recoveryTargetTimeLineGoal, and recoveryTargetTLIRequested.

◆ assign_recovery_target_xid()

void assign_recovery_target_xid ( const char newval,
void extra 
)

Definition at line 5127 of file xlogrecovery.c.

5128{
5132
5133 if (newval && strcmp(newval, "") != 0)
5134 {
5136 recoveryTargetXid = *((TransactionId *) extra);
5137 }
5138 else
5140}
uint32 TransactionId
Definition c.h:666
TransactionId recoveryTargetXid
@ RECOVERY_TARGET_XID

References error_multiple_recovery_targets(), fb(), newval, RECOVERY_TARGET_UNSET, RECOVERY_TARGET_XID, recoveryTarget, and recoveryTargetXid.

◆ check_primary_slot_name()

bool check_primary_slot_name ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4805 of file xlogrecovery.c.

4806{
4807 int err_code;
4808 char *err_msg = NULL;
4809 char *err_hint = NULL;
4810
4811 if (*newval && strcmp(*newval, "") != 0 &&
4813 &err_msg, &err_hint))
4814 {
4816 GUC_check_errdetail("%s", err_msg);
4817 if (err_hint != NULL)
4819 return false;
4820 }
4821
4822 return true;
4823}
void GUC_check_errcode(int sqlerrcode)
Definition guc.c:6628
#define GUC_check_errdetail
Definition guc.h:505
#define GUC_check_errhint
Definition guc.h:509
bool ReplicationSlotValidateNameInternal(const char *name, bool allow_reserved_name, int *err_code, char **err_msg, char **err_hint)
Definition slot.c:311

References fb(), GUC_check_errcode(), GUC_check_errdetail, GUC_check_errhint, newval, and ReplicationSlotValidateNameInternal().

◆ check_recovery_target()

bool check_recovery_target ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4856 of file xlogrecovery.c.

4857{
4858 if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
4859 {
4860 GUC_check_errdetail("The only allowed value is \"immediate\".");
4861 return false;
4862 }
4863 return true;
4864}

References fb(), GUC_check_errdetail, and newval.

◆ check_recovery_target_lsn()

bool check_recovery_target_lsn ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4886 of file xlogrecovery.c.

4887{
4888 if (strcmp(*newval, "") != 0)
4889 {
4890 XLogRecPtr lsn;
4893
4894 lsn = pg_lsn_in_safe(*newval, (Node *) &escontext);
4895 if (escontext.error_occurred)
4896 return false;
4897
4898 myextra = (XLogRecPtr *) guc_malloc(LOG, sizeof(XLogRecPtr));
4899 if (!myextra)
4900 return false;
4901 *myextra = lsn;
4902 *extra = myextra;
4903 }
4904 return true;
4905}
#define LOG
Definition elog.h:31
void * guc_malloc(int elevel, size_t size)
Definition guc.c:636
XLogRecPtr pg_lsn_in_safe(const char *str, Node *escontext)
Definition pg_lsn.c:32
Definition nodes.h:135

References ErrorSaveContext::error_occurred, fb(), guc_malloc(), LOG, newval, and pg_lsn_in_safe().

◆ check_recovery_target_name()

bool check_recovery_target_name ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4930 of file xlogrecovery.c.

4931{
4932 /* Use the value of newval directly */
4933 if (strlen(*newval) >= MAXFNAMELEN)
4934 {
4935 GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
4936 "recovery_target_name", MAXFNAMELEN - 1);
4937 return false;
4938 }
4939 return true;
4940}
#define MAXFNAMELEN

References fb(), GUC_check_errdetail, MAXFNAMELEN, and newval.

◆ check_recovery_target_time()

bool check_recovery_target_time ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4971 of file xlogrecovery.c.

4972{
4973 if (strcmp(*newval, "") != 0)
4974 {
4975 /* reject some special values */
4976 if (strcmp(*newval, "now") == 0 ||
4977 strcmp(*newval, "today") == 0 ||
4978 strcmp(*newval, "tomorrow") == 0 ||
4979 strcmp(*newval, "yesterday") == 0)
4980 {
4981 return false;
4982 }
4983
4984 /*
4985 * parse timestamp value (see also timestamptz_in())
4986 */
4987 {
4988 char *str = *newval;
4989 fsec_t fsec;
4990 struct pg_tm tt,
4991 *tm = &tt;
4992 int tz;
4993 int dtype;
4994 int nf;
4995 int dterr;
4996 char *field[MAXDATEFIELDS];
4997 int ftype[MAXDATEFIELDS];
5001
5003 field, ftype, MAXDATEFIELDS, &nf);
5004 if (dterr == 0)
5005 dterr = DecodeDateTime(field, ftype, nf,
5006 &dtype, tm, &fsec, &tz, &dtextra);
5007 if (dterr != 0)
5008 return false;
5009 if (dtype != DTK_DATE)
5010 return false;
5011
5012 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
5013 {
5014 GUC_check_errdetail("Timestamp out of range: \"%s\".", str);
5015 return false;
5016 }
5017 }
5018 }
5019 return true;
5020}
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition datetime.c:773
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition datetime.c:997
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition timestamp.c:2006
int64 TimestampTz
Definition timestamp.h:39
int32 fsec_t
Definition timestamp.h:41
const char * str
#define MAXDATEFIELDS
Definition datetime.h:202
#define DTK_DATE
Definition datetime.h:144
#define MAXDATELEN
Definition datetime.h:200
static struct pg_tm tm
Definition localtime.c:104
int64 timestamp
Definition pgtime.h:35

References DecodeDateTime(), DTK_DATE, fb(), GUC_check_errdetail, MAXDATEFIELDS, MAXDATELEN, newval, ParseDateTime(), str, tm, and tm2timestamp().

◆ check_recovery_target_timeline()

bool check_recovery_target_timeline ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 5042 of file xlogrecovery.c.

5043{
5046
5047 if (strcmp(*newval, "current") == 0)
5049 else if (strcmp(*newval, "latest") == 0)
5051 else
5052 {
5053 char *endp;
5054 uint64 timeline;
5055
5057
5058 errno = 0;
5059 timeline = strtou64(*newval, &endp, 0);
5060
5061 if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
5062 {
5063 GUC_check_errdetail("\"%s\" is not a valid number.",
5064 "recovery_target_timeline");
5065 return false;
5066 }
5067
5069 {
5070 GUC_check_errdetail("\"%s\" must be between %u and %u.",
5071 "recovery_target_timeline", 1, UINT_MAX);
5072 return false;
5073 }
5074 }
5075
5077 if (!myextra)
5078 return false;
5079 *myextra = rttg;
5080 *extra = myextra;
5081
5082 return true;
5083}
#define PG_UINT32_MAX
Definition c.h:604
uint64_t uint64
Definition c.h:547
@ RECOVERY_TARGET_TIMELINE_CONTROLFILE
@ RECOVERY_TARGET_TIMELINE_LATEST

References fb(), GUC_check_errdetail, guc_malloc(), LOG, newval, PG_UINT32_MAX, RECOVERY_TARGET_TIMELINE_CONTROLFILE, RECOVERY_TARGET_TIMELINE_LATEST, and RECOVERY_TARGET_TIMELINE_NUMERIC.

◆ check_recovery_target_xid()

bool check_recovery_target_xid ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 5102 of file xlogrecovery.c.

5103{
5104 if (strcmp(*newval, "") != 0)
5105 {
5106 TransactionId xid;
5108
5109 errno = 0;
5110 xid = (TransactionId) strtou64(*newval, NULL, 0);
5111 if (errno == EINVAL || errno == ERANGE)
5112 return false;
5113
5115 if (!myextra)
5116 return false;
5117 *myextra = xid;
5118 *extra = myextra;
5119 }
5120 return true;
5121}

References fb(), guc_malloc(), LOG, and newval.

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 4498 of file xlogrecovery.c.

4499{
4501 return true;
4502
4504 {
4505 ereport(LOG, (errmsg("received promote request")));
4509 return true;
4510 }
4511
4512 return false;
4513}
bool IsPromoteSignaled(void)
Definition startup.c:288
void ResetPromoteSignaled(void)
Definition startup.c:294
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ereport(elevel,...)
Definition elog.h:150
bool CheckPromoteSignal(void)
static bool LocalPromoteIsTriggered
static void SetPromoteIsTriggered(void)
void RemovePromoteSignalFiles(void)

References CheckPromoteSignal(), ereport, errmsg(), IsPromoteSignaled(), LocalPromoteIsTriggered, LOG, RemovePromoteSignalFiles(), ResetPromoteSignaled(), and SetPromoteIsTriggered().

Referenced by ReadRecord(), recoveryApplyDelay(), recoveryPausesHere(), RecoveryRequiresIntParameter(), and WaitForWALToBecomeAvailable().

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 4528 of file xlogrecovery.c.

4529{
4530 struct stat stat_buf;
4531
4532 if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4533 return true;
4534
4535 return false;
4536}
#define stat
Definition win32_port.h:74
#define PROMOTE_SIGNAL_FILE
Definition xlog.h:326

References fb(), PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 2207 of file xlogrecovery.c.

2208{
2209 XLogRecPtr lastReplayedEndRecPtr;
2210 TimeLineID lastReplayedTLI;
2211
2212 /*
2213 * During crash recovery, we don't reach a consistent state until we've
2214 * replayed all the WAL.
2215 */
2217 return;
2218
2220
2221 /*
2222 * assume that we are called in the startup process, and hence don't need
2223 * a lock to read lastReplayedEndRecPtr
2224 */
2225 lastReplayedEndRecPtr = XLogRecoveryCtl->lastReplayedEndRecPtr;
2226 lastReplayedTLI = XLogRecoveryCtl->lastReplayedTLI;
2227
2228 /*
2229 * Have we reached the point where our base backup was completed?
2230 */
2232 backupEndPoint <= lastReplayedEndRecPtr)
2233 {
2236
2237 elog(DEBUG1, "end of backup reached");
2238
2239 /*
2240 * We have reached the end of base backup, as indicated by pg_control.
2241 * Update the control file accordingly.
2242 */
2243 ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI);
2246 backupEndRequired = false;
2247
2248 ereport(LOG,
2249 errmsg("completed backup recovery with redo LSN %X/%08X and end LSN %X/%08X",
2252 }
2253
2254 /*
2255 * Have we passed our safe starting point? Note that minRecoveryPoint is
2256 * known to be incorrectly set if recovering from a backup, until the
2257 * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint.
2258 * All we know prior to that is that we're not consistent yet.
2259 */
2261 minRecoveryPoint <= lastReplayedEndRecPtr)
2262 {
2263 /*
2264 * Check to see if the XLOG sequence contained any unresolved
2265 * references to uninitialized pages.
2266 */
2268
2269 /*
2270 * Check that pg_tblspc doesn't contain any real directories. Replay
2271 * of Database/CREATE_* records may have created fictitious tablespace
2272 * directories that should have been removed by the time consistency
2273 * was reached.
2274 */
2276
2277 reachedConsistency = true;
2279 ereport(LOG,
2280 errmsg("consistent recovery state reached at %X/%08X",
2281 LSN_FORMAT_ARGS(lastReplayedEndRecPtr)));
2282 }
2283
2284 /*
2285 * Have we got a valid starting snapshot that will allow queries to be
2286 * run? If so, we can tell postmaster that the database is consistent now,
2287 * enabling connections.
2288 */
2293 {
2297
2298 LocalHotStandbyActive = true;
2299
2301 }
2302}
#define Assert(condition)
Definition c.h:873
#define DEBUG1
Definition elog.h:30
#define elog(elevel,...)
Definition elog.h:226
bool IsUnderPostmaster
Definition globals.c:120
void SendPostmasterSignal(PMSignalReason reason)
Definition pmsignal.c:165
@ PMSIGNAL_BEGIN_HOT_STANDBY
Definition pmsignal.h:37
@ PMSIGNAL_RECOVERY_CONSISTENT
Definition pmsignal.h:36
void ReachedEndOfBackup(XLogRecPtr EndRecPtr, TimeLineID tli)
Definition xlog.c:6373
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
#define InvalidXLogRecPtr
Definition xlogdefs.h:28
bool reachedConsistency
static bool backupEndRequired
static XLogRecPtr minRecoveryPoint
static XLogRecPtr backupEndPoint
bool InArchiveRecovery
static bool LocalHotStandbyActive
static void CheckTablespaceDirectory(void)
static XLogRecPtr backupStartPoint
void XLogCheckInvalidPages(void)
Definition xlogutils.c:234
@ STANDBY_SNAPSHOT_READY
Definition xlogutils.h:55

References Assert, backupEndPoint, backupEndRequired, backupStartPoint, CheckTablespaceDirectory(), DEBUG1, elog, ereport, errmsg(), fb(), InArchiveRecovery, XLogRecoveryCtlData::info_lck, InvalidXLogRecPtr, IsUnderPostmaster, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedTLI, LocalHotStandbyActive, LOG, LSN_FORMAT_ARGS, minRecoveryPoint, PMSIGNAL_BEGIN_HOT_STANDBY, PMSIGNAL_RECOVERY_CONSISTENT, reachedConsistency, ReachedEndOfBackup(), SendPostmasterSignal(), XLogRecoveryCtlData::SharedHotStandbyActive, SpinLockAcquire, SpinLockRelease, STANDBY_SNAPSHOT_READY, standbyState, XLogCheckInvalidPages(), XLogRecoveryCtl, and XLogRecPtrIsValid.

Referenced by ApplyWalRecord(), PerformWalRecovery(), and ReadRecord().

◆ CheckTablespaceDirectory()

static void CheckTablespaceDirectory ( void  )
static

Definition at line 2174 of file xlogrecovery.c.

2175{
2176 DIR *dir;
2177 struct dirent *de;
2178
2180 while ((de = ReadDir(dir, PG_TBLSPC_DIR)) != NULL)
2181 {
2182 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR)];
2183
2184 /* Skip entries of non-oid names */
2185 if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
2186 continue;
2187
2188 snprintf(path, sizeof(path), "%s/%s", PG_TBLSPC_DIR, de->d_name);
2189
2190 if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
2193 errmsg("unexpected directory entry \"%s\" found in %s",
2195 errdetail("All directory entries in %s/ should be symbolic links.",
2197 errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
2198 }
2199}
bool allow_in_place_tablespaces
Definition tablespace.c:85
int errdetail(const char *fmt,...)
Definition elog.c:1216
int errhint(const char *fmt,...)
Definition elog.c:1330
int errcode(int sqlerrcode)
Definition elog.c:863
#define WARNING
Definition elog.h:36
#define PANIC
Definition elog.h:42
#define ERROR
Definition elog.h:39
DIR * AllocateDir(const char *dirname)
Definition fd.c:2887
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2953
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition file_utils.c:547
@ PGFILETYPE_LNK
Definition file_utils.h:24
#define ERRCODE_DATA_CORRUPTED
#define MAXPGPATH
#define snprintf
Definition port.h:260
#define PG_TBLSPC_DIR
Definition relpath.h:41
Definition dirent.c:26
char d_name[MAX_PATH]
Definition dirent.h:15

References AllocateDir(), allow_in_place_tablespaces, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errdetail(), errhint(), errmsg(), ERROR, fb(), get_dirent_type(), MAXPGPATH, PANIC, PG_TBLSPC_DIR, PGFILETYPE_LNK, ReadDir(), snprintf, and WARNING.

Referenced by CheckRecoveryConsistency().

◆ checkTimeLineSwitch()

static void checkTimeLineSwitch ( XLogRecPtr  lsn,
TimeLineID  newTLI,
TimeLineID  prevTLI,
TimeLineID  replayTLI 
)
static

Definition at line 2410 of file xlogrecovery.c.

2412{
2413 /* Check that the record agrees on what the current (old) timeline is */
2414 if (prevTLI != replayTLI)
2415 ereport(PANIC,
2416 (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2417 prevTLI, replayTLI)));
2418
2419 /*
2420 * The new timeline better be in the list of timelines we expect to see,
2421 * according to the timeline history. It should also not decrease.
2422 */
2423 if (newTLI < replayTLI || !tliInHistory(newTLI, expectedTLEs))
2424 ereport(PANIC,
2425 (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
2426 newTLI, replayTLI)));
2427
2428 /*
2429 * If we have not yet reached min recovery point, and we're about to
2430 * switch to a timeline greater than the timeline of the min recovery
2431 * point: trouble. After switching to the new timeline, we could not
2432 * possibly visit the min recovery point on the correct timeline anymore.
2433 * This can happen if there is a newer timeline in the archive that
2434 * branched before the timeline the min recovery point is on, and you
2435 * attempt to do PITR to the new timeline.
2436 */
2438 lsn < minRecoveryPoint &&
2440 ereport(PANIC,
2441 errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%08X on timeline %u",
2442 newTLI,
2445
2446 /* Looks good */
2447}
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition timeline.c:526
static List * expectedTLEs
static TimeLineID minRecoveryPointTLI

References ereport, errmsg(), expectedTLEs, fb(), LSN_FORMAT_ARGS, minRecoveryPoint, minRecoveryPointTLI, PANIC, tliInHistory(), and XLogRecPtrIsValid.

Referenced by ApplyWalRecord().

◆ ConfirmRecoveryPaused()

◆ emode_for_corrupt_record()

static int emode_for_corrupt_record ( int  emode,
XLogRecPtr  RecPtr 
)
static

Definition at line 4097 of file xlogrecovery.c.

4098{
4100
4101 if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
4102 {
4103 if (RecPtr == lastComplaint)
4104 emode = DEBUG1;
4105 else
4107 }
4108 return emode;
4109}
static XLogSource readSource

References DEBUG1, fb(), InvalidXLogRecPtr, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

◆ EnableStandbyMode()

static void EnableStandbyMode ( void  )
static

Definition at line 485 of file xlogrecovery.c.

486{
487 StandbyMode = true;
488
489 /*
490 * To avoid server log bloat, we don't report recovery progress in a
491 * standby as it will always be in recovery unless promoted. We disable
492 * startup progress timeout in standby mode to avoid calling
493 * startup_progress_timeout_handler() unnecessarily.
494 */
496}
void disable_startup_progress_timeout(void)
Definition startup.c:309
bool StandbyMode

References disable_startup_progress_timeout(), and StandbyMode.

Referenced by InitWalRecovery(), and ReadRecord().

◆ error_multiple_recovery_targets()

static pg_noreturn void error_multiple_recovery_targets ( void  )
static

Definition at line 4844 of file xlogrecovery.c.

4845{
4846 ereport(ERROR,
4848 errmsg("multiple recovery targets specified"),
4849 errdetail("At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set.")));
4850}

References ereport, errcode(), errdetail(), errmsg(), ERROR, and fb().

Referenced by assign_recovery_target(), assign_recovery_target_lsn(), assign_recovery_target_name(), assign_recovery_target_time(), and assign_recovery_target_xid().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo * FinishWalRecovery ( void  )

Definition at line 1477 of file xlogrecovery.c.

1478{
1480 XLogRecPtr lastRec;
1481 TimeLineID lastRecTLI;
1482 XLogRecPtr endOfLog;
1483
1484 /*
1485 * Kill WAL receiver, if it's still running, before we continue to write
1486 * the startup checkpoint and aborted-contrecord records. It will trump
1487 * over these records and subsequent ones if it's still alive when we
1488 * start writing WAL.
1489 */
1491
1492 /*
1493 * Shutdown the slot sync worker to drop any temporary slots acquired by
1494 * it and to prevent it from keep trying to fetch the failover slots.
1495 *
1496 * We do not update the 'synced' column in 'pg_replication_slots' system
1497 * view from true to false here, as any failed update could leave 'synced'
1498 * column false for some slots. This could cause issues during slot sync
1499 * after restarting the server as a standby. While updating the 'synced'
1500 * column after switching to the new timeline is an option, it does not
1501 * simplify the handling for the 'synced' column. Therefore, we retain the
1502 * 'synced' column as true after promotion as it may provide useful
1503 * information about the slot origin.
1504 */
1506
1507 /*
1508 * We are now done reading the xlog from stream. Turn off streaming
1509 * recovery to force fetching the files (which would be required at end of
1510 * recovery, e.g., timeline history file) from archive or pg_wal.
1511 *
1512 * Note that standby mode must be turned off after killing WAL receiver,
1513 * i.e., calling XLogShutdownWalRcv().
1514 */
1516 StandbyMode = false;
1517
1518 /*
1519 * Determine where to start writing WAL next.
1520 *
1521 * Re-fetch the last valid or last applied record, so we can identify the
1522 * exact endpoint of what we consider the valid portion of WAL. There may
1523 * be an incomplete continuation record after that, in which case
1524 * 'abortedRecPtr' and 'missingContrecPtr' are set and the caller will
1525 * write a special OVERWRITE_CONTRECORD message to mark that the rest of
1526 * it is intentionally missing. See CreateOverwriteContrecordRecord().
1527 *
1528 * An important side-effect of this is to load the last page into
1529 * xlogreader. The caller uses it to initialize the WAL for writing.
1530 */
1531 if (!InRecovery)
1532 {
1533 lastRec = CheckPointLoc;
1534 lastRecTLI = CheckPointTLI;
1535 }
1536 else
1537 {
1539 lastRecTLI = XLogRecoveryCtl->lastReplayedTLI;
1540 }
1542 (void) ReadRecord(xlogprefetcher, PANIC, false, lastRecTLI);
1543 endOfLog = xlogreader->EndRecPtr;
1544
1545 /*
1546 * Remember the TLI in the filename of the XLOG segment containing the
1547 * end-of-log. It could be different from the timeline that endOfLog
1548 * nominally belongs to, if there was a timeline switch in that segment,
1549 * and we were reading the old WAL from a segment belonging to a higher
1550 * timeline.
1551 */
1552 result->endOfLogTLI = xlogreader->seg.ws_tli;
1553
1555 {
1556 /*
1557 * We are no longer in archive recovery state.
1558 *
1559 * We are now done reading the old WAL. Turn off archive fetching if
1560 * it was active.
1561 */
1563 InArchiveRecovery = false;
1564
1565 /*
1566 * If the ending log segment is still open, close it (to avoid
1567 * problems on Windows with trying to rename or delete an open file).
1568 */
1569 if (readFile >= 0)
1570 {
1571 close(readFile);
1572 readFile = -1;
1573 }
1574 }
1575
1576 /*
1577 * Copy the last partial block to the caller, for initializing the WAL
1578 * buffer for appending new WAL.
1579 */
1580 if (endOfLog % XLOG_BLCKSZ != 0)
1581 {
1582 char *page;
1583 int len;
1585
1586 pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1588
1589 /* Copy the valid part of the last block */
1590 len = endOfLog % XLOG_BLCKSZ;
1591 page = palloc(len);
1592 memcpy(page, xlogreader->readBuf, len);
1593
1595 result->lastPage = page;
1596 }
1597 else
1598 {
1599 /* There is no partial block to copy. */
1600 result->lastPageBeginPtr = endOfLog;
1601 result->lastPage = NULL;
1602 }
1603
1604 /*
1605 * Create a comment for the history file to explain why and where timeline
1606 * changed.
1607 */
1609
1610 result->lastRec = lastRec;
1611 result->lastRecTLI = lastRecTLI;
1612 result->endOfLog = endOfLog;
1613
1614 result->abortedRecPtr = abortedRecPtr;
1616
1619
1620 return result;
1621}
#define palloc_object(type)
Definition fe_memutils.h:74
#define close(a)
Definition win32.h:12
void * palloc(Size size)
Definition mcxt.c:1387
const void size_t len
void ShutDownSlotSync(void)
Definition slotsync.c:1785
XLogRecPtr lastPageBeginPtr
XLogRecPtr missingContrecPtr
TimeLineID ws_tli
Definition xlogreader.h:49
WALOpenSegment seg
Definition xlogreader.h:271
bool WalRcvStreaming(void)
int wal_segment_size
Definition xlog.c:146
void XLogShutdownWalRcv(void)
Definition xlog.c:9636
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
void XLogPrefetcherBeginRead(XLogPrefetcher *prefetcher, XLogRecPtr recPtr)
static char * getRecoveryStopReason(void)
bool ArchiveRecoveryRequested
static XLogRecPtr missingContrecPtr
static uint32 readOff
static bool standby_signal_file_found
static int readFile
static XLogRecPtr abortedRecPtr
static XLogRecord * ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI)
static XLogRecPtr CheckPointLoc
static bool recovery_signal_file_found
static XLogPrefetcher * xlogprefetcher
static TimeLineID CheckPointTLI
bool InRecovery
Definition xlogutils.c:50

References abortedRecPtr, EndOfWalRecoveryInfo::abortedRecPtr, ArchiveRecoveryRequested, Assert, CheckPointLoc, CheckPointTLI, close, EndOfWalRecoveryInfo::endOfLog, EndOfWalRecoveryInfo::endOfLogTLI, XLogReaderState::EndRecPtr, fb(), getRecoveryStopReason(), InArchiveRecovery, InRecovery, EndOfWalRecoveryInfo::lastPage, EndOfWalRecoveryInfo::lastPageBeginPtr, EndOfWalRecoveryInfo::lastRec, EndOfWalRecoveryInfo::lastRecTLI, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, len, missingContrecPtr, EndOfWalRecoveryInfo::missingContrecPtr, palloc(), palloc_object, PANIC, XLogReaderState::readBuf, readFile, readOff, ReadRecord(), recovery_signal_file_found, EndOfWalRecoveryInfo::recovery_signal_file_found, EndOfWalRecoveryInfo::recoveryStopReason, XLogReaderState::seg, ShutDownSlotSync(), standby_signal_file_found, EndOfWalRecoveryInfo::standby_signal_file_found, StandbyMode, wal_segment_size, WalRcvStreaming(), WALOpenSegment::ws_tli, xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, XLogRecoveryCtl, XLogSegmentOffset, and XLogShutdownWalRcv().

Referenced by StartupXLOG().

◆ GetCurrentChunkReplayStartTime()

◆ GetCurrentReplayRecPtr()

XLogRecPtr GetCurrentReplayRecPtr ( TimeLineID replayEndTLI)

◆ GetLatestXTime()

◆ getRecordTimestamp()

static bool getRecordTimestamp ( XLogReaderState record,
TimestampTz recordXtime 
)
static

Definition at line 2459 of file xlogrecovery.c.

2460{
2461 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2463 uint8 rmid = XLogRecGetRmid(record);
2464
2465 if (rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2466 {
2467 *recordXtime = ((xl_restore_point *) XLogRecGetData(record))->rp_time;
2468 return true;
2469 }
2470 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_COMMIT ||
2472 {
2473 *recordXtime = ((xl_xact_commit *) XLogRecGetData(record))->xact_time;
2474 return true;
2475 }
2476 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_ABORT ||
2478 {
2479 *recordXtime = ((xl_xact_abort *) XLogRecGetData(record))->xact_time;
2480 return true;
2481 }
2482 return false;
2483}
#define XLOG_RESTORE_POINT
Definition pg_control.h:76
#define XLOG_XACT_COMMIT_PREPARED
Definition xact.h:173
#define XLOG_XACT_COMMIT
Definition xact.h:170
#define XLOG_XACT_OPMASK
Definition xact.h:180
#define XLOG_XACT_ABORT
Definition xact.h:172
#define XLOG_XACT_ABORT_PREPARED
Definition xact.h:174
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:409
#define XLogRecGetRmid(decoder)
Definition xlogreader.h:410

References fb(), XLOG_RESTORE_POINT, XLOG_XACT_ABORT, XLOG_XACT_ABORT_PREPARED, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_PREPARED, XLOG_XACT_OPMASK, XLogRecGetData, XLogRecGetInfo, and XLogRecGetRmid.

Referenced by recoveryApplyDelay(), recoveryStopsAfter(), and recoveryStopsBefore().

◆ GetRecoveryPauseState()

◆ getRecoveryStopReason()

static char * getRecoveryStopReason ( void  )
static

Definition at line 2919 of file xlogrecovery.c.

2920{
2921 char reason[200];
2922
2924 snprintf(reason, sizeof(reason),
2925 "%s transaction %u",
2926 recoveryStopAfter ? "after" : "before",
2929 snprintf(reason, sizeof(reason),
2930 "%s %s\n",
2931 recoveryStopAfter ? "after" : "before",
2934 snprintf(reason, sizeof(reason),
2935 "%s LSN %X/%08X\n",
2936 recoveryStopAfter ? "after" : "before",
2939 snprintf(reason, sizeof(reason),
2940 "at restore point \"%s\"",
2943 snprintf(reason, sizeof(reason), "reached consistency");
2944 else
2945 snprintf(reason, sizeof(reason), "no recovery target specified");
2946
2947 return pstrdup(reason);
2948}
const char * timestamptz_to_str(TimestampTz t)
Definition timestamp.c:1862
char * pstrdup(const char *in)
Definition mcxt.c:1781
static XLogRecPtr recoveryStopLSN
static TimestampTz recoveryStopTime
static char recoveryStopName[MAXFNAMELEN]
static bool recoveryStopAfter
static TransactionId recoveryStopXid

References LSN_FORMAT_ARGS, pstrdup(), RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_LSN, RECOVERY_TARGET_NAME, RECOVERY_TARGET_TIME, RECOVERY_TARGET_XID, recoveryStopAfter, recoveryStopLSN, recoveryStopName, recoveryStopTime, recoveryStopXid, recoveryTarget, snprintf, and timestamptz_to_str().

Referenced by FinishWalRecovery().

◆ GetXLogReceiptTime()

void GetXLogReceiptTime ( TimestampTz rtime,
bool fromStream 
)

Definition at line 4707 of file xlogrecovery.c.

4708{
4709 /*
4710 * This must be executed in the startup process, since we don't export the
4711 * relevant state to shared memory.
4712 */
4714
4717}
static XLogSource XLogReceiptSource
static TimestampTz XLogReceiptTime

References Assert, fb(), InRecovery, XLOG_FROM_STREAM, XLogReceiptSource, and XLogReceiptTime.

Referenced by GetStandbyLimitTime().

◆ GetXLogReplayRecPtr()

◆ HotStandbyActive()

bool HotStandbyActive ( void  )

Definition at line 4567 of file xlogrecovery.c.

4568{
4569 /*
4570 * We check shared state each time only until Hot Standby is active. We
4571 * can't de-activate Hot Standby, so there's no need to keep checking
4572 * after the shared variable has once been seen true.
4573 */
4575 return true;
4576 else
4577 {
4578 /* spinlock is essential on machines with weak memory ordering! */
4582
4583 return LocalHotStandbyActive;
4584 }
4585}

References XLogRecoveryCtlData::info_lck, LocalHotStandbyActive, XLogRecoveryCtlData::SharedHotStandbyActive, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by XLogWalRcvSendHSFeedback().

◆ HotStandbyActiveInReplay()

static bool HotStandbyActiveInReplay ( void  )
static

Definition at line 4592 of file xlogrecovery.c.

4593{
4595 return LocalHotStandbyActive;
4596}
bool IsPostmasterEnvironment
Definition globals.c:119
#define AmStartupProcess()
Definition miscadmin.h:390

References AmStartupProcess, Assert, IsPostmasterEnvironment, and LocalHotStandbyActive.

Referenced by RecoveryRequiresIntParameter().

◆ InitWalRecovery()

void InitWalRecovery ( ControlFileData ControlFile,
bool wasShutdown_ptr,
bool haveBackupLabel_ptr,
bool haveTblspcMap_ptr 
)

Definition at line 519 of file xlogrecovery.c.

521{
522 XLogPageReadPrivate *private;
523 struct stat st;
524 bool wasShutdown;
525 XLogRecord *record;
527 bool haveTblspcMap = false;
528 bool haveBackupLabel = false;
529 CheckPoint checkPoint;
530 bool backupFromStandby = false;
531
533
534 /*
535 * Initialize on the assumption we want to recover to the latest timeline
536 * that's active according to pg_control.
537 */
541 else
543
544 /*
545 * Check for signal files, and if so set up state for offline recovery
546 */
549
550 /*
551 * Take ownership of the wakeup latch if we're going to sleep during
552 * recovery, if required.
553 */
556
557 /*
558 * Set the WAL reading processor now, as it will be needed when reading
559 * the checkpoint record required (backup_label or not).
560 */
562 xlogreader =
564 XL_ROUTINE(.page_read = &XLogPageRead,
565 .segment_open = NULL,
566 .segment_close = wal_segment_close),
567 private);
568 if (!xlogreader)
571 errmsg("out of memory"),
572 errdetail("Failed while allocating a WAL reading processor.")));
574
575 /*
576 * Set the WAL decode buffer size. This limits how far ahead we can read
577 * in the WAL.
578 */
580
581 /* Create a WAL prefetcher. */
583
584 /*
585 * Allocate two page buffers dedicated to WAL consistency checks. We do
586 * it this way, rather than just making static arrays, for two reasons:
587 * (1) no need to waste the storage in most instantiations of the backend;
588 * (2) a static char array isn't guaranteed to have any particular
589 * alignment, whereas palloc() will provide MAXALIGN'd storage.
590 */
593
594 /*
595 * Read the backup_label file. We want to run this part of the recovery
596 * process after checking for signal files and after performing validation
597 * of the recovery parameters.
598 */
601 {
602 List *tablespaces = NIL;
603
604 /*
605 * Archive recovery was requested, and thanks to the backup label
606 * file, we know how far we need to replay to reach consistency. Enter
607 * archive recovery directly.
608 */
609 InArchiveRecovery = true;
612
613 /*
614 * Omitting backup_label when creating a new replica, PITR node etc.
615 * unfortunately is a common cause of corruption. Logging that
616 * backup_label was used makes it a bit easier to exclude that as the
617 * cause of observed corruption.
618 *
619 * Do so before we try to read the checkpoint record (which can fail),
620 * as otherwise it can be hard to understand why a checkpoint other
621 * than ControlFile->checkPoint is used.
622 */
623 ereport(LOG,
624 errmsg("starting backup recovery with redo LSN %X/%08X, checkpoint LSN %X/%08X, on timeline ID %u",
628
629 /*
630 * When a backup_label file is present, we want to roll forward from
631 * the checkpoint it identifies, rather than using pg_control.
632 */
635 if (record != NULL)
636 {
637 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
640 errmsg_internal("checkpoint record is at %X/%08X",
642 InRecovery = true; /* force recovery even if SHUTDOWNED */
643
644 /*
645 * Make sure that REDO location exists. This may not be the case
646 * if there was a crash during an online backup, which left a
647 * backup_label around that references a WAL segment that's
648 * already been archived.
649 */
650 if (checkPoint.redo < CheckPointLoc)
651 {
653 if (!ReadRecord(xlogprefetcher, LOG, false,
654 checkPoint.ThisTimeLineID))
656 errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
658 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
659 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
660 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
662 }
663 }
664 else
665 {
667 errmsg("could not locate required checkpoint record at %X/%08X",
669 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
670 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
671 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
673 wasShutdown = false; /* keep compiler quiet */
674 }
675
676 /* Read the tablespace_map file if present and create symlinks. */
677 if (read_tablespace_map(&tablespaces))
678 {
679 ListCell *lc;
680
681 foreach(lc, tablespaces)
682 {
684 char *linkloc;
685
686 linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid);
687
688 /*
689 * Remove the existing symlink if any and Create the symlink
690 * under PGDATA.
691 */
693
694 if (symlink(ti->path, linkloc) < 0)
697 errmsg("could not create symbolic link \"%s\": %m",
698 linkloc)));
699
700 pfree(ti->path);
701 pfree(ti);
702 }
703
704 /* tell the caller to delete it later */
705 haveTblspcMap = true;
706 }
707
708 /* tell the caller to delete it later */
709 haveBackupLabel = true;
710 }
711 else
712 {
713 /* No backup_label file has been found if we are here. */
714
715 /*
716 * If tablespace_map file is present without backup_label file, there
717 * is no use of such file. There is no harm in retaining it, but it
718 * is better to get rid of the map file so that we don't have any
719 * redundant file in data directory and it will avoid any sort of
720 * confusion. It seems prudent though to just rename the file out of
721 * the way rather than delete it completely, also we ignore any error
722 * that occurs in rename operation as even if map file is present
723 * without backup_label file, it is harmless.
724 */
725 if (stat(TABLESPACE_MAP, &st) == 0)
726 {
729 ereport(LOG,
730 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
732 errdetail("File \"%s\" was renamed to \"%s\".",
734 else
735 ereport(LOG,
736 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
738 errdetail("Could not rename file \"%s\" to \"%s\": %m.",
740 }
741
742 /*
743 * It's possible that archive recovery was requested, but we don't
744 * know how far we need to replay the WAL before we reach consistency.
745 * This can happen for example if a base backup is taken from a
746 * running server using an atomic filesystem snapshot, without calling
747 * pg_backup_start/stop. Or if you just kill a running primary server
748 * and put it into archive recovery by creating a recovery signal
749 * file.
750 *
751 * Our strategy in that case is to perform crash recovery first,
752 * replaying all the WAL present in pg_wal, and only enter archive
753 * recovery after that.
754 *
755 * But usually we already know how far we need to replay the WAL (up
756 * to minRecoveryPoint, up to backupEndPoint, or until we see an
757 * end-of-backup record), and we can enter archive recovery directly.
758 */
764 {
765 InArchiveRecovery = true;
768 }
769
770 /*
771 * For the same reason as when starting up with backup_label present,
772 * emit a log message when we continue initializing from a base
773 * backup.
774 */
776 ereport(LOG,
777 errmsg("restarting backup recovery with redo LSN %X/%08X",
779
780 /* Get the last valid checkpoint record. */
787 if (record != NULL)
788 {
790 errmsg_internal("checkpoint record is at %X/%08X",
792 }
793 else
794 {
795 /*
796 * We used to attempt to go back to a secondary checkpoint record
797 * here, but only when not in standby mode. We now just fail if we
798 * can't read the last checkpoint because this allows us to
799 * simplify processing around checkpoints.
800 */
802 errmsg("could not locate a valid checkpoint record at %X/%08X",
804 }
805 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
807
808 /* Make sure that REDO location exists. */
809 if (checkPoint.redo < CheckPointLoc)
810 {
812 if (!ReadRecord(xlogprefetcher, LOG, false, checkPoint.ThisTimeLineID))
814 errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
816 }
817 }
818
820 {
822 ereport(LOG,
823 (errmsg("entering standby mode")));
825 ereport(LOG,
826 (errmsg("starting point-in-time recovery to XID %u",
829 ereport(LOG,
830 (errmsg("starting point-in-time recovery to %s",
833 ereport(LOG,
834 (errmsg("starting point-in-time recovery to \"%s\"",
837 ereport(LOG,
838 errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%08X\"",
841 ereport(LOG,
842 (errmsg("starting point-in-time recovery to earliest consistent point")));
843 else
844 ereport(LOG,
845 (errmsg("starting archive recovery")));
846 }
847
848 /*
849 * If the location of the checkpoint record is not on the expected
850 * timeline in the history of the requested timeline, we cannot proceed:
851 * the backup is not part of the history of the requested timeline.
852 */
853 Assert(expectedTLEs); /* was initialized by reading checkpoint
854 * record */
857 {
859
860 /*
861 * tliSwitchPoint will throw an error if the checkpoint's timeline is
862 * not in expectedTLEs at all.
863 */
866 (errmsg("requested timeline %u is not a child of this server's history",
868 /* translator: %s is a backup_label file or a pg_control file */
869 errdetail("Latest checkpoint in file \"%s\" is at %X/%08X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%08X.",
870 haveBackupLabel ? "backup_label" : "pg_control",
874 }
875
876 /*
877 * The min recovery point should be part of the requested timeline's
878 * history, too.
879 */
884 errmsg("requested timeline %u does not contain minimum recovery point %X/%08X on timeline %u",
888
890 errmsg_internal("redo record is at %X/%08X; shutdown %s",
891 LSN_FORMAT_ARGS(checkPoint.redo),
892 wasShutdown ? "true" : "false"));
894 (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
896 checkPoint.nextOid)));
898 (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %" PRIu64,
899 checkPoint.nextMulti, checkPoint.nextMultiOffset)));
901 (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
902 checkPoint.oldestXid, checkPoint.oldestXidDB)));
904 (errmsg_internal("oldest MultiXactId: %u, in database %u",
905 checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
907 (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
908 checkPoint.oldestCommitTsXid,
909 checkPoint.newestCommitTsXid)));
912 (errmsg("invalid next transaction ID")));
913
914 /* sanity check */
915 if (checkPoint.redo > CheckPointLoc)
917 (errmsg("invalid redo in checkpoint record")));
918
919 /*
920 * Check whether we need to force recovery from WAL. If it appears to
921 * have been a clean shutdown and we did not have a recovery signal file,
922 * then assume no recovery needed.
923 */
924 if (checkPoint.redo < CheckPointLoc)
925 {
926 if (wasShutdown)
928 (errmsg("invalid redo record in shutdown checkpoint")));
929 InRecovery = true;
930 }
931 else if (ControlFile->state != DB_SHUTDOWNED)
932 InRecovery = true;
934 {
935 /* force recovery due to presence of recovery signal file */
936 InRecovery = true;
937 }
938
939 /*
940 * If recovery is needed, update our in-memory copy of pg_control to show
941 * that we are recovering and to show the selected checkpoint as the place
942 * we are starting from. We also mark pg_control with any minimum recovery
943 * stop point obtained from a backup history file.
944 *
945 * We don't write the changes to disk yet, though. Only do that after
946 * initializing various subsystems.
947 */
948 if (InRecovery)
949 {
951 {
953 }
954 else
955 {
956 ereport(LOG,
957 (errmsg("database system was not properly shut down; "
958 "automatic recovery in progress")));
960 ereport(LOG,
961 (errmsg("crash recovery starts in timeline %u "
962 "and has target timeline %u",
966 }
968 ControlFile->checkPointCopy = checkPoint;
970 {
971 /* initialize minRecoveryPoint if not set yet */
972 if (ControlFile->minRecoveryPoint < checkPoint.redo)
973 {
974 ControlFile->minRecoveryPoint = checkPoint.redo;
976 }
977 }
978
979 /*
980 * Set backupStartPoint if we're starting recovery from a base backup.
981 *
982 * Also set backupEndPoint and use minRecoveryPoint as the backup end
983 * location if we're starting recovery from a base backup which was
984 * taken from a standby. In this case, the database system status in
985 * pg_control must indicate that the database was already in recovery.
986 * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
987 * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
988 * before reaching this point; e.g. because restore_command or
989 * primary_conninfo were faulty.
990 *
991 * Any other state indicates that the backup somehow became corrupted
992 * and we can't sensibly continue with recovery.
993 */
994 if (haveBackupLabel)
995 {
996 ControlFile->backupStartPoint = checkPoint.redo;
998
1000 {
1003 ereport(FATAL,
1004 (errmsg("backup_label contains data inconsistent with control file"),
1005 errhint("This means that the backup is corrupted and you will "
1006 "have to use another backup for recovery.")));
1008 }
1009 }
1010 }
1011
1012 /* remember these, so that we know when we have reached consistency */
1017 {
1020 }
1021 else
1022 {
1025 }
1026
1027 /*
1028 * Start recovery assuming that the final record isn't lost.
1029 */
1032
1036}
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
Definition timeline.c:544
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition timeline.c:572
void remove_tablespace_symlink(const char *linkloc)
Definition tablespace.c:883
#define UINT64_FORMAT
Definition c.h:565
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
int errcode_for_file_access(void)
Definition elog.c:886
#define FATAL
Definition elog.h:41
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition fd.c:779
#define palloc0_object(type)
Definition fe_memutils.h:75
char * DataDir
Definition globals.c:71
void OwnLatch(Latch *latch)
Definition latch.c:126
void pfree(void *pointer)
Definition mcxt.c:1616
DBState
Definition pg_control.h:92
@ DB_IN_ARCHIVE_RECOVERY
Definition pg_control.h:98
@ DB_SHUTDOWNED_IN_RECOVERY
Definition pg_control.h:95
@ DB_SHUTDOWNED
Definition pg_control.h:94
@ DB_IN_CRASH_RECOVERY
Definition pg_control.h:97
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
Oid oldestMultiDB
Definition pg_control.h:52
MultiXactId oldestMulti
Definition pg_control.h:51
MultiXactOffset nextMultiOffset
Definition pg_control.h:48
TransactionId newestCommitTsXid
Definition pg_control.h:56
TransactionId oldestXid
Definition pg_control.h:49
MultiXactId nextMulti
Definition pg_control.h:47
FullTransactionId nextXid
Definition pg_control.h:45
TransactionId oldestCommitTsXid
Definition pg_control.h:54
XLogRecPtr redo
Definition pg_control.h:37
Oid oldestXidDB
Definition pg_control.h:50
XLogRecPtr backupStartPoint
Definition pg_control.h:172
CheckPoint checkPointCopy
Definition pg_control.h:137
XLogRecPtr backupEndPoint
Definition pg_control.h:173
XLogRecPtr minRecoveryPoint
Definition pg_control.h:170
XLogRecPtr checkPoint
Definition pg_control.h:135
uint64 system_identifier
Definition pg_control.h:112
TimeLineID minRecoveryPointTLI
Definition pg_control.h:171
Definition pg_list.h:54
uint64 system_identifier
Definition xlogreader.h:190
#define U64FromFullTransactionId(x)
Definition transam.h:49
#define XidFromFullTransactionId(x)
Definition transam.h:48
#define TransactionIdIsNormal(xid)
Definition transam.h:42
#define symlink(oldpath, newpath)
Definition win32_port.h:225
int wal_decode_buffer_size
Definition xlog.c:139
static ControlFileData * ControlFile
Definition xlog.c:576
#define TABLESPACE_MAP_OLD
Definition xlog.h:323
#define TABLESPACE_MAP
Definition xlog.h:322
#define BACKUP_LABEL_FILE
Definition xlog.h:319
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition xlogreader.c:107
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition xlogreader.c:91
#define XL_ROUTINE(...)
Definition xlogreader.h:117
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static void validateRecoveryParameters(void)
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
static TimeLineID RedoStartTLI
static void readRecoverySignalFile(void)
static bool read_tablespace_map(List **tablespaces)
static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
static char * primary_image_masked
static char * replay_image_masked
TimeLineID recoveryTargetTLI
static XLogRecPtr RedoStartLSN
static void EnableStandbyMode(void)
TimestampTz recoveryTargetTime
static bool StandbyModeRequested
void wal_segment_close(XLogReaderState *state)
Definition xlogutils.c:831

References abortedRecPtr, ArchiveRecoveryRequested, Assert, BACKUP_LABEL_FILE, backupEndPoint, ControlFileData::backupEndPoint, backupEndRequired, ControlFileData::backupEndRequired, backupStartPoint, ControlFileData::backupStartPoint, ControlFileData::checkPoint, ControlFileData::checkPointCopy, CheckPointLoc, CheckPointTLI, ControlFile, DataDir, DB_IN_ARCHIVE_RECOVERY, DB_IN_CRASH_RECOVERY, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, DEBUG1, durable_rename(), EnableStandbyMode(), ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), errmsg_internal(), ERROR, expectedTLEs, FATAL, fb(), InArchiveRecovery, InRecovery, InvalidXLogRecPtr, lfirst, LOG, LSN_FORMAT_ARGS, minRecoveryPoint, ControlFileData::minRecoveryPoint, minRecoveryPointTLI, ControlFileData::minRecoveryPointTLI, missingContrecPtr, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, NIL, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, OwnLatch(), palloc(), palloc0_object, PANIC, pfree(), PG_TBLSPC_DIR, primary_image_masked, psprintf(), read_backup_label(), read_tablespace_map(), ReadCheckpointRecord(), ReadRecord(), readRecoverySignalFile(), RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_LSN, RECOVERY_TARGET_NAME, RECOVERY_TARGET_TIME, RECOVERY_TARGET_XID, recoveryTarget, recoveryTargetLSN, recoveryTargetName, recoveryTargetTime, recoveryTargetTLI, recoveryTargetXid, XLogRecoveryCtlData::recoveryWakeupLatch, CheckPoint::redo, RedoStartLSN, RedoStartTLI, remove_tablespace_symlink(), replay_image_masked, StandbyModeRequested, stat, ControlFileData::state, symlink, XLogReaderState::system_identifier, ControlFileData::system_identifier, TABLESPACE_MAP, TABLESPACE_MAP_OLD, CheckPoint::ThisTimeLineID, timestamptz_to_str(), tliOfPointInHistory(), tliSwitchPoint(), TransactionIdIsNormal, U64FromFullTransactionId, UINT64_FORMAT, validateRecoveryParameters(), wal_decode_buffer_size, wal_segment_close(), wal_segment_size, XidFromFullTransactionId, XLogRecord::xl_info, XL_ROUTINE, XLOG_CHECKPOINT_SHUTDOWN, XLogPageRead(), xlogprefetcher, XLogPrefetcherAllocate(), XLogPrefetcherBeginRead(), xlogreader, XLogReaderAllocate(), XLogReaderSetDecodeBuffer(), XLogRecGetData, XLogRecoveryCtl, and XLogRecPtrIsValid.

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1672 of file xlogrecovery.c.

1673{
1674 XLogRecord *record;
1675 bool reachedRecoveryTarget = false;
1676 TimeLineID replayTLI;
1677
1678 /*
1679 * Initialize shared variables for tracking progress of WAL replay, as if
1680 * we had just replayed the record before the REDO location (or the
1681 * checkpoint record itself, if it's a shutdown checkpoint).
1682 */
1685 {
1689 }
1690 else
1691 {
1695 }
1702
1703 /* Also ensure XLogReceiptTime has a sane value */
1705
1706 /*
1707 * Let postmaster know we've started redo now, so that it can launch the
1708 * archiver if necessary.
1709 */
1712
1713 /*
1714 * Allow read-only connections immediately if we're consistent already.
1715 */
1717
1718 /*
1719 * Find the first record that logically follows the checkpoint --- it
1720 * might physically precede it, though.
1721 */
1723 {
1724 /* back up to find the record */
1725 replayTLI = RedoStartTLI;
1727 record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1728
1729 /*
1730 * If a checkpoint record's redo pointer points back to an earlier
1731 * LSN, the record at that LSN should be an XLOG_CHECKPOINT_REDO
1732 * record.
1733 */
1734 if (record->xl_rmid != RM_XLOG_ID ||
1736 ereport(FATAL,
1737 errmsg("unexpected record type found at redo point %X/%08X",
1739 }
1740 else
1741 {
1742 /* just have to read next record after CheckPoint */
1744 replayTLI = CheckPointTLI;
1745 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1746 }
1747
1748 if (record != NULL)
1749 {
1751 PGRUsage ru0;
1752
1754
1755 InRedo = true;
1756
1757 RmgrStartup();
1758
1759 ereport(LOG,
1760 errmsg("redo starts at %X/%08X",
1762
1763 /* Prepare to report progress of the redo phase. */
1764 if (!StandbyMode)
1766
1767 /*
1768 * main redo apply loop
1769 */
1770 do
1771 {
1772 if (!StandbyMode)
1773 ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%08X",
1775
1776#ifdef WAL_DEBUG
1777 if (XLOG_DEBUG)
1778 {
1780
1782 appendStringInfo(&buf, "REDO @ %X/%08X; LSN %X/%08X: ",
1786 appendStringInfoString(&buf, " - ");
1788 elog(LOG, "%s", buf.data);
1789 pfree(buf.data);
1790 }
1791#endif
1792
1793 /* Handle interrupt signals of startup process */
1795
1796 /*
1797 * Pause WAL replay, if requested by a hot-standby session via
1798 * SetRecoveryPause().
1799 *
1800 * Note that we intentionally don't take the info_lck spinlock
1801 * here. We might therefore read a slightly stale value of the
1802 * recoveryPause flag, but it can't be very stale (no worse than
1803 * the last spinlock we did acquire). Since a pause request is a
1804 * pretty asynchronous thing anyway, possibly responding to it one
1805 * WAL record later than we otherwise would is a minor issue, so
1806 * it doesn't seem worth adding another spinlock cycle to prevent
1807 * that.
1808 */
1809 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1811 recoveryPausesHere(false);
1812
1813 /*
1814 * Have we reached our recovery target?
1815 */
1817 {
1818 reachedRecoveryTarget = true;
1819 break;
1820 }
1821
1822 /*
1823 * If we've been asked to lag the primary, wait on latch until
1824 * enough time has passed.
1825 */
1827 {
1828 /*
1829 * We test for paused recovery again here. If user sets
1830 * delayed apply, it may be because they expect to pause
1831 * recovery in case of problems, so we must test again here
1832 * otherwise pausing during the delay-wait wouldn't work.
1833 */
1834 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1836 recoveryPausesHere(false);
1837 }
1838
1839 /*
1840 * Apply the record
1841 */
1842 ApplyWalRecord(xlogreader, record, &replayTLI);
1843
1844 /*
1845 * If we replayed an LSN that someone was waiting for then walk
1846 * over the shared memory array and set latches to notify the
1847 * waiters.
1848 */
1849 if (waitLSNState &&
1853
1854 /* Exit loop if we reached inclusive recovery target */
1856 {
1857 reachedRecoveryTarget = true;
1858 break;
1859 }
1860
1861 /* Else, try to fetch the next WAL record */
1862 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1863 } while (record != NULL);
1864
1865 /*
1866 * end of main redo apply loop
1867 */
1868
1870 {
1871 if (!reachedConsistency)
1872 ereport(FATAL,
1873 (errmsg("requested recovery stop point is before consistent recovery point")));
1874
1875 /*
1876 * This is the last point where we can restart recovery with a new
1877 * recovery target, if we shutdown and begin again. After this,
1878 * Resource Managers may choose to do permanent corrective actions
1879 * at end of recovery.
1880 */
1881 switch (recoveryTargetAction)
1882 {
1884
1885 /*
1886 * exit with special return code to request shutdown of
1887 * postmaster. Log messages issued from postmaster.
1888 */
1889 proc_exit(3);
1890
1892 SetRecoveryPause(true);
1893 recoveryPausesHere(true);
1894
1895 /* drop into promote */
1896
1898 break;
1899 }
1900 }
1901
1902 RmgrCleanup();
1903
1904 ereport(LOG,
1905 errmsg("redo done at %X/%08X system usage: %s",
1907 pg_rusage_show(&ru0)));
1909 if (xtime)
1910 ereport(LOG,
1911 (errmsg("last completed transaction was at log time %s",
1913
1914 InRedo = false;
1915 }
1916 else
1917 {
1918 /* there are no WAL records following the checkpoint */
1919 ereport(LOG,
1920 (errmsg("redo is not required")));
1921 }
1922
1923 /*
1924 * This check is intentionally after the above log messages that indicate
1925 * how far recovery went.
1926 */
1930 ereport(FATAL,
1932 errmsg("recovery ended before configured recovery target was reached")));
1933}
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition atomics.h:467
void begin_startup_progress_phase(void)
Definition startup.c:343
void ProcessStartupProcInterrupts(void)
Definition startup.c:154
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
void proc_exit(int code)
Definition ipc.c:105
#define XLOG_CHECKPOINT_REDO
Definition pg_control.h:83
const char * pg_rusage_show(const PGRUsage *ru0)
Definition pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition pg_rusage.c:27
static char buf[DEFAULT_XLOG_SEG_SIZE]
@ PMSIGNAL_RECOVERY_STARTED
Definition pmsignal.h:35
void RmgrStartup(void)
Definition rmgr.c:58
void RmgrCleanup(void)
Definition rmgr.c:74
#define ereport_startup_progress(msg,...)
Definition startup.h:18
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
pg_atomic_uint64 minWaitedLSN[WAIT_LSN_TYPE_COUNT]
Definition xlogwait.h:85
#define XLR_INFO_MASK
Definition xlogrecord.h:62
static bool recoveryStopsBefore(XLogReaderState *record)
int recoveryTargetAction
static bool recoveryApplyDelay(XLogReaderState *record)
static bool recoveryStopsAfter(XLogReaderState *record)
void SetRecoveryPause(bool recoveryPause)
void xlog_outdesc(StringInfo buf, XLogReaderState *record)
static bool InRedo
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
static void recoveryPausesHere(bool endOfRecovery)
TimestampTz GetLatestXTime(void)
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
@ RECOVERY_NOT_PAUSED
struct WaitLSNState * waitLSNState
Definition xlogwait.c:68
void WaitLSNWakeup(WaitLSNType lsnType, XLogRecPtr currentLSN)
Definition xlogwait.c:317
@ WAIT_LSN_TYPE_STANDBY_REPLAY
Definition xlogwait.h:39

References appendStringInfo(), appendStringInfoString(), ApplyWalRecord(), ArchiveRecoveryRequested, Assert, begin_startup_progress_phase(), buf, CheckPointLoc, CheckPointTLI, CheckRecoveryConsistency(), XLogRecoveryCtlData::currentChunkStartTime, elog, XLogReaderState::EndRecPtr, ereport, ereport_startup_progress, errcode(), errmsg(), FATAL, fb(), GetCurrentTimestamp(), GetLatestXTime(), XLogRecoveryCtlData::info_lck, initStringInfo(), InRedo, InvalidXLogRecPtr, IsUnderPostmaster, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, LOG, LSN_FORMAT_ARGS, WaitLSNState::minWaitedLSN, PANIC, pfree(), pg_atomic_read_u64(), pg_rusage_init(), pg_rusage_show(), PMSIGNAL_RECOVERY_STARTED, proc_exit(), ProcessStartupProcInterrupts(), reachedConsistency, ReadRecord(), XLogReaderState::ReadRecPtr, RECOVERY_NOT_PAUSED, RECOVERY_TARGET_ACTION_PAUSE, RECOVERY_TARGET_ACTION_PROMOTE, RECOVERY_TARGET_ACTION_SHUTDOWN, RECOVERY_TARGET_UNSET, recoveryApplyDelay(), XLogRecoveryCtlData::recoveryLastXTime, recoveryPausesHere(), XLogRecoveryCtlData::recoveryPauseState, recoveryStopsAfter(), recoveryStopsBefore(), recoveryTarget, recoveryTargetAction, RedoStartLSN, RedoStartTLI, XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, RmgrCleanup(), RmgrStartup(), SendPostmasterSignal(), SetRecoveryPause(), SpinLockAcquire, SpinLockRelease, StandbyMode, timestamptz_to_str(), WAIT_LSN_TYPE_STANDBY_REPLAY, waitLSNState, WaitLSNWakeup(), XLogRecord::xl_info, XLogRecord::xl_rmid, XLOG_CHECKPOINT_REDO, xlog_outdesc(), xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, XLogReceiptTime, XLogRecoveryCtl, and XLR_INFO_MASK.

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4459 of file xlogrecovery.c.

4460{
4461 /*
4462 * We check shared state each time only until a standby promotion is
4463 * triggered. We can't trigger a promotion again, so there's no need to
4464 * keep checking after the shared variable has once been seen true.
4465 */
4467 return true;
4468
4472
4474}

References XLogRecoveryCtlData::info_lck, LocalPromoteIsTriggered, XLogRecoveryCtlData::SharedPromoteIsTriggered, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by ExecWaitStmt(), PerformRecoveryXLogAction(), pg_wal_replay_pause(), pg_wal_replay_resume(), and WaitForLSN().

◆ read_backup_label()

static bool read_backup_label ( XLogRecPtr checkPointLoc,
TimeLineID backupLabelTLI,
bool backupEndRequired,
bool backupFromStandby 
)
static

Definition at line 1227 of file xlogrecovery.c.

1229{
1233 FILE *lfp;
1234 char ch;
1235 char backuptype[20];
1236 char backupfrom[20];
1237 char backuplabel[MAXPGPATH];
1238 char backuptime[128];
1239 uint32 hi,
1240 lo;
1241
1242 /* suppress possible uninitialized-variable warnings */
1244 *backupLabelTLI = 0;
1245 *backupEndRequired = false;
1246 *backupFromStandby = false;
1247
1248 /*
1249 * See if label file is present
1250 */
1252 if (!lfp)
1253 {
1254 if (errno != ENOENT)
1255 ereport(FATAL,
1257 errmsg("could not read file \"%s\": %m",
1259 return false; /* it's not there, all is fine */
1260 }
1261
1262 /*
1263 * Read and parse the START WAL LOCATION and CHECKPOINT lines (this code
1264 * is pretty crude, but we are not expecting any variability in the file
1265 * format).
1266 */
1267 if (fscanf(lfp, "START WAL LOCATION: %X/%08X (file %08X%16s)%c",
1268 &hi, &lo, &tli_from_walseg, startxlogfilename, &ch) != 5 || ch != '\n')
1269 ereport(FATAL,
1271 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
1272 RedoStartLSN = ((uint64) hi) << 32 | lo;
1274 if (fscanf(lfp, "CHECKPOINT LOCATION: %X/%08X%c",
1275 &hi, &lo, &ch) != 3 || ch != '\n')
1276 ereport(FATAL,
1278 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
1279 *checkPointLoc = ((uint64) hi) << 32 | lo;
1281
1282 /*
1283 * BACKUP METHOD lets us know if this was a typical backup ("streamed",
1284 * which could mean either pg_basebackup or the pg_backup_start/stop
1285 * method was used) or if this label came from somewhere else (the only
1286 * other option today being from pg_rewind). If this was a streamed
1287 * backup then we know that we need to play through until we get to the
1288 * end of the WAL which was generated during the backup (at which point we
1289 * will have reached consistency and backupEndRequired will be reset to be
1290 * false).
1291 */
1292 if (fscanf(lfp, "BACKUP METHOD: %19s\n", backuptype) == 1)
1293 {
1294 if (strcmp(backuptype, "streamed") == 0)
1295 *backupEndRequired = true;
1296 }
1297
1298 /*
1299 * BACKUP FROM lets us know if this was from a primary or a standby. If
1300 * it was from a standby, we'll double-check that the control file state
1301 * matches that of a standby.
1302 */
1303 if (fscanf(lfp, "BACKUP FROM: %19s\n", backupfrom) == 1)
1304 {
1305 if (strcmp(backupfrom, "standby") == 0)
1306 *backupFromStandby = true;
1307 }
1308
1309 /*
1310 * Parse START TIME and LABEL. Those are not mandatory fields for recovery
1311 * but checking for their presence is useful for debugging and the next
1312 * sanity checks. Cope also with the fact that the result buffers have a
1313 * pre-allocated size, hence if the backup_label file has been generated
1314 * with strings longer than the maximum assumed here an incorrect parsing
1315 * happens. That's fine as only minor consistency checks are done
1316 * afterwards.
1317 */
1318 if (fscanf(lfp, "START TIME: %127[^\n]\n", backuptime) == 1)
1320 (errmsg_internal("backup time %s in file \"%s\"",
1322
1323 if (fscanf(lfp, "LABEL: %1023[^\n]\n", backuplabel) == 1)
1325 (errmsg_internal("backup label %s in file \"%s\"",
1327
1328 /*
1329 * START TIMELINE is new as of 11. Its parsing is not mandatory, still use
1330 * it as a sanity check if present.
1331 */
1332 if (fscanf(lfp, "START TIMELINE: %u\n", &tli_from_file) == 1)
1333 {
1335 ereport(FATAL,
1337 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE),
1338 errdetail("Timeline ID parsed is %u, but expected %u.",
1340
1342 (errmsg_internal("backup timeline %u in file \"%s\"",
1344 }
1345
1346 if (fscanf(lfp, "INCREMENTAL FROM LSN: %X/%08X\n", &hi, &lo) > 0)
1347 ereport(FATAL,
1349 errmsg("this is an incremental backup, not a data directory"),
1350 errhint("Use pg_combinebackup to reconstruct a valid data directory.")));
1351
1352 if (ferror(lfp) || FreeFile(lfp))
1353 ereport(FATAL,
1355 errmsg("could not read file \"%s\": %m",
1357
1358 return true;
1359}
uint32_t uint32
Definition c.h:546
int FreeFile(FILE *file)
Definition fd.c:2823
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2624

References AllocateFile(), BACKUP_LABEL_FILE, backupEndRequired, DEBUG1, ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), errmsg_internal(), FATAL, fb(), FreeFile(), InvalidXLogRecPtr, MAXFNAMELEN, MAXPGPATH, RedoStartLSN, and RedoStartTLI.

Referenced by InitWalRecovery().

◆ read_tablespace_map()

static bool read_tablespace_map ( List **  tablespaces)
static

Definition at line 1373 of file xlogrecovery.c.

1374{
1376 FILE *lfp;
1377 char str[MAXPGPATH];
1378 int ch,
1379 i,
1380 n;
1381 bool was_backslash;
1382
1383 /*
1384 * See if tablespace_map file is present
1385 */
1387 if (!lfp)
1388 {
1389 if (errno != ENOENT)
1390 ereport(FATAL,
1392 errmsg("could not read file \"%s\": %m",
1393 TABLESPACE_MAP)));
1394 return false; /* it's not there, all is fine */
1395 }
1396
1397 /*
1398 * Read and parse the link name and path lines from tablespace_map file
1399 * (this code is pretty crude, but we are not expecting any variability in
1400 * the file format). De-escape any backslashes that were inserted.
1401 */
1402 i = 0;
1403 was_backslash = false;
1404 while ((ch = fgetc(lfp)) != EOF)
1405 {
1406 if (!was_backslash && (ch == '\n' || ch == '\r'))
1407 {
1408 char *endp;
1409
1410 if (i == 0)
1411 continue; /* \r immediately followed by \n */
1412
1413 /*
1414 * The de-escaped line should contain an OID followed by exactly
1415 * one space followed by a path. The path might start with
1416 * spaces, so don't be too liberal about parsing.
1417 */
1418 str[i] = '\0';
1419 n = 0;
1420 while (str[n] && str[n] != ' ')
1421 n++;
1422 if (n < 1 || n >= i - 1)
1423 ereport(FATAL,
1425 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1426 str[n++] = '\0';
1427
1429 errno = 0;
1430 ti->oid = strtoul(str, &endp, 10);
1431 if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
1432 ereport(FATAL,
1434 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1435 ti->path = pstrdup(str + n);
1436 *tablespaces = lappend(*tablespaces, ti);
1437
1438 i = 0;
1439 continue;
1440 }
1441 else if (!was_backslash && ch == '\\')
1442 was_backslash = true;
1443 else
1444 {
1445 if (i < sizeof(str) - 1)
1446 str[i++] = ch;
1447 was_backslash = false;
1448 }
1449 }
1450
1451 if (i != 0 || was_backslash) /* last line not terminated? */
1452 ereport(FATAL,
1454 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1455
1456 if (ferror(lfp) || FreeFile(lfp))
1457 ereport(FATAL,
1459 errmsg("could not read file \"%s\": %m",
1460 TABLESPACE_MAP)));
1461
1462 return true;
1463}
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339

References AllocateFile(), ereport, errcode(), errcode_for_file_access(), errmsg(), FATAL, fb(), FreeFile(), i, lappend(), MAXPGPATH, palloc0_object, pstrdup(), str, and TABLESPACE_MAP.

Referenced by InitWalRecovery().

◆ ReadCheckpointRecord()

static XLogRecord * ReadCheckpointRecord ( XLogPrefetcher xlogprefetcher,
XLogRecPtr  RecPtr,
TimeLineID  replayTLI 
)
static

Definition at line 4116 of file xlogrecovery.c.

4118{
4119 XLogRecord *record;
4120 uint8 info;
4121
4123
4124 if (!XRecOffIsValid(RecPtr))
4125 {
4126 ereport(LOG,
4127 (errmsg("invalid checkpoint location")));
4128 return NULL;
4129 }
4130
4132 record = ReadRecord(xlogprefetcher, LOG, true, replayTLI);
4133
4134 if (record == NULL)
4135 {
4136 ereport(LOG,
4137 (errmsg("invalid checkpoint record")));
4138 return NULL;
4139 }
4140 if (record->xl_rmid != RM_XLOG_ID)
4141 {
4142 ereport(LOG,
4143 (errmsg("invalid resource manager ID in checkpoint record")));
4144 return NULL;
4145 }
4146 info = record->xl_info & ~XLR_INFO_MASK;
4147 if (info != XLOG_CHECKPOINT_SHUTDOWN &&
4148 info != XLOG_CHECKPOINT_ONLINE)
4149 {
4150 ereport(LOG,
4151 (errmsg("invalid xl_info in checkpoint record")));
4152 return NULL;
4153 }
4155 {
4156 ereport(LOG,
4157 (errmsg("invalid length of checkpoint record")));
4158 return NULL;
4159 }
4160 return record;
4161}
#define XLOG_CHECKPOINT_ONLINE
Definition pg_control.h:70
uint32 xl_tot_len
Definition xlogrecord.h:43
#define XRecOffIsValid(xlrp)
#define SizeOfXLogRecordDataHeaderShort
Definition xlogrecord.h:217
#define SizeOfXLogRecord
Definition xlogrecord.h:55

References Assert, ereport, errmsg(), fb(), LOG, ReadRecord(), SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, XLogRecord::xl_info, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, and XRecOffIsValid.

Referenced by InitWalRecovery().

◆ ReadRecord()

static XLogRecord * ReadRecord ( XLogPrefetcher xlogprefetcher,
int  emode,
bool  fetching_ckpt,
TimeLineID  replayTLI 
)
static

Definition at line 3164 of file xlogrecovery.c.

3166{
3167 XLogRecord *record;
3170
3172
3173 /* Pass through parameters to XLogPageRead */
3174 private->fetching_ckpt = fetching_ckpt;
3175 private->emode = emode;
3176 private->randAccess = !XLogRecPtrIsValid(xlogreader->ReadRecPtr);
3177 private->replayTLI = replayTLI;
3178
3179 /* This is the first attempt to read this page. */
3180 lastSourceFailed = false;
3181
3182 for (;;)
3183 {
3184 char *errormsg;
3185
3186 record = XLogPrefetcherReadRecord(xlogprefetcher, &errormsg);
3187 if (record == NULL)
3188 {
3189 /*
3190 * When we find that WAL ends in an incomplete record, keep track
3191 * of that record. After recovery is done, we'll write a record
3192 * to indicate to downstream WAL readers that that portion is to
3193 * be ignored.
3194 *
3195 * However, when ArchiveRecoveryRequested = true, we're going to
3196 * switch to a new timeline at the end of recovery. We will only
3197 * copy WAL over to the new timeline up to the end of the last
3198 * complete record, so if we did this, we would later create an
3199 * overwrite contrecord in the wrong place, breaking everything.
3200 */
3203 {
3206 }
3207
3208 if (readFile >= 0)
3209 {
3210 close(readFile);
3211 readFile = -1;
3212 }
3213
3214 /*
3215 * We only end up here without a message when XLogPageRead()
3216 * failed - in that case we already logged something. In
3217 * StandbyMode that only happens if we have been triggered, so we
3218 * shouldn't loop anymore in that case.
3219 */
3220 if (errormsg)
3222 (errmsg_internal("%s", errormsg) /* already translated */ ));
3223 }
3224
3225 /*
3226 * Check page TLI is one of the expected values.
3227 */
3229 {
3230 char fname[MAXFNAMELEN];
3231 XLogSegNo segno;
3232 int32 offset;
3233
3237 XLogFileName(fname, xlogreader->seg.ws_tli, segno,
3240 errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%08X, offset %u",
3242 fname,
3244 offset));
3245 record = NULL;
3246 }
3247
3248 if (record)
3249 {
3250 /* Great, got a record */
3251 return record;
3252 }
3253 else
3254 {
3255 /* No valid record available from this source */
3256 lastSourceFailed = true;
3257
3258 /*
3259 * If archive recovery was requested, but we were still doing
3260 * crash recovery, switch to archive recovery and retry using the
3261 * offline archive. We have now replayed all the valid WAL in
3262 * pg_wal, so we are presumably now consistent.
3263 *
3264 * We require that there's at least some valid WAL present in
3265 * pg_wal, however (!fetching_ckpt). We could recover using the
3266 * WAL from the archive, even if pg_wal is completely empty, but
3267 * we'd have no idea how far we'd have to replay to reach
3268 * consistency. So err on the safe side and give up.
3269 */
3271 !fetching_ckpt)
3272 {
3274 (errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
3275 InArchiveRecovery = true;
3278
3281 minRecoveryPointTLI = replayTLI;
3282
3284
3285 /*
3286 * Before we retry, reset lastSourceFailed and currentSource
3287 * so that we will check the archive next.
3288 */
3289 lastSourceFailed = false;
3291
3292 continue;
3293 }
3294
3295 /* In standby mode, loop back to retry. Otherwise, give up. */
3297 continue;
3298 else
3299 return NULL;
3300 }
3301 }
3302}
int32_t int32
Definition c.h:542
XLogRecPtr missingContrecPtr
Definition xlogreader.h:214
XLogRecPtr abortedRecPtr
Definition xlogreader.h:213
TimeLineID latestPageTLI
Definition xlogreader.h:279
XLogRecPtr latestPagePtr
Definition xlogreader.h:278
void * private_data
Definition xlogreader.h:195
void SwitchIntoArchiveRecovery(XLogRecPtr EndRecPtr, TimeLineID replayTLI)
Definition xlog.c:6335
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint64 XLogSegNo
Definition xlogdefs.h:52
XLogRecord * XLogPrefetcherReadRecord(XLogPrefetcher *prefetcher, char **errmsg)
XLogReaderState * XLogPrefetcherGetReader(XLogPrefetcher *prefetcher)
static bool CheckForStandbyTrigger(void)
static bool lastSourceFailed
static XLogSource currentSource
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)

References abortedRecPtr, XLogReaderState::abortedRecPtr, AmStartupProcess, ArchiveRecoveryRequested, Assert, CheckForStandbyTrigger(), CheckRecoveryConsistency(), close, currentSource, DEBUG1, emode_for_corrupt_record(), EnableStandbyMode(), XLogReaderState::EndRecPtr, ereport, errmsg(), errmsg_internal(), expectedTLEs, fb(), InArchiveRecovery, IsUnderPostmaster, lastSourceFailed, XLogReaderState::latestPagePtr, XLogReaderState::latestPageTLI, LSN_FORMAT_ARGS, MAXFNAMELEN, minRecoveryPoint, minRecoveryPointTLI, missingContrecPtr, XLogReaderState::missingContrecPtr, XLogReaderState::private_data, readFile, XLogReaderState::ReadRecPtr, XLogReaderState::seg, StandbyMode, StandbyModeRequested, SwitchIntoArchiveRecovery(), tliInHistory(), wal_segment_size, WALOpenSegment::ws_tli, XLByteToSeg, XLOG_FROM_ANY, XLogFileName(), xlogprefetcher, XLogPrefetcherGetReader(), XLogPrefetcherReadRecord(), xlogreader, XLogRecPtrIsValid, and XLogSegmentOffset.

Referenced by FinishWalRecovery(), InitWalRecovery(), PerformWalRecovery(), and ReadCheckpointRecord().

◆ readRecoverySignalFile()

static void readRecoverySignalFile ( void  )
static

Definition at line 1046 of file xlogrecovery.c.

1047{
1048 struct stat stat_buf;
1049
1051 return;
1052
1053 /*
1054 * Check for old recovery API file: recovery.conf
1055 */
1057 ereport(FATAL,
1059 errmsg("using recovery command file \"%s\" is not supported",
1061
1062 /*
1063 * Remove unused .done file, if present. Ignore if absent.
1064 */
1066
1067 /*
1068 * Check for recovery signal files and if found, fsync them since they
1069 * represent server state information. We don't sweat too much about the
1070 * possibility of fsync failure, however.
1071 *
1072 * If present, standby signal file takes precedence. If neither is present
1073 * then we won't enter archive recovery.
1074 */
1075 if (stat(STANDBY_SIGNAL_FILE, &stat_buf) == 0)
1076 {
1077 int fd;
1078
1080 S_IRUSR | S_IWUSR);
1081 if (fd >= 0)
1082 {
1083 (void) pg_fsync(fd);
1084 close(fd);
1085 }
1087 }
1088 else if (stat(RECOVERY_SIGNAL_FILE, &stat_buf) == 0)
1089 {
1090 int fd;
1091
1093 S_IRUSR | S_IWUSR);
1094 if (fd >= 0)
1095 {
1096 (void) pg_fsync(fd);
1097 close(fd);
1098 }
1100 }
1101
1102 StandbyModeRequested = false;
1105 {
1106 StandbyModeRequested = true;
1108 }
1110 {
1111 StandbyModeRequested = false;
1113 }
1114 else
1115 return;
1116
1117 /*
1118 * We don't support standby mode in standalone backends; that requires
1119 * other processes such as the WAL receiver to be alive.
1120 */
1122 ereport(FATAL,
1124 errmsg("standby mode is not supported by single-user servers")));
1125}
#define PG_BINARY
Definition c.h:1287
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition fd.c:1108
int pg_fsync(int fd)
Definition fd.c:386
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
static int fd(const char *x, int i)
#define S_IRUSR
Definition win32_port.h:279
#define S_IWUSR
Definition win32_port.h:282
#define STANDBY_SIGNAL_FILE
Definition xlog.h:318
#define RECOVERY_SIGNAL_FILE
Definition xlog.h:317
#define RECOVERY_COMMAND_FILE
#define RECOVERY_COMMAND_DONE

References ArchiveRecoveryRequested, BasicOpenFilePerm(), close, ereport, errcode(), errcode_for_file_access(), errmsg(), FATAL, fb(), fd(), IsBootstrapProcessingMode, IsUnderPostmaster, PG_BINARY, pg_fsync(), RECOVERY_COMMAND_DONE, RECOVERY_COMMAND_FILE, RECOVERY_SIGNAL_FILE, recovery_signal_file_found, S_IRUSR, S_IWUSR, STANDBY_SIGNAL_FILE, standby_signal_file_found, StandbyModeRequested, and stat.

Referenced by InitWalRecovery().

◆ recoveryApplyDelay()

static bool recoveryApplyDelay ( XLogReaderState record)
static

Definition at line 3015 of file xlogrecovery.c.

3016{
3020 long msecs;
3021
3022 /* nothing to do if no delay configured */
3023 if (recovery_min_apply_delay <= 0)
3024 return false;
3025
3026 /* no delay is applied on a database not yet consistent */
3027 if (!reachedConsistency)
3028 return false;
3029
3030 /* nothing to do if crash recovery is requested */
3032 return false;
3033
3034 /*
3035 * Is it a COMMIT record?
3036 *
3037 * We deliberately choose not to delay aborts since they have no effect on
3038 * MVCC. We already allow replay of records that don't have a timestamp,
3039 * so there is already opportunity for issues caused by early conflicts on
3040 * standbys.
3041 */
3042 if (XLogRecGetRmid(record) != RM_XACT_ID)
3043 return false;
3044
3046
3047 if (xact_info != XLOG_XACT_COMMIT &&
3049 return false;
3050
3051 if (!getRecordTimestamp(record, &xtime))
3052 return false;
3053
3055
3056 /*
3057 * Exit without arming the latch if it's already past time to apply this
3058 * record
3059 */
3061 if (msecs <= 0)
3062 return false;
3063
3064 while (true)
3065 {
3067
3068 /* This might change recovery_min_apply_delay. */
3070
3072 break;
3073
3074 /*
3075 * Recalculate delayUntil as recovery_min_apply_delay could have
3076 * changed while waiting in this loop.
3077 */
3079
3080 /*
3081 * Wait for difference between GetCurrentTimestamp() and delayUntil.
3082 */
3084 delayUntil);
3085
3086 if (msecs <= 0)
3087 break;
3088
3089 elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs);
3090
3093 msecs,
3095 }
3096 return true;
3097}
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.c:1757
#define DEBUG2
Definition elog.h:29
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
#define TimestampTzPlusMilliseconds(tz, ms)
Definition timestamp.h:85
#define WL_TIMEOUT
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET
static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime)
int recovery_min_apply_delay

References ArchiveRecoveryRequested, CheckForStandbyTrigger(), DEBUG2, elog, fb(), GetCurrentTimestamp(), getRecordTimestamp(), ProcessStartupProcInterrupts(), reachedConsistency, recovery_min_apply_delay, XLogRecoveryCtlData::recoveryWakeupLatch, ResetLatch(), TimestampDifferenceMilliseconds(), TimestampTzPlusMilliseconds, WaitLatch(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, WL_TIMEOUT, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_PREPARED, XLOG_XACT_OPMASK, XLogRecGetInfo, XLogRecGetRmid, and XLogRecoveryCtl.

Referenced by PerformWalRecovery().

◆ recoveryPausesHere()

static void recoveryPausesHere ( bool  endOfRecovery)
static

Definition at line 2958 of file xlogrecovery.c.

2959{
2960 /* Don't pause unless users can connect! */
2962 return;
2963
2964 /* Don't pause after standby promotion has been triggered */
2966 return;
2967
2968 if (endOfRecovery)
2969 ereport(LOG,
2970 (errmsg("pausing at the end of recovery"),
2971 errhint("Execute pg_wal_replay_resume() to promote.")));
2972 else
2973 ereport(LOG,
2974 (errmsg("recovery has paused"),
2975 errhint("Execute pg_wal_replay_resume() to continue.")));
2976
2977 /* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */
2979 {
2982 return;
2983
2984 /*
2985 * If recovery pause is requested then set it paused. While we are in
2986 * the loop, user might resume and pause again so set this every time.
2987 */
2989
2990 /*
2991 * We wait on a condition variable that will wake us as soon as the
2992 * pause ends, but we use a timeout so we can check the above exit
2993 * condition periodically too.
2994 */
2997 }
2999}
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
ConditionVariable recoveryNotPausedCV
static void ConfirmRecoveryPaused(void)
RecoveryPauseState GetRecoveryPauseState(void)

References CheckForStandbyTrigger(), ConditionVariableCancelSleep(), ConditionVariableTimedSleep(), ConfirmRecoveryPaused(), ereport, errhint(), errmsg(), fb(), GetRecoveryPauseState(), LocalHotStandbyActive, LocalPromoteIsTriggered, LOG, ProcessStartupProcInterrupts(), RECOVERY_NOT_PAUSED, XLogRecoveryCtlData::recoveryNotPausedCV, and XLogRecoveryCtl.

Referenced by PerformWalRecovery(), and WaitForWALToBecomeAvailable().

◆ RecoveryRequiresIntParameter()

void RecoveryRequiresIntParameter ( const char param_name,
int  currValue,
int  minValue 
)

Definition at line 4724 of file xlogrecovery.c.

4725{
4726 if (currValue < minValue)
4727 {
4729 {
4730 bool warned_for_promote = false;
4731
4734 errmsg("hot standby is not possible because of insufficient parameter settings"),
4735 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4736 param_name,
4737 currValue,
4738 minValue)));
4739
4740 SetRecoveryPause(true);
4741
4742 ereport(LOG,
4743 (errmsg("recovery has paused"),
4744 errdetail("If recovery is unpaused, the server will shut down."),
4745 errhint("You can then restart the server after making the necessary configuration changes.")));
4746
4748 {
4750
4752 {
4753 if (!warned_for_promote)
4756 errmsg("promotion is not possible because of insufficient parameter settings"),
4757
4758 /*
4759 * Repeat the detail from above so it's easy to find
4760 * in the log.
4761 */
4762 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4763 param_name,
4764 currValue,
4765 minValue),
4766 errhint("Restart the server after making the necessary configuration changes.")));
4767 warned_for_promote = true;
4768 }
4769
4770 /*
4771 * If recovery pause is requested then set it paused. While
4772 * we are in the loop, user might resume and pause again so
4773 * set this every time.
4774 */
4776
4777 /*
4778 * We wait on a condition variable that will wake us as soon
4779 * as the pause ends, but we use a timeout so we can check the
4780 * above conditions periodically too.
4781 */
4784 }
4786 }
4787
4788 ereport(FATAL,
4790 errmsg("recovery aborted because of insufficient parameter settings"),
4791 /* Repeat the detail from above so it's easy to find in the log. */
4792 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4793 param_name,
4794 currValue,
4795 minValue),
4796 errhint("You can restart the server after making the necessary configuration changes.")));
4797 }
4798}
static bool HotStandbyActiveInReplay(void)

References CheckForStandbyTrigger(), ConditionVariableCancelSleep(), ConditionVariableTimedSleep(), ConfirmRecoveryPaused(), ereport, errcode(), errdetail(), errhint(), errmsg(), FATAL, fb(), GetRecoveryPauseState(), HotStandbyActiveInReplay(), LOG, ProcessStartupProcInterrupts(), RECOVERY_NOT_PAUSED, XLogRecoveryCtlData::recoveryNotPausedCV, SetRecoveryPause(), WARNING, and XLogRecoveryCtl.

Referenced by CheckRequiredParameterValues().

◆ recoveryStopsAfter()

static bool recoveryStopsAfter ( XLogReaderState record)
static

Definition at line 2759 of file xlogrecovery.c.

2760{
2761 uint8 info;
2763 uint8 rmid;
2765
2766 /*
2767 * Ignore recovery target settings when not in archive recovery (meaning
2768 * we are in crash recovery).
2769 */
2771 return false;
2772
2773 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2774 rmid = XLogRecGetRmid(record);
2775
2776 /*
2777 * There can be many restore points that share the same name; we stop at
2778 * the first one.
2779 */
2781 rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2782 {
2784
2786
2788 {
2789 recoveryStopAfter = true;
2794
2795 ereport(LOG,
2796 (errmsg("recovery stopping at restore point \"%s\", time %s",
2799 return true;
2800 }
2801 }
2802
2803 /* Check if the target LSN has been reached */
2806 record->ReadRecPtr >= recoveryTargetLSN)
2807 {
2808 recoveryStopAfter = true;
2810 recoveryStopLSN = record->ReadRecPtr;
2811 recoveryStopTime = 0;
2812 recoveryStopName[0] = '\0';
2813 ereport(LOG,
2814 errmsg("recovery stopping after WAL location (LSN) \"%X/%08X\"",
2816 return true;
2817 }
2818
2819 if (rmid != RM_XACT_ID)
2820 return false;
2821
2822 xact_info = info & XLOG_XACT_OPMASK;
2823
2824 if (xact_info == XLOG_XACT_COMMIT ||
2828 {
2830
2831 /* Update the last applied transaction timestamp */
2832 if (getRecordTimestamp(record, &recordXtime))
2834
2835 /* Extract the XID of the committed/aborted transaction */
2837 {
2840
2842 xlrec,
2843 &parsed);
2844 recordXid = parsed.twophase_xid;
2845 }
2847 {
2850
2852 xlrec,
2853 &parsed);
2854 recordXid = parsed.twophase_xid;
2855 }
2856 else
2857 recordXid = XLogRecGetXid(record);
2858
2859 /*
2860 * There can be only one transaction end record with this exact
2861 * transactionid
2862 *
2863 * when testing for an xid, we MUST test for equality only, since
2864 * transactions are numbered in the order they start, not the order
2865 * they complete. A higher numbered xid will complete before you about
2866 * 50% of the time...
2867 */
2870 {
2871 recoveryStopAfter = true;
2875 recoveryStopName[0] = '\0';
2876
2877 if (xact_info == XLOG_XACT_COMMIT ||
2879 {
2880 ereport(LOG,
2881 (errmsg("recovery stopping after commit of transaction %u, time %s",
2884 }
2885 else if (xact_info == XLOG_XACT_ABORT ||
2887 {
2888 ereport(LOG,
2889 (errmsg("recovery stopping after abort of transaction %u, time %s",
2892 }
2893 return true;
2894 }
2895 }
2896
2897 /* Check if we should stop as soon as reaching consistency */
2899 {
2900 ereport(LOG,
2901 (errmsg("recovery stopping after reaching consistency")));
2902
2903 recoveryStopAfter = true;
2905 recoveryStopTime = 0;
2907 recoveryStopName[0] = '\0';
2908 return true;
2909 }
2910
2911 return false;
2912}
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
#define InvalidTransactionId
Definition transam.h:31
void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
Definition xactdesc.c:35
void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
Definition xactdesc.c:141
#define XLogRecGetXid(decoder)
Definition xlogreader.h:411
bool recoveryTargetInclusive
static void SetLatestXTime(TimestampTz xtime)

References ArchiveRecoveryRequested, ereport, errmsg(), fb(), getRecordTimestamp(), InvalidTransactionId, InvalidXLogRecPtr, LOG, LSN_FORMAT_ARGS, MAXFNAMELEN, ParseAbortRecord(), ParseCommitRecord(), reachedConsistency, XLogReaderState::ReadRecPtr, RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_LSN, RECOVERY_TARGET_NAME, RECOVERY_TARGET_XID, recoveryStopAfter, recoveryStopLSN, recoveryStopName, recoveryStopTime, recoveryStopXid, recoveryTarget, recoveryTargetInclusive, recoveryTargetLSN, recoveryTargetName, recoveryTargetXid, SetLatestXTime(), strlcpy(), timestamptz_to_str(), XLOG_RESTORE_POINT, XLOG_XACT_ABORT, XLOG_XACT_ABORT_PREPARED, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_PREPARED, XLOG_XACT_OPMASK, XLogRecGetData, XLogRecGetInfo, XLogRecGetRmid, and XLogRecGetXid.

Referenced by PerformWalRecovery().

◆ recoveryStopsBefore()

static bool recoveryStopsBefore ( XLogReaderState record)
static

Definition at line 2606 of file xlogrecovery.c.

2607{
2608 bool stopsHere = false;
2610 bool isCommit;
2613
2614 /*
2615 * Ignore recovery target settings when not in archive recovery (meaning
2616 * we are in crash recovery).
2617 */
2619 return false;
2620
2621 /* Check if we should stop as soon as reaching consistency */
2623 {
2624 ereport(LOG,
2625 (errmsg("recovery stopping after reaching consistency")));
2626
2627 recoveryStopAfter = false;
2630 recoveryStopTime = 0;
2631 recoveryStopName[0] = '\0';
2632 return true;
2633 }
2634
2635 /* Check if target LSN has been reached */
2638 record->ReadRecPtr >= recoveryTargetLSN)
2639 {
2640 recoveryStopAfter = false;
2642 recoveryStopLSN = record->ReadRecPtr;
2643 recoveryStopTime = 0;
2644 recoveryStopName[0] = '\0';
2645 ereport(LOG,
2646 errmsg("recovery stopping before WAL location (LSN) \"%X/%08X\"",
2648 return true;
2649 }
2650
2651 /* Otherwise we only consider stopping before COMMIT or ABORT records. */
2652 if (XLogRecGetRmid(record) != RM_XACT_ID)
2653 return false;
2654
2656
2658 {
2659 isCommit = true;
2660 recordXid = XLogRecGetXid(record);
2661 }
2663 {
2666
2667 isCommit = true;
2669 xlrec,
2670 &parsed);
2671 recordXid = parsed.twophase_xid;
2672 }
2673 else if (xact_info == XLOG_XACT_ABORT)
2674 {
2675 isCommit = false;
2676 recordXid = XLogRecGetXid(record);
2677 }
2679 {
2682
2683 isCommit = false;
2685 xlrec,
2686 &parsed);
2687 recordXid = parsed.twophase_xid;
2688 }
2689 else
2690 return false;
2691
2693 {
2694 /*
2695 * There can be only one transaction end record with this exact
2696 * transactionid
2697 *
2698 * when testing for an xid, we MUST test for equality only, since
2699 * transactions are numbered in the order they start, not the order
2700 * they complete. A higher numbered xid will complete before you about
2701 * 50% of the time...
2702 */
2704 }
2705
2706 /*
2707 * Note: we must fetch recordXtime regardless of recoveryTarget setting.
2708 * We don't expect getRecordTimestamp ever to fail, since we already know
2709 * this is a commit or abort record; but test its result anyway.
2710 */
2711 if (getRecordTimestamp(record, &recordXtime) &&
2713 {
2714 /*
2715 * There can be many transactions that share the same commit time, so
2716 * we stop after the last one, if we are inclusive, or stop at the
2717 * first one if we are exclusive
2718 */
2721 else
2723 }
2724
2725 if (stopsHere)
2726 {
2727 recoveryStopAfter = false;
2731 recoveryStopName[0] = '\0';
2732
2733 if (isCommit)
2734 {
2735 ereport(LOG,
2736 (errmsg("recovery stopping before commit of transaction %u, time %s",
2739 }
2740 else
2741 {
2742 ereport(LOG,
2743 (errmsg("recovery stopping before abort of transaction %u, time %s",
2746 }
2747 }
2748
2749 return stopsHere;
2750}

References ArchiveRecoveryRequested, ereport, errmsg(), fb(), getRecordTimestamp(), InvalidTransactionId, InvalidXLogRecPtr, LOG, LSN_FORMAT_ARGS, ParseAbortRecord(), ParseCommitRecord(), reachedConsistency, XLogReaderState::ReadRecPtr, RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_LSN, RECOVERY_TARGET_TIME, RECOVERY_TARGET_XID, recoveryStopAfter, recoveryStopLSN, recoveryStopName, recoveryStopTime, recoveryStopXid, recoveryTarget, recoveryTargetInclusive, recoveryTargetLSN, recoveryTargetTime, recoveryTargetXid, timestamptz_to_str(), XLOG_XACT_ABORT, XLOG_XACT_ABORT_PREPARED, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_PREPARED, XLOG_XACT_OPMASK, XLogRecGetData, XLogRecGetInfo, XLogRecGetRmid, and XLogRecGetXid.

Referenced by PerformWalRecovery().

◆ RemovePromoteSignalFiles()

void RemovePromoteSignalFiles ( void  )

Definition at line 4519 of file xlogrecovery.c.

4520{
4522}

References fb(), and PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ rescanLatestTimeLine()

static bool rescanLatestTimeLine ( TimeLineID  replayTLI,
XLogRecPtr  replayLSN 
)
static

Definition at line 4171 of file xlogrecovery.c.

4172{
4174 bool found;
4175 ListCell *cell;
4179
4182 {
4183 /* No new timelines found */
4184 return false;
4185 }
4186
4187 /*
4188 * Determine the list of expected TLIs for the new TLI
4189 */
4190
4192
4193 /*
4194 * If the current timeline is not part of the history of the new timeline,
4195 * we cannot proceed to it.
4196 */
4197 found = false;
4198 foreach(cell, newExpectedTLEs)
4199 {
4201
4202 if (currentTle->tli == recoveryTargetTLI)
4203 {
4204 found = true;
4205 break;
4206 }
4207 }
4208 if (!found)
4209 {
4210 ereport(LOG,
4211 (errmsg("new timeline %u is not a child of database system timeline %u",
4212 newtarget,
4213 replayTLI)));
4214 return false;
4215 }
4216
4217 /*
4218 * The current timeline was found in the history file, but check that the
4219 * next timeline was forked off from it *after* the current recovery
4220 * location.
4221 */
4222 if (currentTle->end < replayLSN)
4223 {
4224 ereport(LOG,
4225 errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%08X",
4226 newtarget,
4227 replayTLI,
4229 return false;
4230 }
4231
4232 /* The new timeline history seems valid. Switch target */
4236
4237 /*
4238 * As in StartupXLOG(), try to ensure we have all the history files
4239 * between the old target and new target in pg_wal.
4240 */
4242
4243 ereport(LOG,
4244 (errmsg("new target timeline is %u",
4246
4247 return true;
4248}
List * readTimeLineHistory(TimeLineID targetTLI)
Definition timeline.c:76
TimeLineID findNewestTimeLine(TimeLineID startTLI)
Definition timeline.c:264
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
Definition timeline.c:50
void list_free_deep(List *list)
Definition list.c:1560

References ereport, errmsg(), expectedTLEs, fb(), findNewestTimeLine(), lfirst, list_free_deep(), LOG, LSN_FORMAT_ARGS, readTimeLineHistory(), recoveryTargetTLI, and restoreTimeLineHistoryFiles().

Referenced by WaitForWALToBecomeAvailable().

◆ rm_redo_error_callback()

static void rm_redo_error_callback ( void arg)
static

Definition at line 2308 of file xlogrecovery.c.

2309{
2310 XLogReaderState *record = (XLogReaderState *) arg;
2312
2314 xlog_outdesc(&buf, record);
2315 xlog_block_info(&buf, record);
2316
2317 /* translator: %s is a WAL record description */
2318 errcontext("WAL redo at %X/%08X for %s",
2319 LSN_FORMAT_ARGS(record->ReadRecPtr),
2320 buf.data);
2321
2322 pfree(buf.data);
2323}
#define errcontext
Definition elog.h:198
void * arg
static void xlog_block_info(StringInfo buf, XLogReaderState *record)

References arg, buf, errcontext, initStringInfo(), LSN_FORMAT_ARGS, pfree(), XLogReaderState::ReadRecPtr, xlog_block_info(), and xlog_outdesc().

Referenced by ApplyWalRecord().

◆ SetCurrentChunkStartTime()

◆ SetLatestXTime()

◆ SetPromoteIsTriggered()

static void SetPromoteIsTriggered ( void  )
static

Definition at line 4477 of file xlogrecovery.c.

4478{
4482
4483 /*
4484 * Mark the recovery pause state as 'not paused' because the paused state
4485 * ends and promotion continues if a promotion is triggered while recovery
4486 * is paused. Otherwise pg_get_wal_replay_pause_state() can mistakenly
4487 * return 'paused' while a promotion is ongoing.
4488 */
4489 SetRecoveryPause(false);
4490
4492}

References XLogRecoveryCtlData::info_lck, LocalPromoteIsTriggered, SetRecoveryPause(), XLogRecoveryCtlData::SharedPromoteIsTriggered, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by CheckForStandbyTrigger().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1627 of file xlogrecovery.c.

1628{
1629 char recoveryPath[MAXPGPATH];
1630
1631 /* Final update of pg_stat_recovery_prefetch. */
1633
1634 /* Shut down xlogreader */
1635 if (readFile >= 0)
1636 {
1637 close(readFile);
1638 readFile = -1;
1639 }
1643
1645 {
1646 /*
1647 * Since there might be a partial WAL segment named RECOVERYXLOG, get
1648 * rid of it.
1649 */
1650 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1651 unlink(recoveryPath); /* ignore any error */
1652
1653 /* Get rid of any remaining recovered timeline-history file, too */
1654 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1655 unlink(recoveryPath); /* ignore any error */
1656 }
1657
1658 /*
1659 * We don't need the latch anymore. It's not strictly necessary to disown
1660 * it, but let's do it for the sake of tidiness.
1661 */
1664}
void DisownLatch(Latch *latch)
Definition latch.c:144
#define XLOGDIR
void XLogPrefetcherComputeStats(XLogPrefetcher *prefetcher)
void XLogPrefetcherFree(XLogPrefetcher *prefetcher)
void XLogReaderFree(XLogReaderState *state)
Definition xlogreader.c:162

References ArchiveRecoveryRequested, close, DisownLatch(), fb(), MAXPGPATH, pfree(), XLogReaderState::private_data, readFile, XLogRecoveryCtlData::recoveryWakeupLatch, snprintf, XLOGDIR, xlogprefetcher, XLogPrefetcherComputeStats(), XLogPrefetcherFree(), xlogreader, XLogReaderFree(), and XLogRecoveryCtl.

Referenced by StartupXLOG().

◆ StartupRequestWalReceiverRestart()

void StartupRequestWalReceiverRestart ( void  )

Definition at line 4440 of file xlogrecovery.c.

4441{
4443 {
4444 ereport(LOG,
4445 (errmsg("WAL receiver process shutdown requested")));
4446
4447 pendingWalRcvRestart = true;
4448 }
4449}
bool WalRcvRunning(void)
static bool pendingWalRcvRestart

References currentSource, ereport, errmsg(), LOG, pendingWalRcvRestart, WalRcvRunning(), and XLOG_FROM_STREAM.

Referenced by StartupRereadConfig().

◆ validateRecoveryParameters()

static void validateRecoveryParameters ( void  )
static

Definition at line 1128 of file xlogrecovery.c.

1129{
1131 return;
1132
1133 /*
1134 * Check for compulsory parameters
1135 */
1137 {
1138 if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
1141 (errmsg("specified neither \"primary_conninfo\" nor \"restore_command\""),
1142 errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1143 }
1144 else
1145 {
1148 ereport(FATAL,
1150 errmsg("must specify \"restore_command\" when standby mode is not enabled")));
1151 }
1152
1153 /*
1154 * Override any inconsistent requests. Note that this is a change of
1155 * behaviour in 9.5; prior to this we simply ignored a request to pause if
1156 * hot_standby = off, which was surprising behaviour.
1157 */
1161
1162 /*
1163 * Final parsing of recovery_target_time string; see also
1164 * check_recovery_target_time().
1165 */
1167 {
1171 Int32GetDatum(-1)));
1172 }
1173
1174 /*
1175 * If user specified recovery_target_timeline, validate it or compute the
1176 * "latest" value. We can't do this until after we've gotten the restore
1177 * command and set InArchiveRecovery, because we need to fetch timeline
1178 * history files from the archive.
1179 */
1181 {
1183
1184 /* Timeline 1 does not have a history file, all else should */
1185 if (rtli != 1 && !existsTimeLineHistory(rtli))
1186 ereport(FATAL,
1188 errmsg("recovery target timeline %u does not exist",
1189 rtli)));
1191 }
1193 {
1194 /* We start the "latest" search from pg_control's timeline */
1196 }
1197 else
1198 {
1199 /*
1200 * else we just use the recoveryTargetTLI as already read from
1201 * ControlFile
1202 */
1204 }
1205}
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition timeline.c:222
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition timestamp.c:418
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:688
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
#define InvalidOid
static TimestampTz DatumGetTimestampTz(Datum X)
Definition timestamp.h:34
bool EnableHotStandby
Definition xlog.c:124
char * recoveryRestoreCommand
char * recovery_target_time_string
char * PrimaryConnInfo

References ArchiveRecoveryRequested, Assert, CStringGetDatum(), DatumGetTimestampTz(), DirectFunctionCall3, EnableHotStandby, ereport, errcode(), errhint(), errmsg(), existsTimeLineHistory(), FATAL, fb(), findNewestTimeLine(), Int32GetDatum(), InvalidOid, ObjectIdGetDatum(), PrimaryConnInfo, RECOVERY_TARGET_ACTION_PAUSE, RECOVERY_TARGET_ACTION_SHUTDOWN, RECOVERY_TARGET_TIME, recovery_target_time_string, RECOVERY_TARGET_TIMELINE_CONTROLFILE, RECOVERY_TARGET_TIMELINE_LATEST, RECOVERY_TARGET_TIMELINE_NUMERIC, recoveryRestoreCommand, recoveryTarget, recoveryTargetAction, recoveryTargetTime, recoveryTargetTimeLineGoal, recoveryTargetTLI, recoveryTargetTLIRequested, StandbyModeRequested, timestamptz_in(), and WARNING.

Referenced by InitWalRecovery().

◆ verifyBackupPageConsistency()

static void verifyBackupPageConsistency ( XLogReaderState record)
static

Definition at line 2494 of file xlogrecovery.c.

2495{
2497 RelFileLocator rlocator;
2498 ForkNumber forknum;
2499 BlockNumber blkno;
2500 int block_id;
2501
2502 /* Records with no backup blocks have no need for consistency checks. */
2503 if (!XLogRecHasAnyBlockRefs(record))
2504 return;
2505
2507
2508 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2509 {
2510 Buffer buf;
2511 Page page;
2512
2514 &rlocator, &forknum, &blkno, NULL))
2515 {
2516 /*
2517 * WAL record doesn't contain a block reference with the given id.
2518 * Do nothing.
2519 */
2520 continue;
2521 }
2522
2524
2525 if (XLogRecBlockImageApply(record, block_id))
2526 {
2527 /*
2528 * WAL record has already applied the page, so bypass the
2529 * consistency check as that would result in comparing the full
2530 * page stored in the record with itself.
2531 */
2532 continue;
2533 }
2534
2535 /*
2536 * Read the contents from the current buffer and store it in a
2537 * temporary page.
2538 */
2539 buf = XLogReadBufferExtended(rlocator, forknum, blkno,
2542 if (!BufferIsValid(buf))
2543 continue;
2544
2546 page = BufferGetPage(buf);
2547
2548 /*
2549 * Take a copy of the local page where WAL has been applied to have a
2550 * comparison base before masking it...
2551 */
2553
2554 /* No need for this page anymore now that a copy is in. */
2556
2557 /*
2558 * If the block LSN is already ahead of this WAL record, we can't
2559 * expect contents to match. This can happen if recovery is
2560 * restarted.
2561 */
2563 continue;
2564
2565 /*
2566 * Read the contents from the backup copy, stored in WAL record and
2567 * store it in a temporary page. There is no need to allocate a new
2568 * page here, a local buffer is fine to hold its contents and a mask
2569 * can be directly applied on it.
2570 */
2572 ereport(ERROR,
2574 errmsg_internal("%s", record->errormsg_buf)));
2575
2576 /*
2577 * If masking function is defined, mask both the primary and replay
2578 * images
2579 */
2580 if (rmgr.rm_mask != NULL)
2581 {
2582 rmgr.rm_mask(replay_image_masked, blkno);
2583 rmgr.rm_mask(primary_image_masked, blkno);
2584 }
2585
2586 /* Time to compare the primary and replay images. */
2588 {
2589 elog(FATAL,
2590 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2591 rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
2592 forknum, blkno);
2593 }
2594 }
2595}
uint32 BlockNumber
Definition block.h:31
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5518
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:466
@ BUFFER_LOCK_EXCLUSIVE
Definition bufmgr.h:220
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:328
@ RBM_NORMAL_NO_LOG
Definition bufmgr.h:52
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:417
PageData * Page
Definition bufpage.h:81
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:385
ForkNumber
Definition relpath.h:56
RelFileNumber relNumber
char * errormsg_buf
Definition xlogreader.h:310
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
#define XLogRecBlockImageApply(decoder, block_id)
Definition xlogreader.h:424
#define XLogRecMaxBlockId(decoder)
Definition xlogreader.h:417
#define XLogRecHasBlockImage(decoder, block_id)
Definition xlogreader.h:422
#define XLogRecHasAnyBlockRefs(decoder)
Definition xlogreader.h:416
Buffer XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)
Definition xlogutils.c:460

References Assert, buf, BUFFER_LOCK_EXCLUSIVE, BufferGetPage(), BufferIsValid(), RelFileLocator::dbOid, elog, XLogReaderState::EndRecPtr, ereport, errcode(), errmsg_internal(), ERROR, XLogReaderState::errormsg_buf, FATAL, fb(), GetRmgr(), InvalidBuffer, LockBuffer(), PageGetLSN(), primary_image_masked, RBM_NORMAL_NO_LOG, RelFileLocator::relNumber, replay_image_masked, RestoreBlockImage(), RelFileLocator::spcOid, UnlockReleaseBuffer(), XLogReadBufferExtended(), XLogRecBlockImageApply, XLogRecGetBlockTagExtended(), XLogRecGetInfo, XLogRecGetRmid, XLogRecHasAnyBlockRefs, XLogRecHasBlockImage, XLogRecMaxBlockId, and XLR_CHECK_CONSISTENCY.

Referenced by ApplyWalRecord().

◆ WaitForWALToBecomeAvailable()

static XLogPageReadResult WaitForWALToBecomeAvailable ( XLogRecPtr  RecPtr,
bool  randAccess,
bool  fetching_ckpt,
XLogRecPtr  tliRecPtr,
TimeLineID  replayTLI,
XLogRecPtr  replayLSN,
bool  nonblocking 
)
static

Definition at line 3590 of file xlogrecovery.c.

3594{
3595 static TimestampTz last_fail_time = 0;
3597 bool streaming_reply_sent = false;
3598
3599 /*-------
3600 * Standby mode is implemented by a state machine:
3601 *
3602 * 1. Read from either archive or pg_wal (XLOG_FROM_ARCHIVE), or just
3603 * pg_wal (XLOG_FROM_PG_WAL)
3604 * 2. Check for promotion trigger request
3605 * 3. Read from primary server via walreceiver (XLOG_FROM_STREAM)
3606 * 4. Rescan timelines
3607 * 5. Sleep wal_retrieve_retry_interval milliseconds, and loop back to 1.
3608 *
3609 * Failure to read from the current source advances the state machine to
3610 * the next state.
3611 *
3612 * 'currentSource' indicates the current state. There are no currentSource
3613 * values for "check trigger", "rescan timelines", and "sleep" states,
3614 * those actions are taken when reading from the previous source fails, as
3615 * part of advancing to the next state.
3616 *
3617 * If standby mode is turned off while reading WAL from stream, we move
3618 * to XLOG_FROM_ARCHIVE and reset lastSourceFailed, to force fetching
3619 * the files (which would be required at end of recovery, e.g., timeline
3620 * history file) from archive or pg_wal. We don't need to kill WAL receiver
3621 * here because it's already stopped when standby mode is turned off at
3622 * the end of recovery.
3623 *-------
3624 */
3625 if (!InArchiveRecovery)
3627 else if (currentSource == XLOG_FROM_ANY ||
3629 {
3630 lastSourceFailed = false;
3632 }
3633
3634 for (;;)
3635 {
3637 bool startWalReceiver = false;
3638
3639 /*
3640 * First check if we failed to read from the current source, and
3641 * advance the state machine if so. The failure to read might've
3642 * happened outside this function, e.g when a CRC check fails on a
3643 * record, or within this loop.
3644 */
3645 if (lastSourceFailed)
3646 {
3647 /*
3648 * Don't allow any retry loops to occur during nonblocking
3649 * readahead. Let the caller process everything that has been
3650 * decoded already first.
3651 */
3652 if (nonblocking)
3653 return XLREAD_WOULDBLOCK;
3654
3655 switch (currentSource)
3656 {
3657 case XLOG_FROM_ARCHIVE:
3658 case XLOG_FROM_PG_WAL:
3659
3660 /*
3661 * Check to see if promotion is requested. Note that we do
3662 * this only after failure, so when you promote, we still
3663 * finish replaying as much as we can from archive and
3664 * pg_wal before failover.
3665 */
3667 {
3669 return XLREAD_FAIL;
3670 }
3671
3672 /*
3673 * Not in standby mode, and we've now tried the archive
3674 * and pg_wal.
3675 */
3676 if (!StandbyMode)
3677 return XLREAD_FAIL;
3678
3679 /*
3680 * Move to XLOG_FROM_STREAM state, and set to start a
3681 * walreceiver if necessary.
3682 */
3684 startWalReceiver = true;
3685 break;
3686
3687 case XLOG_FROM_STREAM:
3688
3689 /*
3690 * Failure while streaming. Most likely, we got here
3691 * because streaming replication was terminated, or
3692 * promotion was triggered. But we also get here if we
3693 * find an invalid record in the WAL streamed from the
3694 * primary, in which case something is seriously wrong.
3695 * There's little chance that the problem will just go
3696 * away, but PANIC is not good for availability either,
3697 * especially in hot standby mode. So, we treat that the
3698 * same as disconnection, and retry from archive/pg_wal
3699 * again. The WAL in the archive should be identical to
3700 * what was streamed, so it's unlikely that it helps, but
3701 * one can hope...
3702 */
3703
3704 /*
3705 * We should be able to move to XLOG_FROM_STREAM only in
3706 * standby mode.
3707 */
3709
3710 /*
3711 * Before we leave XLOG_FROM_STREAM state, make sure that
3712 * walreceiver is not active, so that it won't overwrite
3713 * WAL that we restore from archive.
3714 *
3715 * If walreceiver is actively streaming (or attempting to
3716 * connect), we must shut it down. However, if it's
3717 * already in WAITING state (e.g., due to timeline
3718 * divergence), we only need to reset the install flag to
3719 * allow archive restoration.
3720 */
3721 if (WalRcvStreaming())
3723 else
3724 {
3725 /*
3726 * WALRCV_STOPPING state is a transient state while
3727 * the startup process is in ShutdownWalRcv(). It
3728 * should never appear here since we would be waiting
3729 * for the walreceiver to reach WALRCV_STOPPED in that
3730 * case.
3731 */
3734 }
3735
3736 /*
3737 * Before we sleep, re-scan for possible new timelines if
3738 * we were requested to recover to the latest timeline.
3739 */
3741 {
3742 if (rescanLatestTimeLine(replayTLI, replayLSN))
3743 {
3745 break;
3746 }
3747 }
3748
3749 /*
3750 * XLOG_FROM_STREAM is the last state in our state
3751 * machine, so we've exhausted all the options for
3752 * obtaining the requested WAL. We're going to loop back
3753 * and retry from the archive, but if it hasn't been long
3754 * since last attempt, sleep wal_retrieve_retry_interval
3755 * milliseconds to avoid busy-waiting.
3756 */
3760 {
3761 long wait_time;
3762
3765
3766 elog(LOG, "waiting for WAL to become available at %X/%08X",
3768
3769 /* Do background tasks that might benefit us later. */
3771
3775 wait_time,
3779
3780 /* Handle interrupt signals of startup process */
3782 }
3785 break;
3786
3787 default:
3788 elog(ERROR, "unexpected WAL source %d", currentSource);
3789 }
3790 }
3791 else if (currentSource == XLOG_FROM_PG_WAL)
3792 {
3793 /*
3794 * We just successfully read a file in pg_wal. We prefer files in
3795 * the archive over ones in pg_wal, so try the next file again
3796 * from the archive first.
3797 */
3800 }
3801
3802 if (currentSource != oldSource)
3803 elog(DEBUG2, "switched WAL source from %s to %s after %s",
3805 lastSourceFailed ? "failure" : "success");
3806
3807 /*
3808 * We've now handled possible failure. Try to read from the chosen
3809 * source.
3810 */
3811 lastSourceFailed = false;
3812
3813 switch (currentSource)
3814 {
3815 case XLOG_FROM_ARCHIVE:
3816 case XLOG_FROM_PG_WAL:
3817
3818 /*
3819 * WAL receiver must not be running when reading WAL from
3820 * archive or pg_wal.
3821 */
3823
3824 /* Close any old file we might have open. */
3825 if (readFile >= 0)
3826 {
3827 close(readFile);
3828 readFile = -1;
3829 }
3830 /* Reset curFileTLI if random fetch. */
3831 if (randAccess)
3832 curFileTLI = 0;
3833
3834 /*
3835 * Try to restore the file from archive, or read an existing
3836 * file from pg_wal.
3837 */
3841 if (readFile >= 0)
3842 return XLREAD_SUCCESS; /* success! */
3843
3844 /*
3845 * Nope, not found in archive or pg_wal.
3846 */
3847 lastSourceFailed = true;
3848 break;
3849
3850 case XLOG_FROM_STREAM:
3851 {
3852 bool havedata;
3853
3854 /*
3855 * We should be able to move to XLOG_FROM_STREAM only in
3856 * standby mode.
3857 */
3859
3860 /*
3861 * First, shutdown walreceiver if its restart has been
3862 * requested -- but no point if we're already slated for
3863 * starting it.
3864 */
3866 {
3868
3869 /*
3870 * Re-scan for possible new timelines if we were
3871 * requested to recover to the latest timeline.
3872 */
3875 rescanLatestTimeLine(replayTLI, replayLSN);
3876
3877 startWalReceiver = true;
3878 }
3879 pendingWalRcvRestart = false;
3880
3881 /*
3882 * Launch walreceiver if needed.
3883 *
3884 * If fetching_ckpt is true, RecPtr points to the initial
3885 * checkpoint location. In that case, we use RedoStartLSN
3886 * as the streaming start position instead of RecPtr, so
3887 * that when we later jump backwards to start redo at
3888 * RedoStartLSN, we will have the logs streamed already.
3889 */
3890 if (startWalReceiver &&
3892 {
3893 XLogRecPtr ptr;
3894 TimeLineID tli;
3895
3896 if (fetching_ckpt)
3897 {
3898 ptr = RedoStartLSN;
3899 tli = RedoStartTLI;
3900 }
3901 else
3902 {
3903 ptr = RecPtr;
3904
3905 /*
3906 * Use the record begin position to determine the
3907 * TLI, rather than the position we're reading.
3908 */
3910
3911 if (curFileTLI > 0 && tli < curFileTLI)
3912 elog(ERROR, "according to history file, WAL location %X/%08X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3914 tli, curFileTLI);
3915 }
3916 curFileTLI = tli;
3922 }
3923
3924 /*
3925 * Check if WAL receiver is active or wait to start up.
3926 */
3927 if (!WalRcvStreaming())
3928 {
3929 lastSourceFailed = true;
3930 break;
3931 }
3932
3933 /*
3934 * Walreceiver is active, so see if new data has arrived.
3935 *
3936 * We only advance XLogReceiptTime when we obtain fresh
3937 * WAL from walreceiver and observe that we had already
3938 * processed everything before the most recent "chunk"
3939 * that it flushed to disk. In steady state where we are
3940 * keeping up with the incoming data, XLogReceiptTime will
3941 * be updated on each cycle. When we are behind,
3942 * XLogReceiptTime will not advance, so the grace time
3943 * allotted to conflicting queries will decrease.
3944 */
3945 if (RecPtr < flushedUpto)
3946 havedata = true;
3947 else
3948 {
3949 XLogRecPtr latestChunkStart;
3950
3951 flushedUpto = GetWalRcvFlushRecPtr(&latestChunkStart, &receiveTLI);
3953 {
3954 havedata = true;
3955 if (latestChunkStart <= RecPtr)
3956 {
3959 }
3960 }
3961 else
3962 havedata = false;
3963 }
3964 if (havedata)
3965 {
3966 /*
3967 * Great, streamed far enough. Open the file if it's
3968 * not open already. Also read the timeline history
3969 * file if we haven't initialized timeline history
3970 * yet; it should be streamed over and present in
3971 * pg_wal by now. Use XLOG_FROM_STREAM so that source
3972 * info is set correctly and XLogReceiptTime isn't
3973 * changed.
3974 *
3975 * NB: We must set readTimeLineHistory based on
3976 * recoveryTargetTLI, not receiveTLI. Normally they'll
3977 * be the same, but if recovery_target_timeline is
3978 * 'latest' and archiving is configured, then it's
3979 * possible that we managed to retrieve one or more
3980 * new timeline history files from the archive,
3981 * updating recoveryTargetTLI.
3982 */
3983 if (readFile < 0)
3984 {
3985 if (!expectedTLEs)
3988 XLOG_FROM_STREAM, false);
3989 Assert(readFile >= 0);
3990 }
3991 else
3992 {
3993 /* just make sure source info is correct... */
3996 return XLREAD_SUCCESS;
3997 }
3998 break;
3999 }
4000
4001 /* In nonblocking mode, return rather than sleeping. */
4002 if (nonblocking)
4003 return XLREAD_WOULDBLOCK;
4004
4005 /*
4006 * Data not here yet. Check for trigger, then wait for
4007 * walreceiver to wake us up when new WAL arrives.
4008 */
4010 {
4011 /*
4012 * Note that we don't return XLREAD_FAIL immediately
4013 * here. After being triggered, we still want to
4014 * replay all the WAL that was already streamed. It's
4015 * in pg_wal now, so we just treat this as a failure,
4016 * and the state machine will move on to replay the
4017 * streamed WAL from pg_wal, and then recheck the
4018 * trigger and exit replay.
4019 */
4020 lastSourceFailed = true;
4021 break;
4022 }
4023
4024 /*
4025 * Since we have replayed everything we have received so
4026 * far and are about to start waiting for more WAL, let's
4027 * tell the upstream server our replay location now so
4028 * that pg_stat_replication doesn't show stale
4029 * information.
4030 */
4032 {
4034 streaming_reply_sent = true;
4035 }
4036
4037 /* Do any background tasks that might benefit us later. */
4039
4040 /* Update pg_stat_recovery_prefetch before sleeping. */
4042
4043 /*
4044 * Wait for more WAL to arrive, when we will be woken
4045 * immediately by the WAL receiver.
4046 */
4049 -1L,
4052 break;
4053 }
4054
4055 default:
4056 elog(ERROR, "unexpected WAL source %d", currentSource);
4057 }
4058
4059 /*
4060 * Check for recovery pause here so that we can confirm more quickly
4061 * that a requested pause has actually taken effect.
4062 */
4063 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
4065 recoveryPausesHere(false);
4066
4067 /*
4068 * This possibly-long loop needs to handle interrupts of startup
4069 * process.
4070 */
4072 }
4073
4074 return XLREAD_FAIL; /* not reached */
4075}
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1781
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1609
void KnownAssignedTransactionIdsIdleMaintenance(void)
Definition procarray.c:4543
@ WALRCV_STOPPING
Definition walreceiver.h:54
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, const char *slotname, bool create_temp_slot)
WalRcvState WalRcvGetState(void)
void SetInstallXLogFileSegmentActive(void)
Definition xlog.c:9646
void ResetInstallXLogFileSegmentActive(void)
Definition xlog.c:9655
int wal_retrieve_retry_interval
Definition xlog.c:137
@ XLREAD_WOULDBLOCK
Definition xlogreader.h:352
@ XLREAD_SUCCESS
Definition xlogreader.h:350
@ XLREAD_FAIL
Definition xlogreader.h:351
char * PrimarySlotName
static TimeLineID curFileTLI
static const char *const xlogSourceNames[]
static int XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source)
static TimeLineID receiveTLI
static int XLogFileRead(XLogSegNo segno, TimeLineID tli, XLogSource source, bool notfoundOk)
static XLogSegNo readSegNo
static void SetCurrentChunkStartTime(TimestampTz xtime)
bool wal_receiver_create_temp_slot
static XLogRecPtr flushedUpto
static bool rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN)

References Assert, CheckForStandbyTrigger(), close, curFileTLI, currentSource, DEBUG2, elog, ERROR, expectedTLEs, fb(), flushedUpto, GetCurrentTimestamp(), GetWalRcvFlushRecPtr(), InArchiveRecovery, InvalidXLogRecPtr, KnownAssignedTransactionIdsIdleMaintenance(), lastSourceFailed, LOG, LSN_FORMAT_ARGS, now(), pendingWalRcvRestart, PrimaryConnInfo, PrimarySlotName, ProcessStartupProcInterrupts(), readFile, readSegNo, readSource, readTimeLineHistory(), receiveTLI, RECOVERY_NOT_PAUSED, RECOVERY_TARGET_TIMELINE_LATEST, recoveryPausesHere(), recoveryTargetTimeLineGoal, recoveryTargetTLI, XLogRecoveryCtlData::recoveryWakeupLatch, RedoStartLSN, RedoStartTLI, RequestXLogStreaming(), rescanLatestTimeLine(), ResetInstallXLogFileSegmentActive(), ResetLatch(), SetCurrentChunkStartTime(), SetInstallXLogFileSegmentActive(), StandbyMode, TimestampDifferenceExceeds(), TimestampDifferenceMilliseconds(), tliOfPointInHistory(), WaitLatch(), wal_receiver_create_temp_slot, wal_retrieve_retry_interval, WALRCV_STOPPING, WalRcvForceReply(), WalRcvGetState(), WalRcvStreaming(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, WL_TIMEOUT, XLOG_FROM_ANY, XLOG_FROM_ARCHIVE, XLOG_FROM_PG_WAL, XLOG_FROM_STREAM, XLogFileRead(), XLogFileReadAnyTLI(), xlogprefetcher, XLogPrefetcherComputeStats(), XLogReceiptSource, XLogReceiptTime, XLogRecoveryCtl, XLogShutdownWalRcv(), xlogSourceNames, XLREAD_FAIL, XLREAD_SUCCESS, and XLREAD_WOULDBLOCK.

Referenced by XLogPageRead().

◆ WakeupRecovery()

◆ xlog_block_info()

static void xlog_block_info ( StringInfo  buf,
XLogReaderState record 
)
static

Definition at line 2369 of file xlogrecovery.c.

2370{
2371 int block_id;
2372
2373 /* decode block references */
2374 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2375 {
2376 RelFileLocator rlocator;
2377 ForkNumber forknum;
2379
2381 &rlocator, &forknum, &blk, NULL))
2382 continue;
2383
2384 if (forknum != MAIN_FORKNUM)
2385 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, fork %u, blk %u",
2386 block_id,
2387 rlocator.spcOid, rlocator.dbOid,
2388 rlocator.relNumber,
2389 forknum,
2390 blk);
2391 else
2392 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, blk %u",
2393 block_id,
2394 rlocator.spcOid, rlocator.dbOid,
2395 rlocator.relNumber,
2396 blk);
2397 if (XLogRecHasBlockImage(record, block_id))
2398 appendStringInfoString(buf, " FPW");
2399 }
2400}
@ MAIN_FORKNUM
Definition relpath.h:58

References appendStringInfo(), appendStringInfoString(), buf, RelFileLocator::dbOid, fb(), MAIN_FORKNUM, RelFileLocator::relNumber, RelFileLocator::spcOid, XLogRecGetBlockTagExtended(), XLogRecHasBlockImage, and XLogRecMaxBlockId.

Referenced by rm_redo_error_callback().

◆ xlog_outdesc()

void xlog_outdesc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 2330 of file xlogrecovery.c.

2331{
2333 uint8 info = XLogRecGetInfo(record);
2334 const char *id;
2335
2338
2339 id = rmgr.rm_identify(info);
2340 if (id == NULL)
2341 appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2342 else
2343 appendStringInfo(buf, "%s: ", id);
2344
2345 rmgr.rm_desc(buf, record);
2346}
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, fb(), GetRmgr(), XLogRecGetInfo, XLogRecGetRmid, and XLR_INFO_MASK.

Referenced by PerformWalRecovery(), rm_redo_error_callback(), and XLogInsertRecord().

◆ XLogFileRead()

static int XLogFileRead ( XLogSegNo  segno,
TimeLineID  tli,
XLogSource  source,
bool  notfoundOk 
)
static

Definition at line 4258 of file xlogrecovery.c.

4260{
4261 char xlogfname[MAXFNAMELEN];
4262 char activitymsg[MAXFNAMELEN + 16];
4263 char path[MAXPGPATH];
4264 int fd;
4265
4267
4268 switch (source)
4269 {
4270 case XLOG_FROM_ARCHIVE:
4271 /* Report recovery progress in PS display */
4272 snprintf(activitymsg, sizeof(activitymsg), "waiting for %s",
4273 xlogfname);
4275
4276 if (!RestoreArchivedFile(path, xlogfname,
4277 "RECOVERYXLOG",
4279 InRedo))
4280 return -1;
4281 break;
4282
4283 case XLOG_FROM_PG_WAL:
4284 case XLOG_FROM_STREAM:
4285 XLogFilePath(path, tli, segno, wal_segment_size);
4286 break;
4287
4288 default:
4289 elog(ERROR, "invalid XLogFileRead source %d", source);
4290 }
4291
4292 /*
4293 * If the segment was fetched from archival storage, replace the existing
4294 * xlog segment (if any) with the archival version.
4295 */
4297 {
4300
4301 /*
4302 * Set path to point at the new file in pg_wal.
4303 */
4304 snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
4305 }
4306
4308 if (fd >= 0)
4309 {
4310 /* Success! */
4311 curFileTLI = tli;
4312
4313 /* Report recovery progress in PS display */
4314 snprintf(activitymsg, sizeof(activitymsg), "recovering %s",
4315 xlogfname);
4317
4318 /* Track source of data in assorted state variables */
4321 /* In FROM_STREAM case, caller tracks receipt time, not me */
4322 if (source != XLOG_FROM_STREAM)
4324
4325 return fd;
4326 }
4327 if (errno != ENOENT || !notfoundOk) /* unexpected failure? */
4328 ereport(PANIC,
4330 errmsg("could not open file \"%s\": %m", path)));
4331 return -1;
4332}
int BasicOpenFile(const char *fileName, int fileFlags)
Definition fd.c:1086
static rewind_source * source
Definition pg_rewind.c:89
static void set_ps_display(const char *activity)
Definition ps_status.h:40
bool IsInstallXLogFileSegmentActive(void)
Definition xlog.c:9663
static void XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize, bool cleanupEnabled)
Definition xlogarchive.c:54
void KeepFileRestoredFromArchive(const char *path, const char *xlogfname)

References Assert, BasicOpenFile(), curFileTLI, elog, ereport, errcode_for_file_access(), errmsg(), ERROR, fb(), fd(), GetCurrentTimestamp(), InRedo, IsInstallXLogFileSegmentActive(), KeepFileRestoredFromArchive(), MAXFNAMELEN, MAXPGPATH, PANIC, PG_BINARY, readSource, RestoreArchivedFile(), set_ps_display(), snprintf, source, wal_segment_size, XLOG_FROM_ARCHIVE, XLOG_FROM_PG_WAL, XLOG_FROM_STREAM, XLOGDIR, XLogFileName(), XLogFilePath(), XLogReceiptSource, and XLogReceiptTime.

Referenced by WaitForWALToBecomeAvailable(), and XLogFileReadAnyTLI().

◆ XLogFileReadAnyTLI()

static int XLogFileReadAnyTLI ( XLogSegNo  segno,
XLogSource  source 
)
static

Definition at line 4340 of file xlogrecovery.c.

4341{
4342 char path[MAXPGPATH];
4343 ListCell *cell;
4344 int fd;
4345 List *tles;
4346
4347 /*
4348 * Loop looking for a suitable timeline ID: we might need to read any of
4349 * the timelines listed in expectedTLEs.
4350 *
4351 * We expect curFileTLI on entry to be the TLI of the preceding file in
4352 * sequence, or 0 if there was no predecessor. We do not allow curFileTLI
4353 * to go backwards; this prevents us from picking up the wrong file when a
4354 * parent timeline extends to higher segment numbers than the child we
4355 * want to read.
4356 *
4357 * If we haven't read the timeline history file yet, read it now, so that
4358 * we know which TLIs to scan. We don't save the list in expectedTLEs,
4359 * however, unless we actually find a valid segment. That way if there is
4360 * neither a timeline history file nor a WAL segment in the archive, and
4361 * streaming replication is set up, we'll read the timeline history file
4362 * streamed from the primary when we start streaming, instead of
4363 * recovering with a dummy history generated here.
4364 */
4365 if (expectedTLEs)
4367 else
4369
4370 foreach(cell, tles)
4371 {
4373 TimeLineID tli = hent->tli;
4374
4375 if (tli < curFileTLI)
4376 break; /* don't bother looking at too-old TLIs */
4377
4378 /*
4379 * Skip scanning the timeline ID that the logfile segment to read
4380 * doesn't belong to
4381 */
4382 if (XLogRecPtrIsValid(hent->begin))
4383 {
4384 XLogSegNo beginseg = 0;
4385
4387
4388 /*
4389 * The logfile segment that doesn't belong to the timeline is
4390 * older or newer than the segment that the timeline started or
4391 * ended at, respectively. It's sufficient to check only the
4392 * starting segment of the timeline here. Since the timelines are
4393 * scanned in descending order in this loop, any segments newer
4394 * than the ending segment should belong to newer timeline and
4395 * have already been read before. So it's not necessary to check
4396 * the ending segment of the timeline here.
4397 */
4398 if (segno < beginseg)
4399 continue;
4400 }
4401
4403 {
4404 fd = XLogFileRead(segno, tli, XLOG_FROM_ARCHIVE, true);
4405 if (fd != -1)
4406 {
4407 elog(DEBUG1, "got WAL segment from archive");
4408 if (!expectedTLEs)
4410 return fd;
4411 }
4412 }
4413
4415 {
4416 fd = XLogFileRead(segno, tli, XLOG_FROM_PG_WAL, true);
4417 if (fd != -1)
4418 {
4419 if (!expectedTLEs)
4421 return fd;
4422 }
4423 }
4424 }
4425
4426 /* Couldn't find it. For simplicity, complain about front timeline */
4428 errno = ENOENT;
4431 errmsg("could not open file \"%s\": %m", path)));
4432 return -1;
4433}

References curFileTLI, DEBUG1, DEBUG2, elog, ereport, errcode_for_file_access(), errmsg(), expectedTLEs, fb(), fd(), lfirst, MAXPGPATH, readTimeLineHistory(), recoveryTargetTLI, source, TimeLineHistoryEntry::tli, wal_segment_size, XLByteToSeg, XLOG_FROM_ANY, XLOG_FROM_ARCHIVE, XLOG_FROM_PG_WAL, XLogFilePath(), XLogFileRead(), and XLogRecPtrIsValid.

Referenced by WaitForWALToBecomeAvailable().

◆ XLogPageRead()

static int XLogPageRead ( XLogReaderState xlogreader,
XLogRecPtr  targetPagePtr,
int  reqLen,
XLogRecPtr  targetRecPtr,
char readBuf 
)
static

Definition at line 3333 of file xlogrecovery.c.

3335{
3336 XLogPageReadPrivate *private =
3338 int emode = private->emode;
3341 int r;
3343
3345
3348
3349 /*
3350 * See if we need to switch to a new segment because the requested record
3351 * is not in the currently open one.
3352 */
3353 if (readFile >= 0 &&
3355 {
3356 /*
3357 * Request a restartpoint if we've replayed too much xlog since the
3358 * last one.
3359 */
3361 {
3363 {
3364 (void) GetRedoRecPtr();
3367 }
3368 }
3369
3370 close(readFile);
3371 readFile = -1;
3373 }
3374
3376
3377retry:
3378 /* See if we need to retrieve more data */
3379 if (readFile < 0 ||
3382 {
3383 if (readFile >= 0 &&
3387 return XLREAD_WOULDBLOCK;
3388
3390 private->randAccess,
3391 private->fetching_ckpt,
3393 private->replayTLI,
3396 {
3397 case XLREAD_WOULDBLOCK:
3398 return XLREAD_WOULDBLOCK;
3399 case XLREAD_FAIL:
3400 if (readFile >= 0)
3401 close(readFile);
3402 readFile = -1;
3403 readLen = 0;
3405 return XLREAD_FAIL;
3406 case XLREAD_SUCCESS:
3407 break;
3408 }
3409 }
3410
3411 /*
3412 * At this point, we have the right segment open and if we're streaming we
3413 * know the requested record is in it.
3414 */
3415 Assert(readFile != -1);
3416
3417 /*
3418 * If the current segment is being streamed from the primary, calculate
3419 * how much of the current page we have received already. We know the
3420 * requested record has been received, but this is for the benefit of
3421 * future calls, to allow quick exit at the top of this function.
3422 */
3424 {
3427 else
3430 }
3431 else
3433
3434 /* Read the requested page */
3436
3437 /* Measure I/O timing when reading segment */
3439
3441 r = pg_pread(readFile, readBuf, XLOG_BLCKSZ, (pgoff_t) readOff);
3442 if (r != XLOG_BLCKSZ)
3443 {
3444 char fname[MAXFNAMELEN];
3445 int save_errno = errno;
3446
3448
3450 io_start, 1, r);
3451
3453 if (r < 0)
3454 {
3455 errno = save_errno;
3458 errmsg("could not read from WAL segment %s, LSN %X/%08X, offset %u: %m",
3460 readOff)));
3461 }
3462 else
3465 errmsg("could not read from WAL segment %s, LSN %X/%08X, offset %u: read %d of %zu",
3467 readOff, r, (Size) XLOG_BLCKSZ)));
3469 }
3471
3473 io_start, 1, r);
3474
3477 Assert(reqLen <= readLen);
3478
3480
3481 /*
3482 * Check the page header immediately, so that we can retry immediately if
3483 * it's not valid. This may seem unnecessary, because ReadPageInternal()
3484 * validates the page header anyway, and would propagate the failure up to
3485 * ReadRecord(), which would retry. However, there's a corner case with
3486 * continuation records, if a record is split across two pages such that
3487 * we would need to read the two pages from different sources across two
3488 * WAL segments.
3489 *
3490 * The first page is only available locally, in pg_wal, because it's
3491 * already been recycled on the primary. The second page, however, is not
3492 * present in pg_wal, and we should stream it from the primary. There is a
3493 * recycled WAL segment present in pg_wal, with garbage contents, however.
3494 * We would read the first page from the local WAL segment, but when
3495 * reading the second page, we would read the bogus, recycled, WAL
3496 * segment. If we didn't catch that case here, we would never recover,
3497 * because ReadRecord() would retry reading the whole record from the
3498 * beginning.
3499 *
3500 * Of course, this only catches errors in the page header, which is what
3501 * happens in the case of a recycled WAL segment. Other kinds of errors or
3502 * corruption still has the same problem. But this at least fixes the
3503 * common case, which can happen as part of normal operation.
3504 *
3505 * Validating the page header is cheap enough that doing it twice
3506 * shouldn't be a big deal from a performance point of view.
3507 *
3508 * When not in standby mode, an invalid page header should cause recovery
3509 * to end, not retry reading the page, so we don't need to validate the
3510 * page header here for the retry. Instead, ReadPageInternal() is
3511 * responsible for the validation.
3512 */
3513 if (StandbyMode &&
3516 {
3517 /*
3518 * Emit this error right now then retry this page immediately. Use
3519 * errmsg_internal() because the message was already translated.
3520 */
3521 if (xlogreader->errormsg_buf[0])
3524
3525 /* reset any error XLogReaderValidatePageHeader() might have set */
3528 }
3529
3530 return readLen;
3531
3533
3534 /*
3535 * If we're reading ahead, give up fast. Retries and error reporting will
3536 * be handled by a later read when recovery catches up to this point.
3537 */
3539 return XLREAD_WOULDBLOCK;
3540
3541 lastSourceFailed = true;
3542
3543 if (readFile >= 0)
3544 close(readFile);
3545 readFile = -1;
3546 readLen = 0;
3548
3549 /* In standby-mode, keep trying */
3550 if (StandbyMode)
3551 goto retry;
3552 else
3553 return XLREAD_FAIL;
3554}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:223
size_t Size
Definition c.h:619
void RequestCheckpoint(int flags)
@ IOOBJECT_WAL
Definition pgstat.h:279
@ IOCONTEXT_NORMAL
Definition pgstat.h:289
@ IOOP_READ
Definition pgstat.h:315
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition pgstat_io.c:91
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition pgstat_io.c:122
#define pg_pread
Definition port.h:247
off_t pgoff_t
Definition port.h:421
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:69
static void pgstat_report_wait_end(void)
Definition wait_event.h:85
XLogRecPtr GetRedoRecPtr(void)
Definition xlog.c:6563
bool track_wal_io_timing
Definition xlog.c:140
bool XLogCheckpointNeeded(XLogSegNo new_segno)
Definition xlog.c:2283
#define CHECKPOINT_CAUSE_XLOG
Definition xlog.h:159
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
void XLogReaderResetError(XLogReaderState *state)
bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr)
static XLogPageReadResult WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr, TimeLineID replayTLI, XLogRecPtr replayLSN, bool nonblocking)
static uint32 readLen

References AmStartupProcess, ArchiveRecoveryRequested, Assert, CHECKPOINT_CAUSE_XLOG, close, curFileTLI, emode_for_corrupt_record(), XLogReaderState::EndRecPtr, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), errmsg_internal(), XLogReaderState::errormsg_buf, fb(), flushedUpto, GetRedoRecPtr(), IOCONTEXT_NORMAL, IOOBJECT_WAL, IOOP_READ, IsUnderPostmaster, lastSourceFailed, LSN_FORMAT_ARGS, MAXFNAMELEN, XLogReaderState::nonblocking, pg_pread, PG_USED_FOR_ASSERTS_ONLY, pgstat_count_io_op_time(), pgstat_prepare_io_time(), pgstat_report_wait_end(), pgstat_report_wait_start(), XLogReaderState::private_data, readFile, readLen, readOff, readSegNo, readSource, RequestCheckpoint(), XLogReaderState::seg, StandbyMode, track_wal_io_timing, WaitForWALToBecomeAvailable(), wal_segment_size, WALOpenSegment::ws_tli, XLByteInSeg, XLByteToSeg, XLOG_FROM_ANY, XLOG_FROM_STREAM, XLogCheckpointNeeded(), XLogFileName(), xlogreader, XLogReaderResetError(), XLogReaderValidatePageHeader(), XLogSegmentOffset, XLREAD_FAIL, XLREAD_SUCCESS, and XLREAD_WOULDBLOCK.

Referenced by InitWalRecovery().

◆ xlogrecovery_redo()

static void xlogrecovery_redo ( XLogReaderState record,
TimeLineID  replayTLI 
)
static

Definition at line 2103 of file xlogrecovery.c.

2104{
2105 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2106 XLogRecPtr lsn = record->EndRecPtr;
2107
2108 Assert(XLogRecGetRmid(record) == RM_XLOG_ID);
2109
2110 if (info == XLOG_OVERWRITE_CONTRECORD)
2111 {
2112 /* Verify the payload of a XLOG_OVERWRITE_CONTRECORD record. */
2114
2116 if (xlrec.overwritten_lsn != record->overwrittenRecPtr)
2117 elog(FATAL, "mismatching overwritten LSN %X/%08X -> %X/%08X",
2118 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
2120
2121 /* We have safely skipped the aborted record */
2124
2125 ereport(LOG,
2126 errmsg("successfully skipped missing contrecord at %X/%08X, overwritten at %s",
2127 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
2128 timestamptz_to_str(xlrec.overwrite_time)));
2129
2130 /* Verifying the record should only happen once */
2132 }
2133 else if (info == XLOG_BACKUP_END)
2134 {
2135 XLogRecPtr startpoint;
2136
2137 memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
2138
2139 if (backupStartPoint == startpoint)
2140 {
2141 /*
2142 * We have reached the end of base backup, the point where
2143 * pg_backup_stop() was done. The data on disk is now consistent
2144 * (assuming we have also reached minRecoveryPoint). Set
2145 * backupEndPoint to the current LSN, so that the next call to
2146 * CheckRecoveryConsistency() will notice it and do the
2147 * end-of-backup processing.
2148 */
2149 elog(DEBUG1, "end of backup record reached");
2150
2151 backupEndPoint = lsn;
2152 }
2153 else
2154 elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%08X, waiting for %X/%08X",
2156 }
2157}
#define XLOG_OVERWRITE_CONTRECORD
Definition pg_control.h:82
#define XLOG_BACKUP_END
Definition pg_control.h:74
XLogRecPtr overwrittenRecPtr
Definition xlogreader.h:216

References abortedRecPtr, Assert, backupEndPoint, backupStartPoint, DEBUG1, elog, XLogReaderState::EndRecPtr, ereport, errmsg(), FATAL, fb(), InvalidXLogRecPtr, LOG, LSN_FORMAT_ARGS, missingContrecPtr, XLogReaderState::overwrittenRecPtr, timestamptz_to_str(), XLOG_BACKUP_END, XLOG_OVERWRITE_CONTRECORD, XLogRecGetData, XLogRecGetInfo, and XLogRecGetRmid.

Referenced by ApplyWalRecord().

◆ XLogRecoveryShmemInit()

void XLogRecoveryShmemInit ( void  )

Definition at line 465 of file xlogrecovery.c.

466{
467 bool found;
468
470 ShmemInitStruct("XLOG Recovery Ctl", XLogRecoveryShmemSize(), &found);
471 if (found)
472 return;
474
478}
void ConditionVariableInit(ConditionVariable *cv)
void InitSharedLatch(Latch *latch)
Definition latch.c:93
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:389
#define SpinLockInit(lock)
Definition spin.h:57
Size XLogRecoveryShmemSize(void)

References ConditionVariableInit(), fb(), XLogRecoveryCtlData::info_lck, InitSharedLatch(), XLogRecoveryCtlData::recoveryNotPausedCV, XLogRecoveryCtlData::recoveryWakeupLatch, ShmemInitStruct(), SpinLockInit, XLogRecoveryCtl, and XLogRecoveryShmemSize().

Referenced by CreateOrAttachShmemStructs().

◆ XLogRecoveryShmemSize()

Size XLogRecoveryShmemSize ( void  )

Definition at line 454 of file xlogrecovery.c.

455{
456 Size size;
457
458 /* XLogRecoveryCtl */
459 size = sizeof(XLogRecoveryCtlData);
460
461 return size;
462}

Referenced by CalculateShmemSize(), and XLogRecoveryShmemInit().

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4552 of file xlogrecovery.c.

4553{
4555}

References doRequestWalReceiverReply.

Referenced by xact_redo_commit().

Variable Documentation

◆ abortedRecPtr

XLogRecPtr abortedRecPtr
static

◆ archiveCleanupCommand

char* archiveCleanupCommand = NULL

Definition at line 86 of file xlogrecovery.c.

Referenced by CreateRestartPoint().

◆ ArchiveRecoveryRequested

◆ backupEndPoint

XLogRecPtr backupEndPoint
static

Definition at line 284 of file xlogrecovery.c.

Referenced by CheckRecoveryConsistency(), InitWalRecovery(), and xlogrecovery_redo().

◆ backupEndRequired

bool backupEndRequired = false
static

Definition at line 285 of file xlogrecovery.c.

Referenced by CheckRecoveryConsistency(), InitWalRecovery(), and read_backup_label().

◆ backupStartPoint

XLogRecPtr backupStartPoint
static

Definition at line 283 of file xlogrecovery.c.

Referenced by CheckRecoveryConsistency(), InitWalRecovery(), and xlogrecovery_redo().

◆ CheckPointLoc

XLogRecPtr CheckPointLoc = InvalidXLogRecPtr
static

Definition at line 169 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), InitWalRecovery(), and PerformWalRecovery().

◆ CheckPointTLI

TimeLineID CheckPointTLI = 0
static

Definition at line 170 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), InitWalRecovery(), and PerformWalRecovery().

◆ curFileTLI

TimeLineID curFileTLI
static

◆ currentSource

XLogSource currentSource = XLOG_FROM_ANY
static

◆ doRequestWalReceiverReply

bool doRequestWalReceiverReply
static

Definition at line 187 of file xlogrecovery.c.

Referenced by ApplyWalRecord(), and XLogRequestWalReceiverReply().

◆ expectedTLEs

◆ flushedUpto

XLogRecPtr flushedUpto = InvalidXLogRecPtr
static

Definition at line 264 of file xlogrecovery.c.

Referenced by WaitForWALToBecomeAvailable(), and XLogPageRead().

◆ InArchiveRecovery

◆ InRedo

bool InRedo = false
static

Definition at line 205 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and XLogFileRead().

◆ lastSourceFailed

bool lastSourceFailed = false
static

Definition at line 249 of file xlogrecovery.c.

Referenced by ReadRecord(), WaitForWALToBecomeAvailable(), and XLogPageRead().

◆ LocalHotStandbyActive

bool LocalHotStandbyActive = false
static

◆ LocalPromoteIsTriggered

bool LocalPromoteIsTriggered = false
static

◆ minRecoveryPoint

XLogRecPtr minRecoveryPoint
static

◆ minRecoveryPointTLI

TimeLineID minRecoveryPointTLI
static

Definition at line 281 of file xlogrecovery.c.

Referenced by checkTimeLineSwitch(), InitWalRecovery(), and ReadRecord().

◆ missingContrecPtr

XLogRecPtr missingContrecPtr
static

◆ pendingWalRcvRestart

bool pendingWalRcvRestart = false
static

◆ primary_image_masked

char* primary_image_masked = NULL
static

Definition at line 305 of file xlogrecovery.c.

Referenced by InitWalRecovery(), and verifyBackupPageConsistency().

◆ PrimaryConnInfo

◆ PrimarySlotName

◆ reachedConsistency

◆ readFile

int readFile = -1
static

◆ readLen

uint32 readLen = 0
static

Definition at line 235 of file xlogrecovery.c.

Referenced by ReadPageInternal(), XLogFindNextRecord(), and XLogPageRead().

◆ readOff

uint32 readOff = 0
static

Definition at line 234 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), XLogDecodeNextRecord(), and XLogPageRead().

◆ readSegNo

XLogSegNo readSegNo = 0
static

Definition at line 233 of file xlogrecovery.c.

Referenced by WaitForWALToBecomeAvailable(), and XLogPageRead().

◆ readSource

◆ receiveTLI

TimeLineID receiveTLI = 0
static

◆ recovery_min_apply_delay

int recovery_min_apply_delay = 0

Definition at line 95 of file xlogrecovery.c.

Referenced by recoveryApplyDelay().

◆ recovery_signal_file_found

bool recovery_signal_file_found = false
static

Definition at line 153 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), and readRecoverySignalFile().

◆ recovery_target_action_options

const struct config_enum_entry recovery_target_action_options[]
Initial value:
= {
{"pause", RECOVERY_TARGET_ACTION_PAUSE, false},
{"promote", RECOVERY_TARGET_ACTION_PROMOTE, false},
{"shutdown", RECOVERY_TARGET_ACTION_SHUTDOWN, false},
{NULL, 0, false}
}

Definition at line 76 of file xlogrecovery.c.

76 {
77 {"pause", RECOVERY_TARGET_ACTION_PAUSE, false},
78 {"promote", RECOVERY_TARGET_ACTION_PROMOTE, false},
79 {"shutdown", RECOVERY_TARGET_ACTION_SHUTDOWN, false},
80 {NULL, 0, false}
81};

◆ recovery_target_time_string

char* recovery_target_time_string

Definition at line 91 of file xlogrecovery.c.

Referenced by validateRecoveryParameters().

◆ recoveryEndCommand

char* recoveryEndCommand = NULL

Definition at line 85 of file xlogrecovery.c.

Referenced by CleanupAfterArchiveRecovery().

◆ recoveryRestoreCommand

char* recoveryRestoreCommand = NULL

Definition at line 84 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), and validateRecoveryParameters().

◆ recoveryStopAfter

bool recoveryStopAfter
static

Definition at line 390 of file xlogrecovery.c.

Referenced by getRecoveryStopReason(), recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryStopLSN

XLogRecPtr recoveryStopLSN
static

Definition at line 388 of file xlogrecovery.c.

Referenced by getRecoveryStopReason(), recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryStopName

char recoveryStopName[MAXFNAMELEN]
static

Definition at line 389 of file xlogrecovery.c.

Referenced by getRecoveryStopReason(), recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryStopTime

TimestampTz recoveryStopTime
static

Definition at line 387 of file xlogrecovery.c.

Referenced by getRecoveryStopReason(), recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryStopXid

TransactionId recoveryStopXid
static

Definition at line 386 of file xlogrecovery.c.

Referenced by getRecoveryStopReason(), recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTarget

◆ recoveryTargetAction

int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE

Definition at line 89 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and validateRecoveryParameters().

◆ recoveryTargetInclusive

bool recoveryTargetInclusive = true

Definition at line 88 of file xlogrecovery.c.

Referenced by recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTargetLSN

XLogRecPtr recoveryTargetLSN

◆ recoveryTargetName

const char* recoveryTargetName

Definition at line 93 of file xlogrecovery.c.

Referenced by assign_recovery_target_name(), InitWalRecovery(), and recoveryStopsAfter().

◆ recoveryTargetTime

TimestampTz recoveryTargetTime

Definition at line 92 of file xlogrecovery.c.

Referenced by InitWalRecovery(), recoveryStopsBefore(), and validateRecoveryParameters().

◆ recoveryTargetTimeLineGoal

◆ recoveryTargetTLI

◆ recoveryTargetTLIRequested

TimeLineID recoveryTargetTLIRequested = 0

Definition at line 123 of file xlogrecovery.c.

Referenced by assign_recovery_target_timeline(), and validateRecoveryParameters().

◆ recoveryTargetXid

◆ RedoStartLSN

◆ RedoStartTLI

TimeLineID RedoStartTLI = 0
static

◆ replay_image_masked

char* replay_image_masked = NULL
static

Definition at line 304 of file xlogrecovery.c.

Referenced by InitWalRecovery(), and verifyBackupPageConsistency().

◆ standby_signal_file_found

bool standby_signal_file_found = false
static

Definition at line 152 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), and readRecoverySignalFile().

◆ StandbyMode

◆ StandbyModeRequested

bool StandbyModeRequested = false
static

◆ wal_receiver_create_temp_slot

bool wal_receiver_create_temp_slot = false

Definition at line 100 of file xlogrecovery.c.

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().

◆ xlogprefetcher

◆ xlogreader

◆ XLogReceiptSource

XLogSource XLogReceiptSource = XLOG_FROM_ANY
static

Definition at line 261 of file xlogrecovery.c.

Referenced by GetXLogReceiptTime(), WaitForWALToBecomeAvailable(), and XLogFileRead().

◆ XLogReceiptTime

TimestampTz XLogReceiptTime = 0
static

◆ XLogRecoveryCtl

◆ xlogSourceNames

const char* const xlogSourceNames[] = {"any", "archive", "pg_wal", "stream"}
static

Definition at line 220 of file xlogrecovery.c.

220{"any", "archive", "pg_wal", "stream"};

Referenced by WaitForWALToBecomeAvailable().