PostgreSQL Source Code  git master
xlog.h File Reference
#include "access/xlogbackup.h"
#include "access/xlogdefs.h"
#include "datatype/timestamp.h"
#include "lib/stringinfo.h"
#include "nodes/pg_list.h"
Include dependency graph for xlog.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  CheckpointStatsData
 

Macros

#define SYNC_METHOD_FSYNC   0
 
#define SYNC_METHOD_FDATASYNC   1
 
#define SYNC_METHOD_OPEN   2 /* for O_SYNC */
 
#define SYNC_METHOD_FSYNC_WRITETHROUGH   3
 
#define SYNC_METHOD_OPEN_DSYNC   4 /* for O_DSYNC */
 
#define XLogArchivingActive()    (AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode > ARCHIVE_MODE_OFF)
 
#define XLogArchivingAlways()    (AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode == ARCHIVE_MODE_ALWAYS)
 
#define XLogIsNeeded()   (wal_level >= WAL_LEVEL_REPLICA)
 
#define XLogHintBitIsNeeded()   (DataChecksumsEnabled() || wal_log_hints)
 
#define XLogStandbyInfoActive()   (wal_level >= WAL_LEVEL_REPLICA)
 
#define XLogLogicalInfoActive()   (wal_level >= WAL_LEVEL_LOGICAL)
 
#define CHECKPOINT_IS_SHUTDOWN   0x0001 /* Checkpoint is for shutdown */
 
#define CHECKPOINT_END_OF_RECOVERY
 
#define CHECKPOINT_IMMEDIATE   0x0004 /* Do it without delays */
 
#define CHECKPOINT_FORCE   0x0008 /* Force even if no activity */
 
#define CHECKPOINT_FLUSH_ALL
 
#define CHECKPOINT_WAIT   0x0020 /* Wait for completion */
 
#define CHECKPOINT_REQUESTED   0x0040 /* Checkpoint request has been made */
 
#define CHECKPOINT_CAUSE_XLOG   0x0080 /* XLOG consumption */
 
#define CHECKPOINT_CAUSE_TIME   0x0100 /* Elapsed time */
 
#define XLOG_INCLUDE_ORIGIN   0x01 /* include the replication origin */
 
#define XLOG_MARK_UNIMPORTANT   0x02 /* record not important for durability */
 
#define RECOVERY_SIGNAL_FILE   "recovery.signal"
 
#define STANDBY_SIGNAL_FILE   "standby.signal"
 
#define BACKUP_LABEL_FILE   "backup_label"
 
#define BACKUP_LABEL_OLD   "backup_label.old"
 
#define TABLESPACE_MAP   "tablespace_map"
 
#define TABLESPACE_MAP_OLD   "tablespace_map.old"
 
#define PROMOTE_SIGNAL_FILE   "promote"
 

Typedefs

typedef enum ArchiveMode ArchiveMode
 
typedef enum WalLevel WalLevel
 
typedef enum WalCompression WalCompression
 
typedef enum RecoveryState RecoveryState
 
typedef struct CheckpointStatsData CheckpointStatsData
 
typedef enum WALAvailability WALAvailability
 
typedef enum SessionBackupState SessionBackupState
 

Enumerations

enum  ArchiveMode { ARCHIVE_MODE_OFF = 0 , ARCHIVE_MODE_ON , ARCHIVE_MODE_ALWAYS }
 
enum  WalLevel { WAL_LEVEL_MINIMAL = 0 , WAL_LEVEL_REPLICA , WAL_LEVEL_LOGICAL }
 
enum  WalCompression { WAL_COMPRESSION_NONE = 0 , WAL_COMPRESSION_PGLZ , WAL_COMPRESSION_LZ4 , WAL_COMPRESSION_ZSTD }
 
enum  RecoveryState { RECOVERY_STATE_CRASH = 0 , RECOVERY_STATE_ARCHIVE , RECOVERY_STATE_DONE }
 
enum  WALAvailability {
  WALAVAIL_INVALID_LSN , WALAVAIL_RESERVED , WALAVAIL_EXTENDED , WALAVAIL_UNRESERVED ,
  WALAVAIL_REMOVED
}
 
enum  SessionBackupState { SESSION_BACKUP_NONE , SESSION_BACKUP_RUNNING }
 

Functions

XLogRecPtr XLogInsertRecord (struct XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, bool topxid_included)
 
void XLogFlush (XLogRecPtr record)
 
bool XLogBackgroundFlush (void)
 
bool XLogNeedsFlush (XLogRecPtr record)
 
int XLogFileInit (XLogSegNo logsegno, TimeLineID logtli)
 
int XLogFileOpen (XLogSegNo segno, TimeLineID tli)
 
void CheckXLogRemoved (XLogSegNo segno, TimeLineID tli)
 
XLogSegNo XLogGetLastRemovedSegno (void)
 
void XLogSetAsyncXactLSN (XLogRecPtr asyncXactLSN)
 
void XLogSetReplicationSlotMinimumLSN (XLogRecPtr lsn)
 
void xlog_redo (struct XLogReaderState *record)
 
void xlog_desc (StringInfo buf, struct XLogReaderState *record)
 
const char * xlog_identify (uint8 info)
 
void issue_xlog_fsync (int fd, XLogSegNo segno, TimeLineID tli)
 
bool RecoveryInProgress (void)
 
RecoveryState GetRecoveryState (void)
 
bool XLogInsertAllowed (void)
 
XLogRecPtr GetXLogInsertRecPtr (void)
 
XLogRecPtr GetXLogWriteRecPtr (void)
 
uint64 GetSystemIdentifier (void)
 
char * GetMockAuthenticationNonce (void)
 
bool DataChecksumsEnabled (void)
 
XLogRecPtr GetFakeLSNForUnloggedRel (void)
 
Size XLOGShmemSize (void)
 
void XLOGShmemInit (void)
 
void BootStrapXLOG (void)
 
void InitializeWalConsistencyChecking (void)
 
void LocalProcessControlFile (bool reset)
 
WalLevel GetActiveWalLevelOnStandby (void)
 
void StartupXLOG (void)
 
void ShutdownXLOG (int code, Datum arg)
 
void CreateCheckPoint (int flags)
 
bool CreateRestartPoint (int flags)
 
WALAvailability GetWALAvailability (XLogRecPtr targetLSN)
 
void XLogPutNextOid (Oid nextOid)
 
XLogRecPtr XLogRestorePoint (const char *rpName)
 
void UpdateFullPageWrites (void)
 
