PostgreSQL Source Code  git master
xlog.h File Reference
#include "access/xlogdefs.h"
#include "access/xlogreader.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 RecPtr)
 
bool XLogBackgroundFlush (void)
 
bool XLogNeedsFlush (XLogRecPtr RecPtr)
 
int XLogFileInit (XLogSegNo segno, TimeLineID tli)
 
int XLogFileOpen (XLogSegNo segno, TimeLineID tli)
 
void CheckXLogRemoved (XLogSegNo segno, TimeLineID tli)
 
XLogSegNo XLogGetLastRemovedSegno (void)
 
void XLogSetAsyncXactLSN (XLogRecPtr record)
 
void XLogSetReplicationSlotMinimumLSN (XLogRecPtr lsn)
 
void xlog_redo (XLogReaderState *record)
 
void xlog_desc (StringInfo buf, 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 LocalProcessControlFile (bool reset)
 
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 assign_max_wal_size (int newval, void *extra)
 
void assign_checkpoint_completion_target (double newval, void *extra)
 
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)
 
XLogRecPtr do_pg_backup_start (const char *backupidstr, bool fast, TimeLineID *starttli_p, StringInfo labelfile, List **tablespaces, StringInfo tblspcmapfile)
 
XLogRecPtr do_pg_backup_stop (char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 
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 292 of file xlog.h.

◆ BACKUP_LABEL_OLD

#define BACKUP_LABEL_OLD   "backup_label.old"

Definition at line 293 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 299 of file xlog.h.

◆ RECOVERY_SIGNAL_FILE

#define RECOVERY_SIGNAL_FILE   "recovery.signal"

Definition at line 290 of file xlog.h.

◆ STANDBY_SIGNAL_FILE

#define STANDBY_SIGNAL_FILE   "standby.signal"

Definition at line 291 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 295 of file xlog.h.

◆ TABLESPACE_MAP_OLD

#define TABLESPACE_MAP_OLD   "tablespace_map.old"

Definition at line 296 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

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 1978 of file xlog.c.

1979 {
1982 }
double CheckPointCompletionTarget
Definition: checkpointer.c:146
#define newval
static void CalculateCheckpointSegments(void)
Definition: xlog.c:1942

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 1971 of file xlog.c.

1972 {
1975 }
int max_wal_size_mb
Definition: xlog.c:115

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 4487 of file xlog.c.

4488 {
4489  CheckPoint checkPoint;
4490  char *buffer;
4491  XLogPageHeader page;
4492  XLogLongPageHeader longpage;
4493  XLogRecord *record;
4494  char *recptr;
4495  uint64 sysidentifier;
4496  struct timeval tv;
4497  pg_crc32c crc;
4498 
4499  /* allow ordinary WAL segment creation, like StartupXLOG() would */
4500  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
4502  LWLockRelease(ControlFileLock);
4503 
4504  /*
4505  * Select a hopefully-unique system identifier code for this installation.
4506  * We use the result of gettimeofday(), including the fractional seconds
4507  * field, as being about as unique as we can easily get. (Think not to
4508  * use random(), since it hasn't been seeded and there's no portable way
4509  * to seed it other than the system clock value...) The upper half of the
4510  * uint64 value is just the tv_sec part, while the lower half contains the
4511  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
4512  * PID for a little extra uniqueness. A person knowing this encoding can
4513  * determine the initialization time of the installation, which could
4514  * perhaps be useful sometimes.
4515  */
4516  gettimeofday(&tv, NULL);
4517  sysidentifier = ((uint64) tv.tv_sec) << 32;
4518  sysidentifier |= ((uint64) tv.tv_usec) << 12;
4519  sysidentifier |= getpid() & 0xFFF;
4520 
4521  /* page buffer must be aligned suitably for O_DIRECT */
4522  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
4523  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
4524  memset(page, 0, XLOG_BLCKSZ);
4525 
4526  /*
4527  * Set up information for the initial checkpoint record
4528  *
4529  * The initial checkpoint record is written to the beginning of the WAL
4530  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
4531  * used, so that we can use 0/0 to mean "before any valid WAL segment".
4532  */
4533  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
4534  checkPoint.ThisTimeLineID = BootstrapTimeLineID;
4535  checkPoint.PrevTimeLineID = BootstrapTimeLineID;
4536  checkPoint.fullPageWrites = fullPageWrites;
4537  checkPoint.nextXid =
4539  checkPoint.nextOid = FirstGenbkiObjectId;
4540  checkPoint.nextMulti = FirstMultiXactId;
4541  checkPoint.nextMultiOffset = 0;
4542  checkPoint.oldestXid = FirstNormalTransactionId;
4543  checkPoint.oldestXidDB = Template1DbOid;
4544  checkPoint.oldestMulti = FirstMultiXactId;
4545  checkPoint.oldestMultiDB = Template1DbOid;
4548  checkPoint.time = (pg_time_t) time(NULL);
4550 
4551  ShmemVariableCache->nextXid = checkPoint.nextXid;
4552  ShmemVariableCache->nextOid = checkPoint.nextOid;
4554  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
4555  AdvanceOldestClogXid(checkPoint.oldestXid);
4556  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
4557  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
4559 
4560  /* Set up the XLOG page header */
4561  page->xlp_magic = XLOG_PAGE_MAGIC;
4562  page->xlp_info = XLP_LONG_HEADER;
4563  page->xlp_tli = BootstrapTimeLineID;
4565  longpage = (XLogLongPageHeader) page;
4566  longpage->xlp_sysid = sysidentifier;
4567  longpage->xlp_seg_size = wal_segment_size;
4568  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
4569 
4570  /* Insert the initial checkpoint record */
4571  recptr = ((char *) page + SizeOfXLogLongPHD);
4572  record = (XLogRecord *) recptr;
4573  record->xl_prev = 0;
4574  record->xl_xid = InvalidTransactionId;
4575  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
4577  record->xl_rmid = RM_XLOG_ID;
4578  recptr += SizeOfXLogRecord;
4579  /* fill the XLogRecordDataHeaderShort struct */
4580  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
4581  *(recptr++) = sizeof(checkPoint);
4582  memcpy(recptr, &checkPoint, sizeof(checkPoint));
4583  recptr += sizeof(checkPoint);
4584  Assert(recptr - (char *) record == record->xl_tot_len);
4585 
4586  INIT_CRC32C(crc);
4587  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
4588  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
4589  FIN_CRC32C(crc);
4590  record->xl_crc = crc;
4591 
4592  /* Create first XLOG segment file */
4595 
4596  /*
4597  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
4598  * close the file again in a moment.
4599  */
4600 
4601  /* Write the first page with the initial record */
4602  errno = 0;
4604  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
4605  {
4606  /* if write didn't set errno, assume problem is no disk space */
4607  if (errno == 0)
4608  errno = ENOSPC;
4609  ereport(PANIC,
4611  errmsg("could not write bootstrap write-ahead log file: %m")));
4612  }
4614 
4616  if (pg_fsync(openLogFile) != 0)
4617  ereport(PANIC,
4619  errmsg("could not fsync bootstrap write-ahead log file: %m")));
4621 
4622  if (close(openLogFile) != 0)
4623  ereport(PANIC,
4625  errmsg("could not close bootstrap write-ahead log file: %m")));
4626 
4627  openLogFile = -1;
4628 
4629  /* Now create pg_control */
4630  InitControlFile(sysidentifier);
4631  ControlFile->time = checkPoint.time;
4632  ControlFile->checkPoint = checkPoint.redo;
4633  ControlFile->checkPointCopy = checkPoint;
4634 
4635  /* some additional ControlFile fields are set in WriteControlFile() */
4636  WriteControlFile();
4637 
4638  /* Bootstrap the commit log, too */
4639  BootStrapCLOG();
4643 
4644  pfree(buffer);
4645 
4646  /*
4647  * Force control file to be read - in contrast to normal processing we'd
4648  * otherwise never run the checks and GUC related initializations therein.
4649  */
4650  ReadControlFile();
4651 }
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:750
#define offsetof(type, field)
Definition: c.h:727
void BootStrapCLOG(void)
Definition: clog.c:713
void BootStrapCommitTs(void)
Definition: commit_ts.c:574
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:881
int errcode_for_file_access(void)
Definition: elog.c:716
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define PANIC
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:143
int pg_fsync(int fd)
Definition: fd.c:359
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1196
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1800
@ LW_EXCLUSIVE
Definition: lwlock.h:104
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
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
bool InstallXLogFileSegmentActive
Definition: xlog.c:528
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:222
@ WAIT_EVENT_WAL_BOOTSTRAP_WRITE
Definition: wait_event.h:223
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:266
static void pgstat_report_wait_end(void)
Definition: wait_event.h:282
int XLogFileInit(XLogSegNo logsegno, TimeLineID logtli)
Definition: xlog.c:3106
static XLogCtlData * XLogCtl
Definition: xlog.c:558
bool fullPageWrites
Definition: xlog.c:123
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:3871
static int openLogFile
Definition: xlog.c:614
static void WriteControlFile(void)
Definition: xlog.c:3906
int wal_segment_size
Definition: xlog.c:144
static TimeLineID openLogTLI
Definition: xlog.c:616
static ControlFileData * ControlFile
Definition: xlog.c:566
#define BootstrapTimeLineID
Definition: xlog.c:112
static void ReadControlFile(void)
Definition: xlog.c:3997
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:206
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:230
#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(), XLogCtlData::InstallXLogFileSegmentActive, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, VariableCacheData::nextOid, CheckPoint::nextOid, VariableCacheData::nextXid, CheckPoint::nextXid, offsetof, 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(), 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, XLogCtl, 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 3454 of file xlog.c.

3455 {
3456  int save_errno = errno;
3457  XLogSegNo lastRemovedSegNo;
3458 
3460  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3462 
3463  if (segno <= lastRemovedSegNo)
3464  {
3465  char filename[MAXFNAMELEN];
3466 
3467  XLogFileName(filename, tli, segno, wal_segment_size);
3468  errno = save_errno;
3469  ereport(ERROR,
3471  errmsg("requested WAL segment %s has already been removed",
3472  filename)));
3473  }
3474  errno = save_errno;
3475 }
#define ERROR
Definition: elog.h:33
static char * filename
Definition: pg_dumpall.c:94
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t info_lck
Definition: xlog.c:555
XLogSegNo lastRemovedSegNo
Definition: xlog.c:466
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
#define MAXFNAMELEN
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 6270 of file xlog.c.

