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

Go to the source code of this file.

Data Structures

struct  CheckpointStatsData
 

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Variables

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

Macro Definition Documentation

◆ BACKUP_LABEL_FILE

#define BACKUP_LABEL_FILE   "backup_label"

Definition at line 290 of file xlog.h.

◆ BACKUP_LABEL_OLD

#define BACKUP_LABEL_OLD   "backup_label.old"

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

◆ RECOVERY_SIGNAL_FILE

#define RECOVERY_SIGNAL_FILE   "recovery.signal"

Definition at line 288 of file xlog.h.

◆ STANDBY_SIGNAL_FILE

#define STANDBY_SIGNAL_FILE   "standby.signal"

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

◆ TABLESPACE_MAP_OLD

#define TABLESPACE_MAP_OLD   "tablespace_map.old"

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

276 {
@ SESSION_BACKUP_NONE
Definition: xlog.h:275

◆ WALAvailability

Enumerator
WALAVAIL_INVALID_LSN 
WALAVAIL_RESERVED 
WALAVAIL_EXTENDED 
WALAVAIL_UNRESERVED 
WALAVAIL_REMOVED 

Definition at line 181 of file xlog.h.

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

◆ WalCompression

Enumerator
WAL_COMPRESSION_NONE 
WAL_COMPRESSION_PGLZ 
WAL_COMPRESSION_LZ4 
WAL_COMPRESSION_ZSTD 

Definition at line 75 of file xlog.h.

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

◆ WalLevel

enum WalLevel
Enumerator
WAL_LEVEL_MINIMAL 
WAL_LEVEL_REPLICA 
WAL_LEVEL_LOGICAL 

Definition at line 67 of file xlog.h.

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

Function Documentation

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 4631 of file xlog.c.

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

Referenced by BootstrapModeMain().

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3433 of file xlog.c.

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

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

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

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 6436 of file xlog.c.

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

References ControlFileData::checkPoint, CHECKPOINT_END_OF_RECOVERY, CHECKPOINT_FORCE, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStats, CheckpointStatsData::ckpt_bufs_written, CheckpointStatsData::ckpt_segs_added, CheckpointStatsData::ckpt_segs_recycled, CheckpointStatsData::ckpt_segs_removed, CheckpointStatsData::ckpt_start_t, XLogCtlData::ckptFullXid, ControlFile, DB_SHUTDOWNED, DB_SHUTDOWNING, DEBUG1, DELAY_CHKPT_COMPLETE, DELAY_CHKPT_START, elog(), END_CRIT_SECTION, ereport, errmsg(), errmsg_internal(), ERROR, CheckPoint::fullPageWrites, GetCurrentTimestamp(), GetLastImportantRecPtr(), GetOldestActiveTransactionId(), GetOldestTransactionIdConsideredRunning(), GetVirtualXIDsDelayingChkpt(), HaveVirtualXIDsDelayingChkpt(), XLogCtlData::info_lck, XLogCtlData::Insert, Insert(), INSERT_FREESPACE, XLogCtlData::InsertTimeLineID, InvalidateObsoleteReplicationSlots(), 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 7077 of file xlog.c.

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

References archiveCleanupCommand, Assert(), B_CHECKPOINTER, ControlFileData::checkPoint, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStats, CheckpointStatsData::ckpt_start_t, ControlFile, DB_IN_ARCHIVE_RECOVERY, DB_SHUTDOWNED_IN_RECOVERY, DEBUG2, EnableHotStandby, ereport, errdetail(), errmsg(), errmsg_internal(), GetCurrentTimestamp(), GetLatestXTime(), GetOldestRestartPointFileName(), 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(), MAXFNAMELEN, MemSet, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyBackendType, PreallocXlogFiles(), RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), shell_archive_cleanup(), SpinLockAcquire, SpinLockRelease, ControlFileData::state, CheckPoint::ThisTimeLineID, timestamptz_to_str(), TruncateSUBTRANS(), update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), UpdateMinRecoveryPoint(), 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 8818 of file xlog.c.

8819 {
8820  bool during_backup_start = DatumGetBool(arg);
8821 
8822  /* If called during backup start, there shouldn't be one already running */
8823  Assert(!during_backup_start || sessionBackupState == SESSION_BACKUP_NONE);
8824 
8825  if (during_backup_start || sessionBackupState != SESSION_BACKUP_NONE)
8826  {
8830 
8833 
8834  if (!during_backup_start)
8835  ereport(WARNING,
8836  errmsg("aborting backup due to backend exiting before pg_backup_stop was called"));
8837  }
8838 }
#define WARNING
Definition: elog.h:36
void * arg
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
int runningBackups
Definition: xlog.c:447
static SessionBackupState sessionBackupState
Definition: xlog.c:400

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

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

