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

Go to the source code of this file.

Data Structures

struct  XLogPageReadPrivate
 

Macros

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

Typedefs

typedef struct XLogPageReadPrivate XLogPageReadPrivate
 

Enumerations

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

Functions

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

Variables

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

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 72 of file xlogrecovery.c.

Typedef Documentation

◆ XLogPageReadPrivate

Enumeration Type Documentation

◆ XLogSource

Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 213 of file xlogrecovery.c.

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

Function Documentation

◆ ApplyWalRecord()

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

Definition at line 1883 of file xlogrecovery.c.

1884{
1885 ErrorContextCallback errcallback;
1886 bool switchedTLI = false;
1887
1888 /* Setup error traceback support for ereport() */
1889 errcallback.callback = rm_redo_error_callback;
1890 errcallback.arg = xlogreader;
1891 errcallback.previous = error_context_stack;
1892 error_context_stack = &errcallback;
1893
1894 /*
1895 * TransamVariables->nextXid must be beyond record's xid.
1896 */
1898
1899 /*
1900 * Before replaying this record, check if this record causes the current
1901 * timeline to change. The record is already considered to be part of the
1902 * new timeline, so we update replayTLI before replaying it. That's
1903 * important so that replayEndTLI, which is recorded as the minimum
1904 * recovery point's TLI if recovery stops after this record, is set
1905 * correctly.
1906 */
1907 if (record->xl_rmid == RM_XLOG_ID)
1908 {
1909 TimeLineID newReplayTLI = *replayTLI;
1910 TimeLineID prevReplayTLI = *replayTLI;
1911 uint8 info = record->xl_info & ~XLR_INFO_MASK;
1912
1913 if (info == XLOG_CHECKPOINT_SHUTDOWN)
1914 {
1915 CheckPoint checkPoint;
1916
1917 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
1918 newReplayTLI = checkPoint.ThisTimeLineID;
1919 prevReplayTLI = checkPoint.PrevTimeLineID;
1920 }
1921 else if (info == XLOG_END_OF_RECOVERY)
1922 {
1924
1926 newReplayTLI = xlrec.ThisTimeLineID;
1927 prevReplayTLI = xlrec.PrevTimeLineID;
1928 }
1929
1930 if (newReplayTLI != *replayTLI)
1931 {
1932 /* Check that it's OK to switch to this TLI */
1934 newReplayTLI, prevReplayTLI, *replayTLI);
1935
1936 /* Following WAL records should be run with new TLI */
1937 *replayTLI = newReplayTLI;
1938 switchedTLI = true;
1939 }
1940 }
1941
1942 /*
1943 * Update shared replayEndRecPtr before replaying this record, so that
1944 * XLogFlush will update minRecoveryPoint correctly.
1945 */
1948 XLogRecoveryCtl->replayEndTLI = *replayTLI;
1950
1951 /*
1952 * If we are attempting to enter Hot Standby mode, process XIDs we see
1953 */
1957
1958 /*
1959 * Some XLOG record types that are related to recovery are processed
1960 * directly here, rather than in xlog_redo()
1961 */
1962 if (record->xl_rmid == RM_XLOG_ID)
1963 xlogrecovery_redo(xlogreader, *replayTLI);
1964
1965 /* Now apply the WAL record itself */
1967
1968 /*
1969 * After redo, check whether the backup pages associated with the WAL
1970 * record are consistent with the existing pages. This check is done only
1971 * if consistency check is enabled for this record.
1972 */
1973 if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
1975
1976 /* Pop the error context stack */
1977 error_context_stack = errcallback.previous;
1978
1979 /*
1980 * Update lastReplayedEndRecPtr after this record has been successfully
1981 * replayed.
1982 */
1986 XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
1988
1989 /* ------
1990 * Wakeup walsenders:
1991 *
1992 * On the standby, the WAL is flushed first (which will only wake up
1993 * physical walsenders) and then applied, which will only wake up logical
1994 * walsenders.
1995 *
1996 * Indeed, logical walsenders on standby can't decode and send data until
1997 * it's been applied.
1998 *
1999 * Physical walsenders don't need to be woken up during replay unless
2000 * cascading replication is allowed and time line change occurred (so that
2001 * they can notice that they are on a new time line).
2002 *
2003 * That's why the wake up conditions are for:
2004 *
2005 * - physical walsenders in case of new time line and cascade
2006 * replication is allowed
2007 * - logical walsenders in case cascade replication is allowed (could not
2008 * be created otherwise)
2009 * ------
2010 */
2013
2014 /*
2015 * If rm_redo called XLogRequestWalReceiverReply, then we wake up the
2016 * receiver so that it notices the updated lastReplayedEndRecPtr and sends
2017 * a reply to the primary.
2018 */
2020 {
2023 }
2024
2025 /* Allow read-only connections if we're consistent now */
2027
2028 /* Is this a timeline switch? */
2029 if (switchedTLI)
2030 {
2031 /*
2032 * Before we continue on the new timeline, clean up any (possibly
2033 * bogus) future WAL segments on the old timeline.
2034 */
2036
2037 /* Reset the prefetcher. */
2039 }
2040}
uint8_t uint8
Definition c.h:622
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
ErrorContextCallback * error_context_stack
Definition elog.c:100
#define XLOG_CHECKPOINT_SHUTDOWN
Definition pg_control.h:72
#define XLOG_END_OF_RECOVERY
Definition pg_control.h:81
static int fb(int x)
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition procarray.c:4456
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56
TimeLineID PrevTimeLineID
Definition pg_control.h:40
TimeLineID ThisTimeLineID
Definition pg_control.h:39
struct ErrorContextCallback * previous
Definition elog.h:299
void(* callback)(void *arg)
Definition elog.h:300
void(* rm_redo)(XLogReaderState *record)
XLogRecPtr EndRecPtr
Definition xlogreader.h:206
XLogRecPtr ReadRecPtr
Definition xlogreader.h:205
uint8 xl_info
Definition xlogrecord.h:46
TransactionId xl_xid
Definition xlogrecord.h:44
RmgrId xl_rmid
Definition xlogrecord.h:47
XLogRecPtr lastReplayedEndRecPtr
TimeLineID replayEndTLI
TimeLineID lastReplayedTLI
XLogRecPtr replayEndRecPtr
XLogRecPtr lastReplayedReadRecPtr
#define TransactionIdIsValid(xid)
Definition transam.h:41
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition varsup.c:299
void WalRcvRequestApplyReply(void)
#define AllowCascadeReplication()
Definition walreceiver.h:40
void WalSndWakeup(bool physical, bool logical)
Definition walsender.c:4012
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition xlog.c:3991
static RmgrData GetRmgr(RmgrId rmid)
uint32 TimeLineID
Definition xlogdefs.h:63
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)
XLogRecoveryCtlData * XLogRecoveryCtl
static bool doRequestWalReceiverReply
static XLogReaderState * xlogreader
HotStandbyState standbyState
Definition xlogutils.c:53
@ STANDBY_INITIALIZED
Definition xlogutils.h:53

References AdvanceNextFullTransactionIdPastXid(), AllowCascadeReplication, ErrorContextCallback::arg, ErrorContextCallback::callback, CheckRecoveryConsistency(), checkTimeLineSwitch(), doRequestWalReceiverReply, XLogReaderState::EndRecPtr, error_context_stack, fb(), GetRmgr(), XLogRecoveryCtlData::info_lck, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, memcpy(), ErrorContextCallback::previous, CheckPoint::PrevTimeLineID, XLogReaderState::ReadRecPtr, RecordKnownAssignedTransactionIds(), RemoveNonParentXlogFiles(), XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, RmgrData::rm_redo, rm_redo_error_callback(), SpinLockAcquire(), SpinLockRelease(), STANDBY_INITIALIZED, standbyState, CheckPoint::ThisTimeLineID, TransactionIdIsValid, verifyBackupPageConsistency(), WalRcvRequestApplyReply(), 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 4814 of file xlogrecovery.c.

4815{
4819
4820 if (newval && strcmp(newval, "") != 0)
4822 else
4824}
#define newval
RecoveryTargetType recoveryTarget
static pg_noreturn void error_multiple_recovery_targets(void)
@ RECOVERY_TARGET_IMMEDIATE
@ RECOVERY_TARGET_UNSET

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

◆ assign_recovery_target_lsn()

void assign_recovery_target_lsn ( const char newval,
void extra 
)

Definition at line 4855 of file xlogrecovery.c.

4856{
4860
4861 if (newval && strcmp(newval, "") != 0)
4862 {
4864 recoveryTargetLSN = *((XLogRecPtr *) extra);
4865 }
4866 else
4868}
uint64 XLogRecPtr
Definition xlogdefs.h:21
XLogRecPtr recoveryTargetLSN
@ RECOVERY_TARGET_LSN

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

◆ assign_recovery_target_name()

void assign_recovery_target_name ( const char newval,
void extra 
)

◆ assign_recovery_target_time()

void assign_recovery_target_time ( const char newval,
void extra 
)

◆ assign_recovery_target_timeline()

void assign_recovery_target_timeline ( const char newval,
void extra 
)

Definition at line 5033 of file xlogrecovery.c.

5034{
5038 else
5040}
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
TimeLineID recoveryTargetTLIRequested
RecoveryTargetTimeLineGoal
@ RECOVERY_TARGET_TIMELINE_NUMERIC

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

◆ assign_recovery_target_xid()

void assign_recovery_target_xid ( const char newval,
void extra 
)

Definition at line 5098 of file xlogrecovery.c.

5099{
5103
5104 if (newval && strcmp(newval, "") != 0)
5105 {
5107 recoveryTargetXid = *((TransactionId *) extra);
5108 }
5109 else
5111}
uint32 TransactionId
Definition c.h:736
TransactionId recoveryTargetXid
@ RECOVERY_TARGET_XID

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

◆ check_primary_slot_name()

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

Definition at line 4749 of file xlogrecovery.c.

4750{
4751 int err_code;
4752 char *err_msg = NULL;
4753 char *err_hint = NULL;
4754
4755 if (*newval && strcmp(*newval, "") != 0 &&
4757 &err_msg, &err_hint))
4758 {
4760 GUC_check_errdetail("%s", err_msg);
4761 if (err_hint != NULL)
4763 return false;
4764 }
4765
4766 return true;
4767}
void GUC_check_errcode(int sqlerrcode)
Definition guc.c:6666
#define GUC_check_errdetail
Definition guc.h:507
#define GUC_check_errhint
Definition guc.h:511
bool ReplicationSlotValidateNameInternal(const char *name, bool allow_reserved_name, int *err_code, char **err_msg, char **err_hint)
Definition slot.c:310

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

◆ check_recovery_target()

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

Definition at line 4800 of file xlogrecovery.c.

4801{
4802 if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
4803 {
4804 GUC_check_errdetail("The only allowed value is \"immediate\".");
4805 return false;
4806 }
4807 return true;
4808}

References fb(), GUC_check_errdetail, and newval.

◆ check_recovery_target_lsn()

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

Definition at line 4830 of file xlogrecovery.c.

4831{
4832 if (strcmp(*newval, "") != 0)
4833 {
4834 XLogRecPtr lsn;
4837
4838 lsn = pg_lsn_in_safe(*newval, (Node *) &escontext);
4839 if (escontext.error_occurred)
4840 return false;
4841
4842 myextra = (XLogRecPtr *) guc_malloc(LOG, sizeof(XLogRecPtr));
4843 if (!myextra)
4844 return false;
4845 *myextra = lsn;
4846 *extra = myextra;
4847 }
4848 return true;
4849}
#define LOG
Definition elog.h:32
void * guc_malloc(int elevel, size_t size)
Definition guc.c:637
XLogRecPtr pg_lsn_in_safe(const char *str, Node *escontext)
Definition pg_lsn.c:32
Definition nodes.h:135

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

◆ check_recovery_target_name()

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

Definition at line 4874 of file xlogrecovery.c.

4875{
4876 /* Use the value of newval directly */
4877 if (strlen(*newval) >= MAXFNAMELEN)
4878 {
4879 GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
4880 "recovery_target_name", MAXFNAMELEN - 1);
4881 return false;
4882 }
4883 return true;
4884}
#define MAXFNAMELEN

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

◆ check_recovery_target_time()

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

Definition at line 4915 of file xlogrecovery.c.

4916{
4917 if (strcmp(*newval, "") != 0)
4918 {
4919 /* reject some special values */
4920 if (strcmp(*newval, "now") == 0 ||
4921 strcmp(*newval, "today") == 0 ||
4922 strcmp(*newval, "tomorrow") == 0 ||
4923 strcmp(*newval, "yesterday") == 0)
4924 {
4925 return false;
4926 }
4927
4928 /*
4929 * parse timestamp value (see also timestamptz_in())
4930 */
4931 {
4932 char *str = *newval;
4933 fsec_t fsec;
4934 struct pg_tm tt,
4935 *tm = &tt;
4936 int tz;
4937 int dtype;
4938 int nf;
4939 int dterr;
4940 char *field[MAXDATEFIELDS];
4941 int ftype[MAXDATEFIELDS];
4945
4947 field, ftype, MAXDATEFIELDS, &nf);
4948 if (dterr == 0)
4949 dterr = DecodeDateTime(field, ftype, nf,
4950 &dtype, tm, &fsec, &tz, &dtextra);
4951 if (dterr != 0)
4952 return false;
4953 if (dtype != DTK_DATE)
4954 return false;
4955
4956 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
4957 {
4958 GUC_check_errdetail("Timestamp out of range: \"%s\".", str);
4959 return false;
4960 }
4961 }
4962 }
4963 return true;
4964}
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition datetime.c:775
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition datetime.c:1000
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition timestamp.c:2015
int64 TimestampTz
Definition timestamp.h:39
int32 fsec_t
Definition timestamp.h:41
const char * str
#define MAXDATEFIELDS
Definition datetime.h:202
#define DTK_DATE
Definition datetime.h:144
#define MAXDATELEN
Definition datetime.h:200
static struct pg_tm tm
Definition localtime.c:104
int64 timestamp
Definition pgtime.h:35

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

