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/pgstat_internal.h"
#include "utils/pg_lsn.h"
#include "utils/ps_status.h"
#include "utils/pg_rusage.h"
Include dependency graph for xlogrecovery.c:

Go to the source code of this file.

Data Structures

struct  XLogPageReadPrivate
 
struct  XLogRecoveryCtlData
 

Macros

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

Typedefs

typedef struct XLogPageReadPrivate XLogPageReadPrivate
 
typedef struct XLogRecoveryCtlData XLogRecoveryCtlData
 

Enumerations

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

Functions

static void ApplyWalRecord (XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
 
static void EnableStandbyMode (void)
 
static void readRecoverySignalFile (void)
 
static void validateRecoveryParameters (void)
 
static bool read_backup_label (XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
 
static bool read_tablespace_map (List **tablespaces)
 
static void xlogrecovery_redo (XLogReaderState *record, TimeLineID replayTLI)
 
static void CheckRecoveryConsistency (void)
 
static void rm_redo_error_callback (void *arg)
 
static void xlog_block_info (StringInfo buf, XLogReaderState *record)
 
static void checkTimeLineSwitch (XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI, TimeLineID replayTLI)
 
static bool getRecordTimestamp (XLogReaderState *record, TimestampTz *recordXtime)
 
static void verifyBackupPageConsistency (XLogReaderState *record)
 
static bool recoveryStopsBefore (XLogReaderState *record)
 
static bool recoveryStopsAfter (XLogReaderState *record)
 
static 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 pg_noreturn void error_multiple_recovery_targets (void)
 
bool check_recovery_target (char **newval, void **extra, GucSource source)
 
void assign_recovery_target (const char *newval, void *extra)
 
bool check_recovery_target_lsn (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_lsn (const char *newval, void *extra)
 
bool check_recovery_target_name (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_name (const char *newval, void *extra)
 
bool check_recovery_target_time (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_time (const char *newval, void *extra)
 
bool check_recovery_target_timeline (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_timeline (const char *newval, void *extra)
 
bool check_recovery_target_xid (char **newval, void **extra, GucSource source)
 
void assign_recovery_target_xid (const char *newval, void *extra)
 

Variables

const struct config_enum_entry recovery_target_action_options []
 
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 70 of file xlogrecovery.c.

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 69 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 210 of file xlogrecovery.c.

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

Function Documentation

◆ ApplyWalRecord()

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

Definition at line 1912 of file xlogrecovery.c.

1913{
1914 ErrorContextCallback errcallback;
1915 bool switchedTLI = false;
1916
1917 /* Setup error traceback support for ereport() */
1918 errcallback.callback = rm_redo_error_callback;
1919 errcallback.arg = xlogreader;
1920 errcallback.previous = error_context_stack;
1921 error_context_stack = &errcallback;
1922
1923 /*
1924 * TransamVariables->nextXid must be beyond record's xid.
1925 */
1927
1928 /*
1929 * Before replaying this record, check if this record causes the current
1930 * timeline to change. The record is already considered to be part of the
1931 * new timeline, so we update replayTLI before replaying it. That's
1932 * important so that replayEndTLI, which is recorded as the minimum
1933 * recovery point's TLI if recovery stops after this record, is set
1934 * correctly.
1935 */
1936 if (record->xl_rmid == RM_XLOG_ID)
1937 {
1938 TimeLineID newReplayTLI = *replayTLI;
1939 TimeLineID prevReplayTLI = *replayTLI;
1940 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1941
1942 if (info == XLOG_CHECKPOINT_SHUTDOWN)
1943 {
1944 CheckPoint checkPoint;
1945
1946 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
1947 newReplayTLI = checkPoint.ThisTimeLineID;
1948 prevReplayTLI = checkPoint.PrevTimeLineID;
1949 }
1950 else if (info == XLOG_END_OF_RECOVERY)
1951 {
1952 xl_end_of_recovery xlrec;
1953
1954 memcpy(&xlrec, XLogRecGetData(xlogreader), sizeof(xl_end_of_recovery));
1955 newReplayTLI = xlrec.ThisTimeLineID;
1956 prevReplayTLI = xlrec.PrevTimeLineID;
1957 }
1958
1959 if (newReplayTLI != *replayTLI)
1960 {
1961 /* Check that it's OK to switch to this TLI */
1963 newReplayTLI, prevReplayTLI, *replayTLI);
1964
1965 /* Following WAL records should be run with new TLI */
1966 *replayTLI = newReplayTLI;
1967 switchedTLI = true;
1968 }
1969 }
1970
1971 /*
1972 * Update shared replayEndRecPtr before replaying this record, so that
1973 * XLogFlush will update minRecoveryPoint correctly.
1974 */
1977 XLogRecoveryCtl->replayEndTLI = *replayTLI;
1979
1980 /*
1981 * If we are attempting to enter Hot Standby mode, process XIDs we see
1982 */
1986
1987 /*
1988 * Some XLOG record types that are related to recovery are processed
1989 * directly here, rather than in xlog_redo()
1990 */
1991 if (record->xl_rmid == RM_XLOG_ID)
1992 xlogrecovery_redo(xlogreader, *replayTLI);
1993
1994 /* Now apply the WAL record itself */
1996
1997 /*
1998 * After redo, check whether the backup pages associated with the WAL
1999 * record are consistent with the existing pages. This check is done only
2000 * if consistency check is enabled for this record.
2001 */
2002 if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
2004
2005 /* Pop the error context stack */
2006 error_context_stack = errcallback.previous;
2007
2008 /*
2009 * Update lastReplayedEndRecPtr after this record has been successfully
2010 * replayed.
2011 */
2015 XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
2017
2018 /* ------
2019 * Wakeup walsenders:
2020 *
2021 * On the standby, the WAL is flushed first (which will only wake up
2022 * physical walsenders) and then applied, which will only wake up logical
2023 * walsenders.
2024 *
2025 * Indeed, logical walsenders on standby can't decode and send data until
2026 * it's been applied.
2027 *
2028 * Physical walsenders don't need to be woken up during replay unless
2029 * cascading replication is allowed and time line change occurred (so that
2030 * they can notice that they are on a new time line).
2031 *
2032 * That's why the wake up conditions are for:
2033 *
2034 * - physical walsenders in case of new time line and cascade
2035 * replication is allowed
2036 * - logical walsenders in case cascade replication is allowed (could not
2037 * be created otherwise)
2038 * ------
2039 */
2041 WalSndWakeup(switchedTLI, true);
2042
2043 /*
2044 * If rm_redo called XLogRequestWalReceiverReply, then we wake up the
2045 * receiver so that it notices the updated lastReplayedEndRecPtr and sends
2046 * a reply to the primary.
2047 */
2049 {
2052 }
2053
2054 /* Allow read-only connections if we're consistent now */
2056
2057 /* Is this a timeline switch? */
2058 if (switchedTLI)
2059 {
2060 /*
2061 * Before we continue on the new timeline, clean up any (possibly
2062 * bogus) future WAL segments on the old timeline.
2063 */
2065
2066 /* Reset the prefetcher. */
2068 }
2069}
uint8_t uint8
Definition: c.h:500
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:340
TimeLineID replayEndTLI
Definition: xlogrecovery.c:349
TimeLineID lastReplayedTLI
Definition: xlogrecovery.c:341
XLogRecPtr replayEndRecPtr
Definition: xlogrecovery.c:348
XLogRecPtr lastReplayedReadRecPtr
Definition: xlogrecovery.c:339
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:1381
#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:3946
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:365
static bool doRequestWalReceiverReply
Definition: xlogrecovery.c:186
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:189
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 4808 of file xlogrecovery.c.

4809{
4813
4814 if (newval && strcmp(newval, "") != 0)
4816 else
4818}
#define newval
RecoveryTargetType recoveryTarget
Definition: xlogrecovery.c:86
static pg_noreturn void error_multiple_recovery_targets(void)
@ RECOVERY_TARGET_IMMEDIATE
Definition: xlogrecovery.h:30
@ RECOVERY_TARGET_UNSET
Definition: xlogrecovery.h:25

References error_multiple_recovery_targets(), 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 4847 of file xlogrecovery.c.

4848{
4852
4853 if (newval && strcmp(newval, "") != 0)
4854 {
4856 recoveryTargetLSN = *((XLogRecPtr *) extra);
4857 }
4858 else
4860}
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr recoveryTargetLSN
Definition: xlogrecovery.c:93
@ RECOVERY_TARGET_LSN
Definition: xlogrecovery.h:29

References error_multiple_recovery_targets(), 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 4882 of file xlogrecovery.c.

4883{
4887
4888 if (newval && strcmp(newval, "") != 0)
4889 {
4892 }
4893 else
4895}
const char * recoveryTargetName
Definition: xlogrecovery.c:92
@ RECOVERY_TARGET_NAME
Definition: xlogrecovery.h:28

References error_multiple_recovery_targets(), newval, RECOVERY_TARGET_NAME, RECOVERY_TARGET_UNSET, recoveryTarget, and recoveryTargetName.

◆ assign_recovery_target_time()

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

◆ assign_recovery_target_timeline()

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

Definition at line 5011 of file xlogrecovery.c.

5012{
5015 recoveryTargetTLIRequested = (TimeLineID) strtoul(newval, NULL, 0);
5016 else
5018}
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
Definition: xlogrecovery.c:121
TimeLineID recoveryTargetTLIRequested
Definition: xlogrecovery.c:122
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 5047 of file xlogrecovery.c.

5048{
5052
5053 if (newval && strcmp(newval, "") != 0)
5054 {
5056 recoveryTargetXid = *((TransactionId *) extra);
5057 }
5058 else
5060}
uint32 TransactionId
Definition: c.h:623
TransactionId recoveryTargetXid
Definition: xlogrecovery.c:89
@ RECOVERY_TARGET_XID
Definition: xlogrecovery.h:26

References error_multiple_recovery_targets(), 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 4754 of file xlogrecovery.c.

4755{
4756 if (*newval && strcmp(*newval, "") != 0 &&
4758 return false;
4759
4760 return true;
4761}
#define WARNING
Definition: elog.h:36
bool ReplicationSlotValidateName(const char *name, int elevel)
Definition: slot.c:267

References newval, ReplicationSlotValidateName(), and WARNING.

◆ check_recovery_target()

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

Definition at line 4794 of file xlogrecovery.c.

4795{
4796 if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
4797 {
4798 GUC_check_errdetail("The only allowed value is \"immediate\".");
4799 return false;
4800 }
4801 return true;
4802}
#define GUC_check_errdetail
Definition: guc.h:481

References GUC_check_errdetail, and newval.

◆ check_recovery_target_lsn()

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

Definition at line 4824 of file xlogrecovery.c.

4825{
4826 if (strcmp(*newval, "") != 0)
4827 {
4828 XLogRecPtr lsn;
4829 XLogRecPtr *myextra;
4830 bool have_error = false;
4831
4832 lsn = pg_lsn_in_internal(*newval, &have_error);
4833 if (have_error)
4834 return false;
4835
4836 myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
4837 *myextra = lsn;
4838 *extra = myextra;
4839 }
4840 return true;
4841}
#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 4866 of file xlogrecovery.c.

4867{
4868 /* Use the value of newval directly */
4869 if (strlen(*newval) >= MAXFNAMELEN)
4870 {
4871 GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
4872 "recovery_target_name", MAXFNAMELEN - 1);
4873 return false;
4874 }
4875 return true;
4876}
#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 4907 of file xlogrecovery.c.

4908{
4909 if (strcmp(*newval, "") != 0)
4910 {
4911 /* reject some special values */
4912 if (strcmp(*newval, "now") == 0 ||
4913 strcmp(*newval, "today") == 0 ||
4914 strcmp(*newval, "tomorrow") == 0 ||
4915 strcmp(*newval, "yesterday") == 0)
4916 {
4917 return false;
4918 }
4919
4920 /*
4921 * parse timestamp value (see also timestamptz_in())
4922 */
4923 {
4924 char *str = *newval;
4925 fsec_t fsec;
4926 struct pg_tm tt,
4927 *tm = &tt;
4928 int tz;
4929 int dtype;
4930 int nf;
4931 int dterr;
4932 char *field[MAXDATEFIELDS];
4933 int ftype[MAXDATEFIELDS];
4934 char workbuf[MAXDATELEN + MAXDATEFIELDS];
4935 DateTimeErrorExtra dtextra;
4937
4938 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
4939 field, ftype, MAXDATEFIELDS, &nf);
4940 if (dterr == 0)
4941 dterr = DecodeDateTime(field, ftype, nf,
4942 &dtype, tm, &fsec, &tz, &dtextra);
4943 if (dterr != 0)
4944 return false;
4945 if (dtype != DTK_DATE)
4946 return false;
4947
4948 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
4949 {
4950 GUC_check_errdetail("Timestamp out of range: \"%s\".", str);
4951 return false;
4952 }
4953 }
4954 }
4955 return true;
4956}
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:2005
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 4978 of file xlogrecovery.c.

4979{
4982
4983 if (strcmp(*newval, "current") == 0)
4985 else if (strcmp(*newval, "latest") == 0)
4987 else
4988 {
4990
4991 errno = 0;
4992 strtoul(*newval, NULL, 0);
4993 if (errno == EINVAL || errno == ERANGE)
4994 {
4995 GUC_check_errdetail("\"recovery_target_timeline\" is not a valid number.");
4996 return false;
4997 }
4998 }
4999
5001 *myextra = rttg;
5002 *extra = myextra;
5003
5004 return true;
5005}
@ 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 5024 of file xlogrecovery.c.

5025{
5026 if (strcmp(*newval, "") != 0)
5027 {
5028 TransactionId xid;
5029 TransactionId *myextra;
5030
5031 errno = 0;
5032 xid = (TransactionId) strtou64(*newval, NULL, 0);
5033 if (errno == EINVAL || errno == ERANGE)
5034 return false;
5035
5036 myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
5037 *myextra = xid;
5038 *extra = myextra;
5039 }
5040 return true;
5041}

References ERROR, guc_malloc(), and newval.

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 4447 of file xlogrecovery.c.

4448{
4450 return true;
4451
4453 {
4454 ereport(LOG, (errmsg("received promote request")));
4458 return true;
4459 }
4460
4461 return false;
4462}
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:183
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 4477 of file xlogrecovery.c.

4478{
4479 struct stat stat_buf;
4480
4481 if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4482 return true;
4483
4484 return false;
4485}
#define stat
Definition: win32_port.h:274
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:310

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 2180 of file xlogrecovery.c.

2181{
2182 XLogRecPtr lastReplayedEndRecPtr;
2183 TimeLineID lastReplayedTLI;
2184
2185 /*
2186 * During crash recovery, we don't reach a consistent state until we've
2187 * replayed all the WAL.
2188 */
2190 return;
2191
2193
2194 /*
2195 * assume that we are called in the startup process, and hence don't need
2196 * a lock to read lastReplayedEndRecPtr
2197 */
2198 lastReplayedEndRecPtr = XLogRecoveryCtl->lastReplayedEndRecPtr;
2199 lastReplayedTLI = XLogRecoveryCtl->lastReplayedTLI;
2200
2201 /*
2202 * Have we reached the point where our base backup was completed?
2203 */
2205 backupEndPoint <= lastReplayedEndRecPtr)
2206 {
2207 XLogRecPtr saveBackupStartPoint = backupStartPoint;
2208 XLogRecPtr saveBackupEndPoint = backupEndPoint;
2209
2210 elog(DEBUG1, "end of backup reached");
2211
2212 /*
2213 * We have reached the end of base backup, as indicated by pg_control.
2214 * Update the control file accordingly.
2215 */
2216 ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI);
2219 backupEndRequired = false;
2220
2221 ereport(LOG,
2222 (errmsg("completed backup recovery with redo LSN %X/%X and end LSN %X/%X",
2223 LSN_FORMAT_ARGS(saveBackupStartPoint),
2224 LSN_FORMAT_ARGS(saveBackupEndPoint))));
2225 }
2226
2227 /*
2228 * Have we passed our safe starting point? Note that minRecoveryPoint is
2229 * known to be incorrectly set if recovering from a backup, until the
2230 * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint.
2231 * All we know prior to that is that we're not consistent yet.
2232 */
2234 minRecoveryPoint <= lastReplayedEndRecPtr)
2235 {
2236 /*
2237 * Check to see if the XLOG sequence contained any unresolved
2238 * references to uninitialized pages.
2239 */
2241
2242 /*
2243 * Check that pg_tblspc doesn't contain any real directories. Replay
2244 * of Database/CREATE_* records may have created fictitious tablespace
2245 * directories that should have been removed by the time consistency
2246 * was reached.
2247 */
2249
2250 reachedConsistency = true;
2251 ereport(LOG,
2252 (errmsg("consistent recovery state reached at %X/%X",
2253 LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
2254 }
2255
2256 /*
2257 * Have we got a valid starting snapshot that will allow queries to be
2258 * run? If so, we can tell postmaster that the database is consistent now,
2259 * enabling connections.
2260 */
2265 {
2269
2270 LocalHotStandbyActive = true;
2271
2273 }
2274}
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:225
bool IsUnderPostmaster
Definition: globals.c:119
Assert(PointerIsAligned(start, uint64))
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:6293
#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:295
static bool backupEndRequired
Definition: xlogrecovery.c:284
static XLogRecPtr minRecoveryPoint
Definition: xlogrecovery.c:279
static XLogRecPtr backupEndPoint
Definition: xlogrecovery.c:283
bool InArchiveRecovery
Definition: xlogrecovery.c:139
static bool LocalHotStandbyActive
Definition: xlogrecovery.c:177
static void CheckTablespaceDirectory(void)
static XLogRecPtr backupStartPoint
Definition: xlogrecovery.c:282
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:234
@ 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 2147 of file xlogrecovery.c.

2148{
2149 DIR *dir;
2150 struct dirent *de;
2151
2153 while ((de = ReadDir(dir, PG_TBLSPC_DIR)) != NULL)
2154 {
2155 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR)];
2156
2157 /* Skip entries of non-oid names */
2158 if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
2159 continue;
2160
2161 snprintf(path, sizeof(path), "%s/%s", PG_TBLSPC_DIR, de->d_name);
2162
2163 if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
2166 errmsg("unexpected directory entry \"%s\" found in %s",
2167 de->d_name, PG_TBLSPC_DIR),
2168 errdetail("All directory entries in %s/ should be symbolic links.",
2170 errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
2171 }
2172}
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:239
#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 2382 of file xlogrecovery.c.

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

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

4047{
4048 static XLogRecPtr lastComplaint = 0;
4049
4050 if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
4051 {
4052 if (RecPtr == lastComplaint)
4053 emode = DEBUG1;
4054 else
4055 lastComplaint = RecPtr;
4056 }
4057 return emode;
4058}
static XLogSource readSource
Definition: xlogrecovery.c:235

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

◆ EnableStandbyMode()

static void EnableStandbyMode ( void  )
static

Definition at line 479 of file xlogrecovery.c.

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

References disable_startup_progress_timeout(), and StandbyMode.

Referenced by InitWalRecovery(), and ReadRecord().

◆ error_multiple_recovery_targets()

static pg_noreturn void error_multiple_recovery_targets ( void  )
static

Definition at line 4782 of file xlogrecovery.c.

4783{
4784 ereport(ERROR,
4785 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4786 errmsg("multiple recovery targets specified"),
4787 errdetail("At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set.")));
4788}

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

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

◆ FinishWalRecovery()

EndOfWalRecoveryInfo * FinishWalRecovery ( void  )

Definition at line 1461 of file xlogrecovery.c.

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

4577{
4578 XLogRecPtr recptr;
4579 TimeLineID tli;
4580
4585
4586 if (replayEndTLI)
4587 *replayEndTLI = tli;
4588 return recptr;
4589}

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

2432{
2433 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2434 uint8 xact_info = info & XLOG_XACT_OPMASK;
2435 uint8 rmid = XLogRecGetRmid(record);
2436
2437 if (rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2438 {
2439 *recordXtime = ((xl_restore_point *) XLogRecGetData(record))->rp_time;
2440 return true;
2441 }
2442 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_COMMIT ||
2443 xact_info == XLOG_XACT_COMMIT_PREPARED))
2444 {
2445 *recordXtime = ((xl_xact_commit *) XLogRecGetData(record))->xact_time;
2446 return true;
2447 }
2448 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_ABORT ||
2449 xact_info == XLOG_XACT_ABORT_PREPARED))
2450 {
2451 *recordXtime = ((xl_xact_abort *) XLogRecGetData(record))->xact_time;
2452 return true;
2453 }
2454 return false;
2455}
#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 2891 of file xlogrecovery.c.