◆ do_pg_backup_start()

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

Definition at line 8245 of file xlog.c.

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

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

Referenced by perform_base_backup(), and pg_backup_start().

◆ do_pg_backup_stop()

void do_pg_backup_stop ( BackupState state,
bool  waitforarchive 
)

Definition at line 8544 of file xlog.c.

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

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

Referenced by perform_base_backup(), and pg_backup_stop().

◆ get_backup_status()

SessionBackupState get_backup_status ( void  )

Definition at line 8525 of file xlog.c.

8526 {
8527  return sessionBackupState;
8528 }

References sessionBackupState.

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

◆ GetFakeLSNForUnloggedRel()

XLogRecPtr GetFakeLSNForUnloggedRel ( void  )

Definition at line 4211 of file xlog.c.

4212 {
4213  XLogRecPtr nextUnloggedLSN;
4214 
4215  /* increment the unloggedLSN counter, need SpinLock */
4217  nextUnloggedLSN = XLogCtl->unloggedLSN++;
4219 
4220  return nextUnloggedLSN;
4221 }

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

Referenced by gistGetFakeLSN().

◆ GetFlushRecPtr()

XLogRecPtr GetFlushRecPtr ( TimeLineID insertTLI)

Definition at line 6073 of file xlog.c.

6074 {
6076 
6080 
6081  /*
6082  * If we're writing and flushing WAL, the time line can't be changing, so
6083  * no lock is required.
6084  */
6085  if (insertTLI)
6086  *insertTLI = XLogCtl->InsertTimeLineID;
6087 
6088  return LogwrtResult.Flush;
6089 }
RecoveryState SharedRecoveryState
Definition: xlog.c:522
XLogwrtResult LogwrtResult
Definition: xlog.c:484
XLogRecPtr Flush
Definition: xlog.c:337
static XLogwrtResult LogwrtResult
Definition: xlog.c:608

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

Referenced by get_flush_position(), 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 6041 of file xlog.c.

6042 {
6043  *RedoRecPtr_p = RedoRecPtr;
6044  *doPageWrites_p = doPageWrites;
6045 }
static bool doPageWrites
Definition: xlog.c:289

References doPageWrites, and RedoRecPtr.

Referenced by XLogCheckBufferNeedsBackup(), and XLogInsert().

◆ GetInsertRecPtr()

XLogRecPtr GetInsertRecPtr ( void  )

Definition at line 6056 of file xlog.c.

6057 {
6058  XLogRecPtr recptr;
6059 
6061  recptr = XLogCtl->LogwrtRqst.Write;
6063 
6064  return recptr;
6065 }
XLogwrtRqst LogwrtRqst
Definition: xlog.c:464
XLogRecPtr Write
Definition: xlog.c:330

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

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

◆ GetLastImportantRecPtr()

XLogRecPtr GetLastImportantRecPtr ( void  )

Definition at line 6113 of file xlog.c.

6114 {
6116  int i;
6117 
6118  for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
6119  {
6120  XLogRecPtr last_important;
6121 
6122  /*
6123  * Need to take a lock to prevent torn reads of the LSN, which are
6124  * possible on some of the supported platforms. WAL insert locks only
6125  * support exclusive mode, so we have to use that.
6126  */
6128  last_important = WALInsertLocks[i].l.lastImportantAt;
6129  LWLockRelease(&WALInsertLocks[i].l.lock);
6130 
6131  if (res < last_important)
6132  res = last_important;
6133  }
6134 
6135  return res;
6136 }
int i
Definition: isn.c:73
XLogRecPtr lastImportantAt
Definition: xlog.c:380
WALInsertLock l
Definition: xlog.c:392
static WALInsertLockPadded * WALInsertLocks
Definition: xlog.c:565
#define NUM_XLOGINSERT_LOCKS
Definition: xlog.c:153

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

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

◆ GetMockAuthenticationNonce()

char* GetMockAuthenticationNonce ( void  )

Definition at line 4185 of file xlog.c.

4186 {
4187  Assert(ControlFile != NULL);
4189 }
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 5944 of file xlog.c.

