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

Go to the source code of this file.

Data Structures

struct  XLogPageReadPrivate
 
struct  XLogRecoveryCtlData
 

Macros

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

Typedefs

typedef struct XLogPageReadPrivate XLogPageReadPrivate
 
typedef struct XLogRecoveryCtlData XLogRecoveryCtlData
 

Enumerations

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

Functions

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

Variables

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

Macro Definition Documentation

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 69 of file xlogrecovery.c.

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 68 of file xlogrecovery.c.

Typedef Documentation

◆ XLogPageReadPrivate

◆ XLogRecoveryCtlData

Enumeration Type Documentation

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 209 of file xlogrecovery.c.

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

Function Documentation

◆ ApplyWalRecord()

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

Definition at line 1813 of file xlogrecovery.c.

1814 {
1815  ErrorContextCallback errcallback;
1816  bool switchedTLI = false;
1817 
1818  /* Setup error traceback support for ereport() */
1819  errcallback.callback = rm_redo_error_callback;
1820  errcallback.arg = (void *) xlogreader;
1821  errcallback.previous = error_context_stack;
1822  error_context_stack = &errcallback;
1823 
1824  /*
1825  * ShmemVariableCache->nextXid must be beyond record's xid.
1826  */
1828 
1829  /*
1830  * Before replaying this record, check if this record causes the current
1831  * timeline to change. The record is already considered to be part of the
1832  * new timeline, so we update replayTLI before replaying it. That's
1833  * important so that replayEndTLI, which is recorded as the minimum
1834  * recovery point's TLI if recovery stops after this record, is set
1835  * correctly.
1836  */
1837  if (record->xl_rmid == RM_XLOG_ID)
1838  {
1839  TimeLineID newReplayTLI = *replayTLI;
1840  TimeLineID prevReplayTLI = *replayTLI;
1841  uint8 info = record->xl_info & ~XLR_INFO_MASK;
1842 
1843  if (info == XLOG_CHECKPOINT_SHUTDOWN)
1844  {
1845  CheckPoint checkPoint;
1846 
1847  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
1848  newReplayTLI = checkPoint.ThisTimeLineID;
1849  prevReplayTLI = checkPoint.PrevTimeLineID;
1850  }
1851  else if (info == XLOG_END_OF_RECOVERY)
1852  {
1853  xl_end_of_recovery xlrec;
1854 
1855  memcpy(&xlrec, XLogRecGetData(xlogreader), sizeof(xl_end_of_recovery));
1856  newReplayTLI = xlrec.ThisTimeLineID;
1857  prevReplayTLI = xlrec.PrevTimeLineID;
1858  }
1859 
1860  if (newReplayTLI != *replayTLI)
1861  {
1862  /* Check that it's OK to switch to this TLI */
1864  newReplayTLI, prevReplayTLI, *replayTLI);
1865 
1866  /* Following WAL records should be run with new TLI */
1867  *replayTLI = newReplayTLI;
1868  switchedTLI = true;
1869  }
1870  }
1871 
1872  /*
1873  * Update shared replayEndRecPtr before replaying this record, so that
1874  * XLogFlush will update minRecoveryPoint correctly.
1875  */
1878  XLogRecoveryCtl->replayEndTLI = *replayTLI;
1880 
1881  /*
1882  * If we are attempting to enter Hot Standby mode, process XIDs we see
1883  */
1885  TransactionIdIsValid(record->xl_xid))
1887 
1888  /*
1889  * Some XLOG record types that are related to recovery are processed
1890  * directly here, rather than in xlog_redo()
1891  */
1892  if (record->xl_rmid == RM_XLOG_ID)
1893  xlogrecovery_redo(xlogreader, *replayTLI);
1894 
1895  /* Now apply the WAL record itself */
1896  GetRmgr(record->xl_rmid).rm_redo(xlogreader);
1897 
1898  /*
1899  * After redo, check whether the backup pages associated with the WAL
1900  * record are consistent with the existing pages. This check is done only
1901  * if consistency check is enabled for this record.
1902  */
1903  if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
1905 
1906  /* Pop the error context stack */
1907  error_context_stack = errcallback.previous;
1908 
1909  /*
1910  * Update lastReplayedEndRecPtr after this record has been successfully
1911  * replayed.
1912  */
1916  XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
1918 
1919  /*
1920  * If rm_redo called XLogRequestWalReceiverReply, then we wake up the
1921  * receiver so that it notices the updated lastReplayedEndRecPtr and sends
1922  * a reply to the primary.
1923  */
1925  {
1926  doRequestWalReceiverReply = false;
1927  WalRcvForceReply();
1928  }
1929 
1930  /* Allow read-only connections if we're consistent now */
1932 
1933  /* Is this a timeline switch? */
1934  if (switchedTLI)
1935  {
1936  /*
1937  * Before we continue on the new timeline, clean up any (possibly
1938  * bogus) future WAL segments on the old timeline.
1939  */
1941 
1942  /*
1943  * Wake up any walsenders to notice that we are on a new timeline.
1944  */
1946  WalSndWakeup();
1947 
1948  /* Reset the prefetcher. */
1950  }
1951 }
unsigned char uint8
Definition: c.h:440
ErrorContextCallback * error_context_stack
Definition: elog.c:94
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4392
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
struct ErrorContextCallback * previous
Definition: elog.h:234
void(* callback)(void *arg)
Definition: elog.h:235
void(* rm_redo)(XLogReaderState *record)
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
uint8 xl_info
Definition: xlogrecord.h:46
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogRecPtr lastReplayedEndRecPtr
Definition: xlogrecovery.c:339
TimeLineID replayEndTLI
Definition: xlogrecovery.c:348
TimeLineID lastReplayedTLI
Definition: xlogrecovery.c:340
XLogRecPtr replayEndRecPtr
Definition: xlogrecovery.c:347
XLogRecPtr lastReplayedReadRecPtr
Definition: xlogrecovery.c:338
TimeLineID PrevTimeLineID
TimeLineID ThisTimeLineID
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:277
void WalRcvForceReply(void)
Definition: walreceiver.c:1358
#define AllowCascadeReplication()
Definition: walreceiver.h:42
void WalSndWakeup(void)
Definition: walsender.c:3296
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition: xlog.c:3605
static RmgrData GetRmgr(RmgrId rmid)
uint32 TimeLineID
Definition: xlogdefs.h:59
void XLogPrefetchReconfigure(void)
#define XLogRecGetData(decoder)
Definition: xlogreader.h:416
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:80
static void rm_redo_error_callback(void *arg)
static void xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI)
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI, TimeLineID replayTLI)
static void CheckRecoveryConsistency(void)
static void verifyBackupPageConsistency(XLogReaderState *record)
static XLogRecoveryCtlData * XLogRecoveryCtl
Definition: xlogrecovery.c:364
static bool doRequestWalReceiverReply
Definition: xlogrecovery.c:185
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188
HotStandbyState standbyState
Definition: xlogutils.c:56
@ STANDBY_INITIALIZED
Definition: xlogutils.h:50

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

Referenced by PerformWalRecovery().

◆ assign_recovery_target()

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

Definition at line 4666 of file xlogrecovery.c.

4667 {
4670  error_multiple_recovery_targets();
4671 
4672  if (newval && strcmp(newval, "") != 0)
4674  else
4676 }
#define newval
RecoveryTargetType recoveryTarget
Definition: xlogrecovery.c:85
@ RECOVERY_TARGET_IMMEDIATE
Definition: xlogrecovery.h:30
@ RECOVERY_TARGET_UNSET
Definition: xlogrecovery.h:25

References newval, RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_UNSET, and recoveryTarget.

◆ assign_recovery_target_lsn()

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

Definition at line 4705 of file xlogrecovery.c.

4706 {
4709  error_multiple_recovery_targets();
4710 
4711  if (newval && strcmp(newval, "") != 0)
4712  {
4714  recoveryTargetLSN = *((XLogRecPtr *) extra);
4715  }
4716  else
4718 }
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr recoveryTargetLSN
Definition: xlogrecovery.c:92
@ RECOVERY_TARGET_LSN
Definition: xlogrecovery.h:29

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

◆ assign_recovery_target_name()

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

Definition at line 4740 of file xlogrecovery.c.

4741 {
4744  error_multiple_recovery_targets();
4745 
4746  if (newval && strcmp(newval, "") != 0)
4747  {
4750  }
4751  else
4753 }
const char * recoveryTargetName
Definition: xlogrecovery.c:91
@ RECOVERY_TARGET_NAME
Definition: xlogrecovery.h:28

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

◆ assign_recovery_target_time()

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

Definition at line 4818 of file xlogrecovery.c.

4819 {
4822  error_multiple_recovery_targets();
4823 
4824  if (newval && strcmp(newval, "") != 0)
4826  else
4828 }
@ RECOVERY_TARGET_TIME
Definition: xlogrecovery.h:27

References newval, RECOVERY_TARGET_TIME, RECOVERY_TARGET_UNSET, and recoveryTarget.

◆ assign_recovery_target_timeline()

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

Definition at line 4867 of file xlogrecovery.c.

4868 {
4871  recoveryTargetTLIRequested = (TimeLineID) strtoul(newval, NULL, 0);
4872  else
4874 }
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
Definition: xlogrecovery.c:120
TimeLineID recoveryTargetTLIRequested
Definition: xlogrecovery.c:121
RecoveryTargetTimeLineGoal
Definition: xlogrecovery.h:37
@ RECOVERY_TARGET_TIMELINE_NUMERIC
Definition: xlogrecovery.h:40

References newval, RECOVERY_TARGET_TIMELINE_NUMERIC, recoveryTargetTimeLineGoal, and recoveryTargetTLIRequested.

◆ assign_recovery_target_xid()

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

Definition at line 4903 of file xlogrecovery.c.

4904 {
4907  error_multiple_recovery_targets();
4908 
4909  if (newval && strcmp(newval, "") != 0)
4910  {
4912  recoveryTargetXid = *((TransactionId *) extra);
4913  }
4914  else
4916 }
uint32 TransactionId
Definition: c.h:588
TransactionId recoveryTargetXid
Definition: xlogrecovery.c:88
@ RECOVERY_TARGET_XID
Definition: xlogrecovery.h:26

References newval, RECOVERY_TARGET_UNSET, RECOVERY_TARGET_XID, recoveryTarget, and recoveryTargetXid.

◆ check_primary_slot_name()

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

Definition at line 4611 of file xlogrecovery.c.

4612 {
4613  if (*newval && strcmp(*newval, "") != 0 &&
4615  return false;
4616 
4617  return true;
4618 }
#define WARNING
Definition: elog.h:32
bool ReplicationSlotValidateName(const char *name, int elevel)
Definition: slot.c:198

References newval, ReplicationSlotValidateName(), and WARNING.

◆ check_recovery_target()

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

Definition at line 4652 of file xlogrecovery.c.

4653 {
4654  if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
4655  {
4656  GUC_check_errdetail("The only allowed value is \"immediate\".");
4657  return false;
4658  }
4659  return true;
4660 }
#define GUC_check_errdetail
Definition: guc.h:434

References GUC_check_errdetail, and newval.

◆ check_recovery_target_lsn()

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

Definition at line 4682 of file xlogrecovery.c.

4683 {
4684  if (strcmp(*newval, "") != 0)
4685  {
4686  XLogRecPtr lsn;
4687  XLogRecPtr *myextra;
4688  bool have_error = false;
4689 
4690  lsn = pg_lsn_in_internal(*newval, &have_error);
4691  if (have_error)
4692  return false;
4693 
4694  myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
4695  *myextra = lsn;
4696  *extra = (void *) myextra;
4697  }
4698  return true;
4699 }
#define ERROR
Definition: elog.h:35
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:631
XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error)
Definition: pg_lsn.c:30

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

◆ check_recovery_target_name()

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

Definition at line 4724 of file xlogrecovery.c.

4725 {
4726  /* Use the value of newval directly */
4727  if (strlen(*newval) >= MAXFNAMELEN)
4728  {
4729  GUC_check_errdetail("%s is too long (maximum %d characters).",
4730  "recovery_target_name", MAXFNAMELEN - 1);
4731  return false;
4732  }
4733  return true;
4734 }
#define MAXFNAMELEN

References GUC_check_errdetail, MAXFNAMELEN, and newval.

◆ check_recovery_target_time()

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

Definition at line 4765 of file xlogrecovery.c.

4766 {
4767  if (strcmp(*newval, "") != 0)
4768  {
4769  /* reject some special values */
4770  if (strcmp(*newval, "now") == 0 ||
4771  strcmp(*newval, "today") == 0 ||
4772  strcmp(*newval, "tomorrow") == 0 ||
4773  strcmp(*newval, "yesterday") == 0)
4774  {
4775  return false;
4776  }
4777 
4778  /*
4779  * parse timestamp value (see also timestamptz_in())
4780  */
4781  {
4782  char *str = *newval;
4783  fsec_t fsec;
4784  struct pg_tm tt,
4785  *tm = &tt;
4786  int tz;
4787  int dtype;
4788  int nf;
4789  int dterr;
4790  char *field[MAXDATEFIELDS];
4791  int ftype[MAXDATEFIELDS];
4792  char workbuf[MAXDATELEN + MAXDATEFIELDS];
4794 
4795  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
4796  field, ftype, MAXDATEFIELDS, &nf);
4797  if (dterr == 0)
4798  dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
4799  if (dterr != 0)
4800  return false;
4801  if (dtype != DTK_DATE)
4802  return false;
4803 
4804  if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
4805  {
4806  GUC_check_errdetail("timestamp out of range: \"%s\"", str);
4807  return false;
4808  }
4809  }
4810  }
4811  return true;
4812 }
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:753
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:974
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1926
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define MAXDATEFIELDS
Definition: datetime.h:203
#define DTK_DATE
Definition: datetime.h:145
#define MAXDATELEN
Definition: datetime.h:201
static struct pg_tm tm
Definition: localtime.c:104
int64 timestamp
Definition: pgtime.h:35

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

◆ check_recovery_target_timeline()

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

Definition at line 4834 of file xlogrecovery.c.