◆ check_recovery_target_timeline()

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

Definition at line 4986 of file xlogrecovery.c.

4987{
4990
4991 if (strcmp(*newval, "current") == 0)
4993 else if (strcmp(*newval, "latest") == 0)
4995 else
4996 {
4997 char *endp;
4998 uint64 timeline;
4999
5001
5002 errno = 0;
5003 timeline = strtou64(*newval, &endp, 0);
5004
5005 if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
5006 {
5007 GUC_check_errdetail("\"%s\" is not a valid number.",
5008 "recovery_target_timeline");
5009 return false;
5010 }
5011
5013 {
5014 GUC_check_errdetail("\"%s\" must be between %u and %u.",
5015 "recovery_target_timeline", 1, PG_UINT32_MAX);
5016 return false;
5017 }
5018 }
5019
5021 if (!myextra)
5022 return false;
5023 *myextra = rttg;
5024 *extra = myextra;
5025
5026 return true;
5027}
#define PG_UINT32_MAX
Definition c.h:674
uint64_t uint64
Definition c.h:625
@ RECOVERY_TARGET_TIMELINE_CONTROLFILE
@ RECOVERY_TARGET_TIMELINE_LATEST

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

◆ check_recovery_target_xid()

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

Definition at line 5046 of file xlogrecovery.c.

5047{
5048 if (strcmp(*newval, "") != 0)
5049 {
5050 TransactionId xid;
5052 char *endp;
5053 char *val;
5054
5055 errno = 0;
5056
5057 /*
5058 * Consume leading whitespace to determine if number is negative
5059 */
5060 val = *newval;
5061
5062 while (isspace((unsigned char) *val))
5063 val++;
5064
5065 /*
5066 * This cast will remove the epoch, if any
5067 */
5068 xid = (TransactionId) strtou64(val, &endp, 0);
5069
5070 if (*endp != '\0' || errno == EINVAL || errno == ERANGE || *val == '-')
5071 {
5072 GUC_check_errdetail("\"%s\" is not a valid number.",
5073 "recovery_target_xid");
5074 return false;
5075 }
5076
5077 if (xid < FirstNormalTransactionId)
5078 {
5079 GUC_check_errdetail("\"%s\" without epoch must be greater than or equal to %u.",
5080 "recovery_target_xid",
5082 return false;
5083 }
5084
5086 if (!myextra)
5087 return false;
5088 *myextra = xid;
5089 *extra = myextra;
5090 }
5091 return true;
5092}
long val
Definition informix.c:689
#define FirstNormalTransactionId
Definition transam.h:34

References fb(), FirstNormalTransactionId, GUC_check_errdetail, guc_malloc(), LOG, newval, and val.

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 4442 of file xlogrecovery.c.

4443{
4445 return true;
4446
4448 {
4449 ereport(LOG, (errmsg("received promote request")));
4453 return true;
4454 }
4455
4456 return false;
4457}
bool IsPromoteSignaled(void)
Definition startup.c:287
void ResetPromoteSignaled(void)
Definition startup.c:293
#define ereport(elevel,...)
Definition elog.h:152
static char * errmsg
bool CheckPromoteSignal(void)
static bool LocalPromoteIsTriggered
static void SetPromoteIsTriggered(void)
void RemovePromoteSignalFiles(void)

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

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

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 4472 of file xlogrecovery.c.

4473{
4474 struct stat stat_buf;
4475
4476 if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4477 return true;
4478
4479 return false;
4480}
#define stat
Definition win32_port.h:74
#define PROMOTE_SIGNAL_FILE
Definition xlog.h:341

References fb(), PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 2151 of file xlogrecovery.c.

2152{
2153 XLogRecPtr lastReplayedEndRecPtr;
2154 TimeLineID lastReplayedTLI;
2155
2156 /*
2157 * During crash recovery, we don't reach a consistent state until we've
2158 * replayed all the WAL.
2159 */
2161 return;
2162
2164
2165 /*
2166 * assume that we are called in the startup process, and hence don't need
2167 * a lock to read lastReplayedEndRecPtr
2168 */
2169 lastReplayedEndRecPtr = XLogRecoveryCtl->lastReplayedEndRecPtr;
2170 lastReplayedTLI = XLogRecoveryCtl->lastReplayedTLI;
2171
2172 /*
2173 * Have we reached the point where our base backup was completed?
2174 */
2176 backupEndPoint <= lastReplayedEndRecPtr)
2177 {
2180
2181 elog(DEBUG1, "end of backup reached");
2182
2183 /*
2184 * We have reached the end of base backup, as indicated by pg_control.
2185 * Update the control file accordingly.
2186 */
2187 ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI);
2190 backupEndRequired = false;
2191
2192 ereport(LOG,
2193 errmsg("completed backup recovery with redo LSN %X/%08X and end LSN %X/%08X",
2196 }
2197
2198 /*
2199 * Have we passed our safe starting point? Note that minRecoveryPoint is
2200 * known to be incorrectly set if recovering from a backup, until the
2201 * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint.
2202 * All we know prior to that is that we're not consistent yet.
2203 */
2205 minRecoveryPoint <= lastReplayedEndRecPtr)
2206 {
2207 /*
2208 * Check to see if the XLOG sequence contained any unresolved
2209 * references to uninitialized pages.
2210 */
2212
2213 /*
2214 * Check that pg_tblspc doesn't contain any real directories. Replay
2215 * of Database/CREATE_* records may have created fictitious tablespace
2216 * directories that should have been removed by the time consistency
2217 * was reached.
2218 */
2220
2221 reachedConsistency = true;
2223 ereport(LOG,
2224 errmsg("consistent recovery state reached at %X/%08X",
2225 LSN_FORMAT_ARGS(lastReplayedEndRecPtr)));
2226 }
2227
2228 /*
2229 * Have we got a valid starting snapshot that will allow queries to be
2230 * run? If so, we can tell postmaster that the database is consistent now,
2231 * enabling connections.
2232 */
2237 {
2241
2242 LocalHotStandbyActive = true;
2243
2245 }
2246}
#define Assert(condition)
Definition c.h:943
#define DEBUG1
Definition elog.h:31
#define elog(elevel,...)
Definition elog.h:228
bool IsUnderPostmaster
Definition globals.c:122
void SendPostmasterSignal(PMSignalReason reason)
Definition pmsignal.c:164
@ PMSIGNAL_BEGIN_HOT_STANDBY
Definition pmsignal.h:37
@ PMSIGNAL_RECOVERY_CONSISTENT
Definition pmsignal.h:36
void ReachedEndOfBackup(XLogRecPtr EndRecPtr, TimeLineID tli)
Definition xlog.c:6745
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
#define InvalidXLogRecPtr
Definition xlogdefs.h:28
bool reachedConsistency
static bool backupEndRequired
static XLogRecPtr minRecoveryPoint
static XLogRecPtr backupEndPoint
bool InArchiveRecovery
static bool LocalHotStandbyActive
static void CheckTablespaceDirectory(void)
static XLogRecPtr backupStartPoint
void XLogCheckInvalidPages(void)
Definition xlogutils.c:234
@ STANDBY_SNAPSHOT_READY
Definition xlogutils.h:55

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

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

◆ CheckTablespaceDirectory()

static void CheckTablespaceDirectory ( void  )
static

Definition at line 2118 of file xlogrecovery.c.

2119{
2120 DIR *dir;
2121 struct dirent *de;
2122
2124 while ((de = ReadDir(dir, PG_TBLSPC_DIR)) != NULL)
2125 {
2126 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR)];
2127
2128 /* Skip entries of non-oid names */
2129 if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
2130 continue;
2131
2132 snprintf(path, sizeof(path), "%s/%s", PG_TBLSPC_DIR, de->d_name);
2133
2134 if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
2137 errmsg("unexpected directory entry \"%s\" found in %s",
2139 errdetail("All directory entries in %s/ should be symbolic links.",
2141 errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete.")));
2142 }
2143}
bool allow_in_place_tablespaces
Definition tablespace.c:87
int errcode(int sqlerrcode)
Definition elog.c:875
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define PANIC
Definition elog.h:44
#define ERROR
Definition elog.h:40
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2957
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition file_utils.c:547
@ PGFILETYPE_LNK
Definition file_utils.h:24
#define ERRCODE_DATA_CORRUPTED
#define MAXPGPATH
#define snprintf
Definition port.h:261
#define PG_TBLSPC_DIR
Definition relpath.h:41
Definition dirent.c:26
char d_name[MAX_PATH]
Definition dirent.h:15

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

Referenced by CheckRecoveryConsistency().

◆ checkTimeLineSwitch()

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

Definition at line 2354 of file xlogrecovery.c.

2356{
2357 /* Check that the record agrees on what the current (old) timeline is */
2358 if (prevTLI != replayTLI)
2359 ereport(PANIC,
2360 (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2361 prevTLI, replayTLI)));
2362
2363 /*
2364 * The new timeline better be in the list of timelines we expect to see,
2365 * according to the timeline history. It should also not decrease.
2366 */
2367 if (newTLI < replayTLI || !tliInHistory(newTLI, expectedTLEs))
2368 ereport(PANIC,
2369 (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
2370 newTLI, replayTLI)));
2371
2372 /*
2373 * If we have not yet reached min recovery point, and we're about to
2374 * switch to a timeline greater than the timeline of the min recovery
2375 * point: trouble. After switching to the new timeline, we could not
2376 * possibly visit the min recovery point on the correct timeline anymore.
2377 * This can happen if there is a newer timeline in the archive that
2378 * branched before the timeline the min recovery point is on, and you
2379 * attempt to do PITR to the new timeline.
2380 */
2382 lsn < minRecoveryPoint &&
2384 ereport(PANIC,
2385 errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%08X on timeline %u",
2386 newTLI,
2389
2390 /* Looks good */
2391}
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition timeline.c:527
static List * expectedTLEs
static TimeLineID minRecoveryPointTLI

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

Referenced by ApplyWalRecord().

◆ ConfirmRecoveryPaused()

◆ emode_for_corrupt_record()

static int emode_for_corrupt_record ( int  emode,
XLogRecPtr  RecPtr 
)
static

Definition at line 4041 of file xlogrecovery.c.

4042{
4044
4045 if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
4046 {
4047 if (RecPtr == lastComplaint)
4048 emode = DEBUG1;
4049 else
4051 }
4052 return emode;
4053}
static XLogSource readSource

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

Referenced by ReadRecord(), and XLogPageRead().

◆ EnableStandbyMode()

static void EnableStandbyMode ( void  )
static

Definition at line 423 of file xlogrecovery.c.

424{
425 StandbyMode = true;
426
427 /*
428 * To avoid server log bloat, we don't report recovery progress in a
429 * standby as it will always be in recovery unless promoted. We disable
430 * startup progress timeout in standby mode to avoid calling
431 * startup_progress_timeout_handler() unnecessarily.
432 */
434}
void disable_startup_progress_timeout(void)
Definition startup.c:308
bool StandbyMode

References disable_startup_progress_timeout(), and StandbyMode.

Referenced by InitWalRecovery(), and ReadRecord().

◆ error_multiple_recovery_targets()

static pg_noreturn void error_multiple_recovery_targets ( void  )
static

Definition at line 4788 of file xlogrecovery.c.

4789{
4790 ereport(ERROR,
4792 errmsg("multiple recovery targets specified"),
4793 errdetail("At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set.")));
4794}

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

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

◆ FinishWalRecovery()

EndOfWalRecoveryInfo * FinishWalRecovery ( void  )

Definition at line 1417 of file xlogrecovery.c.