5945 {
5946  RecoveryState retval;
5947 
5949  retval = XLogCtl->SharedRecoveryState;
5951 
5952  return retval;
5953 }

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

Referenced by XLogArchiveCheckDone().

◆ GetRedoRecPtr()

XLogRecPtr GetRedoRecPtr ( void  )

Definition at line 6011 of file xlog.c.

6012 {
6013  XLogRecPtr ptr;
6014 
6015  /*
6016  * The possibly not up-to-date copy in XlogCtl is enough. Even if we
6017  * grabbed a WAL insertion lock to read the authoritative value in
6018  * Insert->RedoRecPtr, someone might update it just after we've released
6019  * the lock.
6020  */
6022  ptr = XLogCtl->RedoRecPtr;
6024 
6025  if (RedoRecPtr < ptr)
6026  RedoRecPtr = ptr;
6027 
6028  return RedoRecPtr;
6029 }

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

4176 {
4177  Assert(ControlFile != NULL);
4179 }
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 7349 of file xlog.c.

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

6097 {
6099 
6100  /* Since the value can't be changing, no lock is required. */
6101  return XLogCtl->InsertTimeLineID;
6102 }

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

8860 {
8862  uint64 current_bytepos;
8863 
8864  SpinLockAcquire(&Insert->insertpos_lck);
8865  current_bytepos = Insert->CurrBytePos;
8866  SpinLockRelease(&Insert->insertpos_lck);
8867 
8868  return XLogBytePosToRecPtr(current_bytepos);
8869 }

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

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

◆ GetXLogWriteRecPtr()

◆ InitializeWalConsistencyChecking()

void InitializeWalConsistencyChecking ( void  )

Definition at line 4398 of file xlog.c.

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

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

Referenced by PostgresSingleUserMain(), and PostmasterMain().

◆ IsInstallXLogFileSegmentActive()

bool IsInstallXLogFileSegmentActive ( void  )

Definition at line 8934 of file xlog.c.

8935 {
8936  bool result;
8937 
8938  LWLockAcquire(ControlFileLock, LW_SHARED);
8940  LWLockRelease(ControlFileLock);
8941 
8942  return result;
8943 }
bool InstallXLogFileSegmentActive
Definition: xlog.c:532

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

Referenced by XLogFileRead().

◆ issue_xlog_fsync()

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

Definition at line 8137 of file xlog.c.

8138 {
8139  char *msg = NULL;
8140  instr_time start;
8141 
8142  Assert(tli != 0);
8143 
8144  /*
8145  * Quick exit if fsync is disabled or write() has already synced the WAL
8146  * file.
8147  */
8148  if (!enableFsync ||
8151  return;
8152 
8153  /* Measure I/O timing to sync the WAL file */
8154  if (track_wal_io_timing)
8155  INSTR_TIME_SET_CURRENT(start);
8156  else
8157  INSTR_TIME_SET_ZERO(start);
8158 
8160  switch (sync_method)
8161  {
8162  case SYNC_METHOD_FSYNC:
8163  if (pg_fsync_no_writethrough(fd) != 0)
8164  msg = _("could not fsync file \"%s\": %m");
8165  break;
8166 #ifdef HAVE_FSYNC_WRITETHROUGH
8168  if (pg_fsync_writethrough(fd) != 0)
8169  msg = _("could not fsync write-through file \"%s\": %m");
8170  break;
8171 #endif
8172  case SYNC_METHOD_FDATASYNC:
8173  if (pg_fdatasync(fd) != 0)
8174  msg = _("could not fdatasync file \"%s\": %m");
8175  break;
8176  case SYNC_METHOD_OPEN:
8178  /* not reachable */
8179  Assert(false);
8180  break;
8181  default:
8182  elog(PANIC, "unrecognized wal_sync_method: %d", sync_method);
8183  break;
8184  }
8185 
8186  /* PANIC if failed to fsync */
8187  if (msg)
8188  {
8189  char xlogfname[MAXFNAMELEN];
8190  int save_errno = errno;
8191 
8192  XLogFileName(xlogfname, tli, segno, wal_segment_size);
8193  errno = save_errno;
8194  ereport(PANIC,
8196  errmsg(msg, xlogfname)));
8197  }
8198 
8200 
8201  /*
8202  * Increment the I/O timing and the number of times WAL files were synced.
8203  */
8204  if (track_wal_io_timing)
8205  {
8207 
8209  INSTR_TIME_SUBTRACT(duration, start);
8211  }
8212 
8214 }
#define _(x)
Definition: elog.c:91
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:411
int pg_fdatasync(int fd)
Definition: fd.c:444
int pg_fsync_writethrough(int fd)
Definition: fd.c:423
bool enableFsync
Definition: globals.c:123
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:181
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:194
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:172
int duration
Definition: pgbench.c:184
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:234
bool track_wal_io_timing
Definition: xlog.c:140
int sync_method
Definition: xlog.c:133
#define SYNC_METHOD_FSYNC
Definition: xlog.h:22
#define SYNC_METHOD_OPEN
Definition: xlog.h:24
#define SYNC_METHOD_FDATASYNC
Definition: xlog.h:23
#define SYNC_METHOD_OPEN_DSYNC
Definition: xlog.h:26
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:25