4835 {
4837  RecoveryTargetTimeLineGoal *myextra;
4838 
4839  if (strcmp(*newval, "current") == 0)
4841  else if (strcmp(*newval, "latest") == 0)
4843  else
4844  {
4846 
4847  errno = 0;
4848  strtoul(*newval, NULL, 0);
4849  if (errno == EINVAL || errno == ERANGE)
4850  {
4851  GUC_check_errdetail("recovery_target_timeline is not a valid number.");
4852  return false;
4853  }
4854  }
4855 
4857  *myextra = rttg;
4858  *extra = (void *) myextra;
4859 
4860  return true;
4861 }
@ RECOVERY_TARGET_TIMELINE_CONTROLFILE
Definition: xlogrecovery.h:38
@ RECOVERY_TARGET_TIMELINE_LATEST
Definition: xlogrecovery.h:39

References ERROR, GUC_check_errdetail, guc_malloc(), newval, RECOVERY_TARGET_TIMELINE_CONTROLFILE, RECOVERY_TARGET_TIMELINE_LATEST, and RECOVERY_TARGET_TIMELINE_NUMERIC.

◆ check_recovery_target_xid()

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

Definition at line 4880 of file xlogrecovery.c.

4881 {
4882  if (strcmp(*newval, "") != 0)
4883  {
4884  TransactionId xid;
4885  TransactionId *myextra;
4886 
4887  errno = 0;
4888  xid = (TransactionId) strtou64(*newval, NULL, 0);
4889  if (errno == EINVAL || errno == ERANGE)
4890  return false;
4891 
4892  myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
4893  *myextra = xid;
4894  *extra = (void *) myextra;
4895  }
4896  return true;
4897 }
#define strtou64(str, endptr, base)
Definition: c.h:1234

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

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 4304 of file xlogrecovery.c.

4305 {
4307  return true;
4308 
4310  {
4311  ereport(LOG, (errmsg("received promote request")));
4315  return true;
4316  }
4317 
4318  return false;
4319 }
bool IsPromoteSignaled(void)
Definition: startup.c:297
void ResetPromoteSignaled(void)
Definition: startup.c:303
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define LOG
Definition: elog.h:27
#define ereport(elevel,...)
Definition: elog.h:145
bool CheckPromoteSignal(void)
static bool LocalPromoteIsTriggered
Definition: xlogrecovery.c:182
static void SetPromoteIsTriggered(void)
void RemovePromoteSignalFiles(void)

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

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

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 4334 of file xlogrecovery.c.

4335 {
4336  struct stat stat_buf;
4337 
4338  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4339  return true;
4340 
4341  return false;
4342 }
#define stat
Definition: win32_port.h:286
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:297

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and sigusr1_handler().

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 2061 of file xlogrecovery.c.

2062 {
2063  XLogRecPtr lastReplayedEndRecPtr;
2064  TimeLineID lastReplayedTLI;
2065 
2066  /*
2067  * During crash recovery, we don't reach a consistent state until we've
2068  * replayed all the WAL.
2069  */
2071  return;
2072 
2074 
2075  /*
2076  * assume that we are called in the startup process, and hence don't need
2077  * a lock to read lastReplayedEndRecPtr
2078  */
2079  lastReplayedEndRecPtr = XLogRecoveryCtl->lastReplayedEndRecPtr;
2080  lastReplayedTLI = XLogRecoveryCtl->lastReplayedTLI;
2081 
2082  /*
2083  * Have we reached the point where our base backup was completed?
2084  */
2086  backupEndPoint <= lastReplayedEndRecPtr)
2087  {
2088  elog(DEBUG1, "end of backup reached");
2089 
2090  /*
2091  * We have reached the end of base backup, as indicated by pg_control.
2092  * Update the control file accordingly.
2093  */
2094  ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI);
2097  backupEndRequired = false;
2098  }
2099 
2100  /*
2101  * Have we passed our safe starting point? Note that minRecoveryPoint is
2102  * known to be incorrectly set if recovering from a backup, until the
2103  * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint.
2104  * All we know prior to that is that we're not consistent yet.
2105  */
2107  minRecoveryPoint <= lastReplayedEndRecPtr)
2108  {
2109  /*
2110  * Check to see if the XLOG sequence contained any unresolved
2111  * references to uninitialized pages.
2112  */
2114 
2115  /*
2116  * Check that pg_tblspc doesn't contain any real directories. Replay
2117  * of Database/CREATE_* records may have created ficticious tablespace
2118  * directories that should have been removed by the time consistency
2119  * was reached.
2120  */
2122 
2123  reachedConsistency = true;
2124  ereport(LOG,
2125  (errmsg("consistent recovery state reached at %X/%X",
2126  LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
2127  }
2128 
2129  /*
2130  * Have we got a valid starting snapshot that will allow queries to be
2131  * run? If so, we can tell postmaster that the database is consistent now,
2132  * enabling connections.
2133  */
2138  {
2142 
2143  LocalHotStandbyActive = true;
2144 
2146  }
2147 }
#define DEBUG1
Definition: elog.h:26
bool IsUnderPostmaster
Definition: globals.c:113
Assert(fmt[strlen(fmt) - 1] !='\n')
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:181
@ PMSIGNAL_BEGIN_HOT_STANDBY
Definition: pmsignal.h:36
void ReachedEndOfBackup(XLogRecPtr EndRecPtr, TimeLineID tli)
Definition: xlog.c:5825
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
bool reachedConsistency
Definition: xlogrecovery.c:294
static bool backupEndRequired
Definition: xlogrecovery.c:283
static XLogRecPtr minRecoveryPoint
Definition: xlogrecovery.c:278
static XLogRecPtr backupEndPoint
Definition: xlogrecovery.c:282
bool InArchiveRecovery
Definition: xlogrecovery.c:138
static bool LocalHotStandbyActive
Definition: xlogrecovery.c:176
static void CheckTablespaceDirectory(void)
static XLogRecPtr backupStartPoint
Definition: xlogrecovery.c:281
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:248
@ STANDBY_SNAPSHOT_READY
Definition: xlogutils.h:52

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

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

◆ CheckTablespaceDirectory()

static void CheckTablespaceDirectory ( void  )
static

Definition at line 2029 of file xlogrecovery.c.

2030 {
2031  DIR *dir;
2032  struct dirent *de;
2033 
2034  dir = AllocateDir("pg_tblspc");
2035  while ((de = ReadDir(dir, "pg_tblspc")) != NULL)
2036  {
2037  char path[MAXPGPATH + 10];
2038 
2039  /* Skip entries of non-oid names */
2040  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
2041  continue;
2042 
2043  snprintf(path, sizeof(path), "pg_tblspc/%s", de->d_name);
2044 
2045  if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK)
2048  errmsg("unexpected directory entry \"%s\" found in %s",
2049  de->d_name, "pg_tblspc/"),
2050  errdetail("All directory entries in pg_tblspc/ should be symbolic links."),
2051  errhint("Remove those directories, or set allow_in_place_tablespaces to ON transiently to let recovery complete.")));
2052  }
2053 }
bool allow_in_place_tablespaces
Definition: tablespace.c:91
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errhint(const char *fmt,...)
Definition: elog.c:1153
int errcode(int sqlerrcode)
Definition: elog.c:695
#define PANIC
Definition: elog.h:38
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2709
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2643
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:406
@ PGFILETYPE_LNK
Definition: file_utils.h:24
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
#define MAXPGPATH
#define snprintf
Definition: port.h:238
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

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

2257 {
2258  /* Check that the record agrees on what the current (old) timeline is */
2259  if (prevTLI != replayTLI)
2260  ereport(PANIC,
2261  (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2262  prevTLI, replayTLI)));
2263 
2264  /*
2265  * The new timeline better be in the list of timelines we expect to see,
2266  * according to the timeline history. It should also not decrease.
2267  */
2268  if (newTLI < replayTLI || !tliInHistory(newTLI, expectedTLEs))
2269  ereport(PANIC,
2270  (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
2271  newTLI, replayTLI)));
2272 
2273  /*
2274  * If we have not yet reached min recovery point, and we're about to
2275  * switch to a timeline greater than the timeline of the min recovery
2276  * point: trouble. After switching to the new timeline, we could not
2277  * possibly visit the min recovery point on the correct timeline anymore.
2278  * This can happen if there is a newer timeline in the archive that
2279  * branched before the timeline the min recovery point is on, and you
2280  * attempt to do PITR to the new timeline.
2281  */
2283  lsn < minRecoveryPoint &&
2284  newTLI > minRecoveryPointTLI)
2285  ereport(PANIC,
2286  (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
2287  newTLI,
2290 
2291  /* Looks good */
2292 }
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:526
static List * expectedTLEs
Definition: xlogrecovery.c:123
static TimeLineID minRecoveryPointTLI
Definition: xlogrecovery.c:279

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

Referenced by ApplyWalRecord().

◆ ConfirmRecoveryPaused()

static void ConfirmRecoveryPaused ( void  )
static

◆ emode_for_corrupt_record()

static int emode_for_corrupt_record ( int  emode,
XLogRecPtr  RecPtr 
)
static

Definition at line 3901 of file xlogrecovery.c.

3902 {
3903  static XLogRecPtr lastComplaint = 0;
3904 
3905  if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
3906  {
3907  if (RecPtr == lastComplaint)
3908  emode = DEBUG1;
3909  else
3910  lastComplaint = RecPtr;
3911  }
3912  return emode;
3913 }
static XLogSource readSource
Definition: xlogrecovery.c:234

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo* FinishWalRecovery ( void  )

Definition at line 1387 of file xlogrecovery.c.

1388 {
1390  XLogRecPtr lastRec;
1391  TimeLineID lastRecTLI;
1392  XLogRecPtr endOfLog;
1393 
1394  /*
1395  * Kill WAL receiver, if it's still running, before we continue to write
1396  * the startup checkpoint and aborted-contrecord records. It will trump
1397  * over these records and subsequent ones if it's still alive when we
1398  * start writing WAL.
1399  */
1401 
1402  /*
1403  * We are now done reading the xlog from stream. Turn off streaming
1404  * recovery to force fetching the files (which would be required at end of
1405  * recovery, e.g., timeline history file) from archive or pg_wal.
1406  *
1407  * Note that standby mode must be turned off after killing WAL receiver,
1408  * i.e., calling XLogShutdownWalRcv().
1409  */
1410  Assert(!WalRcvStreaming());
1411  StandbyMode = false;
1412 
1413  /*
1414  * Determine where to start writing WAL next.
1415  *
1416  * Re-fetch the last valid or last applied record, so we can identify the
1417  * exact endpoint of what we consider the valid portion of WAL. There may
1418  * be an incomplete continuation record after that, in which case
1419  * 'abortedRecPtr' and 'missingContrecPtr' are set and the caller will
1420  * write a special OVERWRITE_CONTRECORD message to mark that the rest of
1421  * it is intentionally missing. See CreateOverwriteContrecordRecord().
1422  *
1423  * An important side-effect of this is to load the last page into
1424  * xlogreader. The caller uses it to initialize the WAL for writing.
1425  */
1426  if (!InRecovery)
1427  {
1428  lastRec = CheckPointLoc;
1429  lastRecTLI = CheckPointTLI;
1430  }
1431  else
1432  {
1434  lastRecTLI = XLogRecoveryCtl->lastReplayedTLI;
1435  }
1437  (void) ReadRecord(xlogprefetcher, PANIC, false, lastRecTLI);
1438  endOfLog = xlogreader->EndRecPtr;
1439 
1440  /*
1441  * Remember the TLI in the filename of the XLOG segment containing the
1442  * end-of-log. It could be different from the timeline that endOfLog
1443  * nominally belongs to, if there was a timeline switch in that segment,
1444  * and we were reading the old WAL from a segment belonging to a higher
1445  * timeline.
1446  */
1447  result->endOfLogTLI = xlogreader->seg.ws_tli;
1448 
1450  {
1451  /*
1452  * We are no longer in archive recovery state.
1453  *
1454  * We are now done reading the old WAL. Turn off archive fetching if
1455  * it was active.
1456  */
1458  InArchiveRecovery = false;
1459 
1460  /*
1461  * If the ending log segment is still open, close it (to avoid
1462  * problems on Windows with trying to rename or delete an open file).
1463  */
1464  if (readFile >= 0)
1465  {
1466  close(readFile);
1467  readFile = -1;
1468  }
1469  }
1470 
1471  /*
1472  * Copy the last partial block to the caller, for initializing the WAL
1473  * buffer for appending new WAL.
1474  */
1475  if (endOfLog % XLOG_BLCKSZ != 0)
1476  {
1477  char *page;
1478  int len;
1479  XLogRecPtr pageBeginPtr;
1480 
1481  pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1482  Assert(readOff == XLogSegmentOffset(pageBeginPtr, wal_segment_size));
1483 
1484  /* Copy the valid part of the last block */
1485  len = endOfLog % XLOG_BLCKSZ;
1486  page = palloc(len);
1487  memcpy(page, xlogreader->readBuf, len);
1488 
1489  result->lastPageBeginPtr = pageBeginPtr;
1490  result->lastPage = page;
1491  }
1492  else
1493  {
1494  /* There is no partial block to copy. */
1495  result->lastPageBeginPtr = endOfLog;
1496  result->lastPage = NULL;
1497  }
1498 
1499  /*
1500  * Create a comment for the history file to explain why and where timeline
1501  * changed.
1502  */
1504 
1505  result->lastRec = lastRec;
1506  result->lastRecTLI = lastRecTLI;
1507  result->endOfLog = endOfLog;
1508 
1509  result->abortedRecPtr = abortedRecPtr;
1511 
1514 
1515  return result;
1516 }
#define close(a)
Definition: win32.h:12
void * palloc(Size size)
Definition: mcxt.c:1199
const void size_t len
XLogRecPtr lastPageBeginPtr
Definition: xlogrecovery.h:111
XLogRecPtr abortedRecPtr
Definition: xlogrecovery.h:120
XLogRecPtr missingContrecPtr
Definition: xlogrecovery.h:121
TimeLineID endOfLogTLI
Definition: xlogrecovery.h:109
TimeLineID ws_tli
Definition: xlogreader.h:49
WALOpenSegment seg
Definition: xlogreader.h:272
bool WalRcvStreaming(void)
int wal_segment_size
Definition: xlog.c:146
void XLogShutdownWalRcv(void)
Definition: xlog.c:8898
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
void XLogPrefetcherBeginRead(XLogPrefetcher *prefetcher, XLogRecPtr recPtr)
static char * getRecoveryStopReason(void)
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:137
static XLogRecPtr missingContrecPtr
Definition: xlogrecovery.c:373
static uint32 readOff
Definition: xlogrecovery.c:232
static bool standby_signal_file_found
Definition: xlogrecovery.c:150
bool StandbyMode
Definition: xlogrecovery.c:147
static int readFile
Definition: xlogrecovery.c:230
static XLogRecPtr abortedRecPtr
Definition: xlogrecovery.c:372
static XLogRecord * ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI)
static XLogRecPtr CheckPointLoc
Definition: xlogrecovery.c:167
static bool recovery_signal_file_found
Definition: xlogrecovery.c:151
static XLogPrefetcher * xlogprefetcher
Definition: xlogrecovery.c:191
static TimeLineID CheckPointTLI
Definition: xlogrecovery.c:168
bool InRecovery
Definition: xlogutils.c:53

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

