PostgreSQL Source Code git master
xlogrecovery.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <math.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 "backup/basebackup.h"
#include "catalog/pg_control.h"
#include "commands/tablespace.h"
#include "common/file_utils.h"
#include "miscadmin.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/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 char * getRecoveryStopReason (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 void pg_attribute_noreturn () 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 []
 
char * recoveryRestoreCommand = NULL
 
char * recoveryEndCommand = NULL
 
char * archiveCleanupCommand = NULL
 
RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET
 
bool recoveryTargetInclusive = true
 
int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE
 
TransactionId recoveryTargetXid
 
char * recovery_target_time_string
 
TimestampTz recoveryTargetTime
 
const char * recoveryTargetName
 
XLogRecPtr recoveryTargetLSN
 
int recovery_min_apply_delay = 0
 
char * PrimaryConnInfo = NULL
 
char * PrimarySlotName = 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 = 0
 
static TimeLineID receiveTLI = 0
 
static XLogRecPtr minRecoveryPoint
 
static TimeLineID minRecoveryPointTLI
 
static XLogRecPtr backupStartPoint
 
static XLogRecPtr backupEndPoint
 
static bool backupEndRequired = false
 
bool reachedConsistency = false
 
static char * replay_image_masked = NULL
 
static char * primary_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 69 of file xlogrecovery.c.

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 68 of file xlogrecovery.c.

Typedef Documentation

◆ XLogPageReadPrivate

◆ XLogRecoveryCtlData

Enumeration Type Documentation

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 209 of file xlogrecovery.c.

210{
211 XLOG_FROM_ANY = 0, /* request to read WAL from any source */
212 XLOG_FROM_ARCHIVE, /* restored using restore_command */
213 XLOG_FROM_PG_WAL, /* existing file in pg_wal */
214 XLOG_FROM_STREAM, /* streamed from primary */
215} XLogSource;
XLogSource
Definition: xlogrecovery.c:210
@ XLOG_FROM_PG_WAL
Definition: xlogrecovery.c:213
@ XLOG_FROM_STREAM
Definition: xlogrecovery.c:214
@ XLOG_FROM_ARCHIVE
Definition: xlogrecovery.c:212
@ XLOG_FROM_ANY
Definition: xlogrecovery.c:211

Function Documentation

◆ ApplyWalRecord()

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

Definition at line 1909 of file xlogrecovery.c.

1910{
1911 ErrorContextCallback errcallback;
1912 bool switchedTLI = false;
1913
1914 /* Setup error traceback support for ereport() */
1915 errcallback.callback = rm_redo_error_callback;
1916 errcallback.arg = xlogreader;
1917 errcallback.previous = error_context_stack;
1918 error_context_stack = &errcallback;
1919
1920 /*
1921 * TransamVariables->nextXid must be beyond record's xid.
1922 */
1924
1925 /*
1926 * Before replaying this record, check if this record causes the current
1927 * timeline to change. The record is already considered to be part of the
1928 * new timeline, so we update replayTLI before replaying it. That's
1929 * important so that replayEndTLI, which is recorded as the minimum
1930 * recovery point's TLI if recovery stops after this record, is set
1931 * correctly.
1932 */
1933 if (record->xl_rmid == RM_XLOG_ID)
1934 {
1935 TimeLineID newReplayTLI = *replayTLI;
1936 TimeLineID prevReplayTLI = *replayTLI;
1937 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1938
1939 if (info == XLOG_CHECKPOINT_SHUTDOWN)
1940 {
1941 CheckPoint checkPoint;
1942
1943 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
1944 newReplayTLI = checkPoint.ThisTimeLineID;
1945 prevReplayTLI = checkPoint.PrevTimeLineID;
1946 }
1947 else if (info == XLOG_END_OF_RECOVERY)
1948 {
1949 xl_end_of_recovery xlrec;
1950
1951 memcpy(&xlrec, XLogRecGetData(xlogreader), sizeof(xl_end_of_recovery));
1952 newReplayTLI = xlrec.ThisTimeLineID;
1953 prevReplayTLI = xlrec.PrevTimeLineID;
1954 }
1955
1956 if (newReplayTLI != *replayTLI)
1957 {
1958 /* Check that it's OK to switch to this TLI */
1960 newReplayTLI, prevReplayTLI, *replayTLI);
1961
1962 /* Following WAL records should be run with new TLI */
1963 *replayTLI = newReplayTLI;
1964 switchedTLI = true;
1965 }
1966 }
1967
1968 /*
1969 * Update shared replayEndRecPtr before replaying this record, so that
1970 * XLogFlush will update minRecoveryPoint correctly.
1971 */
1974 XLogRecoveryCtl->replayEndTLI = *replayTLI;
1976
1977 /*
1978 * If we are attempting to enter Hot Standby mode, process XIDs we see
1979 */
1983
1984 /*
1985 * Some XLOG record types that are related to recovery are processed
1986 * directly here, rather than in xlog_redo()
1987 */
1988 if (record->xl_rmid == RM_XLOG_ID)
1989 xlogrecovery_redo(xlogreader, *replayTLI);
1990
1991 /* Now apply the WAL record itself */
1993
1994 /*
1995 * After redo, check whether the backup pages associated with the WAL
1996 * record are consistent with the existing pages. This check is done only
1997 * if consistency check is enabled for this record.
1998 */
1999 if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
2001
2002 /* Pop the error context stack */
2003 error_context_stack = errcallback.previous;
2004
2005 /*
2006 * Update lastReplayedEndRecPtr after this record has been successfully
2007 * replayed.
2008 */
2012 XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
2014
2015 /* ------
2016 * Wakeup walsenders:
2017 *
2018 * On the standby, the WAL is flushed first (which will only wake up
2019 * physical walsenders) and then applied, which will only wake up logical
2020 * walsenders.
2021 *
2022 * Indeed, logical walsenders on standby can't decode and send data until
2023 * it's been applied.
2024 *
2025 * Physical walsenders don't need to be woken up during replay unless
2026 * cascading replication is allowed and time line change occurred (so that
2027 * they can notice that they are on a new time line).
2028 *
2029 * That's why the wake up conditions are for:
2030 *
2031 * - physical walsenders in case of new time line and cascade
2032 * replication is allowed
2033 * - logical walsenders in case cascade replication is allowed (could not
2034 * be created otherwise)
2035 * ------
2036 */
2038 WalSndWakeup(switchedTLI, true);
2039
2040 /*
2041 * If rm_redo called XLogRequestWalReceiverReply, then we wake up the
2042 * receiver so that it notices the updated lastReplayedEndRecPtr and sends
2043 * a reply to the primary.
2044 */
2046 {
2049 }
2050
2051 /* Allow read-only connections if we're consistent now */
2053
2054 /* Is this a timeline switch? */
2055 if (switchedTLI)
2056 {
2057 /*
2058 * Before we continue on the new timeline, clean up any (possibly
2059 * bogus) future WAL segments on the old timeline.
2060 */
2062
2063 /* Reset the prefetcher. */
2065 }
2066}
uint8_t uint8
Definition: c.h:486
ErrorContextCallback * error_context_stack
Definition: elog.c:94
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:68
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:77
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4403
#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:296
void(* callback)(void *arg)
Definition: elog.h:297
void(* rm_redo)(XLogReaderState *record)
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
uint8 xl_info
Definition: xlogrecord.h:46
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogRecPtr lastReplayedEndRecPtr
Definition: xlogrecovery.c:339
TimeLineID replayEndTLI
Definition: xlogrecovery.c:348
TimeLineID lastReplayedTLI
Definition: xlogrecovery.c:340
XLogRecPtr replayEndRecPtr
Definition: xlogrecovery.c:347
XLogRecPtr lastReplayedReadRecPtr
Definition: xlogrecovery.c:338
TimeLineID PrevTimeLineID
TimeLineID ThisTimeLineID
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:304
void WalRcvForceReply(void)
Definition: walreceiver.c:1359
#define AllowCascadeReplication()
Definition: walreceiver.h:40
void WalSndWakeup(bool physical, bool logical)
Definition: walsender.c:3639
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition: xlog.c:3940
static RmgrData GetRmgr(RmgrId rmid)
uint32 TimeLineID
Definition: xlogdefs.h:59
void XLogPrefetchReconfigure(void)
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#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
Definition: xlogrecovery.c:364
static bool doRequestWalReceiverReply
Definition: xlogrecovery.c:185
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188
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, GetRmgr(), XLogRecoveryCtlData::info_lck, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, ErrorContextCallback::previous, xl_end_of_recovery::PrevTimeLineID, CheckPoint::PrevTimeLineID, XLogReaderState::ReadRecPtr, RecordKnownAssignedTransactionIds(), RemoveNonParentXlogFiles(), XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, RmgrData::rm_redo, rm_redo_error_callback(), SpinLockAcquire, SpinLockRelease, STANDBY_INITIALIZED, standbyState, xl_end_of_recovery::ThisTimeLineID, 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 4794 of file xlogrecovery.c.

4795{
4798 error_multiple_recovery_targets();
4799
4800 if (newval && strcmp(newval, "") != 0)
4802 else
4804}
#define newval
RecoveryTargetType recoveryTarget
Definition: xlogrecovery.c:85
@ RECOVERY_TARGET_IMMEDIATE
Definition: xlogrecovery.h:30
@ RECOVERY_TARGET_UNSET
Definition: xlogrecovery.h:25

References 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 4833 of file xlogrecovery.c.

4834{
4837 error_multiple_recovery_targets();
4838
4839 if (newval && strcmp(newval, "") != 0)
4840 {
4842 recoveryTargetLSN = *((XLogRecPtr *) extra);
4843 }
4844 else
4846}
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr recoveryTargetLSN
Definition: xlogrecovery.c:92
@ RECOVERY_TARGET_LSN
Definition: xlogrecovery.h:29

References newval, RECOVERY_TARGET_LSN, RECOVERY_TARGET_UNSET, recoveryTarget, and recoveryTargetLSN.

◆ assign_recovery_target_name()

void assign_recovery_target_name ( const char *  newval,
void *  extra 
)

Definition at line 4868 of file xlogrecovery.c.

4869{
4872 error_multiple_recovery_targets();
4873
4874 if (newval && strcmp(newval, "") != 0)
4875 {
4878 }
4879 else
4881}
const char * recoveryTargetName
Definition: xlogrecovery.c:91
@ RECOVERY_TARGET_NAME
Definition: xlogrecovery.h:28

References newval, RECOVERY_TARGET_NAME, RECOVERY_TARGET_UNSET, recoveryTarget, and recoveryTargetName.

◆ assign_recovery_target_time()

void assign_recovery_target_time ( const char *  newval,
void *  extra 
)

Definition at line 4948 of file xlogrecovery.c.

4949{
4952 error_multiple_recovery_targets();
4953
4954 if (newval && strcmp(newval, "") != 0)
4956 else
4958}
@ RECOVERY_TARGET_TIME
Definition: xlogrecovery.h:27

References newval, RECOVERY_TARGET_TIME, RECOVERY_TARGET_UNSET, and recoveryTarget.

◆ assign_recovery_target_timeline()

void assign_recovery_target_timeline ( const char *  newval,
void *  extra 
)

Definition at line 4997 of file xlogrecovery.c.

4998{
5001 recoveryTargetTLIRequested = (TimeLineID) strtoul(newval, NULL, 0);
5002 else
5004}
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
Definition: xlogrecovery.c:120
TimeLineID recoveryTargetTLIRequested
Definition: xlogrecovery.c:121
RecoveryTargetTimeLineGoal
Definition: xlogrecovery.h:37
@ RECOVERY_TARGET_TIMELINE_NUMERIC
Definition: xlogrecovery.h:40

References 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 5033 of file xlogrecovery.c.

5034{
5037 error_multiple_recovery_targets();
5038
5039 if (newval && strcmp(newval, "") != 0)
5040 {
5042 recoveryTargetXid = *((TransactionId *) extra);
5043 }
5044 else
5046}
uint32 TransactionId
Definition: c.h:609
TransactionId recoveryTargetXid
Definition: xlogrecovery.c:88
@ RECOVERY_TARGET_XID
Definition: xlogrecovery.h:26

References 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 4739 of file xlogrecovery.c.

4740{
4741 if (*newval && strcmp(*newval, "") != 0 &&
4743 return false;
4744
4745 return true;
4746}
#define WARNING
Definition: elog.h:36
bool ReplicationSlotValidateName(const char *name, int elevel)
Definition: slot.c:252

References newval, ReplicationSlotValidateName(), and WARNING.

◆ check_recovery_target()

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

Definition at line 4780 of file xlogrecovery.c.

4781{
4782 if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
4783 {
4784 GUC_check_errdetail("The only allowed value is \"immediate\".");
4785 return false;
4786 }
4787 return true;
4788}
#define GUC_check_errdetail
Definition: guc.h:476

References GUC_check_errdetail, and newval.

◆ check_recovery_target_lsn()

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

Definition at line 4810 of file xlogrecovery.c.

4811{
4812 if (strcmp(*newval, "") != 0)
4813 {
4814 XLogRecPtr lsn;
4815 XLogRecPtr *myextra;
4816 bool have_error = false;
4817
4818 lsn = pg_lsn_in_internal(*newval, &have_error);
4819 if (have_error)
4820 return false;
4821
4822 myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
4823 *myextra = lsn;
4824 *extra = myextra;
4825 }
4826 return true;
4827}
#define ERROR
Definition: elog.h:39
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:638
XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error)
Definition: pg_lsn.c:29

References ERROR, guc_malloc(), newval, and pg_lsn_in_internal().

◆ check_recovery_target_name()

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

Definition at line 4852 of file xlogrecovery.c.

4853{
4854 /* Use the value of newval directly */
4855 if (strlen(*newval) >= MAXFNAMELEN)
4856 {
4857 GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
4858 "recovery_target_name", MAXFNAMELEN - 1);
4859 return false;
4860 }
4861 return true;
4862}
#define MAXFNAMELEN

References GUC_check_errdetail, MAXFNAMELEN, and newval.

◆ check_recovery_target_time()

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