References _, Assert(), duration, elog(), enableFsync, ereport, errcode_for_file_access(), errmsg(), fd(), INSTR_TIME_GET_MICROSEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SET_ZERO, 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 4461 of file xlog.c.

4462 {
4463  Assert(reset || ControlFile == NULL);
4464  ControlFile = palloc(sizeof(ControlFileData));
4465  ReadControlFile();
4466 }
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 5821 of file xlog.c.

5822 {
5823  /*
5824  * We have reached the end of base backup, as indicated by pg_control. The
5825  * data on disk is now consistent (unless minRecovery point is further
5826  * ahead, which can happen if we crashed during previous recovery). Reset
5827  * backupStartPoint and backupEndPoint, and update minRecoveryPoint to
5828  * make sure we don't allow starting up at an earlier point even if
5829  * recovery is stopped and restarted soon after this.
5830  */
5831  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5832 
5833  if (ControlFile->minRecoveryPoint < EndRecPtr)
5834  {
5835  ControlFile->minRecoveryPoint = EndRecPtr;
5837  }
5838 
5841  ControlFile->backupEndRequired = false;
5843 
5844  LWLockRelease(ControlFileLock);
5845 }
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 5908 of file xlog.c.

5909 {
5910  /*
5911  * We check shared state each time only until we leave recovery mode. We
5912  * can't re-enter recovery, so there's no need to keep checking after the
5913  * shared variable has once been seen false.
5914  */
5916  return false;
5917  else
5918  {
5919  /*
5920  * use volatile pointer to make sure we make a fresh read of the
5921  * shared variable.
5922  */
5923  volatile XLogCtlData *xlogctl = XLogCtl;
5924 
5926 
5927  /*
5928  * Note: We don't need a memory barrier when we're still in recovery.
5929  * We might exit recovery immediately after return, so the caller
5930  * can't rely on 'true' meaning that we're still in recovery anyway.
5931  */
5932 
5933  return LocalRecoveryInProgress;
5934  }
5935 }
static bool LocalRecoveryInProgress
Definition: xlog.c:227

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

Referenced by BackgroundWriterMain(), BeginReportingGUCOptions(), brin_desummarize_range(), brin_summarize_range(), btree_index_mainfork_expected(), check_transaction_isolation(), check_transaction_read_only(), CheckArchiveTimeout(), CheckLogicalDecodingRequirements(), CheckpointerMain(), ComputeXidHorizons(), CreateCheckPoint(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), CreateRestartPoint(), do_pg_backup_start(), do_pg_backup_stop(), error_commit_ts_disabled(), get_relation_info(), 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(), recovery_create_dbdir(), ReplicationSlotReserveWal(), replorigin_check_prerequisites(), ReportChangedGUCOptions(), sendDir(), SerialSetActiveSerXmin(), show_in_hot_standby(), ShutdownXLOG(), SnapBuildWaitSnapshot(), standard_ProcessUtility(), StartLogicalReplication(), StartReplication(), StartTransaction(), TransactionIdIsInProgress(), TruncateMultiXact(), UpdateFullPageWrites(), verify_heapam(), WalReceiverMain(), WalSndWaitForWal(), XLogBackgroundFlush(), XLogInsertAllowed(), XLogNeedsFlush(), and XLogSendPhysical().

◆ register_persistent_abort_backup_handler()

void register_persistent_abort_backup_handler ( void  )

Definition at line 8845 of file xlog.c.

8846 {
8847  static bool already_done = false;
8848 
8849  if (already_done)
8850  return;
8852  already_done = true;
8853 }
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333

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