6271 {
6272  bool shutdown;
6273  CheckPoint checkPoint;
6274  XLogRecPtr recptr;
6275  XLogSegNo _logSegNo;
6277  uint32 freespace;
6278  XLogRecPtr PriorRedoPtr;
6279  XLogRecPtr curInsert;
6280  XLogRecPtr last_important_lsn;
6281  VirtualTransactionId *vxids;
6282  int nvxids;
6283  int oldXLogAllowed = 0;
6284 
6285  /*
6286  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
6287  * issued at a different time.
6288  */
6290  shutdown = true;
6291  else
6292  shutdown = false;
6293 
6294  /* sanity check */
6295  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
6296  elog(ERROR, "can't create a checkpoint during recovery");
6297 
6298  /*
6299  * Prepare to accumulate statistics.
6300  *
6301  * Note: because it is possible for log_checkpoints to change while a
6302  * checkpoint proceeds, we always accumulate stats, even if
6303  * log_checkpoints is currently off.
6304  */
6305  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
6307 
6308  /*
6309  * Let smgr prepare for checkpoint; this has to happen outside the
6310  * critical section and before we determine the REDO pointer. Note that
6311  * smgr must not do anything that'd have to be undone if we decide no
6312  * checkpoint is needed.
6313  */
6315 
6316  /*
6317  * Use a critical section to force system panic if we have trouble.
6318  */
6320 
6321  if (shutdown)
6322  {
6323  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6326  LWLockRelease(ControlFileLock);
6327  }
6328 
6329  /* Begin filling in the checkpoint WAL record */
6330  MemSet(&checkPoint, 0, sizeof(checkPoint));
6331  checkPoint.time = (pg_time_t) time(NULL);
6332 
6333  /*
6334  * For Hot Standby, derive the oldestActiveXid before we fix the redo
6335  * pointer. This allows us to begin accumulating changes to assemble our
6336  * starting snapshot of locks and transactions.
6337  */
6338  if (!shutdown && XLogStandbyInfoActive())
6340  else
6342 
6343  /*
6344  * Get location of last important record before acquiring insert locks (as
6345  * GetLastImportantRecPtr() also locks WAL locks).
6346  */
6347  last_important_lsn = GetLastImportantRecPtr();
6348 
6349  /*
6350  * We must block concurrent insertions while examining insert state to
6351  * determine the checkpoint REDO pointer.
6352  */
6354  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
6355 
6356  /*
6357  * If this isn't a shutdown or forced checkpoint, and if there has been no
6358  * WAL activity requiring a checkpoint, skip it. The idea here is to
6359  * avoid inserting duplicate checkpoints when the system is idle.
6360  */
6362  CHECKPOINT_FORCE)) == 0)
6363  {
6364  if (last_important_lsn == ControlFile->checkPoint)
6365  {
6367  END_CRIT_SECTION();
6368  ereport(DEBUG1,
6369  (errmsg_internal("checkpoint skipped because system is idle")));
6370  return;
6371  }
6372  }
6373 
6374  /*
6375  * An end-of-recovery checkpoint is created before anyone is allowed to
6376  * write WAL. To allow us to write the checkpoint record, temporarily
6377  * enable XLogInsertAllowed.
6378  */
6379  if (flags & CHECKPOINT_END_OF_RECOVERY)
6380  oldXLogAllowed = LocalSetXLogInsertAllowed();
6381 
6382  checkPoint.ThisTimeLineID = XLogCtl->InsertTimeLineID;
6383  if (flags & CHECKPOINT_END_OF_RECOVERY)
6384  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
6385  else
6386  checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
6387 
6388  checkPoint.fullPageWrites = Insert->fullPageWrites;
6389 
6390  /*
6391  * Compute new REDO record ptr = location of next XLOG record.
6392  *
6393  * NB: this is NOT necessarily where the checkpoint record itself will be,
6394  * since other backends may insert more XLOG records while we're off doing
6395  * the buffer flush work. Those XLOG records are logically after the
6396  * checkpoint, even though physically before it. Got that?
6397  */
6398  freespace = INSERT_FREESPACE(curInsert);
6399  if (freespace == 0)
6400  {
6401  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
6402  curInsert += SizeOfXLogLongPHD;
6403  else
6404  curInsert += SizeOfXLogShortPHD;
6405  }
6406  checkPoint.redo = curInsert;
6407 
6408  /*
6409  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
6410  * must be done while holding all the insertion locks.
6411  *
6412  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
6413  * pointing past where it really needs to point. This is okay; the only
6414  * consequence is that XLogInsert might back up whole buffers that it
6415  * didn't really need to. We can't postpone advancing RedoRecPtr because
6416  * XLogInserts that happen while we are dumping buffers must assume that
6417  * their buffer changes are not included in the checkpoint.
6418  */
6419  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
6420 
6421  /*
6422  * Now we can release the WAL insertion locks, allowing other xacts to
6423  * proceed while we are flushing disk buffers.
6424  */
6426 
6427  /* Update the info_lck-protected copy of RedoRecPtr as well */
6429  XLogCtl->RedoRecPtr = checkPoint.redo;
6431 
6432  /*
6433  * If enabled, log checkpoint start. We postpone this until now so as not
6434  * to log anything if we decided to skip the checkpoint.
6435  */
6436  if (log_checkpoints)
6437  LogCheckpointStart(flags, false);
6438 
6439  /* Update the process title */
6440  update_checkpoint_display(flags, false, false);
6441 
6442  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
6443 
6444  /*
6445  * Get the other info we need for the checkpoint record.
6446  *
6447  * We don't need to save oldestClogXid in the checkpoint, it only matters
6448  * for the short period in which clog is being truncated, and if we crash
6449  * during that we'll redo the clog truncation and fix up oldestClogXid
6450  * there.
6451  */
6452  LWLockAcquire(XidGenLock, LW_SHARED);
6453  checkPoint.nextXid = ShmemVariableCache->nextXid;
6454  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
6456  LWLockRelease(XidGenLock);
6457 
6458  LWLockAcquire(CommitTsLock, LW_SHARED);
6461  LWLockRelease(CommitTsLock);
6462 
6463  LWLockAcquire(OidGenLock, LW_SHARED);
6464  checkPoint.nextOid = ShmemVariableCache->nextOid;
6465  if (!shutdown)
6466  checkPoint.nextOid += ShmemVariableCache->oidCount;
6467  LWLockRelease(OidGenLock);
6468 
6469  MultiXactGetCheckptMulti(shutdown,
6470  &checkPoint.nextMulti,
6471  &checkPoint.nextMultiOffset,
6472  &checkPoint.oldestMulti,
6473  &checkPoint.oldestMultiDB);
6474 
6475  /*
6476  * Having constructed the checkpoint record, ensure all shmem disk buffers
6477  * and commit-log buffers are flushed to disk.
6478  *
6479  * This I/O could fail for various reasons. If so, we will fail to
6480  * complete the checkpoint, but there is no reason to force a system
6481  * panic. Accordingly, exit critical section while doing it.
6482  */
6483  END_CRIT_SECTION();
6484 
6485  /*
6486  * In some cases there are groups of actions that must all occur on one
6487  * side or the other of a checkpoint record. Before flushing the
6488  * checkpoint record we must explicitly wait for any backend currently
6489  * performing those groups of actions.
6490  *
6491  * One example is end of transaction, so we must wait for any transactions
6492  * that are currently in commit critical sections. If an xact inserted
6493  * its commit record into XLOG just before the REDO point, then a crash
6494  * restart from the REDO point would not replay that record, which means
6495  * that our flushing had better include the xact's update of pg_xact. So
6496  * we wait till he's out of his commit critical section before proceeding.
6497  * See notes in RecordTransactionCommit().
6498  *
6499  * Because we've already released the insertion locks, this test is a bit
6500  * fuzzy: it is possible that we will wait for xacts we didn't really need
6501  * to wait for. But the delay should be short and it seems better to make
6502  * checkpoint take a bit longer than to hold off insertions longer than
6503  * necessary. (In fact, the whole reason we have this issue is that xact.c
6504  * does commit record XLOG insertion and clog update as two separate steps
6505  * protected by different locks, but again that seems best on grounds of
6506  * minimizing lock contention.)
6507  *
6508  * A transaction that has not yet set delayChkptFlags when we look cannot
6509  * be at risk, since it has not inserted its commit record yet; and one
6510  * that's already cleared it is not at risk either, since it's done fixing
6511  * clog and we will correctly flush the update below. So we cannot miss
6512  * any xacts we need to wait for.
6513  */
6515  if (nvxids > 0)
6516  {
6517  do
6518  {
6519  pg_usleep(10000L); /* wait for 10 msec */
6520  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6522  }
6523  pfree(vxids);
6524 
6525  CheckPointGuts(checkPoint.redo, flags);
6526 
6528  if (nvxids > 0)
6529  {
6530  do
6531  {
6532  pg_usleep(10000L); /* wait for 10 msec */
6533  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6535  }
6536  pfree(vxids);
6537 
6538  /*
6539  * Take a snapshot of running transactions and write this to WAL. This
6540  * allows us to reconstruct the state of running transactions during
6541  * archive recovery, if required. Skip, if this info disabled.
6542  *
6543  * If we are shutting down, or Startup process is completing crash
6544  * recovery we don't need to write running xact data.
6545  */
6546  if (!shutdown && XLogStandbyInfoActive())
6548 
6550 
6551  /*
6552  * Now insert the checkpoint record into XLOG.
6553  */
6554  XLogBeginInsert();
6555  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
6556  recptr = XLogInsert(RM_XLOG_ID,
6557  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
6559 
6560  XLogFlush(recptr);
6561 
6562  /*
6563  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
6564  * overwritten at next startup. No-one should even try, this just allows
6565  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
6566  * to just temporarily disable writing until the system has exited
6567  * recovery.
6568  */
6569  if (shutdown)
6570  {
6571  if (flags & CHECKPOINT_END_OF_RECOVERY)
6572  LocalXLogInsertAllowed = oldXLogAllowed;
6573  else
6574  LocalXLogInsertAllowed = 0; /* never again write WAL */
6575  }
6576 
6577  /*
6578  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
6579  * = end of actual checkpoint record.
6580  */
6581  if (shutdown && checkPoint.redo != ProcLastRecPtr)
6582  ereport(PANIC,
6583  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
6584 
6585  /*
6586  * Remember the prior checkpoint's redo ptr for
6587  * UpdateCheckPointDistanceEstimate()
6588  */
6589  PriorRedoPtr = ControlFile->checkPointCopy.redo;
6590 
6591  /*
6592  * Update the control file.
6593  */
6594  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6595  if (shutdown)
6598  ControlFile->checkPointCopy = checkPoint;
6599  /* crash recovery should always recover to the end of WAL */
6602 
6603  /*
6604  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
6605  * unused on non-shutdown checkpoints, but seems useful to store it always
6606  * for debugging purposes.
6607  */
6611 
6613  LWLockRelease(ControlFileLock);
6614 
6615  /* Update shared-memory copy of checkpoint XID/epoch */
6617  XLogCtl->ckptFullXid = checkPoint.nextXid;
6619 
6620  /*
6621  * We are now done with critical updates; no need for system panic if we
6622  * have trouble while fooling with old log segments.
6623  */
6624  END_CRIT_SECTION();
6625 
6626  /*
6627  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
6628  */
6630 
6631  /*
6632  * Update the average distance between checkpoints if the prior checkpoint
6633  * exists.
6634  */
6635  if (PriorRedoPtr != InvalidXLogRecPtr)
6637 
6638  /*
6639  * Delete old log files, those no longer needed for last checkpoint to
6640  * prevent the disk holding the xlog from growing full.
6641  */
6643  KeepLogSeg(recptr, &_logSegNo);
6644  if (InvalidateObsoleteReplicationSlots(_logSegNo))
6645  {
6646  /*
6647  * Some slots have been invalidated; recalculate the old-segment
6648  * horizon, starting again from RedoRecPtr.
6649  */
6651  KeepLogSeg(recptr, &_logSegNo);
6652  }
6653  _logSegNo--;
6654  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
6655  checkPoint.ThisTimeLineID);
6656 
6657  /*
6658  * Make more log segments if needed. (Do this after recycling old log
6659  * segments, since that may supply some of the needed files.)
6660  */
6661  if (!shutdown)
6662  PreallocXlogFiles(recptr, checkPoint.ThisTimeLineID);
6663 
6664  /*
6665  * Truncate pg_subtrans if possible. We can throw away all data before
6666  * the oldest XMIN of any running transaction. No future transaction will
6667  * attempt to reference any pg_subtrans entry older than that (see Asserts
6668  * in subtrans.c). During recovery, though, we mustn't do this because
6669  * StartupSUBTRANS hasn't been called yet.
6670  */
6671  if (!RecoveryInProgress())
6673 
6674  /* Real work is done; log and update stats. */
6675  LogCheckpointEnd(false);
6676 
6677  /* Reset the process title */
6678  update_checkpoint_display(flags, false, true);
6679 
6680  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
6681  NBuffers,
6685 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
unsigned int uint32
Definition: c.h:441
#define MemSet(start, val, len)
Definition: c.h:1008
int errmsg_internal(const char *fmt,...)
Definition: elog.c:991
#define DEBUG1
Definition: elog.h:24
#define elog(elevel,...)
Definition: elog.h:218
static void Insert(File file)
Definition: fd.c:1304
int NBuffers
Definition: globals.c:136
@ LW_SHARED
Definition: lwlock.h:105
#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 DELAY_CHKPT_START
Definition: proc.h:117
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:118
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
Definition: procarray.c:3075
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2912
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:2050
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
Definition: procarray.c:3121
void pg_usleep(long microsec)
Definition: signal.c:53
bool InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno)
Definition: slot.c:1393
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:1222
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:462
TimeLineID InsertTimeLineID
Definition: xlog.c:511
slock_t ulsn_lck
Definition: xlog.c:470
XLogRecPtr RedoRecPtr
Definition: xlog.c:461
XLogRecPtr unloggedLSN
Definition: xlog.c:469
XLogCtlInsert Insert
Definition: xlog.c:457
TimeLineID PrevTimeLineID
Definition: xlog.c:512
XLogRecPtr RedoRecPtr
Definition: xlog.c:433
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:250
bool RecoveryInProgress(void)
Definition: xlog.c:5753
static void WALInsertLockRelease(void)
Definition: xlog.c:1376
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1645
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1347
static void UpdateControlFile(void)
Definition: xlog.c:4197
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr, TimeLineID insertTLI)
Definition: xlog.c:3555
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:6051
static XLogRecPtr RedoRecPtr
Definition: xlog.c:270
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:6083
static void PreallocXlogFiles(XLogRecPtr endptr, TimeLineID tli)
Definition: xlog.c:3417
bool log_checkpoints
Definition: xlog.c:130
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:7264
static int LocalSetXLogInsertAllowed(void)
Definition: xlog.c:5841
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:5958
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:6175
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:572
static int LocalXLogInsertAllowed
Definition: xlog.c:233
CheckpointStatsData CheckpointStats
Definition: xlog.c:206
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2509
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:6830
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:6213
#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
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:443
void XLogBeginInsert(void)
Definition: xloginsert.c:150
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:351

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(), 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(), 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 6911 of file xlog.c.

6912 {
6913  XLogRecPtr lastCheckPointRecPtr;
6914  XLogRecPtr lastCheckPointEndPtr;
6915  CheckPoint lastCheckPoint;
6916  XLogRecPtr PriorRedoPtr;
6917  XLogRecPtr receivePtr;
6918  XLogRecPtr replayPtr;
6919  TimeLineID replayTLI;
6920  XLogRecPtr endptr;
6921  XLogSegNo _logSegNo;
6922  TimestampTz xtime;
6923 
6924  /* Concurrent checkpoint/restartpoint cannot happen */
6926 
6927  /* Get a local copy of the last safe checkpoint record. */
6929  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
6930  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
6931  lastCheckPoint = XLogCtl->lastCheckPoint;
6933 
6934  /*
6935  * Check that we're still in recovery mode. It's ok if we exit recovery
6936  * mode after this check, the restart point is valid anyway.
6937  */
6938  if (!RecoveryInProgress())
6939  {
6940  ereport(DEBUG2,
6941  (errmsg_internal("skipping restartpoint, recovery has already ended")));
6942  return false;
6943  }
6944 
6945  /*
6946  * If the last checkpoint record we've replayed is already our last
6947  * restartpoint, we can't perform a new restart point. We still update
6948  * minRecoveryPoint in that case, so that if this is a shutdown restart
6949  * point, we won't start up earlier than before. That's not strictly
6950  * necessary, but when hot standby is enabled, it would be rather weird if
6951  * the database opened up for read-only connections at a point-in-time
6952  * before the last shutdown. Such time travel is still possible in case of
6953  * immediate shutdown, though.
6954  *
6955  * We don't explicitly advance minRecoveryPoint when we do create a
6956  * restartpoint. It's assumed that flushing the buffers will do that as a
6957  * side-effect.
6958  */
6959  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
6960  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
6961  {
6962  ereport(DEBUG2,
6963  (errmsg_internal("skipping restartpoint, already performed at %X/%X",
6964  LSN_FORMAT_ARGS(lastCheckPoint.redo))));
6965 
6967  if (flags & CHECKPOINT_IS_SHUTDOWN)
6968  {
6969  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6972  LWLockRelease(ControlFileLock);
6973  }
6974  return false;
6975  }
6976 
6977  /*
6978  * Update the shared RedoRecPtr so that the startup process can calculate
6979  * the number of segments replayed since last restartpoint, and request a
6980  * restartpoint if it exceeds CheckPointSegments.
6981  *
6982  * Like in CreateCheckPoint(), hold off insertions to update it, although
6983  * during recovery this is just pro forma, because no WAL insertions are
6984  * happening.
6985  */
6987  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
6989 
6990  /* Also update the info_lck-protected copy */
6992  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
6994 
6995  /*
6996  * Prepare to accumulate statistics.
6997  *
6998  * Note: because it is possible for log_checkpoints to change while a
6999  * checkpoint proceeds, we always accumulate stats, even if
7000  * log_checkpoints is currently off.
7001  */
7002  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
7004 
7005  if (log_checkpoints)
7006  LogCheckpointStart(flags, true);
7007 
7008  /* Update the process title */
7009  update_checkpoint_display(flags, true, false);
7010 
7011  CheckPointGuts(lastCheckPoint.redo, flags);
7012 
7013  /*
7014  * Remember the prior checkpoint's redo ptr for
7015  * UpdateCheckPointDistanceEstimate()
7016  */
7017  PriorRedoPtr = ControlFile->checkPointCopy.redo;
7018 
7019  /*
7020  * Update pg_control, using current time. Check that it still shows an
7021  * older checkpoint, else do nothing; this is a quick hack to make sure
7022  * nothing really bad happens if somehow we get here after the
7023  * end-of-recovery checkpoint.
7024  */
7025  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7026  if (ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
7027  {
7028  /*
7029  * Update the checkpoint information. We do this even if the cluster
7030  * does not show DB_IN_ARCHIVE_RECOVERY to match with the set of WAL
7031  * segments recycled below.
7032  */
7033  ControlFile->checkPoint = lastCheckPointRecPtr;
7034  ControlFile->checkPointCopy = lastCheckPoint;
7035 
7036  /*
7037  * Ensure minRecoveryPoint is past the checkpoint record and update it
7038  * if the control file still shows DB_IN_ARCHIVE_RECOVERY. Normally,
7039  * this will have happened already while writing out dirty buffers,
7040  * but not necessarily - e.g. because no buffers were dirtied. We do
7041  * this because a backup performed in recovery uses minRecoveryPoint
7042  * to determine which WAL files must be included in the backup, and
7043  * the file (or files) containing the checkpoint record must be
7044  * included, at a minimum. Note that for an ordinary restart of
7045  * recovery there's no value in having the minimum recovery point any
7046  * earlier than this anyway, because redo will begin just after the
7047  * checkpoint record.
7048  */
7050  {
7051  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
7052  {
7053  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
7055 
7056  /* update local copy */
7059  }
7060  if (flags & CHECKPOINT_IS_SHUTDOWN)
7062  }
7064  }
7065  LWLockRelease(ControlFileLock);
7066 
7067  /*
7068  * Update the average distance between checkpoints/restartpoints if the
7069  * prior checkpoint exists.
7070  */
7071  if (PriorRedoPtr != InvalidXLogRecPtr)
7073 
7074  /*
7075  * Delete old log files, those no longer needed for last restartpoint to
7076  * prevent the disk holding the xlog from growing full.
7077  */
7079 
7080  /*
7081  * Retreat _logSegNo using the current end of xlog replayed or received,
7082  * whichever is later.
7083  */
7084  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
7085  replayPtr = GetXLogReplayRecPtr(&replayTLI);
7086  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
7087  KeepLogSeg(endptr, &_logSegNo);
7088  if (InvalidateObsoleteReplicationSlots(_logSegNo))
7089  {
7090  /*
7091  * Some slots have been invalidated; recalculate the old-segment
7092  * horizon, starting again from RedoRecPtr.
7093  */
7095  KeepLogSeg(endptr, &_logSegNo);
7096  }
7097  _logSegNo--;
7098 
7099  /*
7100  * Try to recycle segments on a useful timeline. If we've been promoted
7101  * since the beginning of this restartpoint, use the new timeline chosen
7102  * at end of recovery. If we're still in recovery, use the timeline we're
7103  * currently replaying.
7104  *
7105  * There is no guarantee that the WAL segments will be useful on the
7106  * current timeline; if recovery proceeds to a new timeline right after
7107  * this, the pre-allocated WAL segments on this timeline will not be used,
7108  * and will go wasted until recycled on the next restartpoint. We'll live
7109  * with that.
7110  */
7111  if (!RecoveryInProgress())
7112  replayTLI = XLogCtl->InsertTimeLineID;
7113 
7114  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, replayTLI);
7115 
7116  /*
7117  * Make more log segments if needed. (Do this after recycling old log
7118  * segments, since that may supply some of the needed files.)
7119  */
7120  PreallocXlogFiles(endptr, replayTLI);
7121 
7122  /*
7123  * Truncate pg_subtrans if possible. We can throw away all data before
7124  * the oldest XMIN of any running transaction. No future transaction will
7125  * attempt to reference any pg_subtrans entry older than that (see Asserts
7126  * in subtrans.c). When hot standby is disabled, though, we mustn't do
7127  * this because StartupSUBTRANS hasn't been called yet.
7128  */
7129  if (EnableHotStandby)
7131 
7132  /* Real work is done; log and update stats. */
7133  LogCheckpointEnd(true);
7134 
7135  /* Reset the process title */
7136  update_checkpoint_display(flags, true, true);
7137 
7138  xtime = GetLatestXTime();
7140  (errmsg("recovery restart point at %X/%X",
7141  LSN_FORMAT_ARGS(lastCheckPoint.redo)),
7142  xtime ? errdetail("Last completed transaction was at log time %s.",
7143  timestamptz_to_str(xtime)) : 0));
7144 
7145  /*
7146  * Finally, execute archive_cleanup_command, if any.
7147  */
7148  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
7150  "archive_cleanup_command",
7151  false,
7153 
7154  return true;
7155 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1768
int64 TimestampTz
Definition: timestamp.h:39
int errdetail(const char *fmt,...)
Definition: elog.c:1037
#define LOG
Definition: elog.h:25
#define DEBUG2
Definition: elog.h:23
bool IsUnderPostmaster
Definition: globals.c:113
@ B_CHECKPOINTER
Definition: miscadmin.h:332
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:547
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:545
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:546
@ WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND
Definition: wait_event.h:82
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
bool EnableHotStandby
Definition: xlog.c:122
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2429
static XLogRecPtr LocalMinRecoveryPoint
Definition: xlog.c:625
static TimeLineID LocalMinRecoveryPointTLI
Definition: xlog.c:626
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal, uint32 wait_event_info)
Definition: xlogarchive.c:290
#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:80
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(), 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(), 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 8759 of file xlog.c.