void GetFullPageWriteInfo (XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
 
XLogRecPtr GetRedoRecPtr (void)
 
XLogRecPtr GetInsertRecPtr (void)
 
XLogRecPtr GetFlushRecPtr (TimeLineID *insertTLI)
 
TimeLineID GetWALInsertionTimeLine (void)
 
XLogRecPtr GetLastImportantRecPtr (void)
 
void SetWalWriterSleeping (bool sleeping)
 
void RemoveNonParentXlogFiles (XLogRecPtr switchpoint, TimeLineID newTLI)
 
bool XLogCheckpointNeeded (XLogSegNo new_segno)
 
void SwitchIntoArchiveRecovery (XLogRecPtr EndRecPtr, TimeLineID replayTLI)
 
void ReachedEndOfBackup (XLogRecPtr EndRecPtr, TimeLineID tli)
 
void SetInstallXLogFileSegmentActive (void)
 
bool IsInstallXLogFileSegmentActive (void)
 
void XLogShutdownWalRcv (void)
 
void do_pg_backup_start (const char *backupidstr, bool fast, List **tablespaces, BackupState *state, StringInfo tblspcmapfile)
 
void do_pg_backup_stop (BackupState *state, bool waitforarchive)
 
void do_pg_abort_backup (int code, Datum arg)
 
void register_persistent_abort_backup_handler (void)
 
SessionBackupState get_backup_status (void)
 

Variables

PGDLLIMPORT int sync_method
 
PGDLLIMPORT XLogRecPtr ProcLastRecPtr
 
PGDLLIMPORT XLogRecPtr XactLastRecEnd
 
PGDLLIMPORT XLogRecPtr XactLastCommitEnd
 
PGDLLIMPORT int wal_segment_size
 
PGDLLIMPORT int min_wal_size_mb
 
PGDLLIMPORT int max_wal_size_mb
 
PGDLLIMPORT int wal_keep_size_mb
 
PGDLLIMPORT int max_slot_wal_keep_size_mb
 
PGDLLIMPORT int XLOGbuffers
 
PGDLLIMPORT int XLogArchiveTimeout
 
PGDLLIMPORT int wal_retrieve_retry_interval
 
PGDLLIMPORT char * XLogArchiveCommand
 
PGDLLIMPORT bool EnableHotStandby
 
PGDLLIMPORT bool fullPageWrites
 
PGDLLIMPORT bool wal_log_hints
 
PGDLLIMPORT int wal_compression
 
PGDLLIMPORT bool wal_init_zero
 
PGDLLIMPORT bool wal_recycle
 
PGDLLIMPORT boolwal_consistency_checking
 
PGDLLIMPORT char * wal_consistency_checking_string
 
PGDLLIMPORT bool log_checkpoints
 
PGDLLIMPORT bool track_wal_io_timing
 
PGDLLIMPORT int wal_decode_buffer_size
 
PGDLLIMPORT int CheckPointSegments
 
PGDLLIMPORT int XLogArchiveMode
 
PGDLLIMPORT int wal_level
 
PGDLLIMPORT CheckpointStatsData CheckpointStats
 

Macro Definition Documentation

◆ BACKUP_LABEL_FILE

#define BACKUP_LABEL_FILE   "backup_label"

Definition at line 291 of file xlog.h.

◆ BACKUP_LABEL_OLD

#define BACKUP_LABEL_OLD   "backup_label.old"

Definition at line 292 of file xlog.h.

◆ CHECKPOINT_CAUSE_TIME

#define CHECKPOINT_CAUSE_TIME   0x0100 /* Elapsed time */

Definition at line 144 of file xlog.h.

◆ CHECKPOINT_CAUSE_XLOG

#define CHECKPOINT_CAUSE_XLOG   0x0080 /* XLOG consumption */

Definition at line 143 of file xlog.h.

◆ CHECKPOINT_END_OF_RECOVERY

#define CHECKPOINT_END_OF_RECOVERY
Value:
0x0002 /* Like shutdown checkpoint, but
* issued at end of WAL recovery */

Definition at line 135 of file xlog.h.

◆ CHECKPOINT_FLUSH_ALL

#define CHECKPOINT_FLUSH_ALL
Value:
0x0010 /* Flush all pages, including those
* belonging to unlogged tables */

Definition at line 138 of file xlog.h.

◆ CHECKPOINT_FORCE

#define CHECKPOINT_FORCE   0x0008 /* Force even if no activity */

Definition at line 137 of file xlog.h.

◆ CHECKPOINT_IMMEDIATE

#define CHECKPOINT_IMMEDIATE   0x0004 /* Do it without delays */

Definition at line 136 of file xlog.h.

◆ CHECKPOINT_IS_SHUTDOWN

#define CHECKPOINT_IS_SHUTDOWN   0x0001 /* Checkpoint is for shutdown */

Definition at line 134 of file xlog.h.

◆ CHECKPOINT_REQUESTED

#define CHECKPOINT_REQUESTED   0x0040 /* Checkpoint request has been made */

Definition at line 141 of file xlog.h.

◆ CHECKPOINT_WAIT

#define CHECKPOINT_WAIT   0x0020 /* Wait for completion */

Definition at line 140 of file xlog.h.

◆ PROMOTE_SIGNAL_FILE

#define PROMOTE_SIGNAL_FILE   "promote"

Definition at line 298 of file xlog.h.

◆ RECOVERY_SIGNAL_FILE

#define RECOVERY_SIGNAL_FILE   "recovery.signal"

Definition at line 289 of file xlog.h.

◆ STANDBY_SIGNAL_FILE

#define STANDBY_SIGNAL_FILE   "standby.signal"

Definition at line 290 of file xlog.h.

◆ SYNC_METHOD_FDATASYNC

#define SYNC_METHOD_FDATASYNC   1

Definition at line 23 of file xlog.h.

◆ SYNC_METHOD_FSYNC

#define SYNC_METHOD_FSYNC   0

Definition at line 22 of file xlog.h.

◆ SYNC_METHOD_FSYNC_WRITETHROUGH

#define SYNC_METHOD_FSYNC_WRITETHROUGH   3

Definition at line 25 of file xlog.h.

◆ SYNC_METHOD_OPEN

#define SYNC_METHOD_OPEN   2 /* for O_SYNC */

Definition at line 24 of file xlog.h.

◆ SYNC_METHOD_OPEN_DSYNC

#define SYNC_METHOD_OPEN_DSYNC   4 /* for O_DSYNC */

Definition at line 26 of file xlog.h.

◆ TABLESPACE_MAP

#define TABLESPACE_MAP   "tablespace_map"

Definition at line 294 of file xlog.h.

◆ TABLESPACE_MAP_OLD

#define TABLESPACE_MAP_OLD   "tablespace_map.old"

Definition at line 295 of file xlog.h.

◆ XLOG_INCLUDE_ORIGIN

#define XLOG_INCLUDE_ORIGIN   0x01 /* include the replication origin */

Definition at line 149 of file xlog.h.

◆ XLOG_MARK_UNIMPORTANT

#define XLOG_MARK_UNIMPORTANT   0x02 /* record not important for durability */

Definition at line 150 of file xlog.h.

◆ XLogArchivingActive

Definition at line 94 of file xlog.h.

◆ XLogArchivingAlways

Definition at line 97 of file xlog.h.

◆ XLogHintBitIsNeeded

#define XLogHintBitIsNeeded ( )    (DataChecksumsEnabled() || wal_log_hints)

Definition at line 115 of file xlog.h.

◆ XLogIsNeeded

#define XLogIsNeeded ( )    (wal_level >= WAL_LEVEL_REPLICA)

Definition at line 104 of file xlog.h.

◆ XLogLogicalInfoActive

#define XLogLogicalInfoActive ( )    (wal_level >= WAL_LEVEL_LOGICAL)

Definition at line 121 of file xlog.h.

◆ XLogStandbyInfoActive

#define XLogStandbyInfoActive ( )    (wal_level >= WAL_LEVEL_REPLICA)

Definition at line 118 of file xlog.h.

Typedef Documentation

◆ ArchiveMode

typedef enum ArchiveMode ArchiveMode

◆ CheckpointStatsData

◆ RecoveryState

◆ SessionBackupState

◆ WALAvailability

◆ WalCompression

◆ WalLevel

typedef enum WalLevel WalLevel

Enumeration Type Documentation

◆ ArchiveMode

Enumerator
ARCHIVE_MODE_OFF 
ARCHIVE_MODE_ON 
ARCHIVE_MODE_ALWAYS 

Definition at line 58 of file xlog.h.

59 {
60  ARCHIVE_MODE_OFF = 0, /* disabled */
61  ARCHIVE_MODE_ON, /* enabled while server is running normally */
62  ARCHIVE_MODE_ALWAYS /* enabled always (even during recovery) */
63 } ArchiveMode;
ArchiveMode
Definition: xlog.h:59
@ ARCHIVE_MODE_ALWAYS
Definition: xlog.h:62
@ ARCHIVE_MODE_OFF
Definition: xlog.h:60
@ ARCHIVE_MODE_ON
Definition: xlog.h:61

◆ RecoveryState

Enumerator
RECOVERY_STATE_CRASH 
RECOVERY_STATE_ARCHIVE 
RECOVERY_STATE_DONE 

Definition at line 84 of file xlog.h.

85 {
86  RECOVERY_STATE_CRASH = 0, /* crash recovery */
87  RECOVERY_STATE_ARCHIVE, /* archive recovery */
88  RECOVERY_STATE_DONE /* currently in production */
RecoveryState
Definition: xlog.h:85
@ RECOVERY_STATE_CRASH
Definition: xlog.h:86
@ RECOVERY_STATE_DONE
Definition: xlog.h:88
@ RECOVERY_STATE_ARCHIVE
Definition: xlog.h:87

◆ SessionBackupState

Enumerator
SESSION_BACKUP_NONE 
SESSION_BACKUP_RUNNING 

Definition at line 274 of file xlog.h.

277 {
@ SESSION_BACKUP_NONE
Definition: xlog.h:276

◆ WALAvailability

Enumerator
WALAVAIL_INVALID_LSN 
WALAVAIL_RESERVED 
WALAVAIL_EXTENDED 
WALAVAIL_UNRESERVED 
WALAVAIL_REMOVED 

Definition at line 181 of file xlog.h.

184 {
185  WALAVAIL_INVALID_LSN, /* parameter error */
186  WALAVAIL_RESERVED, /* WAL segment is within max_wal_size */
187  WALAVAIL_EXTENDED, /* WAL segment is reserved by a slot or
188  * wal_keep_size */
189  WALAVAIL_UNRESERVED, /* no longer reserved, but not removed yet */
@ WALAVAIL_RESERVED
Definition: xlog.h:184
@ WALAVAIL_UNRESERVED
Definition: xlog.h:187
@ WALAVAIL_EXTENDED
Definition: xlog.h:185
@ WALAVAIL_INVALID_LSN
Definition: xlog.h:183

◆ WalCompression

Enumerator
WAL_COMPRESSION_NONE 
WAL_COMPRESSION_PGLZ 
WAL_COMPRESSION_LZ4 
WAL_COMPRESSION_ZSTD 

Definition at line 75 of file xlog.h.

76 {
WalCompression
Definition: xlog.h:76
@ WAL_COMPRESSION_NONE
Definition: xlog.h:77
@ WAL_COMPRESSION_LZ4
Definition: xlog.h:79
@ WAL_COMPRESSION_PGLZ
Definition: xlog.h:78
@ WAL_COMPRESSION_ZSTD
Definition: xlog.h:80

◆ WalLevel

enum WalLevel
Enumerator
WAL_LEVEL_MINIMAL 
WAL_LEVEL_REPLICA 
WAL_LEVEL_LOGICAL 

Definition at line 67 of file xlog.h.

68 {
72 } WalLevel;
WalLevel
Definition: xlog.h:68
@ WAL_LEVEL_REPLICA
Definition: xlog.h:70
@ WAL_LEVEL_LOGICAL
Definition: xlog.h:71
@ WAL_LEVEL_MINIMAL
Definition: xlog.h:69

Function Documentation

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 4646 of file xlog.c.

4647 {
4648  CheckPoint checkPoint;
4649  char *buffer;
4650  XLogPageHeader page;
4651  XLogLongPageHeader longpage;
4652  XLogRecord *record;
4653  char *recptr;
4654  uint64 sysidentifier;
4655  struct timeval tv;
4656  pg_crc32c crc;
4657 
4658  /* allow ordinary WAL segment creation, like StartupXLOG() would */
4660 
4661  /*
4662  * Select a hopefully-unique system identifier code for this installation.
4663  * We use the result of gettimeofday(), including the fractional seconds
4664  * field, as being about as unique as we can easily get. (Think not to
4665  * use random(), since it hasn't been seeded and there's no portable way
4666  * to seed it other than the system clock value...) The upper half of the
4667  * uint64 value is just the tv_sec part, while the lower half contains the
4668  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
4669  * PID for a little extra uniqueness. A person knowing this encoding can
4670  * determine the initialization time of the installation, which could
4671  * perhaps be useful sometimes.
4672  */
4673  gettimeofday(&tv, NULL);
4674  sysidentifier = ((uint64) tv.tv_sec) << 32;
4675  sysidentifier |= ((uint64) tv.tv_usec) << 12;
4676  sysidentifier |= getpid() & 0xFFF;
4677 
4678  /* page buffer must be aligned suitably for O_DIRECT */
4679  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
4680  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
4681  memset(page, 0, XLOG_BLCKSZ);
4682 
4683  /*
4684  * Set up information for the initial checkpoint record
4685  *
4686  * The initial checkpoint record is written to the beginning of the WAL
4687  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
4688  * used, so that we can use 0/0 to mean "before any valid WAL segment".
4689  */
4690  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
4691  checkPoint.ThisTimeLineID = BootstrapTimeLineID;
4692  checkPoint.PrevTimeLineID = BootstrapTimeLineID;
4693  checkPoint.fullPageWrites = fullPageWrites;
4694  checkPoint.nextXid =
4696  checkPoint.nextOid = FirstGenbkiObjectId;
4697  checkPoint.nextMulti = FirstMultiXactId;
4698  checkPoint.nextMultiOffset = 0;
4699  checkPoint.oldestXid = FirstNormalTransactionId;
4700  checkPoint.oldestXidDB = Template1DbOid;
4701  checkPoint.oldestMulti = FirstMultiXactId;
4702  checkPoint.oldestMultiDB = Template1DbOid;
4705  checkPoint.time = (pg_time_t) time(NULL);
4707 
4708  ShmemVariableCache->nextXid = checkPoint.nextXid;
4709  ShmemVariableCache->nextOid = checkPoint.nextOid;
4711  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
4712  AdvanceOldestClogXid(checkPoint.oldestXid);
4713  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
4714  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
4716 
4717  /* Set up the XLOG page header */
4718  page->xlp_magic = XLOG_PAGE_MAGIC;
4719  page->xlp_info = XLP_LONG_HEADER;
4720  page->xlp_tli = BootstrapTimeLineID;
4722  longpage = (XLogLongPageHeader) page;
4723  longpage->xlp_sysid = sysidentifier;
4724  longpage->xlp_seg_size = wal_segment_size;
4725  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
4726 
4727  /* Insert the initial checkpoint record */
4728  recptr = ((char *) page + SizeOfXLogLongPHD);
4729  record = (XLogRecord *) recptr;
4730  record->xl_prev = 0;
4731  record->xl_xid = InvalidTransactionId;
4732  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
4734  record->xl_rmid = RM_XLOG_ID;
4735  recptr += SizeOfXLogRecord;
4736  /* fill the XLogRecordDataHeaderShort struct */
4737  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
4738  *(recptr++) = sizeof(checkPoint);
4739  memcpy(recptr, &checkPoint, sizeof(checkPoint));
4740  recptr += sizeof(checkPoint);
4741  Assert(recptr - (char *) record == record->xl_tot_len);
4742 
4743  INIT_CRC32C(crc);
4744  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
4745  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
4746  FIN_CRC32C(crc);
4747  record->xl_crc = crc;
4748 
4749  /* Create first XLOG segment file */
4752 
4753  /*
4754  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
4755  * close the file again in a moment.
4756  */
4757 
4758  /* Write the first page with the initial record */
4759  errno = 0;
4761  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
4762  {
4763  /* if write didn't set errno, assume problem is no disk space */
4764  if (errno == 0)
4765  errno = ENOSPC;
4766  ereport(PANIC,
4768  errmsg("could not write bootstrap write-ahead log file: %m")));
4769  }
4771 
4773  if (pg_fsync(openLogFile) != 0)
4774  ereport(PANIC,
4776  errmsg("could not fsync bootstrap write-ahead log file: %m")));
4778 
4779  if (close(openLogFile) != 0)
4780  ereport(PANIC,
4782  errmsg("could not close bootstrap write-ahead log file: %m")));
4783 
4784  openLogFile = -1;
4785 
4786  /* Now create pg_control */
4787  InitControlFile(sysidentifier);
4788  ControlFile->time = checkPoint.time;
4789  ControlFile->checkPoint = checkPoint.redo;
4790  ControlFile->checkPointCopy = checkPoint;
4791 
4792  /* some additional ControlFile fields are set in WriteControlFile() */
4793  WriteControlFile();
4794 
4795  /* Bootstrap the commit log, too */
4796  BootStrapCLOG();
4800 
4801  pfree(buffer);
4802 
4803  /*
4804  * Force control file to be read - in contrast to normal processing we'd
4805  * otherwise never run the checks and GUC related initializations therein.
4806  */
4807  ReadControlFile();
4808 }
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:788
void BootStrapCLOG(void)
Definition: clog.c:711
void BootStrapCommitTs(void)
Definition: commit_ts.c:553
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:860
int errcode_for_file_access(void)
Definition: elog.c:881
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define PANIC
Definition: elog.h:42
#define ereport(elevel,...)
Definition: elog.h:149
int pg_fsync(int fd)
Definition: fd.c:361
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2179
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2213
void BootStrapMultiXact(void)
Definition: multixact.c:1894
#define FirstMultiXactId
Definition: multixact.h:25
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
return crc
int64 pg_time_t
Definition: pgtime.h:23
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 PrevTimeLineID
Definition: pg_control.h:40
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
Oid nextOid
Definition: pg_control.h:44
TransactionId oldestActiveXid
Definition: pg_control.h:63
bool fullPageWrites
Definition: pg_control.h:42
MultiXactId nextMulti
Definition: pg_control.h:45
FullTransactionId nextXid
Definition: pg_control.h:43
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
pg_time_t time
Definition: pg_control.h:51
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:48
CheckPoint checkPointCopy
Definition: pg_control.h:133
pg_time_t time
Definition: pg_control.h:130
XLogRecPtr checkPoint
Definition: pg_control.h:131
FullTransactionId nextXid
Definition: transam.h:220
uint32 oidCount
Definition: transam.h:215
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
uint8 xl_info
Definition: xlogrecord.h:46
uint32 xl_tot_len
Definition: xlogrecord.h:43
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
void BootStrapSUBTRANS(void)
Definition: subtrans.c:211
#define InvalidTransactionId
Definition: transam.h:31
#define FirstGenbkiObjectId
Definition: transam.h:195
#define FirstNormalTransactionId
Definition: transam.h:34
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:345
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
VariableCache ShmemVariableCache
Definition: varsup.c:34
@ WAIT_EVENT_WAL_BOOTSTRAP_SYNC
Definition: wait_event.h:227
@ WAIT_EVENT_WAL_BOOTSTRAP_WRITE
Definition: wait_event.h:228
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:271
static void pgstat_report_wait_end(void)
Definition: wait_event.h:287
int gettimeofday(struct timeval *tp, void *tzp)
int XLogFileInit(XLogSegNo logsegno, TimeLineID logtli)
Definition: xlog.c:3091
bool fullPageWrites
Definition: xlog.c:125
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:3854
void SetInstallXLogFileSegmentActive(void)
Definition: xlog.c:8947
static int openLogFile
Definition: xlog.c:618
static void WriteControlFile(void)
Definition: xlog.c:3889
int wal_segment_size
Definition: xlog.c:146
static TimeLineID openLogTLI
Definition: xlog.c:620
static ControlFileData * ControlFile
Definition: xlog.c:570
#define BootstrapTimeLineID
Definition: xlog.c:114
static void ReadControlFile(void)
Definition: xlog.c:3971
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:217
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:241
#define SizeOfXLogRecord
Definition: xlogrecord.h:55

References AdvanceOldestClogXid(), Assert(), BootStrapCLOG(), BootStrapCommitTs(), BootStrapMultiXact(), BootStrapSUBTRANS(), BootstrapTimeLineID, ControlFileData::checkPoint, ControlFileData::checkPointCopy, close, COMP_CRC32C, ControlFile, crc, ereport, errcode_for_file_access(), errmsg(), FIN_CRC32C, FirstGenbkiObjectId, FirstMultiXactId, FirstNormalTransactionId, fullPageWrites, CheckPoint::fullPageWrites, FullTransactionIdFromEpochAndXid(), gettimeofday(), INIT_CRC32C, InitControlFile(), InvalidTransactionId, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, VariableCacheData::nextOid, CheckPoint::nextOid, VariableCacheData::nextXid, CheckPoint::nextXid, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, openLogTLI, palloc(), PANIC, pfree(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), CheckPoint::PrevTimeLineID, ReadControlFile(), CheckPoint::redo, SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetTransactionIdLimit(), ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, TYPEALIGN, WAIT_EVENT_WAL_BOOTSTRAP_SYNC, WAIT_EVENT_WAL_BOOTSTRAP_WRITE, wal_segment_size, write, WriteControlFile(), XLogRecord::xl_crc, XLogRecord::xl_info, XLogRecord::xl_prev, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLogRecord::xl_xid, XLOG_CHECKPOINT_SHUTDOWN, XLOG_PAGE_MAGIC, XLogFileInit(), XLogPageHeaderData::xlp_info, XLP_LONG_HEADER, XLogPageHeaderData::xlp_magic, XLogPageHeaderData::xlp_pageaddr, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, XLogPageHeaderData::xlp_tli, XLogLongPageHeaderData::xlp_xlog_blcksz, and XLR_BLOCK_ID_DATA_SHORT.

Referenced by BootstrapModeMain().

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3438 of file xlog.c.

3439 {
3440  int save_errno = errno;
3441  XLogSegNo lastRemovedSegNo;
3442 
3444  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3446 
3447  if (segno <= lastRemovedSegNo)
3448  {
3449  char filename[MAXFNAMELEN];
3450 
3451  XLogFileName(filename, tli, segno, wal_segment_size);
3452  errno = save_errno;
3453  ereport(ERROR,
3455  errmsg("requested WAL segment %s has already been removed",
3456  filename)));
3457  }
3458  errno = save_errno;
3459 }
#define ERROR
Definition: elog.h:39
static char * filename
Definition: pg_dumpall.c:119
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t info_lck
Definition: xlog.c:559
XLogSegNo lastRemovedSegNo
Definition: xlog.c:470
static XLogCtlData * XLogCtl
Definition: xlog.c:562
#define MAXFNAMELEN
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint64 XLogSegNo
Definition: xlogdefs.h:48

References ereport, errcode_for_file_access(), errmsg(), ERROR, filename, XLogCtlData::info_lck, XLogCtlData::lastRemovedSegNo, MAXFNAMELEN, SpinLockAcquire, SpinLockRelease, wal_segment_size, XLogCtl, and XLogFileName().

Referenced by logical_read_xlog_page(), perform_base_backup(), and XLogSendPhysical().

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 6449 of file xlog.c.

6450 {
6451  bool shutdown;
6452  CheckPoint checkPoint;
6453  XLogRecPtr recptr;
6454  XLogSegNo _logSegNo;
6456  uint32 freespace;
6457  XLogRecPtr PriorRedoPtr;
6458  XLogRecPtr curInsert;
6459  XLogRecPtr last_important_lsn;
6460  VirtualTransactionId *vxids;
6461  int nvxids;
6462  int oldXLogAllowed = 0;
6463 
6464  /*
6465  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
6466  * issued at a different time.
6467  */
6469  shutdown = true;
6470  else
6471  shutdown = false;
6472 
6473  /* sanity check */
6474  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
6475  elog(ERROR, "can't create a checkpoint during recovery");
6476 
6477  /*
6478  * Prepare to accumulate statistics.
6479  *
6480  * Note: because it is possible for log_checkpoints to change while a
6481  * checkpoint proceeds, we always accumulate stats, even if
6482  * log_checkpoints is currently off.
6483  */
6484  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
6486 
6487  /*
6488  * Let smgr prepare for checkpoint; this has to happen outside the
6489  * critical section and before we determine the REDO pointer. Note that
6490  * smgr must not do anything that'd have to be undone if we decide no
6491  * checkpoint is needed.
6492  */
6494 
6495  /*
6496  * Use a critical section to force system panic if we have trouble.
6497  */
6499 
6500  if (shutdown)
6501  {
6502  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6505  LWLockRelease(ControlFileLock);
6506  }
6507 
6508  /* Begin filling in the checkpoint WAL record */
6509  MemSet(&checkPoint, 0, sizeof(checkPoint));
6510  checkPoint.time = (pg_time_t) time(NULL);
6511 
6512  /*
6513  * For Hot Standby, derive the oldestActiveXid before we fix the redo
6514  * pointer. This allows us to begin accumulating changes to assemble our
6515  * starting snapshot of locks and transactions.
6516  */
6517  if (!shutdown && XLogStandbyInfoActive())
6519  else
6521 
6522  /*
6523  * Get location of last important record before acquiring insert locks (as
6524  * GetLastImportantRecPtr() also locks WAL locks).
6525  */
6526  last_important_lsn = GetLastImportantRecPtr();
6527 
6528  /*
6529  * We must block concurrent insertions while examining insert state to
6530  * determine the checkpoint REDO pointer.
6531  */
6533  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
6534 
6535  /*
6536  * If this isn't a shutdown or forced checkpoint, and if there has been no
6537  * WAL activity requiring a checkpoint, skip it. The idea here is to
6538  * avoid inserting duplicate checkpoints when the system is idle.
6539  */
6541  CHECKPOINT_FORCE)) == 0)
6542  {
6543  if (last_important_lsn == ControlFile->checkPoint)
6544  {
6546  END_CRIT_SECTION();
6547  ereport(DEBUG1,
6548  (errmsg_internal("checkpoint skipped because system is idle")));
6549  return;
6550  }
6551  }
6552 
6553  /*
6554  * An end-of-recovery checkpoint is created before anyone is allowed to
6555  * write WAL. To allow us to write the checkpoint record, temporarily
6556  * enable XLogInsertAllowed.
6557  */
6558  if (flags & CHECKPOINT_END_OF_RECOVERY)
6559  oldXLogAllowed = LocalSetXLogInsertAllowed();
6560 
6561  checkPoint.ThisTimeLineID = XLogCtl->InsertTimeLineID;
6562  if (flags & CHECKPOINT_END_OF_RECOVERY)
6563  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
6564  else
6565  checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
6566 
6567  checkPoint.fullPageWrites = Insert->fullPageWrites;
6568 
6569  /*
6570  * Compute new REDO record ptr = location of next XLOG record.
6571  *
6572  * NB: this is NOT necessarily where the checkpoint record itself will be,
6573  * since other backends may insert more XLOG records while we're off doing
6574  * the buffer flush work. Those XLOG records are logically after the
6575  * checkpoint, even though physically before it. Got that?
6576  */
6577  freespace = INSERT_FREESPACE(curInsert);
6578  if (freespace == 0)
6579  {
6580  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
6581  curInsert += SizeOfXLogLongPHD;
6582  else
6583  curInsert += SizeOfXLogShortPHD;
6584  }
6585  checkPoint.redo = curInsert;
6586 
6587  /*
6588  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
6589  * must be done while holding all the insertion locks.
6590  *
6591  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
6592  * pointing past where it really needs to point. This is okay; the only
6593  * consequence is that XLogInsert might back up whole buffers that it
6594  * didn't really need to. We can't postpone advancing RedoRecPtr because
6595  * XLogInserts that happen while we are dumping buffers must assume that
6596  * their buffer changes are not included in the checkpoint.
6597  */
6598  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
6599 
6600  /*
6601  * Now we can release the WAL insertion locks, allowing other xacts to
6602  * proceed while we are flushing disk buffers.
6603  */
6605 
6606  /* Update the info_lck-protected copy of RedoRecPtr as well */
6608  XLogCtl->RedoRecPtr = checkPoint.redo;
6610 
6611  /*
6612  * If enabled, log checkpoint start. We postpone this until now so as not
6613  * to log anything if we decided to skip the checkpoint.
6614  */
6615  if (log_checkpoints)
6616  LogCheckpointStart(flags, false);
6617 
6618  /* Update the process title */
6619  update_checkpoint_display(flags, false, false);
6620 
6621  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
6622 
6623  /*
6624  * Get the other info we need for the checkpoint record.
6625  *
6626  * We don't need to save oldestClogXid in the checkpoint, it only matters
6627  * for the short period in which clog is being truncated, and if we crash
6628  * during that we'll redo the clog truncation and fix up oldestClogXid
6629  * there.
6630  */
6631  LWLockAcquire(XidGenLock, LW_SHARED);
6632  checkPoint.nextXid = ShmemVariableCache->nextXid;
6633  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
6635  LWLockRelease(XidGenLock);
6636 
6637  LWLockAcquire(CommitTsLock, LW_SHARED);
6640  LWLockRelease(CommitTsLock);
6641 
6642  LWLockAcquire(OidGenLock, LW_SHARED);
6643  checkPoint.nextOid = ShmemVariableCache->nextOid;
6644  if (!shutdown)
6645  checkPoint.nextOid += ShmemVariableCache->oidCount;
6646  LWLockRelease(OidGenLock);
6647 
6648  MultiXactGetCheckptMulti(shutdown,
6649  &checkPoint.nextMulti,
6650  &checkPoint.nextMultiOffset,
6651  &checkPoint.oldestMulti,
6652  &checkPoint.oldestMultiDB);
6653 
6654  /*
6655  * Having constructed the checkpoint record, ensure all shmem disk buffers
6656  * and commit-log buffers are flushed to disk.
6657  *
6658  * This I/O could fail for various reasons. If so, we will fail to
6659  * complete the checkpoint, but there is no reason to force a system
6660  * panic. Accordingly, exit critical section while doing it.
6661  */
6662  END_CRIT_SECTION();
6663 
6664  /*
6665  * In some cases there are groups of actions that must all occur on one
6666  * side or the other of a checkpoint record. Before flushing the
6667  * checkpoint record we must explicitly wait for any backend currently
6668  * performing those groups of actions.
6669  *
6670  * One example is end of transaction, so we must wait for any transactions
6671  * that are currently in commit critical sections. If an xact inserted
6672  * its commit record into XLOG just before the REDO point, then a crash
6673  * restart from the REDO point would not replay that record, which means
6674  * that our flushing had better include the xact's update of pg_xact. So
6675  * we wait till he's out of his commit critical section before proceeding.
6676  * See notes in RecordTransactionCommit().
6677  *
6678  * Because we've already released the insertion locks, this test is a bit
6679  * fuzzy: it is possible that we will wait for xacts we didn't really need
6680  * to wait for. But the delay should be short and it seems better to make
6681  * checkpoint take a bit longer than to hold off insertions longer than
6682  * necessary. (In fact, the whole reason we have this issue is that xact.c
6683  * does commit record XLOG insertion and clog update as two separate steps
6684  * protected by different locks, but again that seems best on grounds of
6685  * minimizing lock contention.)
6686  *
6687  * A transaction that has not yet set delayChkptFlags when we look cannot
6688  * be at risk, since it has not inserted its commit record yet; and one
6689  * that's already cleared it is not at risk either, since it's done fixing
6690  * clog and we will correctly flush the update below. So we cannot miss
6691  * any xacts we need to wait for.
6692  */
6694  if (nvxids > 0)
6695  {
6696  do
6697  {
6698  pg_usleep(10000L); /* wait for 10 msec */
6699  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6701  }
6702  pfree(vxids);
6703 
6704  CheckPointGuts(checkPoint.redo, flags);
6705 
6707  if (nvxids > 0)
6708  {
6709  do
6710  {
6711  pg_usleep(10000L); /* wait for 10 msec */
6712  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6714  }
6715  pfree(vxids);
6716 
6717  /*
6718  * Take a snapshot of running transactions and write this to WAL. This
6719  * allows us to reconstruct the state of running transactions during
6720  * archive recovery, if required. Skip, if this info disabled.
6721  *
6722  * If we are shutting down, or Startup process is completing crash
6723  * recovery we don't need to write running xact data.
6724  */
6725  if (!shutdown && XLogStandbyInfoActive())
6727 
6729 
6730  /*
6731  * Now insert the checkpoint record into XLOG.
6732  */
6733  XLogBeginInsert();
6734  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
6735  recptr = XLogInsert(RM_XLOG_ID,
6736  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
6738 
6739  XLogFlush(recptr);
6740 
6741  /*
6742  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
6743  * overwritten at next startup. No-one should even try, this just allows
6744  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
6745  * to just temporarily disable writing until the system has exited
6746  * recovery.
6747  */
6748  if (shutdown)
6749  {
6750  if (flags & CHECKPOINT_END_OF_RECOVERY)
6751  LocalXLogInsertAllowed = oldXLogAllowed;
6752  else
6753  LocalXLogInsertAllowed = 0; /* never again write WAL */
6754  }
6755 
6756  /*
6757  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
6758  * = end of actual checkpoint record.
6759  */
6760  if (shutdown && checkPoint.redo != ProcLastRecPtr)
6761  ereport(PANIC,
6762  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
6763 
6764  /*
6765  * Remember the prior checkpoint's redo ptr for
6766  * UpdateCheckPointDistanceEstimate()
6767  */
6768  PriorRedoPtr = ControlFile->checkPointCopy.redo;
6769 
6770  /*
6771  * Update the control file.
6772  */
6773  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6774  if (shutdown)
6777  ControlFile->checkPointCopy = checkPoint;
6778  /* crash recovery should always recover to the end of WAL */
6781 
6782  /*
6783  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
6784  * unused on non-shutdown checkpoints, but seems useful to store it always
6785  * for debugging purposes.
6786  */
6790 
6792  LWLockRelease(ControlFileLock);
6793 
6794  /* Update shared-memory copy of checkpoint XID/epoch */
6796  XLogCtl->ckptFullXid = checkPoint.nextXid;
6798 
6799  /*
6800  * We are now done with critical updates; no need for system panic if we
6801  * have trouble while fooling with old log segments.
6802  */
6803  END_CRIT_SECTION();
6804 
6805  /*
6806  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
6807  */
6809 
6810  /*
6811  * Update the average distance between checkpoints if the prior checkpoint
6812  * exists.
6813  */
6814  if (PriorRedoPtr != InvalidXLogRecPtr)
6816 
6817  /*
6818  * Delete old log files, those no longer needed for last checkpoint to
6819  * prevent the disk holding the xlog from growing full.
6820  */
6822  KeepLogSeg(recptr, &_logSegNo);
6824  _logSegNo, InvalidOid,
6826  {
6827  /*
6828  * Some slots have been invalidated; recalculate the old-segment
6829  * horizon, starting again from RedoRecPtr.
6830  */
6832  KeepLogSeg(recptr, &_logSegNo);
6833  }
6834  _logSegNo--;
6835  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
6836  checkPoint.ThisTimeLineID);
6837 
6838  /*
6839  * Make more log segments if needed. (Do this after recycling old log
6840  * segments, since that may supply some of the needed files.)
6841  */
6842  if (!shutdown)
6843  PreallocXlogFiles(recptr, checkPoint.ThisTimeLineID);
6844 
6845  /*
6846  * Truncate pg_subtrans if possible. We can throw away all data before
6847  * the oldest XMIN of any running transaction. No future transaction will
6848  * attempt to reference any pg_subtrans entry older than that (see Asserts
6849  * in subtrans.c). During recovery, though, we mustn't do this because
6850  * StartupSUBTRANS hasn't been called yet.
6851  */
6852  if (!RecoveryInProgress())
6854 
6855  /* Real work is done; log and update stats. */
6856  LogCheckpointEnd(false);
6857 
6858  /* Reset the process title */
6859  update_checkpoint_display(flags, false, true);
6860 
6861  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
6862  NBuffers,
6866 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
unsigned int uint32
Definition: c.h:490
#define MemSet(start, val, len)
Definition: c.h:1004
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
#define DEBUG1
Definition: elog.h:30
static void Insert(File file)
Definition: fd.c:1224
int NBuffers
Definition: globals.c:136
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
@ LW_SHARED
Definition: lwlock.h:117
@ LW_EXCLUSIVE
Definition: lwlock.h:116
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2133
@ DB_SHUTDOWNING
Definition: pg_control.h:92
@ DB_SHUTDOWNED
Definition: pg_control.h:90
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:68
#define InvalidOid
Definition: postgres_ext.h:36
#define DELAY_CHKPT_START
Definition: proc.h:119
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:120
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
Definition: procarray.c:3039
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2876
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:2018
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
Definition: procarray.c:3085
void pg_usleep(long microsec)
Definition: signal.c:53
bool InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, XLogSegNo oldestSegno, Oid dboid, TransactionId snapshotConflictHorizon)
Definition: slot.c:1518
@ RS_INVAL_WAL_REMOVED
Definition: slot.h:48
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:1278
TimestampTz ckpt_start_t
Definition: xlog.h:156
int ckpt_segs_removed
Definition: xlog.h:165
int ckpt_segs_added
Definition: xlog.h:164
int ckpt_bufs_written
Definition: xlog.h:162
int ckpt_segs_recycled
Definition: xlog.h:166
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
XLogRecPtr unloggedLSN
Definition: pg_control.h:135
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TransactionId newestCommitTsXid
Definition: transam.h:233
TransactionId oldestXid
Definition: transam.h:222
TransactionId oldestCommitTsXid
Definition: transam.h:232
FullTransactionId ckptFullXid
Definition: xlog.c:466
TimeLineID InsertTimeLineID
Definition: xlog.c:515
slock_t ulsn_lck
Definition: xlog.c:474
XLogRecPtr RedoRecPtr
Definition: xlog.c:465
XLogRecPtr unloggedLSN
Definition: xlog.c:473
XLogCtlInsert Insert
Definition: xlog.c:461
TimeLineID PrevTimeLineID
Definition: xlog.c:516
XLogRecPtr RedoRecPtr
Definition: xlog.c:439
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:338
void SyncPreCheckpoint(void)
Definition: sync.c:184
void SyncPostCheckpoint(void)
Definition: sync.c:209
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:256
bool RecoveryInProgress(void)
Definition: xlog.c:5921
static void WALInsertLockRelease(void)
Definition: xlog.c:1379
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1648
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1350
static void UpdateControlFile(void)
Definition: xlog.c:4171
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr, TimeLineID insertTLI)
Definition: xlog.c:3539
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:6219
static XLogRecPtr RedoRecPtr
Definition: xlog.c:276
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:6251
static void PreallocXlogFiles(XLogRecPtr endptr, TimeLineID tli)
Definition: xlog.c:3401
bool log_checkpoints
Definition: xlog.c:132
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:7448
static int LocalSetXLogInsertAllowed(void)
Definition: xlog.c:6009
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:6126
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:6354
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:576
static int LocalXLogInsertAllowed
Definition: xlog.c:239
CheckpointStatsData CheckpointStats
Definition: xlog.c:212
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2513
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:7011
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:6392
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:135
#define CHECKPOINT_FORCE
Definition: xlog.h:137
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:134
#define XLogStandbyInfoActive()
Definition: xlog.h:118
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
void XLogRegisterData(char *data, uint32 len)
Definition: xloginsert.c:351
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:461
void XLogBeginInsert(void)
Definition: xloginsert.c:150

References ControlFileData::checkPoint, CHECKPOINT_END_OF_RECOVERY, CHECKPOINT_FORCE, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStats, CheckpointStatsData::ckpt_bufs_written, CheckpointStatsData::ckpt_segs_added, CheckpointStatsData::ckpt_segs_recycled, CheckpointStatsData::ckpt_segs_removed, CheckpointStatsData::ckpt_start_t, XLogCtlData::ckptFullXid, ControlFile, DB_SHUTDOWNED, DB_SHUTDOWNING, DEBUG1, DELAY_CHKPT_COMPLETE, DELAY_CHKPT_START, elog(), END_CRIT_SECTION, ereport, errmsg(), errmsg_internal(), ERROR, CheckPoint::fullPageWrites, GetCurrentTimestamp(), GetLastImportantRecPtr(), GetOldestActiveTransactionId(), GetOldestTransactionIdConsideredRunning(), GetVirtualXIDsDelayingChkpt(), HaveVirtualXIDsDelayingChkpt(), XLogCtlData::info_lck, XLogCtlData::Insert, Insert(), INSERT_FREESPACE, XLogCtlData::InsertTimeLineID, InvalidateObsoleteReplicationSlots(), InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, KeepLogSeg(), LocalSetXLogInsertAllowed(), LocalXLogInsertAllowed, log_checkpoints, LogCheckpointEnd(), LogCheckpointStart(), LogStandbySnapshot(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MultiXactGetCheckptMulti(), NBuffers, VariableCacheData::newestCommitTsXid, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, VariableCacheData::nextOid, CheckPoint::nextOid, VariableCacheData::nextXid, CheckPoint::nextXid, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, VariableCacheData::oldestCommitTsXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, VariableCacheData::oldestXid, CheckPoint::oldestXid, VariableCacheData::oldestXidDB, CheckPoint::oldestXidDB, PANIC, pfree(), pg_usleep(), PreallocXlogFiles(), XLogCtlData::PrevTimeLineID, CheckPoint::PrevTimeLineID, ProcLastRecPtr, RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), RS_INVAL_WAL_REMOVED, ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogShortPHD, SpinLockAcquire, SpinLockRelease, START_CRIT_SECTION, ControlFileData::state, SyncPostCheckpoint(), SyncPreCheckpoint(), CheckPoint::ThisTimeLineID, CheckPoint::time, TruncateSUBTRANS(), XLogCtlData::ulsn_lck, XLogCtlData::unloggedLSN, ControlFileData::unloggedLSN, update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, XLogBeginInsert(), XLogBytePosToRecPtr(), XLogCtl, XLogFlush(), XLogInsert(), XLogRegisterData(), XLogSegmentOffset, and XLogStandbyInfoActive.

Referenced by CheckpointerMain(), RequestCheckpoint(), and ShutdownXLOG().

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 7092 of file xlog.c.

7093 {
7094  XLogRecPtr lastCheckPointRecPtr;
7095  XLogRecPtr lastCheckPointEndPtr;
7096  CheckPoint lastCheckPoint;
7097  XLogRecPtr PriorRedoPtr;
7098  XLogRecPtr receivePtr;
7099  XLogRecPtr replayPtr;
7100  TimeLineID replayTLI;
7101  XLogRecPtr endptr;
7102  XLogSegNo _logSegNo;
7103  TimestampTz xtime;
7104 
7105  /* Concurrent checkpoint/restartpoint cannot happen */
7107 
7108  /* Get a local copy of the last safe checkpoint record. */
7110  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
7111  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
7112  lastCheckPoint = XLogCtl->lastCheckPoint;
7114 
7115  /*
7116  * Check that we're still in recovery mode. It's ok if we exit recovery
7117  * mode after this check, the restart point is valid anyway.
7118  */
7119  if (!RecoveryInProgress())
7120  {
7121  ereport(DEBUG2,
7122  (errmsg_internal("skipping restartpoint, recovery has already ended")));
7123  return false;
7124  }
7125 
7126  /*
7127  * If the last checkpoint record we've replayed is already our last
7128  * restartpoint, we can't perform a new restart point. We still update
7129  * minRecoveryPoint in that case, so that if this is a shutdown restart
7130  * point, we won't start up earlier than before. That's not strictly
7131  * necessary, but when hot standby is enabled, it would be rather weird if
7132  * the database opened up for read-only connections at a point-in-time
7133  * before the last shutdown. Such time travel is still possible in case of
7134  * immediate shutdown, though.
7135  *
7136  * We don't explicitly advance minRecoveryPoint when we do create a
7137  * restartpoint. It's assumed that flushing the buffers will do that as a
7138  * side-effect.
7139  */
7140  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
7141  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
7142  {
7143  ereport(DEBUG2,
7144  (errmsg_internal("skipping restartpoint, already performed at %X/%X",
7145  LSN_FORMAT_ARGS(lastCheckPoint.redo))));
7146 
7148  if (flags & CHECKPOINT_IS_SHUTDOWN)
7149  {
7150  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7153  LWLockRelease(ControlFileLock);
7154  }
7155  return false;
7156  }
7157 
7158  /*
7159  * Update the shared RedoRecPtr so that the startup process can calculate
7160  * the number of segments replayed since last restartpoint, and request a
7161  * restartpoint if it exceeds CheckPointSegments.
7162  *
7163  * Like in CreateCheckPoint(), hold off insertions to update it, although
7164  * during recovery this is just pro forma, because no WAL insertions are
7165  * happening.
7166  */
7168  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
7170 
7171  /* Also update the info_lck-protected copy */
7173  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
7175 
7176  /*
7177  * Prepare to accumulate statistics.
7178  *
7179  * Note: because it is possible for log_checkpoints to change while a
7180  * checkpoint proceeds, we always accumulate stats, even if
7181  * log_checkpoints is currently off.
7182  */
7183  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
7185 
7186  if (log_checkpoints)
7187  LogCheckpointStart(flags, true);
7188 
7189  /* Update the process title */
7190  update_checkpoint_display(flags, true, false);
7191 
7192  CheckPointGuts(lastCheckPoint.redo, flags);
7193 
7194  /*
7195  * Remember the prior checkpoint's redo ptr for
7196  * UpdateCheckPointDistanceEstimate()
7197  */
7198  PriorRedoPtr = ControlFile->checkPointCopy.redo;
7199 
7200  /*
7201  * Update pg_control, using current time. Check that it still shows an
7202  * older checkpoint, else do nothing; this is a quick hack to make sure
7203  * nothing really bad happens if somehow we get here after the
7204  * end-of-recovery checkpoint.
7205  */
7206  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7207  if (ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
7208  {
7209  /*
7210  * Update the checkpoint information. We do this even if the cluster
7211  * does not show DB_IN_ARCHIVE_RECOVERY to match with the set of WAL
7212  * segments recycled below.
7213  */
7214  ControlFile->checkPoint = lastCheckPointRecPtr;
7215  ControlFile->checkPointCopy = lastCheckPoint;
7216 
7217  /*
7218  * Ensure minRecoveryPoint is past the checkpoint record and update it
7219  * if the control file still shows DB_IN_ARCHIVE_RECOVERY. Normally,
7220  * this will have happened already while writing out dirty buffers,
7221  * but not necessarily - e.g. because no buffers were dirtied. We do
7222  * this because a backup performed in recovery uses minRecoveryPoint
7223  * to determine which WAL files must be included in the backup, and
7224  * the file (or files) containing the checkpoint record must be
7225  * included, at a minimum. Note that for an ordinary restart of
7226  * recovery there's no value in having the minimum recovery point any
7227  * earlier than this anyway, because redo will begin just after the
7228  * checkpoint record.
7229  */
7231  {
7232  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
7233  {
7234  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
7236 
7237  /* update local copy */
7240  }
7241  if (flags & CHECKPOINT_IS_SHUTDOWN)
7243  }
7245  }
7246  LWLockRelease(ControlFileLock);
7247 
7248  /*
7249  * Update the average distance between checkpoints/restartpoints if the
7250  * prior checkpoint exists.
7251  */
7252  if (PriorRedoPtr != InvalidXLogRecPtr)
7254 
7255  /*
7256  * Delete old log files, those no longer needed for last restartpoint to
7257  * prevent the disk holding the xlog from growing full.
7258  */
7260 
7261  /*
7262  * Retreat _logSegNo using the current end of xlog replayed or received,
7263  * whichever is later.
7264  */
7265  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
7266  replayPtr = GetXLogReplayRecPtr(&replayTLI);
7267  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
7268  KeepLogSeg(endptr, &_logSegNo);
7270  _logSegNo, InvalidOid,
7272  {
7273  /*
7274  * Some slots have been invalidated; recalculate the old-segment
7275  * horizon, starting again from RedoRecPtr.
7276  */
7278  KeepLogSeg(endptr, &_logSegNo);
7279  }
7280  _logSegNo--;
7281 
7282  /*
7283  * Try to recycle segments on a useful timeline. If we've been promoted
7284  * since the beginning of this restartpoint, use the new timeline chosen
7285  * at end of recovery. If we're still in recovery, use the timeline we're
7286  * currently replaying.
7287  *
7288  * There is no guarantee that the WAL segments will be useful on the
7289  * current timeline; if recovery proceeds to a new timeline right after
7290  * this, the pre-allocated WAL segments on this timeline will not be used,
7291  * and will go wasted until recycled on the next restartpoint. We'll live
7292  * with that.
7293  */
7294  if (!RecoveryInProgress())
7295  replayTLI = XLogCtl->InsertTimeLineID;
7296 
7297  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, replayTLI);
7298 
7299  /*
7300  * Make more log segments if needed. (Do this after recycling old log
7301  * segments, since that may supply some of the needed files.)
7302  */
7303  PreallocXlogFiles(endptr, replayTLI);
7304 
7305  /*
7306  * Truncate pg_subtrans if possible. We can throw away all data before
7307  * the oldest XMIN of any running transaction. No future transaction will
7308  * attempt to reference any pg_subtrans entry older than that (see Asserts
7309  * in subtrans.c). When hot standby is disabled, though, we mustn't do
7310  * this because StartupSUBTRANS hasn't been called yet.
7311  */
7312  if (EnableHotStandby)
7314 
7315  /* Real work is done; log and update stats. */
7316  LogCheckpointEnd(true);
7317 
7318  /* Reset the process title */
7319  update_checkpoint_display(flags, true, true);
7320 
7321  xtime = GetLatestXTime();
7323  (errmsg("recovery restart point at %X/%X",
7324  LSN_FORMAT_ARGS(lastCheckPoint.redo)),
7325  xtime ? errdetail("Last completed transaction was at log time %s.",
7326  timestamptz_to_str(xtime)) : 0));
7327 
7328  /*
7329  * Finally, execute archive_cleanup_command, if any.
7330  */
7331  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
7333  "archive_cleanup_command",
7334  false,
7336 
7337  return true;
7338 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1782
int64 TimestampTz
Definition: timestamp.h:39
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#define LOG
Definition: elog.h:31
#define DEBUG2
Definition: elog.h:29
bool IsUnderPostmaster
Definition: globals.c:113
@ B_CHECKPOINTER
Definition: miscadmin.h:335
BackendType MyBackendType
Definition: miscinit.c:63
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:94
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:91
CheckPoint lastCheckPoint
Definition: xlog.c:551
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:549
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:550
@ WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND
Definition: wait_event.h:83
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
bool EnableHotStandby
Definition: xlog.c:124
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2433
static XLogRecPtr LocalMinRecoveryPoint
Definition: xlog.c:629
static TimeLineID LocalMinRecoveryPointTLI
Definition: xlog.c:630
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal, uint32 wait_event_info)
Definition: xlogarchive.c:289
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint32 TimeLineID
Definition: xlogdefs.h:59
char * archiveCleanupCommand
Definition: xlogrecovery.c:84
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
TimestampTz GetLatestXTime(void)