Referenced by pg_backup_start().

◆ RemoveNonParentXlogFiles()

void RemoveNonParentXlogFiles ( XLogRecPtr  switchpoint,
TimeLineID  newTLI 
)

Definition at line 3608 of file xlog.c.

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

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

8927 {
8928  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8930  LWLockRelease(ControlFileLock);
8931 }

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

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

◆ SetWalWriterSleeping()

void SetWalWriterSleeping ( bool  sleeping)

Definition at line 8949 of file xlog.c.

8950 {
8952  XLogCtl->WalWriterSleeping = sleeping;
8954 }
bool WalWriterSleeping
Definition: xlog.c:539

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

Referenced by WalWriterMain().

◆ ShutdownXLOG()

void ShutdownXLOG ( int  code,
Datum  arg 
)

Definition at line 6159 of file xlog.c.

6160 {
6161  /*
6162  * We should have an aux process resource owner to use, and we should not
6163  * be in a transaction that's installed some other resowner.
6164  */
6166  Assert(CurrentResourceOwner == NULL ||
6169 
6170  /* Don't be chatty in standalone mode */
6172  (errmsg("shutting down")));
6173 
6174  /*
6175  * Signal walsenders to move to stopping state.
6176  */
6178 
6179  /*
6180  * Wait for WAL senders to be in stopping state. This prevents commands
6181  * from writing new WAL.
6182  */
6184 
6185  if (RecoveryInProgress())
6187  else
6188  {
6189  /*
6190  * If archiving is enabled, rotate the last XLOG file so that all the
6191  * remaining records are archived (postmaster wakes up the archiver
6192  * process one more time at the end of shutdown). The checkpoint
6193  * record will go to the next XLOG file and won't be archived (yet).
6194  */
6195  if (XLogArchivingActive())
6196  RequestXLogSwitch(false);
6197 
6199  }
6200 }
bool IsPostmasterEnvironment
Definition: globals.c:112
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
ResourceOwner AuxProcessResourceOwner
Definition: resowner.c:149
void WalSndInitStopping(void)
Definition: walsender.c:3341
void WalSndWaitStopping(void)
Definition: walsender.c:3367
bool CreateRestartPoint(int flags)
Definition: xlog.c:7077
void CreateCheckPoint(int flags)
Definition: xlog.c:6436

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

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

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

Referenced by InitPostgres(), and StartupProcessMain().

◆ SwitchIntoArchiveRecovery()

void SwitchIntoArchiveRecovery ( XLogRecPtr  EndRecPtr,
TimeLineID  replayTLI 
)

Definition at line 5783 of file xlog.c.

5784 {
5785  /* initialize minRecoveryPoint to this record */
5786  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5788  if (ControlFile->minRecoveryPoint < EndRecPtr)
5789  {
5790  ControlFile->minRecoveryPoint = EndRecPtr;
5791  ControlFile->minRecoveryPointTLI = replayTLI;
5792  }
5793  /* update local copy */
5796 
5797  /*
5798  * The startup process can update its local copy of minRecoveryPoint from
5799  * this point.
5800  */
5801  updateMinRecoveryPoint = true;
5802 
5804 
5805  /*
5806  * We update SharedRecoveryState while holding the lock on ControlFileLock
5807  * so both states are consistent in shared memory.
5808  */
5812 
5813  LWLockRelease(ControlFileLock);
5814 }
static bool updateMinRecoveryPoint
Definition: xlog.c:631

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

Referenced by ReadRecord().

◆ UpdateFullPageWrites()

void UpdateFullPageWrites ( void  )

Definition at line 7632 of file xlog.c.

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

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

Referenced by StartupXLOG(), and UpdateSharedMemoryConfig().

◆ xlog_desc()

void xlog_desc ( StringInfo  buf,
struct XLogReaderState record 
)

Definition at line 37 of file xlogdesc.c.

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

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

◆ xlog_identify()

const char* xlog_identify ( uint8  info)

Definition at line 154 of file xlogdesc.c.

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

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

◆ xlog_redo()

void xlog_redo ( struct XLogReaderState record)

Definition at line 7701 of file xlog.c.