2892{
2893 char reason[200];
2894
2896 snprintf(reason, sizeof(reason),
2897 "%s transaction %u",
2898 recoveryStopAfter ? "after" : "before",
2901 snprintf(reason, sizeof(reason),
2902 "%s %s\n",
2903 recoveryStopAfter ? "after" : "before",
2906 snprintf(reason, sizeof(reason),
2907 "%s LSN %X/%X\n",
2908 recoveryStopAfter ? "after" : "before",
2911 snprintf(reason, sizeof(reason),
2912 "at restore point \"%s\"",
2915 snprintf(reason, sizeof(reason), "reached consistency");
2916 else
2917 snprintf(reason, sizeof(reason), "no recovery target specified");
2918
2919 return pstrdup(reason);
2920}
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1861
char * pstrdup(const char *in)
Definition: mcxt.c:1699
static XLogRecPtr recoveryStopLSN
Definition: xlogrecovery.c:382
static TimestampTz recoveryStopTime
Definition: xlogrecovery.c:381
static char recoveryStopName[MAXFNAMELEN]
Definition: xlogrecovery.c:383
static bool recoveryStopAfter
Definition: xlogrecovery.c:384
static TransactionId recoveryStopXid
Definition: xlogrecovery.c:380

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

4657{
4658 /*
4659 * This must be executed in the startup process, since we don't export the
4660 * relevant state to shared memory.
4661 */
4663
4664 *rtime = XLogReceiptTime;
4665 *fromStream = (XLogReceiptSource == XLOG_FROM_STREAM);
4666}
static XLogSource XLogReceiptSource
Definition: xlogrecovery.c:260
static TimestampTz XLogReceiptTime
Definition: xlogrecovery.c:259

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

Referenced by GetStandbyLimitTime().

◆ GetXLogReplayRecPtr()

◆ HotStandbyActive()

bool HotStandbyActive ( void  )

Definition at line 4516 of file xlogrecovery.c.

4517{
4518 /*
4519 * We check shared state each time only until Hot Standby is active. We
4520 * can't de-activate Hot Standby, so there's no need to keep checking
4521 * after the shared variable has once been seen true.
4522 */
4524 return true;
4525 else
4526 {
4527 /* spinlock is essential on machines with weak memory ordering! */
4531
4532 return LocalHotStandbyActive;
4533 }
4534}

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

Referenced by XLogWalRcvSendHSFeedback().

◆ HotStandbyActiveInReplay()

static bool HotStandbyActiveInReplay ( void  )
static

Definition at line 4541 of file xlogrecovery.c.

4542{
4544 return LocalHotStandbyActive;
4545}
bool IsPostmasterEnvironment
Definition: globals.c:118
#define AmStartupProcess()
Definition: miscadmin.h:389

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

515{
516 XLogPageReadPrivate *private;
517 struct stat st;
518 bool wasShutdown;
519 XLogRecord *record;
520 DBState dbstate_at_startup;
521 bool haveTblspcMap = false;
522 bool haveBackupLabel = false;
523 CheckPoint checkPoint;
524 bool backupFromStandby = false;
525
526 dbstate_at_startup = ControlFile->state;
527
528 /*
529 * Initialize on the assumption we want to recover to the latest timeline
530 * that's active according to pg_control.
531 */
535 else
537
538 /*
539 * Check for signal files, and if so set up state for offline recovery
540 */
543
544 /*
545 * Take ownership of the wakeup latch if we're going to sleep during
546 * recovery, if required.
547 */
550
551 /*
552 * Set the WAL reading processor now, as it will be needed when reading
553 * the checkpoint record required (backup_label or not).
554 */
555 private = palloc0(sizeof(XLogPageReadPrivate));
556 xlogreader =
558 XL_ROUTINE(.page_read = &XLogPageRead,
559 .segment_open = NULL,
560 .segment_close = wal_segment_close),
561 private);
562 if (!xlogreader)
564 (errcode(ERRCODE_OUT_OF_MEMORY),
565 errmsg("out of memory"),
566 errdetail("Failed while allocating a WAL reading processor.")));
568
569 /*
570 * Set the WAL decode buffer size. This limits how far ahead we can read
571 * in the WAL.
572 */
574
575 /* Create a WAL prefetcher. */
577
578 /*
579 * Allocate two page buffers dedicated to WAL consistency checks. We do
580 * it this way, rather than just making static arrays, for two reasons:
581 * (1) no need to waste the storage in most instantiations of the backend;
582 * (2) a static char array isn't guaranteed to have any particular
583 * alignment, whereas palloc() will provide MAXALIGN'd storage.
584 */
585 replay_image_masked = (char *) palloc(BLCKSZ);
586 primary_image_masked = (char *) palloc(BLCKSZ);
587
588 /*
589 * Read the backup_label file. We want to run this part of the recovery
590 * process after checking for signal files and after performing validation
591 * of the recovery parameters.
592 */
594 &backupFromStandby))
595 {
596 List *tablespaces = NIL;
597
598 /*
599 * Archive recovery was requested, and thanks to the backup label
600 * file, we know how far we need to replay to reach consistency. Enter
601 * archive recovery directly.
602 */
603 InArchiveRecovery = true;
606
607 /*
608 * Omitting backup_label when creating a new replica, PITR node etc.
609 * unfortunately is a common cause of corruption. Logging that
610 * backup_label was used makes it a bit easier to exclude that as the
611 * cause of observed corruption.
612 *
613 * Do so before we try to read the checkpoint record (which can fail),
614 * as otherwise it can be hard to understand why a checkpoint other
615 * than ControlFile->checkPoint is used.
616 */
617 ereport(LOG,
618 (errmsg("starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u",
621 CheckPointTLI)));
622
623 /*
624 * When a backup_label file is present, we want to roll forward from
625 * the checkpoint it identifies, rather than using pg_control.
626 */
629 if (record != NULL)
630 {
631 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
632 wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
634 (errmsg_internal("checkpoint record is at %X/%X",
636 InRecovery = true; /* force recovery even if SHUTDOWNED */
637
638 /*
639 * Make sure that REDO location exists. This may not be the case
640 * if there was a crash during an online backup, which left a
641 * backup_label around that references a WAL segment that's
642 * already been archived.
643 */
644 if (checkPoint.redo < CheckPointLoc)
645 {
647 if (!ReadRecord(xlogprefetcher, LOG, false,
648 checkPoint.ThisTimeLineID))
650 (errmsg("could not find redo location %X/%X referenced by checkpoint record at %X/%X",
652 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
653 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
654 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
656 }
657 }
658 else
659 {
661 (errmsg("could not locate required checkpoint record at %X/%X",
663 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
664 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
665 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
667 wasShutdown = false; /* keep compiler quiet */
668 }
669
670 /* Read the tablespace_map file if present and create symlinks. */
671 if (read_tablespace_map(&tablespaces))
672 {
673 ListCell *lc;
674
675 foreach(lc, tablespaces)
676 {
677 tablespaceinfo *ti = lfirst(lc);
678 char *linkloc;
679
680 linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid);
681
682 /*
683 * Remove the existing symlink if any and Create the symlink
684 * under PGDATA.
685 */
687
688 if (symlink(ti->path, linkloc) < 0)
691 errmsg("could not create symbolic link \"%s\": %m",
692 linkloc)));
693
694 pfree(ti->path);
695 pfree(ti);
696 }
697
698 /* tell the caller to delete it later */
699 haveTblspcMap = true;
700 }
701
702 /* tell the caller to delete it later */
703 haveBackupLabel = true;
704 }
705 else
706 {
707 /* No backup_label file has been found if we are here. */
708
709 /*
710 * If tablespace_map file is present without backup_label file, there
711 * is no use of such file. There is no harm in retaining it, but it
712 * is better to get rid of the map file so that we don't have any
713 * redundant file in data directory and it will avoid any sort of
714 * confusion. It seems prudent though to just rename the file out of
715 * the way rather than delete it completely, also we ignore any error
716 * that occurs in rename operation as even if map file is present
717 * without backup_label file, it is harmless.
718 */
719 if (stat(TABLESPACE_MAP, &st) == 0)
720 {
721 unlink(TABLESPACE_MAP_OLD);
723 ereport(LOG,
724 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
726 errdetail("File \"%s\" was renamed to \"%s\".",
728 else
729 ereport(LOG,
730 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
732 errdetail("Could not rename file \"%s\" to \"%s\": %m.",
734 }
735
736 /*
737 * It's possible that archive recovery was requested, but we don't
738 * know how far we need to replay the WAL before we reach consistency.
739 * This can happen for example if a base backup is taken from a
740 * running server using an atomic filesystem snapshot, without calling
741 * pg_backup_start/stop. Or if you just kill a running primary server
742 * and put it into archive recovery by creating a recovery signal
743 * file.
744 *
745 * Our strategy in that case is to perform crash recovery first,
746 * replaying all the WAL present in pg_wal, and only enter archive
747 * recovery after that.
748 *
749 * But usually we already know how far we need to replay the WAL (up
750 * to minRecoveryPoint, up to backupEndPoint, or until we see an
751 * end-of-backup record), and we can enter archive recovery directly.
752 */
758 {
759 InArchiveRecovery = true;
762 }
763
764 /*
765 * For the same reason as when starting up with backup_label present,
766 * emit a log message when we continue initializing from a base
767 * backup.
768 */
770 ereport(LOG,
771 (errmsg("restarting backup recovery with redo LSN %X/%X",
773
774 /* Get the last valid checkpoint record. */
781 if (record != NULL)
782 {
784 (errmsg_internal("checkpoint record is at %X/%X",
786 }
787 else
788 {
789 /*
790 * We used to attempt to go back to a secondary checkpoint record
791 * here, but only when not in standby mode. We now just fail if we
792 * can't read the last checkpoint because this allows us to
793 * simplify processing around checkpoints.
794 */
796 (errmsg("could not locate a valid checkpoint record at %X/%X",
798 }
799 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
800 wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
801 }
802
804 {
806 ereport(LOG,
807 (errmsg("entering standby mode")));
809 ereport(LOG,
810 (errmsg("starting point-in-time recovery to XID %u",
813 ereport(LOG,
814 (errmsg("starting point-in-time recovery to %s",
817 ereport(LOG,
818 (errmsg("starting point-in-time recovery to \"%s\"",
821 ereport(LOG,
822 (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
825 ereport(LOG,
826 (errmsg("starting point-in-time recovery to earliest consistent point")));
827 else
828 ereport(LOG,
829 (errmsg("starting archive recovery")));
830 }
831
832 /*
833 * If the location of the checkpoint record is not on the expected
834 * timeline in the history of the requested timeline, we cannot proceed:
835 * the backup is not part of the history of the requested timeline.
836 */
837 Assert(expectedTLEs); /* was initialized by reading checkpoint
838 * record */
841 {
842 XLogRecPtr switchpoint;
843
844 /*
845 * tliSwitchPoint will throw an error if the checkpoint's timeline is
846 * not in expectedTLEs at all.
847 */
848 switchpoint = tliSwitchPoint(CheckPointTLI, expectedTLEs, NULL);
850 (errmsg("requested timeline %u is not a child of this server's history",
852 /* translator: %s is a backup_label file or a pg_control file */
853 errdetail("Latest checkpoint in file \"%s\" is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.",
854 haveBackupLabel ? "backup_label" : "pg_control",
857 LSN_FORMAT_ARGS(switchpoint))));
858 }
859
860 /*
861 * The min recovery point should be part of the requested timeline's
862 * history, too.
863 */
868 (errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
872
874 (errmsg_internal("redo record is at %X/%X; shutdown %s",
875 LSN_FORMAT_ARGS(checkPoint.redo),
876 wasShutdown ? "true" : "false")));
878 (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
880 checkPoint.nextOid)));
882 (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
883 checkPoint.nextMulti, checkPoint.nextMultiOffset)));
885 (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
886 checkPoint.oldestXid, checkPoint.oldestXidDB)));
888 (errmsg_internal("oldest MultiXactId: %u, in database %u",
889 checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
891 (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
892 checkPoint.oldestCommitTsXid,
893 checkPoint.newestCommitTsXid)));
896 (errmsg("invalid next transaction ID")));
897
898 /* sanity check */
899 if (checkPoint.redo > CheckPointLoc)
901 (errmsg("invalid redo in checkpoint record")));
902
903 /*
904 * Check whether we need to force recovery from WAL. If it appears to
905 * have been a clean shutdown and we did not have a recovery signal file,
906 * then assume no recovery needed.
907 */
908 if (checkPoint.redo < CheckPointLoc)
909 {
910 if (wasShutdown)
912 (errmsg("invalid redo record in shutdown checkpoint")));
913 InRecovery = true;
914 }
915 else if (ControlFile->state != DB_SHUTDOWNED)
916 InRecovery = true;
918 {
919 /* force recovery due to presence of recovery signal file */
920 InRecovery = true;
921 }
922
923 /*
924 * If recovery is needed, update our in-memory copy of pg_control to show
925 * that we are recovering and to show the selected checkpoint as the place
926 * we are starting from. We also mark pg_control with any minimum recovery
927 * stop point obtained from a backup history file.
928 *
929 * We don't write the changes to disk yet, though. Only do that after
930 * initializing various subsystems.
931 */
932 if (InRecovery)
933 {
935 {
937 }
938 else
939 {
940 ereport(LOG,
941 (errmsg("database system was not properly shut down; "
942 "automatic recovery in progress")));
944 ereport(LOG,
945 (errmsg("crash recovery starts in timeline %u "
946 "and has target timeline %u",
950 }
952 ControlFile->checkPointCopy = checkPoint;
954 {
955 /* initialize minRecoveryPoint if not set yet */
956 if (ControlFile->minRecoveryPoint < checkPoint.redo)
957 {
958 ControlFile->minRecoveryPoint = checkPoint.redo;
960 }
961 }
962
963 /*
964 * Set backupStartPoint if we're starting recovery from a base backup.
965 *
966 * Also set backupEndPoint and use minRecoveryPoint as the backup end
967 * location if we're starting recovery from a base backup which was
968 * taken from a standby. In this case, the database system status in
969 * pg_control must indicate that the database was already in recovery.
970 * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
971 * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
972 * before reaching this point; e.g. because restore_command or
973 * primary_conninfo were faulty.
974 *
975 * Any other state indicates that the backup somehow became corrupted
976 * and we can't sensibly continue with recovery.
977 */
978 if (haveBackupLabel)
979 {
980 ControlFile->backupStartPoint = checkPoint.redo;
982
983 if (backupFromStandby)
984 {
985 if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
986 dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
988 (errmsg("backup_label contains data inconsistent with control file"),
989 errhint("This means that the backup is corrupted and you will "
990 "have to use another backup for recovery.")));
992 }
993 }
994 }
995
996 /* remember these, so that we know when we have reached consistency */
1001 {
1004 }
1005 else
1006 {
1009 }
1010
1011 /*
1012 * Start recovery assuming that the final record isn't lost.
1013 */
1016
1017 *wasShutdown_ptr = wasShutdown;
1018 *haveBackupLabel_ptr = haveBackupLabel;
1019 *haveTblspcMap_ptr = haveTblspcMap;
1020}
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:521
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:126
void pfree(void *pointer)
Definition: mcxt.c:1524
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:307
#define TABLESPACE_MAP
Definition: xlog.h:306
#define BACKUP_LABEL_FILE
Definition: xlog.h:303
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:107
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition: xlogreader.c:91
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static void validateRecoveryParameters(void)
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
static TimeLineID RedoStartTLI
Definition: xlogrecovery.c:171
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:299
static char * replay_image_masked
Definition: xlogrecovery.c:298
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:123
static XLogRecPtr RedoStartLSN
Definition: xlogrecovery.c:170
static void EnableStandbyMode(void)
Definition: xlogrecovery.c:479
TimestampTz recoveryTargetTime
Definition: xlogrecovery.c:91
static bool StandbyModeRequested
Definition: xlogrecovery.c:147
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:831

References abortedRecPtr, ArchiveRecoveryRequested, Assert(), BACKUP_LABEL_FILE, backupEndPoint, ControlFileData::backupEndPoint, backupEndRequired, ControlFileData::backupEndRequired, backupStartPoint, ControlFileData::backupStartPoint, ControlFileData::checkPoint, ControlFileData::checkPointCopy, CheckPointLoc, CheckPointTLI, ControlFile, DataDir, DB_IN_ARCHIVE_RECOVERY, DB_IN_CRASH_RECOVERY, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, DEBUG1, durable_rename(), EnableStandbyMode(), ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), errmsg_internal(), ERROR, expectedTLEs, FATAL, 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 1655 of file xlogrecovery.c.

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

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4408 of file xlogrecovery.c.

4409{
4410 /*
4411 * We check shared state each time only until a standby promotion is
4412 * triggered. We can't trigger a promotion again, so there's no need to
4413 * keep checking after the shared variable has once been seen true.
4414 */
4416 return true;
4417
4421
4423}

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

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

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

4067{
4068 XLogRecord *record;
4069 uint8 info;
4070
4071 Assert(xlogreader != NULL);
4072
4073 if (!XRecOffIsValid(RecPtr))
4074 {
4075 ereport(LOG,
4076 (errmsg("invalid checkpoint location")));
4077 return NULL;
4078 }
4079
4081 record = ReadRecord(xlogprefetcher, LOG, true, replayTLI);
4082
4083 if (record == NULL)
4084 {
4085 ereport(LOG,
4086 (errmsg("invalid checkpoint record")));
4087 return NULL;
4088 }
4089 if (record->xl_rmid != RM_XLOG_ID)
4090 {
4091 ereport(LOG,
4092 (errmsg("invalid resource manager ID in checkpoint record")));
4093 return NULL;
4094 }
4095 info = record->xl_info & ~XLR_INFO_MASK;
4096 if (info != XLOG_CHECKPOINT_SHUTDOWN &&
4097 info != XLOG_CHECKPOINT_ONLINE)
4098 {
4099 ereport(LOG,
4100 (errmsg("invalid xl_info in checkpoint record")));
4101 return NULL;
4102 }
4104 {
4105 ereport(LOG,
4106 (errmsg("invalid length of checkpoint record")));
4107 return NULL;
4108 }
4109 return record;
4110}
#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 3136 of file xlogrecovery.c.

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

1031{
1032 struct stat stat_buf;
1033
1035 return;
1036
1037 /*
1038 * Check for old recovery API file: recovery.conf
1039 */
1040 if (stat(RECOVERY_COMMAND_FILE, &stat_buf) == 0)
1041 ereport(FATAL,
1043 errmsg("using recovery command file \"%s\" is not supported",
1045
1046 /*
1047 * Remove unused .done file, if present. Ignore if absent.
1048 */
1049 unlink(RECOVERY_COMMAND_DONE);
1050
1051 /*
1052 * Check for recovery signal files and if found, fsync them since they
1053 * represent server state information. We don't sweat too much about the
1054 * possibility of fsync failure, however.
1055 *
1056 * If present, standby signal file takes precedence. If neither is present
1057 * then we won't enter archive recovery.
1058 */
1059 if (stat(STANDBY_SIGNAL_FILE, &stat_buf) == 0)
1060 {
1061 int fd;
1062
1064 S_IRUSR | S_IWUSR);
1065 if (fd >= 0)
1066 {
1067 (void) pg_fsync(fd);
1068 close(fd);
1069 }
1071 }
1072 else if (stat(RECOVERY_SIGNAL_FILE, &stat_buf) == 0)
1073 {
1074 int fd;
1075
1077 S_IRUSR | S_IWUSR);
1078 if (fd >= 0)
1079 {
1080 (void) pg_fsync(fd);
1081 close(fd);
1082 }
1084 }
1085
1086 StandbyModeRequested = false;
1089 {
1090 StandbyModeRequested = true;
1092 }
1094 {
1095 StandbyModeRequested = false;
1097 }
1098 else
1099 return;
1100
1101 /*
1102 * We don't support standby mode in standalone backends; that requires
1103 * other processes such as the WAL receiver to be alive.
1104 */
1106 ereport(FATAL,
1107 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1108 errmsg("standby mode is not supported by single-user servers")));
1109}
#define PG_BINARY
Definition: c.h:1244
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:476
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:302
#define RECOVERY_SIGNAL_FILE
Definition: xlog.h:301
#define RECOVERY_COMMAND_FILE
Definition: xlogrecovery.c:69
#define RECOVERY_COMMAND_DONE
Definition: xlogrecovery.c:70

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

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

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

Referenced by PerformWalRecovery().

◆ recoveryPausesHere()

static void recoveryPausesHere ( bool  endOfRecovery)
static

Definition at line 2930 of file xlogrecovery.c.

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

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

Referenced by PerformWalRecovery(), and WaitForWALToBecomeAvailable().

◆ RecoveryRequiresIntParameter()

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

Definition at line 4673 of file xlogrecovery.c.

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

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

Referenced by CheckRequiredParameterValues().

◆ recoveryStopsAfter()

static bool recoveryStopsAfter ( XLogReaderState record)
static

Definition at line 2731 of file xlogrecovery.c.

2732{
2733 uint8 info;
2734 uint8 xact_info;
2735 uint8 rmid;
2736 TimestampTz recordXtime = 0;
2737
2738 /*
2739 * Ignore recovery target settings when not in archive recovery (meaning
2740 * we are in crash recovery).
2741 */
2743 return false;
2744
2745 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2746 rmid = XLogRecGetRmid(record);
2747
2748 /*
2749 * There can be many restore points that share the same name; we stop at
2750 * the first one.
2751 */
2753 rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2754 {
2755 xl_restore_point *recordRestorePointData;
2756
2757 recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
2758
2759 if (strcmp(recordRestorePointData->rp_name, recoveryTargetName) == 0)
2760 {
2761 recoveryStopAfter = true;
2764 (void) getRecordTimestamp(record, &recoveryStopTime);
2765 strlcpy(recoveryStopName, recordRestorePointData->rp_name, MAXFNAMELEN);
2766
2767 ereport(LOG,
2768 (errmsg("recovery stopping at restore point \"%s\", time %s",
2771 return true;
2772 }
2773 }
2774
2775 /* Check if the target LSN has been reached */
2778 record->ReadRecPtr >= recoveryTargetLSN)
2779 {
2780 recoveryStopAfter = true;
2782 recoveryStopLSN = record->ReadRecPtr;
2783 recoveryStopTime = 0;
2784 recoveryStopName[0] = '\0';
2785 ereport(LOG,
2786 (errmsg("recovery stopping after WAL location (LSN) \"%X/%X\"",
2788 return true;
2789 }
2790
2791 if (rmid != RM_XACT_ID)
2792 return false;
2793
2794 xact_info = info & XLOG_XACT_OPMASK;
2795
2796 if (xact_info == XLOG_XACT_COMMIT ||
2797 xact_info == XLOG_XACT_COMMIT_PREPARED ||
2798 xact_info == XLOG_XACT_ABORT ||
2799 xact_info == XLOG_XACT_ABORT_PREPARED)
2800 {
2801 TransactionId recordXid;
2802
2803 /* Update the last applied transaction timestamp */
2804 if (getRecordTimestamp(record, &recordXtime))
2805 SetLatestXTime(recordXtime);
2806
2807 /* Extract the XID of the committed/aborted transaction */
2808 if (xact_info == XLOG_XACT_COMMIT_PREPARED)
2809 {
2810 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
2811 xl_xact_parsed_commit parsed;
2812
2814 xlrec,
2815 &parsed);
2816 recordXid = parsed.twophase_xid;
2817 }
2818 else if (xact_info == XLOG_XACT_ABORT_PREPARED)
2819 {
2820 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2821 xl_xact_parsed_abort parsed;
2822
2824 xlrec,
2825 &parsed);
2826 recordXid = parsed.twophase_xid;
2827 }
2828 else
2829 recordXid = XLogRecGetXid(record);
2830
2831 /*
2832 * There can be only one transaction end record with this exact
2833 * transactionid
2834 *
2835 * when testing for an xid, we MUST test for equality only, since
2836 * transactions are numbered in the order they start, not the order
2837 * they complete. A higher numbered xid will complete before you about
2838 * 50% of the time...
2839 */
2841 recordXid == recoveryTargetXid)
2842 {
2843 recoveryStopAfter = true;
2844 recoveryStopXid = recordXid;
2845 recoveryStopTime = recordXtime;
2847 recoveryStopName[0] = '\0';
2848
2849 if (xact_info == XLOG_XACT_COMMIT ||
2850 xact_info == XLOG_XACT_COMMIT_PREPARED)
2851 {
2852 ereport(LOG,
2853 (errmsg("recovery stopping after commit of transaction %u, time %s",
2856 }
2857 else if (xact_info == XLOG_XACT_ABORT ||
2858 xact_info == XLOG_XACT_ABORT_PREPARED)
2859 {
2860 ereport(LOG,
2861 (errmsg("recovery stopping after abort of transaction %u, time %s",
2864 }
2865 return true;
2866 }
2867 }
2868
2869 /* Check if we should stop as soon as reaching consistency */
2871 {
2872 ereport(LOG,
2873 (errmsg("recovery stopping after reaching consistency")));
2874
2875 recoveryStopAfter = true;
2877 recoveryStopTime = 0;
2879 recoveryStopName[0] = '\0';
2880 return true;
2881 }
2882
2883 return false;
2884}
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:87
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 2578 of file xlogrecovery.c.

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

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

4469{
4470 unlink(PROMOTE_SIGNAL_FILE);
4471}

References PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ rescanLatestTimeLine()

static bool rescanLatestTimeLine ( TimeLineID  replayTLI,
XLogRecPtr  replayLSN 
)
static

Definition at line 4120 of file xlogrecovery.c.

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

2281{
2282 XLogReaderState *record = (XLogReaderState *) arg;
2284
2286 xlog_outdesc(&buf, record);
2287 xlog_block_info(&buf, record);
2288
2289 /* translator: %s is a WAL record description */
2290 errcontext("WAL redo at %X/%X for %s",
2291 LSN_FORMAT_ARGS(record->ReadRecPtr),
2292 buf.data);
2293
2294 pfree(buf.data);
2295}
#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 4426 of file xlogrecovery.c.

4427{
4431
4432 /*
4433 * Mark the recovery pause state as 'not paused' because the paused state
4434 * ends and promotion continues if a promotion is triggered while recovery
4435 * is paused. Otherwise pg_get_wal_replay_pause_state() can mistakenly
4436 * return 'paused' while a promotion is ongoing.
4437 */
4438 SetRecoveryPause(false);
4439
4441}

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

Referenced by CheckForStandbyTrigger().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1611 of file xlogrecovery.c.

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

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

Referenced by StartupXLOG().

◆ StartupRequestWalReceiverRestart()

void StartupRequestWalReceiverRestart ( void  )

Definition at line 4389 of file xlogrecovery.c.

4390{
4392 {
4393 ereport(LOG,
4394 (errmsg("WAL receiver process shutdown requested")));
4395
4396 pendingWalRcvRestart = true;
4397 }
4398}
bool WalRcvRunning(void)
static bool pendingWalRcvRestart
Definition: xlogrecovery.c:249

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

Referenced by StartupRereadConfig().

◆ validateRecoveryParameters()

static void validateRecoveryParameters ( void  )
static

Definition at line 1112 of file xlogrecovery.c.

1113{
1115 return;
1116
1117 /*
1118 * Check for compulsory parameters
1119 */
1121 {
1122 if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
1123 (recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0))
1125 (errmsg("specified neither \"primary_conninfo\" nor \"restore_command\""),
1126 errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1127 }
1128 else
1129 {
1130 if (recoveryRestoreCommand == NULL ||
1131 strcmp(recoveryRestoreCommand, "") == 0)
1132 ereport(FATAL,
1133 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1134 errmsg("must specify \"restore_command\" when standby mode is not enabled")));
1135 }
1136
1137 /*
1138 * Override any inconsistent requests. Note that this is a change of
1139 * behaviour in 9.5; prior to this we simply ignored a request to pause if
1140 * hot_standby = off, which was surprising behaviour.
1141 */
1145
1146 /*
1147 * Final parsing of recovery_target_time string; see also
1148 * check_recovery_target_time().
1149 */
1151 {
1155 Int32GetDatum(-1)));
1156 }
1157
1158 /*
1159 * If user specified recovery_target_timeline, validate it or compute the
1160 * "latest" value. We can't do this until after we've gotten the restore
1161 * command and set InArchiveRecovery, because we need to fetch timeline
1162 * history files from the archive.
1163 */
1165 {
1167
1168 /* Timeline 1 does not have a history file, all else should */
1169 if (rtli != 1 && !existsTimeLineHistory(rtli))
1170 ereport(FATAL,
1171 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1172 errmsg("recovery target timeline %u does not exist",
1173 rtli)));
1174 recoveryTargetTLI = rtli;
1175 }
1177 {
1178 /* We start the "latest" search from pg_control's timeline */
1180 }
1181 else
1182 {
1183 /*
1184 * else we just use the recoveryTargetTLI as already read from
1185 * ControlFile
1186 */
1188 }
1189}
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:83
char * recovery_target_time_string
Definition: xlogrecovery.c:90
char * PrimaryConnInfo
Definition: xlogrecovery.c:97

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

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

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

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

References Assert(), CheckForStandbyTrigger(), close, curFileTLI, currentSource, DEBUG2, elog, ERROR, expectedTLEs, flushedUpto, GetCurrentTimestamp(), GetWalRcvFlushRecPtr(), InArchiveRecovery, KnownAssignedTransactionIdsIdleMaintenance(), lastSourceFailed, LOG, LSN_FORMAT_ARGS, now(), pendingWalRcvRestart, PrimaryConnInfo, PrimarySlotName, ProcessStartupProcInterrupts(), readFile, readSegNo, readSource, readTimeLineHistory(), receiveTLI, RECOVERY_NOT_PAUSED, RECOVERY_TARGET_TIMELINE_LATEST, recoveryPausesHere(), recoveryTargetTimeLineGoal, recoveryTargetTLI, XLogRecoveryCtlData::recoveryWakeupLatch, RedoStartLSN, RedoStartTLI, RequestXLogStreaming(), rescanLatestTimeLine(), 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 2341 of file xlogrecovery.c.

2342{
2343 int block_id;
2344
2345 /* decode block references */
2346 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2347 {
2348 RelFileLocator rlocator;
2349 ForkNumber forknum;
2350 BlockNumber blk;
2351
2352 if (!XLogRecGetBlockTagExtended(record, block_id,
2353 &rlocator, &forknum, &blk, NULL))
2354 continue;
2355
2356 if (forknum != MAIN_FORKNUM)
2357 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, fork %u, blk %u",
2358 block_id,
2359 rlocator.spcOid, rlocator.dbOid,
2360 rlocator.relNumber,
2361 forknum,
2362 blk);
2363 else
2364 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, blk %u",
2365 block_id,
2366 rlocator.spcOid, rlocator.dbOid,
2367 rlocator.relNumber,
2368 blk);
2369 if (XLogRecHasBlockImage(record, block_id))
2370 appendStringInfoString(buf, " FPW");
2371 }
2372}
@ 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 2302 of file xlogrecovery.c.

2303{
2304 RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2305 uint8 info = XLogRecGetInfo(record);
2306 const char *id;
2307
2310
2311 id = rmgr.rm_identify(info);
2312 if (id == NULL)
2313 appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2314 else
2315 appendStringInfo(buf, "%s: ", id);
2316
2317 rmgr.rm_desc(buf, record);
2318}
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 4207 of file xlogrecovery.c.

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

4290{
4291 char path[MAXPGPATH];
4292 ListCell *cell;
4293 int fd;
4294 List *tles;
4295
4296 /*
4297 * Loop looking for a suitable timeline ID: we might need to read any of
4298 * the timelines listed in expectedTLEs.
4299 *
4300 * We expect curFileTLI on entry to be the TLI of the preceding file in
4301 * sequence, or 0 if there was no predecessor. We do not allow curFileTLI
4302 * to go backwards; this prevents us from picking up the wrong file when a
4303 * parent timeline extends to higher segment numbers than the child we
4304 * want to read.
4305 *
4306 * If we haven't read the timeline history file yet, read it now, so that
4307 * we know which TLIs to scan. We don't save the list in expectedTLEs,
4308 * however, unless we actually find a valid segment. That way if there is
4309 * neither a timeline history file nor a WAL segment in the archive, and
4310 * streaming replication is set up, we'll read the timeline history file
4311 * streamed from the primary when we start streaming, instead of
4312 * recovering with a dummy history generated here.
4313 */
4314 if (expectedTLEs)
4315 tles = expectedTLEs;
4316 else
4318
4319 foreach(cell, tles)
4320 {
4322 TimeLineID tli = hent->tli;
4323
4324 if (tli < curFileTLI)
4325 break; /* don't bother looking at too-old TLIs */
4326
4327 /*
4328 * Skip scanning the timeline ID that the logfile segment to read
4329 * doesn't belong to
4330 */
4331 if (hent->begin != InvalidXLogRecPtr)
4332 {
4333 XLogSegNo beginseg = 0;
4334
4335 XLByteToSeg(hent->begin, beginseg, wal_segment_size);
4336
4337 /*
4338 * The logfile segment that doesn't belong to the timeline is
4339 * older or newer than the segment that the timeline started or
4340 * ended at, respectively. It's sufficient to check only the
4341 * starting segment of the timeline here. Since the timelines are
4342 * scanned in descending order in this loop, any segments newer
4343 * than the ending segment should belong to newer timeline and
4344 * have already been read before. So it's not necessary to check
4345 * the ending segment of the timeline here.
4346 */
4347 if (segno < beginseg)
4348 continue;
4349 }
4350
4352 {
4353 fd = XLogFileRead(segno, tli, XLOG_FROM_ARCHIVE, true);
4354 if (fd != -1)
4355 {
4356 elog(DEBUG1, "got WAL segment from archive");
4357 if (!expectedTLEs)
4358 expectedTLEs = tles;
4359 return fd;
4360 }
4361 }
4362
4364 {
4365 fd = XLogFileRead(segno, tli, XLOG_FROM_PG_WAL, true);
4366 if (fd != -1)
4367 {
4368 if (!expectedTLEs)
4369 expectedTLEs = tles;
4370 return fd;
4371 }
4372 }
4373 }
4374
4375 /* Couldn't find it. For simplicity, complain about front timeline */
4377 errno = ENOENT;
4380 errmsg("could not open file \"%s\": %m", path)));
4381 return -1;
4382}
XLogRecPtr begin
Definition: timeline.h:28

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

Referenced by WaitForWALToBecomeAvailable().

◆ XLogPageRead()

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

Definition at line 3303 of file xlogrecovery.c.

3305{
3306 XLogPageReadPrivate *private =
3308 int emode = private->emode;
3309 uint32 targetPageOff;
3311 int r;
3312 instr_time io_start;
3313
3314 XLByteToSeg(targetPagePtr, targetSegNo, wal_segment_size);
3315 targetPageOff = XLogSegmentOffset(targetPagePtr, wal_segment_size);
3316
3317 /*
3318 * See if we need to switch to a new segment because the requested record
3319 * is not in the currently open one.
3320 */
3321 if (readFile >= 0 &&
3322 !XLByteInSeg(targetPagePtr, readSegNo, wal_segment_size))
3323 {
3324 /*
3325 * Request a restartpoint if we've replayed too much xlog since the
3326 * last one.
3327 */
3329 {
3331 {
3332 (void) GetRedoRecPtr();
3335 }
3336 }
3337
3338 close(readFile);
3339 readFile = -1;
3341 }
3342
3343 XLByteToSeg(targetPagePtr, readSegNo, wal_segment_size);
3344
3345retry:
3346 /* See if we need to retrieve more data */
3347 if (readFile < 0 ||
3349 flushedUpto < targetPagePtr + reqLen))
3350 {
3351 if (readFile >= 0 &&
3354 flushedUpto < targetPagePtr + reqLen)
3355 return XLREAD_WOULDBLOCK;
3356
3357 switch (WaitForWALToBecomeAvailable(targetPagePtr + reqLen,
3358 private->randAccess,
3359 private->fetching_ckpt,
3360 targetRecPtr,
3361 private->replayTLI,
3364 {
3365 case XLREAD_WOULDBLOCK:
3366 return XLREAD_WOULDBLOCK;
3367 case XLREAD_FAIL:
3368 if (readFile >= 0)
3369 close(readFile);
3370 readFile = -1;
3371 readLen = 0;
3373 return XLREAD_FAIL;
3374 case XLREAD_SUCCESS:
3375 break;
3376 }
3377 }
3378
3379 /*
3380 * At this point, we have the right segment open and if we're streaming we
3381 * know the requested record is in it.
3382 */
3383 Assert(readFile != -1);
3384
3385 /*
3386 * If the current segment is being streamed from the primary, calculate
3387 * how much of the current page we have received already. We know the
3388 * requested record has been received, but this is for the benefit of
3389 * future calls, to allow quick exit at the top of this function.
3390 */
3392 {
3393 if (((targetPagePtr) / XLOG_BLCKSZ) != (flushedUpto / XLOG_BLCKSZ))
3394 readLen = XLOG_BLCKSZ;
3395 else
3397 targetPageOff;
3398 }
3399 else
3400 readLen = XLOG_BLCKSZ;
3401
3402 /* Read the requested page */
3403 readOff = targetPageOff;
3404
3405 /* Measure I/O timing when reading segment */
3407
3408 pgstat_report_wait_start(WAIT_EVENT_WAL_READ);
3409 r = pg_pread(readFile, readBuf, XLOG_BLCKSZ, (off_t) readOff);
3410 if (r != XLOG_BLCKSZ)
3411 {
3412 char fname[MAXFNAMELEN];
3413 int save_errno = errno;
3414
3416
3418 io_start, 1, r);
3419
3421 if (r < 0)
3422 {
3423 errno = save_errno;
3424 ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
3426 errmsg("could not read from WAL segment %s, LSN %X/%X, offset %u: %m",
3427 fname, LSN_FORMAT_ARGS(targetPagePtr),
3428 readOff)));
3429 }
3430 else
3431 ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
3433 errmsg("could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu",
3434 fname, LSN_FORMAT_ARGS(targetPagePtr),
3435 readOff, r, (Size) XLOG_BLCKSZ)));
3436 goto next_record_is_invalid;
3437 }
3439
3441 io_start, 1, r);
3442
3443 Assert(targetSegNo == readSegNo);
3444 Assert(targetPageOff == readOff);
3445 Assert(reqLen <= readLen);
3446
3448
3449 /*
3450 * Check the page header immediately, so that we can retry immediately if
3451 * it's not valid. This may seem unnecessary, because ReadPageInternal()
3452 * validates the page header anyway, and would propagate the failure up to
3453 * ReadRecord(), which would retry. However, there's a corner case with
3454 * continuation records, if a record is split across two pages such that
3455 * we would need to read the two pages from different sources across two
3456 * WAL segments.
3457 *
3458 * The first page is only available locally, in pg_wal, because it's
3459 * already been recycled on the primary. The second page, however, is not
3460 * present in pg_wal, and we should stream it from the primary. There is a
3461 * recycled WAL segment present in pg_wal, with garbage contents, however.
3462 * We would read the first page from the local WAL segment, but when
3463 * reading the second page, we would read the bogus, recycled, WAL
3464 * segment. If we didn't catch that case here, we would never recover,
3465 * because ReadRecord() would retry reading the whole record from the
3466 * beginning.
3467 *
3468 * Of course, this only catches errors in the page header, which is what
3469 * happens in the case of a recycled WAL segment. Other kinds of errors or
3470 * corruption still has the same problem. But this at least fixes the
3471 * common case, which can happen as part of normal operation.
3472 *
3473 * Validating the page header is cheap enough that doing it twice
3474 * shouldn't be a big deal from a performance point of view.
3475 *
3476 * When not in standby mode, an invalid page header should cause recovery
3477 * to end, not retry reading the page, so we don't need to validate the
3478 * page header here for the retry. Instead, ReadPageInternal() is
3479 * responsible for the validation.
3480 */
3481 if (StandbyMode &&
3482 (targetPagePtr % wal_segment_size) == 0 &&
3483 !XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf))
3484 {
3485 /*
3486 * Emit this error right now then retry this page immediately. Use
3487 * errmsg_internal() because the message was already translated.
3488 */
3489 if (xlogreader->errormsg_buf[0])
3492
3493 /* reset any error XLogReaderValidatePageHeader() might have set */
3495 goto next_record_is_invalid;
3496 }
3497
3498 return readLen;
3499
3500next_record_is_invalid:
3501
3502 /*
3503 * If we're reading ahead, give up fast. Retries and error reporting will
3504 * be handled by a later read when recovery catches up to this point.
3505 */
3507 return XLREAD_WOULDBLOCK;
3508
3509 lastSourceFailed = true;
3510
3511 if (readFile >= 0)
3512 close(readFile);
3513 readFile = -1;
3514 readLen = 0;
3516
3517 /* In standby-mode, keep trying */
3518 if (StandbyMode)
3519 goto retry;
3520 else
3521 return XLREAD_FAIL;
3522}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:224
size_t Size
Definition: c.h:576
void RequestCheckpoint(int flags)
Definition: checkpointer.c:997
@ IOOBJECT_WAL
Definition: pgstat.h:276
@ IOCONTEXT_NORMAL
Definition: pgstat.h:286
@ IOOP_READ
Definition: pgstat.h:312
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition: pgstat_io.c:90
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition: pgstat_io.c:121
#define pg_pread
Definition: port.h:226
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6483
bool track_wal_io_timing
Definition: xlog.c:137
bool XLogCheckpointNeeded(XLogSegNo new_segno)
Definition: xlog.c:2290
#define CHECKPOINT_CAUSE_XLOG
Definition: xlog.h:148
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
void XLogReaderResetError(XLogReaderState *state)
Definition: xlogreader.c:1366
bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr)
Definition: xlogreader.c:1225
static XLogPageReadResult WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr, TimeLineID replayTLI, XLogRecPtr replayLSN, bool nonblocking)
static uint32 readLen
Definition: xlogrecovery.c:234

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

Referenced by InitWalRecovery().

◆ xlogrecovery_redo()

static void xlogrecovery_redo ( XLogReaderState record,
TimeLineID  replayTLI 
)
static

Definition at line 2076 of file xlogrecovery.c.

2077{
2078 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2079 XLogRecPtr lsn = record->EndRecPtr;
2080
2081 Assert(XLogRecGetRmid(record) == RM_XLOG_ID);
2082
2083 if (info == XLOG_OVERWRITE_CONTRECORD)
2084 {
2085 /* Verify the payload of a XLOG_OVERWRITE_CONTRECORD record. */
2087
2088 memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_overwrite_contrecord));
2089 if (xlrec.overwritten_lsn != record->overwrittenRecPtr)
2090 elog(FATAL, "mismatching overwritten LSN %X/%X -> %X/%X",
2093
2094 /* We have safely skipped the aborted record */
2097
2098 ereport(LOG,
2099 (errmsg("successfully skipped missing contrecord at %X/%X, overwritten at %s",
2102
2103 /* Verifying the record should only happen once */
2105 }
2106 else if (info == XLOG_BACKUP_END)
2107 {
2108 XLogRecPtr startpoint;
2109
2110 memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
2111
2112 if (backupStartPoint == startpoint)
2113 {
2114 /*
2115 * We have reached the end of base backup, the point where
2116 * pg_backup_stop() was done. The data on disk is now consistent
2117 * (assuming we have also reached minRecoveryPoint). Set
2118 * backupEndPoint to the current LSN, so that the next call to
2119 * CheckRecoveryConsistency() will notice it and do the
2120 * end-of-backup processing.
2121 */
2122 elog(DEBUG1, "end of backup record reached");
2123
2124 backupEndPoint = lsn;
2125 }
2126 else
2127 elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
2129 }
2130}
#define XLOG_OVERWRITE_CONTRECORD
Definition: pg_control.h:81
#define XLOG_BACKUP_END
Definition: pg_control.h:73
XLogRecPtr overwrittenRecPtr
Definition: xlogreader.h:217

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

Referenced by ApplyWalRecord().

◆ XLogRecoveryShmemInit()

void XLogRecoveryShmemInit ( void  )

Definition at line 459 of file xlogrecovery.c.

460{
461 bool found;
462
464 ShmemInitStruct("XLOG Recovery Ctl", XLogRecoveryShmemSize(), &found);
465 if (found)
466 return;
467 memset(XLogRecoveryCtl, 0, sizeof(XLogRecoveryCtlData));
468
472}
void ConditionVariableInit(ConditionVariable *cv)
void InitSharedLatch(Latch *latch)
Definition: latch.c:93
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:382
#define SpinLockInit(lock)
Definition: spin.h:57
Size XLogRecoveryShmemSize(void)
Definition: xlogrecovery.c:448

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

Referenced by CreateOrAttachShmemStructs().

◆ XLogRecoveryShmemSize()

Size XLogRecoveryShmemSize ( void  )

Definition at line 448 of file xlogrecovery.c.

449{
450 Size size;
451
452 /* XLogRecoveryCtl */
453 size = sizeof(XLogRecoveryCtlData);
454
455 return size;
456}
struct XLogRecoveryCtlData XLogRecoveryCtlData

Referenced by CalculateShmemSize(), and XLogRecoveryShmemInit().

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4501 of file xlogrecovery.c.

4502{
4504}

References doRequestWalReceiverReply.

Referenced by xact_redo_commit().

Variable Documentation

◆ abortedRecPtr

XLogRecPtr abortedRecPtr
static

◆ archiveCleanupCommand

char* archiveCleanupCommand = NULL

Definition at line 85 of file xlogrecovery.c.

Referenced by CreateRestartPoint().

◆ ArchiveRecoveryRequested

◆ backupEndPoint

XLogRecPtr backupEndPoint
static

Definition at line 283 of file xlogrecovery.c.

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

◆ backupEndRequired

bool backupEndRequired = false
static

Definition at line 284 of file xlogrecovery.c.

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

◆ backupStartPoint

XLogRecPtr backupStartPoint
static

Definition at line 282 of file xlogrecovery.c.

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

◆ CheckPointLoc

XLogRecPtr CheckPointLoc = InvalidXLogRecPtr
static

Definition at line 168 of file xlogrecovery.c.

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

◆ CheckPointTLI

TimeLineID CheckPointTLI = 0
static

Definition at line 169 of file xlogrecovery.c.

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

◆ curFileTLI

TimeLineID curFileTLI
static

◆ currentSource

XLogSource currentSource = XLOG_FROM_ANY
static

◆ doRequestWalReceiverReply

bool doRequestWalReceiverReply
static

Definition at line 186 of file xlogrecovery.c.

Referenced by ApplyWalRecord(), and XLogRequestWalReceiverReply().

◆ expectedTLEs

◆ flushedUpto

XLogRecPtr flushedUpto = 0
static

Definition at line 263 of file xlogrecovery.c.

Referenced by WaitForWALToBecomeAvailable(), and XLogPageRead().

◆ InArchiveRecovery

◆ InRedo

bool InRedo = false
static

Definition at line 204 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and XLogFileRead().

◆ lastSourceFailed

bool lastSourceFailed = false
static

Definition at line 248 of file xlogrecovery.c.

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

◆ LocalHotStandbyActive

bool LocalHotStandbyActive = false
static

◆ LocalPromoteIsTriggered

bool LocalPromoteIsTriggered = false
static

◆ minRecoveryPoint

XLogRecPtr minRecoveryPoint
static

◆ minRecoveryPointTLI

TimeLineID minRecoveryPointTLI
static

Definition at line 280 of file xlogrecovery.c.

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

◆ missingContrecPtr

XLogRecPtr missingContrecPtr
static

◆ pendingWalRcvRestart

bool pendingWalRcvRestart = false
static

◆ primary_image_masked

char* primary_image_masked = NULL
static

Definition at line 299 of file xlogrecovery.c.

Referenced by InitWalRecovery(), and verifyBackupPageConsistency().

◆ PrimaryConnInfo

◆ PrimarySlotName

◆ reachedConsistency

◆ readFile

int readFile = -1
static

◆ readLen

uint32 readLen = 0
static

Definition at line 234 of file xlogrecovery.c.

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

◆ readOff

uint32 readOff = 0
static

Definition at line 233 of file xlogrecovery.c.

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

◆ readSegNo

XLogSegNo readSegNo = 0
static

Definition at line 232 of file xlogrecovery.c.

Referenced by WaitForWALToBecomeAvailable(), and XLogPageRead().

◆ readSource

◆ receiveTLI

TimeLineID receiveTLI = 0
static

◆ recovery_min_apply_delay

int recovery_min_apply_delay = 0

Definition at line 94 of file xlogrecovery.c.

Referenced by recoveryApplyDelay().

◆ recovery_signal_file_found

bool recovery_signal_file_found = false
static

Definition at line 152 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), and readRecoverySignalFile().

◆ recovery_target_action_options

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

Definition at line 75 of file xlogrecovery.c.

◆ recovery_target_time_string

char* recovery_target_time_string

Definition at line 90 of file xlogrecovery.c.

Referenced by validateRecoveryParameters().

◆ recoveryEndCommand

char* recoveryEndCommand = NULL

Definition at line 84 of file xlogrecovery.c.

Referenced by CleanupAfterArchiveRecovery().

◆ recoveryRestoreCommand

char* recoveryRestoreCommand = NULL

Definition at line 83 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), and validateRecoveryParameters().

◆ recoveryStopAfter

bool recoveryStopAfter
static

Definition at line 384 of file xlogrecovery.c.

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

◆ recoveryStopLSN

XLogRecPtr recoveryStopLSN
static

Definition at line 382 of file xlogrecovery.c.

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

◆ recoveryStopName

char recoveryStopName[MAXFNAMELEN]
static

Definition at line 383 of file xlogrecovery.c.

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

◆ recoveryStopTime

TimestampTz recoveryStopTime
static

Definition at line 381 of file xlogrecovery.c.

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

◆ recoveryStopXid

TransactionId recoveryStopXid
static

Definition at line 380 of file xlogrecovery.c.

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

◆ recoveryTarget

◆ recoveryTargetAction

int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE

Definition at line 88 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and validateRecoveryParameters().

◆ recoveryTargetInclusive

bool recoveryTargetInclusive = true

Definition at line 87 of file xlogrecovery.c.

Referenced by recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTargetLSN

XLogRecPtr recoveryTargetLSN

◆ recoveryTargetName

const char* recoveryTargetName

Definition at line 92 of file xlogrecovery.c.

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

◆ recoveryTargetTime

TimestampTz recoveryTargetTime

Definition at line 91 of file xlogrecovery.c.

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

◆ recoveryTargetTimeLineGoal

◆ recoveryTargetTLI

◆ recoveryTargetTLIRequested

TimeLineID recoveryTargetTLIRequested = 0

Definition at line 122 of file xlogrecovery.c.

Referenced by assign_recovery_target_timeline(), and validateRecoveryParameters().

◆ recoveryTargetXid

◆ RedoStartLSN

◆ RedoStartTLI

TimeLineID RedoStartTLI = 0
static

◆ replay_image_masked

char* replay_image_masked = NULL
static

Definition at line 298 of file xlogrecovery.c.

Referenced by InitWalRecovery(), and verifyBackupPageConsistency().

◆ standby_signal_file_found

bool standby_signal_file_found = false
static

Definition at line 151 of file xlogrecovery.c.

Referenced by FinishWalRecovery(), and readRecoverySignalFile().

◆ StandbyMode

◆ StandbyModeRequested

bool StandbyModeRequested = false
static

◆ wal_receiver_create_temp_slot

bool wal_receiver_create_temp_slot = false

Definition at line 99 of file xlogrecovery.c.

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().

◆ xlogprefetcher

◆ xlogreader

◆ XLogReceiptSource

XLogSource XLogReceiptSource = XLOG_FROM_ANY
static

Definition at line 260 of file xlogrecovery.c.

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

◆ XLogReceiptTime

TimestampTz XLogReceiptTime = 0
static

◆ XLogRecoveryCtl

◆ xlogSourceNames

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

Definition at line 219 of file xlogrecovery.c.

Referenced by WaitForWALToBecomeAvailable().