8760 {
8761  bool emit_warning = DatumGetBool(arg);
8762 
8763  /*
8764  * Quick exit if session does not have a running backup.
8765  */
8767  return;
8768 
8772 
8773  if (XLogCtl->Insert.runningBackups == 0)
8774  {
8775  XLogCtl->Insert.forcePageWrites = false;
8776  }
8778 
8779  if (emit_warning)
8780  ereport(WARNING,
8781  (errmsg("aborting backup due to backend exiting before pg_backup_stop was called")));
8782 }
#define WARNING
Definition: elog.h:30
void * arg
#define DatumGetBool(X)
Definition: postgres.h:437
bool forcePageWrites
Definition: xlog.c:434
int runningBackups
Definition: xlog.c:443
static SessionBackupState sessionBackupState
Definition: xlog.c:394
@ SESSION_BACKUP_RUNNING
Definition: xlog.h:277

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

Referenced by perform_base_backup(), and register_persistent_abort_backup_handler().

◆ do_pg_backup_start()

XLogRecPtr do_pg_backup_start ( const char *  backupidstr,
bool  fast,
TimeLineID starttli_p,
StringInfo  labelfile,
List **  tablespaces,
StringInfo  tblspcmapfile 
)

Definition at line 8077 of file xlog.c.

8080 {
8081  bool backup_started_in_recovery = false;
8082  XLogRecPtr checkpointloc;
8083  XLogRecPtr startpoint;
8084  TimeLineID starttli;
8085  pg_time_t stamp_time;
8086  char strfbuf[128];
8087  char xlogfilename[MAXFNAMELEN];
8088  XLogSegNo _logSegNo;
8089 
8091 
8092  /*
8093  * During recovery, we don't need to check WAL level. Because, if WAL
8094  * level is not sufficient, it's impossible to get here during recovery.
8095  */
8097  ereport(ERROR,
8098  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8099  errmsg("WAL level not sufficient for making an online backup"),
8100  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8101 
8102  if (strlen(backupidstr) > MAXPGPATH)
8103  ereport(ERROR,
8104  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8105  errmsg("backup label too long (max %d bytes)",
8106  MAXPGPATH)));
8107 
8108  /*
8109  * Mark backup active in shared memory. We must do full-page WAL writes
8110  * during an on-line backup even if not doing so at other times, because
8111  * it's quite possible for the backup dump to obtain a "torn" (partially
8112  * written) copy of a database page if it reads the page concurrently with
8113  * our write to the same page. This can be fixed as long as the first
8114  * write to the page in the WAL sequence is a full-page write. Hence, we
8115  * turn on forcePageWrites and then force a CHECKPOINT, to ensure there
8116  * are no dirty pages in shared memory that might get dumped while the
8117  * backup is in progress without having a corresponding WAL record. (Once
8118  * the backup is complete, we need not force full-page writes anymore,
8119  * since we expect that any pages not modified during the backup interval
8120  * must have been correctly captured by the backup.)
8121  *
8122  * Note that forcePageWrites has no effect during an online backup from
8123  * the standby.
8124  *
8125  * We must hold all the insertion locks to change the value of
8126  * forcePageWrites, to ensure adequate interlocking against
8127  * XLogInsertRecord().
8128  */
8131  XLogCtl->Insert.forcePageWrites = true;
8133 
8134  /* Ensure we release forcePageWrites if fail below */
8136  {
8137  bool gotUniqueStartpoint = false;
8138  DIR *tblspcdir;
8139  struct dirent *de;
8140  tablespaceinfo *ti;
8141  int datadirpathlen;
8142 
8143  /*
8144  * Force an XLOG file switch before the checkpoint, to ensure that the
8145  * WAL segment the checkpoint is written to doesn't contain pages with
8146  * old timeline IDs. That would otherwise happen if you called
8147  * pg_backup_start() right after restoring from a PITR archive: the
8148  * first WAL segment containing the startup checkpoint has pages in
8149  * the beginning with the old timeline ID. That can cause trouble at
8150  * recovery: we won't have a history file covering the old timeline if
8151  * pg_wal directory was not included in the base backup and the WAL
8152  * archive was cleared too before starting the backup.
8153  *
8154  * This also ensures that we have emitted a WAL page header that has
8155  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
8156  * Therefore, if a WAL archiver (such as pglesslog) is trying to
8157  * compress out removable backup blocks, it won't remove any that
8158  * occur after this point.
8159  *
8160  * During recovery, we skip forcing XLOG file switch, which means that
8161  * the backup taken during recovery is not available for the special
8162  * recovery case described above.
8163  */
8165  RequestXLogSwitch(false);
8166 
8167  do
8168  {
8169  bool checkpointfpw;
8170 
8171  /*
8172  * Force a CHECKPOINT. Aside from being necessary to prevent torn
8173  * page problems, this guarantees that two successive backup runs
8174  * will have different checkpoint positions and hence different
8175  * history file names, even if nothing happened in between.
8176  *
8177  * During recovery, establish a restartpoint if possible. We use
8178  * the last restartpoint as the backup starting checkpoint. This
8179  * means that two successive backup runs can have same checkpoint
8180  * positions.
8181  *
8182  * Since the fact that we are executing do_pg_backup_start()
8183  * during recovery means that checkpointer is running, we can use
8184  * RequestCheckpoint() to establish a restartpoint.
8185  *
8186  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
8187  * passing fast = true). Otherwise this can take awhile.
8188  */
8190  (fast ? CHECKPOINT_IMMEDIATE : 0));
8191 
8192  /*
8193  * Now we need to fetch the checkpoint record location, and also
8194  * its REDO pointer. The oldest point in WAL that would be needed
8195  * to restore starting from the checkpoint is precisely the REDO
8196  * pointer.
8197  */
8198  LWLockAcquire(ControlFileLock, LW_SHARED);
8199  checkpointloc = ControlFile->checkPoint;
8200  startpoint = ControlFile->checkPointCopy.redo;
8202  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
8203  LWLockRelease(ControlFileLock);
8204 
8206  {
8207  XLogRecPtr recptr;
8208 
8209  /*
8210  * Check to see if all WAL replayed during online backup
8211  * (i.e., since last restartpoint used as backup starting
8212  * checkpoint) contain full-page writes.
8213  */
8215  recptr = XLogCtl->lastFpwDisableRecPtr;
8217 
8218  if (!checkpointfpw || startpoint <= recptr)
8219  ereport(ERROR,
8220  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8221  errmsg("WAL generated with full_page_writes=off was replayed "
8222  "since last restartpoint"),
8223  errhint("This means that the backup being taken on the standby "
8224  "is corrupt and should not be used. "
8225  "Enable full_page_writes and run CHECKPOINT on the primary, "
8226  "and then try an online backup again.")));
8227 
8228  /*
8229  * During recovery, since we don't use the end-of-backup WAL
8230  * record and don't write the backup history file, the
8231  * starting WAL location doesn't need to be unique. This means
8232  * that two base backups started at the same time might use
8233  * the same checkpoint as starting locations.
8234  */
8235  gotUniqueStartpoint = true;
8236  }
8237 
8238  /*
8239  * If two base backups are started at the same time (in WAL sender
8240  * processes), we need to make sure that they use different
8241  * checkpoints as starting locations, because we use the starting
8242  * WAL location as a unique identifier for the base backup in the
8243  * end-of-backup WAL record and when we write the backup history
8244  * file. Perhaps it would be better generate a separate unique ID
8245  * for each backup instead of forcing another checkpoint, but
8246  * taking a checkpoint right after another is not that expensive
8247  * either because only few buffers have been dirtied yet.
8248  */
8250  if (XLogCtl->Insert.lastBackupStart < startpoint)
8251  {
8252  XLogCtl->Insert.lastBackupStart = startpoint;
8253  gotUniqueStartpoint = true;
8254  }
8256  } while (!gotUniqueStartpoint);
8257 
8258  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
8259  XLogFileName(xlogfilename, starttli, _logSegNo, wal_segment_size);
8260 
8261  /*
8262  * Construct tablespace_map file.
8263  */
8264  datadirpathlen = strlen(DataDir);
8265 
8266  /* Collect information about all tablespaces */
8267  tblspcdir = AllocateDir("pg_tblspc");
8268  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
8269  {
8270  char fullpath[MAXPGPATH + 10];
8271  char linkpath[MAXPGPATH];
8272  char *relpath = NULL;
8273  int rllen;
8274  StringInfoData escapedpath;
8275  char *s;
8276 
8277  /* Skip anything that doesn't look like a tablespace */
8278  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
8279  continue;
8280 
8281  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
8282 
8283  /*
8284  * Skip anything that isn't a symlink/junction. For testing only,
8285  * we sometimes use allow_in_place_tablespaces to create
8286  * directories directly under pg_tblspc, which would fail below.
8287  */
8288 #ifdef WIN32
8289  if (!pgwin32_is_junction(fullpath))
8290  continue;
8291 #else
8292  if (get_dirent_type(fullpath, de, false, ERROR) != PGFILETYPE_LNK)
8293  continue;
8294 #endif
8295 
8296 #if defined(HAVE_READLINK) || defined(WIN32)
8297  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
8298  if (rllen < 0)
8299  {
8300  ereport(WARNING,
8301  (errmsg("could not read symbolic link \"%s\": %m",
8302  fullpath)));
8303  continue;
8304  }
8305  else if (rllen >= sizeof(linkpath))
8306  {
8307  ereport(WARNING,
8308  (errmsg("symbolic link \"%s\" target is too long",
8309  fullpath)));
8310  continue;
8311  }
8312  linkpath[rllen] = '\0';
8313 
8314  /*
8315  * Build a backslash-escaped version of the link path to include
8316  * in the tablespace map file.
8317  */
8318  initStringInfo(&escapedpath);
8319  for (s = linkpath; *s; s++)
8320  {
8321  if (*s == '\n' || *s == '\r' || *s == '\\')
8322  appendStringInfoChar(&escapedpath, '\\');
8323  appendStringInfoChar(&escapedpath, *s);
8324  }
8325 
8326  /*
8327  * Relpath holds the relative path of the tablespace directory
8328  * when it's located within PGDATA, or NULL if it's located
8329  * elsewhere.
8330  */
8331  if (rllen > datadirpathlen &&
8332  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
8333  IS_DIR_SEP(linkpath[datadirpathlen]))
8334  relpath = linkpath + datadirpathlen + 1;
8335 
8336  ti = palloc(sizeof(tablespaceinfo));
8337  ti->oid = pstrdup(de->d_name);
8338  ti->path = pstrdup(linkpath);
8339  ti->rpath = relpath ? pstrdup(relpath) : NULL;
8340  ti->size = -1;
8341 
8342  if (tablespaces)
8343  *tablespaces = lappend(*tablespaces, ti);
8344 
8345  appendStringInfo(tblspcmapfile, "%s %s\n",
8346  ti->oid, escapedpath.data);
8347 
8348  pfree(escapedpath.data);
8349 #else
8350 
8351  /*
8352  * If the platform does not have symbolic links, it should not be
8353  * possible to have tablespaces - clearly somebody else created
8354  * them. Warn about it and ignore.
8355  */
8356  ereport(WARNING,
8357  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8358  errmsg("tablespaces are not supported on this platform")));
8359 #endif
8360  }
8361  FreeDir(tblspcdir);
8362 
8363  /*
8364  * Construct backup label file.
8365  */
8366 
8367  /* Use the log timezone here, not the session timezone */
8368  stamp_time = (pg_time_t) time(NULL);
8369  pg_strftime(strfbuf, sizeof(strfbuf),
8370  "%Y-%m-%d %H:%M:%S %Z",
8371  pg_localtime(&stamp_time, log_timezone));
8372  appendStringInfo(labelfile, "START WAL LOCATION: %X/%X (file %s)\n",
8373  LSN_FORMAT_ARGS(startpoint), xlogfilename);
8374  appendStringInfo(labelfile, "CHECKPOINT LOCATION: %X/%X\n",
8375  LSN_FORMAT_ARGS(checkpointloc));
8376  appendStringInfo(labelfile, "BACKUP METHOD: streamed\n");
8377  appendStringInfo(labelfile, "BACKUP FROM: %s\n",
8378  backup_started_in_recovery ? "standby" : "primary");
8379  appendStringInfo(labelfile, "START TIME: %s\n", strfbuf);
8380  appendStringInfo(labelfile, "LABEL: %s\n", backupidstr);
8381  appendStringInfo(labelfile, "START TIMELINE: %u\n", starttli);
8382  }
8384 
8385  /*
8386  * Mark that the start phase has correctly finished for the backup.
8387  */
8389 
8390  /*
8391  * We're done. As a convenience, return the starting WAL location.
8392  */
8393  if (starttli_p)
8394  *starttli_p = starttli;
8395  return startpoint;
8396 }
static bool backup_started_in_recovery
Definition: basebackup.c:100
void RequestCheckpoint(int flags)
Definition: checkpointer.c:931
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2788
int FreeDir(DIR *dir)
Definition: fd.c:2840
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2722
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:410
@ PGFILETYPE_LNK
Definition: file_utils.h:24
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:336
char * pstrdup(const char *in)
Definition: mcxt.c:1305
#define MAXPGPATH
size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm *tm)
Definition: strftime.c:128
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1342
PGDLLIMPORT pg_tz * log_timezone
Definition: pgtz.c:31
#define snprintf
Definition: port.h:225
#define IS_DIR_SEP(ch)
Definition: port.h:87
uintptr_t Datum
Definition: postgres.h:411
#define relpath(rnode, forknum)
Definition: relpath.h:87
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:553
XLogRecPtr lastBackupStart
Definition: xlog.c:444
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
char * rpath
Definition: basebackup.h:32
bool pgwin32_is_junction(const char *path)
#define readlink(path, buf, size)
Definition: win32_port.h:236
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:7357
static void pg_backup_start_callback(int code, Datum arg)
Definition: xlog.c:8400
#define CHECKPOINT_WAIT
Definition: xlog.h:140
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:136
#define XLogIsNeeded()
Definition: xlog.h:104

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