References archiveCleanupCommand, Assert(), B_CHECKPOINTER, ControlFileData::checkPoint, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStats, CheckpointStatsData::ckpt_start_t, ControlFile, DB_IN_ARCHIVE_RECOVERY, DB_SHUTDOWNED_IN_RECOVERY, DEBUG2, EnableHotStandby, ereport, errdetail(), errmsg(), errmsg_internal(), ExecuteRecoveryCommand(), GetCurrentTimestamp(), GetLatestXTime(), GetOldestTransactionIdConsideredRunning(), GetWalRcvFlushRecPtr(), GetXLogReplayRecPtr(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::InsertTimeLineID, InvalidateObsoleteReplicationSlots(), InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsUnderPostmaster, KeepLogSeg(), XLogCtlData::lastCheckPoint, XLogCtlData::lastCheckPointEndPtr, XLogCtlData::lastCheckPointRecPtr, LocalMinRecoveryPoint, LocalMinRecoveryPointTLI, LOG, log_checkpoints, LogCheckpointEnd(), LogCheckpointStart(), LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyBackendType, PreallocXlogFiles(), RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), RS_INVAL_WAL_REMOVED, SpinLockAcquire, SpinLockRelease, ControlFileData::state, CheckPoint::ThisTimeLineID, timestamptz_to_str(), TruncateSUBTRANS(), update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), UpdateMinRecoveryPoint(), WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND, wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, XLogCtl, and XLogRecPtrIsInvalid.

Referenced by CheckpointerMain(), and ShutdownXLOG().

◆ DataChecksumsEnabled()

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

Definition at line 8855 of file xlog.c.

8856 {
8857  bool during_backup_start = DatumGetBool(arg);
8858 
8859  /* If called during backup start, there shouldn't be one already running */
8860  Assert(!during_backup_start || sessionBackupState == SESSION_BACKUP_NONE);
8861 
8862  if (during_backup_start || sessionBackupState != SESSION_BACKUP_NONE)
8863  {
8867 
8870 
8871  if (!during_backup_start)
8872  ereport(WARNING,
8873  errmsg("aborting backup due to backend exiting before pg_backup_stop was called"));
8874  }
8875 }
#define WARNING
Definition: elog.h:36
void * arg
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
int runningBackups
Definition: xlog.c:447
static SessionBackupState sessionBackupState
Definition: xlog.c:400

References arg, Assert(), DatumGetBool(), ereport, errmsg(), XLogCtlData::Insert, XLogCtlInsert::runningBackups, SESSION_BACKUP_NONE, sessionBackupState, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, and XLogCtl.

Referenced by do_pg_backup_start(), perform_base_backup(), and register_persistent_abort_backup_handler().

◆ do_pg_backup_start()

void do_pg_backup_start ( const char *  backupidstr,
bool  fast,
List **  tablespaces,
BackupState state,
StringInfo  tblspcmapfile 
)

Definition at line 8266 of file xlog.c.

