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 *wasShutdownPtr, bool *haveBackupLabel, bool *haveTblspcMap)
 
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 char * PromoteTriggerFile
 
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 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:283
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:299

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and sigusr1_handler().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo* FinishWalRecovery ( void  )

Definition at line 1384 of file xlogrecovery.c.

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

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 }
TimeLineID replayEndTLI
Definition: xlogrecovery.c:345
XLogRecPtr replayEndRecPtr
Definition: xlogrecovery.c:344

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 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:256
@ XLOG_FROM_STREAM
Definition: xlogrecovery.c:211
static TimestampTz XLogReceiptTime
Definition: xlogrecovery.c:255

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 }
static bool LocalHotStandbyActive
Definition: xlogrecovery.c:173

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

Referenced by XLogWalRcvSendHSFeedback().

◆ InitWalRecovery()

void InitWalRecovery ( ControlFileData ControlFile,
bool wasShutdownPtr,
bool haveBackupLabel,
bool haveTblspcMap 
)

Definition at line 490 of file xlogrecovery.c.

492 {
493  XLogPageReadPrivate *private;
494  struct stat st;
495  bool wasShutdown;
496  XLogRecord *record;
497  DBState dbstate_at_startup;
498  bool haveTblspcMap = false;
499  bool haveBackupLabel = false;
500  CheckPoint checkPoint;
501  bool backupFromStandby = false;
502 
503  dbstate_at_startup = ControlFile->state;
504 
505  /*
506  * Initialize on the assumption we want to recover to the latest timeline
507  * that's active according to pg_control.
508  */
512  else
514 
515  /*
516  * Check for signal files, and if so set up state for offline recovery
517  */
520 
522  {
524  ereport(LOG,
525  (errmsg("entering standby mode")));
527  ereport(LOG,
528  (errmsg("starting point-in-time recovery to XID %u",
531  ereport(LOG,
532  (errmsg("starting point-in-time recovery to %s",
535  ereport(LOG,
536  (errmsg("starting point-in-time recovery to \"%s\"",
539  ereport(LOG,
540  (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
543  ereport(LOG,
544  (errmsg("starting point-in-time recovery to earliest consistent point")));
545  else
546  ereport(LOG,
547  (errmsg("starting archive recovery")));
548  }
549 
550  /*
551  * Take ownership of the wakeup latch if we're going to sleep during
552  * recovery.
553  */
556 
557  private = palloc0(sizeof(XLogPageReadPrivate));
558  xlogreader =
560  XL_ROUTINE(.page_read = &XLogPageRead,
561  .segment_open = NULL,
562  .segment_close = wal_segment_close),
563  private);
564  if (!xlogreader)
565  ereport(ERROR,
566  (errcode(ERRCODE_OUT_OF_MEMORY),
567  errmsg("out of memory"),
568  errdetail("Failed while allocating a WAL reading processor.")));
570 
571  /*
572  * Set the WAL decode buffer size. This limits how far ahead we can read
573  * in the WAL.
574  */
576 
577  /* Create a WAL prefetcher. */
579 
580  /*
581  * Allocate two page buffers dedicated to WAL consistency checks. We do
582  * it this way, rather than just making static arrays, for two reasons:
583  * (1) no need to waste the storage in most instantiations of the backend;
584  * (2) a static char array isn't guaranteed to have any particular
585  * alignment, whereas palloc() will provide MAXALIGN'd storage.
586  */
587  replay_image_masked = (char *) palloc(BLCKSZ);
588  primary_image_masked = (char *) palloc(BLCKSZ);
589 
591  &backupFromStandby))
592  {
593  List *tablespaces = NIL;
594 
595  /*
596  * Archive recovery was requested, and thanks to the backup label
597  * file, we know how far we need to replay to reach consistency. Enter
598  * archive recovery directly.
599  */
600  InArchiveRecovery = true;
602  StandbyMode = true;
603 
604  /*
605  * When a backup_label file is present, we want to roll forward from
606  * the checkpoint it identifies, rather than using pg_control.
607  */
609  CheckPointTLI);
610  if (record != NULL)
611  {
612  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
613  wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
614  ereport(DEBUG1,
615  (errmsg_internal("checkpoint record is at %X/%X",
617  InRecovery = true; /* force recovery even if SHUTDOWNED */
618 
619  /*
620  * Make sure that REDO location exists. This may not be the case
621  * if there was a crash during an online backup, which left a
622  * backup_label around that references a WAL segment that's
623  * already been archived.
624  */
625  if (checkPoint.redo < CheckPointLoc)
626  {
628  if (!ReadRecord(xlogprefetcher, LOG, false,
629  checkPoint.ThisTimeLineID))
630  ereport(FATAL,
631  (errmsg("could not find redo location referenced by checkpoint record"),
632  errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
633  "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
634  "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
635  DataDir, DataDir, DataDir)));
636  }
637  }
638  else
639  {
640  ereport(FATAL,
641  (errmsg("could not locate required checkpoint record"),
642  errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
643  "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
644  "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
645  DataDir, DataDir, DataDir)));
646  wasShutdown = false; /* keep compiler quiet */
647  }
648 
649  /* Read the tablespace_map file if present and create symlinks. */
650  if (read_tablespace_map(&tablespaces))
651  {
652  ListCell *lc;
653 
654  foreach(lc, tablespaces)
655  {
656  tablespaceinfo *ti = lfirst(lc);
657  char *linkloc;
658 
659  linkloc = psprintf("pg_tblspc/%s", ti->oid);
660 
661  /*
662  * Remove the existing symlink if any and Create the symlink
663  * under PGDATA.
664  */
665  remove_tablespace_symlink(linkloc);
666 
667  if (symlink(ti->path, linkloc) < 0)
668  ereport(ERROR,
670  errmsg("could not create symbolic link \"%s\": %m",
671  linkloc)));
672 
673  pfree(ti->oid);
674  pfree(ti->path);
675  pfree(ti);
676  }
677 
678  /* tell the caller to delete it later */
679  haveTblspcMap = true;
680  }
681 
682  /* tell the caller to delete it later */
683  haveBackupLabel = true;
684  }
685  else
686  {
687  /*
688  * If tablespace_map file is present without backup_label file, there
689  * is no use of such file. There is no harm in retaining it, but it
690  * is better to get rid of the map file so that we don't have any
691  * redundant file in data directory and it will avoid any sort of
692  * confusion. It seems prudent though to just rename the file out of
693  * the way rather than delete it completely, also we ignore any error
694  * that occurs in rename operation as even if map file is present
695  * without backup_label file, it is harmless.
696  */
697  if (stat(TABLESPACE_MAP, &st) == 0)
698  {
699  unlink(TABLESPACE_MAP_OLD);
701  ereport(LOG,
702  (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
704  errdetail("File \"%s\" was renamed to \"%s\".",
706  else
707  ereport(LOG,
708  (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
710  errdetail("Could not rename file \"%s\" to \"%s\": %m.",
712  }
713 
714  /*
715  * It's possible that archive recovery was requested, but we don't
716  * know how far we need to replay the WAL before we reach consistency.
717  * This can happen for example if a base backup is taken from a
718  * running server using an atomic filesystem snapshot, without calling
719  * pg_start/stop_backup. Or if you just kill a running primary server
720  * and put it into archive recovery by creating a recovery signal
721  * file.
722  *
723  * Our strategy in that case is to perform crash recovery first,
724  * replaying all the WAL present in pg_wal, and only enter archive
725  * recovery after that.
726  *
727  * But usually we already know how far we need to replay the WAL (up
728  * to minRecoveryPoint, up to backupEndPoint, or until we see an
729  * end-of-backup record), and we can enter archive recovery directly.
730  */
736  {
737  InArchiveRecovery = true;
739  StandbyMode = true;
740  }
741 
742  /* Get the last valid checkpoint record. */
748  CheckPointTLI);
749  if (record != NULL)
750  {
751  ereport(DEBUG1,
752  (errmsg_internal("checkpoint record is at %X/%X",
754  }
755  else
756  {
757  /*
758  * We used to attempt to go back to a secondary checkpoint record
759  * here, but only when not in standby mode. We now just fail if we
760  * can't read the last checkpoint because this allows us to
761  * simplify processing around checkpoints.
762  */
763  ereport(PANIC,
764  (errmsg("could not locate a valid checkpoint record")));
765  }
766  memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
767  wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
768  }
769 
770  /*
771  * If the location of the checkpoint record is not on the expected
772  * timeline in the history of the requested timeline, we cannot proceed:
773  * the backup is not part of the history of the requested timeline.
774  */
775  Assert(expectedTLEs); /* was initialized by reading checkpoint
776  * record */
779  {
780  XLogRecPtr switchpoint;
781 
782  /*
783  * tliSwitchPoint will throw an error if the checkpoint's timeline is
784  * not in expectedTLEs at all.
785  */
787  ereport(FATAL,
788  (errmsg("requested timeline %u is not a child of this server's history",
790  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.",
793  LSN_FORMAT_ARGS(switchpoint))));
794  }
795 
796  /*
797  * The min recovery point should be part of the requested timeline's
798  * history, too.
799  */
803  ereport(FATAL,
804  (errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
808 
809  ereport(DEBUG1,
810  (errmsg_internal("redo record is at %X/%X; shutdown %s",
811  LSN_FORMAT_ARGS(checkPoint.redo),
812  wasShutdown ? "true" : "false")));
813  ereport(DEBUG1,
814  (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
815  U64FromFullTransactionId(checkPoint.nextXid),
816  checkPoint.nextOid)));
817  ereport(DEBUG1,
818  (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
819  checkPoint.nextMulti, checkPoint.nextMultiOffset)));
820  ereport(DEBUG1,
821  (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
822  checkPoint.oldestXid, checkPoint.oldestXidDB)));
823  ereport(DEBUG1,
824  (errmsg_internal("oldest MultiXactId: %u, in database %u",
825  checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
826  ereport(DEBUG1,
827  (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
828  checkPoint.oldestCommitTsXid,
829  checkPoint.newestCommitTsXid)));
831  ereport(PANIC,
832  (errmsg("invalid next transaction ID")));
833 
834  /* sanity check */
835  if (checkPoint.redo > CheckPointLoc)
836  ereport(PANIC,
837  (errmsg("invalid redo in checkpoint record")));
838 
839  /*
840  * Check whether we need to force recovery from WAL. If it appears to
841  * have been a clean shutdown and we did not have a recovery signal file,
842  * then assume no recovery needed.
843  */
844  if (checkPoint.redo < CheckPointLoc)
845  {
846  if (wasShutdown)
847  ereport(PANIC,
848  (errmsg("invalid redo record in shutdown checkpoint")));
849  InRecovery = true;
850  }
851  else if (ControlFile->state != DB_SHUTDOWNED)
852  InRecovery = true;
853  else if (ArchiveRecoveryRequested)
854  {
855  /* force recovery due to presence of recovery signal file */
856  InRecovery = true;
857  }
858 
859  /*
860  * If recovery is needed, update our in-memory copy of pg_control to show
861  * that we are recovering and to show the selected checkpoint as the place
862  * we are starting from. We also mark pg_control with any minimum recovery
863  * stop point obtained from a backup history file.
864  *
865  * We don't write the changes to disk yet, though. Only do that after
866  * initializing various subsystems.
867  */
868  if (InRecovery)
869  {
870  if (InArchiveRecovery)
871  {
873  }
874  else
875  {
876  ereport(LOG,
877  (errmsg("database system was not properly shut down; "
878  "automatic recovery in progress")));
880  ereport(LOG,
881  (errmsg("crash recovery starts in timeline %u "
882  "and has target timeline %u",
886  }
888  ControlFile->checkPointCopy = checkPoint;
889  if (InArchiveRecovery)
890  {
891  /* initialize minRecoveryPoint if not set yet */
892  if (ControlFile->minRecoveryPoint < checkPoint.redo)
893  {
894  ControlFile->minRecoveryPoint = checkPoint.redo;
896  }
897  }
898 
899  /*
900  * Set backupStartPoint if we're starting recovery from a base backup.
901  *
902  * Also set backupEndPoint and use minRecoveryPoint as the backup end
903  * location if we're starting recovery from a base backup which was
904  * taken from a standby. In this case, the database system status in
905  * pg_control must indicate that the database was already in recovery.
906  * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
907  * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
908  * before reaching this point; e.g. because restore_command or
909  * primary_conninfo were faulty.
910  *
911  * Any other state indicates that the backup somehow became corrupted
912  * and we can't sensibly continue with recovery.
913  */
914  if (haveBackupLabel)
915  {
916  ControlFile->backupStartPoint = checkPoint.redo;
918 
919  if (backupFromStandby)
920  {
921  if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
922  dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
923  ereport(FATAL,
924  (errmsg("backup_label contains data inconsistent with control file"),
925  errhint("This means that the backup is corrupted and you will "
926  "have to use another backup for recovery.")));
928  }
929  }
930  }
931 
932  /* remember these, so that we know when we have reached consistency */
936  if (InArchiveRecovery)
937  {
940  }
941  else
942  {
945  }
946 
947  /*
948  * Start recovery assuming that the final record isn't lost.
949  */
952 
953  *wasShutdown_ptr = wasShutdown;
954  *haveBackupLabel_ptr = haveBackupLabel;
955  *haveTblspcMap_ptr = haveTblspcMap;
956 }
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
Definition: timeline.c:552
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition: timeline.c:580
void remove_tablespace_symlink(const char *linkloc)
Definition: tablespace.c:929
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1768
#define UINT64_FORMAT
Definition: c.h:484
int errmsg_internal(const char *fmt,...)
Definition: elog.c:991
int errcode_for_file_access(void)
Definition: elog.c:716
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define LOG
Definition: elog.h:25
#define FATAL
Definition: elog.h:35
#define DEBUG1
Definition: elog.h:24
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:699
char * DataDir
Definition: globals.c:66
void OwnLatch(Latch *latch)
Definition: latch.c:422
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc0(Size size)
Definition: mcxt.c:1099
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 XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
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: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:51
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:137
static ControlFileData * ControlFile
Definition: xlog.c:566
#define TABLESPACE_MAP_OLD
Definition: xlog.h:296
#define TABLESPACE_MAP
Definition: xlog.h:295
#define BACKUP_LABEL_FILE
Definition: xlog.h:292
#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:413
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
static bool backupEndRequired
Definition: xlogrecovery.c:280
const char * recoveryTargetName
Definition: xlogrecovery.c:87
static XLogRecPtr minRecoveryPoint
Definition: xlogrecovery.c:275
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static XLogRecPtr backupEndPoint
Definition: xlogrecovery.c:279
static void validateRecoveryParameters(void)
static TimeLineID RedoStartTLI
Definition: xlogrecovery.c:167
static void readRecoverySignalFile(void)
Definition: xlogrecovery.c:966
XLogRecPtr recoveryTargetLSN
Definition: xlogrecovery.c:88
RecoveryTargetType recoveryTarget
Definition: xlogrecovery.c:81
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:120
static char * primary_image_masked
Definition: xlogrecovery.c:295
static TimeLineID minRecoveryPointTLI
Definition: xlogrecovery.c:276
TransactionId recoveryTargetXid
Definition: xlogrecovery.c:84
static char * replay_image_masked
Definition: xlogrecovery.c:294
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:119
static XLogRecPtr RedoStartLSN
Definition: xlogrecovery.c:166
TimestampTz recoveryTargetTime
Definition: xlogrecovery.c:86
static bool StandbyModeRequested
Definition: xlogrecovery.c:143
static XLogRecPtr backupStartPoint
Definition: xlogrecovery.c:278
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, int whichChkpt, bool report, TimeLineID replayTLI)
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:856

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

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

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4245 of file xlogrecovery.c.

4246 {
4247  /*
4248  * We check shared state each time only until a standby promotion is
4249  * triggered. We can't trigger a promotion again, so there's no need to
4250  * keep checking after the shared variable has once been seen true.
4251  */
4253  return true;
4254 
4258 
4259  return LocalPromoteIsTriggered;
4260 }
static bool LocalPromoteIsTriggered
Definition: xlogrecovery.c:179

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 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 }
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableCancelSleep(void)
#define WARNING
Definition: elog.h:30
ConditionVariable recoveryNotPausedCV
Definition: xlogrecovery.c:356
@ WAIT_EVENT_RECOVERY_PAUSE
Definition: wait_event.h:123
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(), WAIT_EVENT_RECOVERY_PAUSE, WARNING, and XLogRecoveryCtl.

Referenced by CheckRequiredParameterValues().

◆ 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().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1519 of file xlogrecovery.c.

1520 {
1521  char recoveryPath[MAXPGPATH];
1522 
1523  /* Final update of pg_stat_recovery_prefetch. */
1525 
1526  /* Shut down xlogreader */
1527  if (readFile >= 0)
1528  {
1529  close(readFile);
1530  readFile = -1;
1531  }
1534 
1536  {
1537  /*
1538  * Since there might be a partial WAL segment named RECOVERYXLOG, get
1539  * rid of it.
1540  */
1541  snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1542  unlink(recoveryPath); /* ignore any error */
1543 
1544  /* Get rid of any remaining recovered timeline-history file, too */
1545  snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1546  unlink(recoveryPath); /* ignore any error */
1547  }
1548 
1549  /*
1550  * We don't need the latch anymore. It's not strictly necessary to disown
1551  * it, but let's do it for the sake of tidiness.
1552  */
1555 }
void DisownLatch(Latch *latch)
Definition: latch.c:448
#define MAXPGPATH
#define snprintf
Definition: port.h:225
#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 4226 of file xlogrecovery.c.

4227 {
4229  {
4230  ereport(LOG,
4231  (errmsg("WAL receiver process shutdown requested")));
4232 
4233  pendingWalRcvRestart = true;
4234  }
4235 }
bool WalRcvRunning(void)
static bool pendingWalRcvRestart
Definition: xlogrecovery.c:245
static XLogSource currentSource
Definition: xlogrecovery.c:243

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

2124 {
2125  RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2126  uint8 info = XLogRecGetInfo(record);
2127  const char *id;
2128 
2130  appendStringInfoChar(buf, '/');
2131 
2132  id = rmgr.rm_identify(info);
2133  if (id == NULL)
2134  appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2135  else
2136  appendStringInfo(buf, "%s: ", id);
2137 
2138  rmgr.rm_desc(buf, record);
2139 }
unsigned char uint8
Definition: c.h:439
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
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:408
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:409

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

455 {
456  bool found;
457 
459  ShmemInitStruct("XLOG Recovery Ctl", XLogRecoveryShmemSize(), &found);
460  if (found)
461  return;
462  memset(XLogRecoveryCtl, 0, sizeof(XLogRecoveryCtlData));
463 
467 }
void ConditionVariableInit(ConditionVariable *cv)
void InitSharedLatch(Latch *latch)
Definition: latch.c:389
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:443

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

444 {
445  Size size;
446 
447  /* XLogRecoveryCtl */
448  size = sizeof(XLogRecoveryCtlData);
449 
450  return size;
451 }
size_t Size
Definition: c.h:540
struct XLogRecoveryCtlData XLogRecoveryCtlData

Referenced by CalculateShmemSize(), and XLogRecoveryShmemInit().

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4358 of file xlogrecovery.c.

4359 {
4361 }
static bool doRequestWalReceiverReply
Definition: xlogrecovery.c:182

References doRequestWalReceiverReply.

Referenced by xact_redo_commit().

Variable Documentation

◆ archiveCleanupCommand

PGDLLIMPORT char* archiveCleanupCommand
extern

Definition at line 80 of file xlogrecovery.c.

Referenced by CreateRestartPoint().

◆ PrimaryConnInfo

PGDLLIMPORT char* PrimaryConnInfo
extern

◆ PrimarySlotName

PGDLLIMPORT char* PrimarySlotName
extern

Definition at line 93 of file xlogrecovery.c.

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().

◆ PromoteTriggerFile

PGDLLIMPORT char* PromoteTriggerFile
extern

Definition at line 94 of file xlogrecovery.c.

Referenced by CheckForStandbyTrigger().

◆ reachedConsistency

◆ recovery_min_apply_delay

PGDLLIMPORT int recovery_min_apply_delay
extern

Definition at line 89 of file xlogrecovery.c.

Referenced by recoveryApplyDelay().

◆ recovery_target_time_string

PGDLLIMPORT char* recovery_target_time_string
extern

Definition at line 85 of file xlogrecovery.c.

Referenced by validateRecoveryParameters().

◆ recoveryEndCommand

PGDLLIMPORT char* recoveryEndCommand
extern

Definition at line 79 of file xlogrecovery.c.

Referenced by CleanupAfterArchiveRecovery().

◆ recoveryRestoreCommand

PGDLLIMPORT char* recoveryRestoreCommand
extern

Definition at line 78 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), and validateRecoveryParameters().

◆ recoveryTarget

◆ recoveryTargetAction

PGDLLIMPORT int recoveryTargetAction
extern

Definition at line 83 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and validateRecoveryParameters().

◆ recoveryTargetInclusive

PGDLLIMPORT bool recoveryTargetInclusive
extern

Definition at line 82 of file xlogrecovery.c.

Referenced by recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTargetLSN

PGDLLIMPORT XLogRecPtr recoveryTargetLSN
extern

◆ recoveryTargetName

PGDLLIMPORT const char* recoveryTargetName
extern

Definition at line 87 of file xlogrecovery.c.

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

◆ recoveryTargetTime

PGDLLIMPORT TimestampTz recoveryTargetTime
extern

Definition at line 86 of file xlogrecovery.c.

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

◆ recoveryTargetTimeLineGoal

◆ recoveryTargetTLI

◆ recoveryTargetTLIRequested

PGDLLIMPORT TimeLineID recoveryTargetTLIRequested
extern

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

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().