1418{
1420 XLogRecPtr lastRec;
1421 TimeLineID lastRecTLI;
1422 XLogRecPtr endOfLog;
1423
1424 /*
1425 * Kill WAL receiver, if it's still running, before we continue to write
1426 * the startup checkpoint and aborted-contrecord records. It will trump
1427 * over these records and subsequent ones if it's still alive when we
1428 * start writing WAL.
1429 */
1431
1432 /*
1433 * Shutdown the slot sync worker to drop any temporary slots acquired by
1434 * it and to prevent it from keep trying to fetch the failover slots.
1435 *
1436 * We do not update the 'synced' column in 'pg_replication_slots' system
1437 * view from true to false here, as any failed update could leave 'synced'
1438 * column false for some slots. This could cause issues during slot sync
1439 * after restarting the server as a standby. While updating the 'synced'
1440 * column after switching to the new timeline is an option, it does not
1441 * simplify the handling for the 'synced' column. Therefore, we retain the
1442 * 'synced' column as true after promotion as it may provide useful
1443 * information about the slot origin.
1444 */
1446
1447 /*
1448 * We are now done reading the xlog from stream. Turn off streaming
1449 * recovery to force fetching the files (which would be required at end of
1450 * recovery, e.g., timeline history file) from archive or pg_wal.
1451 *
1452 * Note that standby mode must be turned off after killing WAL receiver,
1453 * i.e., calling XLogShutdownWalRcv().
1454 */
1456 StandbyMode = false;
1457
1458 /*
1459 * Determine where to start writing WAL next.
1460 *
1461 * Re-fetch the last valid or last applied record, so we can identify the
1462 * exact endpoint of what we consider the valid portion of WAL. There may
1463 * be an incomplete continuation record after that, in which case
1464 * 'abortedRecPtr' and 'missingContrecPtr' are set and the caller will
1465 * write a special OVERWRITE_CONTRECORD message to mark that the rest of
1466 * it is intentionally missing. See CreateOverwriteContrecordRecord().
1467 *
1468 * An important side-effect of this is to load the last page into
1469 * xlogreader. The caller uses it to initialize the WAL for writing.
1470 */
1471 if (!InRecovery)
1472 {
1473 lastRec = CheckPointLoc;
1474 lastRecTLI = CheckPointTLI;
1475 }
1476 else
1477 {
1479 lastRecTLI = XLogRecoveryCtl->lastReplayedTLI;
1480 }
1482 (void) ReadRecord(xlogprefetcher, PANIC, false, lastRecTLI);
1483 endOfLog = xlogreader->EndRecPtr;
1484
1485 /*
1486 * Remember the TLI in the filename of the XLOG segment containing the
1487 * end-of-log. It could be different from the timeline that endOfLog
1488 * nominally belongs to, if there was a timeline switch in that segment,
1489 * and we were reading the old WAL from a segment belonging to a higher
1490 * timeline.
1491 */
1492 result->endOfLogTLI = xlogreader->seg.ws_tli;
1493
1495 {
1496 /*
1497 * We are no longer in archive recovery state.
1498 *
1499 * We are now done reading the old WAL. Turn off archive fetching if
1500 * it was active.
1501 */
1503 InArchiveRecovery = false;
1504
1505 /*
1506 * If the ending log segment is still open, close it (to avoid
1507 * problems on Windows with trying to rename or delete an open file).
1508 */
1509 if (readFile >= 0)
1510 {
1511 close(readFile);
1512 readFile = -1;
1513 }
1514 }
1515
1516 /*
1517 * Copy the last partial block to the caller, for initializing the WAL
1518 * buffer for appending new WAL.
1519 */
1520 if (endOfLog % XLOG_BLCKSZ != 0)
1521 {
1522 char *page;
1523 int len;
1525
1526 pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1528
1529 /* Copy the valid part of the last block */
1530 len = endOfLog % XLOG_BLCKSZ;
1531 page = palloc(len);
1532 memcpy(page, xlogreader->readBuf, len);
1533
1534 result->lastPageBeginPtr = pageBeginPtr;
1535 result->lastPage = page;
1536 }
1537 else
1538 {
1539 /* There is no partial block to copy. */
1540 result->lastPageBeginPtr = endOfLog;
1541 result->lastPage = NULL;
1542 }
1543
1544 /*
1545 * Create a comment for the history file to explain why and where timeline
1546 * changed.
1547 */
1548 result->recoveryStopReason = getRecoveryStopReason();
1549
1550 result->lastRec = lastRec;
1551 result->lastRecTLI = lastRecTLI;
1552 result->endOfLog = endOfLog;
1553
1554 result->abortedRecPtr = abortedRecPtr;
1555 result->missingContrecPtr = missingContrecPtr;
1556
1557 result->standby_signal_file_found = standby_signal_file_found;
1558 result->recovery_signal_file_found = recovery_signal_file_found;
1559
1560 return result;
1561}
uint32 result
#define palloc_object(type)
Definition fe_memutils.h:89
#define close(a)
Definition win32.h:12
void * palloc(Size size)
Definition mcxt.c:1390
const void size_t len
void ShutDownSlotSync(void)
Definition slotsync.c:1811
TimeLineID ws_tli
Definition xlogreader.h:49
WALOpenSegment seg
Definition xlogreader.h:271
bool WalRcvStreaming(void)
int wal_segment_size
Definition xlog.c:150
void XLogShutdownWalRcv(void)
Definition xlog.c:10146
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
void XLogPrefetcherBeginRead(XLogPrefetcher *prefetcher, XLogRecPtr recPtr)
static char * getRecoveryStopReason(void)
bool ArchiveRecoveryRequested
static XLogRecPtr missingContrecPtr
static uint32 readOff
static bool standby_signal_file_found
static int readFile
static XLogRecPtr abortedRecPtr
static XLogRecord * ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI)
static XLogRecPtr CheckPointLoc
static bool recovery_signal_file_found
static XLogPrefetcher * xlogprefetcher
static TimeLineID CheckPointTLI
bool InRecovery
Definition xlogutils.c:50

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

Referenced by StartupXLOG().

◆ GetCurrentChunkReplayStartTime()

◆ GetCurrentReplayRecPtr()

XLogRecPtr GetCurrentReplayRecPtr ( TimeLineID replayEndTLI)

◆ GetLatestXTime()

◆ getRecordTimestamp()

static bool getRecordTimestamp ( XLogReaderState record,
TimestampTz recordXtime 
)
static

Definition at line 2403 of file xlogrecovery.c.