8268 {
8270 
8271  Assert(state != NULL);
8273 
8274  /*
8275  * During recovery, we don't need to check WAL level. Because, if WAL
8276  * level is not sufficient, it's impossible to get here during recovery.
8277  */
8279  ereport(ERROR,
8280  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8281  errmsg("WAL level not sufficient for making an online backup"),
8282  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8283 
8284  if (strlen(backupidstr) > MAXPGPATH)
8285  ereport(ERROR,
8286  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8287  errmsg("backup label too long (max %d bytes)",
8288  MAXPGPATH)));
8289 
8290  memcpy(state->name, backupidstr, strlen(backupidstr));
8291 
8292  /*
8293  * Mark backup active in shared memory. We must do full-page WAL writes
8294  * during an on-line backup even if not doing so at other times, because
8295  * it's quite possible for the backup dump to obtain a "torn" (partially
8296  * written) copy of a database page if it reads the page concurrently with
8297  * our write to the same page. This can be fixed as long as the first
8298  * write to the page in the WAL sequence is a full-page write. Hence, we
8299  * increment runningBackups then force a CHECKPOINT, to ensure there are
8300  * no dirty pages in shared memory that might get dumped while the backup
8301  * is in progress without having a corresponding WAL record. (Once the
8302  * backup is complete, we need not force full-page writes anymore, since
8303  * we expect that any pages not modified during the backup interval must
8304  * have been correctly captured by the backup.)
8305  *
8306  * Note that forcing full-page writes has no effect during an online
8307  * backup from the standby.
8308  *
8309  * We must hold all the insertion locks to change the value of
8310  * runningBackups, to ensure adequate interlocking against
8311  * XLogInsertRecord().
8312  */
8316 
8317  /*
8318  * Ensure we decrement runningBackups if we fail below. NB -- for this to
8319  * work correctly, it is critical that sessionBackupState is only updated
8320  * after this block is over.
8321  */
8323  {
8324  bool gotUniqueStartpoint = false;
8325  DIR *tblspcdir;
8326  struct dirent *de;
8327  tablespaceinfo *ti;
8328  int datadirpathlen;
8329 
8330  /*
8331  * Force an XLOG file switch before the checkpoint, to ensure that the
8332  * WAL segment the checkpoint is written to doesn't contain pages with
8333  * old timeline IDs. That would otherwise happen if you called
8334  * pg_backup_start() right after restoring from a PITR archive: the
8335  * first WAL segment containing the startup checkpoint has pages in
8336  * the beginning with the old timeline ID. That can cause trouble at
8337  * recovery: we won't have a history file covering the old timeline if
8338  * pg_wal directory was not included in the base backup and the WAL
8339  * archive was cleared too before starting the backup.
8340  *
8341  * This also ensures that we have emitted a WAL page header that has
8342  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
8343  * Therefore, if a WAL archiver (such as pglesslog) is trying to
8344  * compress out removable backup blocks, it won't remove any that
8345  * occur after this point.
8346  *
8347  * During recovery, we skip forcing XLOG file switch, which means that
8348  * the backup taken during recovery is not available for the special
8349  * recovery case described above.
8350  */
8352  RequestXLogSwitch(false);
8353 
8354  do
8355  {
8356  bool checkpointfpw;
8357 
8358  /*
8359  * Force a CHECKPOINT. Aside from being necessary to prevent torn
8360  * page problems, this guarantees that two successive backup runs
8361  * will have different checkpoint positions and hence different
8362  * history file names, even if nothing happened in between.
8363  *
8364  * During recovery, establish a restartpoint if possible. We use
8365  * the last restartpoint as the backup starting checkpoint. This
8366  * means that two successive backup runs can have same checkpoint
8367  * positions.
8368  *
8369  * Since the fact that we are executing do_pg_backup_start()
8370  * during recovery means that checkpointer is running, we can use
8371  * RequestCheckpoint() to establish a restartpoint.
8372  *
8373  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
8374  * passing fast = true). Otherwise this can take awhile.
8375  */
8377  (fast ? CHECKPOINT_IMMEDIATE : 0));
8378 
8379  /*
8380  * Now we need to fetch the checkpoint record location, and also
8381  * its REDO pointer. The oldest point in WAL that would be needed
8382  * to restore starting from the checkpoint is precisely the REDO
8383  * pointer.
8384  */
8385  LWLockAcquire(ControlFileLock, LW_SHARED);
8386  state->checkpointloc = ControlFile->checkPoint;
8387  state->startpoint = ControlFile->checkPointCopy.redo;
8389  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
8390  LWLockRelease(ControlFileLock);
8391 
8393  {
8394  XLogRecPtr recptr;
8395 
8396  /*
8397  * Check to see if all WAL replayed during online backup
8398  * (i.e., since last restartpoint used as backup starting
8399  * checkpoint) contain full-page writes.
8400  */
8402  recptr = XLogCtl->lastFpwDisableRecPtr;
8404 
8405  if (!checkpointfpw || state->startpoint <= recptr)
8406  ereport(ERROR,
8407  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8408  errmsg("WAL generated with full_page_writes=off was replayed "
8409  "since last restartpoint"),
8410  errhint("This means that the backup being taken on the standby "
8411  "is corrupt and should not be used. "
8412  "Enable full_page_writes and run CHECKPOINT on the primary, "
8413  "and then try an online backup again.")));
8414 
8415  /*
8416  * During recovery, since we don't use the end-of-backup WAL
8417  * record and don't write the backup history file, the
8418  * starting WAL location doesn't need to be unique. This means
8419  * that two base backups started at the same time might use
8420  * the same checkpoint as starting locations.
8421  */
8422  gotUniqueStartpoint = true;
8423  }
8424 
8425  /*
8426  * If two base backups are started at the same time (in WAL sender
8427  * processes), we need to make sure that they use different
8428  * checkpoints as starting locations, because we use the starting
8429  * WAL location as a unique identifier for the base backup in the
8430  * end-of-backup WAL record and when we write the backup history
8431  * file. Perhaps it would be better generate a separate unique ID
8432  * for each backup instead of forcing another checkpoint, but
8433  * taking a checkpoint right after another is not that expensive
8434  * either because only few buffers have been dirtied yet.
8435  */
8437  if (XLogCtl->Insert.lastBackupStart < state->startpoint)
8438  {
8439  XLogCtl->Insert.lastBackupStart = state->startpoint;
8440  gotUniqueStartpoint = true;
8441  }
8443  } while (!gotUniqueStartpoint);
8444 
8445  /*
8446  * Construct tablespace_map file.
8447  */
8448  datadirpathlen = strlen(DataDir);
8449 
8450  /* Collect information about all tablespaces */
8451  tblspcdir = AllocateDir("pg_tblspc");
8452  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
8453  {
8454  char fullpath[MAXPGPATH + 10];
8455  char linkpath[MAXPGPATH];
8456  char *relpath = NULL;
8457  char *s;
8458  PGFileType de_type;
8459 
8460  /* Skip anything that doesn't look like a tablespace */
8461  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
8462  continue;
8463 
8464  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
8465 
8466  de_type = get_dirent_type(fullpath, de, false, ERROR);
8467 
8468  if (de_type == PGFILETYPE_LNK)
8469  {
8470  StringInfoData escapedpath;
8471  int rllen;
8472 
8473  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
8474  if (rllen < 0)
8475  {
8476  ereport(WARNING,
8477  (errmsg("could not read symbolic link \"%s\": %m",
8478  fullpath)));
8479  continue;
8480  }
8481  else if (rllen >= sizeof(linkpath))
8482  {
8483  ereport(WARNING,
8484  (errmsg("symbolic link \"%s\" target is too long",
8485  fullpath)));
8486  continue;
8487  }
8488  linkpath[rllen] = '\0';
8489 
8490  /*
8491  * Relpath holds the relative path of the tablespace directory
8492  * when it's located within PGDATA, or NULL if it's located
8493  * elsewhere.
8494  */
8495  if (rllen > datadirpathlen &&
8496  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
8497  IS_DIR_SEP(linkpath[datadirpathlen]))
8498  relpath = pstrdup(linkpath + datadirpathlen + 1);
8499 
8500  /*
8501  * Add a backslash-escaped version of the link path to the
8502  * tablespace map file.
8503  */
8504  initStringInfo(&escapedpath);
8505  for (s = linkpath; *s; s++)
8506  {
8507  if (*s == '\n' || *s == '\r' || *s == '\\')
8508  appendStringInfoChar(&escapedpath, '\\');
8509  appendStringInfoChar(&escapedpath, *s);
8510  }
8511  appendStringInfo(tblspcmapfile, "%s %s\n",
8512  de->d_name, escapedpath.data);
8513  pfree(escapedpath.data);
8514  }
8515  else if (de_type == PGFILETYPE_DIR)
8516  {
8517  /*
8518  * It's possible to use allow_in_place_tablespaces to create
8519  * directories directly under pg_tblspc, for testing purposes
8520  * only.
8521  *
8522  * In this case, we store a relative path rather than an
8523  * absolute path into the tablespaceinfo.
8524  */
8525  snprintf(linkpath, sizeof(linkpath), "pg_tblspc/%s",
8526  de->d_name);
8527  relpath = pstrdup(linkpath);
8528  }
8529  else
8530  {
8531  /* Skip any other file type that appears here. */
8532  continue;
8533  }
8534 
8535  ti = palloc(sizeof(tablespaceinfo));
8536  ti->oid = pstrdup(de->d_name);
8537  ti->path = pstrdup(linkpath);
8538  ti->rpath = relpath;
8539  ti->size = -1;
8540 
8541  if (tablespaces)
8542  *tablespaces = lappend(*tablespaces, ti);
8543  }
8544  FreeDir(tblspcdir);
8545 
8546  state->starttime = (pg_time_t) time(NULL);
8547  }
8549 
8550  state->started_in_recovery = backup_started_in_recovery;
8551 
8552  /*
8553  * Mark that the start phase has correctly finished for the backup.
8554  */
8556 }
static bool backup_started_in_recovery
Definition: basebackup.c:102
void RequestCheckpoint(int flags)
Definition: checkpointer.c:930
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2806
int FreeDir(DIR *dir)
Definition: fd.c:2858
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2740
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:406
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_LNK
Definition: file_utils.h:24
@ PGFILETYPE_DIR
Definition: file_utils.h:23
char * DataDir
Definition: globals.c:66
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
List * lappend(List *list, void *datum)
Definition: list.c:338
char * pstrdup(const char *in)
Definition: mcxt.c:1644
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define IS_DIR_SEP(ch)
Definition: port.h:102
#define relpath(rlocator, forknum)
Definition: relpath.h:94
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Definition: dirent.c:26
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:557
XLogRecPtr lastBackupStart
Definition: xlog.c:448
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
Definition: regguts.h:323
char * rpath
Definition: basebackup.h:32
#define readlink(path, buf, size)
Definition: win32_port.h:244
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:7541
void do_pg_abort_backup(int code, Datum arg)
Definition: xlog.c:8855
@ SESSION_BACKUP_RUNNING
Definition: xlog.h:277
#define CHECKPOINT_WAIT
Definition: xlog.h:140
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:136
#define XLogIsNeeded()
Definition: xlog.h:104

References AllocateDir(), appendStringInfo(), appendStringInfoChar(), Assert(), backup_started_in_recovery, ControlFileData::checkPoint, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, ControlFileData::checkPointCopy, ControlFile, dirent::d_name, StringInfoData::data, DataDir, DatumGetBool(), do_pg_abort_backup(), ereport, errcode(), errhint(), errmsg(), ERROR, FreeDir(), CheckPoint::fullPageWrites, get_dirent_type(), XLogCtlData::info_lck, initStringInfo(), XLogCtlData::Insert, IS_DIR_SEP, lappend(), XLogCtlInsert::lastBackupStart, XLogCtlData::lastFpwDisableRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXPGPATH, tablespaceinfo::oid, palloc(), tablespaceinfo::path, pfree(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, PGFILETYPE_DIR, PGFILETYPE_LNK, pstrdup(), ReadDir(), readlink, RecoveryInProgress(), CheckPoint::redo, relpath, RequestCheckpoint(), RequestXLogSwitch(), tablespaceinfo::rpath, XLogCtlInsert::runningBackups, SESSION_BACKUP_RUNNING, sessionBackupState, tablespaceinfo::size, snprintf, SpinLockAcquire, SpinLockRelease, CheckPoint::ThisTimeLineID, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, XLogCtl, and XLogIsNeeded.

Referenced by perform_base_backup(), and pg_backup_start().

◆ do_pg_backup_stop()

void do_pg_backup_stop ( BackupState state,
bool  waitforarchive 
)

Definition at line 8581 of file xlog.c.

8582 {
8583  bool backup_stopped_in_recovery = false;
8584  char histfilepath[MAXPGPATH];
8585  char lastxlogfilename[MAXFNAMELEN];
8586  char histfilename[MAXFNAMELEN];
8587  XLogSegNo _logSegNo;
8588  FILE *fp;
8589  int seconds_before_warning;
8590  int waits = 0;
8591  bool reported_waiting = false;
8592 
8593  Assert(state != NULL);
8594 
8595  backup_stopped_in_recovery = RecoveryInProgress();
8596 
8597  /*
8598  * During recovery, we don't need to check WAL level. Because, if WAL
8599  * level is not sufficient, it's impossible to get here during recovery.
8600  */
8601  if (!backup_stopped_in_recovery && !XLogIsNeeded())
8602  ereport(ERROR,
8603  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8604  errmsg("WAL level not sufficient for making an online backup"),
8605  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8606 
8607  /*
8608  * OK to update backup counter and session-level lock.
8609  *
8610  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them,
8611  * otherwise they can be updated inconsistently, which might cause
8612  * do_pg_abort_backup() to fail.
8613  */
8615 
8616  /*
8617  * It is expected that each do_pg_backup_start() call is matched by
8618  * exactly one do_pg_backup_stop() call.
8619  */
8622 
8623  /*
8624  * Clean up session-level lock.
8625  *
8626  * You might think that WALInsertLockRelease() can be called before
8627  * cleaning up session-level lock because session-level lock doesn't need
8628  * to be protected with WAL insertion lock. But since
8629  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
8630  * cleaned up before it.
8631  */
8633 
8635 
8636  /*
8637  * If we are taking an online backup from the standby, we confirm that the
8638  * standby has not been promoted during the backup.
8639  */
8640  if (state->started_in_recovery && !backup_stopped_in_recovery)
8641  ereport(ERROR,
8642  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8643  errmsg("the standby was promoted during online backup"),
8644  errhint("This means that the backup being taken is corrupt "
8645  "and should not be used. "
8646  "Try taking another online backup.")));
8647 
8648  /*
8649  * During recovery, we don't write an end-of-backup record. We assume that
8650  * pg_control was backed up last and its minimum recovery point can be
8651  * available as the backup end location. Since we don't have an
8652  * end-of-backup record, we use the pg_control value to check whether
8653  * we've reached the end of backup when starting recovery from this
8654  * backup. We have no way of checking if pg_control wasn't backed up last
8655  * however.
8656  *
8657  * We don't force a switch to new WAL file but it is still possible to
8658  * wait for all the required files to be archived if waitforarchive is
8659  * true. This is okay if we use the backup to start a standby and fetch
8660  * the missing WAL using streaming replication. But in the case of an
8661  * archive recovery, a user should set waitforarchive to true and wait for
8662  * them to be archived to ensure that all the required files are
8663  * available.
8664  *
8665  * We return the current minimum recovery point as the backup end
8666  * location. Note that it can be greater than the exact backup end
8667  * location if the minimum recovery point is updated after the backup of
8668  * pg_control. This is harmless for current uses.
8669  *
8670  * XXX currently a backup history file is for informational and debug
8671  * purposes only. It's not essential for an online backup. Furthermore,
8672  * even if it's created, it will not be archived during recovery because
8673  * an archiver is not invoked. So it doesn't seem worthwhile to write a
8674  * backup history file during recovery.
8675  */
8676  if (backup_stopped_in_recovery)
8677  {
8678  XLogRecPtr recptr;
8679 
8680  /*
8681  * Check to see if all WAL replayed during online backup contain
8682  * full-page writes.
8683  */
8685  recptr = XLogCtl->lastFpwDisableRecPtr;
8687 
8688  if (state->startpoint <= recptr)
8689  ereport(ERROR,
8690  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8691  errmsg("WAL generated with full_page_writes=off was replayed "
8692  "during online backup"),
8693  errhint("This means that the backup being taken on the standby "
8694  "is corrupt and should not be used. "
8695  "Enable full_page_writes and run CHECKPOINT on the primary, "
8696  "and then try an online backup again.")));
8697 
8698 
8699  LWLockAcquire(ControlFileLock, LW_SHARED);
8700  state->stoppoint = ControlFile->minRecoveryPoint;
8702  LWLockRelease(ControlFileLock);
8703  }
8704  else
8705  {
8706  char *history_file;
8707 
8708  /*
8709  * Write the backup-end xlog record
8710  */
8711  XLogBeginInsert();
8712  XLogRegisterData((char *) (&state->startpoint),
8713  sizeof(state->startpoint));
8714  state->stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
8715 
8716  /*
8717  * Given that we're not in recovery, InsertTimeLineID is set and can't
8718  * change, so we can read it without a lock.
8719  */
8720  state->stoptli = XLogCtl->InsertTimeLineID;
8721 
8722  /*
8723  * Force a switch to a new xlog segment file, so that the backup is
8724  * valid as soon as archiver moves out the current segment file.
8725  */
8726  RequestXLogSwitch(false);
8727 
8728  state->stoptime = (pg_time_t) time(NULL);
8729 
8730  /*
8731  * Write the backup history file
8732  */
8733  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
8734  BackupHistoryFilePath(histfilepath, state->stoptli, _logSegNo,
8735  state->startpoint, wal_segment_size);
8736  fp = AllocateFile(histfilepath, "w");
8737  if (!fp)
8738  ereport(ERROR,
8740  errmsg("could not create file \"%s\": %m",
8741  histfilepath)));
8742 
8743  /* Build and save the contents of the backup history file */
8744  history_file = build_backup_content(state, true);
8745  fprintf(fp, "%s", history_file);
8746  pfree(history_file);
8747 
8748  if (fflush(fp) || ferror(fp) || FreeFile(fp))
8749  ereport(ERROR,
8751  errmsg("could not write file \"%s\": %m",
8752  histfilepath)));
8753 
8754  /*
8755  * Clean out any no-longer-needed history files. As a side effect,
8756  * this will post a .ready file for the newly created history file,
8757  * notifying the archiver that history file may be archived
8758  * immediately.
8759  */
8761  }
8762 
8763  /*
8764  * If archiving is enabled, wait for all the required WAL files to be
8765  * archived before returning. If archiving isn't enabled, the required WAL
8766  * needs to be transported via streaming replication (hopefully with
8767  * wal_keep_size set high enough), or some more exotic mechanism like
8768  * polling and copying files from pg_wal with script. We have no knowledge
8769  * of those mechanisms, so it's up to the user to ensure that he gets all
8770  * the required WAL.
8771  *
8772  * We wait until both the last WAL file filled during backup and the
8773  * history file have been archived, and assume that the alphabetic sorting
8774  * property of the WAL files ensures any earlier WAL files are safely
8775  * archived as well.
8776  *
8777  * We wait forever, since archive_command is supposed to work and we
8778  * assume the admin wanted his backup to work completely. If you don't
8779  * wish to wait, then either waitforarchive should be passed in as false,
8780  * or you can set statement_timeout. Also, some notices are issued to
8781  * clue in anyone who might be doing this interactively.
8782  */
8783 
8784  if (waitforarchive &&
8785  ((!backup_stopped_in_recovery && XLogArchivingActive()) ||
8786  (backup_stopped_in_recovery && XLogArchivingAlways())))
8787  {
8788  XLByteToPrevSeg(state->stoppoint, _logSegNo, wal_segment_size);
8789  XLogFileName(lastxlogfilename, state->stoptli, _logSegNo,
8791 
8792  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
8793  BackupHistoryFileName(histfilename, state->stoptli, _logSegNo,
8794  state->startpoint, wal_segment_size);
8795 
8796  seconds_before_warning = 60;
8797  waits = 0;
8798 
8799  while (XLogArchiveIsBusy(lastxlogfilename) ||
8800  XLogArchiveIsBusy(histfilename))
8801  {
8803 
8804  if (!reported_waiting && waits > 5)
8805  {
8806  ereport(NOTICE,
8807  (errmsg("base backup done, waiting for required WAL segments to be archived")));
8808  reported_waiting = true;
8809  }
8810 
8811  (void) WaitLatch(MyLatch,
8813  1000L,
8816 
8817  if (++waits >= seconds_before_warning)
8818  {
8819  seconds_before_warning *= 2; /* This wraps in >10 years... */
8820  ereport(WARNING,
8821  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
8822  waits),
8823  errhint("Check that your archive_command is executing properly. "
8824  "You can safely cancel this backup, "
8825  "but the database backup will not be usable without all the WAL segments.")));
8826  }
8827  }
8828 
8829  ereport(NOTICE,
8830  (errmsg("all required WAL segments have been archived")));
8831  }
8832  else if (waitforarchive)
8833  ereport(NOTICE,
8834  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
8835 }
#define NOTICE
Definition: elog.h:35
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2480
int FreeFile(FILE *file)
Definition: fd.c:2678
struct Latch * MyLatch
Definition: globals.c:58
void ResetLatch(Latch *latch)
Definition: latch.c:699
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:492
#define WL_TIMEOUT
Definition: latch.h:128
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
#define WL_LATCH_SET
Definition: latch.h:125
static void const char fflush(stdout)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define XLOG_BACKUP_END
Definition: pg_control.h:72
#define fprintf
Definition: port.h:242
@ WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE
Definition: wait_event.h:86
static void CleanupBackupHistory(void)
Definition: xlog.c:3811
#define XLogArchivingActive()
Definition: xlog.h:94
#define XLogArchivingAlways()
Definition: xlog.h:97
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
static void BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
static void BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:613
char * build_backup_content(BackupState *state, bool ishistoryfile)
Definition: xlogbackup.c:29

