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

4342 {
4343  struct stat stat_buf;
4344 
4345  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4346  return true;
4347 
4348  return false;
4349 }
#define stat
Definition: win32_port.h:286
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:297

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo* FinishWalRecovery ( void  )

Definition at line 1387 of file xlogrecovery.c.

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

4505 {
4506  TimestampTz xtime;
4507 
4511 
4512  return xtime;
4513 }
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 4440 of file xlogrecovery.c.

4441 {
4442  XLogRecPtr recptr;
4443  TimeLineID tli;
4444 
4446  recptr = XLogRecoveryCtl->replayEndRecPtr;
4449 
4450  if (replayEndTLI)
4451  *replayEndTLI = tli;
4452  return recptr;
4453 }
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 4520 of file xlogrecovery.c.

4521 {
4522  /*
4523  * This must be executed in the startup process, since we don't export the
4524  * relevant state to shared memory.
4525  */
4526  Assert(InRecovery);
4527 
4528  *rtime = XLogReceiptTime;
4529  *fromStream = (XLogReceiptSource == XLOG_FROM_STREAM);
4530 }
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 4380 of file xlogrecovery.c.

4381 {
4382  /*
4383  * We check shared state each time only until Hot Standby is active. We
4384  * can't de-activate Hot Standby, so there's no need to keep checking
4385  * after the shared variable has once been seen true.
4386  */
4388  return true;
4389  else
4390  {
4391  /* spinlock is essential on machines with weak memory ordering! */
4395 
4396  return LocalHotStandbyActive;
4397  }
4398 }
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 493 of file xlogrecovery.c.

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

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

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1566 of file xlogrecovery.c.

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

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4272 of file xlogrecovery.c.

4273 {
4274  /*
4275  * We check shared state each time only until a standby promotion is
4276  * triggered. We can't trigger a promotion again, so there's no need to
4277  * keep checking after the shared variable has once been seen true.
4278  */
4280  return true;
4281 
4285 
4286  return LocalPromoteIsTriggered;
4287 }
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 4537 of file xlogrecovery.c.

4538 {
4539  if (currValue < minValue)
4540  {
4542  {
4543  bool warned_for_promote = false;
4544 
4545  ereport(WARNING,
4546  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4547  errmsg("hot standby is not possible because of insufficient parameter settings"),
4548  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4549  param_name,
4550  currValue,
4551  minValue)));
4552 
4553  SetRecoveryPause(true);
4554 
4555  ereport(LOG,
4556  (errmsg("recovery has paused"),
4557  errdetail("If recovery is unpaused, the server will shut down."),
4558  errhint("You can then restart the server after making the necessary configuration changes.")));
4559 
4561  {
4563 
4564  if (CheckForStandbyTrigger())
4565  {
4566  if (!warned_for_promote)
4567  ereport(WARNING,
4568  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4569  errmsg("promotion is not possible because of insufficient parameter settings"),
4570 
4571  /*
4572  * Repeat the detail from above so it's easy to find
4573  * in the log.
4574  */
4575  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4576  param_name,
4577  currValue,
4578  minValue),
4579  errhint("Restart the server after making the necessary configuration changes.")));
4580  warned_for_promote = true;
4581  }
4582 
4583  /*
4584  * If recovery pause is requested then set it paused. While
4585  * we are in the loop, user might resume and pause again so
4586  * set this every time.
4587  */
4589 
4590  /*
4591  * We wait on a condition variable that will wake us as soon
4592  * as the pause ends, but we use a timeout so we can check the
4593  * above conditions periodically too.
4594  */
4597  }
4599  }
4600 
4601  ereport(FATAL,
4602  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4603  errmsg("recovery aborted because of insufficient parameter settings"),
4604  /* Repeat the detail from above so it's easy to find in the log. */
4605  errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4606  param_name,
4607  currValue,
4608  minValue),
4609  errhint("You can restart the server after making the necessary configuration changes.")));
4610  }
4611 }
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableCancelSleep(void)
#define WARNING
Definition: elog.h:36
ConditionVariable recoveryNotPausedCV
Definition: xlogrecovery.c:359
@ WAIT_EVENT_RECOVERY_PAUSE
Definition: wait_event.h:125
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 4332 of file xlogrecovery.c.

4333 {
4334  unlink(PROMOTE_SIGNAL_FILE);
4335 }

References PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1522 of file xlogrecovery.c.

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

4254 {
4256  {
4257  ereport(LOG,
4258  (errmsg("WAL receiver process shutdown requested")));
4259 
4260  pendingWalRcvRestart = true;
4261  }
4262 }
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 2175 of file xlogrecovery.c.

2176 {
2177  RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2178  uint8 info = XLogRecGetInfo(record);
2179  const char *id;
2180 
2182  appendStringInfoChar(buf, '/');
2183 
2184  id = rmgr.rm_identify(info);
2185  if (id == NULL)
2186  appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2187  else
2188  appendStringInfo(buf, "%s: ", id);
2189 
2190  rmgr.rm_desc(buf, record);
2191 }
unsigned char uint8
Definition: c.h:488
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:409
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:410

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

458 {
459  bool found;
460 
462  ShmemInitStruct("XLOG Recovery Ctl", XLogRecoveryShmemSize(), &found);
463  if (found)
464  return;
465  memset(XLogRecoveryCtl, 0, sizeof(XLogRecoveryCtlData));
466 
470 }
void ConditionVariableInit(ConditionVariable *cv)
void InitSharedLatch(Latch *latch)
Definition: latch.c:405
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:446

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

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

Referenced by CalculateShmemSize(), and XLogRecoveryShmemInit().

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4365 of file xlogrecovery.c.

4366 {
4368 }
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(), and shell_archive_cleanup().

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

◆ recoveryRestoreCommand

PGDLLIMPORT char* recoveryRestoreCommand
extern

Definition at line 82 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), shell_restore(), 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().