2404{
2405 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2407 uint8 rmid = XLogRecGetRmid(record);
2408
2409 if (rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2410 {
2411 *recordXtime = ((xl_restore_point *) XLogRecGetData(record))->rp_time;
2412 return true;
2413 }
2414 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_COMMIT ||
2416 {
2417 *recordXtime = ((xl_xact_commit *) XLogRecGetData(record))->xact_time;
2418 return true;
2419 }
2420 if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_ABORT ||
2422 {
2423 *recordXtime = ((xl_xact_abort *) XLogRecGetData(record))->xact_time;
2424 return true;
2425 }
2426 return false;
2427}
#define XLOG_RESTORE_POINT
Definition pg_control.h:79
#define XLOG_XACT_COMMIT_PREPARED
Definition xact.h:173
#define XLOG_XACT_COMMIT
Definition xact.h:170
#define XLOG_XACT_OPMASK
Definition xact.h:180
#define XLOG_XACT_ABORT
Definition xact.h:172
#define XLOG_XACT_ABORT_PREPARED
Definition xact.h:174
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition xlogreader.h:411

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

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

◆ GetRecoveryPauseState()

◆ getRecoveryStopReason()

static char * getRecoveryStopReason ( void  )
static

Definition at line 2863 of file xlogrecovery.c.

2864{
2865 char reason[200];
2866
2868 snprintf(reason, sizeof(reason),
2869 "%s transaction %u",
2870 recoveryStopAfter ? "after" : "before",
2873 snprintf(reason, sizeof(reason),
2874 "%s %s\n",
2875 recoveryStopAfter ? "after" : "before",
2878 snprintf(reason, sizeof(reason),
2879 "%s LSN %X/%08X\n",
2880 recoveryStopAfter ? "after" : "before",
2883 snprintf(reason, sizeof(reason),
2884 "at restore point \"%s\"",
2887 snprintf(reason, sizeof(reason), "reached consistency");
2888 else
2889 snprintf(reason, sizeof(reason), "no recovery target specified");
2890
2891 return pstrdup(reason);
2892}
const char * timestamptz_to_str(TimestampTz t)
Definition timestamp.c:1870
char * pstrdup(const char *in)
Definition mcxt.c:1910
static XLogRecPtr recoveryStopLSN
static TimestampTz recoveryStopTime
static char recoveryStopName[MAXFNAMELEN]
static bool recoveryStopAfter
static TransactionId recoveryStopXid

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

Referenced by FinishWalRecovery().

◆ GetXLogReceiptTime()

void GetXLogReceiptTime ( TimestampTz rtime,
bool fromStream 
)

Definition at line 4651 of file xlogrecovery.c.

4652{
4653 /*
4654 * This must be executed in the startup process, since we don't export the
4655 * relevant state to shared memory.
4656 */
4658
4661}
static XLogSource XLogReceiptSource
static TimestampTz XLogReceiptTime

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

Referenced by GetStandbyLimitTime().

◆ GetXLogReplayRecPtr()

◆ HotStandbyActive()

bool HotStandbyActive ( void  )

Definition at line 4511 of file xlogrecovery.c.

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

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

Referenced by XLogWalRcvSendHSFeedback().

◆ HotStandbyActiveInReplay()

static bool HotStandbyActiveInReplay ( void  )
static

Definition at line 4536 of file xlogrecovery.c.

4537{
4539 return LocalHotStandbyActive;
4540}
bool IsPostmasterEnvironment
Definition globals.c:121
#define AmStartupProcess()
Definition miscadmin.h:405

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

459{
460 XLogPageReadPrivate *private;
461 struct stat st;
462 bool wasShutdown;
463 XLogRecord *record;
465 bool haveTblspcMap = false;
466 bool haveBackupLabel = false;
467 CheckPoint checkPoint;
468 bool backupFromStandby = false;
469
471
472 /*
473 * Initialize on the assumption we want to recover to the latest timeline
474 * that's active according to pg_control.
475 */
479 else
481
482 /*
483 * Check for signal files, and if so set up state for offline recovery
484 */
487
488 /*
489 * Take ownership of the wakeup latch if we're going to sleep during
490 * recovery, if required.
491 */
494
495 /*
496 * Set the WAL reading processor now, as it will be needed when reading
497 * the checkpoint record required (backup_label or not).
498 */
500 xlogreader =
502 XL_ROUTINE(.page_read = &XLogPageRead,
503 .segment_open = NULL,
504 .segment_close = wal_segment_close),
505 private);
506 if (!xlogreader)
509 errmsg("out of memory"),
510 errdetail("Failed while allocating a WAL reading processor.")));
512
513 /*
514 * Set the WAL decode buffer size. This limits how far ahead we can read
515 * in the WAL.
516 */
518
519 /* Create a WAL prefetcher. */
521
522 /*
523 * Allocate two page buffers dedicated to WAL consistency checks. We do
524 * it this way, rather than just making static arrays, for two reasons:
525 * (1) no need to waste the storage in most instantiations of the backend;
526 * (2) a static char array isn't guaranteed to have any particular
527 * alignment, whereas palloc() will provide MAXALIGN'd storage.
528 */
531
532 /*
533 * Read the backup_label file. We want to run this part of the recovery
534 * process after checking for signal files and after performing validation
535 * of the recovery parameters.
536 */
539 {
540 List *tablespaces = NIL;
541
542 /*
543 * Archive recovery was requested, and thanks to the backup label
544 * file, we know how far we need to replay to reach consistency. Enter
545 * archive recovery directly.
546 */
547 InArchiveRecovery = true;
550
551 /*
552 * Omitting backup_label when creating a new replica, PITR node etc.
553 * unfortunately is a common cause of corruption. Logging that
554 * backup_label was used makes it a bit easier to exclude that as the
555 * cause of observed corruption.
556 *
557 * Do so before we try to read the checkpoint record (which can fail),
558 * as otherwise it can be hard to understand why a checkpoint other
559 * than ControlFile->checkPoint is used.
560 */
561 ereport(LOG,
562 errmsg("starting backup recovery with redo LSN %X/%08X, checkpoint LSN %X/%08X, on timeline ID %u",
566
567 /*
568 * When a backup_label file is present, we want to roll forward from
569 * the checkpoint it identifies, rather than using pg_control.
570 */
573 if (record != NULL)
574 {
575 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
578 errmsg_internal("checkpoint record is at %X/%08X",
580 InRecovery = true; /* force recovery even if SHUTDOWNED */
581
582 /*
583 * Make sure that REDO location exists. This may not be the case
584 * if there was a crash during an online backup, which left a
585 * backup_label around that references a WAL segment that's
586 * already been archived.
587 */
588 if (checkPoint.redo < CheckPointLoc)
589 {
591 if (!ReadRecord(xlogprefetcher, LOG, false,
592 checkPoint.ThisTimeLineID))
594 errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
596 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
597 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
598 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
600 }
601 }
602 else
603 {
605 errmsg("could not locate required checkpoint record at %X/%08X",
607 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
608 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
609 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
611 wasShutdown = false; /* keep compiler quiet */
612 }
613
614 /* Read the tablespace_map file if present and create symlinks. */
615 if (read_tablespace_map(&tablespaces))
616 {
617 ListCell *lc;
618
619 foreach(lc, tablespaces)
620 {
622 char *linkloc;
623
624 linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid);
625
626 /*
627 * Remove the existing symlink if any and Create the symlink
628 * under PGDATA.
629 */
631
632 if (symlink(ti->path, linkloc) < 0)
635 errmsg("could not create symbolic link \"%s\": %m",
636 linkloc)));
637
638 pfree(ti->path);
639 pfree(ti);
640 }
641
642 /* tell the caller to delete it later */
643 haveTblspcMap = true;
644 }
645
646 /* tell the caller to delete it later */
647 haveBackupLabel = true;
648 }
649 else
650 {
651 /* No backup_label file has been found if we are here. */
652
653 /*
654 * If tablespace_map file is present without backup_label file, there
655 * is no use of such file. There is no harm in retaining it, but it
656 * is better to get rid of the map file so that we don't have any
657 * redundant file in data directory and it will avoid any sort of
658 * confusion. It seems prudent though to just rename the file out of
659 * the way rather than delete it completely, also we ignore any error
660 * that occurs in rename operation as even if map file is present
661 * without backup_label file, it is harmless.
662 */
663 if (stat(TABLESPACE_MAP, &st) == 0)
664 {
667 ereport(LOG,
668 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
670 errdetail("File \"%s\" was renamed to \"%s\".",
672 else
673 ereport(LOG,
674 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
676 errdetail("Could not rename file \"%s\" to \"%s\": %m.",
678 }
679
680 /*
681 * It's possible that archive recovery was requested, but we don't
682 * know how far we need to replay the WAL before we reach consistency.
683 * This can happen for example if a base backup is taken from a
684 * running server using an atomic filesystem snapshot, without calling
685 * pg_backup_start/stop. Or if you just kill a running primary server
686 * and put it into archive recovery by creating a recovery signal
687 * file.
688 *
689 * Our strategy in that case is to perform crash recovery first,
690 * replaying all the WAL present in pg_wal, and only enter archive
691 * recovery after that.
692 *
693 * But usually we already know how far we need to replay the WAL (up
694 * to minRecoveryPoint, up to backupEndPoint, or until we see an
695 * end-of-backup record), and we can enter archive recovery directly.
696 */
702 {
703 InArchiveRecovery = true;
706 }
707
708 /*
709 * For the same reason as when starting up with backup_label present,
710 * emit a log message when we continue initializing from a base
711 * backup.
712 */
714 ereport(LOG,
715 errmsg("restarting backup recovery with redo LSN %X/%08X",
717
718 /* Get the last valid checkpoint record. */
725 if (record != NULL)
726 {
728 errmsg_internal("checkpoint record is at %X/%08X",
730 }
731 else
732 {
733 /*
734 * We used to attempt to go back to a secondary checkpoint record
735 * here, but only when not in standby mode. We now just fail if we
736 * can't read the last checkpoint because this allows us to
737 * simplify processing around checkpoints.
738 */
740 errmsg("could not locate a valid checkpoint record at %X/%08X",
742 }
743 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
745
746 /* Make sure that REDO location exists. */
747 if (checkPoint.redo < CheckPointLoc)
748 {
750 if (!ReadRecord(xlogprefetcher, LOG, false, checkPoint.ThisTimeLineID))
752 errmsg("could not find redo location %X/%08X referenced by checkpoint record at %X/%08X",
754 }
755 }
756
758 {
760 ereport(LOG,
761 (errmsg("entering standby mode")));
763 ereport(LOG,
764 (errmsg("starting point-in-time recovery to XID %u",
767 ereport(LOG,
768 (errmsg("starting point-in-time recovery to %s",
771 ereport(LOG,
772 (errmsg("starting point-in-time recovery to \"%s\"",
775 ereport(LOG,
776 errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%08X\"",
779 ereport(LOG,
780 (errmsg("starting point-in-time recovery to earliest consistent point")));
781 else
782 ereport(LOG,
783 (errmsg("starting archive recovery")));
784 }
785
786 /*
787 * If the location of the checkpoint record is not on the expected
788 * timeline in the history of the requested timeline, we cannot proceed:
789 * the backup is not part of the history of the requested timeline.
790 */
791 Assert(expectedTLEs); /* was initialized by reading checkpoint
792 * record */
795 {
797
798 /*
799 * tliSwitchPoint will throw an error if the checkpoint's timeline is
800 * not in expectedTLEs at all.
801 */
804 (errmsg("requested timeline %u is not a child of this server's history",
806 /* translator: %s is a backup_label file or a pg_control file */
807 errdetail("Latest checkpoint in file \"%s\" is at %X/%08X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%08X.",
808 haveBackupLabel ? "backup_label" : "pg_control",
812 }
813
814 /*
815 * The min recovery point should be part of the requested timeline's
816 * history, too.
817 */
822 errmsg("requested timeline %u does not contain minimum recovery point %X/%08X on timeline %u",
826
828 errmsg_internal("redo record is at %X/%08X; shutdown %s",
829 LSN_FORMAT_ARGS(checkPoint.redo),
830 wasShutdown ? "true" : "false"));
832 (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
834 checkPoint.nextOid)));
836 (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %" PRIu64,
837 checkPoint.nextMulti, checkPoint.nextMultiOffset)));
839 (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
840 checkPoint.oldestXid, checkPoint.oldestXidDB)));
842 (errmsg_internal("oldest MultiXactId: %u, in database %u",
843 checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
845 (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
846 checkPoint.oldestCommitTsXid,
847 checkPoint.newestCommitTsXid)));
850 (errmsg("invalid next transaction ID")));
851
852 /* sanity check */
853 if (checkPoint.redo > CheckPointLoc)
855 (errmsg("invalid redo in checkpoint record")));
856
857 /*
858 * Check whether we need to force recovery from WAL. If it appears to
859 * have been a clean shutdown and we did not have a recovery signal file,
860 * then assume no recovery needed.
861 */
862 if (checkPoint.redo < CheckPointLoc)
863 {
864 if (wasShutdown)
866 (errmsg("invalid redo record in shutdown checkpoint")));
867 InRecovery = true;
868 }
869 else if (ControlFile->state != DB_SHUTDOWNED)
870 InRecovery = true;
872 {
873 /* force recovery due to presence of recovery signal file */
874 InRecovery = true;
875 }
876
877 /*
878 * If recovery is needed, update our in-memory copy of pg_control to show
879 * that we are recovering and to show the selected checkpoint as the place
880 * we are starting from. We also mark pg_control with any minimum recovery
881 * stop point obtained from a backup history file.
882 *
883 * We don't write the changes to disk yet, though. Only do that after
884 * initializing various subsystems.
885 */
886 if (InRecovery)
887 {
889 {
891 }
892 else
893 {
894 ereport(LOG,
895 (errmsg("database system was not properly shut down; "
896 "automatic recovery in progress")));
898 ereport(LOG,
899 (errmsg("crash recovery starts in timeline %u "
900 "and has target timeline %u",
904 }
906 ControlFile->checkPointCopy = checkPoint;
908 {
909 /* initialize minRecoveryPoint if not set yet */
910 if (ControlFile->minRecoveryPoint < checkPoint.redo)
911 {
912 ControlFile->minRecoveryPoint = checkPoint.redo;
914 }
915 }
916
917 /*
918 * Set backupStartPoint if we're starting recovery from a base backup.
919 *
920 * Also set backupEndPoint and use minRecoveryPoint as the backup end
921 * location if we're starting recovery from a base backup which was
922 * taken from a standby. In this case, the database system status in
923 * pg_control must indicate that the database was already in recovery.
924 * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
925 * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
926 * before reaching this point; e.g. because restore_command or
927 * primary_conninfo were faulty.
928 *
929 * Any other state indicates that the backup somehow became corrupted
930 * and we can't sensibly continue with recovery.
931 */
932 if (haveBackupLabel)
933 {
934 ControlFile->backupStartPoint = checkPoint.redo;
936
938 {
942 (errmsg("backup_label contains data inconsistent with control file"),
943 errhint("This means that the backup is corrupted and you will "
944 "have to use another backup for recovery.")));
946 }
947 }
948 }
949
950 /* remember these, so that we know when we have reached consistency */
955 {
958 }
959 else
960 {
963 }
964
965 /*
966 * Start recovery assuming that the final record isn't lost.
967 */
970
974}
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
Definition timeline.c:545
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition timeline.c:573
void remove_tablespace_symlink(const char *linkloc)
Definition tablespace.c:891
#define UINT64_FORMAT
Definition c.h:635
int errcode_for_file_access(void)
Definition elog.c:898
#define FATAL
Definition elog.h:42
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition fd.c:783
#define palloc0_object(type)
Definition fe_memutils.h:90
char * DataDir
Definition globals.c:73
void OwnLatch(Latch *latch)
Definition latch.c:126
void pfree(void *pointer)
Definition mcxt.c:1619
DBState
Definition pg_control.h:98
@ DB_IN_ARCHIVE_RECOVERY
Definition pg_control.h:104
@ DB_SHUTDOWNED_IN_RECOVERY
Definition pg_control.h:101
@ DB_SHUTDOWNED
Definition pg_control.h:100
@ DB_IN_CRASH_RECOVERY
Definition pg_control.h:103
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
Oid oldestMultiDB
Definition pg_control.h:52
MultiXactId oldestMulti
Definition pg_control.h:51
MultiXactOffset nextMultiOffset
Definition pg_control.h:48
TransactionId newestCommitTsXid
Definition pg_control.h:56
TransactionId oldestXid
Definition pg_control.h:49
MultiXactId nextMulti
Definition pg_control.h:47
FullTransactionId nextXid
Definition pg_control.h:45
TransactionId oldestCommitTsXid
Definition pg_control.h:54
XLogRecPtr redo
Definition pg_control.h:37
Oid oldestXidDB
Definition pg_control.h:50
XLogRecPtr backupStartPoint
Definition pg_control.h:178
CheckPoint checkPointCopy
Definition pg_control.h:143
XLogRecPtr backupEndPoint
Definition pg_control.h:179
XLogRecPtr minRecoveryPoint
Definition pg_control.h:176
XLogRecPtr checkPoint
Definition pg_control.h:141
uint64 system_identifier
Definition pg_control.h:118
TimeLineID minRecoveryPointTLI
Definition pg_control.h:177
Definition pg_list.h:54
uint64 system_identifier
Definition xlogreader.h:190
#define U64FromFullTransactionId(x)
Definition transam.h:49
#define XidFromFullTransactionId(x)
Definition transam.h:48
#define TransactionIdIsNormal(xid)
Definition transam.h:42
#define symlink(oldpath, newpath)
Definition win32_port.h:225
int wal_decode_buffer_size
Definition xlog.c:143
static ControlFileData * ControlFile
Definition xlog.c:584
#define TABLESPACE_MAP_OLD
Definition xlog.h:338
#define TABLESPACE_MAP
Definition xlog.h:337
#define BACKUP_LABEL_FILE
Definition xlog.h:334
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition xlogreader.c:108
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition xlogreader.c:92
#define XL_ROUTINE(...)
Definition xlogreader.h:117
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static void validateRecoveryParameters(void)
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
static TimeLineID RedoStartTLI
static void readRecoverySignalFile(void)
static bool read_tablespace_map(List **tablespaces)
static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
static char * primary_image_masked
static char * replay_image_masked
TimeLineID recoveryTargetTLI
static XLogRecPtr RedoStartLSN
static void EnableStandbyMode(void)
TimestampTz recoveryTargetTime
static bool StandbyModeRequested
void wal_segment_close(XLogReaderState *state)
Definition xlogutils.c:831

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

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1612 of file xlogrecovery.c.

1613{
1614 XLogRecord *record;
1615 bool reachedRecoveryTarget = false;
1616 TimeLineID replayTLI;
1617
1618 /*
1619 * Initialize shared variables for tracking progress of WAL replay, as if
1620 * we had just replayed the record before the REDO location (or the
1621 * checkpoint record itself, if it's a shutdown checkpoint).
1622 */
1625 {
1629 }
1630 else
1631 {
1635 }
1642
1643 /* Also ensure XLogReceiptTime has a sane value */
1645
1646 /*
1647 * Let postmaster know we've started redo now, so that it can launch the
1648 * archiver if necessary.
1649 */
1652
1653 /*
1654 * Allow read-only connections immediately if we're consistent already.
1655 */
1657
1658 /*
1659 * Find the first record that logically follows the checkpoint --- it
1660 * might physically precede it, though.
1661 */
1663 {
1664 /* back up to find the record */
1665 replayTLI = RedoStartTLI;
1667 record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1668
1669 /*
1670 * If a checkpoint record's redo pointer points back to an earlier
1671 * LSN, the record at that LSN should be an XLOG_CHECKPOINT_REDO
1672 * record.
1673 */
1674 if (record->xl_rmid != RM_XLOG_ID ||
1676 ereport(FATAL,
1677 errmsg("unexpected record type found at redo point %X/%08X",
1679 }
1680 else
1681 {
1682 /* just have to read next record after CheckPoint */
1684 replayTLI = CheckPointTLI;
1685 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1686 }
1687
1688 if (record != NULL)
1689 {
1691 PGRUsage ru0;
1692
1694
1695 InRedo = true;
1696
1697 RmgrStartup();
1698
1699 ereport(LOG,
1700 errmsg("redo starts at %X/%08X",
1702
1703 /* Prepare to report progress of the redo phase. */
1704 if (!StandbyMode)
1706
1707 /*
1708 * main redo apply loop
1709 */
1710 do
1711 {
1712 if (!StandbyMode)
1713 ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%08X",
1715
1716#ifdef WAL_DEBUG
1717 if (XLOG_DEBUG)
1718 {
1720
1722 appendStringInfo(&buf, "REDO @ %X/%08X; LSN %X/%08X: ",
1726 appendStringInfoString(&buf, " - ");
1728 elog(LOG, "%s", buf.data);
1729 pfree(buf.data);
1730 }
1731#endif
1732
1733 /* Handle interrupt signals of startup process */
1735
1736 /*
1737 * Pause WAL replay, if requested by a hot-standby session via
1738 * SetRecoveryPause().
1739 *
1740 * Note that we intentionally don't take the info_lck spinlock
1741 * here. We might therefore read a slightly stale value of the
1742 * recoveryPause flag, but it can't be very stale (no worse than
1743 * the last spinlock we did acquire). Since a pause request is a
1744 * pretty asynchronous thing anyway, possibly responding to it one
1745 * WAL record later than we otherwise would is a minor issue, so
1746 * it doesn't seem worth adding another spinlock cycle to prevent
1747 * that.
1748 */
1749 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1751 recoveryPausesHere(false);
1752
1753 /*
1754 * Have we reached our recovery target?
1755 */
1757 {
1758 reachedRecoveryTarget = true;
1759 break;
1760 }
1761
1762 /*
1763 * If we've been asked to lag the primary, wait on latch until
1764 * enough time has passed.
1765 */
1767 {
1768 /*
1769 * We test for paused recovery again here. If user sets
1770 * delayed apply, it may be because they expect to pause
1771 * recovery in case of problems, so we must test again here
1772 * otherwise pausing during the delay-wait wouldn't work.
1773 */
1774 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1776 recoveryPausesHere(false);
1777 }
1778
1779 /*
1780 * Apply the record
1781 */
1782 ApplyWalRecord(xlogreader, record, &replayTLI);
1783
1784 /*
1785 * Wake up processes waiting for standby replay, write, or flush
1786 * LSN to reach current replay position. Replay implies that the
1787 * WAL was already written and flushed to disk, so write and flush
1788 * waiters can be woken at the replay position too.
1789 */
1796
1797 /* Exit loop if we reached inclusive recovery target */
1799 {
1800 reachedRecoveryTarget = true;
1801 break;
1802 }
1803
1804 /* Else, try to fetch the next WAL record */
1805 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1806 } while (record != NULL);
1807
1808 /*
1809 * end of main redo apply loop
1810 */
1811
1813 {
1814 if (!reachedConsistency)
1815 ereport(FATAL,
1816 (errmsg("requested recovery stop point is before consistent recovery point")));
1817
1818 /*
1819 * This is the last point where we can restart recovery with a new
1820 * recovery target, if we shutdown and begin again. After this,
1821 * Resource Managers may choose to do permanent corrective actions
1822 * at end of recovery.
1823 */
1824 switch (recoveryTargetAction)
1825 {
1827
1828 /*
1829 * exit with special return code to request shutdown of
1830 * postmaster. Log messages issued from postmaster.
1831 */
1832 proc_exit(3);
1833
1835 SetRecoveryPause(true);
1836 recoveryPausesHere(true);
1837
1838 /* drop into promote */
1840
1842 break;
1843 }
1844 }
1845
1846 RmgrCleanup();
1847
1848 ereport(LOG,
1849 errmsg("redo done at %X/%08X system usage: %s",
1851 pg_rusage_show(&ru0)));
1853 if (xtime)
1854 ereport(LOG,
1855 (errmsg("last completed transaction was at log time %s",
1857
1858 InRedo = false;
1859 }
1860 else
1861 {
1862 /* there are no WAL records following the checkpoint */
1863 ereport(LOG,
1864 (errmsg("redo is not required")));
1865 }
1866
1867 /*
1868 * This check is intentionally after the above log messages that indicate
1869 * how far recovery went.
1870 */
1874 ereport(FATAL,
1876 errmsg("recovery ended before configured recovery target was reached")));
1877}
void begin_startup_progress_phase(void)
Definition startup.c:342
void ProcessStartupProcInterrupts(void)
Definition startup.c:154
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1649
#define pg_fallthrough
Definition c.h:161
void proc_exit(int code)
Definition ipc.c:105
#define XLOG_CHECKPOINT_REDO
Definition pg_control.h:86
const char * pg_rusage_show(const PGRUsage *ru0)
Definition pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition pg_rusage.c:27
static char buf[DEFAULT_XLOG_SEG_SIZE]
@ PMSIGNAL_RECOVERY_STARTED
Definition pmsignal.h:35
void RmgrStartup(void)
Definition rmgr.c:58
void RmgrCleanup(void)
Definition rmgr.c:74
#define ereport_startup_progress(msg,...)
Definition startup.h:18
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
#define XLR_INFO_MASK
Definition xlogrecord.h:62
static bool recoveryStopsBefore(XLogReaderState *record)
int recoveryTargetAction
static bool recoveryApplyDelay(XLogReaderState *record)
static bool recoveryStopsAfter(XLogReaderState *record)
void SetRecoveryPause(bool recoveryPause)
void xlog_outdesc(StringInfo buf, XLogReaderState *record)
static bool InRedo
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
static void recoveryPausesHere(bool endOfRecovery)
TimestampTz GetLatestXTime(void)
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
@ RECOVERY_NOT_PAUSED
void WaitLSNWakeup(WaitLSNType lsnType, XLogRecPtr currentLSN)
Definition xlogwait.c:344
@ WAIT_LSN_TYPE_STANDBY_REPLAY
Definition xlogwait.h:39
@ WAIT_LSN_TYPE_STANDBY_FLUSH
Definition xlogwait.h:41
@ WAIT_LSN_TYPE_STANDBY_WRITE
Definition xlogwait.h:40

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

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4403 of file xlogrecovery.c.

4404{
4405 /*
4406 * We check shared state each time only until a standby promotion is
4407 * triggered. We can't trigger a promotion again, so there's no need to
4408 * keep checking after the shared variable has once been seen true.
4409 */
4411 return true;
4412
4416
4418}

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

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

◆ read_backup_label()

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

Definition at line 1167 of file xlogrecovery.c.

1169{
1173 FILE *lfp;
1174 char ch;
1175 char backuptype[20];
1176 char backupfrom[20];
1177 char backuplabel[MAXPGPATH];
1178 char backuptime[128];
1179 uint32 hi,
1180 lo;
1181
1182 /* suppress possible uninitialized-variable warnings */
1184 *backupLabelTLI = 0;
1185 *backupEndRequired = false;
1186 *backupFromStandby = false;
1187
1188 /*
1189 * See if label file is present
1190 */
1192 if (!lfp)
1193 {
1194 if (errno != ENOENT)
1195 ereport(FATAL,
1197 errmsg("could not read file \"%s\": %m",
1199 return false; /* it's not there, all is fine */
1200 }
1201
1202 /*
1203 * Read and parse the START WAL LOCATION and CHECKPOINT lines (this code
1204 * is pretty crude, but we are not expecting any variability in the file
1205 * format).
1206 */
1207 if (fscanf(lfp, "START WAL LOCATION: %X/%08X (file %08X%16s)%c",
1208 &hi, &lo, &tli_from_walseg, startxlogfilename, &ch) != 5 || ch != '\n')
1209 ereport(FATAL,
1211 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
1212 RedoStartLSN = ((uint64) hi) << 32 | lo;
1214 if (fscanf(lfp, "CHECKPOINT LOCATION: %X/%08X%c",
1215 &hi, &lo, &ch) != 3 || ch != '\n')
1216 ereport(FATAL,
1218 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
1219 *checkPointLoc = ((uint64) hi) << 32 | lo;
1221
1222 /*
1223 * BACKUP METHOD lets us know if this was a typical backup ("streamed",
1224 * which could mean either pg_basebackup or the pg_backup_start/stop
1225 * method was used) or if this label came from somewhere else (the only
1226 * other option today being from pg_rewind). If this was a streamed
1227 * backup then we know that we need to play through until we get to the
1228 * end of the WAL which was generated during the backup (at which point we
1229 * will have reached consistency and backupEndRequired will be reset to be
1230 * false).
1231 */
1232 if (fscanf(lfp, "BACKUP METHOD: %19s\n", backuptype) == 1)
1233 {
1234 if (strcmp(backuptype, "streamed") == 0)
1235 *backupEndRequired = true;
1236 }
1237
1238 /*
1239 * BACKUP FROM lets us know if this was from a primary or a standby. If
1240 * it was from a standby, we'll double-check that the control file state
1241 * matches that of a standby.
1242 */
1243 if (fscanf(lfp, "BACKUP FROM: %19s\n", backupfrom) == 1)
1244 {
1245 if (strcmp(backupfrom, "standby") == 0)
1246 *backupFromStandby = true;
1247 }
1248
1249 /*
1250 * Parse START TIME and LABEL. Those are not mandatory fields for recovery
1251 * but checking for their presence is useful for debugging and the next
1252 * sanity checks. Cope also with the fact that the result buffers have a
1253 * pre-allocated size, hence if the backup_label file has been generated
1254 * with strings longer than the maximum assumed here an incorrect parsing
1255 * happens. That's fine as only minor consistency checks are done
1256 * afterwards.
1257 */
1258 if (fscanf(lfp, "START TIME: %127[^\n]\n", backuptime) == 1)
1260 (errmsg_internal("backup time %s in file \"%s\"",
1262
1263 if (fscanf(lfp, "LABEL: %1023[^\n]\n", backuplabel) == 1)
1265 (errmsg_internal("backup label %s in file \"%s\"",
1267
1268 /*
1269 * START TIMELINE is new as of 11. Its parsing is not mandatory, still use
1270 * it as a sanity check if present.
1271 */
1272 if (fscanf(lfp, "START TIMELINE: %u\n", &tli_from_file) == 1)
1273 {
1275 ereport(FATAL,
1277 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE),
1278 errdetail("Timeline ID parsed is %u, but expected %u.",
1280
1282 (errmsg_internal("backup timeline %u in file \"%s\"",
1284 }
1285
1286 if (fscanf(lfp, "INCREMENTAL FROM LSN: %X/%08X\n", &hi, &lo) > 0)
1287 ereport(FATAL,
1289 errmsg("this is an incremental backup, not a data directory"),
1290 errhint("Use pg_combinebackup to reconstruct a valid data directory.")));
1291
1292 if (ferror(lfp) || FreeFile(lfp))
1293 ereport(FATAL,
1295 errmsg("could not read file \"%s\": %m",
1297
1298 return true;
1299}
uint32_t uint32
Definition c.h:624
int FreeFile(FILE *file)
Definition fd.c:2827
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2628

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

Referenced by InitWalRecovery().

◆ read_tablespace_map()

static bool read_tablespace_map ( List **  tablespaces)
static

Definition at line 1313 of file xlogrecovery.c.

1314{
1316 FILE *lfp;
1317 char str[MAXPGPATH];
1318 int ch,
1319 i,
1320 n;
1321 bool was_backslash;
1322
1323 /*
1324 * See if tablespace_map file is present
1325 */
1327 if (!lfp)
1328 {
1329 if (errno != ENOENT)
1330 ereport(FATAL,
1332 errmsg("could not read file \"%s\": %m",
1333 TABLESPACE_MAP)));
1334 return false; /* it's not there, all is fine */
1335 }
1336
1337 /*
1338 * Read and parse the link name and path lines from tablespace_map file
1339 * (this code is pretty crude, but we are not expecting any variability in
1340 * the file format). De-escape any backslashes that were inserted.
1341 */
1342 i = 0;
1343 was_backslash = false;
1344 while ((ch = fgetc(lfp)) != EOF)
1345 {
1346 if (!was_backslash && (ch == '\n' || ch == '\r'))
1347 {
1348 char *endp;
1349
1350 if (i == 0)
1351 continue; /* \r immediately followed by \n */
1352
1353 /*
1354 * The de-escaped line should contain an OID followed by exactly
1355 * one space followed by a path. The path might start with
1356 * spaces, so don't be too liberal about parsing.
1357 */
1358 str[i] = '\0';
1359 n = 0;
1360 while (str[n] && str[n] != ' ')
1361 n++;
1362 if (n < 1 || n >= i - 1)
1363 ereport(FATAL,
1365 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1366 str[n++] = '\0';
1367
1369 errno = 0;
1370 ti->oid = strtoul(str, &endp, 10);
1371 if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
1372 ereport(FATAL,
1374 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1375 ti->path = pstrdup(str + n);
1376 *tablespaces = lappend(*tablespaces, ti);
1377
1378 i = 0;
1379 continue;
1380 }
1381 else if (!was_backslash && ch == '\\')
1382 was_backslash = true;
1383 else
1384 {
1385 if (i < sizeof(str) - 1)
1386 str[i++] = ch;
1387 was_backslash = false;
1388 }
1389 }
1390
1391 if (i != 0 || was_backslash) /* last line not terminated? */
1392 ereport(FATAL,
1394 errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1395
1396 if (ferror(lfp) || FreeFile(lfp))
1397 ereport(FATAL,
1399 errmsg("could not read file \"%s\": %m",
1400 TABLESPACE_MAP)));
1401
1402 return true;
1403}
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339

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

Referenced by InitWalRecovery().

◆ ReadCheckpointRecord()

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

Definition at line 4060 of file xlogrecovery.c.

4062{
4063 XLogRecord *record;
4064 uint8 info;
4065
4067
4068 if (!XRecOffIsValid(RecPtr))
4069 {
4070 ereport(LOG,
4071 (errmsg("invalid checkpoint location")));
4072 return NULL;
4073 }
4074
4076 record = ReadRecord(xlogprefetcher, LOG, true, replayTLI);
4077
4078 if (record == NULL)
4079 {
4080 ereport(LOG,
4081 (errmsg("invalid checkpoint record")));
4082 return NULL;
4083 }
4084 if (record->xl_rmid != RM_XLOG_ID)
4085 {
4086 ereport(LOG,
4087 (errmsg("invalid resource manager ID in checkpoint record")));
4088 return NULL;
4089 }
4090 info = record->xl_info & ~XLR_INFO_MASK;
4091 if (info != XLOG_CHECKPOINT_SHUTDOWN &&
4092 info != XLOG_CHECKPOINT_ONLINE)
4093 {
4094 ereport(LOG,
4095 (errmsg("invalid xl_info in checkpoint record")));
4096 return NULL;
4097 }
4099 {
4100 ereport(LOG,
4101 (errmsg("invalid length of checkpoint record")));
4102 return NULL;
4103 }
4104 return record;
4105}
#define XLOG_CHECKPOINT_ONLINE
Definition pg_control.h:73
uint32 xl_tot_len
Definition xlogrecord.h:43
#define XRecOffIsValid(xlrp)
#define SizeOfXLogRecordDataHeaderShort
Definition xlogrecord.h:217
#define SizeOfXLogRecord
Definition xlogrecord.h:55

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

Referenced by InitWalRecovery().

◆ ReadRecord()

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

Definition at line 3108 of file xlogrecovery.c.

3110{
3111 XLogRecord *record;
3114
3116
3117 /* Pass through parameters to XLogPageRead */
3118 private->fetching_ckpt = fetching_ckpt;
3119 private->emode = emode;
3120 private->randAccess = !XLogRecPtrIsValid(xlogreader->ReadRecPtr);
3121 private->replayTLI = replayTLI;
3122
3123 /* This is the first attempt to read this page. */
3124 lastSourceFailed = false;
3125
3126 for (;;)
3127 {
3128 char *errormsg;
3129
3130 record = XLogPrefetcherReadRecord(xlogprefetcher, &errormsg);
3131 if (record == NULL)
3132 {
3133 /*
3134 * When we find that WAL ends in an incomplete record, keep track
3135 * of that record. After recovery is done, we'll write a record
3136 * to indicate to downstream WAL readers that that portion is to
3137 * be ignored.
3138 *
3139 * However, when ArchiveRecoveryRequested = true, we're going to
3140 * switch to a new timeline at the end of recovery. We will only
3141 * copy WAL over to the new timeline up to the end of the last
3142 * complete record, so if we did this, we would later create an
3143 * overwrite contrecord in the wrong place, breaking everything.
3144 */
3147 {
3150 }
3151
3152 if (readFile >= 0)
3153 {
3154 close(readFile);
3155 readFile = -1;
3156 }
3157
3158 /*
3159 * We only end up here without a message when XLogPageRead()
3160 * failed - in that case we already logged something. In
3161 * StandbyMode that only happens if we have been triggered, so we
3162 * shouldn't loop anymore in that case.
3163 */
3164 if (errormsg)
3166 (errmsg_internal("%s", errormsg) /* already translated */ ));
3167 }
3168
3169 /*
3170 * Check page TLI is one of the expected values.
3171 */
3173 {
3174 char fname[MAXFNAMELEN];
3175 XLogSegNo segno;
3176 int32 offset;
3177
3181 XLogFileName(fname, xlogreader->seg.ws_tli, segno,
3184 errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%08X, offset %u",
3186 fname,
3188 offset));
3189 record = NULL;
3190 }
3191
3192 if (record)
3193 {
3194 /* Great, got a record */
3195 return record;
3196 }
3197 else
3198 {
3199 /* No valid record available from this source */
3200 lastSourceFailed = true;
3201
3202 /*
3203 * If archive recovery was requested, but we were still doing
3204 * crash recovery, switch to archive recovery and retry using the
3205 * offline archive. We have now replayed all the valid WAL in
3206 * pg_wal, so we are presumably now consistent.
3207 *
3208 * We require that there's at least some valid WAL present in
3209 * pg_wal, however (!fetching_ckpt). We could recover using the
3210 * WAL from the archive, even if pg_wal is completely empty, but
3211 * we'd have no idea how far we'd have to replay to reach
3212 * consistency. So err on the safe side and give up.
3213 */
3215 !fetching_ckpt)
3216 {
3218 (errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
3219 InArchiveRecovery = true;
3222
3225 minRecoveryPointTLI = replayTLI;
3226
3228
3229 /*
3230 * Before we retry, reset lastSourceFailed and currentSource
3231 * so that we will check the archive next.
3232 */
3233 lastSourceFailed = false;
3235
3236 continue;
3237 }
3238
3239 /* In standby mode, loop back to retry. Otherwise, give up. */
3241 continue;
3242 else
3243 return NULL;
3244 }
3245 }
3246}
int32_t int32
Definition c.h:620
XLogRecPtr missingContrecPtr
Definition xlogreader.h:214
XLogRecPtr abortedRecPtr
Definition xlogreader.h:213
TimeLineID latestPageTLI
Definition xlogreader.h:279
XLogRecPtr latestPagePtr
Definition xlogreader.h:278
void * private_data
Definition xlogreader.h:195
void SwitchIntoArchiveRecovery(XLogRecPtr EndRecPtr, TimeLineID replayTLI)
Definition xlog.c:6707
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint64 XLogSegNo
Definition xlogdefs.h:52
XLogRecord * XLogPrefetcherReadRecord(XLogPrefetcher *prefetcher, char **errmsg)
XLogReaderState * XLogPrefetcherGetReader(XLogPrefetcher *prefetcher)
static bool CheckForStandbyTrigger(void)
static bool lastSourceFailed
static XLogSource currentSource
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)

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

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

◆ readRecoverySignalFile()

static void readRecoverySignalFile ( void  )
static

Definition at line 984 of file xlogrecovery.c.

985{
986 struct stat stat_buf;
987
989 return;
990
991 /*
992 * Check for old recovery API file: recovery.conf
993 */
997 errmsg("using recovery command file \"%s\" is not supported",
999
1000 /*
1001 * Remove unused .done file, if present. Ignore if absent.
1002 */
1004
1005 /*
1006 * Check for recovery signal files and if found, fsync them since they
1007 * represent server state information. We don't sweat too much about the
1008 * possibility of fsync failure, however.
1009 */
1010 if (stat(STANDBY_SIGNAL_FILE, &stat_buf) == 0)
1011 {
1012 int fd;
1013
1015 S_IRUSR | S_IWUSR);
1016 if (fd >= 0)
1017 {
1018 (void) pg_fsync(fd);
1019 close(fd);
1020 }
1022 }
1023
1025 {
1026 int fd;
1027
1029 S_IRUSR | S_IWUSR);
1030 if (fd >= 0)
1031 {
1032 (void) pg_fsync(fd);
1033 close(fd);
1034 }
1036 }
1037
1038 /*
1039 * If both signal files are present, standby signal file takes precedence.
1040 * If neither is present then we won't enter archive recovery.
1041 */
1042 StandbyModeRequested = false;
1045 {
1046 StandbyModeRequested = true;
1048 }
1050 {
1051 StandbyModeRequested = false;
1053 }
1054 else
1055 return;
1056
1057 /*
1058 * We don't support standby mode in standalone backends; that requires
1059 * other processes such as the WAL receiver to be alive.
1060 */
1062 ereport(FATAL,
1064 errmsg("standby mode is not supported by single-user servers")));
1065}
#define PG_BINARY
Definition c.h:1374
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition fd.c:1112
int pg_fsync(int fd)
Definition fd.c:390
#define IsBootstrapProcessingMode()
Definition miscadmin.h:495
static int fd(const char *x, int i)
#define S_IRUSR
Definition win32_port.h:279
#define S_IWUSR
Definition win32_port.h:282
#define STANDBY_SIGNAL_FILE
Definition xlog.h:333
#define RECOVERY_SIGNAL_FILE
Definition xlog.h:332
#define RECOVERY_COMMAND_FILE
#define RECOVERY_COMMAND_DONE

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

Referenced by InitWalRecovery().

◆ recoveryApplyDelay()

static bool recoveryApplyDelay ( XLogReaderState record)
static

Definition at line 2959 of file xlogrecovery.c.

2960{
2964 long msecs;
2965
2966 /* nothing to do if no delay configured */
2967 if (recovery_min_apply_delay <= 0)
2968 return false;
2969
2970 /* no delay is applied on a database not yet consistent */
2971 if (!reachedConsistency)
2972 return false;
2973
2974 /* nothing to do if crash recovery is requested */
2976 return false;
2977
2978 /*
2979 * Is it a COMMIT record?
2980 *
2981 * We deliberately choose not to delay aborts since they have no effect on
2982 * MVCC. We already allow replay of records that don't have a timestamp,
2983 * so there is already opportunity for issues caused by early conflicts on
2984 * standbys.
2985 */
2986 if (XLogRecGetRmid(record) != RM_XACT_ID)
2987 return false;
2988
2990
2991 if (xact_info != XLOG_XACT_COMMIT &&
2993 return false;
2994
2995 if (!getRecordTimestamp(record, &xtime))
2996 return false;
2997
2999
3000 /*
3001 * Exit without arming the latch if it's already past time to apply this
3002 * record
3003 */
3005 if (msecs <= 0)
3006 return false;
3007
3008 while (true)
3009 {
3011
3012 /* This might change recovery_min_apply_delay. */
3014
3016 break;
3017
3018 /*
3019 * Recalculate delayUntil as recovery_min_apply_delay could have
3020 * changed while waiting in this loop.
3021 */
3023
3024 /*
3025 * Wait for difference between GetCurrentTimestamp() and delayUntil.
3026 */
3028 delayUntil);
3029
3030 if (msecs <= 0)
3031 break;
3032
3033 elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs);
3034
3037 msecs,
3039 }
3040 return true;
3041}
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.c:1765
#define DEBUG2
Definition elog.h:30
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
#define TimestampTzPlusMilliseconds(tz, ms)
Definition timestamp.h:85
#define WL_TIMEOUT
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET
static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime)
int recovery_min_apply_delay

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

Referenced by PerformWalRecovery().

◆ recoveryPausesHere()

static void recoveryPausesHere ( bool  endOfRecovery)
static

Definition at line 2902 of file xlogrecovery.c.

2903{
2904 /* Don't pause unless users can connect! */
2906 return;
2907
2908 /* Don't pause after standby promotion has been triggered */
2910 return;
2911
2912 if (endOfRecovery)
2913 ereport(LOG,
2914 (errmsg("pausing at the end of recovery"),
2915 errhint("Execute pg_wal_replay_resume() to promote.")));
2916 else
2917 ereport(LOG,
2918 (errmsg("recovery has paused"),
2919 errhint("Execute pg_wal_replay_resume() to continue.")));
2920
2921 /* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */
2923 {
2926 return;
2927
2928 /*
2929 * If recovery pause is requested then set it paused. While we are in
2930 * the loop, user might resume and pause again so set this every time.
2931 */
2933
2934 /*
2935 * We wait on a condition variable that will wake us as soon as the
2936 * pause ends, but we use a timeout so we can check the above exit
2937 * condition periodically too.
2938 */
2941 }
2943}
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
ConditionVariable recoveryNotPausedCV
static void ConfirmRecoveryPaused(void)
RecoveryPauseState GetRecoveryPauseState(void)

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

Referenced by PerformWalRecovery(), and WaitForWALToBecomeAvailable().

◆ RecoveryRequiresIntParameter()

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

Definition at line 4668 of file xlogrecovery.c.

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

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

Referenced by CheckRequiredParameterValues().

◆ recoveryStopsAfter()

static bool recoveryStopsAfter ( XLogReaderState record)
static

Definition at line 2703 of file xlogrecovery.c.

2704{
2705 uint8 info;
2707 uint8 rmid;
2709
2710 /*
2711 * Ignore recovery target settings when not in archive recovery (meaning
2712 * we are in crash recovery).
2713 */
2715 return false;
2716
2717 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2718 rmid = XLogRecGetRmid(record);
2719
2720 /*
2721 * There can be many restore points that share the same name; we stop at
2722 * the first one.
2723 */
2725 rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2726 {
2728
2730
2732 {
2733 recoveryStopAfter = true;
2738
2739 ereport(LOG,
2740 (errmsg("recovery stopping at restore point \"%s\", time %s",
2743 return true;
2744 }
2745 }
2746
2747 /* Check if the target LSN has been reached */
2750 record->ReadRecPtr >= recoveryTargetLSN)
2751 {
2752 recoveryStopAfter = true;
2754 recoveryStopLSN = record->ReadRecPtr;
2755 recoveryStopTime = 0;
2756 recoveryStopName[0] = '\0';
2757 ereport(LOG,
2758 errmsg("recovery stopping after WAL location (LSN) \"%X/%08X\"",
2760 return true;
2761 }
2762
2763 if (rmid != RM_XACT_ID)
2764 return false;
2765
2766 xact_info = info & XLOG_XACT_OPMASK;
2767
2768 if (xact_info == XLOG_XACT_COMMIT ||
2772 {
2774
2775 /* Update the last applied transaction timestamp */
2776 if (getRecordTimestamp(record, &recordXtime))
2778
2779 /* Extract the XID of the committed/aborted transaction */
2781 {
2784
2786 xlrec,
2787 &parsed);
2788 recordXid = parsed.twophase_xid;
2789 }
2791 {
2794
2796 xlrec,
2797 &parsed);
2798 recordXid = parsed.twophase_xid;
2799 }
2800 else
2801 recordXid = XLogRecGetXid(record);
2802
2803 /*
2804 * There can be only one transaction end record with this exact
2805 * transactionid
2806 *
2807 * when testing for an xid, we MUST test for equality only, since
2808 * transactions are numbered in the order they start, not the order
2809 * they complete. A higher numbered xid will complete before you about
2810 * 50% of the time...
2811 */
2814 {
2815 recoveryStopAfter = true;
2819 recoveryStopName[0] = '\0';
2820
2821 if (xact_info == XLOG_XACT_COMMIT ||
2823 {
2824 ereport(LOG,
2825 (errmsg("recovery stopping after commit of transaction %u, time %s",
2828 }
2829 else if (xact_info == XLOG_XACT_ABORT ||
2831 {
2832 ereport(LOG,
2833 (errmsg("recovery stopping after abort of transaction %u, time %s",
2836 }
2837 return true;
2838 }
2839 }
2840
2841 /* Check if we should stop as soon as reaching consistency */
2843 {
2844 ereport(LOG,
2845 (errmsg("recovery stopping after reaching consistency")));
2846
2847 recoveryStopAfter = true;
2849 recoveryStopTime = 0;
2851 recoveryStopName[0] = '\0';
2852 return true;
2853 }
2854
2855 return false;
2856}
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
#define InvalidTransactionId
Definition transam.h:31
void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
Definition xactdesc.c:35
void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
Definition xactdesc.c:141
#define XLogRecGetXid(decoder)
Definition xlogreader.h:412
bool recoveryTargetInclusive
static void SetLatestXTime(TimestampTz xtime)

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

Referenced by PerformWalRecovery().

◆ recoveryStopsBefore()

static bool recoveryStopsBefore ( XLogReaderState record)
static

Definition at line 2550 of file xlogrecovery.c.

2551{
2552 bool stopsHere = false;
2554 bool isCommit;
2557
2558 /*
2559 * Ignore recovery target settings when not in archive recovery (meaning
2560 * we are in crash recovery).
2561 */
2563 return false;
2564
2565 /* Check if we should stop as soon as reaching consistency */
2567 {
2568 ereport(LOG,
2569 (errmsg("recovery stopping after reaching consistency")));
2570
2571 recoveryStopAfter = false;
2574 recoveryStopTime = 0;
2575 recoveryStopName[0] = '\0';
2576 return true;
2577 }
2578
2579 /* Check if target LSN has been reached */
2582 record->ReadRecPtr >= recoveryTargetLSN)
2583 {
2584 recoveryStopAfter = false;
2586 recoveryStopLSN = record->ReadRecPtr;
2587 recoveryStopTime = 0;
2588 recoveryStopName[0] = '\0';
2589 ereport(LOG,
2590 errmsg("recovery stopping before WAL location (LSN) \"%X/%08X\"",
2592 return true;
2593 }
2594
2595 /* Otherwise we only consider stopping before COMMIT or ABORT records. */
2596 if (XLogRecGetRmid(record) != RM_XACT_ID)
2597 return false;
2598
2600
2602 {
2603 isCommit = true;
2604 recordXid = XLogRecGetXid(record);
2605 }
2607 {
2610
2611 isCommit = true;
2613 xlrec,
2614 &parsed);
2615 recordXid = parsed.twophase_xid;
2616 }
2617 else if (xact_info == XLOG_XACT_ABORT)
2618 {
2619 isCommit = false;
2620 recordXid = XLogRecGetXid(record);
2621 }
2623 {
2626
2627 isCommit = false;
2629 xlrec,
2630 &parsed);
2631 recordXid = parsed.twophase_xid;
2632 }
2633 else
2634 return false;
2635
2637 {
2638 /*
2639 * There can be only one transaction end record with this exact
2640 * transactionid
2641 *
2642 * when testing for an xid, we MUST test for equality only, since
2643 * transactions are numbered in the order they start, not the order
2644 * they complete. A higher numbered xid will complete before you about
2645 * 50% of the time...
2646 */
2648 }
2649
2650 /*
2651 * Note: we must fetch recordXtime regardless of recoveryTarget setting.
2652 * We don't expect getRecordTimestamp ever to fail, since we already know
2653 * this is a commit or abort record; but test its result anyway.
2654 */
2655 if (getRecordTimestamp(record, &recordXtime) &&
2657 {
2658 /*
2659 * There can be many transactions that share the same commit time, so
2660 * we stop after the last one, if we are inclusive, or stop at the
2661 * first one if we are exclusive
2662 */
2665 else
2667 }
2668
2669 if (stopsHere)
2670 {
2671 recoveryStopAfter = false;
2675 recoveryStopName[0] = '\0';
2676
2677 if (isCommit)
2678 {
2679 ereport(LOG,
2680 (errmsg("recovery stopping before commit of transaction %u, time %s",
2683 }
2684 else
2685 {
2686 ereport(LOG,
2687 (errmsg("recovery stopping before abort of transaction %u, time %s",
2690 }
2691 }
2692
2693 return stopsHere;
2694}

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

Referenced by PerformWalRecovery().

◆ RemovePromoteSignalFiles()

void RemovePromoteSignalFiles ( void  )

Definition at line 4463 of file xlogrecovery.c.

4464{
4466}

References fb(), and PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ rescanLatestTimeLine()

static bool rescanLatestTimeLine ( TimeLineID  replayTLI,
XLogRecPtr  replayLSN 
)
static

Definition at line 4115 of file xlogrecovery.c.

4116{
4118 bool found;
4119 ListCell *cell;
4123
4126 {
4127 /* No new timelines found */
4128 return false;
4129 }
4130
4131 /*
4132 * Determine the list of expected TLIs for the new TLI
4133 */
4134
4136
4137 /*
4138 * If the current timeline is not part of the history of the new timeline,
4139 * we cannot proceed to it.
4140 */
4141 found = false;
4142 foreach(cell, newExpectedTLEs)
4143 {
4145
4146 if (currentTle->tli == recoveryTargetTLI)
4147 {
4148 found = true;
4149 break;
4150 }
4151 }
4152 if (!found)
4153 {
4154 ereport(LOG,
4155 (errmsg("new timeline %u is not a child of database system timeline %u",
4156 newtarget,
4157 replayTLI)));
4158 return false;
4159 }
4160
4161 /*
4162 * The current timeline was found in the history file, but check that the
4163 * next timeline was forked off from it *after* the current recovery
4164 * location.
4165 */
4166 if (currentTle->end < replayLSN)
4167 {
4168 ereport(LOG,
4169 errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%08X",
4170 newtarget,
4171 replayTLI,
4173 return false;
4174 }
4175
4176 /* The new timeline history seems valid. Switch target */
4180
4181 /*
4182 * As in StartupXLOG(), try to ensure we have all the history files
4183 * between the old target and new target in pg_wal.
4184 */
4186
4187 ereport(LOG,
4188 (errmsg("new target timeline is %u",
4190
4191 return true;
4192}
List * readTimeLineHistory(TimeLineID targetTLI)
Definition timeline.c:77
TimeLineID findNewestTimeLine(TimeLineID startTLI)
Definition timeline.c:265
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
Definition timeline.c:51
void list_free_deep(List *list)
Definition list.c:1560

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

Referenced by WaitForWALToBecomeAvailable().

◆ rm_redo_error_callback()

static void rm_redo_error_callback ( void arg)
static

Definition at line 2252 of file xlogrecovery.c.

2253{
2254 XLogReaderState *record = (XLogReaderState *) arg;
2256
2258 xlog_outdesc(&buf, record);
2259 xlog_block_info(&buf, record);
2260
2261 /* translator: %s is a WAL record description */
2262 errcontext("WAL redo at %X/%08X for %s",
2263 LSN_FORMAT_ARGS(record->ReadRecPtr),
2264 buf.data);
2265
2266 pfree(buf.data);
2267}
Datum arg
Definition elog.c:1323
#define errcontext
Definition elog.h:200
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 4421 of file xlogrecovery.c.

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

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

Referenced by CheckForStandbyTrigger().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1567 of file xlogrecovery.c.

1568{
1569 char recoveryPath[MAXPGPATH];
1570
1571 /* Final update of pg_stat_recovery_prefetch. */
1573
1574 /* Shut down xlogreader */
1575 if (readFile >= 0)
1576 {
1577 close(readFile);
1578 readFile = -1;
1579 }
1583
1585 {
1586 /*
1587 * Since there might be a partial WAL segment named RECOVERYXLOG, get
1588 * rid of it.
1589 */
1590 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1591 unlink(recoveryPath); /* ignore any error */
1592
1593 /* Get rid of any remaining recovered timeline-history file, too */
1594 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1595 unlink(recoveryPath); /* ignore any error */
1596 }
1597
1598 /*
1599 * We don't need the latch anymore. It's not strictly necessary to disown
1600 * it, but let's do it for the sake of tidiness.
1601 */
1604}
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:163

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

Referenced by StartupXLOG().

◆ StartupRequestWalReceiverRestart()

void StartupRequestWalReceiverRestart ( void  )

Definition at line 4384 of file xlogrecovery.c.

4385{
4387 {
4388 ereport(LOG,
4389 (errmsg("WAL receiver process shutdown requested")));
4390
4391 pendingWalRcvRestart = true;
4392 }
4393}
bool WalRcvRunning(void)
static bool pendingWalRcvRestart

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

Referenced by StartupRereadConfig().

◆ validateRecoveryParameters()

static void validateRecoveryParameters ( void  )
static

Definition at line 1068 of file xlogrecovery.c.

1069{
1071 return;
1072
1073 /*
1074 * Check for compulsory parameters
1075 */
1077 {
1078 if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
1081 (errmsg("specified neither \"primary_conninfo\" nor \"restore_command\""),
1082 errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1083 }
1084 else
1085 {
1088 ereport(FATAL,
1090 errmsg("must specify \"restore_command\" when standby mode is not enabled")));
1091 }
1092
1093 /*
1094 * Override any inconsistent requests. Note that this is a change of
1095 * behaviour in 9.5; prior to this we simply ignored a request to pause if
1096 * hot_standby = off, which was surprising behaviour.
1097 */
1101
1102 /*
1103 * Final parsing of recovery_target_time string; see also
1104 * check_recovery_target_time().
1105 */
1107 {
1111 Int32GetDatum(-1)));
1112 }
1113
1114 /*
1115 * If user specified recovery_target_timeline, validate it or compute the
1116 * "latest" value. We can't do this until after we've gotten the restore
1117 * command and set InArchiveRecovery, because we need to fetch timeline
1118 * history files from the archive.
1119 */
1121 {
1123
1124 /* Timeline 1 does not have a history file, all else should */
1125 if (rtli != 1 && !existsTimeLineHistory(rtli))
1126 ereport(FATAL,
1128 errmsg("recovery target timeline %u does not exist",
1129 rtli)));
1131 }
1133 {
1134 /* We start the "latest" search from pg_control's timeline */
1136 }
1137 else
1138 {
1139 /*
1140 * else we just use the recoveryTargetTLI as already read from
1141 * ControlFile
1142 */
1144 }
1145}
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition timeline.c:223
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition timestamp.c:414
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:692
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
static TimestampTz DatumGetTimestampTz(Datum X)
Definition timestamp.h:34
bool EnableHotStandby
Definition xlog.c:128
char * recoveryRestoreCommand
char * recovery_target_time_string
char * PrimaryConnInfo

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

Referenced by InitWalRecovery().

◆ verifyBackupPageConsistency()

static void verifyBackupPageConsistency ( XLogReaderState record)
static

Definition at line 2438 of file xlogrecovery.c.

2439{
2441 RelFileLocator rlocator;
2442 ForkNumber forknum;
2443 BlockNumber blkno;
2444 int block_id;
2445
2446 /* Records with no backup blocks have no need for consistency checks. */
2447 if (!XLogRecHasAnyBlockRefs(record))
2448 return;
2449
2451
2452 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2453 {
2454 Buffer buf;
2455 Page page;
2456
2458 &rlocator, &forknum, &blkno, NULL))
2459 {
2460 /*
2461 * WAL record doesn't contain a block reference with the given id.
2462 * Do nothing.
2463 */
2464 continue;
2465 }
2466
2468
2469 if (XLogRecBlockImageApply(record, block_id))
2470 {
2471 /*
2472 * WAL record has already applied the page, so bypass the
2473 * consistency check as that would result in comparing the full
2474 * page stored in the record with itself.
2475 */
2476 continue;
2477 }
2478
2479 /*
2480 * Read the contents from the current buffer and store it in a
2481 * temporary page.
2482 */
2483 buf = XLogReadBufferExtended(rlocator, forknum, blkno,
2486 if (!BufferIsValid(buf))
2487 continue;
2488
2490 page = BufferGetPage(buf);
2491
2492 /*
2493 * Take a copy of the local page where WAL has been applied to have a
2494 * comparison base before masking it...
2495 */
2497
2498 /* No need for this page anymore now that a copy is in. */
2500
2501 /*
2502 * If the block LSN is already ahead of this WAL record, we can't
2503 * expect contents to match. This can happen if recovery is
2504 * restarted.
2505 */
2507 continue;
2508
2509 /*
2510 * Read the contents from the backup copy, stored in WAL record and
2511 * store it in a temporary page. There is no need to allocate a new
2512 * page here, a local buffer is fine to hold its contents and a mask
2513 * can be directly applied on it.
2514 */
2516 ereport(ERROR,
2518 errmsg_internal("%s", record->errormsg_buf)));
2519
2520 /*
2521 * If masking function is defined, mask both the primary and replay
2522 * images
2523 */
2524 if (rmgr.rm_mask != NULL)
2525 {
2526 rmgr.rm_mask(replay_image_masked, blkno);
2527 rmgr.rm_mask(primary_image_masked, blkno);
2528 }
2529
2530 /* Time to compare the primary and replay images. */
2532 {
2533 elog(FATAL,
2534 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2535 rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
2536 forknum, blkno);
2537 }
2538 }
2539}
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:5612
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
@ BUFFER_LOCK_EXCLUSIVE
Definition bufmgr.h:222
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:334
@ RBM_NORMAL_NO_LOG
Definition bufmgr.h:52
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
PageData * Page
Definition bufpage.h:81
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:410
ForkNumber
Definition relpath.h:56
RelFileNumber relNumber
char * errormsg_buf
Definition xlogreader.h:310
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
#define XLogRecBlockImageApply(decoder, block_id)
Definition xlogreader.h: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, fb(), GetRmgr(), InvalidBuffer, LockBuffer(), memcpy(), PageGetLSN(), primary_image_masked, RBM_NORMAL_NO_LOG, RelFileLocator::relNumber, replay_image_masked, RestoreBlockImage(), RelFileLocator::spcOid, UnlockReleaseBuffer(), XLogReadBufferExtended(), XLogRecBlockImageApply, XLogRecGetBlockTagExtended(), XLogRecGetInfo, XLogRecGetRmid, XLogRecHasAnyBlockRefs, XLogRecHasBlockImage, XLogRecMaxBlockId, and XLR_CHECK_CONSISTENCY.

Referenced by ApplyWalRecord().

◆ WaitForWALToBecomeAvailable()

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

Definition at line 3534 of file xlogrecovery.c.

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

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

2314{
2315 int block_id;
2316
2317 /* decode block references */
2318 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2319 {
2320 RelFileLocator rlocator;
2321 ForkNumber forknum;
2323
2325 &rlocator, &forknum, &blk, NULL))
2326 continue;
2327
2328 if (forknum != MAIN_FORKNUM)
2329 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, fork %u, blk %u",
2330 block_id,
2331 rlocator.spcOid, rlocator.dbOid,
2332 rlocator.relNumber,
2333 forknum,
2334 blk);
2335 else
2336 appendStringInfo(buf, "; blkref #%d: rel %u/%u/%u, blk %u",
2337 block_id,
2338 rlocator.spcOid, rlocator.dbOid,
2339 rlocator.relNumber,
2340 blk);
2341 if (XLogRecHasBlockImage(record, block_id))
2342 appendStringInfoString(buf, " FPW");
2343 }
2344}
@ MAIN_FORKNUM
Definition relpath.h:58

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

Referenced by rm_redo_error_callback().

◆ xlog_outdesc()

void xlog_outdesc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 2274 of file xlogrecovery.c.

2275{
2277 uint8 info = XLogRecGetInfo(record);
2278 const char *id;
2279
2282
2283 id = rmgr.rm_identify(info);
2284 if (id == NULL)
2285 appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2286 else
2287 appendStringInfo(buf, "%s: ", id);
2288
2289 rmgr.rm_desc(buf, record);
2290}
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242

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

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

◆ XLogFileRead()

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

Definition at line 4202 of file xlogrecovery.c.

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

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

Referenced by WaitForWALToBecomeAvailable(), and XLogFileReadAnyTLI().

◆ XLogFileReadAnyTLI()

static int XLogFileReadAnyTLI ( XLogSegNo  segno,
XLogSource  source 
)
static

Definition at line 4284 of file xlogrecovery.c.

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

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

Referenced by WaitForWALToBecomeAvailable().

◆ XLogPageRead()

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

Definition at line 3277 of file xlogrecovery.c.

3279{
3280 XLogPageReadPrivate *private =
3282 int emode = private->emode;
3285 int r;
3287
3289
3292
3293 /*
3294 * See if we need to switch to a new segment because the requested record
3295 * is not in the currently open one.
3296 */
3297 if (readFile >= 0 &&
3299 {
3300 /*
3301 * Request a restartpoint if we've replayed too much xlog since the
3302 * last one.
3303 */
3305 {
3307 {
3308 (void) GetRedoRecPtr();
3311 }
3312 }
3313
3314 close(readFile);
3315 readFile = -1;
3317 }
3318
3320
3321retry:
3322 /* See if we need to retrieve more data */
3323 if (readFile < 0 ||
3326 {
3327 if (readFile >= 0 &&
3331 return XLREAD_WOULDBLOCK;
3332
3334 private->randAccess,
3335 private->fetching_ckpt,
3337 private->replayTLI,
3340 {
3341 case XLREAD_WOULDBLOCK:
3342 return XLREAD_WOULDBLOCK;
3343 case XLREAD_FAIL:
3344 if (readFile >= 0)
3345 close(readFile);
3346 readFile = -1;
3347 readLen = 0;
3349 return XLREAD_FAIL;
3350 case XLREAD_SUCCESS:
3351 break;
3352 }
3353 }
3354
3355 /*
3356 * At this point, we have the right segment open and if we're streaming we
3357 * know the requested record is in it.
3358 */
3359 Assert(readFile != -1);
3360
3361 /*
3362 * If the current segment is being streamed from the primary, calculate
3363 * how much of the current page we have received already. We know the
3364 * requested record has been received, but this is for the benefit of
3365 * future calls, to allow quick exit at the top of this function.
3366 */
3368 {
3371 else
3374 }
3375 else
3377
3378 /* Read the requested page */
3380
3381 /* Measure I/O timing when reading segment */
3383
3385 r = pg_pread(readFile, readBuf, XLOG_BLCKSZ, (pgoff_t) readOff);
3386 if (r != XLOG_BLCKSZ)
3387 {
3388 char fname[MAXFNAMELEN];
3389 int save_errno = errno;
3390
3392
3394 io_start, 1, r);
3395
3397 if (r < 0)
3398 {
3399 errno = save_errno;
3402 errmsg("could not read from WAL segment %s, LSN %X/%08X, offset %u: %m",
3404 readOff)));
3405 }
3406 else
3409 errmsg("could not read from WAL segment %s, LSN %X/%08X, offset %u: read %d of %zu",
3411 readOff, r, (Size) XLOG_BLCKSZ)));
3413 }
3415
3417 io_start, 1, r);
3418
3421 Assert(reqLen <= readLen);
3422
3424
3425 /*
3426 * Check the page header immediately, so that we can retry immediately if
3427 * it's not valid. This may seem unnecessary, because ReadPageInternal()
3428 * validates the page header anyway, and would propagate the failure up to
3429 * ReadRecord(), which would retry. However, there's a corner case with
3430 * continuation records, if a record is split across two pages such that
3431 * we would need to read the two pages from different sources across two
3432 * WAL segments.
3433 *
3434 * The first page is only available locally, in pg_wal, because it's
3435 * already been recycled on the primary. The second page, however, is not
3436 * present in pg_wal, and we should stream it from the primary. There is a
3437 * recycled WAL segment present in pg_wal, with garbage contents, however.
3438 * We would read the first page from the local WAL segment, but when
3439 * reading the second page, we would read the bogus, recycled, WAL
3440 * segment. If we didn't catch that case here, we would never recover,
3441 * because ReadRecord() would retry reading the whole record from the
3442 * beginning.
3443 *
3444 * Of course, this only catches errors in the page header, which is what
3445 * happens in the case of a recycled WAL segment. Other kinds of errors or
3446 * corruption still has the same problem. But this at least fixes the
3447 * common case, which can happen as part of normal operation.
3448 *
3449 * Validating the page header is cheap enough that doing it twice
3450 * shouldn't be a big deal from a performance point of view.
3451 *
3452 * When not in standby mode, an invalid page header should cause recovery
3453 * to end, not retry reading the page, so we don't need to validate the
3454 * page header here for the retry. Instead, ReadPageInternal() is
3455 * responsible for the validation.
3456 */
3457 if (StandbyMode &&
3460 {
3461 /*
3462 * Emit this error right now then retry this page immediately. Use
3463 * errmsg_internal() because the message was already translated.
3464 */
3465 if (xlogreader->errormsg_buf[0])
3468
3469 /* reset any error XLogReaderValidatePageHeader() might have set */
3472 }
3473
3474 return readLen;
3475
3477
3478 /*
3479 * If we're reading ahead, give up fast. Retries and error reporting will
3480 * be handled by a later read when recovery catches up to this point.
3481 */
3483 return XLREAD_WOULDBLOCK;
3484
3485 lastSourceFailed = true;
3486
3487 if (readFile >= 0)
3488 close(readFile);
3489 readFile = -1;
3490 readLen = 0;
3492
3493 /* In standby-mode, keep trying */
3494 if (StandbyMode)
3495 goto retry;
3496 else
3497 return XLREAD_FAIL;
3498}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
size_t Size
Definition c.h:689
void RequestCheckpoint(int flags)
@ IOOBJECT_WAL
Definition pgstat.h:283
@ IOCONTEXT_NORMAL
Definition pgstat.h:293
@ IOOP_READ
Definition pgstat.h:319
instr_time pgstat_prepare_io_time(bool track_io_guc)
Definition pgstat_io.c:91
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
Definition pgstat_io.c:122
#define pg_pread
Definition port.h:248
off_t pgoff_t
Definition port.h:422
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:67
static void pgstat_report_wait_end(void)
Definition wait_event.h:83
XLogRecPtr GetRedoRecPtr(void)
Definition xlog.c:6935
bool track_wal_io_timing
Definition xlog.c:144
bool XLogCheckpointNeeded(XLogSegNo new_segno)
Definition xlog.c:2301
#define CHECKPOINT_CAUSE_XLOG
Definition xlog.h:160
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
void XLogReaderResetError(XLogReaderState *state)
bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr)
static XLogPageReadResult WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr, TimeLineID replayTLI, XLogRecPtr replayLSN, bool nonblocking)
static uint32 readLen

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

Referenced by InitWalRecovery().

◆ xlogrecovery_redo()

static void xlogrecovery_redo ( XLogReaderState record,
TimeLineID  replayTLI 
)
static

Definition at line 2047 of file xlogrecovery.c.

2048{
2049 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2050 XLogRecPtr lsn = record->EndRecPtr;
2051
2052 Assert(XLogRecGetRmid(record) == RM_XLOG_ID);
2053
2054 if (info == XLOG_OVERWRITE_CONTRECORD)
2055 {
2056 /* Verify the payload of a XLOG_OVERWRITE_CONTRECORD record. */
2058
2060 if (xlrec.overwritten_lsn != record->overwrittenRecPtr)
2061 elog(FATAL, "mismatching overwritten LSN %X/%08X -> %X/%08X",
2062 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
2064
2065 /* We have safely skipped the aborted record */
2068
2069 ereport(LOG,
2070 errmsg("successfully skipped missing contrecord at %X/%08X, overwritten at %s",
2071 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
2072 timestamptz_to_str(xlrec.overwrite_time)));
2073
2074 /* Verifying the record should only happen once */
2076 }
2077 else if (info == XLOG_BACKUP_END)
2078 {
2079 XLogRecPtr startpoint;
2080
2081 memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
2082
2083 if (backupStartPoint == startpoint)
2084 {
2085 /*
2086 * We have reached the end of base backup, the point where
2087 * pg_backup_stop() was done. The data on disk is now consistent
2088 * (assuming we have also reached minRecoveryPoint). Set
2089 * backupEndPoint to the current LSN, so that the next call to
2090 * CheckRecoveryConsistency() will notice it and do the
2091 * end-of-backup processing.
2092 */
2093 elog(DEBUG1, "end of backup record reached");
2094
2095 backupEndPoint = lsn;
2096 }
2097 else
2098 elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%08X, waiting for %X/%08X",
2100 }
2101}
#define XLOG_OVERWRITE_CONTRECORD
Definition pg_control.h:85
#define XLOG_BACKUP_END
Definition pg_control.h:77
XLogRecPtr overwrittenRecPtr
Definition xlogreader.h:216

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

Referenced by ApplyWalRecord().

◆ XLogRecoveryShmemInit()

static void XLogRecoveryShmemInit ( void arg)
static

◆ XLogRecoveryShmemRequest()

static void XLogRecoveryShmemRequest ( void arg)
static

Definition at line 400 of file xlogrecovery.c.

401{
402 ShmemRequestStruct(.name = "XLOG Recovery Ctl",
403 .size = sizeof(XLogRecoveryCtlData),
404 .ptr = (void **) &XLogRecoveryCtl,
405 );
406}
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name

References name, ShmemRequestStruct, and XLogRecoveryCtl.

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4496 of file xlogrecovery.c.

4497{
4499}

References doRequestWalReceiverReply.

Referenced by xact_redo_commit().

Variable Documentation

◆ abortedRecPtr

XLogRecPtr abortedRecPtr
static

◆ archiveCleanupCommand

char* archiveCleanupCommand = NULL

Definition at line 88 of file xlogrecovery.c.

Referenced by CreateRestartPoint().

◆ ArchiveRecoveryRequested

◆ backupEndPoint

XLogRecPtr backupEndPoint
static

Definition at line 286 of file xlogrecovery.c.

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

◆ backupEndRequired

bool backupEndRequired = false
static

Definition at line 287 of file xlogrecovery.c.

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

◆ backupStartPoint

XLogRecPtr backupStartPoint
static

Definition at line 285 of file xlogrecovery.c.

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

◆ CheckPointLoc

XLogRecPtr CheckPointLoc = InvalidXLogRecPtr
static

Definition at line 171 of file xlogrecovery.c.

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

◆ CheckPointTLI

TimeLineID CheckPointTLI = 0
static

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

Referenced by ApplyWalRecord(), and XLogRequestWalReceiverReply().

◆ expectedTLEs

◆ flushedUpto

XLogRecPtr flushedUpto = InvalidXLogRecPtr
static

Definition at line 266 of file xlogrecovery.c.

Referenced by WaitForWALToBecomeAvailable(), and XLogPageRead().

◆ InArchiveRecovery

◆ InRedo

bool InRedo = false
static

Definition at line 207 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and XLogFileRead().

◆ lastSourceFailed

bool lastSourceFailed = false
static

Definition at line 251 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 283 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 307 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 237 of file xlogrecovery.c.

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

◆ readOff

uint32 readOff = 0
static

Definition at line 236 of file xlogrecovery.c.

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

◆ readSegNo

XLogSegNo readSegNo = 0
static

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

Referenced by recoveryApplyDelay().

◆ recovery_signal_file_found

bool recovery_signal_file_found = false
static

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

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

◆ recovery_target_time_string

char* recovery_target_time_string

Definition at line 93 of file xlogrecovery.c.

Referenced by validateRecoveryParameters().

◆ recoveryEndCommand

char* recoveryEndCommand = NULL

Definition at line 87 of file xlogrecovery.c.

Referenced by CleanupAfterArchiveRecovery().

◆ recoveryRestoreCommand

char* recoveryRestoreCommand = NULL

Definition at line 86 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), and validateRecoveryParameters().

◆ recoveryStopAfter

bool recoveryStopAfter
static

Definition at line 336 of file xlogrecovery.c.

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

◆ recoveryStopLSN

XLogRecPtr recoveryStopLSN
static

Definition at line 334 of file xlogrecovery.c.

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

◆ recoveryStopName

char recoveryStopName[MAXFNAMELEN]
static

Definition at line 335 of file xlogrecovery.c.

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

◆ recoveryStopTime

TimestampTz recoveryStopTime
static

Definition at line 333 of file xlogrecovery.c.

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

◆ recoveryStopXid

TransactionId recoveryStopXid
static

Definition at line 332 of file xlogrecovery.c.

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

◆ recoveryTarget

◆ recoveryTargetAction

int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE

Definition at line 91 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and validateRecoveryParameters().

◆ recoveryTargetInclusive

bool recoveryTargetInclusive = true

Definition at line 90 of file xlogrecovery.c.

Referenced by recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTargetLSN

XLogRecPtr recoveryTargetLSN

◆ recoveryTargetName

const char* recoveryTargetName

Definition at line 95 of file xlogrecovery.c.

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

◆ recoveryTargetTime

TimestampTz recoveryTargetTime

Definition at line 94 of file xlogrecovery.c.

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

◆ recoveryTargetTimeLineGoal

◆ recoveryTargetTLI

◆ recoveryTargetTLIRequested

TimeLineID recoveryTargetTLIRequested = 0

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

Referenced by InitWalRecovery(), and verifyBackupPageConsistency().

◆ standby_signal_file_found

bool standby_signal_file_found = false
static

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

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().

◆ xlogprefetcher

◆ xlogreader

◆ XLogReceiptSource

XLogSource XLogReceiptSource = XLOG_FROM_ANY
static

Definition at line 263 of file xlogrecovery.c.

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

◆ XLogReceiptTime

TimestampTz XLogReceiptTime = 0
static

◆ XLogRecoveryCtl

◆ XLogRecoveryShmemCallbacks

const ShmemCallbacks XLogRecoveryShmemCallbacks
Initial value:
= {
.request_fn = XLogRecoveryShmemRequest,
}
static void XLogRecoveryShmemInit(void *arg)
static void XLogRecoveryShmemRequest(void *arg)

Definition at line 314 of file xlogrecovery.c.

314 {
315 .request_fn = XLogRecoveryShmemRequest,
316 .init_fn = XLogRecoveryShmemInit,
317};

◆ xlogSourceNames

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

Definition at line 222 of file xlogrecovery.c.

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

Referenced by WaitForWALToBecomeAvailable().