References AllocateFile(), Assert(), BackupHistoryFileName(), BackupHistoryFilePath(), build_backup_content(), CHECK_FOR_INTERRUPTS, CleanupBackupHistory(), ControlFile, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, fflush(), fprintf, FreeFile(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::InsertTimeLineID, XLogCtlData::lastFpwDisableRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXFNAMELEN, MAXPGPATH, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyLatch, NOTICE, pfree(), RecoveryInProgress(), RequestXLogSwitch(), ResetLatch(), XLogCtlInsert::runningBackups, SESSION_BACKUP_NONE, sessionBackupState, SpinLockAcquire, SpinLockRelease, WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE, WaitLatch(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, WL_TIMEOUT, XLByteToPrevSeg, XLByteToSeg, XLOG_BACKUP_END, XLogArchiveIsBusy(), XLogArchivingActive, XLogArchivingAlways, XLogBeginInsert(), XLogCtl, XLogFileName(), XLogInsert(), XLogIsNeeded, and XLogRegisterData().

Referenced by perform_base_backup(), and pg_backup_stop().

◆ get_backup_status()

SessionBackupState get_backup_status ( void  )

Definition at line 8562 of file xlog.c.

8563 {
8564  return sessionBackupState;
8565 }

References sessionBackupState.

Referenced by pg_backup_start(), pg_backup_stop(), and SendBaseBackup().

◆ GetActiveWalLevelOnStandby()

WalLevel GetActiveWalLevelOnStandby ( void  )

Definition at line 4478 of file xlog.c.

4479 {
4480  return ControlFile->wal_level;
4481 }

References ControlFile, and ControlFileData::wal_level.

Referenced by CheckLogicalDecodingRequirements().

◆ GetFakeLSNForUnloggedRel()

XLogRecPtr GetFakeLSNForUnloggedRel ( void  )

Definition at line 4216 of file xlog.c.

4217 {
4218  XLogRecPtr nextUnloggedLSN;
4219 
4220  /* increment the unloggedLSN counter, need SpinLock */
4222  nextUnloggedLSN = XLogCtl->unloggedLSN++;
4224 
4225  return nextUnloggedLSN;
4226 }

References SpinLockAcquire, SpinLockRelease, XLogCtlData::ulsn_lck, XLogCtlData::unloggedLSN, and XLogCtl.

Referenced by gistGetFakeLSN().

◆ GetFlushRecPtr()

XLogRecPtr GetFlushRecPtr ( TimeLineID insertTLI)

Definition at line 6086 of file xlog.c.

6087 {
6089 
6093 
6094  /*
6095  * If we're writing and flushing WAL, the time line can't be changing, so
6096  * no lock is required.
6097  */
6098  if (insertTLI)
6099  *insertTLI = XLogCtl->InsertTimeLineID;
6100 
6101  return LogwrtResult.Flush;
6102 }
RecoveryState SharedRecoveryState
Definition: xlog.c:522
XLogwrtResult LogwrtResult
Definition: xlog.c:484
XLogRecPtr Flush
Definition: xlog.c:337
static XLogwrtResult LogwrtResult
Definition: xlog.c:608

References Assert(), XLogwrtResult::Flush, XLogCtlData::info_lck, XLogCtlData::InsertTimeLineID, XLogCtlData::LogwrtResult, LogwrtResult, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by get_flush_position(), GetCurrentLSN(), IdentifySystem(), pg_current_wal_flush_lsn(), pg_logical_slot_get_changes_guts(), pg_replication_slot_advance(), read_local_xlog_page_guts(), StartReplication(), WalSndWaitForWal(), XLogSendLogical(), and XLogSendPhysical().

◆ GetFullPageWriteInfo()

void GetFullPageWriteInfo ( XLogRecPtr RedoRecPtr_p,
bool doPageWrites_p 
)

Definition at line 6054 of file xlog.c.

6055 {
6056  *RedoRecPtr_p = RedoRecPtr;
6057  *doPageWrites_p = doPageWrites;
6058 }
static bool doPageWrites
Definition: xlog.c:289

References doPageWrites, and RedoRecPtr.

Referenced by XLogCheckBufferNeedsBackup(), and XLogInsert().

◆ GetInsertRecPtr()

XLogRecPtr GetInsertRecPtr ( void  )

Definition at line 6069 of file xlog.c.

6070 {
6071  XLogRecPtr recptr;
6072 
6074  recptr = XLogCtl->LogwrtRqst.Write;
6076 
6077  return recptr;
6078 }
XLogwrtRqst LogwrtRqst
Definition: xlog.c:464
XLogRecPtr Write
Definition: xlog.c:330

References XLogCtlData::info_lck, XLogCtlData::LogwrtRqst, SpinLockAcquire, SpinLockRelease, XLogwrtRqst::Write, and XLogCtl.

Referenced by CheckpointerMain(), gistvacuumscan(), and IsCheckpointOnSchedule().

◆ GetLastImportantRecPtr()

XLogRecPtr GetLastImportantRecPtr ( void  )

Definition at line 6126 of file xlog.c.

6127 {
6129  int i;
6130 
6131  for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
6132  {
6133  XLogRecPtr last_important;
6134 
6135  /*
6136  * Need to take a lock to prevent torn reads of the LSN, which are
6137  * possible on some of the supported platforms. WAL insert locks only
6138  * support exclusive mode, so we have to use that.
6139  */
6141  last_important = WALInsertLocks[i].l.lastImportantAt;
6142  LWLockRelease(&WALInsertLocks[i].l.lock);
6143 
6144  if (res < last_important)
6145  res = last_important;
6146  }
6147 
6148  return res;
6149 }
int i
Definition: isn.c:73
XLogRecPtr lastImportantAt
Definition: xlog.c:380
WALInsertLock l
Definition: xlog.c:392
static WALInsertLockPadded * WALInsertLocks
Definition: xlog.c:565
#define NUM_XLOGINSERT_LOCKS
Definition: xlog.c:153

References i, InvalidXLogRecPtr, WALInsertLockPadded::l, WALInsertLock::lastImportantAt, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NUM_XLOGINSERT_LOCKS, res, and WALInsertLocks.

Referenced by BackgroundWriterMain(), CheckArchiveTimeout(), and CreateCheckPoint().

◆ GetMockAuthenticationNonce()

char* GetMockAuthenticationNonce ( void  )

Definition at line 4190 of file xlog.c.

4191 {
4192  Assert(ControlFile != NULL);
4194 }
char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]
Definition: pg_control.h:227

References Assert(), ControlFile, and ControlFileData::mock_authentication_nonce.

Referenced by scram_mock_salt().

◆ GetRecoveryState()

RecoveryState GetRecoveryState ( void  )

Definition at line 5957 of file xlog.c.

5958 {
5959  RecoveryState retval;
5960 
5962  retval = XLogCtl->SharedRecoveryState;
5964 
5965  return retval;
5966 }

References XLogCtlData::info_lck, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by XLogArchiveCheckDone().

◆ GetRedoRecPtr()

XLogRecPtr GetRedoRecPtr ( void  )

Definition at line 6024 of file xlog.c.

6025 {
6026  XLogRecPtr ptr;
6027 
6028  /*
6029  * The possibly not up-to-date copy in XlogCtl is enough. Even if we
6030  * grabbed a WAL insertion lock to read the authoritative value in
6031  * Insert->RedoRecPtr, someone might update it just after we've released
6032  * the lock.
6033  */
6035  ptr = XLogCtl->RedoRecPtr;
6037 
6038  if (RedoRecPtr < ptr)
6039  RedoRecPtr = ptr;
6040 
6041  return RedoRecPtr;
6042 }

References XLogCtlData::info_lck, RedoRecPtr, XLogCtlData::RedoRecPtr, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), nextval_internal(), ReplicationSlotReserveWal(), XLogPageRead(), XLogSaveBufferForHint(), and XLogWrite().

◆ GetSystemIdentifier()

uint64 GetSystemIdentifier ( void  )

Definition at line 4180 of file xlog.c.

4181 {
4182  Assert(ControlFile != NULL);
4184 }
uint64 system_identifier
Definition: pg_control.h:108

References Assert(), ControlFile, and ControlFileData::system_identifier.

Referenced by IdentifySystem(), ReplicationSlotNameForTablesync(), and WalReceiverMain().

◆ GetWALAvailability()

WALAvailability GetWALAvailability ( XLogRecPtr  targetLSN)

Definition at line 7364 of file xlog.c.

7365 {
7366  XLogRecPtr currpos; /* current write LSN */
7367  XLogSegNo currSeg; /* segid of currpos */
7368  XLogSegNo targetSeg; /* segid of targetLSN */
7369  XLogSegNo oldestSeg; /* actual oldest segid */
7370  XLogSegNo oldestSegMaxWalSize; /* oldest segid kept by max_wal_size */
7371  XLogSegNo oldestSlotSeg; /* oldest segid kept by slot */
7372  uint64 keepSegs;
7373 
7374  /*
7375  * slot does not reserve WAL. Either deactivated, or has never been active
7376  */
7377  if (XLogRecPtrIsInvalid(targetLSN))
7378  return WALAVAIL_INVALID_LSN;
7379 
7380  /*
7381  * Calculate the oldest segment currently reserved by all slots,
7382  * considering wal_keep_size and max_slot_wal_keep_size. Initialize
7383  * oldestSlotSeg to the current segment.
7384  */
7385  currpos = GetXLogWriteRecPtr();
7386  XLByteToSeg(currpos, oldestSlotSeg, wal_segment_size);
7387  KeepLogSeg(currpos, &oldestSlotSeg);
7388 
7389  /*
7390  * Find the oldest extant segment file. We get 1 until checkpoint removes
7391  * the first WAL segment file since startup, which causes the status being
7392  * wrong under certain abnormal conditions but that doesn't actually harm.
7393  */
7394  oldestSeg = XLogGetLastRemovedSegno() + 1;
7395 
7396  /* calculate oldest segment by max_wal_size */
7397  XLByteToSeg(currpos, currSeg, wal_segment_size);
7399 
7400  if (currSeg > keepSegs)
7401  oldestSegMaxWalSize = currSeg - keepSegs;
7402  else
7403  oldestSegMaxWalSize = 1;
7404 
7405  /* the segment we care about */
7406  XLByteToSeg(targetLSN, targetSeg, wal_segment_size);
7407 
7408  /*
7409  * No point in returning reserved or extended status values if the
7410  * targetSeg is known to be lost.
7411  */
7412  if (targetSeg >= oldestSlotSeg)
7413  {
7414  /* show "reserved" when targetSeg is within max_wal_size */
7415  if (targetSeg >= oldestSegMaxWalSize)
7416  return WALAVAIL_RESERVED;
7417 
7418  /* being retained by slots exceeding max_wal_size */
7419  return WALAVAIL_EXTENDED;
7420  }
7421 
7422  /* WAL segments are no longer retained but haven't been removed yet */
7423  if (targetSeg >= oldestSeg)
7424  return WALAVAIL_UNRESERVED;
7425 
7426  /* Definitely lost */
7427  return WALAVAIL_REMOVED;
7428 }
XLogSegNo XLogGetLastRemovedSegno(void)
Definition: xlog.c:3469
int max_wal_size_mb
Definition: xlog.c:117
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:599
XLogRecPtr GetXLogWriteRecPtr(void)
Definition: xlog.c:8912
@ WALAVAIL_REMOVED
Definition: xlog.h:188

References ConvertToXSegs, GetXLogWriteRecPtr(), KeepLogSeg(), max_wal_size_mb, wal_segment_size, WALAVAIL_EXTENDED, WALAVAIL_INVALID_LSN, WALAVAIL_REMOVED, WALAVAIL_RESERVED, WALAVAIL_UNRESERVED, XLByteToSeg, XLogGetLastRemovedSegno(), and XLogRecPtrIsInvalid.

Referenced by pg_get_replication_slots().

◆ GetWALInsertionTimeLine()

TimeLineID GetWALInsertionTimeLine ( void  )

Definition at line 6109 of file xlog.c.

6110 {
6112 
6113  /* Since the value can't be changing, no lock is required. */
6114  return XLogCtl->InsertTimeLineID;
6115 }

References Assert(), XLogCtlData::InsertTimeLineID, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, and XLogCtl.

Referenced by logical_read_xlog_page(), pg_walfile_name(), pg_walfile_name_offset(), ReadReplicationSlot(), and XLogSendPhysical().

◆ GetXLogInsertRecPtr()

XLogRecPtr GetXLogInsertRecPtr ( void  )

Definition at line 8896 of file xlog.c.

8897 {
8899  uint64 current_bytepos;
8900 
8901  SpinLockAcquire(&Insert->insertpos_lck);
8902  current_bytepos = Insert->CurrBytePos;
8903  SpinLockRelease(&Insert->insertpos_lck);
8904 
8905  return XLogBytePosToRecPtr(current_bytepos);
8906 }

References XLogCtlData::Insert, Insert(), SpinLockAcquire, SpinLockRelease, XLogBytePosToRecPtr(), and XLogCtl.

Referenced by CreateOverwriteContrecordRecord(), GetSnapshotDataInitOldSnapshot(), gistGetFakeLSN(), logical_begin_heap_rewrite(), pg_current_wal_insert_lsn(), and ReplicationSlotReserveWal().

◆ GetXLogWriteRecPtr()

◆ InitializeWalConsistencyChecking()

void InitializeWalConsistencyChecking ( void  )

Definition at line 4403 of file xlog.c.