Definition at line 4893 of file xlogrecovery.c.

4894{
4895 if (strcmp(*newval, "") != 0)
4896 {
4897 /* reject some special values */
4898 if (strcmp(*newval, "now") == 0 ||
4899 strcmp(*newval, "today") == 0 ||
4900 strcmp(*newval, "tomorrow") == 0 ||
4901 strcmp(*newval, "yesterday") == 0)
4902 {
4903 return false;
4904 }
4905
4906 /*
4907 * parse timestamp value (see also timestamptz_in())
4908 */
4909 {
4910 char *str = *newval;
4911 fsec_t fsec;
4912 struct pg_tm tt,
4913 *tm = &tt;
4914 int tz;
4915 int dtype;
4916 int nf;
4917 int dterr;
4918 char *field[MAXDATEFIELDS];
4919 int ftype[MAXDATEFIELDS];
4920 char workbuf[MAXDATELEN + MAXDATEFIELDS];
4921 DateTimeErrorExtra dtextra;
4923
4924 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
4925 field, ftype, MAXDATEFIELDS, &nf);
4926 if (dterr == 0)
4927 dterr = DecodeDateTime(field, ftype, nf,
4928 &dtype, tm, &fsec, &tz, &dtextra);
4929 if (dterr != 0)
4930 return false;
4931 if (dtype != DTK_DATE)
4932 return false;
4933
4934 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
4935 {
4936 GUC_check_errdetail("Timestamp out of range: \"%s\".", str);
4937 return false;
4938 }
4939 }
4940 }
4941 return true;
4942}
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:764
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:988
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1987
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, 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 4964 of file xlogrecovery.c.

4965{
4968
4969 if (strcmp(*newval, "current") == 0)
4971 else if (strcmp(*newval, "latest") == 0)
4973 else
4974 {
4976
4977 errno = 0;
4978 strtoul(*newval, NULL, 0);
4979 if (errno == EINVAL || errno == ERANGE)
4980 {
4981 GUC_check_errdetail("\"recovery_target_timeline\" is not a valid number.");
4982 return false;
4983 }
4984 }
4985
4987 *myextra = rttg;
4988 *extra = myextra;
4989
4990 return true;
4991}
@ RECOVERY_TARGET_TIMELINE_CONTROLFILE
Definition: xlogrecovery.h:38
@ RECOVERY_TARGET_TIMELINE_LATEST
Definition: xlogrecovery.h:39

References ERROR, GUC_check_errdetail, guc_malloc(), newval, 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 5010 of file xlogrecovery.c.

5011{
5012 if (strcmp(*newval, "") != 0)
5013 {
5014 TransactionId xid;
5015 TransactionId *myextra;
5016
5017 errno = 0;
5018 xid = (TransactionId) strtou64(*newval, NULL, 0);
5019 if (errno == EINVAL || errno == ERANGE)
5020 return false;
5021
5022 myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
5023 *myextra = xid;
5024 *extra = myextra;
5025 }
5026 return true;
5027}

References ERROR, guc_malloc(), and newval.

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 4432 of file xlogrecovery.c.

4433{
4435 return true;
4436
4438 {
4439 ereport(LOG, (errmsg("received promote request")));
4443 return true;
4444 }
4445
4446 return false;
4447}
bool IsPromoteSignaled(void)
Definition: startup.c:288
void ResetPromoteSignaled(void)
Definition: startup.c:294
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:149
bool CheckPromoteSignal(void)
static bool LocalPromoteIsTriggered
Definition: xlogrecovery.c:182
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 4462 of file xlogrecovery.c.

4463{
4464 struct stat stat_buf;
4465
4466 if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4467 return true;
4468
4469 return false;
4470}
#define stat
Definition: win32_port.h:274
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:309

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 2177 of file xlogrecovery.c.

2178{
2179 XLogRecPtr lastReplayedEndRecPtr;
2180 TimeLineID lastReplayedTLI;
2181
2182 /*
2183 * During crash recovery, we don't reach a consistent state until we've
2184 * replayed all the WAL.
2185 */
2187 return;
2188
2190
2191 /*
2192 * assume that we are called in the startup process, and hence don't need
2193 * a lock to read lastReplayedEndRecPtr
2194 */
2195 lastReplayedEndRecPtr = XLogRecoveryCtl->lastReplayedEndRecPtr;
2196 lastReplayedTLI = XLogRecoveryCtl->lastReplayedTLI;
2197
2198 /*
2199 * Have we reached the point where our base backup was completed?
2200 */
2202 backupEndPoint <= lastReplayedEndRecPtr)
2203 {
2204 XLogRecPtr saveBackupStartPoint = backupStartPoint;
2205 XLogRecPtr saveBackupEndPoint = backupEndPoint;
2206
2207 elog(DEBUG1, "end of backup reached");
2208
2209 /*
2210 * We have reached the end of base backup, as indicated by pg_control.
2211 * Update the control file accordingly.
2212 */
2213 ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI);
2216 backupEndRequired = false;
2217
2218 ereport(LOG,
2219 (errmsg("completed backup recovery with redo LSN %X/%X and end LSN %X/%X",
2220 LSN_FORMAT_ARGS(saveBackupStartPoint),
2221 LSN_FORMAT_ARGS(saveBackupEndPoint))));
2222 }
2223
2224 /*
2225 * Have we passed our safe starting point? Note that minRecoveryPoint is
2226 * known to be incorrectly set if recovering from a backup, until the
2227 * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint.
2228 * All we know prior to that is that we're not consistent yet.
2229 */
2231 minRecoveryPoint <= lastReplayedEndRecPtr)
2232 {
2233 /*
2234 * Check to see if the XLOG sequence contained any unresolved
2235 * references to uninitialized pages.
2236 */
2238
2239 /*
2240 * Check that pg_tblspc doesn't contain any real directories. Replay
2241 * of Database/CREATE_* records may have created fictitious tablespace
2242 * directories that should have been removed by the time consistency
2243 * was reached.
2244 */
2246
2247 reachedConsistency = true;
2248 ereport(LOG,
2249 (errmsg("consistent recovery state reached at %X/%X",
2250 LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
2251 }
2252
2253 /*
2254 * Have we got a valid starting snapshot that will allow queries to be
2255 * run? If so, we can tell postmaster that the database is consistent now,
2256 * enabling connections.
2257 */
2262 {
2266
2267 LocalHotStandbyActive = true;
2268
2270 }
2271}
#define Assert(condition)
Definition: c.h:815
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:225
bool IsUnderPostmaster
Definition: globals.c:119
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:165
@ PMSIGNAL_BEGIN_HOT_STANDBY
Definition: pmsignal.h:36
void ReachedEndOfBackup(XLogRecPtr EndRecPtr, TimeLineID tli)
Definition: xlog.c:6247
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
bool reachedConsistency
Definition: xlogrecovery.c:294
static bool backupEndRequired
Definition: xlogrecovery.c:283
static XLogRecPtr minRecoveryPoint
Definition: xlogrecovery.c:278
static XLogRecPtr backupEndPoint
Definition: xlogrecovery.c:282
bool InArchiveRecovery
Definition: xlogrecovery.c:138
static bool LocalHotStandbyActive
Definition: xlogrecovery.c:176
static void CheckTablespaceDirectory(void)
static XLogRecPtr backupStartPoint
Definition: xlogrecovery.c:281
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:245
@ STANDBY_SNAPSHOT_READY
Definition: xlogutils.h:55

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

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

◆ CheckTablespaceDirectory()

static void CheckTablespaceDirectory ( void  )
static

Definition at line 2144 of file xlogrecovery.c.

2145{
2146 DIR *dir;
2147 struct dirent *de;
2148
2150 while ((de = ReadDir(dir, PG_TBLSPC_DIR)) != NULL)
2151 {
2152 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR)];
2153
2154 /* Skip entries of non-oid names */
2155 if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
2156 continue;
2157
2158 snprintf(path, sizeof(path), "%s/%s", PG_TBLSPC_DIR, de->d_name);
2159
2160 if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
2163 errmsg("unexpected directory entry \"%s\" found in %s",
2164 de->d_name, PG_TBLSPC_DIR),
2165 errdetail("All directory entries in %s/ should be symbolic links.",
2167 errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
2168 }
2169}
bool allow_in_place_tablespaces
Definition: tablespace.c:85
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
#define PANIC
Definition: elog.h:42
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2865
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2931
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:526
@ PGFILETYPE_LNK
Definition: file_utils.h:24
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define PG_TBLSPC_DIR
Definition: relpath.h:41
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References AllocateDir(), allow_in_place_tablespaces, dirent::d_name, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errdetail(), errhint(), errmsg(), ERROR, 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 2379 of file xlogrecovery.c.

2381{
2382 /* Check that the record agrees on what the current (old) timeline is */
2383 if (prevTLI != replayTLI)
2384 ereport(PANIC,
2385 (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2386 prevTLI, replayTLI)));
2387
2388 /*
2389 * The new timeline better be in the list of timelines we expect to see,
2390 * according to the timeline history. It should also not decrease.
2391 */
2392 if (newTLI < replayTLI || !tliInHistory(newTLI, expectedTLEs))
2393 ereport(PANIC,
2394 (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
2395 newTLI, replayTLI)));
2396
2397 /*
2398 * If we have not yet reached min recovery point, and we're about to
2399 * switch to a timeline greater than the timeline of the min recovery
2400 * point: trouble. After switching to the new timeline, we could not
2401 * possibly visit the min recovery point on the correct timeline anymore.
2402 * This can happen if there is a newer timeline in the archive that
2403 * branched before the timeline the min recovery point is on, and you
2404 * attempt to do PITR to the new timeline.
2405 */
2407 lsn < minRecoveryPoint &&
2408 newTLI > minRecoveryPointTLI)
2409 ereport(PANIC,
2410 (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
2411 newTLI,
2414
2415 /* Looks good */
2416}
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:526
static List * expectedTLEs
Definition: xlogrecovery.c:123
static TimeLineID minRecoveryPointTLI
Definition: xlogrecovery.c:279

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

Referenced by ApplyWalRecord().

◆ ConfirmRecoveryPaused()

static void ConfirmRecoveryPaused ( void  )
static

◆ emode_for_corrupt_record()

static int emode_for_corrupt_record ( int  emode,
XLogRecPtr  RecPtr 
)
static

Definition at line 4031 of file xlogrecovery.c.

4032{
4033 static XLogRecPtr lastComplaint = 0;
4034
4035 if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
4036 {
4037 if (RecPtr == lastComplaint)
4038 emode = DEBUG1;
4039 else
4040 lastComplaint = RecPtr;
4041 }
4042 return emode;
4043}
static XLogSource readSource
Definition: xlogrecovery.c:234

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

◆ EnableStandbyMode()

static void EnableStandbyMode ( void  )
static

Definition at line 478 of file xlogrecovery.c.

479{
480 StandbyMode = true;
481
482 /*
483 * To avoid server log bloat, we don't report recovery progress in a
484 * standby as it will always be in recovery unless promoted. We disable
485 * startup progress timeout in standby mode to avoid calling
486 * startup_progress_timeout_handler() unnecessarily.
487 */
489}
void disable_startup_progress_timeout(void)
Definition: startup.c:309
bool StandbyMode
Definition: xlogrecovery.c:147

References disable_startup_progress_timeout(), and StandbyMode.

Referenced by InitWalRecovery(), and ReadRecord().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo * FinishWalRecovery ( void  )

Definition at line 1458 of file xlogrecovery.c.

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

References abortedRecPtr, EndOfWalRecoveryInfo::abortedRecPtr, ArchiveRecoveryRequested, Assert, CheckPointLoc, CheckPointTLI, close, EndOfWalRecoveryInfo::endOfLog, EndOfWalRecoveryInfo::endOfLogTLI, XLogReaderState::EndRecPtr, getRecoveryStopReason(), InArchiveRecovery, InRecovery, EndOfWalRecoveryInfo::lastPage, EndOfWalRecoveryInfo::lastPageBeginPtr, EndOfWalRecoveryInfo::lastRec, EndOfWalRecoveryInfo::lastRecTLI, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, len, missingContrecPtr, EndOfWalRecoveryInfo::missingContrecPtr, palloc(), 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()

TimestampTz GetCurrentChunkReplayStartTime ( void  )

◆ GetCurrentReplayRecPtr()

XLogRecPtr GetCurrentReplayRecPtr ( TimeLineID replayEndTLI)

Definition at line 4561 of file xlogrecovery.c.

4562{
4563 XLogRecPtr recptr;
4564 TimeLineID tli;
4565
4570
4571 if (replayEndTLI)
4572 *replayEndTLI = tli;
4573 return recptr;
4574}

References XLogRecoveryCtlData::info_lck, XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by UpdateMinRecoveryPoint(), and xlog_redo().

◆ GetLatestXTime()

◆ getRecordTimestamp()

static bool getRecordTimestamp ( XLogReaderState record,
TimestampTz recordXtime 
)
static

Definition at line 2428 of file xlogrecovery.c.

2429{
2430 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2431 uint8 xact_info = info & XLOG_XACT_OPMASK;
2432 uint8 rmid = XLogRecGetRmid(record);
2433
2434 if (rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2435 {
2436 *recordXtime = ((xl_restore_point *) XLogRecGetData(record))->rp_time;
2437 return true;
2438 }
2439 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_COMMIT ||
2440 xact_info == XLOG_XACT_COMMIT_PREPARED))
2441 {
2442 *recordXtime = ((xl_xact_commit *) XLogRecGetData(record))->xact_time;
2443 return true;
2444 }
2445 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_ABORT ||
2446 xact_info == XLOG_XACT_ABORT_PREPARED))
2447 {
2448 *recordXtime = ((xl_xact_abort *) XLogRecGetData(record))->xact_time;
2449 return true;
2450 }
2451 return false;
2452}
#define XLOG_RESTORE_POINT
Definition: pg_control.h:75
#define XLOG_XACT_COMMIT_PREPARED
Definition: xact.h:172
#define XLOG_XACT_COMMIT
Definition: xact.h:169
#define XLOG_XACT_OPMASK
Definition: xact.h:179
#define XLOG_XACT_ABORT
Definition: xact.h:171
#define XLOG_XACT_ABORT_PREPARED
Definition: xact.h:173
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:411