Referenced by StartupXLOG().

◆ GetCurrentChunkReplayStartTime()

TimestampTz GetCurrentChunkReplayStartTime ( void  )

Definition at line 4497 of file xlogrecovery.c.

4498 {
4499  TimestampTz xtime;
4500 
4504 
4505  return xtime;
4506 }
TimestampTz currentChunkStartTime
Definition: xlogrecovery.c:356

References XLogRecoveryCtlData::currentChunkStartTime, XLogRecoveryCtlData::info_lck, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by GetReplicationApplyDelay().

◆ GetCurrentReplayRecPtr()

XLogRecPtr GetCurrentReplayRecPtr ( TimeLineID replayEndTLI)

Definition at line 4433 of file xlogrecovery.c.

4434 {
4435  XLogRecPtr recptr;
4436  TimeLineID tli;
4437 
4439  recptr = XLogRecoveryCtl->replayEndRecPtr;
4442 
4443  if (replayEndTLI)
4444  *replayEndTLI = tli;
4445  return recptr;
4446 }

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

Referenced by UpdateMinRecoveryPoint(), and xlog_redo().

◆ GetLatestXTime()

TimestampTz GetLatestXTime ( void  )

◆ getRecordTimestamp()

static bool getRecordTimestamp ( XLogReaderState record,
TimestampTz recordXtime 
)
static

Definition at line 2304 of file xlogrecovery.c.

2305 {
2306  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2307  uint8 xact_info = info & XLOG_XACT_OPMASK;
2308  uint8 rmid = XLogRecGetRmid(record);
2309 
2310  if (rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2311  {
2312  *recordXtime = ((xl_restore_point *) XLogRecGetData(record))->rp_time;
2313  return true;
2314  }
2315  if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_COMMIT ||
2316  xact_info == XLOG_XACT_COMMIT_PREPARED))
2317  {
2318  *recordXtime = ((xl_xact_commit *) XLogRecGetData(record))->xact_time;
2319  return true;
2320  }
2321  if (rmid == RM_XACT_ID && (xact_info == XLOG_XACT_ABORT ||
2322  xact_info == XLOG_XACT_ABORT_PREPARED))
2323  {
2324  *recordXtime = ((xl_xact_abort *) XLogRecGetData(record))->xact_time;
2325  return true;
2326  }
2327  return false;
2328 }
#define XLOG_RESTORE_POINT
Definition: pg_control.h:74
#define XLOG_XACT_COMMIT_PREPARED
Definition: xact.h:165
#define XLOG_XACT_COMMIT
Definition: xact.h:162
#define XLOG_XACT_OPMASK
Definition: xact.h:172
#define XLOG_XACT_ABORT
Definition: xact.h:164
#define XLOG_XACT_ABORT_PREPARED
Definition: xact.h:166
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:411
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:412

References XLOG_RESTORE_POINT, XLOG_XACT_ABORT, XLOG_XACT_ABORT_PREPARED, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_PREPARED, XLOG_XACT_OPMASK, XLogRecGetData, XLogRecGetInfo, XLogRecGetRmid, and XLR_INFO_MASK.

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

◆ GetRecoveryPauseState()

◆ getRecoveryStopReason()

static char * getRecoveryStopReason ( void  )
static

Definition at line 2759 of file xlogrecovery.c.