4404 {
4406 
4408  {
4409  struct config_generic *guc;
4410 
4411  guc = find_option("wal_consistency_checking", false, false, ERROR);
4412 
4414 
4415  set_config_option_ext("wal_consistency_checking",
4417  guc->scontext, guc->source, guc->srole,
4418  GUC_ACTION_SET, true, ERROR, false);
4419 
4420  /* checking should not be deferred again */
4422  }
4423 }
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
Definition: guc.c:1163
int set_config_option_ext(const char *name, const char *value, GucContext context, GucSource source, Oid srole, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3324
@ GUC_ACTION_SET
Definition: guc.h:197
bool process_shared_preload_libraries_done
Definition: miscinit.c:1783
GucContext scontext
Definition: guc_tables.h:166
GucSource source
Definition: guc_tables.h:164
char * wal_consistency_checking_string
Definition: xlog.c:128
static bool check_wal_consistency_checking_deferred
Definition: xlog.c:169

References Assert(), check_wal_consistency_checking_deferred, ERROR, find_option(), GUC_ACTION_SET, process_shared_preload_libraries_done, config_generic::scontext, set_config_option_ext(), config_generic::source, config_generic::srole, and wal_consistency_checking_string.

Referenced by PostgresSingleUserMain(), and PostmasterMain().

◆ IsInstallXLogFileSegmentActive()

bool IsInstallXLogFileSegmentActive ( void  )

Definition at line 8955 of file xlog.c.

8956 {
8957  bool result;
8958 
8959  LWLockAcquire(ControlFileLock, LW_SHARED);
8961  LWLockRelease(ControlFileLock);
8962 
8963  return result;
8964 }
bool InstallXLogFileSegmentActive
Definition: xlog.c:532

References XLogCtlData::InstallXLogFileSegmentActive, LW_SHARED, LWLockAcquire(), LWLockRelease(), and XLogCtl.

Referenced by XLogFileRead().

◆ issue_xlog_fsync()

void issue_xlog_fsync ( int  fd,
XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 8159 of file xlog.c.

8160 {
8161  char *msg = NULL;
8162  instr_time start;
8163 
8164  Assert(tli != 0);
8165 
8166  /*
8167  * Quick exit if fsync is disabled or write() has already synced the WAL
8168  * file.
8169  */
8170  if (!enableFsync ||
8173  return;
8174 
8175  /* Measure I/O timing to sync the WAL file */
8176  if (track_wal_io_timing)
8177  INSTR_TIME_SET_CURRENT(start);
8178  else
8179  INSTR_TIME_SET_ZERO(start);
8180 
8182  switch (sync_method)
8183  {
8184  case SYNC_METHOD_FSYNC:
8185  if (pg_fsync_no_writethrough(fd) != 0)
8186  msg = _("could not fsync file \"%s\": %m");
8187  break;
8188 #ifdef HAVE_FSYNC_WRITETHROUGH
8190  if (pg_fsync_writethrough(fd) != 0)
8191  msg = _("could not fsync write-through file \"%s\": %m");
8192  break;
8193 #endif
8194  case SYNC_METHOD_FDATASYNC:
8195  if (pg_fdatasync(fd) != 0)
8196  msg = _("could not fdatasync file \"%s\": %m");
8197  break;
8198  case SYNC_METHOD_OPEN:
8200  /* not reachable */
8201  Assert(false);
8202  break;
8203  default:
8204  elog(PANIC, "unrecognized wal_sync_method: %d", sync_method);
8205  break;
8206  }
8207 
8208  /* PANIC if failed to fsync */
8209  if (msg)
8210  {
8211  char xlogfname[MAXFNAMELEN];
8212  int save_errno = errno;
8213 
8214  XLogFileName(xlogfname, tli, segno, wal_segment_size);
8215  errno = save_errno;
8216  ereport(PANIC,
8218  errmsg(msg, xlogfname)));
8219  }
8220 
8222 
8223  /*
8224  * Increment the I/O timing and the number of times WAL files were synced.
8225  */
8226  if (track_wal_io_timing)
8227  {
8229 
8232  }
8233 
8235 }
#define _(x)
Definition: elog.c:91
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:416
int pg_fdatasync(int fd)
Definition: fd.c:449
int pg_fsync_writethrough(int fd)
Definition: fd.c:428
bool enableFsync
Definition: globals.c:123
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:172
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:184
int duration
Definition: pgbench.c:184
PgStat_PendingWalStats PendingWalStats
Definition: pgstat_wal.c:24
static int fd(const char *x, int i)
Definition: preproc-init.c:105
instr_time wal_sync_time
Definition: pgstat.h:454
PgStat_Counter wal_sync
Definition: pgstat.h:452
@ WAIT_EVENT_WAL_SYNC
Definition: wait_event.h:235
bool track_wal_io_timing
Definition: xlog.c:140
int sync_method
Definition: xlog.c:133
#define SYNC_METHOD_FSYNC
Definition: xlog.h:22
#define SYNC_METHOD_OPEN
Definition: xlog.h:24
#define SYNC_METHOD_FDATASYNC
Definition: xlog.h:23
#define SYNC_METHOD_OPEN_DSYNC
Definition: xlog.h:26
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:25

References _, Assert(), duration, elog(), enableFsync, ereport, errcode_for_file_access(), errmsg(), fd(), INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, INSTR_TIME_SET_ZERO, MAXFNAMELEN, PANIC, PendingWalStats, pg_fdatasync(), pg_fsync_no_writethrough(), pg_fsync_writethrough(), pgstat_report_wait_end(), pgstat_report_wait_start(), sync_method, SYNC_METHOD_FDATASYNC, SYNC_METHOD_FSYNC, SYNC_METHOD_FSYNC_WRITETHROUGH, SYNC_METHOD_OPEN, SYNC_METHOD_OPEN_DSYNC, track_wal_io_timing, WAIT_EVENT_WAL_SYNC, wal_segment_size, PgStat_PendingWalStats::wal_sync, PgStat_PendingWalStats::wal_sync_time, and XLogFileName().

Referenced by XLogWalRcvFlush(), and XLogWrite().

◆ LocalProcessControlFile()

void LocalProcessControlFile ( bool  reset)

Definition at line 4465 of file xlog.c.

4466 {
4467  Assert(reset || ControlFile == NULL);
4468  ControlFile = palloc(sizeof(ControlFileData));
4469  ReadControlFile();
4470 }
void reset(void)
Definition: sql-declare.c:600

References Assert(), ControlFile, palloc(), ReadControlFile(), and reset().

Referenced by PostgresSingleUserMain(), PostmasterMain(), and PostmasterStateMachine().

◆ ReachedEndOfBackup()

void ReachedEndOfBackup ( XLogRecPtr  EndRecPtr,
TimeLineID  tli 
)

Definition at line 5834 of file xlog.c.

5835 {
5836  /*
5837  * We have reached the end of base backup, as indicated by pg_control. The
5838  * data on disk is now consistent (unless minRecoveryPoint is further
5839  * ahead, which can happen if we crashed during previous recovery). Reset
5840  * backupStartPoint and backupEndPoint, and update minRecoveryPoint to
5841  * make sure we don't allow starting up at an earlier point even if
5842  * recovery is stopped and restarted soon after this.
5843  */
5844  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5845 
5846  if (ControlFile->minRecoveryPoint < EndRecPtr)
5847  {
5848  ControlFile->minRecoveryPoint = EndRecPtr;
5850  }
5851 
5854  ControlFile->backupEndRequired = false;
5856 
5857  LWLockRelease(ControlFileLock);
5858 }
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
bool backupEndRequired
Definition: pg_control.h:170
XLogRecPtr backupEndPoint
Definition: pg_control.h:169

References ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, ControlFile, InvalidXLogRecPtr, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, and UpdateControlFile().

Referenced by CheckRecoveryConsistency().

◆ RecoveryInProgress()

bool RecoveryInProgress ( void  )

Definition at line 5921 of file xlog.c.

5922 {
5923  /*
5924  * We check shared state each time only until we leave recovery mode. We
5925  * can't re-enter recovery, so there's no need to keep checking after the
5926  * shared variable has once been seen false.
5927  */
5929  return false;
5930  else
5931  {
5932  /*
5933  * use volatile pointer to make sure we make a fresh read of the
5934  * shared variable.
5935  */
5936  volatile XLogCtlData *xlogctl = XLogCtl;
5937 
5939 
5940  /*
5941  * Note: We don't need a memory barrier when we're still in recovery.
5942  * We might exit recovery immediately after return, so the caller
5943  * can't rely on 'true' meaning that we're still in recovery anyway.
5944  */
5945 
5946  return LocalRecoveryInProgress;
5947  }
5948 }
static bool LocalRecoveryInProgress
Definition: xlog.c:227

References LocalRecoveryInProgress, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, and XLogCtl.

Referenced by BackgroundWriterMain(), BeginReportingGUCOptions(), brin_desummarize_range(), brin_summarize_range(), btree_index_mainfork_expected(), check_transaction_isolation(), check_transaction_read_only(), CheckArchiveTimeout(), CheckLogicalDecodingRequirements(), CheckpointerMain(), ComputeXidHorizons(), CreateCheckPoint(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), CreateRestartPoint(), do_pg_backup_start(), do_pg_backup_stop(), error_commit_ts_disabled(), get_relation_info(), GetCurrentLSN(), GetNewMultiXactId(), GetNewObjectId(), GetNewTransactionId(), GetOldestActiveTransactionId(), GetOldestSafeDecodingTransactionId(), GetRunningTransactionData(), GetSerializableTransactionSnapshot(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), gin_clean_pending_list(), GlobalVisHorizonKindForRel(), heap_force_common(), heap_page_prune_opt(), IdentifySystem(), InitTempTableNamespace(), IsCheckpointOnSchedule(), LockAcquireExtended(), logical_read_xlog_page(), MaintainLatestCompletedXid(), MarkBufferDirtyHint(), perform_base_backup(), pg_create_restore_point(), pg_current_wal_flush_lsn(), pg_current_wal_insert_lsn(), pg_current_wal_lsn(), pg_get_wal_replay_pause_state(), pg_is_in_recovery(), pg_is_wal_replay_paused(), pg_log_standby_snapshot(), pg_logical_slot_get_changes_guts(), pg_promote(), pg_replication_slot_advance(), pg_switch_wal(), pg_wal_replay_pause(), pg_wal_replay_resume(), pg_walfile_name(), pg_walfile_name_offset(), PrepareRedoAdd(), PrepareRedoRemove(), PreventCommandDuringRecovery(), ProcSleep(), read_local_xlog_page_guts(), ReadReplicationSlot(), recovery_create_dbdir(), ReplicationSlotReserveWal(), replorigin_check_prerequisites(), ReportChangedGUCOptions(), sendDir(), SerialSetActiveSerXmin(), show_in_hot_standby(), ShutdownXLOG(), SnapBuildWaitSnapshot(), standard_ProcessUtility(), StartLogicalReplication(), StartReplication(), StartTransaction(), TransactionIdIsInProgress(), TruncateMultiXact(), UpdateFullPageWrites(), verify_heapam(), WalReceiverMain(), WalSndWaitForWal(), xlog_decode(), XLogBackgroundFlush(), XLogFlush(), XLogInsertAllowed(), XLogNeedsFlush(), and XLogSendPhysical().

◆ register_persistent_abort_backup_handler()

void register_persistent_abort_backup_handler ( void  )

Definition at line 8882 of file xlog.c.

8883 {
8884  static bool already_done = false;
8885 
8886  if (already_done)
8887  return;
8889  already_done = true;
8890 }
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333

References before_shmem_exit(), DatumGetBool(), and do_pg_abort_backup().

Referenced by pg_backup_start().

◆ RemoveNonParentXlogFiles()

void RemoveNonParentXlogFiles ( XLogRecPtr  switchpoint,
TimeLineID  newTLI 
)

Definition at line 3613 of file xlog.c.

3614 {
3615  DIR *xldir;
3616  struct dirent *xlde;
3617  char switchseg[MAXFNAMELEN];
3618  XLogSegNo endLogSegNo;
3619  XLogSegNo switchLogSegNo;
3620  XLogSegNo recycleSegNo;
3621 
3622  /*
3623  * Initialize info about where to begin the work. This will recycle,
3624  * somewhat arbitrarily, 10 future segments.
3625  */
3626  XLByteToPrevSeg(switchpoint, switchLogSegNo, wal_segment_size);
3627  XLByteToSeg(switchpoint, endLogSegNo, wal_segment_size);
3628  recycleSegNo = endLogSegNo + 10;
3629 
3630  /*
3631  * Construct a filename of the last segment to be kept.
3632  */
3633  XLogFileName(switchseg, newTLI, switchLogSegNo, wal_segment_size);
3634 
3635  elog(DEBUG2, "attempting to remove WAL segments newer than log file %s",
3636  switchseg);
3637 
3638  xldir = AllocateDir(XLOGDIR);
3639 
3640  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
3641  {
3642  /* Ignore files that are not XLOG segments */
3643  if (!IsXLogFileName(xlde->d_name))
3644  continue;
3645 
3646  /*
3647  * Remove files that are on a timeline older than the new one we're
3648  * switching to, but with a segment number >= the first segment on the
3649  * new timeline.
3650  */
3651  if (strncmp(xlde->d_name, switchseg, 8) < 0 &&
3652  strcmp(xlde->d_name + 8, switchseg + 8) > 0)
3653  {
3654  /*
3655  * If the file has already been marked as .ready, however, don't
3656  * remove it yet. It should be OK to remove it - files that are
3657  * not part of our timeline history are not required for recovery
3658  * - but seems safer to let them be archived and removed later.
3659  */
3660  if (!XLogArchiveIsReady(xlde->d_name))
3661  RemoveXlogFile(xlde, recycleSegNo, &endLogSegNo, newTLI);
3662  }
3663  }
3664 
3665  FreeDir(xldir);
3666 }
static void RemoveXlogFile(const struct dirent *segment_de, XLogSegNo recycleSegNo, XLogSegNo *endlogSegNo, TimeLineID insertTLI)
Definition: xlog.c:3682
static bool IsXLogFileName(const char *fname)
#define XLOGDIR
bool XLogArchiveIsReady(const char *xlog)
Definition: xlogarchive.c:688

References AllocateDir(), dirent::d_name, DEBUG2, elog(), FreeDir(), IsXLogFileName(), MAXFNAMELEN, ReadDir(), RemoveXlogFile(), wal_segment_size, XLByteToPrevSeg, XLByteToSeg, XLogArchiveIsReady(), XLOGDIR, and XLogFileName().

Referenced by ApplyWalRecord(), and CleanupAfterArchiveRecovery().

◆ SetInstallXLogFileSegmentActive()

void SetInstallXLogFileSegmentActive ( void  )

Definition at line 8947 of file xlog.c.

8948 {
8949  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8951  LWLockRelease(ControlFileLock);
8952 }

References XLogCtlData::InstallXLogFileSegmentActive, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and XLogCtl.

Referenced by BootStrapXLOG(), StartupXLOG(), and WaitForWALToBecomeAvailable().

◆ SetWalWriterSleeping()

void SetWalWriterSleeping ( bool  sleeping)

Definition at line 8970 of file xlog.c.

8971 {
8973  XLogCtl->WalWriterSleeping = sleeping;
8975 }
bool WalWriterSleeping
Definition: xlog.c:539

References XLogCtlData::info_lck, SpinLockAcquire, SpinLockRelease, XLogCtlData::WalWriterSleeping, and XLogCtl.

Referenced by WalWriterMain().

◆ ShutdownXLOG()

void ShutdownXLOG ( int  code,
Datum  arg 
)

Definition at line 6172 of file xlog.c.

6173 {
6174  /*
6175  * We should have an aux process resource owner to use, and we should not
6176  * be in a transaction that's installed some other resowner.
6177  */
6179  Assert(CurrentResourceOwner == NULL ||
6182 
6183  /* Don't be chatty in standalone mode */
6185  (errmsg("shutting down")));
6186 
6187  /*
6188  * Signal walsenders to move to stopping state.
6189  */
6191 
6192  /*
6193  * Wait for WAL senders to be in stopping state. This prevents commands
6194  * from writing new WAL.
6195  */
6197 
6198  if (RecoveryInProgress())
6200  else
6201  {
6202  /*
6203  * If archiving is enabled, rotate the last XLOG file so that all the
6204  * remaining records are archived (postmaster wakes up the archiver
6205  * process one more time at the end of shutdown). The checkpoint
6206  * record will go to the next XLOG file and won't be archived (yet).
6207  */
6208  if (XLogArchivingActive())
6209  RequestXLogSwitch(false);
6210 
6212  }
6213 }
bool IsPostmasterEnvironment
Definition: globals.c:112
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
ResourceOwner AuxProcessResourceOwner
Definition: resowner.c:150
void WalSndInitStopping(void)
Definition: walsender.c:3407
void WalSndWaitStopping(void)
Definition: walsender.c:3433
bool CreateRestartPoint(int flags)
Definition: xlog.c:7092
void CreateCheckPoint(int flags)
Definition: xlog.c:6449

References Assert(), AuxProcessResourceOwner, CHECKPOINT_IMMEDIATE, CHECKPOINT_IS_SHUTDOWN, CreateCheckPoint(), CreateRestartPoint(), CurrentResourceOwner, ereport, errmsg(), IsPostmasterEnvironment, LOG, NOTICE, RecoveryInProgress(), RequestXLogSwitch(), WalSndInitStopping(), WalSndWaitStopping(), and XLogArchivingActive.

Referenced by HandleCheckpointerInterrupts(), and InitPostgres().

◆ StartupXLOG()

void StartupXLOG ( void  )

Definition at line 5033 of file xlog.c.

5034 {
5036  CheckPoint checkPoint;
5037  bool wasShutdown;
5038  bool didCrash;
5039  bool haveTblspcMap;
5040  bool haveBackupLabel;
5041  XLogRecPtr EndOfLog;
5042  TimeLineID EndOfLogTLI;
5043  TimeLineID newTLI;
5044  bool performedWalRecovery;
5045  EndOfWalRecoveryInfo *endOfRecoveryInfo;
5048  TransactionId oldestActiveXID;
5049  bool promoted = false;
5050 
5051  /*
5052  * We should have an aux process resource owner to use, and we should not
5053  * be in a transaction that's installed some other resowner.
5054  */
5056  Assert(CurrentResourceOwner == NULL ||
5059 
5060  /*
5061  * Check that contents look valid.
5062  */
5064  ereport(FATAL,
5065  (errmsg("control file contains invalid checkpoint location")));
5066 
5067  switch (ControlFile->state)
5068  {
5069  case DB_SHUTDOWNED:
5070 
5071  /*
5072  * This is the expected case, so don't be chatty in standalone
5073  * mode
5074  */
5076  (errmsg("database system was shut down at %s",
5077  str_time(ControlFile->time))));
5078  break;
5079 
5081  ereport(LOG,
5082  (errmsg("database system was shut down in recovery at %s",
5083  str_time(ControlFile->time))));
5084  break;
5085 
5086  case DB_SHUTDOWNING:
5087  ereport(LOG,
5088  (errmsg("database system shutdown was interrupted; last known up at %s",
5089  str_time(ControlFile->time))));
5090  break;
5091 
5092  case DB_IN_CRASH_RECOVERY:
5093  ereport(LOG,
5094  (errmsg("database system was interrupted while in recovery at %s",
5096  errhint("This probably means that some data is corrupted and"
5097  " you will have to use the last backup for recovery.")));
5098  break;
5099 
5101  ereport(LOG,
5102  (errmsg("database system was interrupted while in recovery at log time %s",
5104  errhint("If this has occurred more than once some data might be corrupted"
5105  " and you might need to choose an earlier recovery target.")));
5106  break;
5107 
5108  case DB_IN_PRODUCTION:
5109  ereport(LOG,
5110  (errmsg("database system was interrupted; last known up at %s",
5111  str_time(ControlFile->time))));
5112  break;
5113 
5114  default:
5115  ereport(FATAL,
5116  (errmsg("control file contains invalid database cluster state")));
5117  }
5118 
5119  /* This is just to allow attaching to startup process with a debugger */
5120 #ifdef XLOG_REPLAY_DELAY
5122  pg_usleep(60000000L);
5123 #endif
5124 
5125  /*
5126  * Verify that pg_wal and pg_wal/archive_status exist. In cases where
5127  * someone has performed a copy for PITR, these directories may have been
5128  * excluded and need to be re-created.
5129  */
5131 
5132  /* Set up timeout handler needed to report startup progress. */
5136 
5137  /*----------
5138  * If we previously crashed, perform a couple of actions:
5139  *
5140  * - The pg_wal directory may still include some temporary WAL segments
5141  * used when creating a new segment, so perform some clean up to not
5142  * bloat this path. This is done first as there is no point to sync
5143  * this temporary data.
5144  *
5145  * - There might be data which we had written, intending to fsync it, but
5146  * which we had not actually fsync'd yet. Therefore, a power failure in
5147  * the near future might cause earlier unflushed writes to be lost, even
5148  * though more recent data written to disk from here on would be
5149  * persisted. To avoid that, fsync the entire data directory.
5150  */
5151  if (ControlFile->state != DB_SHUTDOWNED &&
5153  {
5156  didCrash = true;
5157  }
5158  else
5159  didCrash = false;
5160 
5161  /*
5162  * Prepare for WAL recovery if needed.
5163  *
5164  * InitWalRecovery analyzes the control file and the backup label file, if
5165  * any. It updates the in-memory ControlFile buffer according to the
5166  * starting checkpoint, and sets InRecovery and ArchiveRecoveryRequested.
5167  * It also applies the tablespace map file, if any.
5168  */
5169  InitWalRecovery(ControlFile, &wasShutdown,
5170  &haveBackupLabel, &haveTblspcMap);
5171  checkPoint = ControlFile->checkPointCopy;
5172 
5173  /* initialize shared memory variables from the checkpoint record */
5174  ShmemVariableCache->nextXid = checkPoint.nextXid;
5175  ShmemVariableCache->nextOid = checkPoint.nextOid;
5177  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5178  AdvanceOldestClogXid(checkPoint.oldestXid);
5179  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5180  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5182  checkPoint.newestCommitTsXid);
5183  XLogCtl->ckptFullXid = checkPoint.nextXid;
5184 
5185  /*
5186  * Clear out any old relcache cache files. This is *necessary* if we do
5187  * any WAL replay, since that would probably result in the cache files
5188  * being out of sync with database reality. In theory we could leave them
5189  * in place if the database had been cleanly shut down, but it seems
5190  * safest to just remove them always and let them be rebuilt during the
5191  * first backend startup. These files needs to be removed from all
5192  * directories including pg_tblspc, however the symlinks are created only
5193  * after reading tablespace_map file in case of archive recovery from
5194  * backup, so needs to clear old relcache files here after creating
5195  * symlinks.
5196  */
5198 
5199  /*
5200  * Initialize replication slots, before there's a chance to remove
5201  * required resources.
5202  */
5204 
5205  /*
5206  * Startup logical state, needs to be setup now so we have proper data
5207  * during crash recovery.
5208  */
5210 
5211  /*
5212  * Startup CLOG. This must be done after ShmemVariableCache->nextXid has
5213  * been initialized and before we accept connections or begin WAL replay.
5214  */
5215  StartupCLOG();
5216 
5217  /*
5218  * Startup MultiXact. We need to do this early to be able to replay
5219  * truncations.
5220  */
5221  StartupMultiXact();
5222 
5223  /*
5224  * Ditto for commit timestamps. Activate the facility if the setting is
5225  * enabled in the control file, as there should be no tracking of commit
5226  * timestamps done when the setting was disabled. This facility can be
5227  * started or stopped when replaying a XLOG_PARAMETER_CHANGE record.
5228  */
5230  StartupCommitTs();
5231 
5232  /*
5233  * Recover knowledge about replay progress of known replication partners.
5234  */
5236 
5237  /*
5238  * Initialize unlogged LSN. On a clean shutdown, it's restored from the
5239  * control file. On recovery, all unlogged relations are blown away, so
5240  * the unlogged LSN counter can be reset too.
5241  */
5244  else
5246 
5247  /*
5248  * Copy any missing timeline history files between 'now' and the recovery
5249  * target timeline from archive to pg_wal. While we don't need those files
5250  * ourselves - the history file of the recovery target timeline covers all
5251  * the previous timelines in the history too - a cascading standby server
5252  * might be interested in them. Or, if you archive the WAL from this
5253  * server to a different archive than the primary, it'd be good for all
5254  * the history files to get archived there after failover, so that you can
5255  * use one of the old timelines as a PITR target. Timeline history files
5256  * are small, so it's better to copy them unnecessarily than not copy them
5257  * and regret later.
5258  */
5260 
5261  /*
5262  * Before running in recovery, scan pg_twophase and fill in its status to
5263  * be able to work on entries generated by redo. Doing a scan before
5264  * taking any recovery action has the merit to discard any 2PC files that
5265  * are newer than the first record to replay, saving from any conflicts at
5266  * replay. This avoids as well any subsequent scans when doing recovery
5267  * of the on-disk two-phase data.
5268  */
5270 
5271  /*
5272  * When starting with crash recovery, reset pgstat data - it might not be
5273  * valid. Otherwise restore pgstat data. It's safe to do this here,
5274  * because postmaster will not yet have started any other processes.
5275  *
5276  * NB: Restoring replication slot stats relies on slot state to have
5277  * already been restored from disk.
5278  *
5279  * TODO: With a bit of extra work we could just start with a pgstat file
5280  * associated with the checkpoint redo location we're starting from.
5281  */
5282  if (didCrash)
5284  else
5286 
5287  lastFullPageWrites = checkPoint.fullPageWrites;
5288 
5291 
5292  /* REDO */
5293  if (InRecovery)
5294  {
5295  /* Initialize state for RecoveryInProgress() */
5297  if (InArchiveRecovery)
5299  else
5302 
5303  /*
5304  * Update pg_control to show that we are recovering and to show the
5305  * selected checkpoint as the place we are starting from. We also mark
5306  * pg_control with any minimum recovery stop point obtained from a
5307  * backup history file.
5308  *
5309  * No need to hold ControlFileLock yet, we aren't up far enough.
5310  */
5312 
5313  /*
5314  * If there was a backup label file, it's done its job and the info
5315  * has now been propagated into pg_control. We must get rid of the
5316  * label file so that if we crash during recovery, we'll pick up at
5317  * the latest recovery restartpoint instead of going all the way back
5318  * to the backup start point. It seems prudent though to just rename
5319  * the file out of the way rather than delete it completely.
5320  */
5321  if (haveBackupLabel)
5322  {
5323  unlink(BACKUP_LABEL_OLD);
5325  }
5326 
5327  /*
5328  * If there was a tablespace_map file, it's done its job and the
5329  * symlinks have been created. We must get rid of the map file so
5330  * that if we crash during recovery, we don't create symlinks again.
5331  * It seems prudent though to just rename the file out of the way
5332  * rather than delete it completely.
5333  */
5334  if (haveTblspcMap)
5335  {
5336  unlink(TABLESPACE_MAP_OLD);
5338  }
5339 
5340  /*
5341  * Initialize our local copy of minRecoveryPoint. When doing crash
5342  * recovery we want to replay up to the end of WAL. Particularly, in
5343  * the case of a promoted standby minRecoveryPoint value in the
5344  * control file is only updated after the first checkpoint. However,
5345  * if the instance crashes before the first post-recovery checkpoint
5346  * is completed then recovery will use a stale location causing the
5347  * startup process to think that there are still invalid page
5348  * references when checking for data consistency.
5349  */
5350  if (InArchiveRecovery)
5351  {
5354  }
5355  else
5356  {
5359  }
5360 
5361  /* Check that the GUCs used to generate the WAL allow recovery */
5363 
5364  /*
5365  * We're in recovery, so unlogged relations may be trashed and must be
5366  * reset. This should be done BEFORE allowing Hot Standby
5367  * connections, so that read-only backends don't try to read whatever
5368  * garbage is left over from before.
5369  */
5371 
5372  /*
5373  * Likewise, delete any saved transaction snapshot files that got left
5374  * behind by crashed backends.
5375  */
5377 
5378  /*
5379  * Initialize for Hot Standby, if enabled. We won't let backends in
5380  * yet, not until we've reached the min recovery point specified in
5381  * control file and we've established a recovery snapshot from a
5382  * running-xacts WAL record.
5383  */
5385  {
5386  TransactionId *xids;
5387  int nxids;
5388 
5389  ereport(DEBUG1,
5390  (errmsg_internal("initializing for hot standby")));
5391 
5393 
5394  if (wasShutdown)
5395  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
5396  else
5397  oldestActiveXID = checkPoint.oldestActiveXid;
5398  Assert(TransactionIdIsValid(oldestActiveXID));
5399 
5400  /* Tell procarray about the range of xids it has to deal with */
5402 
5403  /*
5404  * Startup subtrans only. CLOG, MultiXact and commit timestamp
5405  * have already been started up and other SLRUs are not maintained
5406  * during recovery and need not be started yet.
5407  */
5408  StartupSUBTRANS(oldestActiveXID);
5409 
5410  /*
5411  * If we're beginning at a shutdown checkpoint, we know that
5412  * nothing was running on the primary at this point. So fake-up an
5413  * empty running-xacts record and use that here and now. Recover
5414  * additional standby state for prepared transactions.
5415  */
5416  if (wasShutdown)
5417  {
5418  RunningTransactionsData running;
5419  TransactionId latestCompletedXid;
5420 
5421  /*
5422  * Construct a RunningTransactions snapshot representing a
5423  * shut down server, with only prepared transactions still
5424  * alive. We're never overflowed at this point because all
5425  * subxids are listed with their parent prepared transactions.
5426  */
5427  running.xcnt = nxids;
5428  running.subxcnt = 0;
5429  running.subxid_overflow = false;
5430  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
5431  running.oldestRunningXid = oldestActiveXID;
5432  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
5433  TransactionIdRetreat(latestCompletedXid);
5434  Assert(TransactionIdIsNormal(latestCompletedXid));
5435  running.latestCompletedXid = latestCompletedXid;
5436  running.xids = xids;
5437 
5438  ProcArrayApplyRecoveryInfo(&running);
5439 
5441  }
5442  }
5443 
5444  /*
5445  * We're all set for replaying the WAL now. Do it.
5446  */
5448  performedWalRecovery = true;
5449  }
5450  else
5451  performedWalRecovery = false;
5452 
5453  /*
5454  * Finish WAL recovery.
5455  */
5456  endOfRecoveryInfo = FinishWalRecovery();
5457  EndOfLog = endOfRecoveryInfo->endOfLog;
5458  EndOfLogTLI = endOfRecoveryInfo->endOfLogTLI;
5459  abortedRecPtr = endOfRecoveryInfo->abortedRecPtr;
5460  missingContrecPtr = endOfRecoveryInfo->missingContrecPtr;
5461 
5462  /*
5463  * Reset ps status display, so as no information related to recovery shows
5464  * up.
5465  */
5466  set_ps_display("");
5467 
5468  /*
5469  * When recovering from a backup (we are in recovery, and archive recovery
5470  * was requested), complain if we did not roll forward far enough to reach
5471  * the point where the database is consistent. For regular online
5472  * backup-from-primary, that means reaching the end-of-backup WAL record
5473  * (at which point we reset backupStartPoint to be Invalid), for
5474  * backup-from-replica (which can't inject records into the WAL stream),
5475  * that point is when we reach the minRecoveryPoint in pg_control (which
5476  * we purposefully copy last when backing up from a replica). For
5477  * pg_rewind (which creates a backup_label with a method of "pg_rewind")
5478  * or snapshot-style backups (which don't), backupEndRequired will be set
5479  * to false.
5480  *
5481  * Note: it is indeed okay to look at the local variable
5482  * LocalMinRecoveryPoint here, even though ControlFile->minRecoveryPoint
5483  * might be further ahead --- ControlFile->minRecoveryPoint cannot have
5484  * been advanced beyond the WAL we processed.
5485  */
5486  if (InRecovery &&
5487  (EndOfLog < LocalMinRecoveryPoint ||
5489  {
5490  /*
5491  * Ran off end of WAL before reaching end-of-backup WAL record, or
5492  * minRecoveryPoint. That's a bad sign, indicating that you tried to
5493  * recover from an online backup but never called pg_backup_stop(), or
5494  * you didn't archive all the WAL needed.
5495  */
5497  {
5499  ereport(FATAL,
5500  (errmsg("WAL ends before end of online backup"),
5501  errhint("All WAL generated while online backup was taken must be available at recovery.")));
5502  else
5503  ereport(FATAL,
5504  (errmsg("WAL ends before consistent recovery point")));
5505  }
5506  }
5507 
5508  /*
5509  * Reset unlogged relations to the contents of their INIT fork. This is
5510  * done AFTER recovery is complete so as to include any unlogged relations
5511  * created during recovery, but BEFORE recovery is marked as having
5512  * completed successfully. Otherwise we'd not retry if any of the post
5513  * end-of-recovery steps fail.
5514  */
5515  if (InRecovery)
5517 
5518  /*
5519  * Pre-scan prepared transactions to find out the range of XIDs present.
5520  * This information is not quite needed yet, but it is positioned here so
5521  * as potential problems are detected before any on-disk change is done.
5522  */
5523  oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
5524 
5525  /*
5526  * Allow ordinary WAL segment creation before possibly switching to a new
5527  * timeline, which creates a new segment, and after the last ReadRecord().
5528  */
5530 
5531  /*
5532  * Consider whether we need to assign a new timeline ID.
5533  *
5534  * If we did archive recovery, we always assign a new ID. This handles a
5535  * couple of issues. If we stopped short of the end of WAL during
5536  * recovery, then we are clearly generating a new timeline and must assign
5537  * it a unique new ID. Even if we ran to the end, modifying the current
5538  * last segment is problematic because it may result in trying to
5539  * overwrite an already-archived copy of that segment, and we encourage
5540  * DBAs to make their archive_commands reject that. We can dodge the
5541  * problem by making the new active segment have a new timeline ID.
5542  *
5543  * In a normal crash recovery, we can just extend the timeline we were in.
5544  */
5545  newTLI = endOfRecoveryInfo->lastRecTLI;
5547  {
5548  newTLI = findNewestTimeLine(recoveryTargetTLI) + 1;
5549  ereport(LOG,
5550  (errmsg("selected new timeline ID: %u", newTLI)));
5551 
5552  /*
5553  * Make a writable copy of the last WAL segment. (Note that we also
5554  * have a copy of the last block of the old WAL in
5555  * endOfRecovery->lastPage; we will use that below.)
5556  */
5557  XLogInitNewTimeline(EndOfLogTLI, EndOfLog, newTLI);
5558 
5559  /*
5560  * Remove the signal files out of the way, so that we don't
5561  * accidentally re-enter archive recovery mode in a subsequent crash.
5562  */
5563  if (endOfRecoveryInfo->standby_signal_file_found)
5565 
5566  if (endOfRecoveryInfo->recovery_signal_file_found)
5568 
5569  /*
5570  * Write the timeline history file, and have it archived. After this
5571  * point (or rather, as soon as the file is archived), the timeline
5572  * will appear as "taken" in the WAL archive and to any standby
5573  * servers. If we crash before actually switching to the new
5574  * timeline, standby servers will nevertheless think that we switched
5575  * to the new timeline, and will try to connect to the new timeline.
5576  * To minimize the window for that, try to do as little as possible
5577  * between here and writing the end-of-recovery record.
5578  */
5580  EndOfLog, endOfRecoveryInfo->recoveryStopReason);
5581 
5582  ereport(LOG,
5583  (errmsg("archive recovery complete")));
5584  }
5585 
5586  /* Save the selected TimeLineID in shared memory, too */
5587  XLogCtl->InsertTimeLineID = newTLI;
5588  XLogCtl->PrevTimeLineID = endOfRecoveryInfo->lastRecTLI;
5589 
5590  /*
5591  * Actually, if WAL ended in an incomplete record, skip the parts that
5592  * made it through and start writing after the portion that persisted.
5593  * (It's critical to first write an OVERWRITE_CONTRECORD message, which
5594  * we'll do as soon as we're open for writing new WAL.)
5595  */
5597  {
5598  /*
5599  * We should only have a missingContrecPtr if we're not switching to a
5600  * new timeline. When a timeline switch occurs, WAL is copied from the
5601  * old timeline to the new only up to the end of the last complete
5602  * record, so there can't be an incomplete WAL record that we need to
5603  * disregard.
5604  */
5605  Assert(newTLI == endOfRecoveryInfo->lastRecTLI);
5607  EndOfLog = missingContrecPtr;
5608  }
5609 
5610  /*
5611  * Prepare to write WAL starting at EndOfLog location, and init xlog
5612  * buffer cache using the block containing the last record from the
5613  * previous incarnation.
5614  */
5615  Insert = &XLogCtl->Insert;
5616  Insert->PrevBytePos = XLogRecPtrToBytePos(endOfRecoveryInfo->lastRec);
5617  Insert->CurrBytePos = XLogRecPtrToBytePos(EndOfLog);
5618 
5619  /*
5620  * Tricky point here: lastPage contains the *last* block that the LastRec
5621  * record spans, not the one it starts in. The last block is indeed the
5622  * one we want to use.
5623  */
5624  if (EndOfLog % XLOG_BLCKSZ != 0)
5625  {
5626  char *page;
5627  int len;
5628  int firstIdx;
5629 
5630  firstIdx = XLogRecPtrToBufIdx(EndOfLog);
5631  len = EndOfLog - endOfRecoveryInfo->lastPageBeginPtr;
5632  Assert(len < XLOG_BLCKSZ);
5633 
5634  /* Copy the valid part of the last block, and zero the rest */
5635  page = &XLogCtl->pages[firstIdx * XLOG_BLCKSZ];
5636  memcpy(page, endOfRecoveryInfo->lastPage, len);
5637  memset(page + len, 0, XLOG_BLCKSZ - len);
5638 
5639  XLogCtl->xlblocks[firstIdx] = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ;
5640  XLogCtl->InitializedUpTo = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ;
5641  }
5642  else
5643  {
5644  /*
5645  * There is no partial block to copy. Just set InitializedUpTo, and
5646  * let the first attempt to insert a log record to initialize the next
5647  * buffer.
5648  */
5649  XLogCtl->InitializedUpTo = EndOfLog;
5650  }
5651 
5652  LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
5653 
5655 
5656  XLogCtl->LogwrtRqst.Write = EndOfLog;
5657  XLogCtl->LogwrtRqst.Flush = EndOfLog;
5658 
5659  /*
5660  * Preallocate additional log files, if wanted.
5661  */
5662  PreallocXlogFiles(EndOfLog, newTLI);
5663 
5664  /*
5665  * Okay, we're officially UP.
5666  */
5667  InRecovery = false;
5668 
5669  /* start the archive_timeout timer and LSN running */
5670  XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
5671  XLogCtl->lastSegSwitchLSN = EndOfLog;
5672 
5673  /* also initialize latestCompletedXid, to nextXid - 1 */
5674  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
5677  LWLockRelease(ProcArrayLock);
5678 
5679  /*
5680  * Start up subtrans, if not already done for hot standby. (commit
5681  * timestamps are started below, if necessary.)
5682  */
5684  StartupSUBTRANS(oldestActiveXID);
5685 
5686  /*
5687  * Perform end of recovery actions for any SLRUs that need it.
5688  */
5689  TrimCLOG();
5690  TrimMultiXact();
5691 
5692  /* Reload shared-memory state for prepared transactions */
5694 
5695  /* Shut down xlogreader */
5697 
5698  /* Enable WAL writes for this backend only. */
5700 
5701  /* If necessary, write overwrite-contrecord before doing anything else */
5703  {
5706  }
5707 
5708  /*
5709  * Update full_page_writes in shared memory and write an XLOG_FPW_CHANGE
5710  * record before resource manager writes cleanup WAL records or checkpoint
5711  * record is written.
5712  */
5713  Insert->fullPageWrites = lastFullPageWrites;
5715 
5716  /*
5717  * Emit checkpoint or end-of-recovery record in XLOG, if required.
5718  */
5719  if (performedWalRecovery)
5720  promoted = PerformRecoveryXLogAction();
5721 
5722  /*
5723  * If any of the critical GUCs have changed, log them before we allow
5724  * backends to write WAL.
5725  */
5727 
5728  /* If this is archive recovery, perform post-recovery cleanup actions. */
5730  CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog, newTLI);
5731 
5732  /*
5733  * Local WAL inserts enabled, so it's time to finish initialization of
5734  * commit timestamp.
5735  */
5737 
5738  /*
5739  * All done with end-of-recovery actions.
5740  *
5741  * Now allow backends to write WAL and update the control file status in
5742  * consequence. SharedRecoveryState, that controls if backends can write
5743  * WAL, is updated while holding ControlFileLock to prevent other backends
5744  * to look at an inconsistent state of the control file in shared memory.
5745  * There is still a small window during which backends can write WAL and
5746  * the control file is still referring to a system not in DB_IN_PRODUCTION
5747  * state while looking at the on-disk control file.
5748  *
5749  * Also, we use info_lck to update SharedRecoveryState to ensure that
5750  * there are no race conditions concerning visibility of other recent
5751  * updates to shared memory.
5752  */
5753  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5755 
5759 
5761  LWLockRelease(ControlFileLock);
5762 
5763  /*
5764  * Shutdown the recovery environment. This must occur after
5765  * RecoverPreparedTransactions() (see notes in lock_twophase_recover())
5766  * and after switching SharedRecoveryState to RECOVERY_STATE_DONE so as
5767  * any session building a snapshot will not rely on KnownAssignedXids as
5768  * RecoveryInProgress() would return false at this stage. This is
5769  * particularly critical for prepared 2PC transactions, that would still
5770  * need to be included in snapshots once recovery has ended.
5771  */
5774 
5775  /*
5776  * If there were cascading standby servers connected to us, nudge any wal
5777  * sender processes to notice that we've been promoted.
5778  */
5779  WalSndWakeup(true, true);
5780 
5781  /*
5782  * If this was a promotion, request an (online) checkpoint now. This isn't
5783  * required for consistency, but the last restartpoint might be far back,
5784  * and in case of a crash, recovering from it might take a longer than is
5785  * appropriate now that we're not in standby mode anymore.
5786  */
5787  if (promoted)
5789 }
TimeLineID findNewestTimeLine(TimeLineID startTLI)
Definition: timeline.c:264
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
Definition: timeline.c:50
void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, XLogRecPtr switchpoint, char *reason)
Definition: timeline.c:304
void startup_progress_timeout_handler(void)
Definition: startup.c:312
uint32 TransactionId
Definition: c.h:636
void StartupCLOG(void)
Definition: clog.c:754
void TrimCLOG(void)
Definition: clog.c:773
void StartupCommitTs(void)
Definition: commit_ts.c:589
void CompleteCommitTsInitialization(void)
Definition: commit_ts.c:599
#define FATAL
Definition: elog.h:41
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:693
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:783
void SyncDataDirectory(void)
Definition: fd.c:3441
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
void TrimMultiXact(void)
Definition: multixact.c:2031
void StartupMultiXact(void)
Definition: multixact.c:2008
void StartupReplicationOrigin(void)
Definition: origin.c:699
@ DB_IN_PRODUCTION
Definition: pg_control.h:95
@ DB_IN_CRASH_RECOVERY
Definition: pg_control.h:93
const void size_t len
void pgstat_restore_stats(void)
Definition: pgstat.c:410
void pgstat_discard_stats(void)
Definition: pgstat.c:422
void ProcArrayApplyRecoveryInfo(RunningTransactions running)
Definition: procarray.c:1056
void ProcArrayInitRecovery(TransactionId initializedUptoXID)
Definition: procarray.c:1025
static void set_ps_display(const char *activity)
Definition: ps_status.h:40
void ResetUnloggedRelations(int op)
Definition: reinit.c:47
#define UNLOGGED_RELATION_INIT
Definition: reinit.h:27
#define UNLOGGED_RELATION_CLEANUP
Definition: reinit.h:26
void RelationCacheInitFileRemove(void)
Definition: relcache.c:6747
void StartupReorderBuffer(void)
void StartupReplicationSlots(void)
Definition: slot.c:1607
void DeleteAllExportedSnapshotFiles(void)
Definition: snapmgr.c:1584
void InitRecoveryTransactionEnvironment(void)
Definition: standby.c:96
void ShutdownRecoveryTransactionEnvironment(void)
Definition: standby.c:161
bool track_commit_timestamp
Definition: pg_control.h:183
XLogRecPtr lastPageBeginPtr
Definition: xlogrecovery.h:111
XLogRecPtr abortedRecPtr
Definition: xlogrecovery.h:120
XLogRecPtr missingContrecPtr
Definition: xlogrecovery.h:121
TimeLineID endOfLogTLI
Definition: xlogrecovery.h:109
TransactionId oldestRunningXid
Definition: standby.h:84
TransactionId nextXid
Definition: standby.h:83
TransactionId latestCompletedXid
Definition: standby.h:85
TransactionId * xids
Definition: standby.h:87
FullTransactionId latestCompletedXid
Definition: transam.h:238
XLogRecPtr InitializedUpTo
Definition: xlog.c:496
char * pages
Definition: xlog.c:503
pg_time_t lastSegSwitchTime
Definition: xlog.c:477
XLogRecPtr lastSegSwitchLSN
Definition: xlog.c:478
XLogRecPtr * xlblocks
Definition: xlog.c:504
XLogRecPtr Flush
Definition: xlog.c:331
void StartupSUBTRANS(TransactionId oldestActiveXID)
Definition: subtrans.c:249
TimeoutId RegisterTimeout(TimeoutId id, timeout_handler_proc handler)
Definition: timeout.c:509
@ STARTUP_PROGRESS_TIMEOUT
Definition: timeout.h:37
#define TransactionIdRetreat(dest)
Definition: transam.h:141
static void FullTransactionIdRetreat(FullTransactionId *dest)
Definition: transam.h:103
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
void RecoverPreparedTransactions(void)
Definition: twophase.c:2059
void restoreTwoPhaseData(void)
Definition: twophase.c:1875
TransactionId PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
Definition: twophase.c:1937
void StandbyRecoverPreparedTransactions(void)
Definition: twophase.c:2018
void WalSndWakeup(bool physical, bool logical)
Definition: walsender.c:3334
void UpdateFullPageWrites(void)
Definition: xlog.c:7647
static char * str_time(pg_time_t tnow)
Definition: xlog.c:4811
static void ValidateXLOGDirectoryStructure(void)
Definition: xlog.c:3772
static XLogRecPtr CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr pagePtr, TimeLineID newTLI)
Definition: xlog.c:6941
static void XLogReportParameters(void)
Definition: xlog.c:7584
static bool PerformRecoveryXLogAction(void)
Definition: xlog.c:5871
static void CleanupAfterArchiveRecovery(TimeLineID EndOfLogTLI, XLogRecPtr EndOfLog, TimeLineID newTLI)
Definition: xlog.c:4901
static bool lastFullPageWrites
Definition: xlog.c:220
static uint64 XLogRecPtrToBytePos(XLogRecPtr ptr)
Definition: xlog.c:1731
static void XLogInitNewTimeline(TimeLineID endTLI, XLogRecPtr endOfLog, TimeLineID newTLI)
Definition: xlog.c:4826
static void CheckRequiredParameterValues(void)
Definition: xlog.c:4990
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:587
static void RemoveTempXlogFiles(void)
Definition: xlog.c:3506
#define TABLESPACE_MAP_OLD
Definition: xlog.h:295
#define TABLESPACE_MAP
Definition: xlog.h:294
#define STANDBY_SIGNAL_FILE
Definition: xlog.h:290
#define BACKUP_LABEL_OLD
Definition: xlog.h:292
#define BACKUP_LABEL_FILE
Definition: xlog.h:291
#define RECOVERY_SIGNAL_FILE
Definition: xlog.h:289
#define XRecOffIsValid(xlrp)
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
void ShutdownWalRecovery(void)
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:137
bool InArchiveRecovery
Definition: xlogrecovery.c:138
void PerformWalRecovery(void)
EndOfWalRecoveryInfo * FinishWalRecovery(void)
static XLogRecPtr missingContrecPtr
Definition: xlogrecovery.c:373
static XLogRecPtr abortedRecPtr
Definition: xlogrecovery.c:372
void InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
Definition: xlogrecovery.c:512
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:122
HotStandbyState standbyState
Definition: xlogutils.c:56
bool InRecovery
Definition: xlogutils.c:53
@ STANDBY_DISABLED
Definition: xlogutils.h:49

References abortedRecPtr, EndOfWalRecoveryInfo::abortedRecPtr, AdvanceOldestClogXid(), ArchiveRecoveryRequested, Assert(), AuxProcessResourceOwner, BACKUP_LABEL_FILE, BACKUP_LABEL_OLD, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, ControlFileData::checkPoint, CHECKPOINT_FORCE, ControlFileData::checkPointCopy, CheckRequiredParameterValues(), XLogCtlData::ckptFullXid, CleanupAfterArchiveRecovery(), CompleteCommitTsInitialization(), ControlFile, CreateOverwriteContrecordRecord(), CurrentResourceOwner, DB_IN_ARCHIVE_RECOVERY, DB_IN_CRASH_RECOVERY, DB_IN_PRODUCTION, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, DB_SHUTDOWNING, DEBUG1, DeleteAllExportedSnapshotFiles(), doPageWrites, durable_rename(), durable_unlink(), EnableHotStandby, EndOfWalRecoveryInfo::endOfLog, EndOfWalRecoveryInfo::endOfLogTLI, ereport, errhint(), errmsg(), errmsg_internal(), FATAL, findNewestTimeLine(), FinishWalRecovery(), FirstNormalUnloggedLSN, XLogwrtRqst::Flush, XLogwrtResult::Flush, CheckPoint::fullPageWrites, FullTransactionIdRetreat(), InArchiveRecovery, XLogCtlData::info_lck, XLogCtlData::InitializedUpTo, InitRecoveryTransactionEnvironment(), InitWalRecovery(), InRecovery, XLogCtlData::Insert, Insert(), XLogCtlData::InsertTimeLineID, InvalidXLogRecPtr, IsBootstrapProcessingMode, IsPostmasterEnvironment, lastFullPageWrites, EndOfWalRecoveryInfo::lastPage, EndOfWalRecoveryInfo::lastPageBeginPtr, EndOfWalRecoveryInfo::lastRec, EndOfWalRecoveryInfo::lastRecTLI, XLogCtlData::lastSegSwitchLSN, XLogCtlData::lastSegSwitchTime, VariableCacheData::latestCompletedXid, RunningTransactionsData::latestCompletedXid, len, LocalMinRecoveryPoint, LocalMinRecoveryPointTLI, LocalSetXLogInsertAllowed(), LOG, XLogCtlData::LogwrtResult, LogwrtResult, XLogCtlData::LogwrtRqst, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, missingContrecPtr, EndOfWalRecoveryInfo::missingContrecPtr, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, VariableCacheData::nextOid, CheckPoint::nextOid, VariableCacheData::nextXid, CheckPoint::nextXid, RunningTransactionsData::nextXid, NOTICE, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, RunningTransactionsData::oldestRunningXid, CheckPoint::oldestXid, CheckPoint::oldestXidDB, XLogCtlData::pages, PerformRecoveryXLogAction(), PerformWalRecovery(), pg_usleep(), pgstat_discard_stats(), pgstat_restore_stats(), PreallocXlogFiles(), PrescanPreparedTransactions(), XLogCtlData::PrevTimeLineID, ProcArrayApplyRecoveryInfo(), ProcArrayInitRecovery(), RecoverPreparedTransactions(), RECOVERY_SIGNAL_FILE, EndOfWalRecoveryInfo::recovery_signal_file_found, RECOVERY_STATE_ARCHIVE, RECOVERY_STATE_CRASH, RECOVERY_STATE_DONE, EndOfWalRecoveryInfo::recoveryStopReason, recoveryTargetTLI, CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RegisterTimeout(), RelationCacheInitFileRemove(), RemoveTempXlogFiles(), RequestCheckpoint(), ResetUnloggedRelations(), restoreTimeLineHistoryFiles(), restoreTwoPhaseData(), set_ps_display(), SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetTransactionIdLimit(), XLogCtlData::SharedRecoveryState, ShmemVariableCache, ShutdownRecoveryTransactionEnvironment(), ShutdownWalRecovery(), SpinLockAcquire, SpinLockRelease, STANDBY_DISABLED, STANDBY_SIGNAL_FILE, EndOfWalRecoveryInfo::standby_signal_file_found, StandbyRecoverPreparedTransactions(), standbyState, STARTUP_PROGRESS_TIMEOUT, startup_progress_timeout_handler(), StartupCLOG(), StartupCommitTs(), StartupMultiXact(), StartupReorderBuffer(), StartupReplicationOrigin(), StartupReplicationSlots(), StartupSUBTRANS(), ControlFileData::state, str_time(), RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_overflow, SyncDataDirectory(), TABLESPACE_MAP, TABLESPACE_MAP_OLD, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, ControlFileData::track_commit_timestamp, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdRetreat, TrimCLOG(), TrimMultiXact(), UNLOGGED_RELATION_CLEANUP, UNLOGGED_RELATION_INIT, XLogCtlData::unloggedLSN, ControlFileData::unloggedLSN, UpdateControlFile(), UpdateFullPageWrites(), ValidateXLOGDirectoryStructure(), WalSndWakeup(), XLogwrtRqst::Write, XLogwrtResult::Write, writeTimeLineHistory(), RunningTransactionsData::xcnt, XidFromFullTransactionId, RunningTransactionsData::xids, XLogCtlData::xlblocks, XLogCtl, XLogInitNewTimeline(), XLogRecPtrIsInvalid, XLogRecPtrToBufIdx, XLogRecPtrToBytePos(), XLogReportParameters(), and XRecOffIsValid.

Referenced by InitPostgres(), and StartupProcessMain().

◆ SwitchIntoArchiveRecovery()

void SwitchIntoArchiveRecovery ( XLogRecPtr  EndRecPtr,
TimeLineID  replayTLI 
)

Definition at line 5796 of file xlog.c.

5797 {
5798  /* initialize minRecoveryPoint to this record */
5799  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5801  if (ControlFile->minRecoveryPoint < EndRecPtr)
5802  {
5803  ControlFile->minRecoveryPoint = EndRecPtr;
5804  ControlFile->minRecoveryPointTLI = replayTLI;
5805  }
5806  /* update local copy */
5809 
5810  /*
5811  * The startup process can update its local copy of minRecoveryPoint from
5812  * this point.
5813  */
5814  updateMinRecoveryPoint = true;
5815 
5817 
5818  /*
5819  * We update SharedRecoveryState while holding the lock on ControlFileLock
5820  * so both states are consistent in shared memory.
5821  */
5825 
5826  LWLockRelease(ControlFileLock);
5827 }
static bool updateMinRecoveryPoint
Definition: xlog.c:631

References ControlFile, DB_IN_ARCHIVE_RECOVERY, XLogCtlData::info_lck, LocalMinRecoveryPoint, LocalMinRecoveryPointTLI, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, RECOVERY_STATE_ARCHIVE, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, ControlFileData::state, UpdateControlFile(), updateMinRecoveryPoint, and XLogCtl.

Referenced by ReadRecord().

◆ UpdateFullPageWrites()

void UpdateFullPageWrites ( void  )

Definition at line 7647 of file xlog.c.

7648 {
7650  bool recoveryInProgress;
7651 
7652  /*
7653  * Do nothing if full_page_writes has not been changed.
7654  *
7655  * It's safe to check the shared full_page_writes without the lock,
7656  * because we assume that there is no concurrently running process which
7657  * can update it.
7658  */
7659  if (fullPageWrites == Insert->fullPageWrites)
7660  return;
7661 
7662  /*
7663  * Perform this outside critical section so that the WAL insert
7664  * initialization done by RecoveryInProgress() doesn't trigger an
7665  * assertion failure.
7666  */
7667  recoveryInProgress = RecoveryInProgress();
7668 
7670 
7671  /*
7672  * It's always safe to take full page images, even when not strictly
7673  * required, but not the other round. So if we're setting full_page_writes
7674  * to true, first set it true and then write the WAL record. If we're
7675  * setting it to false, first write the WAL record and then set the global
7676  * flag.
7677  */
7678  if (fullPageWrites)
7679  {
7681  Insert->fullPageWrites = true;
7683  }
7684 
7685  /*
7686  * Write an XLOG_FPW_CHANGE record. This allows us to keep track of
7687  * full_page_writes during archive recovery, if required.
7688  */
7689  if (XLogStandbyInfoActive() && !recoveryInProgress)
7690  {
7691  XLogBeginInsert();
7692  XLogRegisterData((char *) (&fullPageWrites), sizeof(bool));
7693 
7694  XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE);
7695  }
7696 
7697  if (!fullPageWrites)
7698  {
7700  Insert->fullPageWrites = false;
7702  }
7703  END_CRIT_SECTION();
7704 }
#define XLOG_FPW_CHANGE
Definition: pg_control.h:75

References END_CRIT_SECTION, fullPageWrites, XLogCtlData::Insert, Insert(), RecoveryInProgress(), START_CRIT_SECTION, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLOG_FPW_CHANGE, XLogBeginInsert(), XLogCtl, XLogInsert(), XLogRegisterData(), and XLogStandbyInfoActive.

Referenced by StartupXLOG(), and UpdateSharedMemoryConfig().

◆ xlog_desc()

void xlog_desc ( StringInfo  buf,
struct XLogReaderState record 
)

Definition at line 37 of file xlogdesc.c.

38 {
39  char *rec = XLogRecGetData(record);
40  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
41 
42  if (info == XLOG_CHECKPOINT_SHUTDOWN ||
43  info == XLOG_CHECKPOINT_ONLINE)
44  {
45  CheckPoint *checkpoint = (CheckPoint *) rec;
46 
47  appendStringInfo(buf, "redo %X/%X; "
48  "tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
49  "oldest xid %u in DB %u; oldest multi %u in DB %u; "
50  "oldest/newest commit timestamp xid: %u/%u; "
51  "oldest running xid %u; %s",
52  LSN_FORMAT_ARGS(checkpoint->redo),
53  checkpoint->ThisTimeLineID,
54  checkpoint->PrevTimeLineID,
55  checkpoint->fullPageWrites ? "true" : "false",
57  XidFromFullTransactionId(checkpoint->nextXid),
58  checkpoint->nextOid,
59  checkpoint->nextMulti,
60  checkpoint->nextMultiOffset,
61  checkpoint->oldestXid,
62  checkpoint->oldestXidDB,
63  checkpoint->oldestMulti,
64  checkpoint->oldestMultiDB,
65  checkpoint->oldestCommitTsXid,
66  checkpoint->newestCommitTsXid,
67  checkpoint->oldestActiveXid,
68  (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
69  }
70  else if (info == XLOG_NEXTOID)
71  {
72  Oid nextOid;
73 
74  memcpy(&nextOid, rec, sizeof(Oid));
75  appendStringInfo(buf, "%u", nextOid);
76  }
77  else if (info == XLOG_RESTORE_POINT)
78  {
79  xl_restore_point *xlrec = (xl_restore_point *) rec;
80 
82  }
83  else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
84  {
85  /* no further information to print */
86  }
87  else if (info == XLOG_BACKUP_END)
88  {
89  XLogRecPtr startpoint;
90 
91  memcpy(&startpoint, rec, sizeof(XLogRecPtr));
92  appendStringInfo(buf, "%X/%X", LSN_FORMAT_ARGS(startpoint));
93  }
94  else if (info == XLOG_PARAMETER_CHANGE)
95  {
96  xl_parameter_change xlrec;
97  const char *wal_level_str;
98  const struct config_enum_entry *entry;
99 
100  memcpy(&xlrec, rec, sizeof(xl_parameter_change));
101 
102  /* Find a string representation for wal_level */
103  wal_level_str = "?";
104  for (entry = wal_level_options; entry->name; entry++)
105  {
106  if (entry->val == xlrec.wal_level)
107  {
108  wal_level_str = entry->name;
109  break;
110  }
111  }
112 
113  appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
114  "max_wal_senders=%d max_prepared_xacts=%d "
115  "max_locks_per_xact=%d wal_level=%s "
116  "wal_log_hints=%s track_commit_timestamp=%s",
117  xlrec.MaxConnections,
118  xlrec.max_worker_processes,
119  xlrec.max_wal_senders,
120  xlrec.max_prepared_xacts,
121  xlrec.max_locks_per_xact,
123  xlrec.wal_log_hints ? "on" : "off",
124  xlrec.track_commit_timestamp ? "on" : "off");
125  }
126  else if (info == XLOG_FPW_CHANGE)
127  {
128  bool fpw;
129 
130  memcpy(&fpw, rec, sizeof(bool));
131  appendStringInfoString(buf, fpw ? "true" : "false");
132  }
133  else if (info == XLOG_END_OF_RECOVERY)
134  {
135  xl_end_of_recovery xlrec;
136 
137  memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
138  appendStringInfo(buf, "tli %u; prev tli %u; time %s",
139  xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
141  }
142  else if (info == XLOG_OVERWRITE_CONTRECORD)
143  {
145 
146  memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
147  appendStringInfo(buf, "lsn %X/%X; time %s",
150  }
151 }
static const char * wal_level_str(WalLevel wal_level)
unsigned char uint8
Definition: c.h:488
#define XLOG_RESTORE_POINT
Definition: pg_control.h:74
#define XLOG_OVERWRITE_CONTRECORD
Definition: pg_control.h:80
#define XLOG_FPI
Definition: pg_control.h:78
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:77
#define XLOG_NEXTOID
Definition: pg_control.h:70
#define XLOG_PARAMETER_CHANGE
Definition: pg_control.h:73
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
static char * buf
Definition: pg_test_fsync.c:67
unsigned int Oid
Definition: postgres_ext.h:31
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
Definition: guc.h:168
const char * name
Definition: guc.h:169
int val
Definition: guc.h:170
TimeLineID PrevTimeLineID
TimestampTz end_time
TimeLineID ThisTimeLineID
char rp_name[MAXFNAMELEN]
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
const struct config_enum_entry wal_level_options[]
Definition: xlogdesc.c:27
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References appendStringInfo(), appendStringInfoString(), buf, xl_end_of_recovery::end_time, EpochFromFullTransactionId, CheckPoint::fullPageWrites, LSN_FORMAT_ARGS, xl_parameter_change::max_locks_per_xact, xl_parameter_change::max_prepared_xacts, xl_parameter_change::max_wal_senders, xl_parameter_change::max_worker_processes, xl_parameter_change::MaxConnections, config_enum_entry::name, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, xl_overwrite_contrecord::overwrite_time, xl_overwrite_contrecord::overwritten_lsn, xl_end_of_recovery::PrevTimeLineID, CheckPoint::PrevTimeLineID, CheckPoint::redo, xl_restore_point::rp_name, xl_end_of_recovery::ThisTimeLineID, CheckPoint::ThisTimeLineID, timestamptz_to_str(), xl_parameter_change::track_commit_timestamp, config_enum_entry::val, xl_parameter_change::wal_level, wal_level_options, wal_level_str(), xl_parameter_change::wal_log_hints, XidFromFullTransactionId, XLOG_BACKUP_END, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, XLOG_END_OF_RECOVERY, XLOG_FPI, XLOG_FPI_FOR_HINT, XLOG_FPW_CHANGE, XLOG_NEXTOID, XLOG_OVERWRITE_CONTRECORD, XLOG_PARAMETER_CHANGE, XLOG_RESTORE_POINT, XLogRecGetData, XLogRecGetInfo, and XLR_INFO_MASK.

◆ xlog_identify()

const char* xlog_identify ( uint8  info)

Definition at line 154 of file xlogdesc.c.

155 {
156  const char *id = NULL;
157 
158  switch (info & ~XLR_INFO_MASK)
159  {
161  id = "CHECKPOINT_SHUTDOWN";
162  break;
164  id = "CHECKPOINT_ONLINE";
165  break;
166  case XLOG_NOOP:
167  id = "NOOP";
168  break;
169  case XLOG_NEXTOID:
170  id = "NEXTOID";
171  break;
172  case XLOG_SWITCH:
173  id = "SWITCH";
174  break;
175  case XLOG_BACKUP_END:
176  id = "BACKUP_END";
177  break;
179  id = "PARAMETER_CHANGE";
180  break;
181  case XLOG_RESTORE_POINT:
182  id = "RESTORE_POINT";
183  break;
184  case XLOG_FPW_CHANGE:
185  id = "FPW_CHANGE";
186  break;
188  id = "END_OF_RECOVERY";
189  break;
191  id = "OVERWRITE_CONTRECORD";
192  break;
193  case XLOG_FPI:
194  id = "FPI";
195  break;
196  case XLOG_FPI_FOR_HINT:
197  id = "FPI_FOR_HINT";
198  break;
199  }
200 
201  return id;
202 }
#define XLOG_NOOP
Definition: pg_control.h:69
#define XLOG_SWITCH
Definition: pg_control.h:71

References XLOG_BACKUP_END, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, XLOG_END_OF_RECOVERY, XLOG_FPI, XLOG_FPI_FOR_HINT, XLOG_FPW_CHANGE, XLOG_NEXTOID, XLOG_NOOP, XLOG_OVERWRITE_CONTRECORD, XLOG_PARAMETER_CHANGE, XLOG_RESTORE_POINT, XLOG_SWITCH, and XLR_INFO_MASK.

◆ xlog_redo()

void xlog_redo ( struct XLogReaderState record)

Definition at line 7716 of file xlog.c.

7717 {
7718  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
7719  XLogRecPtr lsn = record->EndRecPtr;
7720 
7721  /*
7722  * In XLOG rmgr, backup blocks are only used by XLOG_FPI and
7723  * XLOG_FPI_FOR_HINT records.
7724  */
7725  Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
7726  !XLogRecHasAnyBlockRefs(record));
7727 
7728  if (info == XLOG_NEXTOID)
7729  {
7730  Oid nextOid;
7731 
7732  /*
7733  * We used to try to take the maximum of ShmemVariableCache->nextOid
7734  * and the recorded nextOid, but that fails if the OID counter wraps
7735  * around. Since no OID allocation should be happening during replay
7736  * anyway, better to just believe the record exactly. We still take
7737  * OidGenLock while setting the variable, just in case.
7738  */
7739  memcpy(&nextOid, XLogRecGetData(record), sizeof(Oid));
7740  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7741  ShmemVariableCache->nextOid = nextOid;
7743  LWLockRelease(OidGenLock);
7744  }
7745  else if (info == XLOG_CHECKPOINT_SHUTDOWN)
7746  {
7747  CheckPoint checkPoint;
7748  TimeLineID replayTLI;
7749 
7750  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7751  /* In a SHUTDOWN checkpoint, believe the counters exactly */
7752  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7753  ShmemVariableCache->nextXid = checkPoint.nextXid;
7754  LWLockRelease(XidGenLock);
7755  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7756  ShmemVariableCache->nextOid = checkPoint.nextOid;
7758  LWLockRelease(OidGenLock);
7759  MultiXactSetNextMXact(checkPoint.nextMulti,
7760  checkPoint.nextMultiOffset);
7761 
7763  checkPoint.oldestMultiDB);
7764 
7765  /*
7766  * No need to set oldestClogXid here as well; it'll be set when we
7767  * redo an xl_clog_truncate if it changed since initialization.
7768  */
7769  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
7770 
7771  /*
7772  * If we see a shutdown checkpoint while waiting for an end-of-backup
7773  * record, the backup was canceled and the end-of-backup record will
7774  * never arrive.
7775  */
7779  ereport(PANIC,
7780  (errmsg("online backup was canceled, recovery cannot continue")));
7781 
7782  /*
7783  * If we see a shutdown checkpoint, we know that nothing was running
7784  * on the primary at this point. So fake-up an empty running-xacts
7785  * record and use that here and now. Recover additional standby state
7786  * for prepared transactions.
7787  */
7789  {
7790  TransactionId *xids;
7791  int nxids;
7792  TransactionId oldestActiveXID;
7793  TransactionId latestCompletedXid;
7794  RunningTransactionsData running;
7795 
7796  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
7797 
7798  /*
7799  * Construct a RunningTransactions snapshot representing a shut
7800  * down server, with only prepared transactions still alive. We're
7801  * never overflowed at this point because all subxids are listed
7802  * with their parent prepared transactions.
7803  */
7804  running.xcnt = nxids;
7805  running.subxcnt = 0;
7806  running.subxid_overflow = false;
7807  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
7808  running.oldestRunningXid = oldestActiveXID;
7809  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
7810  TransactionIdRetreat(latestCompletedXid);
7811  Assert(TransactionIdIsNormal(latestCompletedXid));
7812  running.latestCompletedXid = latestCompletedXid;
7813  running.xids = xids;
7814 
7815  ProcArrayApplyRecoveryInfo(&running);
7816 
7818  }
7819 
7820  /* ControlFile->checkPointCopy always tracks the latest ckpt XID */
7821  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7822  ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
7823  LWLockRelease(ControlFileLock);
7824 
7825  /* Update shared-memory copy of checkpoint XID/epoch */
7827  XLogCtl->ckptFullXid = checkPoint.nextXid;
7829 
7830  /*
7831  * We should've already switched to the new TLI before replaying this
7832  * record.
7833  */
7834  (void) GetCurrentReplayRecPtr(&replayTLI);
7835  if (checkPoint.ThisTimeLineID != replayTLI)
7836  ereport(PANIC,
7837  (errmsg("unexpected timeline ID %u (should be %u) in shutdown checkpoint record",
7838  checkPoint.ThisTimeLineID, replayTLI)));
7839 
7840  RecoveryRestartPoint(&checkPoint, record);
7841  }
7842  else if (info == XLOG_CHECKPOINT_ONLINE)
7843  {
7844  CheckPoint checkPoint;
7845  TimeLineID replayTLI;
7846 
7847  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7848  /* In an ONLINE checkpoint, treat the XID counter as a minimum */
7849  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7851  checkPoint.nextXid))
7852  ShmemVariableCache->nextXid = checkPoint.nextXid;
7853  LWLockRelease(XidGenLock);
7854 
7855  /*
7856  * We ignore the nextOid counter in an ONLINE checkpoint, preferring
7857  * to track OID assignment through XLOG_NEXTOID records. The nextOid
7858  * counter is from the start of the checkpoint and might well be stale
7859  * compared to later XLOG_NEXTOID records. We could try to take the
7860  * maximum of the nextOid counter and our latest value, but since
7861  * there's no particular guarantee about the speed with which the OID
7862  * counter wraps around, that's a risky thing to do. In any case,
7863  * users of the nextOid counter are required to avoid assignment of
7864  * duplicates, so that a somewhat out-of-date value should be safe.
7865  */
7866 
7867  /* Handle multixact */
7869  checkPoint.nextMultiOffset);
7870 
7871  /*
7872  * NB: This may perform multixact truncation when replaying WAL
7873  * generated by an older primary.
7874  */
7876  checkPoint.oldestMultiDB);
7878  checkPoint.oldestXid))
7879  SetTransactionIdLimit(checkPoint.oldestXid,
7880  checkPoint.oldestXidDB);
7881  /* ControlFile->checkPointCopy always tracks the latest ckpt XID */
7882  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7883  ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
7884  LWLockRelease(ControlFileLock);
7885 
7886  /* Update shared-memory copy of checkpoint XID/epoch */
7888  XLogCtl->ckptFullXid = checkPoint.nextXid;
7890 
7891  /* TLI should not change in an on-line checkpoint */
7892  (void) GetCurrentReplayRecPtr(&replayTLI);
7893  if (checkPoint.ThisTimeLineID != replayTLI)
7894  ereport(PANIC,
7895  (errmsg("unexpected timeline ID %u (should be %u) in online checkpoint record",
7896  checkPoint.ThisTimeLineID, replayTLI)));
7897 
7898  RecoveryRestartPoint(&checkPoint, record);
7899  }
7900  else if (info == XLOG_OVERWRITE_CONTRECORD)
7901  {
7902  /* nothing to do here, handled in xlogrecovery_redo() */
7903  }
7904  else if (info == XLOG_END_OF_RECOVERY)
7905  {
7906  xl_end_of_recovery xlrec;
7907  TimeLineID replayTLI;
7908 
7909  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_end_of_recovery));
7910 
7911  /*
7912  * For Hot Standby, we could treat this like a Shutdown Checkpoint,
7913  * but this case is rarer and harder to test, so the benefit doesn't
7914  * outweigh the potential extra cost of maintenance.
7915  */