References 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 2888 of file xlogrecovery.c.

2889{
2890 char reason[200];
2891
2893 snprintf(reason, sizeof(reason),
2894 "%s transaction %u",
2895 recoveryStopAfter ? "after" : "before",
2898 snprintf(reason, sizeof(reason),
2899 "%s %s\n",
2900 recoveryStopAfter ? "after" : "before",
2903 snprintf(reason, sizeof(reason),
2904 "%s LSN %X/%X\n",
2905 recoveryStopAfter ? "after" : "before",
2908 snprintf(reason, sizeof(reason),
2909 "at restore point \"%s\"",
2912 snprintf(reason, sizeof(reason), "reached consistency");
2913 else
2914 snprintf(reason, sizeof(reason), "no recovery target specified");
2915
2916 return pstrdup(reason);
2917}
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1843
char * pstrdup(const char *in)
Definition: mcxt.c:1696
static XLogRecPtr recoveryStopLSN
Definition: xlogrecovery.c:381
static TimestampTz recoveryStopTime
Definition: xlogrecovery.c:380
static char recoveryStopName[MAXFNAMELEN]
Definition: xlogrecovery.c:382
static bool recoveryStopAfter
Definition: xlogrecovery.c:383
static TransactionId recoveryStopXid
Definition: xlogrecovery.c:379

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 4641 of file xlogrecovery.c.

4642{
4643 /*
4644 * This must be executed in the startup process, since we don't export the
4645 * relevant state to shared memory.
4646 */
4648
4649 *rtime = XLogReceiptTime;
4650 *fromStream = (XLogReceiptSource == XLOG_FROM_STREAM);
4651}
static XLogSource XLogReceiptSource
Definition: xlogrecovery.c:259
static TimestampTz XLogReceiptTime
Definition: xlogrecovery.c:258

References Assert, InRecovery, XLOG_FROM_STREAM, XLogReceiptSource, and XLogReceiptTime.

Referenced by GetStandbyLimitTime().

◆ GetXLogReplayRecPtr()

◆ HotStandbyActive()

bool HotStandbyActive ( void  )

Definition at line 4501 of file xlogrecovery.c.

4502{
4503 /*
4504 * We check shared state each time only until Hot Standby is active. We
4505 * can't de-activate Hot Standby, so there's no need to keep checking
4506 * after the shared variable has once been seen true.
4507 */
4509 return true;
4510 else
4511 {
4512 /* spinlock is essential on machines with weak memory ordering! */
4516
4517 return LocalHotStandbyActive;
4518 }
4519}

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

Referenced by XLogWalRcvSendHSFeedback().

◆ HotStandbyActiveInReplay()

static bool HotStandbyActiveInReplay ( void  )
static

Definition at line 4526 of file xlogrecovery.c.

4527{
4529 return LocalHotStandbyActive;
4530}
bool IsPostmasterEnvironment
Definition: globals.c:118
#define AmStartupProcess()
Definition: miscadmin.h:388

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 512 of file xlogrecovery.c.

514{
515 XLogPageReadPrivate *private;
516 struct stat st;
517 bool wasShutdown;
518 XLogRecord *record;
519 DBState dbstate_at_startup;
520 bool haveTblspcMap = false;
521 bool haveBackupLabel = false;
522 CheckPoint checkPoint;
523 bool backupFromStandby = false;
524
525 dbstate_at_startup = ControlFile->state;
526
527 /*
528 * Initialize on the assumption we want to recover to the latest timeline
529 * that's active according to pg_control.
530 */
534 else
536
537 /*
538 * Check for signal files, and if so set up state for offline recovery
539 */
542
543 /*
544 * Take ownership of the wakeup latch if we're going to sleep during
545 * recovery, if required.
546 */
549
550 /*
551 * Set the WAL reading processor now, as it will be needed when reading
552 * the checkpoint record required (backup_label or not).
553 */
554 private = palloc0(sizeof(XLogPageReadPrivate));
555 xlogreader =
557 XL_ROUTINE(.page_read = &XLogPageRead,
558 .segment_open = NULL,
559 .segment_close = wal_segment_close),
560 private);
561 if (!xlogreader)
563 (errcode(ERRCODE_OUT_OF_MEMORY),
564 errmsg("out of memory"),
565 errdetail("Failed while allocating a WAL reading processor.")));
567
568 /*
569 * Set the WAL decode buffer size. This limits how far ahead we can read
570 * in the WAL.
571 */
573
574 /* Create a WAL prefetcher. */
576
577 /*
578 * Allocate two page buffers dedicated to WAL consistency checks. We do
579 * it this way, rather than just making static arrays, for two reasons:
580 * (1) no need to waste the storage in most instantiations of the backend;
581 * (2) a static char array isn't guaranteed to have any particular
582 * alignment, whereas palloc() will provide MAXALIGN'd storage.
583 */
584 replay_image_masked = (char *) palloc(BLCKSZ);
585 primary_image_masked = (char *) palloc(BLCKSZ);
586
587 /*
588 * Read the backup_label file. We want to run this part of the recovery
589 * process after checking for signal files and after performing validation
590 * of the recovery parameters.
591 */
593 &backupFromStandby))
594 {
595 List *tablespaces = NIL;
596
597 /*
598 * Archive recovery was requested, and thanks to the backup label
599 * file, we know how far we need to replay to reach consistency. Enter
600 * archive recovery directly.
601 */
602 InArchiveRecovery = true;
605
606 /*
607 * Omitting backup_label when creating a new replica, PITR node etc.
608 * unfortunately is a common cause of corruption. Logging that
609 * backup_label was used makes it a bit easier to exclude that as the
610 * cause of observed corruption.
611 *
612 * Do so before we try to read the checkpoint record (which can fail),
613 * as otherwise it can be hard to understand why a checkpoint other
614 * than ControlFile->checkPoint is used.
615 */
616 ereport(LOG,
617 (errmsg("starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u",
620 CheckPointTLI)));
621
622 /*
623 * When a backup_label file is present, we want to roll forward from
624 * the checkpoint it identifies, rather than using pg_control.
625 */
628 if (record != NULL)
629 {
630 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
631 wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
633 (errmsg_internal("checkpoint record is at %X/%X",
635 InRecovery = true; /* force recovery even if SHUTDOWNED */
636
637 /*
638 * Make sure that REDO location exists. This may not be the case
639 * if there was a crash during an online backup, which left a
640 * backup_label around that references a WAL segment that's
641 * already been archived.
642 */
643 if (checkPoint.redo < CheckPointLoc)
644 {
646 if (!ReadRecord(xlogprefetcher, LOG, false,
647 checkPoint.ThisTimeLineID))
649 (errmsg("could not find redo location %X/%X referenced by checkpoint record at %X/%X",
651 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
652 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
653 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
655 }
656 }
657 else
658 {
660 (errmsg("could not locate required checkpoint record at %X/%X",
662 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
663 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
664 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
666 wasShutdown = false; /* keep compiler quiet */
667 }
668
669 /* Read the tablespace_map file if present and create symlinks. */
670 if (read_tablespace_map(&tablespaces))
671 {
672 ListCell *lc;
673
674 foreach(lc, tablespaces)
675 {
676 tablespaceinfo *ti = lfirst(lc);
677 char *linkloc;
678
679 linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid);
680
681 /*
682 * Remove the existing symlink if any and Create the symlink
683 * under PGDATA.
684 */
686
687 if (symlink(ti->path, linkloc) < 0)
690 errmsg("could not create symbolic link \"%s\": %m",
691 linkloc)));
692
693 pfree(ti->path);
694 pfree(ti);
695 }
696
697 /* tell the caller to delete it later */
698 haveTblspcMap = true;
699 }
700
701 /* tell the caller to delete it later */
702 haveBackupLabel = true;
703 }
704 else
705 {
706 /* No backup_label file has been found if we are here. */
707
708 /*
709 * If tablespace_map file is present without backup_label file, there
710 * is no use of such file. There is no harm in retaining it, but it
711 * is better to get rid of the map file so that we don't have any
712 * redundant file in data directory and it will avoid any sort of
713 * confusion. It seems prudent though to just rename the file out of
714 * the way rather than delete it completely, also we ignore any error
715 * that occurs in rename operation as even if map file is present
716 * without backup_label file, it is harmless.
717 */
718 if (stat(TABLESPACE_MAP, &st) == 0)
719 {
720 unlink(TABLESPACE_MAP_OLD);
722 ereport(LOG,
723 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
725 errdetail("File \"%s\" was renamed to \"%s\".",
727 else
728 ereport(LOG,
729 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
731 errdetail("Could not rename file \"%s\" to \"%s\": %m.",
733 }
734
735 /*
736 * It's possible that archive recovery was requested, but we don't
737 * know how far we need to replay the WAL before we reach consistency.
738 * This can happen for example if a base backup is taken from a
739 * running server using an atomic filesystem snapshot, without calling
740 * pg_backup_start/stop. Or if you just kill a running primary server
741 * and put it into archive recovery by creating a recovery signal
742 * file.
743 *
744 * Our strategy in that case is to perform crash recovery first,
745 * replaying all the WAL present in pg_wal, and only enter archive
746 * recovery after that.
747 *
748 * But usually we already know how far we need to replay the WAL (up
749 * to minRecoveryPoint, up to backupEndPoint, or until we see an
750 * end-of-backup record), and we can enter archive recovery directly.
751 */
757 {
758 InArchiveRecovery = true;
761 }
762
763 /*
764 * For the same reason as when starting up with backup_label present,
765 * emit a log message when we continue initializing from a base
766 * backup.
767 */
769 ereport(LOG,
770 (errmsg("restarting backup recovery with redo LSN %X/%X",
772
773 /* Get the last valid checkpoint record. */
780 if (record != NULL)
781 {
783 (errmsg_internal("checkpoint record is at %X/%X",
785 }
786 else
787 {
788 /*
789 * We used to attempt to go back to a secondary checkpoint record
790 * here, but only when not in standby mode. We now just fail if we
791 * can't read the last checkpoint because this allows us to
792 * simplify processing around checkpoints.
793 */
795 (errmsg("could not locate a valid checkpoint record at %X/%X",
797 }
798 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
799 wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
800 }
801
803 {
805 ereport(LOG,
806 (errmsg("entering standby mode")));
808 ereport(LOG,
809 (errmsg("starting point-in-time recovery to XID %u",
812 ereport(LOG,
813 (errmsg("starting point-in-time recovery to %s",
816 ereport(LOG,
817 (errmsg("starting point-in-time recovery to \"%s\"",
820 ereport(LOG,
821 (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
824 ereport(LOG,
825 (errmsg("starting point-in-time recovery to earliest consistent point")));
826 else
827 ereport(LOG,
828 (errmsg("starting archive recovery")));
829 }
830
831 /*
832 * If the location of the checkpoint record is not on the expected
833 * timeline in the history of the requested timeline, we cannot proceed:
834 * the backup is not part of the history of the requested timeline.
835 */
836 Assert(expectedTLEs); /* was initialized by reading checkpoint
837 * record */
840 {
841 XLogRecPtr switchpoint;
842
843 /*
844 * tliSwitchPoint will throw an error if the checkpoint's timeline is
845 * not in expectedTLEs at all.
846 */
849 (errmsg("requested timeline %u is not a child of this server's history",
851 errdetail("Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.",
854 LSN_FORMAT_ARGS(switchpoint))));
855 }
856
857 /*
858 * The min recovery point should be part of the requested timeline's
859 * history, too.
860 */
865 (errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
869
871 (errmsg_internal("redo record is at %X/%X; shutdown %s",
872 LSN_FORMAT_ARGS(checkPoint.redo),
873 wasShutdown ? "true" : "false")));
875 (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
877 checkPoint.nextOid)));
879 (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
880 checkPoint.nextMulti, checkPoint.nextMultiOffset)));
882 (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
883 checkPoint.oldestXid, checkPoint.oldestXidDB)));
885 (errmsg_internal("oldest MultiXactId: %u, in database %u",
886 checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
888 (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
889 checkPoint.oldestCommitTsXid,
890 checkPoint.newestCommitTsXid)));
893 (errmsg("invalid next transaction ID")));
894
895 /* sanity check */
896 if (checkPoint.redo > CheckPointLoc)
898 (errmsg("invalid redo in checkpoint record")));
899
900 /*
901 * Check whether we need to force recovery from WAL. If it appears to
902 * have been a clean shutdown and we did not have a recovery signal file,
903 * then assume no recovery needed.
904 */
905 if (checkPoint.redo < CheckPointLoc)
906 {
907 if (wasShutdown)
909 (errmsg("invalid redo record in shutdown checkpoint")));
910 InRecovery = true;
911 }
912 else if (ControlFile->state != DB_SHUTDOWNED)
913 InRecovery = true;
915 {
916 /* force recovery due to presence of recovery signal file */
917 InRecovery = true;
918 }
919
920 /*
921 * If recovery is needed, update our in-memory copy of pg_control to show
922 * that we are recovering and to show the selected checkpoint as the place
923 * we are starting from. We also mark pg_control with any minimum recovery
924 * stop point obtained from a backup history file.
925 *
926 * We don't write the changes to disk yet, though. Only do that after
927 * initializing various subsystems.
928 */
929 if (InRecovery)
930 {
932 {
934 }
935 else
936 {
937 ereport(LOG,
938 (errmsg("database system was not properly shut down; "
939 "automatic recovery in progress")));
941 ereport(LOG,
942 (errmsg("crash recovery starts in timeline %u "
943 "and has target timeline %u",
947 }
949 ControlFile->checkPointCopy = checkPoint;
951 {
952 /* initialize minRecoveryPoint if not set yet */
953 if (ControlFile->minRecoveryPoint < checkPoint.redo)
954 {
955 ControlFile->minRecoveryPoint = checkPoint.redo;
957 }
958 }
959
960 /*
961 * Set backupStartPoint if we're starting recovery from a base backup.
962 *
963 * Also set backupEndPoint and use minRecoveryPoint as the backup end
964 * location if we're starting recovery from a base backup which was
965 * taken from a standby. In this case, the database system status in
966 * pg_control must indicate that the database was already in recovery.
967 * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
968 * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
969 * before reaching this point; e.g. because restore_command or
970 * primary_conninfo were faulty.
971 *
972 * Any other state indicates that the backup somehow became corrupted
973 * and we can't sensibly continue with recovery.
974 */
975 if (haveBackupLabel)
976 {
977 ControlFile->backupStartPoint = checkPoint.redo;
979
980 if (backupFromStandby)
981 {
982 if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
983 dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
985 (errmsg("backup_label contains data inconsistent with control file"),
986 errhint("This means that the backup is corrupted and you will "
987 "have to use another backup for recovery.")));
989 }
990 }
991 }
992
993 /* remember these, so that we know when we have reached consistency */
998 {
1001 }
1002 else
1003 {
1006 }
1007
1008 /*
1009 * Start recovery assuming that the final record isn't lost.
1010 */
1013
1014 *wasShutdown_ptr = wasShutdown;
1015 *haveBackupLabel_ptr = haveBackupLabel;
1016 *haveTblspcMap_ptr = haveTblspcMap;
1017}
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:507
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
#define FATAL
Definition: elog.h:41
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:781
char * DataDir
Definition: globals.c:70
void OwnLatch(Latch *latch)
Definition: latch.c:463
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
DBState
Definition: pg_control.h:90
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:96
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:93
@ DB_SHUTDOWNED
Definition: pg_control.h:92
@ DB_IN_CRASH_RECOVERY
Definition: pg_control.h:95
#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:51
MultiXactId oldestMulti
Definition: pg_control.h:50
MultiXactOffset nextMultiOffset
Definition: pg_control.h:47
TransactionId newestCommitTsXid
Definition: pg_control.h:55
TransactionId oldestXid
Definition: pg_control.h:48
Oid nextOid
Definition: pg_control.h:45
MultiXactId nextMulti
Definition: pg_control.h:46
FullTransactionId nextXid
Definition: pg_control.h:44
TransactionId oldestCommitTsXid
Definition: pg_control.h:53
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:49
XLogRecPtr backupStartPoint
Definition: pg_control.h:170
bool backupEndRequired
Definition: pg_control.h:172
CheckPoint checkPointCopy
Definition: pg_control.h:135
XLogRecPtr backupEndPoint
Definition: pg_control.h:171
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:168
XLogRecPtr checkPoint
Definition: pg_control.h:133
uint64 system_identifier
Definition: pg_control.h:110
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:169
Definition: pg_list.h:54
uint64 system_identifier
Definition: xlogreader.h:191
#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:136
static ControlFileData * ControlFile
Definition: xlog.c:574
#define TABLESPACE_MAP_OLD
Definition: xlog.h:306
#define TABLESPACE_MAP
Definition: xlog.h:305
#define BACKUP_LABEL_FILE
Definition: xlog.h:302
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:106
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition: xlogreader.c:90
#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
Definition: xlogrecovery.c:170
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
Definition: xlogrecovery.c:298
static char * replay_image_masked
Definition: xlogrecovery.c:297
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:122
static XLogRecPtr RedoStartLSN
Definition: xlogrecovery.c:169
static void EnableStandbyMode(void)
Definition: xlogrecovery.c:478
TimestampTz recoveryTargetTime
Definition: xlogrecovery.c:90
static bool StandbyModeRequested
Definition: xlogrecovery.c:146
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:842

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, 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, tablespaceinfo::oid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, OwnLatch(), palloc(), palloc0(), PANIC, tablespaceinfo::path, 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 XLogRecPtrIsInvalid.

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1652 of file xlogrecovery.c.

1653{
1654 XLogRecord *record;
1655 bool reachedRecoveryTarget = false;
1656 TimeLineID replayTLI;
1657
1658 /*
1659 * Initialize shared variables for tracking progress of WAL replay, as if
1660 * we had just replayed the record before the REDO location (or the
1661 * checkpoint record itself, if it's a shutdown checkpoint).
1662 */
1665 {
1669 }
1670 else
1671 {
1675 }
1682
1683 /* Also ensure XLogReceiptTime has a sane value */
1685
1686 /*
1687 * Let postmaster know we've started redo now, so that it can launch the
1688 * archiver if necessary.
1689 */
1692
1693 /*
1694 * Allow read-only connections immediately if we're consistent already.
1695 */
1697
1698 /*
1699 * Find the first record that logically follows the checkpoint --- it
1700 * might physically precede it, though.
1701 */
1703 {
1704 /* back up to find the record */
1705 replayTLI = RedoStartTLI;
1707 record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1708
1709 /*
1710 * If a checkpoint record's redo pointer points back to an earlier
1711 * LSN, the record at that LSN should be an XLOG_CHECKPOINT_REDO
1712 * record.
1713 */
1714 if (record->xl_rmid != RM_XLOG_ID ||
1716 ereport(FATAL,
1717 (errmsg("unexpected record type found at redo point %X/%X",
1719 }
1720 else
1721 {
1722 /* just have to read next record after CheckPoint */
1724 replayTLI = CheckPointTLI;
1725 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1726 }
1727
1728 if (record != NULL)
1729 {
1730 TimestampTz xtime;
1731 PGRUsage ru0;
1732
1733 pg_rusage_init(&ru0);
1734
1735 InRedo = true;
1736
1737 RmgrStartup();
1738
1739 ereport(LOG,
1740 (errmsg("redo starts at %X/%X",
1742
1743 /* Prepare to report progress of the redo phase. */
1744 if (!StandbyMode)
1746
1747 /*
1748 * main redo apply loop
1749 */
1750 do
1751 {
1752 if (!StandbyMode)
1753 ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
1755
1756#ifdef WAL_DEBUG
1757 if (XLOG_DEBUG)
1758 {
1760
1762 appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
1765 xlog_outrec(&buf, xlogreader);
1766 appendStringInfoString(&buf, " - ");
1768 elog(LOG, "%s", buf.data);
1769 pfree(buf.data);
1770 }
1771#endif
1772
1773 /* Handle interrupt signals of startup process */
1775
1776 /*
1777 * Pause WAL replay, if requested by a hot-standby session via
1778 * SetRecoveryPause().
1779 *
1780 * Note that we intentionally don't take the info_lck spinlock
1781 * here. We might therefore read a slightly stale value of the
1782 * recoveryPause flag, but it can't be very stale (no worse than
1783 * the last spinlock we did acquire). Since a pause request is a
1784 * pretty asynchronous thing anyway, possibly responding to it one
1785 * WAL record later than we otherwise would is a minor issue, so
1786 * it doesn't seem worth adding another spinlock cycle to prevent
1787 * that.
1788 */
1789 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1791 recoveryPausesHere(false);
1792
1793 /*
1794 * Have we reached our recovery target?
1795 */
1797 {
1798 reachedRecoveryTarget = true;
1799 break;
1800 }
1801
1802 /*
1803 * If we've been asked to lag the primary, wait on latch until
1804 * enough time has passed.
1805 */
1807 {
1808 /*
1809 * We test for paused recovery again here. If user sets
1810 * delayed apply, it may be because they expect to pause
1811 * recovery in case of problems, so we must test again here
1812 * otherwise pausing during the delay-wait wouldn't work.
1813 */
1814 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1816 recoveryPausesHere(false);
1817 }
1818
1819 /*
1820 * Apply the record
1821 */
1822 ApplyWalRecord(xlogreader, record, &replayTLI);
1823
1824 /* Exit loop if we reached inclusive recovery target */
1826 {
1827 reachedRecoveryTarget = true;
1828 break;
1829 }
1830
1831 /* Else, try to fetch the next WAL record */
1832 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1833 } while (record != NULL);
1834
1835 /*
1836 * end of main redo apply loop
1837 */
1838
1839 if (reachedRecoveryTarget)
1840 {
1841 if (!reachedConsistency)
1842 ereport(FATAL,
1843 (errmsg("requested recovery stop point is before consistent recovery point")));
1844
1845 /*
1846 * This is the last point where we can restart recovery with a new
1847 * recovery target, if we shutdown and begin again. After this,
1848 * Resource Managers may choose to do permanent corrective actions
1849 * at end of recovery.
1850 */
1851 switch (recoveryTargetAction)
1852 {
1854
1855 /*
1856 * exit with special return code to request shutdown of
1857 * postmaster. Log messages issued from postmaster.
1858 */
1859 proc_exit(3);
1860
1862 SetRecoveryPause(true);
1863 recoveryPausesHere(true);
1864
1865 /* drop into promote */
1866
1868 break;
1869 }
1870 }
1871
1872 RmgrCleanup();
1873
1874 ereport(LOG,
1875 (errmsg("redo done at %X/%X system usage: %s",
1877 pg_rusage_show(&ru0))));
1878 xtime = GetLatestXTime();
1879 if (xtime)
1880 ereport(LOG,
1881 (errmsg("last completed transaction was at log time %s",
1882 timestamptz_to_str(xtime))));
1883
1884 InRedo = false;
1885 }
1886 else
1887 {
1888 /* there are no WAL records following the checkpoint */
1889 ereport(LOG,
1890 (errmsg("redo is not required")));
1891 }
1892
1893 /*
1894 * This check is intentionally after the above log messages that indicate
1895 * how far recovery went.
1896 */
1899 !reachedRecoveryTarget)
1900 ereport(FATAL,
1901 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1902 errmsg("recovery ended before configured recovery target was reached")));
1903}
void HandleStartupProcInterrupts(void)
Definition: startup.c:154
void begin_startup_progress_phase(void)
Definition: startup.c:343
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
void proc_exit(int code)
Definition: ipc.c:104
#define XLOG_CHECKPOINT_REDO
Definition: pg_control.h:82
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
Definition: pg_test_fsync.c:72
@ 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
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
static bool recoveryStopsBefore(XLogReaderState *record)
int recoveryTargetAction
Definition: xlogrecovery.c:87
static bool recoveryApplyDelay(XLogReaderState *record)
static bool recoveryStopsAfter(XLogReaderState *record)
void SetRecoveryPause(bool recoveryPause)
void xlog_outdesc(StringInfo buf, XLogReaderState *record)
static bool InRedo
Definition: xlogrecovery.c:203
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
static void recoveryPausesHere(bool endOfRecovery)
TimestampTz GetLatestXTime(void)
@ RECOVERY_NOT_PAUSED
Definition: xlogrecovery.h:46

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, GetCurrentTimestamp(), GetLatestXTime(), HandleStartupProcInterrupts(), XLogRecoveryCtlData::info_lck, initStringInfo(), InRedo, InvalidXLogRecPtr, IsUnderPostmaster, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, LOG, LSN_FORMAT_ARGS, PANIC, pfree(), pg_rusage_init(), pg_rusage_show(), PMSIGNAL_RECOVERY_STARTED, proc_exit(), 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(), XLogRecord::xl_info, XLogRecord::xl_rmid, XLOG_CHECKPOINT_REDO, xlog_outdesc(), xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, XLogReceiptTime, XLogRecoveryCtl, and XLR_INFO_MASK.

Referenced by StartupXLOG().

◆ pg_attribute_noreturn()

static void pg_attribute_noreturn ( )
static

Definition at line 4767 of file xlogrecovery.c.

4769{
4770 ereport(ERROR,
4771 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4772 errmsg("multiple recovery targets specified"),
4773 errdetail("At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set.")));
4774}

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

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4393 of file xlogrecovery.c.

4394{
4395 /*
4396 * We check shared state each time only until a standby promotion is
4397 * triggered. We can't trigger a promotion again, so there's no need to
4398 * keep checking after the shared variable has once been seen true.
4399 */
4401 return true;
4402
4406
4408}

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

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

◆ read_backup_label()

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

Definition at line 1208 of file xlogrecovery.c.

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

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

Referenced by InitWalRecovery().

◆ read_tablespace_map()

static bool read_tablespace_map ( List **  tablespaces)
static

Definition at line 1354 of file xlogrecovery.c.

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

References AllocateFile(), ereport, errcode(), errcode_for_file_access(), errmsg(), FATAL, FreeFile(), i, lappend(), MAXPGPATH, tablespaceinfo::oid, palloc0(), tablespaceinfo::path, pstrdup(), str, and TABLESPACE_MAP.

Referenced by InitWalRecovery().

◆ ReadCheckpointRecord()

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

Definition at line 4050 of file xlogrecovery.c.

4052{
4053 XLogRecord *record;
4054 uint8 info;
4055
4056 Assert(xlogreader != NULL);
4057
4058 if (!XRecOffIsValid(RecPtr))
4059 {
4060 ereport(LOG,
4061 (errmsg("invalid checkpoint location")));
4062 return NULL;
4063 }
4064
4066 record = ReadRecord(xlogprefetcher, LOG, true, replayTLI);
4067
4068 if (record == NULL)
4069 {
4070 ereport(LOG,
4071 (errmsg("invalid checkpoint record")));
4072 return NULL;
4073 }
4074 if (record->xl_rmid != RM_XLOG_ID)
4075 {
4076 ereport(LOG,
4077 (errmsg("invalid resource manager ID in checkpoint record")));
4078 return NULL;
4079 }
4080 info = record->xl_info & ~XLR_INFO_MASK;
4081 if (info != XLOG_CHECKPOINT_SHUTDOWN &&
4082 info != XLOG_CHECKPOINT_ONLINE)
4083 {
4084 ereport(LOG,
4085 (errmsg("invalid xl_info in checkpoint record")));
4086 return NULL;
4087 }
4089 {
4090 ereport(LOG,
4091 (errmsg("invalid length of checkpoint record")));
4092 return NULL;
4093 }
4094 return record;
4095}
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:69
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(), 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 3133 of file xlogrecovery.c.

3135{
3136 XLogRecord *record;
3139
3140 /* Pass through parameters to XLogPageRead */
3141 private->fetching_ckpt = fetching_ckpt;
3142 private->emode = emode;
3143 private->randAccess = (xlogreader->ReadRecPtr == InvalidXLogRecPtr);
3144 private->replayTLI = replayTLI;
3145
3146 /* This is the first attempt to read this page. */
3147 lastSourceFailed = false;
3148
3149 for (;;)
3150 {
3151 char *errormsg;
3152
3153 record = XLogPrefetcherReadRecord(xlogprefetcher, &errormsg);
3154 if (record == NULL)
3155 {
3156 /*
3157 * When we find that WAL ends in an incomplete record, keep track
3158 * of that record. After recovery is done, we'll write a record
3159 * to indicate to downstream WAL readers that that portion is to
3160 * be ignored.
3161 *
3162 * However, when ArchiveRecoveryRequested = true, we're going to
3163 * switch to a new timeline at the end of recovery. We will only
3164 * copy WAL over to the new timeline up to the end of the last
3165 * complete record, so if we did this, we would later create an
3166 * overwrite contrecord in the wrong place, breaking everything.
3167 */
3170 {
3173 }
3174
3175 if (readFile >= 0)
3176 {
3177 close(readFile);
3178 readFile = -1;
3179 }
3180
3181 /*
3182 * We only end up here without a message when XLogPageRead()
3183 * failed - in that case we already logged something. In
3184 * StandbyMode that only happens if we have been triggered, so we
3185 * shouldn't loop anymore in that case.
3186 */
3187 if (errormsg)
3189 (errmsg_internal("%s", errormsg) /* already translated */ ));
3190 }
3191
3192 /*
3193 * Check page TLI is one of the expected values.
3194 */
3196 {
3197 char fname[MAXFNAMELEN];
3198 XLogSegNo segno;
3199 int32 offset;
3200
3204 XLogFileName(fname, xlogreader->seg.ws_tli, segno,
3207 (errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u",
3209 fname,
3211 offset)));
3212 record = NULL;
3213 }
3214
3215 if (record)
3216 {
3217 /* Great, got a record */
3218 return record;
3219 }
3220 else
3221 {
3222 /* No valid record available from this source */
3223 lastSourceFailed = true;
3224
3225 /*
3226 * If archive recovery was requested, but we were still doing
3227 * crash recovery, switch to archive recovery and retry using the
3228 * offline archive. We have now replayed all the valid WAL in
3229 * pg_wal, so we are presumably now consistent.
3230 *
3231 * We require that there's at least some valid WAL present in
3232 * pg_wal, however (!fetching_ckpt). We could recover using the
3233 * WAL from the archive, even if pg_wal is completely empty, but
3234 * we'd have no idea how far we'd have to replay to reach
3235 * consistency. So err on the safe side and give up.
3236 */
3238 !fetching_ckpt)
3239 {
3241 (errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
3242 InArchiveRecovery = true;
3245
3248 minRecoveryPointTLI = replayTLI;
3249
3251
3252 /*
3253 * Before we retry, reset lastSourceFailed and currentSource
3254 * so that we will check the archive next.
3255 */
3256 lastSourceFailed = false;
3258
3259 continue;
3260 }
3261
3262 /* In standby mode, loop back to retry. Otherwise, give up. */
3264 continue;
3265 else
3266 return NULL;
3267 }
3268 }
3269}
int32_t int32
Definition: c.h:484
XLogRecPtr missingContrecPtr
Definition: xlogreader.h:215
XLogRecPtr abortedRecPtr
Definition: xlogreader.h:214
TimeLineID latestPageTLI
Definition: xlogreader.h:280
XLogRecPtr latestPagePtr
Definition: xlogreader.h:279
void * private_data
Definition: xlogreader.h:196
void SwitchIntoArchiveRecovery(XLogRecPtr EndRecPtr, TimeLineID replayTLI)
Definition: xlog.c:6209
#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:48
XLogRecord * XLogPrefetcherReadRecord(XLogPrefetcher *prefetcher, char **errmsg)
XLogReaderState * XLogPrefetcherGetReader(XLogPrefetcher *prefetcher)
static bool CheckForStandbyTrigger(void)
static bool lastSourceFailed
Definition: xlogrecovery.c:247
static XLogSource currentSource
Definition: xlogrecovery.c:246
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)

References abortedRecPtr, XLogReaderState::abortedRecPtr, ArchiveRecoveryRequested, CheckForStandbyTrigger(), CheckRecoveryConsistency(), close, currentSource, DEBUG1, emode_for_corrupt_record(), EnableStandbyMode(), XLogReaderState::EndRecPtr, ereport, errmsg(), errmsg_internal(), expectedTLEs, InArchiveRecovery, InvalidXLogRecPtr, 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, XLogRecPtrIsInvalid, and XLogSegmentOffset.

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

◆ readRecoverySignalFile()

static void readRecoverySignalFile ( void  )
static

Definition at line 1027 of file xlogrecovery.c.

1028{
1029 struct stat stat_buf;
1030
1032 return;
1033
1034 /*
1035 * Check for old recovery API file: recovery.conf
1036 */
1037 if (stat(RECOVERY_COMMAND_FILE, &stat_buf) == 0)
1038 ereport(FATAL,
1040 errmsg("using recovery command file \"%s\" is not supported",
1042
1043 /*
1044 * Remove unused .done file, if present. Ignore if absent.
1045 */
1046 unlink(RECOVERY_COMMAND_DONE);
1047
1048 /*
1049 * Check for recovery signal files and if found, fsync them since they
1050 * represent server state information. We don't sweat too much about the
1051 * possibility of fsync failure, however.
1052 *
1053 * If present, standby signal file takes precedence. If neither is present
1054 * then we won't enter archive recovery.
1055 */
1056 if (stat(STANDBY_SIGNAL_FILE, &stat_buf) == 0)
1057 {
1058 int fd;
1059
1061 S_IRUSR | S_IWUSR);
1062 if (fd >= 0)
1063 {
1064 (void) pg_fsync(fd);
1065 close(fd);
1066 }
1068 }
1069 else if (stat(RECOVERY_SIGNAL_FILE, &stat_buf) == 0)
1070 {
1071 int fd;
1072
1074 S_IRUSR | S_IWUSR);
1075 if (fd >= 0)
1076 {
1077 (void) pg_fsync(fd);
1078 close(fd);
1079 }
1081 }
1082
1083 StandbyModeRequested = false;
1086 {
1087 StandbyModeRequested = true;
1089 }
1091 {
1092 StandbyModeRequested = false;
1094 }
1095 else
1096 return;
1097
1098 /*
1099 * We don't support standby mode in standalone backends; that requires
1100 * other processes such as the WAL receiver to be alive.
1101 */
1103 ereport(FATAL,
1104 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1105 errmsg("standby mode is not supported by single-user servers")));
1106}
#define PG_BINARY
Definition: c.h:1230
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1108
int pg_fsync(int fd)
Definition: fd.c:385
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define S_IRUSR
Definition: win32_port.h:279
#define S_IWUSR
Definition: win32_port.h:282
#define STANDBY_SIGNAL_FILE
Definition: xlog.h:301
#define RECOVERY_SIGNAL_FILE
Definition: xlog.h:300
#define RECOVERY_COMMAND_FILE
Definition: xlogrecovery.c:68
#define RECOVERY_COMMAND_DONE
Definition: xlogrecovery.c:69

References ArchiveRecoveryRequested, BasicOpenFilePerm(), close, ereport, errcode(), errcode_for_file_access(), errmsg(), FATAL, 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 2984 of file xlogrecovery.c.

2985{
2986 uint8 xact_info;
2987 TimestampTz xtime;
2988 TimestampTz delayUntil;
2989 long msecs;
2990
2991 /* nothing to do if no delay configured */
2992 if (recovery_min_apply_delay <= 0)
2993 return false;
2994
2995 /* no delay is applied on a database not yet consistent */
2996 if (!reachedConsistency)
2997 return false;
2998
2999 /* nothing to do if crash recovery is requested */
3001 return false;
3002
3003 /*
3004 * Is it a COMMIT record?
3005 *
3006 * We deliberately choose not to delay aborts since they have no effect on
3007 * MVCC. We already allow replay of records that don't have a timestamp,
3008 * so there is already opportunity for issues caused by early conflicts on
3009 * standbys.
3010 */
3011 if (XLogRecGetRmid(record) != RM_XACT_ID)
3012 return false;
3013
3014 xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
3015
3016 if (xact_info != XLOG_XACT_COMMIT &&
3017 xact_info != XLOG_XACT_COMMIT_PREPARED)
3018 return false;
3019
3020 if (!getRecordTimestamp(record, &xtime))
3021 return false;
3022
3024
3025 /*
3026 * Exit without arming the latch if it's already past time to apply this
3027 * record
3028 */
3030 if (msecs <= 0)
3031 return false;
3032
3033 while (true)
3034 {
3036
3037 /* This might change recovery_min_apply_delay. */
3039
3041 break;
3042
3043 /*
3044 * Recalculate delayUntil as recovery_min_apply_delay could have
3045 * changed while waiting in this loop.
3046 */
3048
3049 /*
3050 * Wait for difference between GetCurrentTimestamp() and delayUntil.
3051 */
3053 delayUntil);
3054
3055 if (msecs <= 0)
3056 break;
3057
3058 elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs);
3059
3062 msecs,
3063 WAIT_EVENT_RECOVERY_APPLY_DELAY);
3064 }
3065 return true;
3066}
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition: timestamp.c:1756
#define DEBUG2
Definition: elog.h:29
void ResetLatch(Latch *latch)
Definition: latch.c:724
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:517
#define WL_TIMEOUT
Definition: latch.h:130
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
#define WL_LATCH_SET
Definition: latch.h:127
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:85
static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime)
int recovery_min_apply_delay
Definition: xlogrecovery.c:93

References ArchiveRecoveryRequested, CheckForStandbyTrigger(), DEBUG2, elog, GetCurrentTimestamp(), getRecordTimestamp(), HandleStartupProcInterrupts(), 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 2927 of file xlogrecovery.c.

2928{
2929 /* Don't pause unless users can connect! */
2931 return;
2932
2933 /* Don't pause after standby promotion has been triggered */
2935 return;
2936
2937 if (endOfRecovery)
2938 ereport(LOG,
2939 (errmsg("pausing at the end of recovery"),
2940 errhint("Execute pg_wal_replay_resume() to promote.")));
2941 else
2942 ereport(LOG,
2943 (errmsg("recovery has paused"),
2944 errhint("Execute pg_wal_replay_resume() to continue.")));
2945
2946 /* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */
2948 {
2951 return;
2952
2953 /*
2954 * If recovery pause is requested then set it paused. While we are in
2955 * the loop, user might resume and pause again so set this every time.
2956 */
2958
2959 /*
2960 * We wait on a condition variable that will wake us as soon as the
2961 * pause ends, but we use a timeout so we can check the above exit
2962 * condition periodically too.
2963 */
2965 WAIT_EVENT_RECOVERY_PAUSE);
2966 }
2968}
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
ConditionVariable recoveryNotPausedCV
Definition: xlogrecovery.c:359
static void ConfirmRecoveryPaused(void)
RecoveryPauseState GetRecoveryPauseState(void)

References CheckForStandbyTrigger(), ConditionVariableCancelSleep(), ConditionVariableTimedSleep(), ConfirmRecoveryPaused(), ereport, errhint(), errmsg(), GetRecoveryPauseState(), HandleStartupProcInterrupts(), LocalHotStandbyActive, LocalPromoteIsTriggered, LOG, 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 4658 of file xlogrecovery.c.

4659{
4660 if (currValue < minValue)
4661 {
4663 {
4664 bool warned_for_promote = false;
4665
4667 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4668 errmsg("hot standby is not possible because of insufficient parameter settings"),
4669 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4670 param_name,
4671 currValue,
4672 minValue)));
4673
4674 SetRecoveryPause(true);
4675
4676 ereport(LOG,
4677 (errmsg("recovery has paused"),
4678 errdetail("If recovery is unpaused, the server will shut down."),
4679 errhint("You can then restart the server after making the necessary configuration changes.")));
4680
4682 {
4684
4686 {
4687 if (!warned_for_promote)
4689 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4690 errmsg("promotion is not possible because of insufficient parameter settings"),
4691
4692 /*
4693 * Repeat the detail from above so it's easy to find
4694 * in the log.
4695 */
4696 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4697 param_name,
4698 currValue,
4699 minValue),
4700 errhint("Restart the server after making the necessary configuration changes.")));
4701 warned_for_promote = true;
4702 }
4703
4704 /*
4705 * If recovery pause is requested then set it paused. While
4706 * we are in the loop, user might resume and pause again so
4707 * set this every time.
4708 */
4710
4711 /*
4712 * We wait on a condition variable that will wake us as soon
4713 * as the pause ends, but we use a timeout so we can check the
4714 * above conditions periodically too.
4715 */
4717 WAIT_EVENT_RECOVERY_PAUSE);
4718 }
4720 }
4721
4722 ereport(FATAL,
4723 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4724 errmsg("recovery aborted because of insufficient parameter settings"),
4725 /* Repeat the detail from above so it's easy to find in the log. */
4726 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4727 param_name,
4728 currValue,
4729 minValue),
4730 errhint("You can restart the server after making the necessary configuration changes.")));
4731 }
4732}
static bool HotStandbyActiveInReplay(void)

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

Referenced by CheckRequiredParameterValues().

◆ recoveryStopsAfter()

static bool recoveryStopsAfter ( XLogReaderState record)
static

Definition at line 2728 of file xlogrecovery.c.

2729{
2730 uint8 info;
2731 uint8 xact_info;
2732 uint8 rmid;
2733 TimestampTz recordXtime = 0;
2734
2735 /*
2736 * Ignore recovery target settings when not in archive recovery (meaning
2737 * we are in crash recovery).
2738 */
2740 return false;
2741
2742 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2743 rmid = XLogRecGetRmid(record);
2744
2745 /*
2746 * There can be many restore points that share the same name; we stop at
2747 * the first one.
2748 */
2750 rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2751 {
2752 xl_restore_point *recordRestorePointData;
2753
2754 recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
2755
2756 if (strcmp(recordRestorePointData->rp_name, recoveryTargetName) == 0)
2757 {
2758 recoveryStopAfter = true;
2761 (void) getRecordTimestamp(record, &recoveryStopTime);
2762 strlcpy(recoveryStopName, recordRestorePointData->rp_name, MAXFNAMELEN);
2763
2764 ereport(LOG,
2765 (errmsg("recovery stopping at restore point \"%s\", time %s",
2768 return true;
2769 }
2770 }
2771
2772 /* Check if the target LSN has been reached */
2775 record->ReadRecPtr >= recoveryTargetLSN)
2776 {
2777 recoveryStopAfter = true;
2779 recoveryStopLSN = record->ReadRecPtr;
2780 recoveryStopTime = 0;
2781 recoveryStopName[0] = '\0';
2782 ereport(LOG,
2783 (errmsg("recovery stopping after WAL location (LSN) \"%X/%X\"",
2785 return true;
2786 }
2787
2788 if (rmid != RM_XACT_ID)
2789 return false;
2790
2791 xact_info = info & XLOG_XACT_OPMASK;
2792
2793 if (xact_info == XLOG_XACT_COMMIT ||
2794 xact_info == XLOG_XACT_COMMIT_PREPARED ||
2795 xact_info == XLOG_XACT_ABORT ||
2796 xact_info == XLOG_XACT_ABORT_PREPARED)
2797 {
2798 TransactionId recordXid;
2799
2800 /* Update the last applied transaction timestamp */
2801 if (getRecordTimestamp(record, &recordXtime))
2802 SetLatestXTime(recordXtime);
2803
2804 /* Extract the XID of the committed/aborted transaction */
2805 if (xact_info == XLOG_XACT_COMMIT_PREPARED)
2806 {
2807 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
2808 xl_xact_parsed_commit parsed;
2809
2811 xlrec,
2812 &parsed);
2813 recordXid = parsed.twophase_xid;
2814 }
2815 else if (xact_info == XLOG_XACT_ABORT_PREPARED)
2816 {
2817 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2818 xl_xact_parsed_abort parsed;
2819
2821 xlrec,
2822 &parsed);
2823 recordXid = parsed.twophase_xid;
2824 }
2825 else
2826 recordXid = XLogRecGetXid(record);
2827
2828 /*
2829 * There can be only one transaction end record with this exact
2830 * transactionid
2831 *
2832 * when testing for an xid, we MUST test for equality only, since
2833 * transactions are numbered in the order they start, not the order
2834 * they complete. A higher numbered xid will complete before you about
2835 * 50% of the time...
2836 */
2838 recordXid == recoveryTargetXid)
2839 {
2840 recoveryStopAfter = true;
2841 recoveryStopXid = recordXid;
2842 recoveryStopTime = recordXtime;
2844 recoveryStopName[0] = '\0';
2845
2846 if (xact_info == XLOG_XACT_COMMIT ||
2847 xact_info == XLOG_XACT_COMMIT_PREPARED)
2848 {
2849 ereport(LOG,
2850 (errmsg("recovery stopping after commit of transaction %u, time %s",
2853 }
2854 else if (xact_info == XLOG_XACT_ABORT ||
2855 xact_info == XLOG_XACT_ABORT_PREPARED)
2856 {
2857 ereport(LOG,
2858 (errmsg("recovery stopping after abort of transaction %u, time %s",
2861 }
2862 return true;
2863 }
2864 }
2865
2866 /* Check if we should stop as soon as reaching consistency */
2868 {
2869 ereport(LOG,
2870 (errmsg("recovery stopping after reaching consistency")));
2871
2872 recoveryStopAfter = true;
2874 recoveryStopTime = 0;
2876 recoveryStopName[0] = '\0';
2877 return true;
2878 }
2879
2880 return false;
2881}
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char rp_name[MAXFNAMELEN]
TransactionId twophase_xid
Definition: xact.h:427
TransactionId twophase_xid
Definition: xact.h:397
#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:412
bool recoveryTargetInclusive
Definition: xlogrecovery.c:86
static void SetLatestXTime(TimestampTz xtime)

References ArchiveRecoveryRequested, ereport, errmsg(), 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, xl_restore_point::rp_name, SetLatestXTime(), strlcpy(), timestamptz_to_str(), xl_xact_parsed_commit::twophase_xid, xl_xact_parsed_abort::twophase_xid, 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 2575 of file xlogrecovery.c.

2576{
2577 bool stopsHere = false;
2578 uint8 xact_info;
2579 bool isCommit;
2580 TimestampTz recordXtime = 0;
2581 TransactionId recordXid;
2582
2583 /*
2584 * Ignore recovery target settings when not in archive recovery (meaning
2585 * we are in crash recovery).
2586 */
2588 return false;
2589
2590 /* Check if we should stop as soon as reaching consistency */
2592 {
2593 ereport(LOG,
2594 (errmsg("recovery stopping after reaching consistency")));
2595
2596 recoveryStopAfter = false;
2599 recoveryStopTime = 0;
2600 recoveryStopName[0] = '\0';
2601 return true;
2602 }
2603
2604 /* Check if target LSN has been reached */
2607 record->ReadRecPtr >= recoveryTargetLSN)
2608 {
2609 recoveryStopAfter = false;
2611 recoveryStopLSN = record->ReadRecPtr;
2612 recoveryStopTime = 0;
2613 recoveryStopName[0] = '\0';
2614 ereport(LOG,
2615 (errmsg("recovery stopping before WAL location (LSN) \"%X/%X\"",
2617 return true;
2618 }
2619
2620 /* Otherwise we only consider stopping before COMMIT or ABORT records. */
2621 if (XLogRecGetRmid(record) != RM_XACT_ID)
2622 return false;
2623
2624 xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
2625
2626 if (xact_info == XLOG_XACT_COMMIT)
2627 {
2628 isCommit = true;
2629 recordXid = XLogRecGetXid(record);
2630 }
2631 else if (xact_info == XLOG_XACT_COMMIT_PREPARED)
2632 {
2633 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
2634 xl_xact_parsed_commit parsed;
2635
2636 isCommit = true;
2638 xlrec,
2639 &parsed);
2640 recordXid = parsed.twophase_xid;
2641 }
2642 else if (xact_info == XLOG_XACT_ABORT)
2643 {
2644 isCommit = false;
2645 recordXid = XLogRecGetXid(record);
2646 }
2647 else if (xact_info == XLOG_XACT_ABORT_PREPARED)
2648 {
2649 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2650 xl_xact_parsed_abort parsed;
2651
2652 isCommit = false;
2654 xlrec,
2655 &parsed);
2656 recordXid = parsed.twophase_xid;
2657 }
2658 else
2659 return false;
2660
2662 {
2663 /*
2664 * There can be only one transaction end record with this exact
2665 * transactionid
2666 *
2667 * when testing for an xid, we MUST test for equality only, since
2668 * transactions are numbered in the order they start, not the order
2669 * they complete. A higher numbered xid will complete before you about
2670 * 50% of the time...
2671 */
2672 stopsHere = (recordXid == recoveryTargetXid);
2673 }
2674
2675 /*
2676 * Note: we must fetch recordXtime regardless of recoveryTarget setting.
2677 * We don't expect getRecordTimestamp ever to fail, since we already know
2678 * this is a commit or abort record; but test its result anyway.
2679 */
2680 if (getRecordTimestamp(record, &recordXtime) &&
2682 {
2683 /*
2684 * There can be many transactions that share the same commit time, so
2685 * we stop after the last one, if we are inclusive, or stop at the
2686 * first one if we are exclusive
2687 */
2689 stopsHere = (recordXtime > recoveryTargetTime);
2690 else
2691 stopsHere = (recordXtime >= recoveryTargetTime);
2692 }
2693
2694 if (stopsHere)
2695 {
2696 recoveryStopAfter = false;
2697 recoveryStopXid = recordXid;
2698 recoveryStopTime = recordXtime;
2700 recoveryStopName[0] = '\0';
2701
2702 if (isCommit)
2703 {
2704 ereport(LOG,
2705 (errmsg("recovery stopping before commit of transaction %u, time %s",
2708 }
2709 else
2710 {
2711 ereport(LOG,
2712 (errmsg("recovery stopping before abort of transaction %u, time %s",
2715 }
2716 }
2717
2718 return stopsHere;
2719}

References ArchiveRecoveryRequested, ereport, errmsg(), 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(), xl_xact_parsed_commit::twophase_xid, xl_xact_parsed_abort::twophase_xid, 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 4453 of file xlogrecovery.c.

4454{
4455 unlink(PROMOTE_SIGNAL_FILE);
4456}

References PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ rescanLatestTimeLine()

static bool rescanLatestTimeLine ( TimeLineID  replayTLI,
XLogRecPtr  replayLSN 
)
static

Definition at line 4105 of file xlogrecovery.c.

4106{
4107 List *newExpectedTLEs;
4108 bool found;
4109 ListCell *cell;
4110 TimeLineID newtarget;
4111 TimeLineID oldtarget = recoveryTargetTLI;
4112 TimeLineHistoryEntry *currentTle = NULL;
4113
4115 if (newtarget == recoveryTargetTLI)
4116 {
4117 /* No new timelines found */
4118 return false;
4119 }
4120
4121 /*
4122 * Determine the list of expected TLIs for the new TLI
4123 */
4124
4125 newExpectedTLEs = readTimeLineHistory(newtarget);
4126
4127 /*
4128 * If the current timeline is not part of the history of the new timeline,
4129 * we cannot proceed to it.
4130 */
4131 found = false;
4132 foreach(cell, newExpectedTLEs)
4133 {
4134 currentTle = (TimeLineHistoryEntry *) lfirst(cell);
4135
4136 if (currentTle->tli == recoveryTargetTLI)
4137 {
4138 found = true;
4139 break;
4140 }
4141 }
4142 if (!found)
4143 {
4144 ereport(LOG,
4145 (errmsg("new timeline %u is not a child of database system timeline %u",
4146 newtarget,
4147 replayTLI)));
4148 return false;
4149 }
4150
4151 /*
4152 * The current timeline was found in the history file, but check that the
4153 * next timeline was forked off from it *after* the current recovery
4154 * location.
4155 */
4156 if (currentTle->end < replayLSN)
4157 {
4158 ereport(LOG,
4159 (errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
4160 newtarget,
4161 replayTLI,
4162 LSN_FORMAT_ARGS(replayLSN))));
4163 return false;
4164 }
4165
4166 /* The new timeline history seems valid. Switch target */
4167 recoveryTargetTLI = newtarget;
4169 expectedTLEs = newExpectedTLEs;
4170
4171 /*
4172 * As in StartupXLOG(), try to ensure we have all the history files
4173 * between the old target and new target in pg_wal.
4174 */
4175 restoreTimeLineHistoryFiles(oldtarget + 1, newtarget);
4176
4177 ereport(LOG,
4178 (errmsg("new target timeline is %u",
4180
4181 return true;
4182}
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
TimeLineID tli
Definition: timeline.h:27
XLogRecPtr end
Definition: timeline.h:29

References TimeLineHistoryEntry::end, ereport, errmsg(), expectedTLEs, findNewestTimeLine(), lfirst, list_free_deep(), LOG, LSN_FORMAT_ARGS, readTimeLineHistory(), recoveryTargetTLI, restoreTimeLineHistoryFiles(), and TimeLineHistoryEntry::tli.

Referenced by WaitForWALToBecomeAvailable().

◆ rm_redo_error_callback()

static void rm_redo_error_callback ( void *  arg)
static

Definition at line 2277 of file xlogrecovery.c.

2278{
2279 XLogReaderState *record = (XLogReaderState *) arg;
2281
2283 xlog_outdesc(&buf, record);
2284 xlog_block_info(&buf, record);
2285
2286 /* translator: %s is a WAL record description */
2287 errcontext("WAL redo at %X/%X for %s",
2288 LSN_FORMAT_ARGS(record->ReadRecPtr),
2289 buf.data);
2290
2291 pfree(buf.data);
2292}
#define errcontext
Definition: elog.h:196
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 4411 of file xlogrecovery.c.

4412{
4416
4417 /*
4418 * Mark the recovery pause state as 'not paused' because the paused state
4419 * ends and promotion continues if a promotion is triggered while recovery
4420 * is paused. Otherwise pg_get_wal_replay_pause_state() can mistakenly
4421 * return 'paused' while a promotion is ongoing.
4422 */
4423 SetRecoveryPause(false);
4424
4426}

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

Referenced by CheckForStandbyTrigger().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1608 of file xlogrecovery.c.

1609{
1610 char recoveryPath[MAXPGPATH];
1611
1612 /* Final update of pg_stat_recovery_prefetch. */
1614
1615 /* Shut down xlogreader */
1616 if (readFile >= 0)
1617 {
1618 close(readFile);
1619 readFile = -1;
1620 }
1623
1625 {
1626 /*
1627 * Since there might be a partial WAL segment named RECOVERYXLOG, get
1628 * rid of it.
1629 */
1630 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1631 unlink(recoveryPath); /* ignore any error */
1632
1633 /* Get rid of any remaining recovered timeline-history file, too */
1634 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1635 unlink(recoveryPath); /* ignore any error */
1636 }
1637
1638 /*
1639 * We don't need the latch anymore. It's not strictly necessary to disown
1640 * it, but let's do it for the sake of tidiness.
1641 */
1644}
void DisownLatch(Latch *latch)
Definition: latch.c:489
#define XLOGDIR
void XLogPrefetcherComputeStats(XLogPrefetcher *prefetcher)
void XLogPrefetcherFree(XLogPrefetcher *prefetcher)
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:161

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

Referenced by StartupXLOG().

◆ StartupRequestWalReceiverRestart()

void StartupRequestWalReceiverRestart ( void  )

Definition at line 4374 of file xlogrecovery.c.

4375{
4377 {
4378 ereport(LOG,
4379 (errmsg("WAL receiver process shutdown requested")));
4380
4381 pendingWalRcvRestart = true;
4382 }
4383}
bool WalRcvRunning(void)
static bool pendingWalRcvRestart
Definition: xlogrecovery.c:248

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

Referenced by StartupRereadConfig().

◆ validateRecoveryParameters()

static void validateRecoveryParameters ( void  )
static

Definition at line 1109 of file xlogrecovery.c.

1110{
1112 return;
1113
1114 /*
1115 * Check for compulsory parameters
1116 */
1118 {
1119 if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
1120 (recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0))
1122 (errmsg("specified neither \"primary_conninfo\" nor \"restore_command\""),
1123 errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1124 }
1125 else
1126 {
1127 if (recoveryRestoreCommand == NULL ||
1128 strcmp(recoveryRestoreCommand, "") == 0)
1129 ereport(FATAL,
1130 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1131 errmsg("must specify \"restore_command\" when standby mode is not enabled")));
1132 }
1133
1134 /*
1135 * Override any inconsistent requests. Note that this is a change of
1136 * behaviour in 9.5; prior to this we simply ignored a request to pause if
1137 * hot_standby = off, which was surprising behaviour.
1138 */
1142
1143 /*
1144 * Final parsing of recovery_target_time string; see also
1145 * check_recovery_target_time().
1146 */
1148 {
1152 Int32GetDatum(-1)));
1153 }
1154
1155 /*
1156 * If user specified recovery_target_timeline, validate it or compute the
1157 * "latest" value. We can't do this until after we've gotten the restore
1158 * command and set InArchiveRecovery, because we need to fetch timeline
1159 * history files from the archive.
1160 */
1162 {
1164
1165 /* Timeline 1 does not have a history file, all else should */
1166 if (rtli != 1 && !existsTimeLineHistory(rtli))
1167 ereport(FATAL,
1168 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1169 errmsg("recovery target timeline %u does not exist",
1170 rtli)));
1171 recoveryTargetTLI = rtli;
1172 }
1174 {
1175 /* We start the "latest" search from pg_control's timeline */
1177 }
1178 else
1179 {
1180 /*
1181 * else we just use the recoveryTargetTLI as already read from
1182 * ControlFile
1183 */
1185 }
1186}
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition: timeline.c:222
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:417
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:645
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
#define InvalidOid
Definition: postgres_ext.h:37
static TimestampTz DatumGetTimestampTz(Datum X)
Definition: timestamp.h:34
bool EnableHotStandby
Definition: xlog.c:121
char * recoveryRestoreCommand
Definition: xlogrecovery.c:82
char * recovery_target_time_string
Definition: xlogrecovery.c:89
char * PrimaryConnInfo
Definition: xlogrecovery.c:96

References ArchiveRecoveryRequested, Assert, CStringGetDatum(), DatumGetTimestampTz(), DirectFunctionCall3, EnableHotStandby, ereport, errcode(), errhint(), errmsg(), existsTimeLineHistory(), FATAL, 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 2463 of file xlogrecovery.c.

2464{
2465 RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2466 RelFileLocator rlocator;
2467 ForkNumber forknum;
2468 BlockNumber blkno;
2469 int block_id;
2470
2471 /* Records with no backup blocks have no need for consistency checks. */
2472 if (!XLogRecHasAnyBlockRefs(record))
2473 return;
2474
2476
2477 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2478 {
2479 Buffer buf;
2480 Page page;
2481
2482 if (!XLogRecGetBlockTagExtended(record, block_id,
2483 &rlocator, &forknum, &blkno, NULL))
2484 {
2485 /*
2486 * WAL record doesn't contain a block reference with the given id.
2487 * Do nothing.
2488 */
2489 continue;
2490 }
2491
2492 Assert(XLogRecHasBlockImage(record, block_id));
2493
2494 if (XLogRecBlockImageApply(record, block_id))
2495 {
2496 /*
2497 * WAL record has already applied the page, so bypass the
2498 * consistency check as that would result in comparing the full
2499 * page stored in the record with itself.
2500 */
2501 continue;
2502 }
2503
2504 /*
2505 * Read the contents from the current buffer and store it in a
2506 * temporary page.
2507 */
2508 buf = XLogReadBufferExtended(rlocator, forknum, blkno,
2511 if (!BufferIsValid(buf))
2512 continue;
2513
2515 page = BufferGetPage(buf);
2516
2517 /*
2518 * Take a copy of the local page where WAL has been applied to have a
2519 * comparison base before masking it...
2520 */
2521 memcpy(replay_image_masked, page, BLCKSZ);
2522
2523 /* No need for this page anymore now that a copy is in. */
2525
2526 /*
2527 * If the block LSN is already ahead of this WAL record, we can't
2528 * expect contents to match. This can happen if recovery is
2529 * restarted.
2530 */
2532 continue;
2533
2534 /*
2535 * Read the contents from the backup copy, stored in WAL record and
2536 * store it in a temporary page. There is no need to allocate a new
2537 * page here, a local buffer is fine to hold its contents and a mask
2538 * can be directly applied on it.
2539 */
2540 if (!RestoreBlockImage(record, block_id, primary_image_masked))
2541 ereport(ERROR,
2542 (errcode(ERRCODE_INTERNAL_ERROR),
2543 errmsg_internal("%s", record->errormsg_buf)));
2544
2545 /*
2546 * If masking function is defined, mask both the primary and replay
2547 * images
2548 */
2549 if (rmgr.rm_mask != NULL)
2550 {
2551 rmgr.rm_mask(replay_image_masked, blkno);
2552 rmgr.rm_mask(primary_image_masked, blkno);
2553 }
2554
2555 /* Time to compare the primary and replay images. */
2556 if (memcmp(replay_image_masked, primary_image_masked, BLCKSZ) != 0)
2557 {
2558 elog(FATAL,
2559 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2560 rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
2561 forknum, blkno);
2562 }
2563 }
2564}
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:4941
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5158
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:191
@ RBM_NORMAL_NO_LOG
Definition: bufmgr.h:51
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:351
Pointer Page
Definition: bufpage.h:81
static XLogRecPtr PageGetLSN(const char *page)
Definition: bufpage.h:386
ForkNumber
Definition: relpath.h:56
RelFileNumber relNumber
void(* rm_mask)(char *pagedata, BlockNumber blkno)
char * errormsg_buf
Definition: xlogreader.h:311
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
Definition: xlogreader.c:1997
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:2056
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:425
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:418
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:423
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417
Buffer XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)
Definition: xlogutils.c:471

References Assert, buf, BUFFER_LOCK_EXCLUSIVE, BufferGetPage(), BufferIsValid(), RelFileLocator::dbOid, elog, XLogReaderState::EndRecPtr, ereport, errcode(), errmsg_internal(), ERROR, XLogReaderState::errormsg_buf, FATAL, GetRmgr(), InvalidBuffer, LockBuffer(), PageGetLSN(), primary_image_masked, RBM_NORMAL_NO_LOG, RelFileLocator::relNumber, replay_image_masked, RestoreBlockImage(), RmgrData::rm_mask, 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 3543 of file xlogrecovery.c.

3547{
3548 static TimestampTz last_fail_time = 0;
3550 bool streaming_reply_sent = false;
3551
3552 /*-------
3553 * Standby mode is implemented by a state machine:
3554 *
3555 * 1. Read from either archive or pg_wal (XLOG_FROM_ARCHIVE), or just
3556 * pg_wal (XLOG_FROM_PG_WAL)
3557 * 2. Check for promotion trigger request
3558 * 3. Read from primary server via walreceiver (XLOG_FROM_STREAM)
3559 * 4. Rescan timelines
3560 * 5. Sleep wal_retrieve_retry_interval milliseconds, and loop back to 1.
3561 *
3562 * Failure to read from the current source advances the state machine to
3563 * the next state.
3564 *
3565 * 'currentSource' indicates the current state. There are no currentSource
3566 * values for "check trigger", "rescan timelines", and "sleep" states,
3567 * those actions are taken when reading from the previous source fails, as
3568 * part of advancing to the next state.
3569 *
3570 * If standby mode is turned off while reading WAL from stream, we move
3571 * to XLOG_FROM_ARCHIVE and reset lastSourceFailed, to force fetching
3572 * the files (which would be required at end of recovery, e.g., timeline
3573 * history file) from archive or pg_wal. We don't need to kill WAL receiver
3574 * here because it's already stopped when standby mode is turned off at
3575 * the end of recovery.
3576 *-------
3577 */
3578 if (!InArchiveRecovery)
3580 else if (currentSource == XLOG_FROM_ANY ||
3582 {
3583 lastSourceFailed = false;
3585 }
3586
3587 for (;;)
3588 {
3589 XLogSource oldSource = currentSource;
3590 bool startWalReceiver = false;
3591
3592 /*
3593 * First check if we failed to read from the current source, and
3594 * advance the state machine if so. The failure to read might've
3595 * happened outside this function, e.g when a CRC check fails on a
3596 * record, or within this loop.
3597 */
3598 if (lastSourceFailed)
3599 {
3600 /*
3601 * Don't allow any retry loops to occur during nonblocking
3602 * readahead. Let the caller process everything that has been
3603 * decoded already first.
3604 */
3605 if (nonblocking)
3606 return XLREAD_WOULDBLOCK;
3607
3608 switch (currentSource)
3609 {
3610 case XLOG_FROM_ARCHIVE:
3611 case XLOG_FROM_PG_WAL:
3612
3613 /*
3614 * Check to see if promotion is requested. Note that we do
3615 * this only after failure, so when you promote, we still
3616 * finish replaying as much as we can from archive and
3617 * pg_wal before failover.
3618 */
3620 {
3622 return XLREAD_FAIL;
3623 }
3624
3625 /*
3626 * Not in standby mode, and we've now tried the archive
3627 * and pg_wal.
3628 */
3629 if (!StandbyMode)
3630 return XLREAD_FAIL;
3631
3632 /*
3633 * Move to XLOG_FROM_STREAM state, and set to start a
3634 * walreceiver if necessary.
3635 */
3637 startWalReceiver = true;
3638 break;
3639
3640 case XLOG_FROM_STREAM:
3641
3642 /*
3643 * Failure while streaming. Most likely, we got here
3644 * because streaming replication was terminated, or
3645 * promotion was triggered. But we also get here if we
3646 * find an invalid record in the WAL streamed from the
3647 * primary, in which case something is seriously wrong.
3648 * There's little chance that the problem will just go
3649 * away, but PANIC is not good for availability either,
3650 * especially in hot standby mode. So, we treat that the
3651 * same as disconnection, and retry from archive/pg_wal
3652 * again. The WAL in the archive should be identical to
3653 * what was streamed, so it's unlikely that it helps, but
3654 * one can hope...
3655 */
3656
3657 /*
3658 * We should be able to move to XLOG_FROM_STREAM only in
3659 * standby mode.
3660 */
3662
3663 /*
3664 * Before we leave XLOG_FROM_STREAM state, make sure that
3665 * walreceiver is not active, so that it won't overwrite
3666 * WAL that we restore from archive.
3667 */
3669
3670 /*
3671 * Before we sleep, re-scan for possible new timelines if
3672 * we were requested to recover to the latest timeline.
3673 */
3675 {
3676 if (rescanLatestTimeLine(replayTLI, replayLSN))
3677 {
3679 break;
3680 }
3681 }
3682
3683 /*
3684 * XLOG_FROM_STREAM is the last state in our state
3685 * machine, so we've exhausted all the options for
3686 * obtaining the requested WAL. We're going to loop back
3687 * and retry from the archive, but if it hasn't been long
3688 * since last attempt, sleep wal_retrieve_retry_interval
3689 * milliseconds to avoid busy-waiting.
3690 */
3692 if (!TimestampDifferenceExceeds(last_fail_time, now,
3694 {
3695 long wait_time;
3696
3697 wait_time = wal_retrieve_retry_interval -
3698 TimestampDifferenceMilliseconds(last_fail_time, now);
3699
3700 elog(LOG, "waiting for WAL to become available at %X/%X",
3701 LSN_FORMAT_ARGS(RecPtr));
3702
3703 /* Do background tasks that might benefit us later. */
3705
3709 wait_time,
3710 WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL);
3713
3714 /* Handle interrupt signals of startup process */
3716 }
3717 last_fail_time = now;
3719 break;
3720
3721 default:
3722 elog(ERROR, "unexpected WAL source %d", currentSource);
3723 }
3724 }
3725 else if (currentSource == XLOG_FROM_PG_WAL)
3726 {
3727 /*
3728 * We just successfully read a file in pg_wal. We prefer files in
3729 * the archive over ones in pg_wal, so try the next file again
3730 * from the archive first.
3731 */
3734 }
3735
3736 if (currentSource != oldSource)
3737 elog(DEBUG2, "switched WAL source from %s to %s after %s",
3739 lastSourceFailed ? "failure" : "success");
3740
3741 /*
3742 * We've now handled possible failure. Try to read from the chosen
3743 * source.
3744 */
3745 lastSourceFailed = false;
3746
3747 switch (currentSource)
3748 {
3749 case XLOG_FROM_ARCHIVE:
3750 case XLOG_FROM_PG_WAL:
3751
3752 /*
3753 * WAL receiver must not be running when reading WAL from
3754 * archive or pg_wal.
3755 */
3757
3758 /* Close any old file we might have open. */
3759 if (readFile >= 0)
3760 {
3761 close(readFile);
3762 readFile = -1;
3763 }
3764 /* Reset curFileTLI if random fetch. */
3765 if (randAccess)
3766 curFileTLI = 0;
3767
3768 /*
3769 * Try to restore the file from archive, or read an existing
3770 * file from pg_wal.
3771 */
3775 if (readFile >= 0)
3776 return XLREAD_SUCCESS; /* success! */
3777
3778 /*
3779 * Nope, not found in archive or pg_wal.
3780 */
3781 lastSourceFailed = true;
3782 break;
3783
3784 case XLOG_FROM_STREAM:
3785 {
3786 bool havedata;
3787
3788 /*
3789 * We should be able to move to XLOG_FROM_STREAM only in
3790 * standby mode.
3791 */
3793
3794 /*
3795 * First, shutdown walreceiver if its restart has been
3796 * requested -- but no point if we're already slated for
3797 * starting it.
3798 */
3799 if (pendingWalRcvRestart && !startWalReceiver)
3800 {
3802
3803 /*
3804 * Re-scan for possible new timelines if we were
3805 * requested to recover to the latest timeline.
3806 */
3809 rescanLatestTimeLine(replayTLI, replayLSN);
3810
3811 startWalReceiver = true;
3812 }
3813 pendingWalRcvRestart = false;
3814
3815 /*
3816 * Launch walreceiver if needed.
3817 *
3818 * If fetching_ckpt is true, RecPtr points to the initial
3819 * checkpoint location. In that case, we use RedoStartLSN
3820 * as the streaming start position instead of RecPtr, so
3821 * that when we later jump backwards to start redo at
3822 * RedoStartLSN, we will have the logs streamed already.
3823 */
3824 if (startWalReceiver &&
3825 PrimaryConnInfo && strcmp(PrimaryConnInfo, "") != 0)
3826 {
3827 XLogRecPtr ptr;
3828 TimeLineID tli;
3829
3830 if (fetching_ckpt)
3831 {
3832 ptr = RedoStartLSN;
3833 tli = RedoStartTLI;
3834 }
3835 else
3836 {
3837 ptr = RecPtr;
3838
3839 /*
3840 * Use the record begin position to determine the
3841 * TLI, rather than the position we're reading.
3842 */
3843 tli = tliOfPointInHistory(tliRecPtr, expectedTLEs);
3844
3845 if (curFileTLI > 0 && tli < curFileTLI)
3846 elog(ERROR, "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3847 LSN_FORMAT_ARGS(tliRecPtr),
3848 tli, curFileTLI);
3849 }
3850 curFileTLI = tli;
3855 flushedUpto = 0;
3856 }
3857
3858 /*
3859 * Check if WAL receiver is active or wait to start up.
3860 */
3861 if (!WalRcvStreaming())
3862 {
3863 lastSourceFailed = true;
3864 break;
3865 }
3866
3867 /*
3868 * Walreceiver is active, so see if new data has arrived.
3869 *
3870 * We only advance XLogReceiptTime when we obtain fresh
3871 * WAL from walreceiver and observe that we had already
3872 * processed everything before the most recent "chunk"
3873 * that it flushed to disk. In steady state where we are
3874 * keeping up with the incoming data, XLogReceiptTime will
3875 * be updated on each cycle. When we are behind,
3876 * XLogReceiptTime will not advance, so the grace time
3877 * allotted to conflicting queries will decrease.
3878 */
3879 if (RecPtr < flushedUpto)
3880 havedata = true;
3881 else
3882 {
3883 XLogRecPtr latestChunkStart;
3884
3885 flushedUpto = GetWalRcvFlushRecPtr(&latestChunkStart, &receiveTLI);
3886 if (RecPtr < flushedUpto && receiveTLI == curFileTLI)
3887 {
3888 havedata = true;
3889 if (latestChunkStart <= RecPtr)
3890 {
3893 }
3894 }
3895 else
3896 havedata = false;
3897 }
3898 if (havedata)
3899 {
3900 /*
3901 * Great, streamed far enough. Open the file if it's
3902 * not open already. Also read the timeline history
3903 * file if we haven't initialized timeline history
3904 * yet; it should be streamed over and present in
3905 * pg_wal by now. Use XLOG_FROM_STREAM so that source
3906 * info is set correctly and XLogReceiptTime isn't
3907 * changed.
3908 *
3909 * NB: We must set readTimeLineHistory based on
3910 * recoveryTargetTLI, not receiveTLI. Normally they'll
3911 * be the same, but if recovery_target_timeline is
3912 * 'latest' and archiving is configured, then it's
3913 * possible that we managed to retrieve one or more
3914 * new timeline history files from the archive,
3915 * updating recoveryTargetTLI.
3916 */
3917 if (readFile < 0)
3918 {
3919 if (!expectedTLEs)
3922 XLOG_FROM_STREAM, false);
3923 Assert(readFile >= 0);
3924 }
3925 else
3926 {
3927 /* just make sure source info is correct... */
3930 return XLREAD_SUCCESS;
3931 }
3932 break;
3933 }
3934
3935 /* In nonblocking mode, return rather than sleeping. */
3936 if (nonblocking)
3937 return XLREAD_WOULDBLOCK;
3938
3939 /*
3940 * Data not here yet. Check for trigger, then wait for
3941 * walreceiver to wake us up when new WAL arrives.
3942 */
3944 {
3945 /*
3946 * Note that we don't return XLREAD_FAIL immediately
3947 * here. After being triggered, we still want to
3948 * replay all the WAL that was already streamed. It's
3949 * in pg_wal now, so we just treat this as a failure,
3950 * and the state machine will move on to replay the
3951 * streamed WAL from pg_wal, and then recheck the
3952 * trigger and exit replay.
3953 */
3954 lastSourceFailed = true;
3955 break;
3956 }
3957
3958 /*
3959 * Since we have replayed everything we have received so
3960 * far and are about to start waiting for more WAL, let's
3961 * tell the upstream server our replay location now so
3962 * that pg_stat_replication doesn't show stale
3963 * information.
3964 */
3965 if (!streaming_reply_sent)
3966 {
3968 streaming_reply_sent = true;
3969 }
3970
3971 /* Do any background tasks that might benefit us later. */
3973
3974 /* Update pg_stat_recovery_prefetch before sleeping. */
3976
3977 /*
3978 * Wait for more WAL to arrive, when we will be woken
3979 * immediately by the WAL receiver.
3980 */
3983 -1L,
3984 WAIT_EVENT_RECOVERY_WAL_STREAM);
3986 break;
3987 }
3988
3989 default:
3990 elog(ERROR, "unexpected WAL source %d", currentSource);
3991 }
3992
3993 /*
3994 * Check for recovery pause here so that we can confirm more quickly
3995 * that a requested pause has actually taken effect.
3996 */
3997 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
3999 recoveryPausesHere(false);
4000
4001 /*
4002 * This possibly-long loop needs to handle interrupts of startup
4003 * process.
4004 */
4006 }
4007
4008 return XLREAD_FAIL; /* not reached */
4009}
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1780
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
void KnownAssignedTransactionIdsIdleMaintenance(void)
Definition: procarray.c:4540
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, const char *slotname, bool create_temp_slot)
void SetInstallXLogFileSegmentActive(void)
Definition: xlog.c:9484
int wal_retrieve_retry_interval
Definition: xlog.c:134
@ XLREAD_WOULDBLOCK
Definition: xlogreader.h:353
@ XLREAD_SUCCESS
Definition: xlogreader.h:351
@ XLREAD_FAIL
Definition: xlogreader.h:352
char * PrimarySlotName
Definition: xlogrecovery.c:97
static TimeLineID curFileTLI
Definition: xlogrecovery.c:124
static const char *const xlogSourceNames[]
Definition: xlogrecovery.c:218
static int XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source)
static TimeLineID receiveTLI
Definition: xlogrecovery.c:263
static int XLogFileRead(XLogSegNo segno, TimeLineID tli, XLogSource source, bool notfoundOk)
static XLogSegNo readSegNo
Definition: xlogrecovery.c:231
static void SetCurrentChunkStartTime(TimestampTz xtime)
bool wal_receiver_create_temp_slot
Definition: xlogrecovery.c:98
static XLogRecPtr flushedUpto
Definition: xlogrecovery.c:262
static bool rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN)

References Assert, CheckForStandbyTrigger(), close, curFileTLI, currentSource, DEBUG2, elog, ERROR, expectedTLEs, flushedUpto, GetCurrentTimestamp(), GetWalRcvFlushRecPtr(), HandleStartupProcInterrupts(), InArchiveRecovery, KnownAssignedTransactionIdsIdleMaintenance(), lastSourceFailed, LOG, LSN_FORMAT_ARGS, now(), pendingWalRcvRestart, PrimaryConnInfo, PrimarySlotName, readFile, readSegNo, readSource, readTimeLineHistory(), receiveTLI, RECOVERY_NOT_PAUSED, RECOVERY_TARGET_TIMELINE_LATEST, recoveryPausesHere(), recoveryTargetTimeLineGoal, recoveryTargetTLI, XLogRecoveryCtlData::recoveryWakeupLatch, RedoStartLSN, RedoStartTLI, RequestXLogStreaming(), rescanLatestTimeLine(), ResetLatch(), SetCurrentChunkStartTime(), SetInstallXLogFileSegmentActive(), StandbyMode, TimestampDifferenceExceeds(), TimestampDifferenceMilliseconds(), tliOfPointInHistory(), WaitLatch(), wal_receiver_create_temp_slot, wal_retrieve_retry_interval, WalRcvForceReply(), 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 2338 of file xlogrecovery.c.

2339{
2340 int block_id;
2341
2342 /* decode block references */
2343 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2344 {
2345 RelFileLocator rlocator;
2346 ForkNumber forknum;
2347 BlockNumber blk;
2348
2349 if (!XLogRecGetBlockTagExtended(record, block_id,
2350 &rlocator, &forknum, &blk, NULL))
2351 continue;
2352
2353 if (forknum != MAIN_FORKNUM)
2354 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, fork %u, blk %u",
2355 block_id,
2356 rlocator.spcOid, rlocator.dbOid,
2357 rlocator.relNumber,
2358 forknum,
2359 blk);
2360 else
2361 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, blk %u",
2362 block_id,
2363 rlocator.spcOid, rlocator.dbOid,
2364 rlocator.relNumber,
2365 blk);
2366 if (XLogRecHasBlockImage(record, block_id))
2367 appendStringInfoString(buf, " FPW");
2368 }
2369}
@ MAIN_FORKNUM
Definition: relpath.h:58

References appendStringInfo(), appendStringInfoString(), buf, RelFileLocator::dbOid, 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 2299 of file xlogrecovery.c.

2300{
2301 RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2302 uint8 info = XLogRecGetInfo(record);
2303 const char *id;
2304
2307
2308 id = rmgr.rm_identify(info);
2309 if (id == NULL)
2310 appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2311 else
2312 appendStringInfo(buf, "%s: ", id);
2313
2314 rmgr.rm_desc(buf, record);
2315}
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
const char *(* rm_identify)(uint8 info)
const char * rm_name
void(* rm_desc)(StringInfo buf, XLogReaderState *record)

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, GetRmgr(), RmgrData::rm_desc, RmgrData::rm_identify, RmgrData::rm_name, 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 4192 of file xlogrecovery.c.

4194{
4195 char xlogfname[MAXFNAMELEN];
4196 char activitymsg[MAXFNAMELEN + 16];
4197 char path[MAXPGPATH];
4198 int fd;
4199
4200 XLogFileName(xlogfname, tli, segno, wal_segment_size);
4201
4202 switch (source)
4203 {
4204 case XLOG_FROM_ARCHIVE:
4205 /* Report recovery progress in PS display */
4206 snprintf(activitymsg, sizeof(activitymsg), "waiting for %s",
4207 xlogfname);
4208 set_ps_display(activitymsg);
4209
4210 if (!RestoreArchivedFile(path, xlogfname,
4211 "RECOVERYXLOG",
4213 InRedo))
4214 return -1;
4215 break;
4216
4217 case XLOG_FROM_PG_WAL:
4218 case XLOG_FROM_STREAM:
4219 XLogFilePath(path, tli, segno, wal_segment_size);
4220 break;
4221
4222 default:
4223 elog(ERROR, "invalid XLogFileRead source %d", source);
4224 }
4225
4226 /*
4227 * If the segment was fetched from archival storage, replace the existing
4228 * xlog segment (if any) with the archival version.
4229 */
4231 {
4233 KeepFileRestoredFromArchive(path, xlogfname);
4234
4235 /*
4236 * Set path to point at the new file in pg_wal.
4237 */
4238 snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
4239 }
4240
4241 fd = BasicOpenFile(path, O_RDONLY | PG_BINARY);
4242 if (fd >= 0)
4243 {
4244 /* Success! */
4245 curFileTLI = tli;
4246
4247 /* Report recovery progress in PS display */
4248 snprintf(activitymsg, sizeof(activitymsg), "recovering %s",
4249 xlogfname);
4250 set_ps_display(activitymsg);
4251
4252 /* Track source of data in assorted state variables */
4255 /* In FROM_STREAM case, caller tracks receipt time, not me */
4256 if (source != XLOG_FROM_STREAM)
4258
4259 return fd;
4260 }
4261 if (errno != ENOENT || !notfoundOk) /* unexpected failure? */
4262 ereport(PANIC,
4264 errmsg("could not open file \"%s\": %m", path)));
4265 return -1;
4266}
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:9492
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)
Definition: xlogarchive.c:358

References Assert, BasicOpenFile(), curFileTLI, elog, ereport, errcode_for_file_access(), errmsg(), ERROR, 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 4274 of file xlogrecovery.c.

4275{
4276 char path[MAXPGPATH];
4277 ListCell *cell;
4278 int fd;
4279 List *tles;
4280
4281 /*
4282 * Loop looking for a suitable timeline ID: we might need to read any of
4283 * the timelines listed in expectedTLEs.
4284 *
4285 * We expect curFileTLI on entry to be the TLI of the preceding file in
4286 * sequence, or 0 if there was no predecessor. We do not allow curFileTLI
4287 * to go backwards; this prevents us from picking up the wrong file when a
4288 * parent timeline extends to higher segment numbers than the child we
4289 * want to read.
4290 *
4291 * If we haven't read the timeline history file yet, read it now, so that
4292 * we know which TLIs to scan. We don't save the list in expectedTLEs,
4293 * however, unless we actually find a valid segment. That way if there is
4294 * neither a timeline history file nor a WAL segment in the archive, and
4295 * streaming replication is set up, we'll read the timeline history file
4296 * streamed from the primary when we start streaming, instead of
4297 * recovering with a dummy history generated here.
4298 */
4299 if (expectedTLEs)
4300 tles = expectedTLEs;
4301 else
4303
4304 foreach(cell, tles)
4305 {
4307 TimeLineID tli = hent->tli;
4308
4309 if (tli < curFileTLI)
4310 break;