Referenced by perform_base_backup(), and pg_backup_start().

◆ do_pg_backup_stop()

XLogRecPtr do_pg_backup_stop ( char *  labelfile,
bool  waitforarchive,
TimeLineID stoptli_p 
)

Definition at line 8437 of file xlog.c.

8438 {
8439  bool backup_started_in_recovery = false;
8440  XLogRecPtr startpoint;
8441  XLogRecPtr stoppoint;
8442  TimeLineID stoptli;
8443  pg_time_t stamp_time;
8444  char strfbuf[128];
8445  char histfilepath[MAXPGPATH];
8446  char startxlogfilename[MAXFNAMELEN];
8447  char stopxlogfilename[MAXFNAMELEN];
8448  char lastxlogfilename[MAXFNAMELEN];
8449  char histfilename[MAXFNAMELEN];
8450  char backupfrom[20];
8451  XLogSegNo _logSegNo;
8452  FILE *fp;
8453  char ch;
8454  int seconds_before_warning;
8455  int waits = 0;
8456  bool reported_waiting = false;
8457  char *remaining;
8458  char *ptr;
8459  uint32 hi,
8460  lo;
8461 
8463 
8464  /*
8465  * During recovery, we don't need to check WAL level. Because, if WAL
8466  * level is not sufficient, it's impossible to get here during recovery.
8467  */
8469  ereport(ERROR,
8470  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8471  errmsg("WAL level not sufficient for making an online backup"),
8472  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8473 
8474  /*
8475  * OK to update backup counters, forcePageWrites, and session-level lock.
8476  *
8477  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
8478  * Otherwise they can be updated inconsistently, and which might cause
8479  * do_pg_abort_backup() to fail.
8480  */
8482 
8483  /*
8484  * It is expected that each do_pg_backup_start() call is matched by
8485  * exactly one do_pg_backup_stop() call.
8486  */
8489 
8490  if (XLogCtl->Insert.runningBackups == 0)
8491  {
8492  XLogCtl->Insert.forcePageWrites = false;
8493  }
8494 
8495  /*
8496  * Clean up session-level lock.
8497  *
8498  * You might think that WALInsertLockRelease() can be called before
8499  * cleaning up session-level lock because session-level lock doesn't need
8500  * to be protected with WAL insertion lock. But since
8501  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
8502  * cleaned up before it.
8503  */
8505 
8507 
8508  /*
8509  * Read and parse the START WAL LOCATION line (this code is pretty crude,
8510  * but we are not expecting any variability in the file format).
8511  */
8512  if (sscanf(labelfile, "START WAL LOCATION: %X/%X (file %24s)%c",
8513  &hi, &lo, startxlogfilename,
8514  &ch) != 4 || ch != '\n')
8515  ereport(ERROR,
8516  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8517  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
8518  startpoint = ((uint64) hi) << 32 | lo;
8519  remaining = strchr(labelfile, '\n') + 1; /* %n is not portable enough */
8520 
8521  /*
8522  * Parse the BACKUP FROM line. If we are taking an online backup from the
8523  * standby, we confirm that the standby has not been promoted during the
8524  * backup.
8525  */
8526  ptr = strstr(remaining, "BACKUP FROM:");
8527  if (!ptr || sscanf(ptr, "BACKUP FROM: %19s\n", backupfrom) != 1)
8528  ereport(ERROR,
8529  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8530  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
8531  if (strcmp(backupfrom, "standby") == 0 && !backup_started_in_recovery)
8532  ereport(ERROR,
8533  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8534  errmsg("the standby was promoted during online backup"),
8535  errhint("This means that the backup being taken is corrupt "
8536  "and should not be used. "
8537  "Try taking another online backup.")));
8538 
8539  /*
8540  * During recovery, we don't write an end-of-backup record. We assume that
8541  * pg_control was backed up last and its minimum recovery point can be
8542  * available as the backup end location. Since we don't have an
8543  * end-of-backup record, we use the pg_control value to check whether
8544  * we've reached the end of backup when starting recovery from this
8545  * backup. We have no way of checking if pg_control wasn't backed up last
8546  * however.
8547  *
8548  * We don't force a switch to new WAL file but it is still possible to
8549  * wait for all the required files to be archived if waitforarchive is
8550  * true. This is okay if we use the backup to start a standby and fetch
8551  * the missing WAL using streaming replication. But in the case of an
8552  * archive recovery, a user should set waitforarchive to true and wait for
8553  * them to be archived to ensure that all the required files are
8554  * available.
8555  *
8556  * We return the current minimum recovery point as the backup end
8557  * location. Note that it can be greater than the exact backup end
8558  * location if the minimum recovery point is updated after the backup of
8559  * pg_control. This is harmless for current uses.
8560  *
8561  * XXX currently a backup history file is for informational and debug
8562  * purposes only. It's not essential for an online backup. Furthermore,
8563  * even if it's created, it will not be archived during recovery because
8564  * an archiver is not invoked. So it doesn't seem worthwhile to write a
8565  * backup history file during recovery.
8566  */
8568  {
8569  XLogRecPtr recptr;
8570 
8571  /*
8572  * Check to see if all WAL replayed during online backup contain
8573  * full-page writes.
8574  */
8576  recptr = XLogCtl->lastFpwDisableRecPtr;
8578 
8579  if (startpoint <= recptr)
8580  ereport(ERROR,
8581  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8582  errmsg("WAL generated with full_page_writes=off was replayed "
8583  "during online backup"),
8584  errhint("This means that the backup being taken on the standby "
8585  "is corrupt and should not be used. "
8586  "Enable full_page_writes and run CHECKPOINT on the primary, "
8587  "and then try an online backup again.")));
8588 
8589 
8590  LWLockAcquire(ControlFileLock, LW_SHARED);
8591  stoppoint = ControlFile->minRecoveryPoint;
8592  stoptli = ControlFile->minRecoveryPointTLI;
8593  LWLockRelease(ControlFileLock);
8594  }
8595  else
8596  {
8597  /*
8598  * Write the backup-end xlog record
8599  */
8600  XLogBeginInsert();
8601  XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
8602  stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
8603 
8604  /*
8605  * Given that we're not in recovery, InsertTimeLineID is set and can't
8606  * change, so we can read it without a lock.
8607  */
8608  stoptli = XLogCtl->InsertTimeLineID;
8609 
8610  /*
8611  * Force a switch to a new xlog segment file, so that the backup is
8612  * valid as soon as archiver moves out the current segment file.
8613  */
8614  RequestXLogSwitch(false);
8615 
8616  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
8617  XLogFileName(stopxlogfilename, stoptli, _logSegNo, wal_segment_size);
8618 
8619  /* Use the log timezone here, not the session timezone */
8620  stamp_time = (pg_time_t) time(NULL);
8621  pg_strftime(strfbuf, sizeof(strfbuf),
8622  "%Y-%m-%d %H:%M:%S %Z",
8623  pg_localtime(&stamp_time, log_timezone));
8624 
8625  /*
8626  * Write the backup history file
8627  */
8628  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
8629  BackupHistoryFilePath(histfilepath, stoptli, _logSegNo,
8630  startpoint, wal_segment_size);
8631  fp = AllocateFile(histfilepath, "w");
8632  if (!fp)
8633  ereport(ERROR,
8635  errmsg("could not create file \"%s\": %m",
8636  histfilepath)));
8637  fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
8638  LSN_FORMAT_ARGS(startpoint), startxlogfilename);
8639  fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
8640  LSN_FORMAT_ARGS(stoppoint), stopxlogfilename);
8641 
8642  /*
8643  * Transfer remaining lines including label and start timeline to
8644  * history file.
8645  */
8646  fprintf(fp, "%s", remaining);
8647  fprintf(fp, "STOP TIME: %s\n", strfbuf);
8648  fprintf(fp, "STOP TIMELINE: %u\n", stoptli);
8649  if (fflush(fp) || ferror(fp) || FreeFile(fp))
8650  ereport(ERROR,
8652  errmsg("could not write file \"%s\": %m",
8653  histfilepath)));
8654 
8655  /*
8656  * Clean out any no-longer-needed history files. As a side effect,
8657  * this will post a .ready file for the newly created history file,
8658  * notifying the archiver that history file may be archived
8659  * immediately.
8660  */
8662  }
8663 
8664  /*
8665  * If archiving is enabled, wait for all the required WAL files to be
8666  * archived before returning. If archiving isn't enabled, the required WAL
8667  * needs to be transported via streaming replication (hopefully with
8668  * wal_keep_size set high enough), or some more exotic mechanism like
8669  * polling and copying files from pg_wal with script. We have no knowledge
8670  * of those mechanisms, so it's up to the user to ensure that he gets all
8671  * the required WAL.
8672  *
8673  * We wait until both the last WAL file filled during backup and the
8674  * history file have been archived, and assume that the alphabetic sorting
8675  * property of the WAL files ensures any earlier WAL files are safely
8676  * archived as well.
8677  *
8678  * We wait forever, since archive_command is supposed to work and we
8679  * assume the admin wanted his backup to work completely. If you don't
8680  * wish to wait, then either waitforarchive should be passed in as false,
8681  * or you can set statement_timeout. Also, some notices are issued to
8682  * clue in anyone who might be doing this interactively.
8683  */
8684 
8685  if (waitforarchive &&
8688  {
8689  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
8690  XLogFileName(lastxlogfilename, stoptli, _logSegNo, wal_segment_size);
8691 
8692  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
8693  BackupHistoryFileName(histfilename, stoptli, _logSegNo,
8694  startpoint, wal_segment_size);
8695 
8696  seconds_before_warning = 60;
8697  waits = 0;
8698 
8699  while (XLogArchiveIsBusy(lastxlogfilename) ||
8700  XLogArchiveIsBusy(histfilename))
8701  {
8703 
8704  if (!reported_waiting && waits > 5)
8705  {
8706  ereport(NOTICE,
8707  (errmsg("base backup done, waiting for required WAL segments to be archived")));
8708  reported_waiting = true;
8709  }
8710 
8711  (void) WaitLatch(MyLatch,
8713  1000L,
8716 
8717  if (++waits >= seconds_before_warning)
8718  {
8719  seconds_before_warning *= 2; /* This wraps in >10 years... */
8720  ereport(WARNING,
8721  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
8722  waits),
8723  errhint("Check that your archive_command is executing properly. "
8724  "You can safely cancel this backup, "
8725  "but the database backup will not be usable without all the WAL segments.")));
8726  }
8727  }
8728 
8729  ereport(NOTICE,
8730  (errmsg("all required WAL segments have been archived")));
8731  }
8732  else if (waitforarchive)
8733  ereport(NOTICE,
8734  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
8735 
8736  /*
8737  * We're done. As a convenience, return the ending WAL location.
8738  */
8739  if (stoptli_p)
8740  *stoptli_p = stoptli;
8741  return stoppoint;
8742 }
#define NOTICE
Definition: elog.h:29
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2461
int FreeFile(FILE *file)
Definition: fd.c:2660
struct Latch * MyLatch
Definition: globals.c:58
int remaining
Definition: informix.c:667
void ResetLatch(Latch *latch)
Definition: latch.c:658
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:451
#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:229
@ WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE
Definition: wait_event.h:85
static void CleanupBackupHistory(void)
Definition: xlog.c:3828
#define XLogArchivingActive()
Definition: xlog.h:94
#define BACKUP_LABEL_FILE
Definition: xlog.h:292
#define XLogArchivingAlways()
Definition: xlog.h:97
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
#define BackupHistoryFileName(fname, tli, logSegNo, startpoint, wal_segsz_bytes)
#define BackupHistoryFilePath(path, tli, logSegNo, startpoint, wal_segsz_bytes)
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:649

