PostgreSQL Source Code  git master
xlogrecovery.h File Reference
#include "access/xlogreader.h"
#include "catalog/pg_control.h"
#include "lib/stringinfo.h"
#include "utils/timestamp.h"
Include dependency graph for xlogrecovery.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  EndOfWalRecoveryInfo
 

Typedefs

typedef enum RecoveryPauseState RecoveryPauseState
 

Enumerations

enum  RecoveryTargetType {
  RECOVERY_TARGET_UNSET , RECOVERY_TARGET_XID , RECOVERY_TARGET_TIME , RECOVERY_TARGET_NAME ,
  RECOVERY_TARGET_LSN , RECOVERY_TARGET_IMMEDIATE
}
 
enum  RecoveryTargetTimeLineGoal { RECOVERY_TARGET_TIMELINE_CONTROLFILE , RECOVERY_TARGET_TIMELINE_LATEST , RECOVERY_TARGET_TIMELINE_NUMERIC }
 
enum  RecoveryPauseState { RECOVERY_NOT_PAUSED , RECOVERY_PAUSE_REQUESTED , RECOVERY_PAUSED }
 

Functions

Size XLogRecoveryShmemSize (void)
 
void XLogRecoveryShmemInit (void)
 
void InitWalRecovery (ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
 
void PerformWalRecovery (void)
 
EndOfWalRecoveryInfoFinishWalRecovery (void)
 
void ShutdownWalRecovery (void)
 
void RemovePromoteSignalFiles (void)
 
bool HotStandbyActive (void)
 
XLogRecPtr GetXLogReplayRecPtr (TimeLineID *replayTLI)
 
RecoveryPauseState GetRecoveryPauseState (void)
 
void SetRecoveryPause (bool recoveryPause)
 
void GetXLogReceiptTime (TimestampTz *rtime, bool *fromStream)
 
TimestampTz GetLatestXTime (void)
 
TimestampTz GetCurrentChunkReplayStartTime (void)
 
XLogRecPtr GetCurrentReplayRecPtr (TimeLineID *replayEndTLI)
 
bool PromoteIsTriggered (void)
 
bool CheckPromoteSignal (void)
 
void WakeupRecovery (void)
 
void StartupRequestWalReceiverRestart (void)
 
void XLogRequestWalReceiverReply (void)
 
void RecoveryRequiresIntParameter (const char *param_name, int currValue, int minValue)
 
void xlog_outdesc (StringInfo buf, XLogReaderState *record)
 

Variables

PGDLLIMPORT bool recoveryTargetInclusive
 
PGDLLIMPORT int recoveryTargetAction
 
PGDLLIMPORT int recovery_min_apply_delay
 
PGDLLIMPORT char * PrimaryConnInfo
 
PGDLLIMPORT char * PrimarySlotName
 
PGDLLIMPORT char * recoveryRestoreCommand
 
PGDLLIMPORT char * recoveryEndCommand
 
PGDLLIMPORT char * archiveCleanupCommand
 
PGDLLIMPORT TransactionId recoveryTargetXid
 
PGDLLIMPORT char * recovery_target_time_string
 
PGDLLIMPORT TimestampTz recoveryTargetTime
 
PGDLLIMPORT const char * recoveryTargetName
 
PGDLLIMPORT XLogRecPtr recoveryTargetLSN
 
PGDLLIMPORT RecoveryTargetType recoveryTarget
 
PGDLLIMPORT bool wal_receiver_create_temp_slot
 
PGDLLIMPORT RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
 
PGDLLIMPORT TimeLineID recoveryTargetTLIRequested
 
PGDLLIMPORT TimeLineID recoveryTargetTLI
 
PGDLLIMPORT bool reachedConsistency
 
PGDLLIMPORT bool StandbyMode
 

Typedef Documentation

◆ RecoveryPauseState

Enumeration Type Documentation

◆ RecoveryPauseState

Enumerator
RECOVERY_NOT_PAUSED 
RECOVERY_PAUSE_REQUESTED 
RECOVERY_PAUSED 

Definition at line 44 of file xlogrecovery.h.

45 {
46  RECOVERY_NOT_PAUSED, /* pause not requested */
47  RECOVERY_PAUSE_REQUESTED, /* pause requested, but not yet paused */
48  RECOVERY_PAUSED, /* recovery is paused */
RecoveryPauseState
Definition: xlogrecovery.h:45
@ RECOVERY_PAUSED
Definition: xlogrecovery.h:48
@ RECOVERY_NOT_PAUSED
Definition: xlogrecovery.h:46
@ RECOVERY_PAUSE_REQUESTED
Definition: xlogrecovery.h:47

◆ RecoveryTargetTimeLineGoal

Enumerator
RECOVERY_TARGET_TIMELINE_CONTROLFILE 
RECOVERY_TARGET_TIMELINE_LATEST 
RECOVERY_TARGET_TIMELINE_NUMERIC 

Definition at line 36 of file xlogrecovery.h.

37 {
RecoveryTargetTimeLineGoal
Definition: xlogrecovery.h:37
@ RECOVERY_TARGET_TIMELINE_NUMERIC
Definition: xlogrecovery.h:40
@ RECOVERY_TARGET_TIMELINE_CONTROLFILE
Definition: xlogrecovery.h:38
@ RECOVERY_TARGET_TIMELINE_LATEST
Definition: xlogrecovery.h:39

◆ RecoveryTargetType

Enumerator
RECOVERY_TARGET_UNSET 
RECOVERY_TARGET_XID 
RECOVERY_TARGET_TIME 
RECOVERY_TARGET_NAME 
RECOVERY_TARGET_LSN 
RECOVERY_TARGET_IMMEDIATE 

Definition at line 23 of file xlogrecovery.h.

24 {
RecoveryTargetType
Definition: xlogrecovery.h:24
@ RECOVERY_TARGET_IMMEDIATE
Definition: xlogrecovery.h:30
@ RECOVERY_TARGET_TIME
Definition: xlogrecovery.h:27
@ RECOVERY_TARGET_UNSET
Definition: xlogrecovery.h:25
@ RECOVERY_TARGET_XID
Definition: xlogrecovery.h:26
@ RECOVERY_TARGET_LSN
Definition: xlogrecovery.h:29
@ RECOVERY_TARGET_NAME
Definition: xlogrecovery.h:28

Function Documentation

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 4407 of file xlogrecovery.c.

4408 {
4409  struct stat stat_buf;
4410 
4411  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4412  return true;
4413 
4414  return false;
4415 }
#define stat
Definition: win32_port.h:284
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:301

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo* FinishWalRecovery ( void  )

Definition at line 1423 of file xlogrecovery.c.

1424 {
1426  XLogRecPtr lastRec;
1427  TimeLineID lastRecTLI;
1428  XLogRecPtr endOfLog;
1429 
1430  /*
1431  * Kill WAL receiver, if it's still running, before we continue to write
1432  * the startup checkpoint and aborted-contrecord records. It will trump
1433  * over these records and subsequent ones if it's still alive when we
1434  * start writing WAL.
1435  */
1437 
1438  /*
1439  * We are now done reading the xlog from stream. Turn off streaming
1440  * recovery to force fetching the files (which would be required at end of
1441  * recovery, e.g., timeline history file) from archive or pg_wal.
1442  *
1443  * Note that standby mode must be turned off after killing WAL receiver,
1444  * i.e., calling XLogShutdownWalRcv().
1445  */
1446  Assert(!WalRcvStreaming());
1447  StandbyMode = false;
1448 
1449  /*
1450  * Determine where to start writing WAL next.
1451  *
1452  * Re-fetch the last valid or last applied record, so we can identify the
1453  * exact endpoint of what we consider the valid portion of WAL. There may
1454  * be an incomplete continuation record after that, in which case
1455  * 'abortedRecPtr' and 'missingContrecPtr' are set and the caller will
1456  * write a special OVERWRITE_CONTRECORD message to mark that the rest of
1457  * it is intentionally missing. See CreateOverwriteContrecordRecord().
1458  *
1459  * An important side-effect of this is to load the last page into
1460  * xlogreader. The caller uses it to initialize the WAL for writing.
1461  */
1462  if (!InRecovery)
1463  {
1464  lastRec = CheckPointLoc;
1465  lastRecTLI = CheckPointTLI;
1466  }
1467  else
1468  {
1470  lastRecTLI = XLogRecoveryCtl->lastReplayedTLI;
1471  }
1473  (void) ReadRecord(xlogprefetcher, PANIC, false, lastRecTLI);
1474  endOfLog = xlogreader->EndRecPtr;
1475 
1476  /*
1477  * Remember the TLI in the filename of the XLOG segment containing the
1478  * end-of-log. It could be different from the timeline that endOfLog
1479  * nominally belongs to, if there was a timeline switch in that segment,
1480  * and we were reading the old WAL from a segment belonging to a higher
1481  * timeline.
1482  */
1483  result->endOfLogTLI = xlogreader->seg.ws_tli;
1484 
1486  {
1487  /*
1488  * We are no longer in archive recovery state.
1489  *
1490  * We are now done reading the old WAL. Turn off archive fetching if
1491  * it was active.
1492  */
1494  InArchiveRecovery = false;
1495 
1496  /*
1497  * If the ending log segment is still open, close it (to avoid
1498  * problems on Windows with trying to rename or delete an open file).
1499  */
1500  if (readFile >= 0)
1501  {
1502  close(readFile);
1503  readFile = -1;
1504  }
1505  }
1506 
1507  /*
1508  * Copy the last partial block to the caller, for initializing the WAL
1509  * buffer for appending new WAL.
1510  */
1511  if (endOfLog % XLOG_BLCKSZ != 0)
1512  {
1513  char *page;
1514  int len;
1515  XLogRecPtr pageBeginPtr;
1516 
1517  pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1518  Assert(readOff == XLogSegmentOffset(pageBeginPtr, wal_segment_size));
1519 
1520  /* Copy the valid part of the last block */
1521  len = endOfLog % XLOG_BLCKSZ;
1522  page = palloc(len);
1523  memcpy(page, xlogreader->readBuf, len);
1524 
1525  result->lastPageBeginPtr = pageBeginPtr;
1526  result->lastPage = page;
1527  }
1528  else
1529  {
1530  /* There is no partial block to copy. */
1531  result->lastPageBeginPtr = endOfLog;
1532  result->lastPage = NULL;
1533  }
1534 
1535  /*
1536  * Create a comment for the history file to explain why and where timeline
1537  * changed.
1538  */
1540 
1541  result->lastRec = lastRec;
1542  result->lastRecTLI = lastRecTLI;
1543  result->endOfLog = endOfLog;
1544 
1545  result->abortedRecPtr = abortedRecPtr;
1547 
1550 
1551  return result;
1552 }
#define PANIC
Definition: elog.h:42
#define close(a)
Definition: win32.h:12
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc(Size size)
Definition: mcxt.c:1226
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
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
WALOpenSegment seg
Definition: xlogreader.h:272
TimeLineID lastReplayedTLI
Definition: xlogrecovery.c:340
XLogRecPtr lastReplayedReadRecPtr
Definition: xlogrecovery.c:338
bool WalRcvStreaming(void)
int wal_segment_size
Definition: xlog.c:146
void XLogShutdownWalRcv(void)
Definition: xlog.c:9105
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
uint32 TimeLineID
Definition: xlogdefs.h:59
void XLogPrefetcherBeginRead(XLogPrefetcher *prefetcher, XLogRecPtr recPtr)
static char * getRecoveryStopReason(void)
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:137
bool InArchiveRecovery
Definition: xlogrecovery.c:138
static XLogRecPtr missingContrecPtr
Definition: xlogrecovery.c:373
static XLogRecoveryCtlData * XLogRecoveryCtl
Definition: xlogrecovery.c:364
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 XLogReaderState * xlogreader
Definition: xlogrecovery.c:188
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 4570 of file xlogrecovery.c.

4571 {
4572  TimestampTz xtime;
4573 
4577 
4578  return xtime;
4579 }
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
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 4506 of file xlogrecovery.c.

4507 {
4508  XLogRecPtr recptr;
4509  TimeLineID tli;
4510 
4512  recptr = XLogRecoveryCtl->replayEndRecPtr;
4515 
4516  if (replayEndTLI)
4517  *replayEndTLI = tli;
4518  return recptr;
4519 }
TimeLineID replayEndTLI
Definition: xlogrecovery.c:348
XLogRecPtr replayEndRecPtr
Definition: xlogrecovery.c:347

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

Referenced by UpdateMinRecoveryPoint(), and xlog_redo().

◆ GetLatestXTime()

TimestampTz GetLatestXTime ( void  )

◆ GetRecoveryPauseState()

◆ GetXLogReceiptTime()

void GetXLogReceiptTime ( TimestampTz rtime,
bool fromStream 
)

Definition at line 4586 of file xlogrecovery.c.

4587 {
4588  /*
4589  * This must be executed in the startup process, since we don't export the
4590  * relevant state to shared memory.
4591  */
4592  Assert(InRecovery);
4593 
4594  *rtime = XLogReceiptTime;
4595  *fromStream = (XLogReceiptSource == XLOG_FROM_STREAM);
4596 }
static XLogSource XLogReceiptSource
Definition: xlogrecovery.c:259
@ XLOG_FROM_STREAM
Definition: xlogrecovery.c:214
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 4446 of file xlogrecovery.c.

4447 {
4448  /*
4449  * We check shared state each time only until Hot Standby is active. We
4450  * can't de-activate Hot Standby, so there's no need to keep checking
4451  * after the shared variable has once been seen true.
4452  */
4454  return true;
4455  else
4456  {
4457  /* spinlock is essential on machines with weak memory ordering! */
4461 
4462  return LocalHotStandbyActive;
4463  }
4464 }
static bool LocalHotStandbyActive
Definition: xlogrecovery.c:176

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

Referenced by XLogWalRcvSendHSFeedback().

◆ InitWalRecovery()

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

Definition at line 512 of file xlogrecovery.c.

514 {
515  XLogPageReadPrivate *private;
516  struct stat st;
517  bool wasShutdown;
518  XLogRecord *record;
519  DBState dbstate_at_startup;
520  bool haveTblspcMap = false;
521  bool haveBackupLabel = false;
522  CheckPoint checkPoint;
523  bool backupFromStandby = false;
524 
525  dbstate_at_startup = ControlFile->state;
526 
527  /*
528  * Initialize on the assumption we want to recover to the latest timeline
529  * that's active according to pg_control.
530  */
534  else
536 
537  /*
538  * Check for signal files, and if so set up state for offline recovery
539  */
542 
543  /*
544  * Take ownership of the wakeup latch if we're going to sleep during
545  * recovery, if required.
546  */
549 
550  /*
551  * Set the WAL reading processor now, as it will be needed when reading
552  * the checkpoint record required (backup_label or not).
553  */
554  private = palloc0(sizeof(XLogPageReadPrivate));
555  xlogreader =
557  XL_ROUTINE(.page_read = &XLogPageRead,
558  .segment_open = NULL,
559  .segment_close = wal_segment_close),
560  private);
561  if (!xlogreader)
562  ereport(ERROR,
563  (errcode(ERRCODE_OUT_OF_MEMORY),
564  errmsg("out of memory"),
565  errdetail("Failed while allocating a WAL reading processor.")));
567 
568  /*
569  * Set the WAL decode buffer size. This limits how far ahead we can read
570  * in the WAL.
571  */
573 
574  /* Create a WAL prefetcher. */
576 
577  /*
578  * Allocate two page buffers dedicated to WAL consistency checks. We do
579  * it this way, rather than just making static arrays, for two reasons:
580  * (1) no need to waste the storage in most instantiations of the backend;
581  * (2) a static char array isn't guaranteed to have any particular
582  * alignment, whereas palloc() will provide MAXALIGN'd storage.
583  */
584  replay_image_masked = (char *) palloc(BLCKSZ);
585  primary_image_masked = (char *) palloc(BLCKSZ);
586 
587  /*
588  * Read the backup_label file. We want to run this part of the recovery
589  * process after checking for signal files and after performing validation
590  * of the recovery parameters.
591  */
593  &backupFromStandby))
594  {
595  List *tablespaces = NIL;
596 
597  /*
598  * Archive recovery was requested, and thanks to the backup label
599  * file, we know how far we need to replay to reach consistency. Enter
600  * archive recovery directly.
601  */
602  InArchiveRecovery = true;
605 
606  /*
607  * When a backup_label file is present, we want to roll forward from
608  * the checkpoint it identifies, rather than using pg_control.
609  */
611  CheckPointTLI);
612  if (record != NULL)
613  {
614  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
615  wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
616  ereport(DEBUG1,
617  (errmsg_internal("checkpoint record is at %X/%X",
619  InRecovery = true; /* force recovery even if SHUTDOWNED */
620 
621  /*
622  * Make sure that REDO location exists. This may not be the case
623  * if there was a crash during an online backup, which left a
624  * backup_label around that references a WAL segment that's
625  * already been archived.
626  */
627  if (checkPoint.redo < CheckPointLoc)
628  {
630  if (!ReadRecord(xlogprefetcher, LOG, false,
631  checkPoint.ThisTimeLineID))
632  ereport(FATAL,
633  (errmsg("could not find redo location referenced by checkpoint record"),
634  errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
635  "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
636  "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
638  }
639  }
640  else
641  {
642  ereport(FATAL,
643  (errmsg("could not locate required checkpoint record"),
644  errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
645  "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
646  "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
648  wasShutdown = false; /* keep compiler quiet */
649  }
650 
651  /* Read the tablespace_map file if present and create symlinks. */
652  if (read_tablespace_map(&tablespaces))
653  {
654  ListCell *lc;
655 
656  foreach(lc, tablespaces)
657  {
658  tablespaceinfo *ti = lfirst(lc);
659  char *linkloc;
660 
661  linkloc = psprintf("pg_tblspc/%u", ti->oid);
662 
663  /*
664  * Remove the existing symlink if any and Create the symlink
665  * under PGDATA.
666  */
667  remove_tablespace_symlink(linkloc);
668 
669  if (symlink(ti->path, linkloc) < 0)
670  ereport(ERROR,
672  errmsg("could not create symbolic link \"%s\": %m",
673  linkloc)));
674 
675  pfree(ti->path);
676  pfree(ti);
677  }
678 
679  /* tell the caller to delete it later */
680  haveTblspcMap = true;
681  }
682 
683  /* tell the caller to delete it later */
684  haveBackupLabel = true;
685  }
686  else
687  {
688  /* No backup_label file has been found if we are here. */
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;
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 
774  {
776  ereport(LOG,
777  (errmsg("entering standby mode")));
779  ereport(LOG,
780  (errmsg("starting point-in-time recovery to XID %u",
783  ereport(LOG,
784  (errmsg("starting point-in-time recovery to %s",
787  ereport(LOG,
788  (errmsg("starting point-in-time recovery to \"%s\"",
791  ereport(LOG,
792  (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
795  ereport(LOG,
796  (errmsg("starting point-in-time recovery to earliest consistent point")));
797  else
798  ereport(LOG,
799  (errmsg("starting archive recovery")));
800  }
801 
802  /*
803  * If the location of the checkpoint record is not on the expected
804  * timeline in the history of the requested timeline, we cannot proceed:
805  * the backup is not part of the history of the requested timeline.
806  */
807  Assert(expectedTLEs); /* was initialized by reading checkpoint
808  * record */
811  {
812  XLogRecPtr switchpoint;
813 
814  /*
815  * tliSwitchPoint will throw an error if the checkpoint's timeline is
816  * not in expectedTLEs at all.
817  */
819  ereport(FATAL,
820  (errmsg("requested timeline %u is not a child of this server's history",
822  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.",
825  LSN_FORMAT_ARGS(switchpoint))));
826  }
827 
828  /*
829  * The min recovery point should be part of the requested timeline's
830  * history, too.
831  */
835  ereport(FATAL,
836  (errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
840 
841  ereport(DEBUG1,
842  (errmsg_internal("redo record is at %X/%X; shutdown %s",
843  LSN_FORMAT_ARGS(checkPoint.redo),
844  wasShutdown ? "true" : "false")));
845  ereport(DEBUG1,
846  (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
847  U64FromFullTransactionId(checkPoint.nextXid),
848  checkPoint.nextOid)));
849  ereport(DEBUG1,
850  (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
851  checkPoint.nextMulti, checkPoint.nextMultiOffset)));
852  ereport(DEBUG1,
853  (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
854  checkPoint.oldestXid, checkPoint.oldestXidDB)));
855  ereport(DEBUG1,
856  (errmsg_internal("oldest MultiXactId: %u, in database %u",
857  checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
858  ereport(DEBUG1,
859  (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
860  checkPoint.oldestCommitTsXid,
861  checkPoint.newestCommitTsXid)));
863  ereport(PANIC,
864  (errmsg("invalid next transaction ID")));
865 
866  /* sanity check */
867  if (checkPoint.redo > CheckPointLoc)
868  ereport(PANIC,
869  (errmsg("invalid redo in checkpoint record")));
870 
871  /*
872  * Check whether we need to force recovery from WAL. If it appears to
873  * have been a clean shutdown and we did not have a recovery signal file,
874  * then assume no recovery needed.
875  */
876  if (checkPoint.redo < CheckPointLoc)
877  {
878  if (wasShutdown)
879  ereport(PANIC,
880  (errmsg("invalid redo record in shutdown checkpoint")));
881  InRecovery = true;
882  }
883  else if (ControlFile->state != DB_SHUTDOWNED)
884  InRecovery = true;
885  else if (ArchiveRecoveryRequested)
886  {
887  /* force recovery due to presence of recovery signal file */
888  InRecovery = true;
889  }
890 
891  /*
892  * If recovery is needed, update our in-memory copy of pg_control to show
893  * that we are recovering and to show the selected checkpoint as the place
894  * we are starting from. We also mark pg_control with any minimum recovery
895  * stop point obtained from a backup history file.
896  *
897  * We don't write the changes to disk yet, though. Only do that after
898  * initializing various subsystems.
899  */
900  if (InRecovery)
901  {
902  if (InArchiveRecovery)
903  {
905  }
906  else
907  {
908  ereport(LOG,
909  (errmsg("database system was not properly shut down; "
910  "automatic recovery in progress")));
912  ereport(LOG,
913  (errmsg("crash recovery starts in timeline %u "
914  "and has target timeline %u",
918  }
920  ControlFile->checkPointCopy = checkPoint;
921  if (InArchiveRecovery)
922  {
923  /* initialize minRecoveryPoint if not set yet */
924  if (ControlFile->minRecoveryPoint < checkPoint.redo)
925  {
926  ControlFile->minRecoveryPoint = checkPoint.redo;
928  }
929  }
930 
931  /*
932  * Set backupStartPoint if we're starting recovery from a base backup.
933  *
934  * Also set backupEndPoint and use minRecoveryPoint as the backup end
935  * location if we're starting recovery from a base backup which was
936  * taken from a standby. In this case, the database system status in
937  * pg_control must indicate that the database was already in recovery.
938  * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
939  * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
940  * before reaching this point; e.g. because restore_command or
941  * primary_conninfo were faulty.
942  *
943  * Any other state indicates that the backup somehow became corrupted
944  * and we can't sensibly continue with recovery.
945  */
946  if (haveBackupLabel)
947  {
948  ControlFile->backupStartPoint = checkPoint.redo;
950 
951  if (backupFromStandby)
952  {
953  if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
954  dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
955  ereport(FATAL,
956  (errmsg("backup_label contains data inconsistent with control file"),
957  errhint("This means that the backup is corrupted and you will "
958  "have to use another backup for recovery.")));
960  }
961  }
962  }
963 
964  /* remember these, so that we know when we have reached consistency */
968  if (InArchiveRecovery)
969  {
972  }
973  else
974  {
977  }
978 
979  /*
980  * Start recovery assuming that the final record isn't lost.
981  */
984 
985  *wasShutdown_ptr = wasShutdown;
986  *haveBackupLabel_ptr = haveBackupLabel;
987  *haveTblspcMap_ptr = haveTblspcMap;
988 }
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
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1848
#define UINT64_FORMAT
Definition: c.h:538
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
int errcode_for_file_access(void)
Definition: elog.c:881
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define LOG
Definition: elog.h:31
#define FATAL
Definition: elog.h:41
#define DEBUG1
Definition: elog.h:30
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:759
char * DataDir
Definition: globals.c:66
void OwnLatch(Latch *latch)
Definition: latch.c:464
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc0(Size size)
Definition: mcxt.c:1257
DBState
Definition: pg_control.h:89
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:95
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:92
@ DB_SHUTDOWNED
Definition: pg_control.h:91
@ DB_IN_CRASH_RECOVERY
Definition: pg_control.h:94
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
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
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
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:169
bool backupEndRequired
Definition: pg_control.h:171
CheckPoint checkPointCopy
Definition: pg_control.h:134
XLogRecPtr backupEndPoint
Definition: pg_control.h:170
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:167
XLogRecPtr checkPoint
Definition: pg_control.h:132
uint64 system_identifier
Definition: pg_control.h:109
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:168
Definition: pg_list.h:54
uint64 system_identifier
Definition: xlogreader.h:191
uint8 xl_info
Definition: xlogrecord.h:46
#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:235
int wal_decode_buffer_size
Definition: xlog.c:139
static ControlFileData * ControlFile
Definition: xlog.c:580
#define TABLESPACE_MAP_OLD
Definition: xlog.h:298
#define TABLESPACE_MAP
Definition: xlog.h:297
#define BACKUP_LABEL_FILE
Definition: xlog.h:294
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
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 XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
static bool backupEndRequired
Definition: xlogrecovery.c:283
const char * recoveryTargetName
Definition: xlogrecovery.c:91
static XLogRecPtr minRecoveryPoint
Definition: xlogrecovery.c:278
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static XLogRecPtr backupEndPoint
Definition: xlogrecovery.c:282
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:998
XLogRecPtr recoveryTargetLSN
Definition: xlogrecovery.c:92
RecoveryTargetType recoveryTarget
Definition: xlogrecovery.c:85
static bool read_tablespace_map(List **tablespaces)
static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
static List * expectedTLEs
Definition: xlogrecovery.c:123
static char * primary_image_masked
Definition: xlogrecovery.c:298
static TimeLineID minRecoveryPointTLI
Definition: xlogrecovery.c:279
TransactionId recoveryTargetXid
Definition: xlogrecovery.c:88
static char * replay_image_masked
Definition: xlogrecovery.c:297
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:122
static XLogRecPtr RedoStartLSN
Definition: xlogrecovery.c:169
static void EnableStandbyMode(void)
Definition: xlogrecovery.c:478
TimestampTz recoveryTargetTime
Definition: xlogrecovery.c:90
static bool StandbyModeRequested
Definition: xlogrecovery.c:146
static XLogRecPtr backupStartPoint
Definition: xlogrecovery.c:281
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:844

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

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1602 of file xlogrecovery.c.

1603 {
1604  XLogRecord *record;
1605  bool reachedRecoveryTarget = false;
1606  TimeLineID replayTLI;
1607 
1608  /*
1609  * Initialize shared variables for tracking progress of WAL replay, as if
1610  * we had just replayed the record before the REDO location (or the
1611  * checkpoint record itself, if it's a shutdown checkpoint).
1612  */
1615  {
1619  }
1620  else
1621  {
1625  }
1632 
1633  /* Also ensure XLogReceiptTime has a sane value */
1635 
1636  /*
1637  * Let postmaster know we've started redo now, so that it can launch the
1638  * archiver if necessary.
1639  */
1640  if (IsUnderPostmaster)
1642 
1643  /*
1644  * Allow read-only connections immediately if we're consistent already.
1645  */
1647 
1648  /*
1649  * Find the first record that logically follows the checkpoint --- it
1650  * might physically precede it, though.
1651  */
1653  {
1654  /* back up to find the record */
1655  replayTLI = RedoStartTLI;
1657  record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1658 
1659  /*
1660  * If a checkpoint record's redo pointer points back to an earlier
1661  * LSN, the record at that LSN should be an XLOG_CHECKPOINT_REDO
1662  * record.
1663  */
1664  if (record->xl_rmid != RM_XLOG_ID ||
1665  (record->xl_info & ~XLR_INFO_MASK) != XLOG_CHECKPOINT_REDO)
1666  ereport(FATAL,
1667  (errmsg("unexpected record type found at redo point %X/%X",
1669  }
1670  else
1671  {
1672  /* just have to read next record after CheckPoint */
1674  replayTLI = CheckPointTLI;
1675  record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1676  }
1677 
1678  if (record != NULL)
1679  {
1680  TimestampTz xtime;
1681  PGRUsage ru0;
1682 
1683  pg_rusage_init(&ru0);
1684 
1685  InRedo = true;
1686 
1687  RmgrStartup();
1688 
1689  ereport(LOG,
1690  (errmsg("redo starts at %X/%X",
1692 
1693  /* Prepare to report progress of the redo phase. */
1694  if (!StandbyMode)
1696 
1697  /*
1698  * main redo apply loop
1699  */
1700  do
1701  {
1702  if (!StandbyMode)
1703  ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
1705 
1706 #ifdef WAL_DEBUG
1707  if (XLOG_DEBUG ||
1708  (record->xl_rmid == RM_XACT_ID && trace_recovery_messages <= DEBUG2) ||
1709  (record->xl_rmid != RM_XACT_ID && trace_recovery_messages <= DEBUG3))
1710  {
1712 
1713  initStringInfo(&buf);
1714  appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
1717  xlog_outrec(&buf, xlogreader);
1718  appendStringInfoString(&buf, " - ");
1720  elog(LOG, "%s", buf.data);
1721  pfree(buf.data);
1722  }
1723 #endif
1724 
1725  /* Handle interrupt signals of startup process */
1727 
1728  /*
1729  * Pause WAL replay, if requested by a hot-standby session via
1730  * SetRecoveryPause().
1731  *
1732  * Note that we intentionally don't take the info_lck spinlock
1733  * here. We might therefore read a slightly stale value of the
1734  * recoveryPause flag, but it can't be very stale (no worse than
1735  * the last spinlock we did acquire). Since a pause request is a
1736  * pretty asynchronous thing anyway, possibly responding to it one
1737  * WAL record later than we otherwise would is a minor issue, so
1738  * it doesn't seem worth adding another spinlock cycle to prevent
1739  * that.
1740  */
1741  if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1743  recoveryPausesHere(false);
1744 
1745  /*
1746  * Have we reached our recovery target?
1747  */
1749  {
1750  reachedRecoveryTarget = true;
1751  break;
1752  }
1753 
1754  /*
1755  * If we've been asked to lag the primary, wait on latch until
1756  * enough time has passed.
1757  */
1759  {
1760  /*
1761  * We test for paused recovery again here. If user sets
1762  * delayed apply, it may be because they expect to pause
1763  * recovery in case of problems, so we must test again here
1764  * otherwise pausing during the delay-wait wouldn't work.
1765  */
1766  if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1768  recoveryPausesHere(false);
1769  }
1770 
1771  /*
1772  * Apply the record
1773  */
1774  ApplyWalRecord(xlogreader, record, &replayTLI);
1775 
1776  /* Exit loop if we reached inclusive recovery target */
1778  {
1779  reachedRecoveryTarget = true;
1780  break;
1781  }
1782 
1783  /* Else, try to fetch the next WAL record */
1784  record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1785  } while (record != NULL);
1786 
1787  /*
1788  * end of main redo apply loop
1789  */
1790 
1791  if (reachedRecoveryTarget)
1792  {
1793  if (!reachedConsistency)
1794  ereport(FATAL,
1795  (errmsg("requested recovery stop point is before consistent recovery point")));
1796 
1797  /*
1798  * This is the last point where we can restart recovery with a new
1799  * recovery target, if we shutdown and begin again. After this,
1800  * Resource Managers may choose to do permanent corrective actions
1801  * at end of recovery.
1802  */
1803  switch (recoveryTargetAction)
1804  {
1806 
1807  /*
1808  * exit with special return code to request shutdown of
1809  * postmaster. Log messages issued from postmaster.
1810  */
1811  proc_exit(3);
1812 
1814  SetRecoveryPause(true);
1815  recoveryPausesHere(true);
1816 
1817  /* drop into promote */
1818 
1820  break;
1821  }
1822  }
1823 
1824  RmgrCleanup();
1825 
1826  ereport(LOG,
1827  (errmsg("redo done at %X/%X system usage: %s",
1829  pg_rusage_show(&ru0))));
1830  xtime = GetLatestXTime();
1831  if (xtime)
1832  ereport(LOG,
1833  (errmsg("last completed transaction was at log time %s",
1834  timestamptz_to_str(xtime))));
1835 
1836  InRedo = false;
1837  }
1838  else
1839  {
1840  /* there are no WAL records following the checkpoint */
1841  ereport(LOG,
1842  (errmsg("redo is not required")));
1843  }
1844 
1845  /*
1846  * This check is intentionally after the above log messages that indicate
1847  * how far recovery went.
1848  */
1851  !reachedRecoveryTarget)
1852  ereport(FATAL,
1853  (errmsg("recovery ended before configured recovery target was reached")));
1854 }
void HandleStartupProcInterrupts(void)
Definition: startup.c:183
void begin_startup_progress_phase(void)
Definition: startup.c:367
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1649
#define DEBUG3
Definition: elog.h:28
#define DEBUG2
Definition: elog.h:29
bool IsUnderPostmaster
Definition: globals.c:115
int trace_recovery_messages
Definition: guc_tables.c:528
void proc_exit(int code)
Definition: ipc.c:104
#define XLOG_CHECKPOINT_REDO
Definition: pg_control.h:81
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:73
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:181
@ 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:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
RmgrId xl_rmid
Definition: xlogrecord.h:47
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
bool reachedConsistency
Definition: xlogrecovery.c:294
static bool recoveryStopsBefore(XLogReaderState *record)
int recoveryTargetAction
Definition: xlogrecovery.c:87
static bool recoveryApplyDelay(XLogReaderState *record)
static bool recoveryStopsAfter(XLogReaderState *record)
static void CheckRecoveryConsistency(void)
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)

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_info, XLogRecord::xl_rmid, XLOG_CHECKPOINT_REDO, xlog_outdesc(), xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, XLogReceiptTime, XLogRecoveryCtl, and XLR_INFO_MASK.

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4338 of file xlogrecovery.c.

4339 {
4340  /*
4341  * We check shared state each time only until a standby promotion is
4342  * triggered. We can't trigger a promotion again, so there's no need to
4343  * keep checking after the shared variable has once been seen true.
4344  */
4346  return true;
4347 
4351 
4352  return LocalPromoteIsTriggered;
4353 }
static bool LocalPromoteIsTriggered
Definition: xlogrecovery.c:182

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

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

◆ RecoveryRequiresIntParameter()

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

Definition at line 4603 of file xlogrecovery.c.

4604 {
4605  if (currValue < minValue)
4606  {
4608  {
4609  bool warned_for_promote = false;
4610 
4611  ereport(WARNING,
4612  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4613  errmsg("hot standby is not possible because of insufficient parameter settings"),
4614  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4615  param_name,
4616  currValue,
4617  minValue)));
4618 
4619  SetRecoveryPause(true);
4620 
4621  ereport(LOG,
4622  (errmsg("recovery has paused"),
4623  errdetail("If recovery is unpaused, the server will shut down."),
4624  errhint("You can then restart the server after making the necessary configuration changes.")));
4625 
4627  {
4629 
4630  if (CheckForStandbyTrigger())
4631  {
4632  if (!warned_for_promote)
4633  ereport(WARNING,
4634  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4635  errmsg("promotion is not possible because of insufficient parameter settings"),
4636 
4637  /*
4638  * Repeat the detail from above so it's easy to find
4639  * in the log.
4640  */
4641  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4642  param_name,
4643  currValue,
4644  minValue),
4645  errhint("Restart the server after making the necessary configuration changes.")));
4646  warned_for_promote = true;
4647  }
4648 
4649  /*
4650  * If recovery pause is requested then set it paused. While
4651  * we are in the loop, user might resume and pause again so
4652  * set this every time.
4653  */
4655 
4656  /*
4657  * We wait on a condition variable that will wake us as soon
4658  * as the pause ends, but we use a timeout so we can check the
4659  * above conditions periodically too.
4660  */
4662  WAIT_EVENT_RECOVERY_PAUSE);
4663  }
4665  }
4666 
4667  ereport(FATAL,
4668  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4669  errmsg("recovery aborted because of insufficient parameter settings"),
4670  /* Repeat the detail from above so it's easy to find in the log. */
4671  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4672  param_name,
4673  currValue,
4674  minValue),
4675  errhint("You can restart the server after making the necessary configuration changes.")));
4676  }
4677 }
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
#define WARNING
Definition: elog.h:36
ConditionVariable recoveryNotPausedCV
Definition: xlogrecovery.c:359
static bool CheckForStandbyTrigger(void)
static void ConfirmRecoveryPaused(void)
static bool HotStandbyActiveInReplay(void)
RecoveryPauseState GetRecoveryPauseState(void)

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

Referenced by CheckRequiredParameterValues().

◆ RemovePromoteSignalFiles()

void RemovePromoteSignalFiles ( void  )

Definition at line 4398 of file xlogrecovery.c.

4399 {
4400  unlink(PROMOTE_SIGNAL_FILE);
4401 }

References PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1558 of file xlogrecovery.c.

1559 {
1560  char recoveryPath[MAXPGPATH];
1561 
1562  /* Final update of pg_stat_recovery_prefetch. */
1564 
1565  /* Shut down xlogreader */
1566  if (readFile >= 0)
1567  {
1568  close(readFile);
1569  readFile = -1;
1570  }
1573 
1575  {
1576  /*
1577  * Since there might be a partial WAL segment named RECOVERYXLOG, get
1578  * rid of it.
1579  */
1580  snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1581  unlink(recoveryPath); /* ignore any error */
1582 
1583  /* Get rid of any remaining recovered timeline-history file, too */
1584  snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1585  unlink(recoveryPath); /* ignore any error */
1586  }
1587 
1588  /*
1589  * We don't need the latch anymore. It's not strictly necessary to disown
1590  * it, but let's do it for the sake of tidiness.
1591  */
1594 }
void DisownLatch(Latch *latch)
Definition: latch.c:490
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define XLOGDIR
void XLogPrefetcherComputeStats(XLogPrefetcher *prefetcher)
void XLogPrefetcherFree(XLogPrefetcher *prefetcher)
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:163

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

4320 {
4322  {
4323  ereport(LOG,
4324  (errmsg("WAL receiver process shutdown requested")));
4325 
4326  pendingWalRcvRestart = true;
4327  }
4328 }
bool WalRcvRunning(void)
static bool pendingWalRcvRestart
Definition: xlogrecovery.c:248
static XLogSource currentSource
Definition: xlogrecovery.c:246

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

Referenced by StartupRereadConfig().

◆ WakeupRecovery()

◆ xlog_outdesc()

void xlog_outdesc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 2241 of file xlogrecovery.c.

2242 {
2243  RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2244  uint8 info = XLogRecGetInfo(record);
2245  const char *id;
2246 
2248  appendStringInfoChar(buf, '/');
2249 
2250  id = rmgr.rm_identify(info);
2251  if (id == NULL)
2252  appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2253  else
2254  appendStringInfo(buf, "%s: ", id);
2255 
2256  rmgr.rm_desc(buf, record);
2257 }
unsigned char uint8
Definition: c.h:493
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
const char *(* rm_identify)(uint8 info)
const char * rm_name
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
static RmgrData GetRmgr(RmgrId rmid)
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:411

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, GetRmgr(), RmgrData::rm_desc, RmgrData::rm_identify, RmgrData::rm_name, XLogRecGetInfo, XLogRecGetRmid, and XLR_INFO_MASK.

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

◆ XLogRecoveryShmemInit()

void XLogRecoveryShmemInit ( void  )

Definition at line 458 of file xlogrecovery.c.

459 {
460  bool found;
461 
463  ShmemInitStruct("XLOG Recovery Ctl", XLogRecoveryShmemSize(), &found);
464  if (found)
465  return;
466  memset(XLogRecoveryCtl, 0, sizeof(XLogRecoveryCtlData));
467 
471 }
void ConditionVariableInit(ConditionVariable *cv)
void InitSharedLatch(Latch *latch)
Definition: latch.c:431
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
#define SpinLockInit(lock)
Definition: spin.h:60
Size XLogRecoveryShmemSize(void)
Definition: xlogrecovery.c:447

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

Referenced by CreateSharedMemoryAndSemaphores().

◆ XLogRecoveryShmemSize()

Size XLogRecoveryShmemSize ( void  )

Definition at line 447 of file xlogrecovery.c.

448 {
449  Size size;
450 
451  /* XLogRecoveryCtl */
452  size = sizeof(XLogRecoveryCtlData);
453 
454  return size;
455 }
size_t Size
Definition: c.h:594
struct XLogRecoveryCtlData XLogRecoveryCtlData

Referenced by CalculateShmemSize(), and XLogRecoveryShmemInit().

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4431 of file xlogrecovery.c.

4432 {
4434 }
static bool doRequestWalReceiverReply
Definition: xlogrecovery.c:185

References doRequestWalReceiverReply.

Referenced by xact_redo_commit().

Variable Documentation

◆ archiveCleanupCommand

PGDLLIMPORT char* archiveCleanupCommand
extern

Definition at line 84 of file xlogrecovery.c.

Referenced by CreateRestartPoint().

◆ PrimaryConnInfo

PGDLLIMPORT char* PrimaryConnInfo
extern

◆ PrimarySlotName

PGDLLIMPORT char* PrimarySlotName
extern

Definition at line 97 of file xlogrecovery.c.

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().

◆ reachedConsistency

◆ recovery_min_apply_delay

PGDLLIMPORT int recovery_min_apply_delay
extern

Definition at line 93 of file xlogrecovery.c.

Referenced by recoveryApplyDelay().

◆ recovery_target_time_string

PGDLLIMPORT char* recovery_target_time_string
extern

Definition at line 89 of file xlogrecovery.c.

Referenced by validateRecoveryParameters().

◆ recoveryEndCommand

PGDLLIMPORT char* recoveryEndCommand
extern

Definition at line 83 of file xlogrecovery.c.

Referenced by CleanupAfterArchiveRecovery().

◆ recoveryRestoreCommand

PGDLLIMPORT char* recoveryRestoreCommand
extern

Definition at line 82 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), and validateRecoveryParameters().

◆ recoveryTarget

◆ recoveryTargetAction

PGDLLIMPORT int recoveryTargetAction
extern

Definition at line 87 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and validateRecoveryParameters().

◆ recoveryTargetInclusive

PGDLLIMPORT bool recoveryTargetInclusive
extern

Definition at line 86 of file xlogrecovery.c.

Referenced by recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTargetLSN

PGDLLIMPORT XLogRecPtr recoveryTargetLSN
extern

◆ recoveryTargetName

PGDLLIMPORT const char* recoveryTargetName
extern

Definition at line 91 of file xlogrecovery.c.

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

◆ recoveryTargetTime

PGDLLIMPORT TimestampTz recoveryTargetTime
extern

Definition at line 90 of file xlogrecovery.c.

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

◆ recoveryTargetTimeLineGoal

◆ recoveryTargetTLI

◆ recoveryTargetTLIRequested

PGDLLIMPORT TimeLineID recoveryTargetTLIRequested
extern

Definition at line 121 of file xlogrecovery.c.

Referenced by assign_recovery_target_timeline(), and validateRecoveryParameters().

◆ recoveryTargetXid

PGDLLIMPORT TransactionId recoveryTargetXid
extern

◆ StandbyMode

◆ wal_receiver_create_temp_slot

PGDLLIMPORT bool wal_receiver_create_temp_slot
extern

Definition at line 98 of file xlogrecovery.c.

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().