7702 {
7703  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
7704  XLogRecPtr lsn = record->EndRecPtr;
7705 
7706  /*
7707  * In XLOG rmgr, backup blocks are only used by XLOG_FPI and
7708  * XLOG_FPI_FOR_HINT records.
7709  */
7710  Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
7711  !XLogRecHasAnyBlockRefs(record));
7712 
7713  if (info == XLOG_NEXTOID)
7714  {
7715  Oid nextOid;
7716 
7717  /*
7718  * We used to try to take the maximum of ShmemVariableCache->nextOid
7719  * and the recorded nextOid, but that fails if the OID counter wraps
7720  * around. Since no OID allocation should be happening during replay
7721  * anyway, better to just believe the record exactly. We still take
7722  * OidGenLock while setting the variable, just in case.
7723  */
7724  memcpy(&nextOid, XLogRecGetData(record), sizeof(Oid));
7725  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7726  ShmemVariableCache->nextOid = nextOid;
7728  LWLockRelease(OidGenLock);
7729  }
7730  else if (info == XLOG_CHECKPOINT_SHUTDOWN)
7731  {
7732  CheckPoint checkPoint;
7733  TimeLineID replayTLI;
7734 
7735  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7736  /* In a SHUTDOWN checkpoint, believe the counters exactly */
7737  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7738  ShmemVariableCache->nextXid = checkPoint.nextXid;
7739  LWLockRelease(XidGenLock);
7740  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7741  ShmemVariableCache->nextOid = checkPoint.nextOid;
7743  LWLockRelease(OidGenLock);
7744  MultiXactSetNextMXact(checkPoint.nextMulti,
7745  checkPoint.nextMultiOffset);
7746 
7748  checkPoint.oldestMultiDB);
7749 
7750  /*
7751  * No need to set oldestClogXid here as well; it'll be set when we
7752  * redo an xl_clog_truncate if it changed since initialization.
7753  */
7754  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
7755 
7756  /*
7757  * If we see a shutdown checkpoint while waiting for an end-of-backup
7758  * record, the backup was canceled and the end-of-backup record will
7759  * never arrive.
7760  */
7764  ereport(PANIC,
7765  (errmsg("online backup was canceled, recovery cannot continue")));
7766 
7767  /*
7768  * If we see a shutdown checkpoint, we know that nothing was running
7769  * on the primary at this point. So fake-up an empty running-xacts
7770  * record and use that here and now. Recover additional standby state
7771  * for prepared transactions.
7772  */
7774  {
7775  TransactionId *xids;
7776  int nxids;
7777  TransactionId oldestActiveXID;
7778  TransactionId latestCompletedXid;
7779  RunningTransactionsData running;
7780 
7781  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
7782 
7783  /*
7784  * Construct a RunningTransactions snapshot representing a shut
7785  * down server, with only prepared transactions still alive. We're
7786  * never overflowed at this point because all subxids are listed
7787  * with their parent prepared transactions.
7788  */
7789  running.xcnt = nxids;
7790  running.subxcnt = 0;
7791  running.subxid_overflow = false;
7792  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
7793  running.oldestRunningXid = oldestActiveXID;
7794  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
7795  TransactionIdRetreat(latestCompletedXid);
7796  Assert(TransactionIdIsNormal(latestCompletedXid));
7797  running.latestCompletedXid = latestCompletedXid;
7798  running.xids = xids;
7799 
7800  ProcArrayApplyRecoveryInfo(&running);
7801 
7803  }
7804 
7805  /* ControlFile->checkPointCopy always tracks the latest ckpt XID */
7806  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7807  ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
7808  LWLockRelease(ControlFileLock);
7809 
7810  /* Update shared-memory copy of checkpoint XID/epoch */
7812  XLogCtl->ckptFullXid = checkPoint.nextXid;
7814 
7815  /*
7816  * We should've already switched to the new TLI before replaying this
7817  * record.
7818  */
7819  (void) GetCurrentReplayRecPtr(&replayTLI);
7820  if (checkPoint.ThisTimeLineID != replayTLI)
7821  ereport(PANIC,
7822  (errmsg("unexpected timeline ID %u (should be %u) in shutdown checkpoint record",
7823  checkPoint.ThisTimeLineID, replayTLI)));
7824 
7825  RecoveryRestartPoint(&checkPoint, record);
7826  }
7827  else if (info == XLOG_CHECKPOINT_ONLINE)
7828  {
7829  CheckPoint checkPoint;
7830  TimeLineID replayTLI;
7831 
7832  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7833  /* In an ONLINE checkpoint, treat the XID counter as a minimum */
7834  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7836  checkPoint.nextXid))
7837  ShmemVariableCache->nextXid = checkPoint.nextXid;
7838  LWLockRelease(XidGenLock);
7839 
7840  /*
7841  * We ignore the nextOid counter in an ONLINE checkpoint, preferring
7842  * to track OID assignment through XLOG_NEXTOID records. The nextOid
7843  * counter is from the start of the checkpoint and might well be stale
7844  * compared to later XLOG_NEXTOID records. We could try to take the
7845  * maximum of the nextOid counter and our latest value, but since
7846  * there's no particular guarantee about the speed with which the OID
7847  * counter wraps around, that's a risky thing to do. In any case,
7848  * users of the nextOid counter are required to avoid assignment of
7849  * duplicates, so that a somewhat out-of-date value should be safe.
7850  */
7851 
7852  /* Handle multixact */
7854  checkPoint.nextMultiOffset);
7855 
7856  /*
7857  * NB: This may perform multixact truncation when replaying WAL
7858  * generated by an older primary.
7859  */
7861  checkPoint.oldestMultiDB);
7863  checkPoint.oldestXid))
7864  SetTransactionIdLimit(checkPoint.oldestXid,
7865  checkPoint.oldestXidDB);
7866  /* ControlFile->checkPointCopy always tracks the latest ckpt XID */
7867  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7868  ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
7869  LWLockRelease(ControlFileLock);
7870 
7871  /* Update shared-memory copy of checkpoint XID/epoch */
7873  XLogCtl->ckptFullXid = checkPoint.nextXid;
7875 
7876  /* TLI should not change in an on-line checkpoint */
7877  (void) GetCurrentReplayRecPtr(&replayTLI);
7878  if (checkPoint.ThisTimeLineID != replayTLI)
7879  ereport(PANIC,
7880  (errmsg("unexpected timeline ID %u (should be %u) in online checkpoint record",
7881  checkPoint.ThisTimeLineID, replayTLI)));
7882 
7883  RecoveryRestartPoint(&checkPoint, record);
7884  }
7885  else if (info == XLOG_OVERWRITE_CONTRECORD)
7886  {
7887  /* nothing to do here, handled in xlogrecovery_redo() */
7888  }
7889  else if (info == XLOG_END_OF_RECOVERY)
7890  {
7891  xl_end_of_recovery xlrec;
7892  TimeLineID replayTLI;
7893 
7894  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_end_of_recovery));
7895 
7896  /*
7897  * For Hot Standby, we could treat this like a Shutdown Checkpoint,
7898  * but this case is rarer and harder to test, so the benefit doesn't
7899  * outweigh the potential extra cost of maintenance.
7900  */
7901 
7902  /*
7903  * We should've already switched to the new TLI before replaying this
7904  * record.
7905  */
7906  (void) GetCurrentReplayRecPtr(&replayTLI);
7907  if (xlrec.ThisTimeLineID != replayTLI)
7908  ereport(PANIC,
7909  (errmsg("unexpected timeline ID %u (should be %u) in end-of-recovery record",
7910  xlrec.ThisTimeLineID, replayTLI)));
7911  }
7912  else if (info == XLOG_NOOP)
7913  {
7914  /* nothing to do here */
7915  }
7916  else if (info == XLOG_SWITCH)
7917  {
7918  /* nothing to do here */
7919  }
7920  else if (info == XLOG_RESTORE_POINT)
7921  {
7922  /* nothing to do here, handled in xlogrecovery.c */
7923  }
7924  else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
7925  {
7926  /*
7927  * XLOG_FPI records contain nothing else but one or more block
7928  * references. Every block reference must include a full-page image
7929  * even if full_page_writes was disabled when the record was generated
7930  * - otherwise there would be no point in this record.
7931  *
7932  * XLOG_FPI_FOR_HINT records are generated when a page needs to be
7933  * WAL-logged because of a hint bit update. They are only generated
7934  * when checksums and/or wal_log_hints are enabled. They may include
7935  * no full-page images if full_page_writes was disabled when they were
7936  * generated. In this case there is nothing to do here.
7937  *
7938  * No recovery conflicts are generated by these generic records - if a
7939  * resource manager needs to generate conflicts, it has to define a
7940  * separate WAL record type and redo routine.
7941  */
7942  for (uint8 block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
7943  {
7944  Buffer buffer;
7945 
7946  if (!XLogRecHasBlockImage(record, block_id))
7947  {