References AllocateFile(), Assert(), BACKUP_LABEL_FILE, backup_started_in_recovery, BackupHistoryFileName, BackupHistoryFilePath, CHECK_FOR_INTERRUPTS, CleanupBackupHistory(), ControlFile, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, fflush(), XLogCtlInsert::forcePageWrites, fprintf, FreeFile(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::InsertTimeLineID, XLogCtlData::lastFpwDisableRecPtr, log_timezone, LSN_FORMAT_ARGS, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXFNAMELEN, MAXPGPATH, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyLatch, NOTICE, pg_localtime(), pg_strftime(), RecoveryInProgress(), remaining, 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 8419 of file xlog.c.

8420 {
8421  return sessionBackupState;
8422 }

References sessionBackupState.

Referenced by pg_backup_start(), and pg_backup_stop().

◆ GetFakeLSNForUnloggedRel()

XLogRecPtr GetFakeLSNForUnloggedRel ( void  )

Definition at line 4242 of file xlog.c.

4243 {
4244  XLogRecPtr nextUnloggedLSN;
4245 
4246  /* increment the unloggedLSN counter, need SpinLock */
4248  nextUnloggedLSN = XLogCtl->unloggedLSN++;
4250 
4251  return nextUnloggedLSN;
4252 }

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

Referenced by gistGetFakeLSN().

◆ GetFlushRecPtr()

XLogRecPtr GetFlushRecPtr ( TimeLineID insertTLI)

Definition at line 5918 of file xlog.c.

5919 {
5921 
5925 
5926  /*
5927  * If we're writing and flushing WAL, the time line can't be changing, so
5928  * no lock is required.
5929  */
5930  if (insertTLI)
5931  *insertTLI = XLogCtl->InsertTimeLineID;
5932 
5933  return LogwrtResult.Flush;
5934 }
RecoveryState SharedRecoveryState
Definition: xlog.c:518
XLogwrtResult LogwrtResult
Definition: xlog.c:480
XLogRecPtr Flush
Definition: xlog.c:331
static XLogwrtResult LogwrtResult
Definition: xlog.c:604

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(), IdentifySystem(), IsFutureLSN(), 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 5886 of file xlog.c.

5887 {
5888  *RedoRecPtr_p = RedoRecPtr;
5889  *doPageWrites_p = doPageWrites;
5890 }
static bool doPageWrites
Definition: xlog.c:283

References doPageWrites, and RedoRecPtr.

Referenced by XLogCheckBufferNeedsBackup(), and XLogInsert().

◆ GetInsertRecPtr()

XLogRecPtr GetInsertRecPtr ( void  )

Definition at line 5901 of file xlog.c.

5902 {
5903  XLogRecPtr recptr;
5904 
5906  recptr = XLogCtl->LogwrtRqst.Write;
5908 
5909  return recptr;
5910 }
XLogwrtRqst LogwrtRqst
Definition: xlog.c:460
XLogRecPtr Write
Definition: xlog.c:324

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 5958 of file xlog.c.

5959 {
5961  int i;
5962 
5963  for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
5964  {
5965  XLogRecPtr last_important;
5966 
5967  /*
5968  * Need to take a lock to prevent torn reads of the LSN, which are
5969  * possible on some of the supported platforms. WAL insert locks only
5970  * support exclusive mode, so we have to use that.
5971  */
5973  last_important = WALInsertLocks[i].l.lastImportantAt;
5974  LWLockRelease(&WALInsertLocks[i].l.lock);
5975 
5976  if (res < last_important)
5977  res = last_important;
5978  }
5979 
5980  return res;
5981 }
int i
Definition: isn.c:73
XLogRecPtr lastImportantAt
Definition: xlog.c:374
WALInsertLock l
Definition: xlog.c:386
static WALInsertLockPadded * WALInsertLocks
Definition: xlog.c:561
#define NUM_XLOGINSERT_LOCKS
Definition: xlog.c:151

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 4216 of file xlog.c.

4217 {
4218  Assert(ControlFile != NULL);
4220 }
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 5789 of file xlog.c.

5790 {
5791  RecoveryState retval;
5792 
5794  retval = XLogCtl->SharedRecoveryState;
5796 
5797  return retval;
5798 }

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

Referenced by XLogArchiveCheckDone().

◆ GetRedoRecPtr()

XLogRecPtr GetRedoRecPtr ( void  )

Definition at line 5856 of file xlog.c.

5857 {
5858  XLogRecPtr ptr;
5859 
5860  /*
5861  * The possibly not up-to-date copy in XlogCtl is enough. Even if we
5862  * grabbed a WAL insertion lock to read the authoritative value in
5863  * Insert->RedoRecPtr, someone might update it just after we've released
5864  * the lock.
5865  */
5867  ptr = XLogCtl->RedoRecPtr;
5869 
5870  if (RedoRecPtr < ptr)
5871  RedoRecPtr = ptr;
5872 
5873  return RedoRecPtr;
5874 }

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 4206 of file xlog.c.

4207 {
4208  Assert(ControlFile != NULL);
4210 }
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 7180 of file xlog.c.

7181 {
7182  XLogRecPtr currpos; /* current write LSN */
7183  XLogSegNo currSeg; /* segid of currpos */
7184  XLogSegNo targetSeg; /* segid of targetLSN */
7185  XLogSegNo oldestSeg; /* actual oldest segid */
7186  XLogSegNo oldestSegMaxWalSize; /* oldest segid kept by max_wal_size */
7187  XLogSegNo oldestSlotSeg; /* oldest segid kept by slot */
7188  uint64 keepSegs;
7189 
7190  /*
7191  * slot does not reserve WAL. Either deactivated, or has never been active
7192  */
7193  if (XLogRecPtrIsInvalid(targetLSN))
7194  return WALAVAIL_INVALID_LSN;
7195 
7196  /*
7197  * Calculate the oldest segment currently reserved by all slots,
7198  * considering wal_keep_size and max_slot_wal_keep_size. Initialize
7199  * oldestSlotSeg to the current segment.
7200  */
7201  currpos = GetXLogWriteRecPtr();
7202  XLByteToSeg(currpos, oldestSlotSeg, wal_segment_size);
7203  KeepLogSeg(currpos, &oldestSlotSeg);
7204 
7205  /*
7206  * Find the oldest extant segment file. We get 1 until checkpoint removes
7207  * the first WAL segment file since startup, which causes the status being
7208  * wrong under certain abnormal conditions but that doesn't actually harm.
7209  */
7210  oldestSeg = XLogGetLastRemovedSegno() + 1;
7211 
7212  /* calculate oldest segment by max_wal_size */
7213  XLByteToSeg(currpos, currSeg, wal_segment_size);
7215 
7216  if (currSeg > keepSegs)
7217  oldestSegMaxWalSize = currSeg - keepSegs;
7218  else
7219  oldestSegMaxWalSize = 1;
7220 
7221  /* the segment we care about */
7222  XLByteToSeg(targetLSN, targetSeg, wal_segment_size);
7223 
7224  /*
7225  * No point in returning reserved or extended status values if the
7226  * targetSeg is known to be lost.
7227  */
7228  if (targetSeg >= oldestSlotSeg)
7229  {
7230  /* show "reserved" when targetSeg is within max_wal_size */
7231  if (targetSeg >= oldestSegMaxWalSize)
7232  return WALAVAIL_RESERVED;
7233 
7234  /* being retained by slots exceeding max_wal_size */
7235  return WALAVAIL_EXTENDED;
7236  }
7237 
7238  /* WAL segments are no longer retained but haven't been removed yet */
7239  if (targetSeg >= oldestSeg)
7240  return WALAVAIL_UNRESERVED;
7241 
7242  /* Definitely lost */
7243  return WALAVAIL_REMOVED;
7244 }
XLogSegNo XLogGetLastRemovedSegno(void)
Definition: xlog.c:3485
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:595
XLogRecPtr GetXLogWriteRecPtr(void)
Definition: xlog.c:8819
@ 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 5941 of file xlog.c.

5942 {
5944 
5945  /* Since the value can't be changing, no lock is required. */
5946  return XLogCtl->InsertTimeLineID;
5947 }

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 8803 of file xlog.c.

8804 {
8806  uint64 current_bytepos;
8807 
8808  SpinLockAcquire(&Insert->insertpos_lck);
8809  current_bytepos = Insert->CurrBytePos;
8810  SpinLockRelease(&Insert->insertpos_lck);
8811 
8812  return XLogBytePosToRecPtr(current_bytepos);
8813 }

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

◆ IsInstallXLogFileSegmentActive()

bool IsInstallXLogFileSegmentActive ( void  )

Definition at line 8862 of file xlog.c.

8863 {
8864  bool result;
8865 
8866  LWLockAcquire(ControlFileLock, LW_SHARED);
8868  LWLockRelease(ControlFileLock);
8869 
8870  return result;
8871 }

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 7968 of file xlog.c.

7969 {
7970  char *msg = NULL;
7971  instr_time start;
7972 
7973  Assert(tli != 0);
7974 
7975  /*
7976  * Quick exit if fsync is disabled or write() has already synced the WAL
7977  * file.
7978  */
7979  if (!enableFsync ||
7982  return;
7983 
7984  /* Measure I/O timing to sync the WAL file */
7985  if (track_wal_io_timing)
7986  INSTR_TIME_SET_CURRENT(start);
7987 
7989  switch (sync_method)
7990  {
7991  case SYNC_METHOD_FSYNC:
7992  if (pg_fsync_no_writethrough(fd) != 0)
7993  msg = _("could not fsync file \"%s\": %m");
7994  break;
7995 #ifdef HAVE_FSYNC_WRITETHROUGH
7997  if (pg_fsync_writethrough(fd) != 0)
7998  msg = _("could not fsync write-through file \"%s\": %m");
7999  break;
8000 #endif
8001 #ifdef HAVE_FDATASYNC
8002  case SYNC_METHOD_FDATASYNC:
8003  if (pg_fdatasync(fd) != 0)
8004  msg = _("could not fdatasync file \"%s\": %m");
8005  break;
8006 #endif
8007  case SYNC_METHOD_OPEN:
8009  /* not reachable */
8010  Assert(false);
8011  break;
8012  default:
8013  elog(PANIC, "unrecognized wal_sync_method: %d", sync_method);
8014  break;
8015  }
8016 
8017  /* PANIC if failed to fsync */
8018  if (msg)
8019  {
8020  char xlogfname[MAXFNAMELEN];
8021  int save_errno = errno;
8022 
8023  XLogFileName(xlogfname, tli, segno, wal_segment_size);
8024  errno = save_errno;
8025  ereport(PANIC,
8027  errmsg(msg, xlogfname)));
8028  }
8029 
8031 
8032  /*
8033  * Increment the I/O timing and the number of times WAL files were synced.
8034  */
8035  if (track_wal_io_timing)
8036  {
8038 
8040  INSTR_TIME_SUBTRACT(duration, start);
8042  }
8043 
8045 }
#define _(x)
Definition: elog.c:89
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:414
int pg_fdatasync(int fd)
Definition: fd.c:449
int pg_fsync_writethrough(int fd)
Definition: fd.c:426
bool enableFsync
Definition: globals.c:123
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:170
struct timeval instr_time
Definition: instr_time.h:150
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:205
int duration
Definition: pgbench.c:187
PgStat_WalStats PendingWalStats
Definition: pgstat_wal.c:24
static int fd(const char *x, int i)
Definition: preproc-init.c:105
PgStat_Counter wal_sync_time
Definition: pgstat.h:394
PgStat_Counter wal_sync
Definition: pgstat.h:392
@ WAIT_EVENT_WAL_SYNC
Definition: wait_event.h:230
bool track_wal_io_timing
Definition: xlog.c:138
int sync_method
Definition: xlog.c:131
#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_GET_MICROSEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, 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_WalStats::wal_sync, PgStat_WalStats::wal_sync_time, and XLogFileName.

Referenced by XLogWalRcvFlush(), and XLogWrite().

◆ LocalProcessControlFile()

void LocalProcessControlFile ( bool  reset)

Definition at line 4326 of file xlog.c.

4327 {
4328  Assert(reset || ControlFile == NULL);
4329  ControlFile = palloc(sizeof(ControlFileData));
4330  ReadControlFile();
4331 }
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 5666 of file xlog.c.

5667 {
5668  /*
5669  * We have reached the end of base backup, as indicated by pg_control. The
5670  * data on disk is now consistent (unless minRecovery point is further
5671  * ahead, which can happen if we crashed during previous recovery). Reset
5672  * backupStartPoint and backupEndPoint, and update minRecoveryPoint to
5673  * make sure we don't allow starting up at an earlier point even if
5674  * recovery is stopped and restarted soon after this.
5675  */
5676  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5677 
5678  if (ControlFile->minRecoveryPoint < EndRecPtr)
5679  {
5680  ControlFile->minRecoveryPoint = EndRecPtr;
5682  }
5683 
5686  ControlFile->backupEndRequired = false;
5688 
5689  LWLockRelease(ControlFileLock);
5690 }
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 5753 of file xlog.c.

5754 {
5755  /*
5756  * We check shared state each time only until we leave recovery mode. We
5757  * can't re-enter recovery, so there's no need to keep checking after the
5758  * shared variable has once been seen false.
5759  */
5761  return false;
5762  else
5763  {
5764  /*
5765  * use volatile pointer to make sure we make a fresh read of the
5766  * shared variable.
5767  */
5768  volatile XLogCtlData *xlogctl = XLogCtl;
5769 
5771 
5772  /*
5773  * Note: We don't need a memory barrier when we're still in recovery.
5774  * We might exit recovery immediately after return, so the caller
5775  * can't rely on 'true' meaning that we're still in recovery anyway.
5776  */
5777 
5778  return LocalRecoveryInProgress;
5779  }
5780 }
static bool LocalRecoveryInProgress
Definition: xlog.c:221

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_read_only(), check_XactIsoLevel(), CheckArchiveTimeout(), CheckLogicalDecodingRequirements(), CheckpointerMain(), ComputeXidHorizons(), CreateCheckPoint(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), CreateRestartPoint(), do_pg_backup_start(), do_pg_backup_stop(), error_commit_ts_disabled(), get_relation_info(), GetNewMultiXactId(), GetNewObjectId(), GetNewTransactionId(), GetOldestActiveTransactionId(), GetOldestSafeDecodingTransactionId(), GetRunningTransactionData(), GetSerializableTransactionSnapshot(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), gin_clean_pending_list(), GlobalVisHorizonKindForRel(), heap_force_common(), heap_page_prune_opt(), IdentifySystem(), InitTempTableNamespace(), IsCheckpointOnSchedule(), IsFutureLSN(), LockAcquireExtended(), 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_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(), 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(), XLogBackgroundFlush(), XLogInsertAllowed(), XLogNeedsFlush(), and XLogSendPhysical().

◆ register_persistent_abort_backup_handler()

void register_persistent_abort_backup_handler ( void  )

Definition at line 8789 of file xlog.c.

8790 {
8791  static bool already_done = false;
8792 
8793  if (already_done)
8794  return;
8796  already_done = true;
8797 }
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333
void do_pg_abort_backup(int code, Datum arg)
Definition: xlog.c:8759

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 3630 of file xlog.c.

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

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 8854 of file xlog.c.

8855 {
8856  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8858  LWLockRelease(ControlFileLock);
8859 }

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

Referenced by WaitForWALToBecomeAvailable().

◆ SetWalWriterSleeping()

void SetWalWriterSleeping ( bool  sleeping)

Definition at line 8877 of file xlog.c.

8878 {
8880  XLogCtl->WalWriterSleeping = sleeping;
8882 }
bool WalWriterSleeping
Definition: xlog.c:535

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

Referenced by WalWriterMain().

◆ ShutdownXLOG()

void ShutdownXLOG ( int  code,
Datum  arg 
)

Definition at line 6004 of file xlog.c.

6005 {
6006  /*
6007  * We should have an aux process resource owner to use, and we should not
6008  * be in a transaction that's installed some other resowner.
6009  */
6011  Assert(CurrentResourceOwner == NULL ||
6014 
6015  /* Don't be chatty in standalone mode */
6017  (errmsg("shutting down")));
6018 
6019  /*
6020  * Signal walsenders to move to stopping state.
6021  */
6023 
6024  /*
6025  * Wait for WAL senders to be in stopping state. This prevents commands
6026  * from writing new WAL.
6027  */
6029 
6030  if (RecoveryInProgress())
6032  else
6033  {
6034  /*
6035  * If archiving is enabled, rotate the last XLOG file so that all the
6036  * remaining records are archived (postmaster wakes up the archiver
6037  * process one more time at the end of shutdown). The checkpoint
6038  * record will go to the next XLOG file and won't be archived (yet).
6039  */
6040  if (XLogArchivingActive())
6041  RequestXLogSwitch(false);
6042 
6044  }
6045 }
bool IsPostmasterEnvironment
Definition: globals.c:112
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
ResourceOwner AuxProcessResourceOwner
Definition: resowner.c:149
void WalSndInitStopping(void)
Definition: walsender.c:3354
void WalSndWaitStopping(void)
Definition: walsender.c:3380
bool CreateRestartPoint(int flags)
Definition: xlog.c:6911
void CreateCheckPoint(int flags)
Definition: xlog.c:6270

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 4877 of file xlog.c.

4878 {
4880  CheckPoint checkPoint;
4881  bool wasShutdown;
4882  bool didCrash;
4883  bool haveTblspcMap;
4884  bool haveBackupLabel;
4885  XLogRecPtr EndOfLog;
4886  TimeLineID EndOfLogTLI;
4887  TimeLineID newTLI;
4888  bool performedWalRecovery;
4889  EndOfWalRecoveryInfo *endOfRecoveryInfo;
4892  TransactionId oldestActiveXID;
4893  bool promoted = false;
4894 
4895  /*
4896  * We should have an aux process resource owner to use, and we should not
4897  * be in a transaction that's installed some other resowner.
4898  */
4900  Assert(CurrentResourceOwner == NULL ||
4903 
4904  /*
4905  * Check that contents look valid.
4906  */
4908  ereport(FATAL,
4909  (errmsg("control file contains invalid checkpoint location")));
4910 
4911  switch (ControlFile->state)
4912  {
4913  case DB_SHUTDOWNED:
4914 
4915  /*
4916  * This is the expected case, so don't be chatty in standalone
4917  * mode
4918  */
4920  (errmsg("database system was shut down at %s",
4921  str_time(ControlFile->time))));
4922  break;
4923 
4925  ereport(LOG,
4926  (errmsg("database system was shut down in recovery at %s",
4927  str_time(ControlFile->time))));
4928  break;
4929 
4930  case DB_SHUTDOWNING:
4931  ereport(LOG,
4932  (errmsg("database system shutdown was interrupted; last known up at %s",
4933  str_time(ControlFile->time))));
4934  break;
4935 
4936  case DB_IN_CRASH_RECOVERY:
4937  ereport(LOG,
4938  (errmsg("database system was interrupted while in recovery at %s",
4940  errhint("This probably means that some data is corrupted and"
4941  " you will have to use the last backup for recovery.")));
4942  break;
4943 
4945  ereport(LOG,
4946  (errmsg("database system was interrupted while in recovery at log time %s",
4948  errhint("If this has occurred more than once some data might be corrupted"
4949  " and you might need to choose an earlier recovery target.")));
4950  break;
4951 
4952  case DB_IN_PRODUCTION:
4953  ereport(LOG,
4954  (errmsg("database system was interrupted; last known up at %s",
4955  str_time(ControlFile->time))));
4956  break;
4957 
4958  default:
4959  ereport(FATAL,
4960  (errmsg("control file contains invalid database cluster state")));
4961  }
4962 
4963  /* This is just to allow attaching to startup process with a debugger */
4964 #ifdef XLOG_REPLAY_DELAY
4966  pg_usleep(60000000L);
4967 #endif
4968 
4969  /*
4970  * Verify that pg_wal and pg_wal/archive_status exist. In cases where
4971  * someone has performed a copy for PITR, these directories may have been
4972  * excluded and need to be re-created.
4973  */
4975 
4976  /* Set up timeout handler needed to report startup progress. */
4980 
4981  /*----------
4982  * If we previously crashed, perform a couple of actions:
4983  *
4984  * - The pg_wal directory may still include some temporary WAL segments
4985  * used when creating a new segment, so perform some clean up to not
4986  * bloat this path. This is done first as there is no point to sync
4987  * this temporary data.
4988  *
4989  * - There might be data which we had written, intending to fsync it, but
4990  * which we had not actually fsync'd yet. Therefore, a power failure in
4991  * the near future might cause earlier unflushed writes to be lost, even
4992  * though more recent data written to disk from here on would be
4993  * persisted. To avoid that, fsync the entire data directory.
4994  */
4995  if (ControlFile->state != DB_SHUTDOWNED &&
4997  {
5000  didCrash = true;
5001  }
5002  else
5003  didCrash = false;
5004 
5005  /*
5006  * Prepare for WAL recovery if needed.
5007  *
5008  * InitWalRecovery analyzes the control file and the backup label file, if
5009  * any. It updates the in-memory ControlFile buffer according to the
5010  * starting checkpoint, and sets InRecovery and ArchiveRecoveryRequested.
5011  * It also applies the tablespace map file, if any.
5012  */
5013  InitWalRecovery(ControlFile, &wasShutdown,
5014  &haveBackupLabel, &haveTblspcMap);
5015  checkPoint = ControlFile->checkPointCopy;
5016 
5017  /* initialize shared memory variables from the checkpoint record */
5018  ShmemVariableCache->nextXid = checkPoint.nextXid;
5019  ShmemVariableCache->nextOid = checkPoint.nextOid;
5021  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5022  AdvanceOldestClogXid(checkPoint.oldestXid);
5023  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5024  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5026  checkPoint.newestCommitTsXid);
5027  XLogCtl->ckptFullXid = checkPoint.nextXid;
5028 
5029  /*
5030  * Clear out any old relcache cache files. This is *necessary* if we do
5031  * any WAL replay, since that would probably result in the cache files
5032  * being out of sync with database reality. In theory we could leave them
5033  * in place if the database had been cleanly shut down, but it seems
5034  * safest to just remove them always and let them be rebuilt during the
5035  * first backend startup. These files needs to be removed from all
5036  * directories including pg_tblspc, however the symlinks are created only
5037  * after reading tablespace_map file in case of archive recovery from
5038  * backup, so needs to clear old relcache files here after creating
5039  * symlinks.
5040  */
5042 
5043  /*
5044  * Initialize replication slots, before there's a chance to remove
5045  * required resources.
5046  */
5048 
5049  /*
5050  * Startup logical state, needs to be setup now so we have proper data
5051  * during crash recovery.
5052  */
5054 
5055  /*
5056  * Startup CLOG. This must be done after ShmemVariableCache->nextXid has
5057  * been initialized and before we accept connections or begin WAL replay.
5058  */
5059  StartupCLOG();
5060 
5061  /*
5062  * Startup MultiXact. We need to do this early to be able to replay
5063  * truncations.
5064  */
5065  StartupMultiXact();
5066 
5067  /*
5068  * Ditto for commit timestamps. Activate the facility if the setting is
5069  * enabled in the control file, as there should be no tracking of commit
5070  * timestamps done when the setting was disabled. This facility can be
5071  * started or stopped when replaying a XLOG_PARAMETER_CHANGE record.
5072  */
5074  StartupCommitTs();
5075 
5076  /*
5077  * Recover knowledge about replay progress of known replication partners.
5078  */
5080 
5081  /*
5082  * Initialize unlogged LSN. On a clean shutdown, it's restored from the
5083  * control file. On recovery, all unlogged relations are blown away, so
5084  * the unlogged LSN counter can be reset too.
5085  */
5088  else
5090 
5091  /*
5092  * Copy any missing timeline history files between 'now' and the recovery
5093  * target timeline from archive to pg_wal. While we don't need those files
5094  * ourselves - the history file of the recovery target timeline covers all
5095  * the previous timelines in the history too - a cascading standby server
5096  * might be interested in them. Or, if you archive the WAL from this
5097  * server to a different archive than the primary, it'd be good for all
5098  * the history files to get archived there after failover, so that you can
5099  * use one of the old timelines as a PITR target. Timeline history files
5100  * are small, so it's better to copy them unnecessarily than not copy them
5101  * and regret later.
5102  */
5104 
5105  /*
5106  * Before running in recovery, scan pg_twophase and fill in its status to
5107  * be able to work on entries generated by redo. Doing a scan before
5108  * taking any recovery action has the merit to discard any 2PC files that
5109  * are newer than the first record to replay, saving from any conflicts at
5110  * replay. This avoids as well any subsequent scans when doing recovery
5111  * of the on-disk two-phase data.
5112  */
5114 
5115  /*
5116  * When starting with crash recovery, reset pgstat data - it might not be
5117  * valid. Otherwise restore pgstat data. It's safe to do this here,
5118  * because postmaster will not yet have started any other processes.
5119  *
5120  * NB: Restoring replication slot stats relies on slot state to have
5121  * already been restored from disk.
5122  *
5123  * TODO: With a bit of extra work we could just start with a pgstat file
5124  * associated with the checkpoint redo location we're starting from.
5125  */
5126  if (didCrash)
5128  else
5130 
5131  lastFullPageWrites = checkPoint.fullPageWrites;
5132 
5135 
5136  /* REDO */
5137  if (InRecovery)
5138  {
5139  /* Initialize state for RecoveryInProgress() */
5141  if (InArchiveRecovery)
5143  else
5146 
5147  /*
5148  * Update pg_control to show that we are recovering and to show the
5149  * selected checkpoint as the place we are starting from. We also mark
5150  * pg_control with any minimum recovery stop point obtained from a
5151  * backup history file.
5152  *
5153  * No need to hold ControlFileLock yet, we aren't up far enough.
5154  */
5156 
5157  /*
5158  * If there was a backup label file, it's done its job and the info
5159  * has now been propagated into pg_control. We must get rid of the
5160  * label file so that if we crash during recovery, we'll pick up at
5161  * the latest recovery restartpoint instead of going all the way back
5162  * to the backup start point. It seems prudent though to just rename
5163  * the file out of the way rather than delete it completely.
5164  */
5165  if (haveBackupLabel)
5166  {
5167  unlink(BACKUP_LABEL_OLD);
5169  }
5170 
5171  /*
5172  * If there was a tablespace_map file, it's done its job and the
5173  * symlinks have been created. We must get rid of the map file so
5174  * that if we crash during recovery, we don't create symlinks again.
5175  * It seems prudent though to just rename the file out of the way
5176  * rather than delete it completely.
5177  */
5178  if (haveTblspcMap)
5179  {
5180  unlink(TABLESPACE_MAP_OLD);
5182  }
5183 
5184  /*
5185  * Initialize our local copy of minRecoveryPoint. When doing crash
5186  * recovery we want to replay up to the end of WAL. Particularly, in
5187  * the case of a promoted standby minRecoveryPoint value in the
5188  * control file is only updated after the first checkpoint. However,
5189  * if the instance crashes before the first post-recovery checkpoint
5190  * is completed then recovery will use a stale location causing the
5191  * startup process to think that there are still invalid page
5192  * references when checking for data consistency.
5193  */
5194  if (InArchiveRecovery)
5195  {
5198  }
5199  else
5200  {
5203  }
5204 
5205  /* Check that the GUCs used to generate the WAL allow recovery */
5207 
5208  /*
5209  * We're in recovery, so unlogged relations may be trashed and must be
5210  * reset. This should be done BEFORE allowing Hot Standby
5211  * connections, so that read-only backends don't try to read whatever
5212  * garbage is left over from before.
5213  */
5215 
5216  /*
5217  * Likewise, delete any saved transaction snapshot files that got left
5218  * behind by crashed backends.
5219  */
5221 
5222  /*
5223  * Initialize for Hot Standby, if enabled. We won't let backends in
5224  * yet, not until we've reached the min recovery point specified in
5225  * control file and we've established a recovery snapshot from a
5226  * running-xacts WAL record.
5227  */
5229  {
5230  TransactionId *xids;
5231  int nxids;
5232 
5233  ereport(DEBUG1,
5234  (errmsg_internal("initializing for hot standby")));
5235 
5237 
5238  if (wasShutdown)
5239  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
5240  else
5241  oldestActiveXID = checkPoint.oldestActiveXid;
5242  Assert(TransactionIdIsValid(oldestActiveXID));
5243 
5244  /* Tell procarray about the range of xids it has to deal with */
5246 
5247  /*
5248  * Startup subtrans only. CLOG, MultiXact and commit timestamp
5249  * have already been started up and other SLRUs are not maintained
5250  * during recovery and need not be started yet.
5251  */
5252  StartupSUBTRANS(oldestActiveXID);
5253 
5254  /*
5255  * If we're beginning at a shutdown checkpoint, we know that
5256  * nothing was running on the primary at this point. So fake-up an
5257  * empty running-xacts record and use that here and now. Recover
5258  * additional standby state for prepared transactions.
5259  */
5260  if (wasShutdown)
5261  {
5262  RunningTransactionsData running;
5263  TransactionId latestCompletedXid;
5264 
5265  /*
5266  * Construct a RunningTransactions snapshot representing a
5267  * shut down server, with only prepared transactions still
5268  * alive. We're never overflowed at this point because all
5269  * subxids are listed with their parent prepared transactions.
5270  */
5271  running.xcnt = nxids;
5272  running.subxcnt = 0;
5273  running.subxid_overflow = false;
5274  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
5275  running.oldestRunningXid = oldestActiveXID;
5276  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
5277  TransactionIdRetreat(latestCompletedXid);
5278  Assert(TransactionIdIsNormal(latestCompletedXid));
5279  running.latestCompletedXid = latestCompletedXid;
5280  running.xids = xids;
5281 
5282  ProcArrayApplyRecoveryInfo(&running);
5283 
5285  }
5286  }
5287 
5288  /*
5289  * We're all set for replaying the WAL now. Do it.
5290  */
5292  performedWalRecovery = true;
5293  }
5294  else
5295  performedWalRecovery = false;
5296 
5297  /*
5298  * Finish WAL recovery.
5299  */
5300  endOfRecoveryInfo = FinishWalRecovery();
5301  EndOfLog = endOfRecoveryInfo->endOfLog;
5302  EndOfLogTLI = endOfRecoveryInfo->endOfLogTLI;
5303  abortedRecPtr = endOfRecoveryInfo->abortedRecPtr;
5304  missingContrecPtr = endOfRecoveryInfo->missingContrecPtr;
5305 
5306  /*
5307  * When recovering from a backup (we are in recovery, and archive recovery
5308  * was requested), complain if we did not roll forward far enough to reach
5309  * the point where the database is consistent. For regular online
5310  * backup-from-primary, that means reaching the end-of-backup WAL record
5311  * (at which point we reset backupStartPoint to be Invalid), for
5312  * backup-from-replica (which can't inject records into the WAL stream),
5313  * that point is when we reach the minRecoveryPoint in pg_control (which
5314  * we purposefully copy last when backing up from a replica). For
5315  * pg_rewind (which creates a backup_label with a method of "pg_rewind")
5316  * or snapshot-style backups (which don't), backupEndRequired will be set
5317  * to false.
5318  *
5319  * Note: it is indeed okay to look at the local variable
5320  * LocalMinRecoveryPoint here, even though ControlFile->minRecoveryPoint
5321  * might be further ahead --- ControlFile->minRecoveryPoint cannot have
5322  * been advanced beyond the WAL we processed.
5323  */
5324  if (InRecovery &&
5325  (EndOfLog < LocalMinRecoveryPoint ||
5327  {
5328  /*
5329  * Ran off end of WAL before reaching end-of-backup WAL record, or
5330  * minRecoveryPoint. That's a bad sign, indicating that you tried to
5331  * recover from an online backup but never called pg_backup_stop(), or
5332  * you didn't archive all the WAL needed.
5333  */
5335  {
5337  ereport(FATAL,
5338  (errmsg("WAL ends before end of online backup"),
5339  errhint("All WAL generated while online backup was taken must be available at recovery.")));
5340  else
5341  ereport(FATAL,
5342  (errmsg("WAL ends before consistent recovery point")));
5343  }
5344  }
5345 
5346  /*
5347  * Reset unlogged relations to the contents of their INIT fork. This is
5348  * done AFTER recovery is complete so as to include any unlogged relations
5349  * created during recovery, but BEFORE recovery is marked as having
5350  * completed successfully. Otherwise we'd not retry if any of the post
5351  * end-of-recovery steps fail.
5352  */
5353  if (InRecovery)
5355 
5356  /*
5357  * Pre-scan prepared transactions to find out the range of XIDs present.
5358  * This information is not quite needed yet, but it is positioned here so
5359  * as potential problems are detected before any on-disk change is done.
5360  */
5361  oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
5362 
5363  /*
5364  * Allow ordinary WAL segment creation before possibly switching to a new
5365  * timeline, which creates a new segment, and after the last ReadRecord().
5366  */
5367  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5369  LWLockRelease(ControlFileLock);
5370 
5371  /*
5372  * Consider whether we need to assign a new timeline ID.
5373  *
5374  * If we did archive recovery, we always assign a new ID. This handles a
5375  * couple of issues. If we stopped short of the end of WAL during
5376  * recovery, then we are clearly generating a new timeline and must assign
5377  * it a unique new ID. Even if we ran to the end, modifying the current
5378  * last segment is problematic because it may result in trying to
5379  * overwrite an already-archived copy of that segment, and we encourage
5380  * DBAs to make their archive_commands reject that. We can dodge the
5381  * problem by making the new active segment have a new timeline ID.
5382  *
5383  * In a normal crash recovery, we can just extend the timeline we were in.
5384  */
5385  newTLI = endOfRecoveryInfo->lastRecTLI;
5387  {
5388  newTLI = findNewestTimeLine(recoveryTargetTLI) + 1;
5389  ereport(LOG,
5390  (errmsg("selected new timeline ID: %u", newTLI)));
5391 
5392  /*
5393  * Make a writable copy of the last WAL segment. (Note that we also
5394  * have a copy of the last block of the old WAL in
5395  * endOfRecovery->lastPage; we will use that below.)
5396  */
5397  XLogInitNewTimeline(EndOfLogTLI, EndOfLog, newTLI);
5398 
5399  /*
5400  * Remove the signal files out of the way, so that we don't
5401  * accidentally re-enter archive recovery mode in a subsequent crash.
5402  */
5403  if (endOfRecoveryInfo->standby_signal_file_found)
5405 
5406  if (endOfRecoveryInfo->recovery_signal_file_found)
5408 
5409  /*
5410  * Write the timeline history file, and have it archived. After this
5411  * point (or rather, as soon as the file is archived), the timeline
5412  * will appear as "taken" in the WAL archive and to any standby
5413  * servers. If we crash before actually switching to the new
5414  * timeline, standby servers will nevertheless think that we switched
5415  * to the new timeline, and will try to connect to the new timeline.
5416  * To minimize the window for that, try to do as little as possible
5417  * between here and writing the end-of-recovery record.
5418  */
5420  EndOfLog, endOfRecoveryInfo->recoveryStopReason);
5421 
5422  ereport(LOG,
5423  (errmsg("archive recovery complete")));
5424  }
5425 
5426  /* Save the selected TimeLineID in shared memory, too */
5427  XLogCtl->InsertTimeLineID = newTLI;
5428  XLogCtl->PrevTimeLineID = endOfRecoveryInfo->lastRecTLI;
5429 
5430  /*
5431  * Actually, if WAL ended in an incomplete record, skip the parts that
5432  * made it through and start writing after the portion that persisted.
5433  * (It's critical to first write an OVERWRITE_CONTRECORD message, which
5434  * we'll do as soon as we're open for writing new WAL.)
5435  */
5437  {
5439  EndOfLog = missingContrecPtr;
5440  }
5441 
5442  /*
5443  * Prepare to write WAL starting at EndOfLog location, and init xlog
5444  * buffer cache using the block containing the last record from the
5445  * previous incarnation.
5446  */
5447  Insert = &XLogCtl->Insert;
5448  Insert->PrevBytePos = XLogRecPtrToBytePos(endOfRecoveryInfo->lastRec);
5449  Insert->CurrBytePos = XLogRecPtrToBytePos(EndOfLog);
5450 
5451  /*
5452  * Tricky point here: lastPage contains the *last* block that the LastRec
5453  * record spans, not the one it starts in. The last block is indeed the
5454  * one we want to use.
5455  */
5456  if (EndOfLog % XLOG_BLCKSZ != 0)
5457  {
5458  char *page;
5459  int len;
5460  int firstIdx;
5461 
5462  firstIdx = XLogRecPtrToBufIdx(EndOfLog);
5463  len = EndOfLog - endOfRecoveryInfo->lastPageBeginPtr;
5464  Assert(len < XLOG_BLCKSZ);
5465 
5466  /* Copy the valid part of the last block, and zero the rest */
5467  page = &XLogCtl->pages[firstIdx * XLOG_BLCKSZ];
5468  memcpy(page, endOfRecoveryInfo->lastPage, len);
5469  memset(page + len, 0, XLOG_BLCKSZ - len);
5470 
5471  XLogCtl->xlblocks[firstIdx] = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ;
5472  XLogCtl->InitializedUpTo = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ;
5473  }
5474  else
5475  {
5476  /*
5477  * There is no partial block to copy. Just set InitializedUpTo, and
5478  * let the first attempt to insert a log record to initialize the next
5479  * buffer.
5480  */
5481  XLogCtl->InitializedUpTo = EndOfLog;
5482  }
5483 
5484  LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
5485 
5487 
5488  XLogCtl->LogwrtRqst.Write = EndOfLog;
5489  XLogCtl->LogwrtRqst.Flush = EndOfLog;
5490 
5491  /*
5492  * Preallocate additional log files, if wanted.
5493  */
5494  PreallocXlogFiles(EndOfLog, newTLI);
5495 
5496  /*
5497  * Okay, we're officially UP.
5498  */
5499  InRecovery = false;
5500 
5501  /* start the archive_timeout timer and LSN running */
5502  XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
5503  XLogCtl->lastSegSwitchLSN = EndOfLog;
5504 
5505  /* also initialize latestCompletedXid, to nextXid - 1 */
5506  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
5509  LWLockRelease(ProcArrayLock);
5510 
5511  /*
5512  * Start up subtrans, if not already done for hot standby. (commit
5513  * timestamps are started below, if necessary.)
5514  */
5516  StartupSUBTRANS(oldestActiveXID);
5517 
5518  /*
5519  * Perform end of recovery actions for any SLRUs that need it.
5520  */
5521  TrimCLOG();
5522  TrimMultiXact();
5523 
5524  /* Reload shared-memory state for prepared transactions */
5526 
5527  /* Shut down xlogreader */
5529 
5530  /* Enable WAL writes for this backend only. */
5532 
5533  /* If necessary, write overwrite-contrecord before doing anything else */
5535  {
5538  }
5539 
5540  /*
5541  * Update full_page_writes in shared memory and write an XLOG_FPW_CHANGE
5542  * record before resource manager writes cleanup WAL records or checkpoint
5543  * record is written.
5544  */
5545  Insert->fullPageWrites = lastFullPageWrites;
5547 
5548  /*
5549  * Emit checkpoint or end-of-recovery record in XLOG, if required.
5550  */
5551  if (performedWalRecovery)
5552  promoted = PerformRecoveryXLogAction();
5553 
5554  /*
5555  * If any of the critical GUCs have changed, log them before we allow
5556  * backends to write WAL.
5557  */
5559 
5560  /* If this is archive recovery, perform post-recovery cleanup actions. */
5562  CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog, newTLI);
5563 
5564  /*
5565  * Local WAL inserts enabled, so it's time to finish initialization of
5566  * commit timestamp.
5567  */
5569 
5570  /*
5571  * All done with end-of-recovery actions.
5572  *
5573  * Now allow backends to write WAL and update the control file status in
5574  * consequence. SharedRecoveryState, that controls if backends can write
5575  * WAL, is updated while holding ControlFileLock to prevent other backends
5576  * to look at an inconsistent state of the control file in shared memory.
5577  * There is still a small window during which backends can write WAL and
5578  * the control file is still referring to a system not in DB_IN_PRODUCTION
5579  * state while looking at the on-disk control file.
5580  *
5581  * Also, we use info_lck to update SharedRecoveryState to ensure that
5582  * there are no race conditions concerning visibility of other recent
5583  * updates to shared memory.
5584  */
5585  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5587 
5591 
5593  LWLockRelease(ControlFileLock);
5594 
5595  /*
5596  * Shutdown the recovery environment. This must occur after
5597  * RecoverPreparedTransactions() (see notes in lock_twophase_recover())
5598  * and after switching SharedRecoveryState to RECOVERY_STATE_DONE so as
5599  * any session building a snapshot will not rely on KnownAssignedXids as
5600  * RecoveryInProgress() would return false at this stage. This is
5601  * particularly critical for prepared 2PC transactions, that would still
5602  * need to be included in snapshots once recovery has ended.
5603  */
5606 
5607  /*
5608  * If there were cascading standby servers connected to us, nudge any wal
5609  * sender processes to notice that we've been promoted.
5610  */
5611  WalSndWakeup();
5612 
5613  /*
5614  * If this was a promotion, request an (online) checkpoint now. This isn't
5615  * required for consistency, but the last restartpoint might be far back,
5616  * and in case of a crash, recovering from it might take a longer than is
5617  * appropriate now that we're not in standby mode anymore.
5618  */
5619  if (promoted)
5621 }
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:587
void StartupCLOG(void)
Definition: clog.c:756
void TrimCLOG(void)
Definition: clog.c:775
void StartupCommitTs(void)
Definition: commit_ts.c:610
void CompleteCommitTsInitialization(void)
Definition: commit_ts.c:620
#define FATAL
Definition: elog.h:35
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:699
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:789
void SyncDataDirectory(void)
Definition: fd.c:3429
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
void TrimMultiXact(void)
Definition: multixact.c:2031
void StartupMultiXact(void)
Definition: multixact.c:2008
void StartupReplicationOrigin(void)
Definition: origin.c:683
@ 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:392
void pgstat_discard_stats(void)
Definition: pgstat.c:404
void ProcArrayApplyRecoveryInfo(RunningTransactions running)
Definition: procarray.c:1039
void ProcArrayInitRecovery(TransactionId initializedUptoXID)
Definition: procarray.c:1008
void ResetUnloggedRelations(int op)
Definition: reinit.c:47
#define UNLOGGED_RELATION_INIT
Definition: reinit.h:26
#define UNLOGGED_RELATION_CLEANUP
Definition: reinit.h:25
void RelationCacheInitFileRemove(void)
Definition: relcache.c:6661
void StartupReorderBuffer(void)
void StartupReplicationSlots(void)
Definition: slot.c:1477
void DeleteAllExportedSnapshotFiles(void)
Definition: snapmgr.c:1582
void InitRecoveryTransactionEnvironment(void)
Definition: standby.c:83
void ShutdownRecoveryTransactionEnvironment(void)
Definition: standby.c:140
bool track_commit_timestamp
Definition: pg_control.h:183
XLogRecPtr lastPageBeginPtr
Definition: xlogrecovery.h:110
XLogRecPtr abortedRecPtr
Definition: xlogrecovery.h:119
XLogRecPtr missingContrecPtr
Definition: xlogrecovery.h:120
TimeLineID endOfLogTLI
Definition: xlogrecovery.h:108
TransactionId oldestRunningXid
Definition: standby.h:83
TransactionId nextXid
Definition: standby.h:82
TransactionId latestCompletedXid
Definition: standby.h:84
TransactionId * xids
Definition: standby.h:86
FullTransactionId latestCompletedXid
Definition: transam.h:238
XLogRecPtr InitializedUpTo
Definition: xlog.c:492
char * pages
Definition: xlog.c:499
pg_time_t lastSegSwitchTime
Definition: xlog.c:473
XLogRecPtr lastSegSwitchLSN
Definition: xlog.c:474
XLogRecPtr * xlblocks
Definition: xlog.c:500
XLogRecPtr Flush
Definition: xlog.c:325
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:2061
void restoreTwoPhaseData(void)
Definition: twophase.c:1877
TransactionId PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
Definition: twophase.c:1939
void StandbyRecoverPreparedTransactions(void)
Definition: twophase.c:2020
void WalSndWakeup(void)
Definition: walsender.c:3309
void UpdateFullPageWrites(void)
Definition: xlog.c:7463
static char * str_time(pg_time_t tnow)
Definition: xlog.c:4654
static void ValidateXLOGDirectoryStructure(void)
Definition: xlog.c:3789
static XLogRecPtr CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr missingContrecPtr, TimeLineID newTLI)
Definition: xlog.c:6760
static void XLogReportParameters(void)
Definition: xlog.c:7400
static bool PerformRecoveryXLogAction(void)
Definition: xlog.c:5703
static void CleanupAfterArchiveRecovery(TimeLineID EndOfLogTLI, XLogRecPtr EndOfLog, TimeLineID newTLI)
Definition: xlog.c:4745
static bool lastFullPageWrites
Definition: xlog.c:214
static uint64 XLogRecPtrToBytePos(XLogRecPtr ptr)
Definition: xlog.c:1728
static void XLogInitNewTimeline(TimeLineID endTLI, XLogRecPtr endOfLog, TimeLineID newTLI)
Definition: xlog.c:4669
static void CheckRequiredParameterValues(void)
Definition: xlog.c:4834
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:583
static void RemoveTempXlogFiles(void)
Definition: xlog.c:3522
#define TABLESPACE_MAP_OLD
Definition: xlog.h:296
#define TABLESPACE_MAP
Definition: xlog.h:295
#define STANDBY_SIGNAL_FILE
Definition: xlog.h:291
#define BACKUP_LABEL_OLD
Definition: xlog.h:293
#define RECOVERY_SIGNAL_FILE
Definition: xlog.h:290
#define XRecOffIsValid(xlrp)
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
void ShutdownWalRecovery(void)
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:134
bool InArchiveRecovery
Definition: xlogrecovery.c:135
void PerformWalRecovery(void)
EndOfWalRecoveryInfo * FinishWalRecovery(void)
static XLogRecPtr missingContrecPtr
Definition: xlogrecovery.c:370
static XLogRecPtr abortedRecPtr
Definition: xlogrecovery.c:369
void InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
Definition: xlogrecovery.c:490
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:119
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, XLogCtlData::InstallXLogFileSegmentActive, 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(), SetCommitTsLimit(), 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 5628 of file xlog.c.

5629 {
5630  /* initialize minRecoveryPoint to this record */
5631  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5633  if (ControlFile->minRecoveryPoint < EndRecPtr)
5634  {
5635  ControlFile->minRecoveryPoint = EndRecPtr;
5636  ControlFile->minRecoveryPointTLI = replayTLI;
5637  }
5638  /* update local copy */
5641 
5642  /*
5643  * The startup process can update its local copy of minRecoveryPoint from
5644  * this point.
5645  */
5646  updateMinRecoveryPoint = true;
5647 
5649 
5650  /*
5651  * We update SharedRecoveryState while holding the lock on ControlFileLock
5652  * so both states are consistent in shared memory.
5653  */
5657 
5658  LWLockRelease(ControlFileLock);
5659 }
static bool updateMinRecoveryPoint
Definition: xlog.c:627

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 7463 of file xlog.c.

7464 {
7466  bool recoveryInProgress;
7467 
7468  /*
7469  * Do nothing if full_page_writes has not been changed.
7470  *
7471  * It's safe to check the shared full_page_writes without the lock,
7472  * because we assume that there is no concurrently running process which
7473  * can update it.
7474  */
7475  if (fullPageWrites == Insert->fullPageWrites)
7476  return;
7477 
7478  /*
7479  * Perform this outside critical section so that the WAL insert
7480  * initialization done by RecoveryInProgress() doesn't trigger an
7481  * assertion failure.
7482  */
7483  recoveryInProgress = RecoveryInProgress();
7484 
7486 
7487  /*
7488  * It's always safe to take full page images, even when not strictly
7489  * required, but not the other round. So if we're setting full_page_writes
7490  * to true, first set it true and then write the WAL record. If we're
7491  * setting it to false, first write the WAL record and then set the global
7492  * flag.
7493  */
7494  if (fullPageWrites)
7495  {
7497  Insert->fullPageWrites = true;
7499  }
7500 
7501  /*
7502  * Write an XLOG_FPW_CHANGE record. This allows us to keep track of
7503  * full_page_writes during archive recovery, if required.
7504  */
7505  if (XLogStandbyInfoActive() && !recoveryInProgress)
7506  {
7507  XLogBeginInsert();
7508  XLogRegisterData((char *) (&fullPageWrites), sizeof(bool));
7509 
7510  XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE);
7511  }
7512 
7513  if (!fullPageWrites)
7514  {
7516  Insert->fullPageWrites = false;
7518  }
7519  END_CRIT_SECTION();
7520 }
#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,
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:439
#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:165
const char * name
Definition: guc.h:166
int val
Definition: guc.h:167
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:408
#define XLogRecGetData(decoder)
Definition: xlogreader.h:413
#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 ( XLogReaderState record)

Definition at line 7532 of file xlog.c.

7533 {
7534  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
7535  XLogRecPtr lsn = record->EndRecPtr;
7536 
7537  /*
7538  * In XLOG rmgr, backup blocks are only used by XLOG_FPI and
7539  * XLOG_FPI_FOR_HINT records.
7540  */
7541  Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
7542  !XLogRecHasAnyBlockRefs(record));
7543 
7544  if (info == XLOG_NEXTOID)
7545  {
7546  Oid nextOid;
7547 
7548  /*
7549  * We used to try to take the maximum of ShmemVariableCache->nextOid
7550  * and the recorded nextOid, but that fails if the OID counter wraps
7551  * around. Since no OID allocation should be happening during replay
7552  * anyway, better to just believe the record exactly. We still take
7553  * OidGenLock while setting the variable, just in case.
7554  */
7555  memcpy(&nextOid, XLogRecGetData(record), sizeof(Oid));
7556  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7557  ShmemVariableCache->nextOid = nextOid;
7559  LWLockRelease(OidGenLock);
7560  }
7561  else if (info == XLOG_CHECKPOINT_SHUTDOWN)
7562  {
7563  CheckPoint checkPoint;
7564  TimeLineID replayTLI;
7565 
7566  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7567  /* In a SHUTDOWN checkpoint, believe the counters exactly */
7568  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7569  ShmemVariableCache->nextXid = checkPoint.nextXid;
7570  LWLockRelease(XidGenLock);
7571  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7572  ShmemVariableCache->nextOid = checkPoint.nextOid;
7574  LWLockRelease(OidGenLock);
7575  MultiXactSetNextMXact(checkPoint.nextMulti,
7576  checkPoint.nextMultiOffset);
7577 
7579  checkPoint.oldestMultiDB);
7580 
7581  /*
7582  * No need to set oldestClogXid here as well; it'll be set when we
7583  * redo an xl_clog_truncate if it changed since initialization.
7584  */
7585  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
7586 
7587  /*
7588  * If we see a shutdown checkpoint while waiting for an end-of-backup
7589  * record, the backup was canceled and the end-of-backup record will
7590  * never arrive.
7591  */
7595  ereport(PANIC,
7596  (errmsg("online backup was canceled, recovery cannot continue")));
7597 
7598  /*
7599  * If we see a shutdown checkpoint, we know that nothing was running
7600  * on the primary at this point. So fake-up an empty running-xacts
7601  * record and use that here and now. Recover additional standby state
7602  * for prepared transactions.
7603  */
7605  {
7606  TransactionId *xids;
7607  int nxids;
7608  TransactionId oldestActiveXID;
7609  TransactionId latestCompletedXid;
7610  RunningTransactionsData running;
7611 
7612  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
7613 
7614  /*
7615  * Construct a RunningTransactions snapshot representing a shut
7616  * down server, with only prepared transactions still alive. We're
7617  * never overflowed at this point because all subxids are listed
7618  * with their parent prepared transactions.
7619  */
7620  running.xcnt = nxids;
7621  running.subxcnt = 0;
7622  running.subxid_overflow = false;
7623  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
7624  running.oldestRunningXid = oldestActiveXID;
7625  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
7626  TransactionIdRetreat(latestCompletedXid);
7627  Assert(TransactionIdIsNormal(latestCompletedXid));
7628  running.latestCompletedXid = latestCompletedXid;
7629  running.xids = xids;
7630 
7631  ProcArrayApplyRecoveryInfo(&running);
7632 
7634  }
7635 
7636  /* ControlFile->checkPointCopy always tracks the latest ckpt XID */
7637  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7638  ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
7639  LWLockRelease(ControlFileLock);
7640 
7641  /* Update shared-memory copy of checkpoint XID/epoch */
7643  XLogCtl->ckptFullXid = checkPoint.nextXid;
7645 
7646  /*
7647  * We should've already switched to the new TLI before replaying this
7648  * record.
7649  */
7650  (void) GetCurrentReplayRecPtr(&replayTLI);
7651  if (checkPoint.ThisTimeLineID != replayTLI)
7652  ereport(PANIC,
7653  (errmsg("unexpected timeline ID %u (should be %u) in shutdown checkpoint record",
7654  checkPoint.ThisTimeLineID, replayTLI)));
7655 
7656  RecoveryRestartPoint(&checkPoint, record);
7657  }
7658  else if (info == XLOG_CHECKPOINT_ONLINE)
7659  {
7660  CheckPoint checkPoint;
7661  TimeLineID replayTLI;
7662 
7663  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7664  /* In an ONLINE checkpoint, treat the XID counter as a minimum */
7665  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7667  checkPoint.nextXid))
7668  ShmemVariableCache->nextXid = checkPoint.nextXid;
7669  LWLockRelease(XidGenLock);
7670 
7671  /*
7672  * We ignore the nextOid counter in an ONLINE checkpoint, preferring
7673  * to track OID assignment through XLOG_NEXTOID records. The nextOid
7674  * counter is from the start of the checkpoint and might well be stale
7675  * compared to later XLOG_NEXTOID records. We could try to take the
7676  * maximum of the nextOid counter and our latest value, but since
7677  * there's no particular guarantee about the speed with which the OID
7678  * counter wraps around, that's a risky thing to do. In any case,
7679  * users of the nextOid counter are required to avoid assignment of
7680  * duplicates, so that a somewhat out-of-date value should be safe.
7681  */
7682 
7683  /* Handle multixact */
7685  checkPoint.nextMultiOffset);
7686 
7687  /*
7688