2760 {
2761  char reason[200];
2762 
2764  snprintf(reason, sizeof(reason),
2765  "%s transaction %u",
2766  recoveryStopAfter ? "after" : "before",
2767  recoveryStopXid);
2769  snprintf(reason, sizeof(reason),
2770  "%s %s\n",
2771  recoveryStopAfter ? "after" : "before",
2773  else if (recoveryTarget == RECOVERY_TARGET_LSN)
2774  snprintf(reason, sizeof(reason),
2775  "%s LSN %X/%X\n",
2776  recoveryStopAfter ? "after" : "before",
2779  snprintf(reason, sizeof(reason),
2780  "at restore point \"%s\"",
2783  snprintf(reason, sizeof(reason), "reached consistency");
2784  else
2785  snprintf(reason, sizeof(reason), "no recovery target specified");
2786 
2787  return pstrdup(reason);
2788 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1782
char * pstrdup(const char *in)
Definition: mcxt.c:1483
static XLogRecPtr recoveryStopLSN
Definition: xlogrecovery.c:381
static TimestampTz recoveryStopTime
Definition: xlogrecovery.c:380
static char recoveryStopName[MAXFNAMELEN]
Definition: xlogrecovery.c:382
static bool recoveryStopAfter
Definition: xlogrecovery.c:383
static TransactionId recoveryStopXid
Definition: xlogrecovery.c:379

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

Referenced by FinishWalRecovery().

◆ GetXLogReceiptTime()

void GetXLogReceiptTime ( TimestampTz rtime,
bool fromStream 
)

Definition at line 4513 of file xlogrecovery.c.

4514 {
4515  /*
4516  * This must be executed in the startup process, since we don't export the
4517  * relevant state to shared memory.
4518  */
4519  Assert(InRecovery);
4520 
4521  *rtime = XLogReceiptTime;
4522  *fromStream = (XLogReceiptSource == XLOG_FROM_STREAM);
4523 }
static XLogSource XLogReceiptSource
Definition: xlogrecovery.c:259
static TimestampTz XLogReceiptTime
Definition: xlogrecovery.c:258

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

Referenced by GetStandbyLimitTime().

◆ GetXLogReplayRecPtr()

◆ HotStandbyActive()

bool HotStandbyActive ( void  )

Definition at line 4373 of file xlogrecovery.c.

4374 {
4375  /*
4376  * We check shared state each time only until Hot Standby is active. We
4377  * can't de-activate Hot Standby, so there's no need to keep checking
4378  * after the shared variable has once been seen true.
4379  */
4381  return true;
4382  else
4383  {
4384  /* spinlock is essential on machines with weak memory ordering! */
4388 
4389  return LocalHotStandbyActive;
4390  }
4391 }

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

Referenced by XLogWalRcvSendHSFeedback().

◆ HotStandbyActiveInReplay()

static bool HotStandbyActiveInReplay ( void  )
static

Definition at line 4398 of file xlogrecovery.c.

4399 {
4401  return LocalHotStandbyActive;
4402 }
bool IsPostmasterEnvironment
Definition: globals.c:112
#define AmStartupProcess()
Definition: miscadmin.h:440

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

495 {
496  XLogPageReadPrivate *private;
497  struct stat st;
498  bool wasShutdown;
499  XLogRecord *record;
500  DBState dbstate_at_startup;
501  bool haveTblspcMap = false;
502  bool haveBackupLabel = false;
503  CheckPoint checkPoint;
504  bool backupFromStandby = false;
505 
506  dbstate_at_startup = ControlFile->state;
507 
508  /*
509  * Initialize on the assumption we want to recover to the latest timeline
510  * that's active according to pg_control.
511  */
515  else
517 
518  /*
519  * Check for signal files, and if so set up state for offline recovery
520  */
523 
525  {
527  ereport(LOG,
528  (errmsg("entering standby mode")));
530  ereport(LOG,
531  (errmsg("starting point-in-time recovery to XID %u",
534  ereport(LOG,
535  (errmsg("starting point-in-time recovery to %s",
538  ereport(LOG,
539  (errmsg("starting point-in-time recovery to \"%s\"",
542  ereport(LOG,
543  (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
546  ereport(LOG,
547  (errmsg("starting point-in-time recovery to earliest consistent point")));
548  else
549  ereport(LOG,
550  (errmsg("starting archive recovery")));
551  }
552 
553  /*
554  * Take ownership of the wakeup latch if we're going to sleep during
555  * recovery.
556  */
559 
560  private = palloc0(sizeof(XLogPageReadPrivate));
561  xlogreader =
563  XL_ROUTINE(.page_read = &XLogPageRead,
564  .segment_open = NULL,
565  .segment_close = wal_segment_close),
566  private);
567  if (!xlogreader)
568  ereport(ERROR,
569  (errcode(ERRCODE_OUT_OF_MEMORY),
570  errmsg("out of memory"),
571  errdetail("Failed while allocating a WAL reading processor.")));
573 
574  /*
575  * Set the WAL decode buffer size. This limits how far ahead we can read
576  * in the WAL.
577  */
579 
580  /* Create a WAL prefetcher. */
582 
583  /*
584  * Allocate two page buffers dedicated to WAL consistency checks. We do
585  * it this way, rather than just making static arrays, for two reasons:
586  * (1) no need to waste the storage in most instantiations of the backend;
587  * (2) a static char array isn't guaranteed to have any particular
588  * alignment, whereas palloc() will provide MAXALIGN'd storage.
589  */
590  replay_image_masked = (char *) palloc(BLCKSZ);
591  primary_image_masked = (char *) palloc(BLCKSZ);
592 
594  &backupFromStandby))
595  {
596  List *tablespaces = NIL;
597 
598  /*
599  * Archive recovery was requested, and thanks to the backup label
600  * file, we know how far we need to replay to reach consistency. Enter
601  * archive recovery directly.
602  */
603  InArchiveRecovery = true;
605  StandbyMode = true;
606 
607  /*
608  * When a backup_label file is present, we want to roll forward from
609  * the checkpoint it identifies, rather than using pg_control.
610  */
612  CheckPointTLI);
613  if (record != NULL)
614  {
615  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
616  wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
617  ereport(DEBUG1,
618  (errmsg_internal("checkpoint record is at %X/%X",
620  InRecovery = true; /* force recovery even if SHUTDOWNED */
621 
622  /*
623  * Make sure that REDO location exists. This may not be the case
624  * if there was a crash during an online backup, which left a
625  * backup_label around that references a WAL segment that's
626  * already been archived.
627  */
628  if (checkPoint.redo < CheckPointLoc)
629  {
631  if (!ReadRecord(xlogprefetcher, LOG, false,
632  checkPoint.ThisTimeLineID))
633  ereport(FATAL,
634  (errmsg("could not find redo location referenced by checkpoint record"),
635  errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
636  "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
637  "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
638  DataDir, DataDir, DataDir)));
639  }
640  }
641  else
642  {
643  ereport(FATAL,
644  (errmsg("could not locate required checkpoint record"),
645  errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
646  "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
647  "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
648  DataDir, DataDir, DataDir)));
649  wasShutdown = false; /* keep compiler quiet */
650  }
651 
652  /* Read the tablespace_map file if present and create symlinks. */
653  if (read_tablespace_map(&tablespaces))
654  {
655  ListCell *lc;
656 
657  foreach(lc, tablespaces)
658  {
659  tablespaceinfo *ti = lfirst(lc);
660  char *linkloc;
661 
662  linkloc = psprintf("pg_tblspc/%s", ti->oid);
663 
664  /*
665  * Remove the existing symlink if any and Create the symlink
666  * under PGDATA.
667  */
668  remove_tablespace_symlink(linkloc);
669 
670  if (symlink(ti->path, linkloc) < 0)
671  ereport(ERROR,
673  errmsg("could not create symbolic link \"%s\": %m",
674  linkloc)));
675 
676  pfree(ti->oid);
677  pfree(ti->path);
678  pfree(ti);
679  }
680 
681  /* tell the caller to delete it later */
682  haveTblspcMap = true;
683  }
684 
685  /* tell the caller to delete it later */
686  haveBackupLabel = true;
687  }
688  else
689  {
690  /*
691  * If tablespace_map file is present without backup_label file, there
692  * is no use of such file. There is no harm in retaining it, but it
693  * is better to get rid of the map file so that we don't have any
694  * redundant file in data directory and it will avoid any sort of
695  * confusion. It seems prudent though to just rename the file out of
696  * the way rather than delete it completely, also we ignore any error
697  * that occurs in rename operation as even if map file is present
698  * without backup_label file, it is harmless.
699  */
700  if (stat(TABLESPACE_MAP, &st) == 0)
701  {
702  unlink(TABLESPACE_MAP_OLD);
704  ereport(LOG,
705  (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
707  errdetail("File \"%s\" was renamed to \"%s\".",
709  else
710  ereport(LOG,
711  (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
713  errdetail("Could not rename file \"%s\" to \"%s\": %m.",
715  }
716 
717  /*
718  * It's possible that archive recovery was requested, but we don't
719  * know how far we need to replay the WAL before we reach consistency.
720  * This can happen for example if a base backup is taken from a
721  * running server using an atomic filesystem snapshot, without calling
722  * pg_backup_start/stop. Or if you just kill a running primary server
723  * and put it into archive recovery by creating a recovery signal
724  * file.
725  *
726  * Our strategy in that case is to perform crash recovery first,
727  * replaying all the WAL present in pg_wal, and only enter archive
728  * recovery after that.
729  *
730  * But usually we already know how far we need to replay the WAL (up
731  * to minRecoveryPoint, up to backupEndPoint, or until we see an
732  * end-of-backup record), and we can enter archive recovery directly.
733  */
739  {
740  InArchiveRecovery = true;
742  StandbyMode = true;
743  }
744 
745  /* Get the last valid checkpoint record. */
751  CheckPointTLI);
752  if (record != NULL)
753  {
754  ereport(DEBUG1,
755  (errmsg_internal("checkpoint record is at %X/%X",
757  }
758  else
759  {
760  /*
761  * We used to attempt to go back to a secondary checkpoint record
762  * here, but only when not in standby mode. We now just fail if we
763  * can't read the last checkpoint because this allows us to
764  * simplify processing around checkpoints.
765  */
766  ereport(PANIC,
767  (errmsg("could not locate a valid checkpoint record")));
768  }
769  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
770  wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
771  }
772 
773  /*
774  * If the location of the checkpoint record is not on the expected
775  * timeline in the history of the requested timeline, we cannot proceed:
776  * the backup is not part of the history of the requested timeline.
777  */
778  Assert(expectedTLEs); /* was initialized by reading checkpoint
779  * record */
782  {
783  XLogRecPtr switchpoint;
784 
785  /*
786  * tliSwitchPoint will throw an error if the checkpoint's timeline is
787  * not in expectedTLEs at all.
788  */
790  ereport(FATAL,
791  (errmsg("requested timeline %u is not a child of this server's history",
793  errdetail("Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.",
796  LSN_FORMAT_ARGS(switchpoint))));
797  }
798 
799  /*
800  * The min recovery point should be part of the requested timeline's
801  * history, too.
802  */
806  ereport(FATAL,
807  (errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
811 
812  ereport(DEBUG1,
813  (errmsg_internal("redo record is at %X/%X; shutdown %s",
814  LSN_FORMAT_ARGS(checkPoint.redo),
815  wasShutdown ? "true" : "false")));
816  ereport(DEBUG1,
817  (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
818  U64FromFullTransactionId(checkPoint.nextXid),
819  checkPoint.nextOid)));
820  ereport(DEBUG1,
821  (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
822  checkPoint.nextMulti, checkPoint.nextMultiOffset)));
823  ereport(DEBUG1,
824  (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
825  checkPoint.oldestXid, checkPoint.oldestXidDB)));
826  ereport(DEBUG1,
827  (errmsg_internal("oldest MultiXactId: %u, in database %u",
828  checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
829  ereport(DEBUG1,
830  (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
831  checkPoint.oldestCommitTsXid,
832  checkPoint.newestCommitTsXid)));
834  ereport(PANIC,
835  (errmsg("invalid next transaction ID")));
836 
837  /* sanity check */
838  if (checkPoint.redo > CheckPointLoc)
839  ereport(PANIC,
840  (errmsg("invalid redo in checkpoint record")));
841 
842  /*
843  * Check whether we need to force recovery from WAL. If it appears to
844  * have been a clean shutdown and we did not have a recovery signal file,
845  * then assume no recovery needed.
846  */
847  if (checkPoint.redo < CheckPointLoc)
848  {
849  if (wasShutdown)
850  ereport(PANIC,
851  (errmsg("invalid redo record in shutdown checkpoint")));
852  InRecovery = true;
853  }
854  else if (ControlFile->state != DB_SHUTDOWNED)
855  InRecovery = true;
856  else if (ArchiveRecoveryRequested)
857  {
858  /* force recovery due to presence of recovery signal file */
859  InRecovery = true;
860  }
861 
862  /*
863  * If recovery is needed, update our in-memory copy of pg_control to show
864  * that we are recovering and to show the selected checkpoint as the place
865  * we are starting from. We also mark pg_control with any minimum recovery
866  * stop point obtained from a backup history file.
867  *
868  * We don't write the changes to disk yet, though. Only do that after
869  * initializing various subsystems.
870  */
871  if (InRecovery)
872  {
873  if (InArchiveRecovery)
874  {
876  }
877  else
878  {
879  ereport(LOG,
880  (errmsg("database system was not properly shut down; "
881  "automatic recovery in progress")));
883  ereport(LOG,
884  (errmsg("crash recovery starts in timeline %u "
885  "and has target timeline %u",
889  }
891  ControlFile->checkPointCopy = checkPoint;
892  if (InArchiveRecovery)
893  {
894  /* initialize minRecoveryPoint if not set yet */
895  if (ControlFile->minRecoveryPoint < checkPoint.redo)
896  {
897  ControlFile->minRecoveryPoint = checkPoint.redo;
899  }
900  }
901 
902  /*
903  * Set backupStartPoint if we're starting recovery from a base backup.
904  *
905  * Also set backupEndPoint and use minRecoveryPoint as the backup end
906  * location if we're starting recovery from a base backup which was
907  * taken from a standby. In this case, the database system status in
908  * pg_control must indicate that the database was already in recovery.
909  * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
910  * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
911  * before reaching this point; e.g. because restore_command or
912  * primary_conninfo were faulty.
913  *
914  * Any other state indicates that the backup somehow became corrupted
915  * and we can't sensibly continue with recovery.
916  */
917  if (haveBackupLabel)
918  {
919  ControlFile->backupStartPoint = checkPoint.redo;
921 
922  if (backupFromStandby)
923  {
924  if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
925  dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
926  ereport(FATAL,
927  (errmsg("backup_label contains data inconsistent with control file"),
928  errhint("This means that the backup is corrupted and you will "
929  "have to use another backup for recovery.")));
931  }
932  }
933  }
934 
935  /* remember these, so that we know when we have reached consistency */
939  if (InArchiveRecovery)
940  {
943  }
944  else
945  {
948  }
949 
950  /*
951  * Start recovery assuming that the final record isn't lost.
952  */
955 
956  *wasShutdown_ptr = wasShutdown;
957  *haveBackupLabel_ptr = haveBackupLabel;
958  *haveTblspcMap_ptr = haveTblspcMap;
959 }
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
Definition: timeline.c:544
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition: timeline.c:572
void remove_tablespace_symlink(const char *linkloc)
Definition: tablespace.c:889
#define UINT64_FORMAT
Definition: c.h:485
int errmsg_internal(const char *fmt,...)
Definition: elog.c:993
int errcode_for_file_access(void)
Definition: elog.c:718
#define FATAL
Definition: elog.h:37
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:688
char * DataDir
Definition: globals.c:66
void OwnLatch(Latch *latch)
Definition: latch.c:422
void pfree(void *pointer)
Definition: mcxt.c:1306
void * palloc0(Size size)
Definition: mcxt.c:1230
DBState
Definition: pg_control.h:88
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:94
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:91
@ DB_SHUTDOWNED
Definition: pg_control.h:90
@ DB_IN_CRASH_RECOVERY
Definition: pg_control.h:93
#define lfirst(lc)
Definition: pg_list.h:170
#define NIL
Definition: pg_list.h:66
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Oid oldestMultiDB
Definition: pg_control.h:50
MultiXactId oldestMulti
Definition: pg_control.h:49
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId newestCommitTsXid
Definition: pg_control.h:54
TransactionId oldestXid
Definition: pg_control.h:47
Oid nextOid
Definition: pg_control.h:44
MultiXactId nextMulti
Definition: pg_control.h:45
FullTransactionId nextXid
Definition: pg_control.h:43
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:48
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
bool backupEndRequired
Definition: pg_control.h:170
CheckPoint checkPointCopy
Definition: pg_control.h:133
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
XLogRecPtr checkPoint
Definition: pg_control.h:131
uint64 system_identifier
Definition: pg_control.h:108
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
Definition: pg_list.h:52
uint64 system_identifier
Definition: xlogreader.h:191
#define U64FromFullTransactionId(x)
Definition: transam.h:49
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define symlink(oldpath, newpath)
Definition: win32_port.h:237
int wal_decode_buffer_size
Definition: xlog.c:139
static ControlFileData * ControlFile
Definition: xlog.c:570
#define TABLESPACE_MAP_OLD
Definition: xlog.h:294
#define TABLESPACE_MAP
Definition: xlog.h:293
#define BACKUP_LABEL_FILE
Definition: xlog.h:290
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition: xlogreader.c:92
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:108
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static void validateRecoveryParameters(void)
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
static TimeLineID RedoStartTLI
Definition: xlogrecovery.c:170
static void readRecoverySignalFile(void)
Definition: xlogrecovery.c:969
static bool read_tablespace_map(List **tablespaces)
static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
static char * primary_image_masked
Definition: xlogrecovery.c:298
static char * replay_image_masked
Definition: xlogrecovery.c:297
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:122
static XLogRecPtr RedoStartLSN
Definition: xlogrecovery.c:169
TimestampTz recoveryTargetTime
Definition: xlogrecovery.c:90
static bool StandbyModeRequested
Definition: xlogrecovery.c:146
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:859

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(), ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), errmsg_internal(), ERROR, expectedTLEs, FATAL, InArchiveRecovery, InRecovery, InvalidXLogRecPtr, lfirst, LOG, LSN_FORMAT_ARGS, minRecoveryPoint, ControlFileData::minRecoveryPoint, minRecoveryPointTLI, ControlFileData::minRecoveryPointTLI, missingContrecPtr, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, NIL, tablespaceinfo::oid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, OwnLatch(), palloc(), palloc0(), PANIC, tablespaceinfo::path, pfree(), 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, StandbyMode, 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, XLogRecPtrIsInvalid, and XLR_INFO_MASK.

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1566 of file xlogrecovery.c.

1567 {
1568  XLogRecord *record;
1569  bool reachedRecoveryTarget = false;
1570  TimeLineID replayTLI;
1571 
1572  /*
1573  * Initialize shared variables for tracking progress of WAL replay, as if
1574  * we had just replayed the record before the REDO location (or the
1575  * checkpoint record itself, if it's a shutdown checkpoint).
1576  */
1579  {
1583  }
1584  else
1585  {
1589  }
1596 
1597  /* Also ensure XLogReceiptTime has a sane value */
1599 
1600  /*
1601  * Let postmaster know we've started redo now, so that it can launch the
1602  * archiver if necessary.
1603  */
1604  if (IsUnderPostmaster)
1606 
1607  /*
1608  * Allow read-only connections immediately if we're consistent already.
1609  */
1611 
1612  /*
1613  * Find the first record that logically follows the checkpoint --- it
1614  * might physically precede it, though.
1615  */
1617  {
1618  /* back up to find the record */
1619  replayTLI = RedoStartTLI;
1621  record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1622  }
1623  else
1624  {
1625  /* just have to read next record after CheckPoint */
1627  replayTLI = CheckPointTLI;
1628  record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1629  }
1630 
1631  if (record != NULL)
1632  {
1633  TimestampTz xtime;
1634  PGRUsage ru0;
1635 
1636  pg_rusage_init(&ru0);
1637 
1638  InRedo = true;
1639 
1640  RmgrStartup();
1641 
1642  ereport(LOG,
1643  (errmsg("redo starts at %X/%X",
1645 
1646  /* Prepare to report progress of the redo phase. */
1647  if (!StandbyMode)
1649 
1650  /*
1651  * main redo apply loop
1652  */
1653  do
1654  {
1655  if (!StandbyMode)
1656  ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
1658 
1659 #ifdef WAL_DEBUG
1660  if (XLOG_DEBUG ||
1661  (record->xl_rmid == RM_XACT_ID && trace_recovery_messages <= DEBUG2) ||
1662  (record->xl_rmid != RM_XACT_ID && trace_recovery_messages <= DEBUG3))
1663  {
1665 
1666  initStringInfo(&buf);
1667  appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
1670  xlog_outrec(&buf, xlogreader);
1671  appendStringInfoString(&buf, " - ");
1673  elog(LOG, "%s", buf.data);
1674  pfree(buf.data);
1675  }
1676 #endif
1677 
1678  /* Handle interrupt signals of startup process */
1680 
1681  /*
1682  * Pause WAL replay, if requested by a hot-standby session via
1683  * SetRecoveryPause().
1684  *
1685  * Note that we intentionally don't take the info_lck spinlock
1686  * here. We might therefore read a slightly stale value of the
1687  * recoveryPause flag, but it can't be very stale (no worse than
1688  * the last spinlock we did acquire). Since a pause request is a
1689  * pretty asynchronous thing anyway, possibly responding to it one
1690  * WAL record later than we otherwise would is a minor issue, so
1691  * it doesn't seem worth adding another spinlock cycle to prevent
1692  * that.
1693  */
1694  if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1696  recoveryPausesHere(false);
1697 
1698  /*
1699  * Have we reached our recovery target?
1700  */
1702  {
1703  reachedRecoveryTarget = true;
1704  break;
1705  }
1706 
1707  /*
1708  * If we've been asked to lag the primary, wait on latch until
1709  * enough time has passed.
1710  */
1712  {
1713  /*
1714  * We test for paused recovery again here. If user sets
1715  * delayed apply, it may be because they expect to pause
1716  * recovery in case of problems, so we must test again here
1717  * otherwise pausing during the delay-wait wouldn't work.
1718  */
1719  if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1721  recoveryPausesHere(false);
1722  }
1723 
1724  /*
1725  * Apply the record
1726  */
1727  ApplyWalRecord(xlogreader, record, &replayTLI);
1728 
1729  /* Exit loop if we reached inclusive recovery target */
1731  {
1732  reachedRecoveryTarget = true;
1733  break;
1734  }
1735 
1736  /* Else, try to fetch the next WAL record */
1737  record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1738  } while (record != NULL);
1739 
1740  /*
1741  * end of main redo apply loop
1742  */
1743 
1744  if (reachedRecoveryTarget)
1745  {
1746  if (!reachedConsistency)
1747  ereport(FATAL,
1748  (errmsg("requested recovery stop point is before consistent recovery point")));
1749 
1750  /*
1751  * This is the last point where we can restart recovery with a new
1752  * recovery target, if we shutdown and begin again. After this,
1753  * Resource Managers may choose to do permanent corrective actions
1754  * at end of recovery.
1755  */
1756  switch (recoveryTargetAction)
1757  {
1759 
1760  /*
1761  * exit with special return code to request shutdown of
1762  * postmaster. Log messages issued from postmaster.
1763  */
1764  proc_exit(3);
1765 
1767  SetRecoveryPause(true);
1768  recoveryPausesHere(true);
1769 
1770  /* drop into promote */
1771 
1773  break;
1774  }
1775  }
1776 
1777  RmgrCleanup();
1778 
1779  ereport(LOG,
1780  (errmsg("redo done at %X/%X system usage: %s",
1782  pg_rusage_show(&ru0))));
1783  xtime = GetLatestXTime();
1784  if (xtime)
1785  ereport(LOG,
1786  (errmsg("last completed transaction was at log time %s",
1787  timestamptz_to_str(xtime))));
1788 
1789  InRedo = false;
1790  }
1791  else
1792  {
1793  /* there are no WAL records following the checkpoint */
1794  ereport(LOG,
1795  (errmsg("redo is not required")));
1796  }
1797 
1798  /*
1799  * This check is intentionally after the above log messages that indicate
1800  * how far recovery went.
1801  */
1804  !reachedRecoveryTarget)
1805  ereport(FATAL,
1806  (errmsg("recovery ended before configured recovery target was reached")));
1807 }
void HandleStartupProcInterrupts(void)
Definition: startup.c:168
void begin_startup_progress_phase(void)
Definition: startup.c:321
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1573
#define DEBUG3
Definition: elog.h:24
#define DEBUG2
Definition: elog.h:25
int trace_recovery_messages
Definition: guc_tables.c:495
void proc_exit(int code)
Definition: ipc.c:104
const char * pg_rusage_show(const PGRUsage *ru0)
Definition: pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition: pg_rusage.c:27
static char * buf
Definition: pg_test_fsync.c:67
@ PMSIGNAL_RECOVERY_STARTED
Definition: pmsignal.h:35
void RmgrStartup(void)
Definition: rmgr.c:49
void RmgrCleanup(void)
Definition: rmgr.c:65
#define ereport_startup_progress(msg,...)
Definition: startup.h:18
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
static bool recoveryStopsBefore(XLogReaderState *record)
int recoveryTargetAction
Definition: xlogrecovery.c:87
static bool recoveryApplyDelay(XLogReaderState *record)
static bool recoveryStopsAfter(XLogReaderState *record)
void SetRecoveryPause(bool recoveryPause)
void xlog_outdesc(StringInfo buf, XLogReaderState *record)
static bool InRedo
Definition: xlogrecovery.c:203
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
static void recoveryPausesHere(bool endOfRecovery)
TimestampTz GetLatestXTime(void)
@ RECOVERY_NOT_PAUSED
Definition: xlogrecovery.h:46

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

Referenced by StartupXLOG().

◆ pg_attribute_noreturn()

static void pg_attribute_noreturn ( )
static

Definition at line 4639 of file xlogrecovery.c.

4641 {
4642  ereport(ERROR,
4643  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4644  errmsg("multiple recovery targets specified"),
4645  errdetail("At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set.")));
4646 }

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

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4265 of file xlogrecovery.c.

4266 {
4267  /*
4268  * We check shared state each time only until a standby promotion is
4269  * triggered. We can't trigger a promotion again, so there's no need to
4270  * keep checking after the shared variable has once been seen true.
4271  */
4273  return true;
4274 
4278 
4279  return LocalPromoteIsTriggered;
4280 }

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

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

◆ read_backup_label()

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

Definition at line 1150 of file xlogrecovery.c.

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

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

Referenced by InitWalRecovery().

◆ read_tablespace_map()

static bool read_tablespace_map ( List **  tablespaces)
static

Definition at line 1290 of file xlogrecovery.c.

1291 {
1292  tablespaceinfo *ti;
1293  FILE *lfp;
1294  char str[MAXPGPATH];
1295  int ch,
1296  i,
1297  n;
1298  bool was_backslash;
1299 
1300  /*
1301  * See if tablespace_map file is present
1302  */
1303  lfp = AllocateFile(TABLESPACE_MAP, "r");
1304  if (!lfp)
1305  {
1306  if (errno != ENOENT)
1307  ereport(FATAL,
1309  errmsg("could not read file \"%s\": %m",
1310  TABLESPACE_MAP)));
1311  return false; /* it's not there, all is fine */
1312  }
1313 
1314  /*
1315  * Read and parse the link name and path lines from tablespace_map file
1316  * (this code is pretty crude, but we are not expecting any variability in
1317  * the file format). De-escape any backslashes that were inserted.
1318  */
1319  i = 0;
1320  was_backslash = false;
1321  while ((ch = fgetc(lfp)) != EOF)
1322  {
1323  if (!was_backslash && (ch == '\n' || ch == '\r'))
1324  {
1325  if (i == 0)
1326  continue; /* \r immediately followed by \n */
1327 
1328  /*
1329  * The de-escaped line should contain an OID followed by exactly
1330  * one space followed by a path. The path might start with
1331  * spaces, so don't be too liberal about parsing.
1332  */
1333  str[i] = '\0';
1334  n = 0;
1335  while (str[n] && str[n] != ' ')
1336  n++;
1337  if (n < 1 || n >= i - 1)
1338  ereport(FATAL,
1339  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1340  errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1341  str[n++] = '\0';
1342 
1343  ti = palloc0(sizeof(tablespaceinfo));
1344  ti->oid = pstrdup(str);
1345  ti->path = pstrdup(str + n);
1346  *tablespaces = lappend(*tablespaces, ti);
1347 
1348  i = 0;
1349  continue;
1350  }
1351  else if (!was_backslash && ch == '\\')
1352  was_backslash = true;
1353  else
1354  {
1355  if (i < sizeof(str) - 1)
1356  str[i++] = ch;
1357  was_backslash = false;
1358  }
1359  }
1360 
1361  if (i != 0 || was_backslash) /* last line not terminated? */
1362  ereport(FATAL,
1363  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1364  errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
1365 
1366  if (ferror(lfp) || FreeFile(lfp))
1367  ereport(FATAL,
1369  errmsg("could not read file \"%s\": %m",
1370  TABLESPACE_MAP)));
1371 
1372  return true;
1373 }
int i
Definition: isn.c:73
List * lappend(List *list, void *datum)
Definition: list.c:338

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

Referenced by InitWalRecovery().

◆ ReadCheckpointRecord()

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

Definition at line 3920 of file xlogrecovery.c.

3922 {
3923  XLogRecord *record;
3924  uint8 info;
3925 
3926  Assert(xlogreader != NULL);
3927 
3928  if (!XRecOffIsValid(RecPtr))
3929  {
3930  ereport(LOG,
3931  (errmsg("invalid checkpoint location")));
3932  return NULL;
3933  }
3934 
3936  record = ReadRecord(xlogprefetcher, LOG, true, replayTLI);
3937 
3938  if (record == NULL)
3939  {
3940  ereport(LOG,
3941  (errmsg("invalid checkpoint record")));
3942  return NULL;
3943  }
3944  if (record->xl_rmid != RM_XLOG_ID)
3945  {
3946  ereport(LOG,
3947  (errmsg("invalid resource manager ID in checkpoint record")));
3948  return NULL;
3949  }
3950  info = record->xl_info & ~XLR_INFO_MASK;
3951  if (info != XLOG_CHECKPOINT_SHUTDOWN &&
3952  info != XLOG_CHECKPOINT_ONLINE)
3953  {
3954  ereport(LOG,
3955  (errmsg("invalid xl_info in checkpoint record")));
3956  return NULL;
3957  }
3959  {
3960  ereport(LOG,
3961  (errmsg("invalid length of checkpoint record")));
3962  return NULL;
3963  }
3964  return record;
3965 }
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:68
uint32 xl_tot_len
Definition: xlogrecord.h:43
#define XRecOffIsValid(xlrp)
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:206
#define SizeOfXLogRecord
Definition: xlogrecord.h:55

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

Referenced by InitWalRecovery().

◆ ReadRecord()

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

Definition at line 3004 of file xlogrecovery.c.

3006 {
3007  XLogRecord *record;
3010 
3011  /* Pass through parameters to XLogPageRead */
3012  private->fetching_ckpt = fetching_ckpt;
3013  private->emode = emode;
3014  private->randAccess = (xlogreader->ReadRecPtr == InvalidXLogRecPtr);
3015  private->replayTLI = replayTLI;
3016 
3017  /* This is the first attempt to read this page. */
3018  lastSourceFailed = false;
3019 
3020  for (;;)
3021  {
3022  char *errormsg;
3023 
3024  record = XLogPrefetcherReadRecord(xlogprefetcher, &errormsg);
3025  if (record == NULL)
3026  {
3027  /*
3028  * When we find that WAL ends in an incomplete record, keep track
3029  * of that record. After recovery is done, we'll write a record to
3030  * indicate to downstream WAL readers that that portion is to be
3031  * ignored.
3032  *
3033  * However, when ArchiveRecoveryRequested = true, we're going to
3034  * switch to a new timeline at the end of recovery. We will only
3035  * copy WAL over to the new timeline up to the end of the last
3036  * complete record, so if we did this, we would later create an
3037  * overwrite contrecord in the wrong place, breaking everything.
3038  */
3039  if (!ArchiveRecoveryRequested &&
3041  {
3044  }
3045 
3046  if (readFile >= 0)
3047  {
3048  close(readFile);
3049  readFile = -1;
3050  }
3051 
3052  /*
3053  * We only end up here without a message when XLogPageRead()
3054  * failed - in that case we already logged something. In
3055  * StandbyMode that only happens if we have been triggered, so we
3056  * shouldn't loop anymore in that case.
3057  */
3058  if (errormsg)
3060  (errmsg_internal("%s", errormsg) /* already translated */ ));
3061  }
3062 
3063  /*
3064  * Check page TLI is one of the expected values.
3065  */
3067  {
3068  char fname[MAXFNAMELEN];
3069  XLogSegNo segno;
3070  int32 offset;
3071 
3075  XLogFileName(fname, xlogreader->seg.ws_tli, segno,
3078  (errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u",
3080  fname,
3082  offset)));
3083  record = NULL;
3084  }
3085 
3086  if (record)
3087  {
3088  /* Great, got a record */
3089  return record;
3090  }
3091  else
3092  {
3093  /* No valid record available from this source */
3094  lastSourceFailed = true;
3095 
3096  /*
3097  * If archive recovery was requested, but we were still doing
3098  * crash recovery, switch to archive recovery and retry using the
3099  * offline archive. We have now replayed all the valid WAL in
3100  * pg_wal, so we are presumably now consistent.
3101  *
3102  * We require that there's at least some valid WAL present in
3103  * pg_wal, however (!fetching_ckpt). We could recover using the
3104  * WAL from the archive, even if pg_wal is completely empty, but
3105  * we'd have no idea how far we'd have to replay to reach
3106  * consistency. So err on the safe side and give up.
3107  */
3109  !fetching_ckpt)
3110  {
3111  ereport(DEBUG1,
3112  (errmsg_internal("reached end of WAL in pg_wal, entering archive recovery")));
3113  InArchiveRecovery = true;
3115  StandbyMode = true;
3116 
3119  minRecoveryPointTLI = replayTLI;
3120 
3122 
3123  /*
3124  * Before we retry, reset lastSourceFailed and currentSource
3125  * so that we will check the archive next.
3126  */
3127  lastSourceFailed = false;
3129 
3130  continue;
3131  }
3132 
3133  /* In standby mode, loop back to retry. Otherwise, give up. */
3135  continue;
3136  else
3137  return NULL;
3138  }
3139  }
3140 }
signed int int32
Definition: c.h:430
XLogRecPtr missingContrecPtr
Definition: xlogreader.h:215
XLogRecPtr abortedRecPtr
Definition: xlogreader.h:214
TimeLineID latestPageTLI
Definition: xlogreader.h:280
XLogRecPtr latestPagePtr
Definition: xlogreader.h:279
void * private_data
Definition: xlogreader.h:196
void SwitchIntoArchiveRecovery(XLogRecPtr EndRecPtr, TimeLineID replayTLI)
Definition: xlog.c:5787
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint64 XLogSegNo
Definition: xlogdefs.h:48
XLogRecord * XLogPrefetcherReadRecord(XLogPrefetcher *prefetcher, char **errmsg)
XLogReaderState * XLogPrefetcherGetReader(XLogPrefetcher *prefetcher)
static bool CheckForStandbyTrigger(void)
static bool lastSourceFailed
Definition: xlogrecovery.c:247
static XLogSource currentSource
Definition: xlogrecovery.c:246
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)

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

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

◆ readRecoverySignalFile()

static void readRecoverySignalFile ( void  )
static

Definition at line 969 of file xlogrecovery.c.

970 {
971  struct stat stat_buf;
972 
974  return;
975 
976  /*
977  * Check for old recovery API file: recovery.conf
978  */
979  if (stat(RECOVERY_COMMAND_FILE, &stat_buf) == 0)
980  ereport(FATAL,
982  errmsg("using recovery command file \"%s\" is not supported",
984 
985  /*
986  * Remove unused .done file, if present. Ignore if absent.
987  */
988  unlink(RECOVERY_COMMAND_DONE);
989 
990  /*
991  * Check for recovery signal files and if found, fsync them since they
992  * represent server state information. We don't sweat too much about the
993  * possibility of fsync failure, however.
994  *
995  * If present, standby signal file takes precedence. If neither is present
996  * then we won't enter archive recovery.
997  */
998  if (stat(STANDBY_SIGNAL_FILE, &stat_buf) == 0)
999  {
1000  int fd;
1001 
1003  S_IRUSR | S_IWUSR);
1004  if (fd >= 0)
1005  {
1006  (void) pg_fsync(fd);
1007  close(fd);
1008  }
1010  }
1011  else if (stat(RECOVERY_SIGNAL_FILE, &stat_buf) == 0)
1012  {
1013  int fd;
1014 
1016  S_IRUSR | S_IWUSR);
1017  if (fd >= 0)
1018  {
1019  (void) pg_fsync(fd);
1020  close(fd);
1021  }
1023  }
1024 
1025  StandbyModeRequested = false;
1026  ArchiveRecoveryRequested = false;
1028  {
1029  StandbyModeRequested = true;
1030  ArchiveRecoveryRequested = true;
1031  }
1032  else if (recovery_signal_file_found)
1033  {
1034  StandbyModeRequested = false;
1035  ArchiveRecoveryRequested = true;
1036  }
1037  else
1038  return;
1039 
1040  /*
1041  * We don't support standby mode in standalone backends; that requires
1042  * other processes such as the WAL receiver to be alive.
1043  */
1045  ereport(FATAL,
1046  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1047  errmsg("standby mode is not supported by single-user servers")));
1048 }
#define PG_BINARY
Definition: c.h:1209
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1015
int pg_fsync(int fd)
Definition: fd.c:356
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:402
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define S_IRUSR
Definition: win32_port.h:291
#define S_IWUSR
Definition: win32_port.h:294
#define STANDBY_SIGNAL_FILE
Definition: xlog.h:289
#define RECOVERY_SIGNAL_FILE
Definition: xlog.h:288
#define RECOVERY_COMMAND_FILE
Definition: xlogrecovery.c:68
#define RECOVERY_COMMAND_DONE
Definition: xlogrecovery.c:69

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

Referenced by InitWalRecovery().

◆ recoveryApplyDelay()

static bool recoveryApplyDelay ( XLogReaderState record)
static

Definition at line 2855 of file xlogrecovery.c.

2856 {
2857  uint8 xact_info;
2858  TimestampTz xtime;
2859  TimestampTz delayUntil;
2860  long msecs;
2861 
2862  /* nothing to do if no delay configured */
2863  if (recovery_min_apply_delay <= 0)
2864  return false;
2865 
2866  /* no delay is applied on a database not yet consistent */
2867  if (!reachedConsistency)
2868  return false;
2869 
2870  /* nothing to do if crash recovery is requested */
2872  return false;
2873 
2874  /*
2875  * Is it a COMMIT record?
2876  *
2877  * We deliberately choose not to delay aborts since they have no effect on
2878  * MVCC. We already allow replay of records that don't have a timestamp,
2879  * so there is already opportunity for issues caused by early conflicts on
2880  * standbys.
2881  */
2882  if (XLogRecGetRmid(record) != RM_XACT_ID)
2883  return false;
2884 
2885  xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
2886 
2887  if (xact_info != XLOG_XACT_COMMIT &&
2888  xact_info != XLOG_XACT_COMMIT_PREPARED)
2889  return false;
2890 
2891  if (!getRecordTimestamp(record, &xtime))
2892  return false;
2893 
2895 
2896  /*
2897  * Exit without arming the latch if it's already past time to apply this
2898  * record
2899  */
2901  if (msecs <= 0)
2902  return false;
2903 
2904  while (true)
2905  {
2907 
2908  /* This might change recovery_min_apply_delay. */
2910 
2911  if (CheckForStandbyTrigger())
2912  break;
2913 
2914  /*
2915  * Recalculate delayUntil as recovery_min_apply_delay could have
2916  * changed while waiting in this loop.
2917  */
2919 
2920  /*
2921  * Wait for difference between GetCurrentTimestamp() and delayUntil.
2922  */
2924  delayUntil);
2925 
2926  if (msecs <= 0)
2927  break;
2928 
2929  elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs);
2930 
2933  msecs,
2935  }
2936  return true;
2937 }
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition: timestamp.c:1701
void ResetLatch(Latch *latch)
Definition: latch.c:683
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:476
#define WL_TIMEOUT
Definition: latch.h:128
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
#define WL_LATCH_SET
Definition: latch.h:125
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:84
@ WAIT_EVENT_RECOVERY_APPLY_DELAY
Definition: wait_event.h:145
static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime)
int recovery_min_apply_delay
Definition: xlogrecovery.c:93

References ArchiveRecoveryRequested, CheckForStandbyTrigger(), DEBUG2, elog(), GetCurrentTimestamp(), getRecordTimestamp(), HandleStartupProcInterrupts(), reachedConsistency, recovery_min_apply_delay, XLogRecoveryCtlData::recoveryWakeupLatch, ResetLatch(), TimestampDifferenceMilliseconds(), TimestampTzPlusMilliseconds, WAIT_EVENT_RECOVERY_APPLY_DELAY, 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 2798 of file xlogrecovery.c.

2799 {
2800  /* Don't pause unless users can connect! */
2801  if (!LocalHotStandbyActive)
2802  return;
2803 
2804  /* Don't pause after standby promotion has been triggered */
2806  return;
2807 
2808  if (endOfRecovery)
2809  ereport(LOG,
2810  (errmsg("pausing at the end of recovery"),
2811  errhint("Execute pg_wal_replay_resume() to promote.")));
2812  else
2813  ereport(LOG,
2814  (errmsg("recovery has paused"),
2815  errhint("Execute pg_wal_replay_resume() to continue.")));
2816 
2817  /* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */
2819  {
2821  if (CheckForStandbyTrigger())
2822  return;
2823 
2824  /*
2825  * If recovery pause is requested then set it paused. While we are in
2826  * the loop, user might resume and pause again so set this every time.
2827  */
2829 
2830  /*
2831  * We wait on a condition variable that will wake us as soon as the
2832  * pause ends, but we use a timeout so we can check the above exit
2833  * condition periodically too.
2834  */
2837  }
2839 }
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableCancelSleep(void)
ConditionVariable recoveryNotPausedCV
Definition: xlogrecovery.c:359
@ WAIT_EVENT_RECOVERY_PAUSE
Definition: wait_event.h:123
static void ConfirmRecoveryPaused(void)
RecoveryPauseState GetRecoveryPauseState(void)

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

Referenced by PerformWalRecovery(), and WaitForWALToBecomeAvailable().

◆ RecoveryRequiresIntParameter()

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

Definition at line 4530 of file xlogrecovery.c.

4531 {
4532  if (currValue < minValue)
4533  {
4535  {
4536  bool warned_for_promote = false;
4537 
4538  ereport(WARNING,
4539  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4540  errmsg("hot standby is not possible because of insufficient parameter settings"),
4541  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4542  param_name,
4543  currValue,
4544  minValue)));
4545 
4546  SetRecoveryPause(true);
4547 
4548  ereport(LOG,
4549  (errmsg("recovery has paused"),
4550  errdetail("If recovery is unpaused, the server will shut down."),
4551  errhint("You can then restart the server after making the necessary configuration changes.")));
4552 
4554  {
4556 
4557  if (CheckForStandbyTrigger())
4558  {
4559  if (!warned_for_promote)
4560  ereport(WARNING,
4561  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4562  errmsg("promotion is not possible because of insufficient parameter settings"),
4563 
4564  /*
4565  * Repeat the detail from above so it's easy to find
4566  * in the log.
4567  */
4568  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4569  param_name,
4570  currValue,
4571  minValue),
4572  errhint("Restart the server after making the necessary configuration changes.")));
4573  warned_for_promote = true;
4574  }
4575 
4576  /*
4577  * If recovery pause is requested then set it paused. While
4578  * we are in the loop, user might resume and pause again so
4579  * set this every time.
4580  */
4582 
4583  /*
4584  * We wait on a condition variable that will wake us as soon
4585  * as the pause ends, but we use a timeout so we can check the
4586  * above conditions periodically too.
4587  */
4590  }
4592  }
4593 
4594  ereport(FATAL,
4595  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4596  errmsg("recovery aborted because of insufficient parameter settings"),
4597  /* Repeat the detail from above so it's easy to find in the log. */
4598  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4599  param_name,
4600  currValue,
4601  minValue),
4602  errhint("You can restart the server after making the necessary configuration changes.")));
4603  }
4604 }
static bool HotStandbyActiveInReplay(void)

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

Referenced by CheckRequiredParameterValues().

◆ recoveryStopsAfter()

static bool recoveryStopsAfter ( XLogReaderState record)
static

Definition at line 2599 of file xlogrecovery.c.

2600 {
2601  uint8 info;
2602  uint8 xact_info;
2603  uint8 rmid;
2604  TimestampTz recordXtime;
2605 
2606  /*
2607  * Ignore recovery target settings when not in archive recovery (meaning
2608  * we are in crash recovery).
2609  */
2611  return false;
2612 
2613  info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2614  rmid = XLogRecGetRmid(record);
2615 
2616  /*
2617  * There can be many restore points that share the same name; we stop at
2618  * the first one.
2619  */
2621  rmid == RM_XLOG_ID && info == XLOG_RESTORE_POINT)
2622  {
2623  xl_restore_point *recordRestorePointData;
2624 
2625  recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
2626 
2627  if (strcmp(recordRestorePointData->rp_name, recoveryTargetName) == 0)
2628  {
2629  recoveryStopAfter = true;
2632  (void) getRecordTimestamp(record, &recoveryStopTime);
2633  strlcpy(recoveryStopName, recordRestorePointData->rp_name, MAXFNAMELEN);
2634 
2635  ereport(LOG,
2636  (errmsg("recovery stopping at restore point \"%s\", time %s",
2639  return true;
2640  }
2641  }
2642 
2643  /* Check if the target LSN has been reached */
2646  record->ReadRecPtr >= recoveryTargetLSN)
2647  {
2648  recoveryStopAfter = true;
2650  recoveryStopLSN = record->ReadRecPtr;
2651  recoveryStopTime = 0;
2652  recoveryStopName[0] = '\0';
2653  ereport(LOG,
2654  (errmsg("recovery stopping after WAL location (LSN) \"%X/%X\"",
2656  return true;
2657  }
2658 
2659  if (rmid != RM_XACT_ID)
2660  return false;
2661 
2662  xact_info = info & XLOG_XACT_OPMASK;
2663 
2664  if (xact_info == XLOG_XACT_COMMIT ||
2665  xact_info == XLOG_XACT_COMMIT_PREPARED ||
2666  xact_info == XLOG_XACT_ABORT ||
2667  xact_info == XLOG_XACT_ABORT_PREPARED)
2668  {
2669  TransactionId recordXid;
2670 
2671  /* Update the last applied transaction timestamp */
2672  if (getRecordTimestamp(record, &recordXtime))
2673  SetLatestXTime(recordXtime);
2674 
2675  /* Extract the XID of the committed/aborted transaction */
2676  if (xact_info == XLOG_XACT_COMMIT_PREPARED)
2677  {
2678  xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
2679  xl_xact_parsed_commit parsed;
2680 
2682  xlrec,
2683  &parsed);
2684  recordXid = parsed.twophase_xid;
2685  }
2686  else if (xact_info == XLOG_XACT_ABORT_PREPARED)
2687  {
2688  xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2689  xl_xact_parsed_abort parsed;
2690 
2692  xlrec,
2693  &parsed);
2694  recordXid = parsed.twophase_xid;
2695  }
2696  else
2697  recordXid = XLogRecGetXid(record);
2698 
2699  /*
2700  * There can be only one transaction end record with this exact
2701  * transactionid
2702  *
2703  * when testing for an xid, we MUST test for equality only, since
2704  * transactions are numbered in the order they start, not the order
2705  * they complete. A higher numbered xid will complete before you about
2706  * 50% of the time...
2707  */
2709  recordXid == recoveryTargetXid)
2710  {
2711  recoveryStopAfter = true;
2712  recoveryStopXid = recordXid;
2713  recoveryStopTime = recordXtime;
2715  recoveryStopName[0] = '\0';
2716 
2717  if (xact_info == XLOG_XACT_COMMIT ||
2718  xact_info == XLOG_XACT_COMMIT_PREPARED)
2719  {
2720  ereport(LOG,
2721  (errmsg("recovery stopping after commit of transaction %u, time %s",
2724  }
2725  else if (xact_info == XLOG_XACT_ABORT ||
2726  xact_info == XLOG_XACT_ABORT_PREPARED)
2727  {
2728  ereport(LOG,
2729  (errmsg("recovery stopping after abort of transaction %u, time %s",
2732  }
2733  return true;
2734  }
2735  }
2736 
2737  /* Check if we should stop as soon as reaching consistency */
2739  {
2740  ereport(LOG,
2741  (errmsg("recovery stopping after reaching consistency")));
2742 
2743  recoveryStopAfter = true;
2745  recoveryStopTime = 0;
2747  recoveryStopName[0] = '\0';
2748  return true;
2749  }
2750 
2751  return false;
2752 }
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char rp_name[MAXFNAMELEN]
TransactionId twophase_xid
Definition: xact.h:414
TransactionId twophase_xid
Definition: xact.h:384
#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:413
bool recoveryTargetInclusive
Definition: xlogrecovery.c:86
static void SetLatestXTime(TimestampTz xtime)

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

Referenced by PerformWalRecovery().

◆ recoveryStopsBefore()

static bool recoveryStopsBefore ( XLogReaderState record)
static

Definition at line 2451 of file xlogrecovery.c.

2452 {
2453  bool stopsHere = false;
2454  uint8 xact_info;
2455  bool isCommit;
2456  TimestampTz recordXtime = 0;
2457  TransactionId recordXid;
2458 
2459  /*
2460  * Ignore recovery target settings when not in archive recovery (meaning
2461  * we are in crash recovery).
2462  */
2464  return false;
2465 
2466  /* Check if we should stop as soon as reaching consistency */
2468  {
2469  ereport(LOG,
2470  (errmsg("recovery stopping after reaching consistency")));
2471 
2472  recoveryStopAfter = false;
2475  recoveryStopTime = 0;
2476  recoveryStopName[0] = '\0';
2477  return true;
2478  }
2479 
2480  /* Check if target LSN has been reached */
2483  record->ReadRecPtr >= recoveryTargetLSN)
2484  {
2485  recoveryStopAfter = false;
2487  recoveryStopLSN = record->ReadRecPtr;
2488  recoveryStopTime = 0;
2489  recoveryStopName[0] = '\0';
2490  ereport(LOG,
2491  (errmsg("recovery stopping before WAL location (LSN) \"%X/%X\"",
2493  return true;
2494  }
2495 
2496  /* Otherwise we only consider stopping before COMMIT or ABORT records. */
2497  if (XLogRecGetRmid(record) != RM_XACT_ID)
2498  return false;
2499 
2500  xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
2501 
2502  if (xact_info == XLOG_XACT_COMMIT)
2503  {
2504  isCommit = true;
2505  recordXid = XLogRecGetXid(record);
2506  }
2507  else if (xact_info == XLOG_XACT_COMMIT_PREPARED)
2508  {
2509  xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
2510  xl_xact_parsed_commit parsed;
2511 
2512  isCommit = true;
2514  xlrec,
2515  &parsed);
2516  recordXid = parsed.twophase_xid;
2517  }
2518  else if (xact_info == XLOG_XACT_ABORT)
2519  {
2520  isCommit = false;
2521  recordXid = XLogRecGetXid(record);
2522  }
2523  else if (xact_info == XLOG_XACT_ABORT_PREPARED)
2524  {
2525  xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
2526  xl_xact_parsed_abort parsed;
2527 
2528  isCommit = false;
2530  xlrec,
2531  &parsed);
2532  recordXid = parsed.twophase_xid;
2533  }
2534  else
2535  return false;
2536 
2538  {
2539  /*
2540  * There can be only one transaction end record with this exact
2541  * transactionid
2542  *
2543  * when testing for an xid, we MUST test for equality only, since
2544  * transactions are numbered in the order they start, not the order
2545  * they complete. A higher numbered xid will complete before you about
2546  * 50% of the time...
2547  */
2548  stopsHere = (recordXid == recoveryTargetXid);
2549  }
2550 
2552  getRecordTimestamp(record, &recordXtime))
2553  {
2554  /*
2555  * There can be many transactions that share the same commit time, so
2556  * we stop after the last one, if we are inclusive, or stop at the
2557  * first one if we are exclusive
2558  */
2560  stopsHere = (recordXtime > recoveryTargetTime);
2561  else
2562  stopsHere = (recordXtime >= recoveryTargetTime);
2563  }
2564 
2565  if (stopsHere)
2566  {
2567  recoveryStopAfter = false;
2568  recoveryStopXid = recordXid;
2569  recoveryStopTime = recordXtime;
2571  recoveryStopName[0] = '\0';
2572 
2573  if (isCommit)
2574  {
2575  ereport(LOG,
2576  (errmsg("recovery stopping before commit of transaction %u, time %s",
2579  }
2580  else
2581  {
2582  ereport(LOG,
2583  (errmsg("recovery stopping before abort of transaction %u, time %s",
2586  }
2587  }
2588 
2589  return stopsHere;
2590 }

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

Referenced by PerformWalRecovery().

◆ RemovePromoteSignalFiles()

void RemovePromoteSignalFiles ( void  )

Definition at line 4325 of file xlogrecovery.c.

4326 {
4327  unlink(PROMOTE_SIGNAL_FILE);
4328 }

References PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ rescanLatestTimeLine()

static bool rescanLatestTimeLine ( TimeLineID  replayTLI,
XLogRecPtr  replayLSN 
)
static

Definition at line 3975 of file xlogrecovery.c.

3976 {
3977  List *newExpectedTLEs;
3978  bool found;
3979  ListCell *cell;
3980  TimeLineID newtarget;
3981  TimeLineID oldtarget = recoveryTargetTLI;
3982  TimeLineHistoryEntry *currentTle = NULL;
3983 
3985  if (newtarget == recoveryTargetTLI)
3986  {
3987  /* No new timelines found */
3988  return false;
3989  }
3990 
3991  /*
3992  * Determine the list of expected TLIs for the new TLI
3993  */
3994 
3995  newExpectedTLEs = readTimeLineHistory(newtarget);
3996 
3997  /*
3998  * If the current timeline is not part of the history of the new timeline,
3999  * we cannot proceed to it.
4000  */
4001  found = false;
4002  foreach(cell, newExpectedTLEs)
4003  {
4004  currentTle = (TimeLineHistoryEntry *) lfirst(cell);
4005 
4006  if (currentTle->tli == recoveryTargetTLI)
4007  {
4008  found = true;
4009  break;
4010  }
4011  }
4012  if (!found)
4013  {
4014  ereport(LOG,
4015  (errmsg("new timeline %u is not a child of database system timeline %u",
4016  newtarget,
4017  replayTLI)));
4018  return false;
4019  }
4020 
4021  /*
4022  * The current timeline was found in the history file, but check that the
4023  * next timeline was forked off from it *after* the current recovery
4024  * location.
4025  */
4026  if (currentTle->end < replayLSN)
4027  {
4028  ereport(LOG,
4029  (errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
4030  newtarget,
4031  replayTLI,
4032  LSN_FORMAT_ARGS(replayLSN))));
4033  return false;
4034  }
4035 
4036  /* The new timeline history seems valid. Switch target */
4037  recoveryTargetTLI = newtarget;
4039  expectedTLEs = newExpectedTLEs;
4040 
4041  /*
4042  * As in StartupXLOG(), try to ensure we have all the history files
4043  * between the old target and new target in pg_wal.
4044  */
4045  restoreTimeLineHistoryFiles(oldtarget + 1, newtarget);
4046 
4047  ereport(LOG,
4048  (errmsg("new target timeline is %u",
4049  recoveryTargetTLI)));
4050 
4051  return true;
4052 }
TimeLineID findNewestTimeLine(TimeLineID startTLI)
Definition: timeline.c:264
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
Definition: timeline.c:50
List * readTimeLineHistory(TimeLineID targetTLI)
Definition: timeline.c:76
void list_free_deep(List *list)
Definition: list.c:1559
TimeLineID tli
Definition: timeline.h:27
XLogRecPtr end
Definition: timeline.h:29

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

Referenced by WaitForWALToBecomeAvailable().

◆ rm_redo_error_callback()

static void rm_redo_error_callback ( void *  arg)
static

Definition at line 2153 of file xlogrecovery.c.

2154 {
2155  XLogReaderState *record = (XLogReaderState *) arg;
2157 
2158  initStringInfo(&buf);
2159  xlog_outdesc(&buf, record);
2160  xlog_block_info(&buf, record);
2161 
2162  /* translator: %s is a WAL record description */
2163  errcontext("WAL redo at %X/%X for %s",
2164  LSN_FORMAT_ARGS(record->ReadRecPtr),
2165  buf.data);
2166 
2167  pfree(buf.data);
2168 }
#define errcontext
Definition: elog.h:192
void * arg
static void xlog_block_info(StringInfo buf, XLogReaderState *record)

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

Referenced by ApplyWalRecord().

◆ SetCurrentChunkStartTime()

static void SetCurrentChunkStartTime ( TimestampTz  xtime)
static

◆ SetLatestXTime()

static void SetLatestXTime ( TimestampTz  xtime)
static

◆ SetPromoteIsTriggered()

static void SetPromoteIsTriggered ( void  )
static

Definition at line 4283 of file xlogrecovery.c.

4284 {
4288 
4289  /*
4290  * Mark the recovery pause state as 'not paused' because the paused state
4291  * ends and promotion continues if a promotion is triggered while recovery
4292  * is paused. Otherwise pg_get_wal_replay_pause_state() can mistakenly
4293  * return 'paused' while a promotion is ongoing.
4294  */
4295  SetRecoveryPause(false);
4296 
4297  LocalPromoteIsTriggered = true;
4298 }

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

Referenced by CheckForStandbyTrigger().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1522 of file xlogrecovery.c.

1523 {
1524  char recoveryPath[MAXPGPATH];
1525 
1526  /* Final update of pg_stat_recovery_prefetch. */
1528 
1529  /* Shut down xlogreader */
1530  if (readFile >= 0)
1531  {
1532  close(readFile);
1533  readFile = -1;
1534  }
1537 
1539  {
1540  /*
1541  * Since there might be a partial WAL segment named RECOVERYXLOG, get
1542  * rid of it.
1543  */
1544  snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1545  unlink(recoveryPath); /* ignore any error */
1546 
1547  /* Get rid of any remaining recovered timeline-history file, too */
1548  snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1549  unlink(recoveryPath); /* ignore any error */
1550  }
1551 
1552  /*
1553  * We don't need the latch anymore. It's not strictly necessary to disown
1554  * it, but let's do it for the sake of tidiness.
1555  */
1558 }
void DisownLatch(Latch *latch)
Definition: latch.c:448
#define XLOGDIR
void XLogPrefetcherComputeStats(XLogPrefetcher *prefetcher)
void XLogPrefetcherFree(XLogPrefetcher *prefetcher)
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:170

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

Referenced by StartupXLOG().

◆ StartupRequestWalReceiverRestart()

void StartupRequestWalReceiverRestart ( void  )

Definition at line 4246 of file xlogrecovery.c.

4247 {
4249  {
4250  ereport(LOG,
4251  (errmsg("WAL receiver process shutdown requested")));
4252 
4253  pendingWalRcvRestart = true;
4254  }
4255 }
bool WalRcvRunning(void)
static bool pendingWalRcvRestart
Definition: xlogrecovery.c:248

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

Referenced by StartupRereadConfig().

◆ validateRecoveryParameters()

static void validateRecoveryParameters ( void  )
static

Definition at line 1051 of file xlogrecovery.c.

1052 {
1054  return;
1055 
1056  /*
1057  * Check for compulsory parameters
1058  */
1060  {
1061  if ((PrimaryConnInfo == NULL || strcmp(PrimaryConnInfo, "") == 0) &&
1062  (recoveryRestoreCommand == NULL || strcmp(recoveryRestoreCommand, "") == 0))
1063  ereport(WARNING,
1064  (errmsg("specified neither primary_conninfo nor restore_command"),
1065  errhint("The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1066  }
1067  else
1068  {
1069  if (recoveryRestoreCommand == NULL ||
1070  strcmp(recoveryRestoreCommand, "") == 0)
1071  ereport(FATAL,
1072  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1073  errmsg("must specify restore_command when standby mode is not enabled")));
1074  }
1075 
1076  /*
1077  * Override any inconsistent requests. Note that this is a change of
1078  * behaviour in 9.5; prior to this we simply ignored a request to pause if
1079  * hot_standby = off, which was surprising behaviour.
1080  */
1084 
1085  /*
1086  * Final parsing of recovery_target_time string; see also
1087  * check_recovery_target_time().
1088  */
1090  {
1094  Int32GetDatum(-1)));
1095  }
1096 
1097  /*
1098  * If user specified recovery_target_timeline, validate it or compute the
1099  * "latest" value. We can't do this until after we've gotten the restore
1100  * command and set InArchiveRecovery, because we need to fetch timeline
1101  * history files from the archive.
1102  */
1104  {
1106 
1107  /* Timeline 1 does not have a history file, all else should */
1108  if (rtli != 1 && !existsTimeLineHistory(rtli))
1109  ereport(FATAL,
1110  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1111  errmsg("recovery target timeline %u does not exist",
1112  rtli)));
1113  recoveryTargetTLI = rtli;
1114  }
1116  {
1117  /* We start the "latest" search from pg_control's timeline */
1119  }
1120  else
1121  {
1122  /*
1123  * else we just use the recoveryTargetTLI as already read from
1124  * ControlFile
1125  */
1127  }
1128 }
bool existsTimeLineHistory(TimeLineID probeTLI)
Definition: timeline.c:222
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:403
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:646
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:698
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
#define InvalidOid
Definition: postgres_ext.h:36
static TimestampTz DatumGetTimestampTz(Datum X)
Definition: timestamp.h:34
bool EnableHotStandby
Definition: xlog.c:124
char * recoveryRestoreCommand
Definition: xlogrecovery.c:82
char * recovery_target_time_string
Definition: xlogrecovery.c:89
char * PrimaryConnInfo
Definition: xlogrecovery.c:96

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

Referenced by InitWalRecovery().

◆ verifyBackupPageConsistency()

static void verifyBackupPageConsistency ( XLogReaderState record)
static

Definition at line 2339 of file xlogrecovery.c.

2340 {
2341  RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2342  RelFileLocator rlocator;
2343  ForkNumber forknum;
2344  BlockNumber blkno;
2345  int block_id;
2346 
2347  /* Records with no backup blocks have no need for consistency checks. */
2348  if (!XLogRecHasAnyBlockRefs(record))
2349  return;
2350 
2351  Assert((XLogRecGetInfo(record) & XLR_CHECK_CONSISTENCY) != 0);
2352 
2353  for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
2354  {
2355  Buffer buf;
2356  Page page;
2357 
2358  if (!XLogRecGetBlockTagExtended(record, block_id,
2359  &rlocator, &forknum, &blkno, NULL))
2360  {
2361  /*
2362  * WAL record doesn't contain a block reference with the given id.
2363  * Do nothing.
2364  */
2365  continue;
2366  }
2367 
2368  Assert(XLogRecHasBlockImage(record, block_id));
2369 
2370  if (XLogRecBlockImageApply(record, block_id))
2371  {
2372  /*
2373  * WAL record has already applied the page, so bypass the
2374  * consistency check as that would result in comparing the full
2375  * page stored in the record with itself.
2376  */
2377  continue;
2378  }
2379 
2380  /*
2381  * Read the contents from the current buffer and store it in a
2382  * temporary page.
2383  */
2384  buf = XLogReadBufferExtended(rlocator, forknum, blkno,
2386  InvalidBuffer);
2387  if (!BufferIsValid(buf))
2388  continue;
2389 
2391  page = BufferGetPage(buf);
2392 
2393  /*
2394  * Take a copy of the local page where WAL has been applied to have a
2395  * comparison base before masking it...
2396  */
2397  memcpy(replay_image_masked, page, BLCKSZ);
2398 
2399  /* No need for this page anymore now that a copy is in. */
2401 
2402  /*
2403  * If the block LSN is already ahead of this WAL record, we can't
2404  * expect contents to match. This can happen if recovery is
2405  * restarted.
2406  */
2407  if (PageGetLSN(replay_image_masked) > record->EndRecPtr)
2408  continue;
2409 
2410  /*
2411  * Read the contents from the backup copy, stored in WAL record and
2412  * store it in a temporary page. There is no need to allocate a new
2413  * page here, a local buffer is fine to hold its contents and a mask
2414  * can be directly applied on it.
2415  */
2416  if (!RestoreBlockImage(record, block_id, primary_image_masked))
2417  ereport(ERROR,
2418  (errcode(ERRCODE_INTERNAL_ERROR),
2419  errmsg_internal("%s", record->errormsg_buf)));
2420 
2421  /*
2422  * If masking function is defined, mask both the primary and replay
2423  * images
2424  */
2425  if (rmgr.rm_mask != NULL)
2426  {
2427  rmgr.rm_mask(replay_image_masked, blkno);
2428  rmgr.rm_mask(primary_image_masked, blkno);
2429  }
2430 
2431  /* Time to compare the primary and replay images. */
2432  if (memcmp(replay_image_masked, primary_image_masked, BLCKSZ) != 0)
2433  {
2434  elog(FATAL,
2435  "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2436  rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
2437  forknum, blkno);
2438  }
2439  }
2440 }
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:3954
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4172
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:280
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:107
@ RBM_NORMAL_NO_LOG
Definition: bufmgr.h:45
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:228
Pointer Page
Definition: bufpage.h:78
static XLogRecPtr PageGetLSN(Page page)
Definition: bufpage.h:383
ForkNumber
Definition: relpath.h:48
RelFileNumber relNumber
void(* rm_mask)(char *pagedata, BlockNumber blkno)
char * errormsg_buf
Definition: xlogreader.h:311
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
Definition: xlogreader.c:1986
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:2045
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:426
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:419
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:424
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:418
Buffer XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)
Definition: xlogutils.c:474

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

Referenced by ApplyWalRecord().

◆ WaitForWALToBecomeAvailable()

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

Definition at line 3412 of file xlogrecovery.c.

3416 {
3417  static TimestampTz last_fail_time = 0;
3418  TimestampTz now;
3419  bool streaming_reply_sent = false;
3420 
3421  /*-------
3422  * Standby mode is implemented by a state machine:
3423  *
3424  * 1. Read from either archive or pg_wal (XLOG_FROM_ARCHIVE), or just
3425  * pg_wal (XLOG_FROM_PG_WAL)
3426  * 2. Check for promotion trigger request
3427  * 3. Read from primary server via walreceiver (XLOG_FROM_STREAM)
3428  * 4. Rescan timelines
3429  * 5. Sleep wal_retrieve_retry_interval milliseconds, and loop back to 1.
3430  *
3431  * Failure to read from the current source advances the state machine to
3432  * the next state.
3433  *
3434  * 'currentSource' indicates the current state. There are no currentSource
3435  * values for "check trigger", "rescan timelines", and "sleep" states,
3436  * those actions are taken when reading from the previous source fails, as
3437  * part of advancing to the next state.
3438  *
3439  * If standby mode is turned off while reading WAL from stream, we move
3440  * to XLOG_FROM_ARCHIVE and reset lastSourceFailed, to force fetching
3441  * the files (which would be required at end of recovery, e.g., timeline
3442  * history file) from archive or pg_wal. We don't need to kill WAL receiver
3443  * here because it's already stopped when standby mode is turned off at
3444  * the end of recovery.
3445  *-------
3446  */
3447  if (!InArchiveRecovery)
3449  else if (currentSource == XLOG_FROM_ANY ||
3451  {
3452  lastSourceFailed = false;
3454  }
3455 
3456  for (;;)
3457  {
3458  XLogSource oldSource = currentSource;
3459  bool startWalReceiver = false;
3460 
3461  /*
3462  * First check if we failed to read from the current source, and
3463  * advance the state machine if so. The failure to read might've
3464  * happened outside this function, e.g when a CRC check fails on a
3465  * record, or within this loop.
3466  */
3467  if (lastSourceFailed)
3468  {
3469  /*
3470  * Don't allow any retry loops to occur during nonblocking
3471  * readahead. Let the caller process everything that has been
3472  * decoded already first.
3473  */
3474  if (nonblocking)
3475  return XLREAD_WOULDBLOCK;
3476 
3477  switch (currentSource)
3478  {
3479  case XLOG_FROM_ARCHIVE:
3480  case XLOG_FROM_PG_WAL:
3481 
3482  /*
3483  * Check to see if promotion is requested. Note that we do
3484  * this only after failure, so when you promote, we still
3485  * finish replaying as much as we can from archive and
3486  * pg_wal before failover.
3487  */
3489  {
3491  return XLREAD_FAIL;
3492  }
3493 
3494  /*
3495  * Not in standby mode, and we've now tried the archive
3496  * and pg_wal.
3497  */
3498  if (!StandbyMode)
3499  return XLREAD_FAIL;
3500 
3501  /*
3502  * Move to XLOG_FROM_STREAM state, and set to start a
3503  * walreceiver if necessary.
3504  */
3506  startWalReceiver = true;
3507  break;
3508 
3509  case XLOG_FROM_STREAM:
3510 
3511  /*
3512  * Failure while streaming. Most likely, we got here
3513  * because streaming replication was terminated, or
3514  * promotion was triggered. But we also get here if we
3515  * find an invalid record in the WAL streamed from the
3516  * primary, in which case something is seriously wrong.
3517  * There's little chance that the problem will just go
3518  * away, but PANIC is not good for availability either,
3519  * especially in hot standby mode. So, we treat that the
3520  * same as disconnection, and retry from archive/pg_wal
3521  * again. The WAL in the archive should be identical to
3522  * what was streamed, so it's unlikely that it helps, but
3523  * one can hope...
3524  */
3525 
3526  /*
3527  * We should be able to move to XLOG_FROM_STREAM only in
3528  * standby mode.
3529  */
3531 
3532  /*
3533  * Before we leave XLOG_FROM_STREAM state, make sure that
3534  * walreceiver is not active, so that it won't overwrite
3535  * WAL that we restore from archive.
3536  */
3538 
3539  /*
3540  * Before we sleep, re-scan for possible new timelines if
3541  * we were requested to recover to the latest timeline.
3542  */
3544  {
3545  if (rescanLatestTimeLine(replayTLI, replayLSN))
3546  {
3548  break;
3549  }
3550  }
3551 
3552  /*
3553  * XLOG_FROM_STREAM is the last state in our state
3554  * machine, so we've exhausted all the options for
3555  * obtaining the requested WAL. We're going to loop back
3556  * and retry from the archive, but if it hasn't been long
3557  * since last attempt, sleep wal_retrieve_retry_interval
3558  * milliseconds to avoid busy-waiting.
3559  */
3561  if (!TimestampDifferenceExceeds(last_fail_time, now,
3563  {
3564  long wait_time;
3565 
3566  wait_time = wal_retrieve_retry_interval -
3567  TimestampDifferenceMilliseconds(last_fail_time, now);
3568 
3569  elog(LOG, "waiting for WAL to become available at %X/%X",
3570  LSN_FORMAT_ARGS(RecPtr));
3571 
3572  /* Do background tasks that might benefit us later. */
3574 
3578  wait_time,
3582 
3583  /* Handle interrupt signals of startup process */
3585  }
3586  last_fail_time = now;
3588  break;
3589 
3590  default:
3591  elog(ERROR, "unexpected WAL source %d", currentSource);
3592  }
3593  }
3594  else if (currentSource == XLOG_FROM_PG_WAL)
3595  {
3596  /*
3597  * We just successfully read a file in pg_wal. We prefer files in
3598  * the archive over ones in pg_wal, so try the next file again
3599  * from the archive first.
3600  */
3601  if (InArchiveRecovery)
3603  }
3604 
3605  if (currentSource != oldSource)
3606  elog(DEBUG2, "switched WAL source from %s to %s after %s",
3608  lastSourceFailed ? "failure" : "success");
3609 
3610  /*
3611  * We've now handled possible failure. Try to read from the chosen
3612  * source.
3613  */
3614  lastSourceFailed = false;
3615 
3616  switch (currentSource)
3617  {
3618  case XLOG_FROM_ARCHIVE:
3619  case XLOG_FROM_PG_WAL:
3620 
3621  /*
3622  * WAL receiver must not be running when reading WAL from
3623  * archive or pg_wal.
3624  */
3625  Assert(!WalRcvStreaming());
3626 
3627  /* Close any old file we might have open. */
3628  if (readFile >= 0)
3629  {
3630  close(readFile);
3631  readFile = -1;
3632  }
3633  /* Reset curFileTLI if random fetch. */
3634  if (randAccess)
3635  curFileTLI = 0;
3636 
3637  /*
3638  * Try to restore the file from archive, or read an existing
3639  * file from pg_wal.
3640  */
3643  currentSource);
3644  if (readFile >= 0)
3645  return XLREAD_SUCCESS; /* success! */
3646 
3647  /*
3648  * Nope, not found in archive or pg_wal.
3649  */
3650  lastSourceFailed = true;
3651  break;
3652 
3653  case XLOG_FROM_STREAM:
3654  {
3655  bool havedata;
3656 
3657  /*
3658  * We should be able to move to XLOG_FROM_STREAM only in
3659  * standby mode.
3660  */
3662 
3663  /*
3664  * First, shutdown walreceiver if its restart has been
3665  * requested -- but no point if we're already slated for
3666  * starting it.
3667  */
3668  if (pendingWalRcvRestart && !startWalReceiver)
3669  {
3671 
3672  /*
3673  * Re-scan for possible new timelines if we were
3674  * requested to recover to the latest timeline.
3675  */
3678  rescanLatestTimeLine(replayTLI, replayLSN);
3679 
3680  startWalReceiver = true;
3681  }
3682  pendingWalRcvRestart = false;
3683 
3684  /*
3685  * Launch walreceiver if needed.
3686  *
3687  * If fetching_ckpt is true, RecPtr points to the initial
3688  * checkpoint location. In that case, we use RedoStartLSN
3689  * as the streaming start position instead of RecPtr, so
3690  * that when we later jump backwards to start redo at
3691  * RedoStartLSN, we will have the logs streamed already.
3692  */
3693  if (startWalReceiver &&
3694  PrimaryConnInfo && strcmp(PrimaryConnInfo, "") != 0)
3695  {
3696  XLogRecPtr ptr;
3697  TimeLineID tli;
3698 
3699  if (fetching_ckpt)
3700  {
3701  ptr = RedoStartLSN;
3702  tli = RedoStartTLI;
3703  }
3704  else
3705  {
3706  ptr = RecPtr;
3707 
3708  /*
3709  * Use the record begin position to determine the
3710  * TLI, rather than the position we're reading.
3711  */
3712  tli = tliOfPointInHistory(tliRecPtr, expectedTLEs);
3713 
3714  if (curFileTLI > 0 && tli < curFileTLI)
3715  elog(ERROR, "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3716  LSN_FORMAT_ARGS(tliRecPtr),
3717  tli, curFileTLI);
3718  }
3719  curFileTLI = tli;
3724  flushedUpto = 0;
3725  }
3726 
3727  /*
3728  * Check if WAL receiver is active or wait to start up.
3729  */
3730  if (!WalRcvStreaming())
3731  {
3732  lastSourceFailed = true;
3733  break;
3734  }
3735 
3736  /*
3737  * Walreceiver is active, so see if new data has arrived.
3738  *
3739  * We only advance XLogReceiptTime when we obtain fresh
3740  * WAL from walreceiver and observe that we had already
3741  * processed everything before the most recent "chunk"
3742  * that it flushed to disk. In steady state where we are
3743  * keeping up with the incoming data, XLogReceiptTime will
3744  * be updated on each cycle. When we are behind,
3745  * XLogReceiptTime will not advance, so the grace time
3746  * allotted to conflicting queries will decrease.
3747  */
3748  if (RecPtr < flushedUpto)
3749  havedata = true;
3750  else
3751  {
3752  XLogRecPtr latestChunkStart;
3753 
3754  flushedUpto = GetWalRcvFlushRecPtr(&latestChunkStart, &receiveTLI);
3755  if (RecPtr < flushedUpto && receiveTLI == curFileTLI)
3756  {
3757  havedata = true;
3758  if (latestChunkStart <= RecPtr)
3759  {
3762  }
3763  }
3764  else
3765  havedata = false;
3766  }
3767  if (havedata)
3768  {
3769  /*
3770  * Great, streamed far enough. Open the file if it's
3771  * not open already. Also read the timeline history
3772  * file if we haven't initialized timeline history
3773  * yet; it should be streamed over and present in
3774  * pg_wal by now. Use XLOG_FROM_STREAM so that source
3775  * info is set correctly and XLogReceiptTime isn't
3776  * changed.
3777  *
3778  * NB: We must set readTimeLineHistory based on
3779  * recoveryTargetTLI, not receiveTLI. Normally they'll
3780  * be the same, but if recovery_target_timeline is
3781  * 'latest' and archiving is configured, then it's
3782  * possible that we managed to retrieve one or more
3783  * new timeline history files from the archive,
3784  * updating recoveryTargetTLI.
3785  */
3786  if (readFile < 0)
3787  {
3788  if (!expectedTLEs)
3791  receiveTLI,
3792  XLOG_FROM_STREAM, false);
3793  Assert(readFile >= 0);
3794  }
3795  else
3796  {
3797  /* just make sure source info is correct... */
3800  return XLREAD_SUCCESS;
3801  }
3802  break;
3803  }
3804 
3805  /* In nonblocking mode, return rather than sleeping. */
3806  if (nonblocking)
3807  return XLREAD_WOULDBLOCK;
3808 
3809  /*
3810  * Data not here yet. Check for trigger, then wait for
3811  * walreceiver to wake us up when new WAL arrives.
3812  */
3813  if (CheckForStandbyTrigger())
3814  {
3815  /*
3816  * Note that we don't return XLREAD_FAIL immediately
3817  * here. After being triggered, we still want to
3818  * replay all the WAL that was already streamed. It's
3819  * in pg_wal now, so we just treat this as a failure,
3820  * and the state machine will move on to replay the
3821  * streamed WAL from pg_wal, and then recheck the
3822  * trigger and exit replay.
3823  */
3824  lastSourceFailed = true;
3825  break;
3826  }
3827 
3828  /*
3829  * Since we have replayed everything we have received so
3830  * far and are about to start waiting for more WAL, let's
3831  * tell the upstream server our replay location now so
3832  * that pg_stat_replication doesn't show stale
3833  * information.
3834  */
3835  if (!streaming_reply_sent)
3836  {
3837  WalRcvForceReply();
3838  streaming_reply_sent = true;
3839  }
3840 
3841  /* Do any background tasks that might benefit us later. */
3843 
3844  /* Update pg_stat_recovery_prefetch before sleeping. */
3846 
3847  /*
3848  * Wait for more WAL to arrive, when we will be woken
3849  * immediately by the WAL receiver.
3850  */
3853  -1L,
3856  break;
3857  }
3858 
3859  default:
3860  elog(ERROR, "unexpected WAL source %d", currentSource);
3861  }
3862 
3863  /*
3864  * Check for recovery pause here so that we can confirm more quickly
3865  * that a requested pause has actually taken effect.
3866  */
3867  if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
3869  recoveryPausesHere(false);
3870 
3871  /*
3872  * This possibly-long loop needs to handle interrupts of startup
3873  * process.
3874  */
3876  }
3877 
3878  return XLREAD_FAIL; /* not reached */
3879 }
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1719
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1537
void KnownAssignedTransactionIdsIdleMaintenance(void)
Definition: procarray.c:4529
@ WAIT_EVENT_RECOVERY_WAL_STREAM
Definition: wait_event.h:45
@ WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL
Definition: wait_event.h:146
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, const char *slotname, bool create_temp_slot)
void SetInstallXLogFileSegmentActive(void)
Definition: xlog.c:8909
int wal_retrieve_retry_interval
Definition: xlog.c:137
@ XLREAD_WOULDBLOCK
Definition: xlogreader.h:354
@ XLREAD_SUCCESS
Definition: xlogreader.h:352
@ XLREAD_FAIL
Definition: xlogreader.h:353
char * PrimarySlotName
Definition: xlogrecovery.c:97
static TimeLineID curFileTLI
Definition: xlogrecovery.c:124
static const char *const xlogSourceNames[]
Definition: xlogrecovery.c:218
static TimeLineID receiveTLI
Definition: xlogrecovery.c:263
static int XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source)
static XLogSegNo readSegNo
Definition: xlogrecovery.c:231
static int XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli, XLogSource source, bool notfoundOk)
static void SetCurrentChunkStartTime(TimestampTz xtime)
bool wal_receiver_create_temp_slot
Definition: xlogrecovery.c:98
static XLogRecPtr flushedUpto
Definition: xlogrecovery.c:262
static bool rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN)

References Assert(), CheckForStandbyTrigger(), close, curFileTLI, currentSource, DEBUG2, elog(), ERROR, expectedTLEs, flushedUpto, GetCurrentTimestamp(), GetWalRcvFlushRecPtr(), HandleStartupProcInterrupts(), InArchiveRecovery, KnownAssignedTransactionIdsIdleMaintenance(), lastSourceFailed, LOG, LSN_FORMAT_ARGS, now(), PANIC, pendingWalRcvRestart, PrimaryConnInfo, PrimarySlotName, readFile, r