PostgreSQL Source Code  git master
xlog.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "access/clog.h"
#include "access/commit_ts.h"
#include "access/heaptoast.h"
#include "access/multixact.h"
#include "access/rewriteheap.h"
#include "access/subtrans.h"
#include "access/timeline.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "access/xlogarchive.h"
#include "access/xloginsert.h"
#include "access/xlogprefetch.h"
#include "access/xlogreader.h"
#include "access/xlogutils.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "catalog/pg_database.h"
#include "commands/progress.h"
#include "commands/tablespace.h"
#include "common/controldata_utils.h"
#include "executor/instrument.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "port/pg_iovec.h"
#include "postmaster/bgwriter.h"
#include "postmaster/startup.h"
#include "postmaster/walwriter.h"
#include "replication/basebackup.h"
#include "replication/logical.h"
#include "replication/origin.h"
#include "replication/slot.h"
#include "replication/snapbuild.h"
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/large_object.h"
#include "storage/latch.h"
#include "storage/pmsignal.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/reinit.h"
#include "storage/smgr.h"
#include "storage/spin.h"
#include "storage/sync.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
#include "utils/pg_rusage.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
Include dependency graph for xlog.c:

Go to the source code of this file.

Data Structures

struct  XLogwrtRqst
 
struct  XLogwrtResult
 
struct  WALInsertLock
 
union  WALInsertLockPadded
 
struct  XLogCtlInsert
 
struct  XLogCtlData
 

Macros

#define RECOVERY_COMMAND_FILE   "recovery.conf"
 
#define RECOVERY_COMMAND_DONE   "recovery.done"
 
#define NUM_XLOGINSERT_LOCKS   8
 
#define INSERT_FREESPACE(endptr)   (((endptr) % XLOG_BLCKSZ == 0) ? 0 : (XLOG_BLCKSZ - (endptr) % XLOG_BLCKSZ))
 
#define NextBufIdx(idx)   (((idx) == XLogCtl->XLogCacheBlck) ? 0 : ((idx) + 1))
 
#define XLogRecPtrToBufIdx(recptr)   (((recptr) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))
 
#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)
 
#define ConvertToXSegs(x, segsize)   XLogMBVarToSegs((x), (segsize))
 

Typedefs

typedef struct XLogwrtRqst XLogwrtRqst
 
typedef struct XLogwrtResult XLogwrtResult
 
typedef union WALInsertLockPadded WALInsertLockPadded
 
typedef enum ExclusiveBackupState ExclusiveBackupState
 
typedef struct XLogCtlInsert XLogCtlInsert
 
typedef struct XLogCtlData XLogCtlData
 

Enumerations

enum  ExclusiveBackupState { EXCLUSIVE_BACKUP_NONE = 0, EXCLUSIVE_BACKUP_STARTING, EXCLUSIVE_BACKUP_IN_PROGRESS, EXCLUSIVE_BACKUP_STOPPING }
 
enum  XLogSource { XLOG_FROM_ANY = 0, XLOG_FROM_ARCHIVE, XLOG_FROM_PG_WAL, XLOG_FROM_STREAM }
 

Functions

static void readRecoverySignalFile (void)
 
static void validateRecoveryParameters (void)
 
static void exitArchiveRecovery (TimeLineID endTLI, XLogRecPtr endOfLog)
 
static bool recoveryStopsBefore (XLogReaderState *record)
 
static bool recoveryStopsAfter (XLogReaderState *record)
 
static void ConfirmRecoveryPaused (void)
 
static void recoveryPausesHere (bool endOfRecovery)
 
static bool recoveryApplyDelay (XLogReaderState *record)
 
static void SetLatestXTime (TimestampTz xtime)
 
static void SetCurrentChunkStartTime (TimestampTz xtime)
 
static void CheckRequiredParameterValues (void)
 
static void XLogReportParameters (void)
 
static void checkTimeLineSwitch (XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI)
 
static void LocalSetXLogInsertAllowed (void)
 
static void CreateEndOfRecoveryRecord (void)
 
static void CheckPointGuts (XLogRecPtr checkPointRedo, int flags)
 
static void KeepLogSeg (XLogRecPtr recptr, XLogSegNo *logSegNo)
 
static XLogRecPtr XLogGetReplicationSlotMinimumLSN (void)
 
static void AdvanceXLInsertBuffer (XLogRecPtr upto, bool opportunistic)
 
static bool XLogCheckpointNeeded (XLogSegNo new_segno)
 
static void XLogWrite (XLogwrtRqst WriteRqst, bool flexible)
 
static bool InstallXLogFileSegment (XLogSegNo *segno, char *tmppath, bool find_free, XLogSegNo max_segno, bool use_lock)
 
static int XLogFileRead (XLogSegNo segno, int emode, TimeLineID tli, XLogSource source, bool notfoundOk)
 
static int XLogFileReadAnyTLI (XLogSegNo segno, int emode, XLogSource source)
 
static bool XLogPageRead (XLogReaderState *state, bool fetching_ckpt, int emode, bool randAccess, bool nowait)
 
static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr, XLogSegNo readSegNo)
 
static int emode_for_corrupt_record (int emode, XLogRecPtr RecPtr)
 
static void XLogFileClose (void)
 
static void PreallocXlogFiles (XLogRecPtr endptr)
 
static void RemoveTempXlogFiles (void)
 
static void RemoveOldXlogFiles (XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
 
static void RemoveXlogFile (const char *segname, XLogSegNo recycleSegNo, XLogSegNo *endlogSegNo)
 
static void UpdateLastRemovedPtr (char *filename)
 
static void ValidateXLOGDirectoryStructure (void)
 
static void CleanupBackupHistory (void)
 
static void UpdateMinRecoveryPoint (XLogRecPtr lsn, bool force)
 
static XLogRecordReadRecord (XLogReaderState *xlogreader, int emode, bool fetching_ckpt)
 
static void CheckRecoveryConsistency (void)
 
static XLogRecordReadCheckpointRecord (XLogReaderState *xlogreader, XLogRecPtr RecPtr, int whichChkpt, bool report)
 
static bool rescanLatestTimeLine (void)
 
static void InitControlFile (uint64 sysidentifier)
 
static void WriteControlFile (void)
 
static void ReadControlFile (void)
 
static char * str_time (pg_time_t tnow)
 
static void SetPromoteIsTriggered (void)
 
static bool CheckForStandbyTrigger (void)
 
static void xlog_block_info (StringInfo buf, XLogReaderState *record)
 
static void xlog_outdesc (StringInfo buf, XLogReaderState *record)
 
static void pg_start_backup_callback (int code, Datum arg)
 
static void pg_stop_backup_callback (int code, Datum arg)
 
static bool read_backup_label (XLogRecPtr *checkPointLoc, bool *backupEndRequired, bool *backupFromStandby)
 
static bool read_tablespace_map (List **tablespaces)
 
static void rm_redo_error_callback (void *arg)
 
static int get_sync_bit (int method)
 
static void CopyXLogRecordToWAL (int write_len, bool isLogSwitch, XLogRecData *rdata, XLogRecPtr StartPos, XLogRecPtr EndPos)
 
static void ReserveXLogInsertLocation (int size, XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
 
static bool ReserveXLogSwitch (XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
 
static XLogRecPtr WaitXLogInsertionsToFinish (XLogRecPtr upto)
 
static char * GetXLogBuffer (XLogRecPtr ptr)
 
static XLogRecPtr XLogBytePosToRecPtr (uint64 bytepos)
 
static XLogRecPtr XLogBytePosToEndRecPtr (uint64 bytepos)
 
static uint64 XLogRecPtrToBytePos (XLogRecPtr ptr)
 
static void checkXLogConsistency (XLogReaderState *record)
 
static void WALInsertLockAcquire (void)
 
static void WALInsertLockAcquireExclusive (void)
 
static void WALInsertLockRelease (void)
 
static void WALInsertLockUpdateInsertingAt (XLogRecPtr insertingAt)
 
XLogRecPtr XLogInsertRecord (XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi)
 
static void CalculateCheckpointSegments (void)
 
void assign_max_wal_size (int newval, void *extra)
 
void assign_checkpoint_completion_target (double newval, void *extra)
 
static XLogSegNo XLOGfileslop (XLogRecPtr lastredoptr)
 
void XLogSetAsyncXactLSN (XLogRecPtr asyncXactLSN)
 
void XLogSetReplicationSlotMinimumLSN (XLogRecPtr lsn)
 
void XLogFlush (XLogRecPtr record)
 
bool XLogBackgroundFlush (void)
 
bool XLogNeedsFlush (XLogRecPtr record)
 
int XLogFileInit (XLogSegNo logsegno, bool *use_existent, bool use_lock)
 
static void XLogFileCopy (XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno, int upto)
 
int XLogFileOpen (XLogSegNo segno)
 
void CheckXLogRemoved (XLogSegNo segno, TimeLineID tli)
 
XLogSegNo XLogGetLastRemovedSegno (void)
 
static void RemoveNonParentXlogFiles (XLogRecPtr switchpoint, TimeLineID newTLI)
 
void UpdateControlFile (void)
 
uint64 GetSystemIdentifier (void)
 
char * GetMockAuthenticationNonce (void)
 
bool DataChecksumsEnabled (void)
 
XLogRecPtr GetFakeLSNForUnloggedRel (void)
 
static int XLOGChooseNumBuffers (void)
 
bool check_wal_buffers (int *newval, void **extra, GucSource source)
 
void LocalProcessControlFile (bool reset)
 
Size XLOGShmemSize (void)
 
void XLOGShmemInit (void)
 
void BootStrapXLOG (void)
 
static bool getRecordTimestamp (XLogReaderState *record, TimestampTz *recordXtime)
 
RecoveryPauseState GetRecoveryPauseState (void)
 
void SetRecoveryPause (bool recoveryPause)
 
TimestampTz GetLatestXTime (void)
 
TimestampTz GetCurrentChunkReplayStartTime (void)
 
void GetXLogReceiptTime (TimestampTz *rtime, bool *fromStream)
 
static void RecoveryRequiresIntParameter (const char *param_name, int currValue, int minValue)
 
void StartupXLOG (void)
 
bool RecoveryInProgress (void)
 
RecoveryState GetRecoveryState (void)
 
bool HotStandbyActive (void)
 
bool HotStandbyActiveInReplay (void)
 
bool XLogInsertAllowed (void)
 
void InitXLOGAccess (void)
 
XLogRecPtr GetRedoRecPtr (void)
 
void GetFullPageWriteInfo (XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
 
XLogRecPtr GetInsertRecPtr (void)
 
XLogRecPtr GetFlushRecPtr (void)
 
XLogRecPtr GetLastImportantRecPtr (void)
 
pg_time_t GetLastSegSwitchData (XLogRecPtr *lastSwitchLSN)
 
void ShutdownXLOG (int code, Datum arg)
 
static void LogCheckpointStart (int flags, bool restartpoint)
 
static void LogCheckpointEnd (bool restartpoint)
 
static void UpdateCheckPointDistanceEstimate (uint64 nbytes)
 
static void update_checkpoint_display (int flags, bool restartpoint, bool reset)
 
void CreateCheckPoint (int flags)
 
static void RecoveryRestartPoint (const CheckPoint *checkPoint)
 
bool CreateRestartPoint (int flags)
 
WALAvailability GetWALAvailability (XLogRecPtr targetLSN)
 
void XLogPutNextOid (Oid nextOid)
 
XLogRecPtr RequestXLogSwitch (bool mark_unimportant)
 
XLogRecPtr XLogRestorePoint (const char *rpName)
 
void UpdateFullPageWrites (void)
 
void xlog_redo (XLogReaderState *record)
 
void assign_xlog_sync_method (int new_sync_method, void *extra)
 
void issue_xlog_fsync (int fd, XLogSegNo segno)
 
XLogRecPtr do_pg_start_backup (const char *backupidstr, bool fast, TimeLineID *starttli_p, StringInfo labelfile, List **tablespaces, StringInfo tblspcmapfile)
 
SessionBackupState get_backup_status (void)
 
XLogRecPtr do_pg_stop_backup (char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 
void do_pg_abort_backup (int code, Datum arg)
 
void register_persistent_abort_backup_handler (void)
 
XLogRecPtr GetXLogReplayRecPtr (TimeLineID *replayTLI)
 
XLogRecPtr GetXLogInsertRecPtr (void)
 
XLogRecPtr GetXLogWriteRecPtr (void)
 
void GetOldestRestartPoint (XLogRecPtr *oldrecptr, TimeLineID *oldtli)
 
bool BackupInProgress (void)
 
void CancelBackup (void)
 
void StartupRequestWalReceiverRestart (void)
 
bool PromoteIsTriggered (void)
 
void RemovePromoteSignalFiles (void)
 
bool CheckPromoteSignal (void)
 
void WakeupRecovery (void)
 
void SetWalWriterSleeping (bool sleeping)
 
void XLogRequestWalReceiverReply (void)
 

Variables

uint32 bootstrap_data_checksum_version
 
int max_wal_size_mb = 1024
 
int min_wal_size_mb = 80
 
int wal_keep_size_mb = 0
 
int XLOGbuffers = -1
 
int XLogArchiveTimeout = 0
 
int XLogArchiveMode = ARCHIVE_MODE_OFF
 
char * XLogArchiveCommand = NULL
 
bool EnableHotStandby = false
 
bool fullPageWrites = true
 
bool wal_log_hints = false
 
bool wal_compression = false
 
char * wal_consistency_checking_string = NULL
 
boolwal_consistency_checking = NULL
 
bool wal_init_zero = true
 
bool wal_recycle = true
 
bool log_checkpoints = false
 
int sync_method = DEFAULT_SYNC_METHOD
 
int wal_level = WAL_LEVEL_MINIMAL
 
int CommitDelay = 0
 
int CommitSiblings = 5
 
int wal_retrieve_retry_interval = 5000
 
int max_slot_wal_keep_size_mb = -1
 
int wal_decode_buffer_size = 512 * 1024
 
bool track_wal_io_timing = false
 
int wal_segment_size = DEFAULT_XLOG_SEG_SIZE
 
int CheckPointSegments
 
static double CheckPointDistanceEstimate = 0
 
static double PrevCheckPointDistance = 0
 
const struct config_enum_entry sync_method_options []
 
const struct config_enum_entry archive_mode_options []
 
const struct config_enum_entry recovery_target_action_options []
 
CheckpointStatsData CheckpointStats
 
TimeLineID ThisTimeLineID = 0
 
bool InRecovery = false
 
HotStandbyState standbyState = STANDBY_DISABLED
 
static XLogRecPtr LastRec
 
static XLogRecPtr flushedUpto = 0
 
static TimeLineID receiveTLI = 0
 
static bool lastFullPageWrites
 
static bool LocalRecoveryInProgress = true
 
static bool LocalHotStandbyActive = false
 
static bool LocalPromoteIsTriggered = false
 
static int LocalXLogInsertAllowed = -1
 
bool ArchiveRecoveryRequested = false
 
bool InArchiveRecovery = false
 
static bool standby_signal_file_found = false
 
static bool recovery_signal_file_found = false
 
static bool restoredFromArchive = false
 
static char * replay_image_masked = NULL
 
static char * primary_image_masked = NULL
 
char * recoveryRestoreCommand = NULL
 
char * recoveryEndCommand = NULL
 
char * archiveCleanupCommand = NULL
 
RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET
 
bool recoveryTargetInclusive = true
 
int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE
 
TransactionId recoveryTargetXid
 
char * recovery_target_time_string
 
static TimestampTz recoveryTargetTime
 
const char * recoveryTargetName
 
XLogRecPtr recoveryTargetLSN
 
int recovery_min_apply_delay = 0
 
bool StandbyModeRequested = false
 
char * PrimaryConnInfo = NULL
 
char * PrimarySlotName = NULL
 
char * PromoteTriggerFile = NULL
 
bool wal_receiver_create_temp_slot = false
 
bool StandbyMode = false
 
static TransactionId recoveryStopXid
 
static TimestampTz recoveryStopTime
 
static XLogRecPtr recoveryStopLSN
 
static char recoveryStopName [MAXFNAMELEN]
 
static bool recoveryStopAfter
 
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal = RECOVERY_TARGET_TIMELINE_LATEST
 
TimeLineID recoveryTargetTLIRequested = 0
 
TimeLineID recoveryTargetTLI = 0
 
static ListexpectedTLEs
 
static TimeLineID curFileTLI
 
XLogRecPtr ProcLastRecPtr = InvalidXLogRecPtr
 
XLogRecPtr XactLastRecEnd = InvalidXLogRecPtr
 
XLogRecPtr XactLastCommitEnd = InvalidXLogRecPtr
 
static XLogRecPtr RedoRecPtr
 
static bool doPageWrites
 
static bool doRequestWalReceiverReply
 
static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr
 
static SessionBackupState sessionBackupState = SESSION_BACKUP_NONE
 
static XLogCtlDataXLogCtl = NULL
 
static WALInsertLockPaddedWALInsertLocks = NULL
 
static ControlFileDataControlFile = NULL
 
static int UsableBytesInSegment
 
static XLogwrtResult LogwrtResult = {0, 0}
 
static const char *const xlogSourceNames [] = {"any", "archive", "pg_wal", "stream"}
 
static int openLogFile = -1
 
static XLogSegNo openLogSegNo = 0
 
static int readFile = -1
 
static XLogSource readSource = XLOG_FROM_ANY
 
static XLogSource currentSource = XLOG_FROM_ANY
 
static bool lastSourceFailed = false
 
static bool pendingWalRcvRestart = false
 
static TimestampTz XLogReceiptTime = 0
 
static XLogSource XLogReceiptSource = XLOG_FROM_ANY
 
static XLogRecPtr ReadRecPtr
 
static XLogRecPtr EndRecPtr
 
static XLogRecPtr minRecoveryPoint
 
static TimeLineID minRecoveryPointTLI
 
static bool updateMinRecoveryPoint = true
 
bool reachedConsistency = false
 
static bool InRedo = false
 
static bool bgwriterLaunched = false
 
static int MyLockNo = 0
 
static bool holdingAllLocks = false
 

Macro Definition Documentation

◆ ConvertToXSegs

#define ConvertToXSegs (   x,
  segsize 
)    XLogMBVarToSegs((x), (segsize))

◆ INSERT_FREESPACE

#define INSERT_FREESPACE (   endptr)    (((endptr) % XLOG_BLCKSZ == 0) ? 0 : (XLOG_BLCKSZ - (endptr) % XLOG_BLCKSZ))

Definition at line 754 of file xlog.c.

Referenced by CopyXLogRecordToWAL(), and CreateCheckPoint().

◆ NextBufIdx

#define NextBufIdx (   idx)    (((idx) == XLogCtl->XLogCacheBlck) ? 0 : ((idx) + 1))

Definition at line 758 of file xlog.c.

Referenced by XLogWrite().

◆ NUM_XLOGINSERT_LOCKS

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 89 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 88 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ UsableBytesInPage

#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)

◆ XLogRecPtrToBufIdx

#define XLogRecPtrToBufIdx (   recptr)    (((recptr) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))

Definition at line 765 of file xlog.c.

Referenced by AdvanceXLInsertBuffer(), GetXLogBuffer(), StartupXLOG(), and XLogWrite().

Typedef Documentation

◆ ExclusiveBackupState

◆ WALInsertLockPadded

◆ XLogCtlData

typedef struct XLogCtlData XLogCtlData

◆ XLogCtlInsert

typedef struct XLogCtlInsert XLogCtlInsert

◆ XLogwrtResult

typedef struct XLogwrtResult XLogwrtResult

◆ XLogwrtRqst

typedef struct XLogwrtRqst XLogwrtRqst

Enumeration Type Documentation

◆ ExclusiveBackupState

Enumerator
EXCLUSIVE_BACKUP_NONE 
EXCLUSIVE_BACKUP_STARTING 
EXCLUSIVE_BACKUP_IN_PROGRESS 
EXCLUSIVE_BACKUP_STOPPING 

Definition at line 522 of file xlog.c.

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 792 of file xlog.c.

793 {
794  XLOG_FROM_ANY = 0, /* request to read WAL from any source */
795  XLOG_FROM_ARCHIVE, /* restored using restore_command */
796  XLOG_FROM_PG_WAL, /* existing file in pg_wal */
797  XLOG_FROM_STREAM /* streamed from primary */
798 } XLogSource;
XLogSource
Definition: xlog.c:792

Function Documentation

◆ AdvanceXLInsertBuffer()

static void AdvanceXLInsertBuffer ( XLogRecPtr  upto,
bool  opportunistic 
)
static

Definition at line 2140 of file xlog.c.

References Assert, DEBUG1, elog, XLogwrtRqst::Flush, XLogCtlInsert::forcePageWrites, XLogCtlData::info_lck, XLogCtlData::InitializedUpTo, Insert(), XLogCtlData::Insert, InvalidXLogRecPtr, XLogCtlData::LogwrtResult, XLogCtlData::LogwrtRqst, LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PgStat_MsgWal::m_wal_buffers_full, MemSet, XLogCtlData::pages, pg_write_barrier, SpinLockAcquire, SpinLockRelease, ControlFileData::system_identifier, ThisTimeLineID, WaitXLogInsertionsToFinish(), wal_segment_size, WalStats, XLogwrtRqst::Write, XLogwrtResult::Write, XLogCtlData::xlblocks, XLOG_PAGE_MAGIC, XLogRecPtrToBufIdx, XLogSegmentOffset, XLogWrite(), XLP_BKP_REMOVABLE, XLP_LONG_HEADER, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, and XLogLongPageHeaderData::xlp_xlog_blcksz.

Referenced by GetXLogBuffer(), and XLogBackgroundFlush().

2141 {
2143  int nextidx;
2144  XLogRecPtr OldPageRqstPtr;
2145  XLogwrtRqst WriteRqst;
2146  XLogRecPtr NewPageEndPtr = InvalidXLogRecPtr;
2147  XLogRecPtr NewPageBeginPtr;
2148  XLogPageHeader NewPage;
2149  int npages = 0;
2150 
2151  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2152 
2153  /*
2154  * Now that we have the lock, check if someone initialized the page
2155  * already.
2156  */
2157  while (upto >= XLogCtl->InitializedUpTo || opportunistic)
2158  {
2160 
2161  /*
2162  * Get ending-offset of the buffer page we need to replace (this may
2163  * be zero if the buffer hasn't been used yet). Fall through if it's
2164  * already written out.
2165  */
2166  OldPageRqstPtr = XLogCtl->xlblocks[nextidx];
2167  if (LogwrtResult.Write < OldPageRqstPtr)
2168  {
2169  /*
2170  * Nope, got work to do. If we just want to pre-initialize as much
2171  * as we can without flushing, give up now.
2172  */
2173  if (opportunistic)
2174  break;
2175 
2176  /* Before waiting, get info_lck and update LogwrtResult */
2178  if (XLogCtl->LogwrtRqst.Write < OldPageRqstPtr)
2179  XLogCtl->LogwrtRqst.Write = OldPageRqstPtr;
2182 
2183  /*
2184  * Now that we have an up-to-date LogwrtResult value, see if we
2185  * still need to write it or if someone else already did.
2186  */
2187  if (LogwrtResult.Write < OldPageRqstPtr)
2188  {
2189  /*
2190  * Must acquire write lock. Release WALBufMappingLock first,
2191  * to make sure that all insertions that we need to wait for
2192  * can finish (up to this same position). Otherwise we risk
2193  * deadlock.
2194  */
2195  LWLockRelease(WALBufMappingLock);
2196 
2197  WaitXLogInsertionsToFinish(OldPageRqstPtr);
2198 
2199  LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
2200 
2202  if (LogwrtResult.Write >= OldPageRqstPtr)
2203  {
2204  /* OK, someone wrote it already */
2205  LWLockRelease(WALWriteLock);
2206  }
2207  else
2208  {
2209  /* Have to write it ourselves */
2210  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
2211  WriteRqst.Write = OldPageRqstPtr;
2212  WriteRqst.Flush = 0;
2213  XLogWrite(WriteRqst, false);
2214  LWLockRelease(WALWriteLock);
2216  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
2217  }
2218  /* Re-acquire WALBufMappingLock and retry */
2219  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2220  continue;
2221  }
2222  }
2223 
2224  /*
2225  * Now the next buffer slot is free and we can set it up to be the
2226  * next output page.
2227  */
2228  NewPageBeginPtr = XLogCtl->InitializedUpTo;
2229  NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
2230 
2231  Assert(XLogRecPtrToBufIdx(NewPageBeginPtr) == nextidx);
2232 
2233  NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
2234 
2235  /*
2236  * Be sure to re-zero the buffer so that bytes beyond what we've
2237  * written will look like zeroes and not valid XLOG records...
2238  */
2239  MemSet((char *) NewPage, 0, XLOG_BLCKSZ);
2240 
2241  /*
2242  * Fill the new page's header
2243  */
2244  NewPage->xlp_magic = XLOG_PAGE_MAGIC;
2245 
2246  /* NewPage->xlp_info = 0; */ /* done by memset */
2247  NewPage->xlp_tli = ThisTimeLineID;
2248  NewPage->xlp_pageaddr = NewPageBeginPtr;
2249 
2250  /* NewPage->xlp_rem_len = 0; */ /* done by memset */
2251 
2252  /*
2253  * If online backup is not in progress, mark the header to indicate
2254  * that WAL records beginning in this page have removable backup
2255  * blocks. This allows the WAL archiver to know whether it is safe to
2256  * compress archived WAL data by transforming full-block records into
2257  * the non-full-block format. It is sufficient to record this at the
2258  * page level because we force a page switch (in fact a segment
2259  * switch) when starting a backup, so the flag will be off before any
2260  * records can be written during the backup. At the end of a backup,
2261  * the last page will be marked as all unsafe when perhaps only part
2262  * is unsafe, but at worst the archiver would miss the opportunity to
2263  * compress a few records.
2264  */
2265  if (!Insert->forcePageWrites)
2266  NewPage->xlp_info |= XLP_BKP_REMOVABLE;
2267 
2268  /*
2269  * If first page of an XLOG segment file, make it a long header.
2270  */
2271  if ((XLogSegmentOffset(NewPage->xlp_pageaddr, wal_segment_size)) == 0)
2272  {
2273  XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
2274 
2275  NewLongPage->xlp_sysid = ControlFile->system_identifier;
2276  NewLongPage->xlp_seg_size = wal_segment_size;
2277  NewLongPage->xlp_xlog_blcksz = XLOG_BLCKSZ;
2278  NewPage->xlp_info |= XLP_LONG_HEADER;
2279  }
2280 
2281  /*
2282  * Make sure the initialization of the page becomes visible to others
2283  * before the xlblocks update. GetXLogBuffer() reads xlblocks without
2284  * holding a lock.
2285  */
2286  pg_write_barrier();
2287 
2288  *((volatile XLogRecPtr *) &XLogCtl->xlblocks[nextidx]) = NewPageEndPtr;
2289 
2290  XLogCtl->InitializedUpTo = NewPageEndPtr;
2291 
2292  npages++;
2293  }
2294  LWLockRelease(WALBufMappingLock);
2295 
2296 #ifdef WAL_DEBUG
2297  if (XLOG_DEBUG && npages > 0)
2298  {
2299  elog(DEBUG1, "initialized %d pages, up to %X/%X",
2300  npages, LSN_FORMAT_ARGS(NewPageEndPtr));
2301  }
2302 #endif
2303 }
XLogRecPtr InitializedUpTo
Definition: xlog.c:635
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
int wal_segment_size
Definition: xlog.c:121
XLogRecPtr * xlblocks
Definition: xlog.c:643
static XLogwrtResult LogwrtResult
Definition: xlog.c:786
slock_t info_lck
Definition: xlog.c:737
#define MemSet(start, val, len)
Definition: c.h:1008
static XLogRecPtr WaitXLogInsertionsToFinish(XLogRecPtr upto)
Definition: xlog.c:1803
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
XLogCtlInsert Insert
Definition: xlog.c:600
XLogRecPtr Flush
Definition: xlog.c:442
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLP_BKP_REMOVABLE
Definition: xlog_internal.h:78
bool forcePageWrites
Definition: xlog.c:574
uint64 system_identifier
Definition: pg_control.h:106
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
XLogwrtResult LogwrtResult
Definition: xlog.c:623
static void Insert(File file)
Definition: fd.c:1222
PgStat_Counter m_wal_buffers_full
Definition: pgstat.h:509
TimeLineID xlp_tli
Definition: xlog_internal.h:40
static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
Definition: xlog.c:2431
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SpinLockRelease(lock)
Definition: spin.h:64
XLogRecPtr Write
Definition: xlog.c:441
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
PgStat_MsgWal WalStats
Definition: pgstat.c:132
static ControlFileData * ControlFile
Definition: xlog.c:748
XLogwrtRqst LogwrtRqst
Definition: xlog.c:603
TimeLineID ThisTimeLineID
Definition: xlog.c:196
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
size_t Size
Definition: c.h:540
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:765
XLogRecPtr Write
Definition: xlog.c:447
#define elog(elevel,...)
Definition: elog.h:232
#define pg_write_barrier()
Definition: atomics.h:159
char * pages
Definition: xlog.c:642

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 2346 of file xlog.c.

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

2347 {
2350 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2310
#define newval
double CheckPointCompletionTarget
Definition: checkpointer.c:148

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 2339 of file xlog.c.

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

2340 {
2343 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2310
int max_wal_size_mb
Definition: xlog.c:92
#define newval

◆ assign_xlog_sync_method()

void assign_xlog_sync_method ( int  new_sync_method,
void *  extra 
)

Definition at line 10587 of file xlog.c.

References ereport, errcode_for_file_access(), errmsg(), get_sync_bit(), MAXFNAMELEN, openLogFile, openLogSegNo, PANIC, pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), sync_method, ThisTimeLineID, WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN, wal_segment_size, XLogFileClose(), and XLogFileName.

10588 {
10589  if (sync_method != new_sync_method)
10590  {
10591  /*
10592  * To ensure that no blocks escape unsynced, force an fsync on the
10593  * currently open log segment (if any). Also, if the open flag is
10594  * changing, close the log file so it will be reopened (with new flag
10595  * bit) at next use.
10596  */
10597  if (openLogFile >= 0)
10598  {
10600  if (pg_fsync(openLogFile) != 0)
10601  {
10602  char xlogfname[MAXFNAMELEN];
10603  int save_errno;
10604 
10605  save_errno = errno;
10608  errno = save_errno;
10609  ereport(PANIC,
10611  errmsg("could not fsync file \"%s\": %m", xlogfname)));
10612  }
10613 
10615  if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
10616  XLogFileClose();
10617  }
10618  }
10619 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:277
int wal_segment_size
Definition: xlog.c:121
static int get_sync_bit(int method)
Definition: xlog.c:10531
#define PANIC
Definition: elog.h:50
static XLogSegNo openLogSegNo
Definition: xlog.c:810
static void XLogFileClose(void)
Definition: xlog.c:3901
int errcode_for_file_access(void)
Definition: elog.c:721
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:261
#define MAXFNAMELEN
static int openLogFile
Definition: xlog.c:809
TimeLineID ThisTimeLineID
Definition: xlog.c:196
#define ereport(elevel,...)
Definition: elog.h:157
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
int sync_method
Definition: xlog.c:108
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pg_fsync(int fd)
Definition: fd.c:352

◆ BackupInProgress()

bool BackupInProgress ( void  )

Definition at line 12039 of file xlog.c.

References BACKUP_LABEL_FILE, and stat.

Referenced by pg_is_in_backup(), and PostmasterStateMachine().

12040 {
12041  struct stat stat_buf;
12042 
12043  return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
12044 }
#define BACKUP_LABEL_FILE
Definition: xlog.h:398
#define stat
Definition: win32_port.h:275

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 5249 of file xlog.c.

References AdvanceOldestClogXid(), Assert, BootStrapCLOG(), BootStrapCommitTs(), BootStrapMultiXact(), BootStrapSUBTRANS(), ControlFileData::checkPoint, ControlFileData::checkPointCopy, close, COMP_CRC32C, ereport, errcode_for_file_access(), errmsg(), FIN_CRC32C, FirstBootstrapObjectId, FirstMultiXactId, FirstNormalTransactionId, CheckPoint::fullPageWrites, fullPageWrites, FullTransactionIdFromEpochAndXid(), gettimeofday(), INIT_CRC32C, InitControlFile(), InvalidTransactionId, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, CheckPoint::nextXid, VariableCacheData::nextXid, offsetof, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, palloc(), PANIC, pfree(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), CheckPoint::PrevTimeLineID, ReadControlFile(), CheckPoint::redo, SetCommitTsLimit(), SetMultiXactIdLimit(), SetTransactionIdLimit(), ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, CheckPoint::ThisTimeLineID, ThisTimeLineID, CheckPoint::time, ControlFileData::time, TYPEALIGN, WAIT_EVENT_WAL_BOOTSTRAP_SYNC, WAIT_EVENT_WAL_BOOTSTRAP_WRITE, wal_segment_size, write, WriteControlFile(), 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 AuxiliaryProcessMain().

5250 {
5251  CheckPoint checkPoint;
5252  char *buffer;
5253  XLogPageHeader page;
5254  XLogLongPageHeader longpage;
5255  XLogRecord *record;
5256  char *recptr;
5257  bool use_existent;
5258  uint64 sysidentifier;
5259  struct timeval tv;
5260  pg_crc32c crc;
5261 
5262  /*
5263  * Select a hopefully-unique system identifier code for this installation.
5264  * We use the result of gettimeofday(), including the fractional seconds
5265  * field, as being about as unique as we can easily get. (Think not to
5266  * use random(), since it hasn't been seeded and there's no portable way
5267  * to seed it other than the system clock value...) The upper half of the
5268  * uint64 value is just the tv_sec part, while the lower half contains the
5269  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
5270  * PID for a little extra uniqueness. A person knowing this encoding can
5271  * determine the initialization time of the installation, which could
5272  * perhaps be useful sometimes.
5273  */
5274  gettimeofday(&tv, NULL);
5275  sysidentifier = ((uint64) tv.tv_sec) << 32;
5276  sysidentifier |= ((uint64) tv.tv_usec) << 12;
5277  sysidentifier |= getpid() & 0xFFF;
5278 
5279  /* First timeline ID is always 1 */
5280  ThisTimeLineID = 1;
5281 
5282  /* page buffer must be aligned suitably for O_DIRECT */
5283  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
5284  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
5285  memset(page, 0, XLOG_BLCKSZ);
5286 
5287  /*
5288  * Set up information for the initial checkpoint record
5289  *
5290  * The initial checkpoint record is written to the beginning of the WAL
5291  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
5292  * used, so that we can use 0/0 to mean "before any valid WAL segment".
5293  */
5294  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
5295  checkPoint.ThisTimeLineID = ThisTimeLineID;
5296  checkPoint.PrevTimeLineID = ThisTimeLineID;
5297  checkPoint.fullPageWrites = fullPageWrites;
5298  checkPoint.nextXid =
5300  checkPoint.nextOid = FirstBootstrapObjectId;
5301  checkPoint.nextMulti = FirstMultiXactId;
5302  checkPoint.nextMultiOffset = 0;
5303  checkPoint.oldestXid = FirstNormalTransactionId;
5304  checkPoint.oldestXidDB = TemplateDbOid;
5305  checkPoint.oldestMulti = FirstMultiXactId;
5306  checkPoint.oldestMultiDB = TemplateDbOid;
5309  checkPoint.time = (pg_time_t) time(NULL);
5311 
5312  ShmemVariableCache->nextXid = checkPoint.nextXid;
5313  ShmemVariableCache->nextOid = checkPoint.nextOid;
5315  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5316  AdvanceOldestClogXid(checkPoint.oldestXid);
5317  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5318  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5320 
5321  /* Set up the XLOG page header */
5322  page->xlp_magic = XLOG_PAGE_MAGIC;
5323  page->xlp_info = XLP_LONG_HEADER;
5324  page->xlp_tli = ThisTimeLineID;
5326  longpage = (XLogLongPageHeader) page;
5327  longpage->xlp_sysid = sysidentifier;
5328  longpage->xlp_seg_size = wal_segment_size;
5329  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
5330 
5331  /* Insert the initial checkpoint record */
5332  recptr = ((char *) page + SizeOfXLogLongPHD);
5333  record = (XLogRecord *) recptr;
5334  record->xl_prev = 0;
5335  record->xl_xid = InvalidTransactionId;
5336  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
5338  record->xl_rmid = RM_XLOG_ID;
5339  recptr += SizeOfXLogRecord;
5340  /* fill the XLogRecordDataHeaderShort struct */
5341  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
5342  *(recptr++) = sizeof(checkPoint);
5343  memcpy(recptr, &checkPoint, sizeof(checkPoint));
5344  recptr += sizeof(checkPoint);
5345  Assert(recptr - (char *) record == record->xl_tot_len);
5346 
5347  INIT_CRC32C(crc);
5348  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
5349  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
5350  FIN_CRC32C(crc);
5351  record->xl_crc = crc;
5352 
5353  /* Create first XLOG segment file */
5354  use_existent = false;
5355  openLogFile = XLogFileInit(1, &use_existent, false);
5356 
5357  /*
5358  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
5359  * close the file again in a moment.
5360  */
5361 
5362  /* Write the first page with the initial record */
5363  errno = 0;
5365  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
5366  {
5367  /* if write didn't set errno, assume problem is no disk space */
5368  if (errno == 0)
5369  errno = ENOSPC;
5370  ereport(PANIC,
5372  errmsg("could not write bootstrap write-ahead log file: %m")));
5373  }
5375 
5377  if (pg_fsync(openLogFile) != 0)
5378  ereport(PANIC,
5380  errmsg("could not fsync bootstrap write-ahead log file: %m")));
5382 
5383  if (close(openLogFile) != 0)
5384  ereport(PANIC,
5386  errmsg("could not close bootstrap write-ahead log file: %m")));
5387 
5388  openLogFile = -1;
5389 
5390  /* Now create pg_control */
5391  InitControlFile(sysidentifier);
5392  ControlFile->time = checkPoint.time;
5393  ControlFile->checkPoint = checkPoint.redo;
5394  ControlFile->checkPointCopy = checkPoint;
5395 
5396  /* some additional ControlFile fields are set in WriteControlFile() */
5397  WriteControlFile();
5398 
5399  /* Bootstrap the commit log, too */
5400  BootStrapCLOG();
5404 
5405  pfree(buffer);
5406 
5407  /*
5408  * Force control file to be read - in contrast to normal processing we'd
5409  * otherwise never run the checks and GUC related initializations therein.
5410  */
5411  ReadControlFile();
5412 }
static void WriteControlFile(void)
Definition: xlog.c:4665
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
int64 pg_time_t
Definition: pgtime.h:23
static void pgstat_report_wait_end(void)
Definition: wait_event.h:277
int wal_segment_size
Definition: xlog.c:121
pg_time_t time
Definition: pg_control.h:128
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:876
uint32 oidCount
Definition: transam.h:208
#define write(a, b, c)
Definition: win32.h:14
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:200
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:63
int XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
Definition: xlog.c:3288
void BootStrapMultiXact(void)
Definition: multixact.c:1891
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:4630
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
FullTransactionId nextXid
Definition: transam.h:213
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:50
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
bool fullPageWrites
Definition: xlog.c:100
void BootStrapSUBTRANS(void)
Definition: subtrans.c:211
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1169
#define FirstNormalTransactionId
Definition: transam.h:34
uint32 xl_tot_len
Definition: xlogrecord.h:43
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
static void ReadControlFile(void)
Definition: xlog.c:4756
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
int errcode_for_file_access(void)
Definition: elog.c:721
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
#define FirstBootstrapObjectId
Definition: transam.h:189
#define FirstMultiXactId
Definition: multixact.h:25
TimeLineID xlp_tli
Definition: xlog_internal.h:40
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:261
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
TransactionId newestCommitTsXid
Definition: pg_control.h:54
Oid oldestMultiDB
Definition: pg_control.h:50
static int openLogFile
Definition: xlog.c:809
static ControlFileData * ControlFile
Definition: xlog.c:748
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2210
TimeLineID ThisTimeLineID
Definition: xlog.c:196
Oid nextOid
Definition: pg_control.h:44
#define ereport(elevel,...)
Definition: elog.h:157
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:750
bool fullPageWrites
Definition: pg_control.h:42
void BootStrapCLOG(void)
Definition: clog.c:707
#define Assert(condition)
Definition: c.h:804
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
Oid oldestXidDB
Definition: pg_control.h:48
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:345
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:45
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:223
TransactionId xl_xid
Definition: xlogrecord.h:44
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pg_fsync(int fd)
Definition: fd.c:352
#define close(a)
Definition: win32.h:12
void BootStrapCommitTs(void)
Definition: commit_ts.c:569
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
#define offsetof(type, field)
Definition: c.h:727
FullTransactionId nextXid
Definition: pg_control.h:43
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2176

◆ CalculateCheckpointSegments()

static void CalculateCheckpointSegments ( void  )
static

Definition at line 2310 of file xlog.c.

References CheckPointCompletionTarget, CheckPointSegments, ConvertToXSegs, max_wal_size_mb, and wal_segment_size.

Referenced by assign_checkpoint_completion_target(), assign_max_wal_size(), and ReadControlFile().

2311 {
2312  double target;
2313 
2314  /*-------
2315  * Calculate the distance at which to trigger a checkpoint, to avoid
2316  * exceeding max_wal_size_mb. This is based on two assumptions:
2317  *
2318  * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
2319  * WAL for two checkpoint cycles to allow us to recover from the
2320  * secondary checkpoint if the first checkpoint failed, though we
2321  * only did this on the primary anyway, not on standby. Keeping just
2322  * one checkpoint simplifies processing and reduces disk space in
2323  * many smaller databases.)
2324  * b) during checkpoint, we consume checkpoint_completion_target *
2325  * number of segments consumed between checkpoints.
2326  *-------
2327  */
2328  target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
2330 
2331  /* round down */
2332  CheckPointSegments = (int) target;
2333 
2334  if (CheckPointSegments < 1)
2335  CheckPointSegments = 1;
2336 }
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:777
int wal_segment_size
Definition: xlog.c:121
int max_wal_size_mb
Definition: xlog.c:92
int CheckPointSegments
Definition: xlog.c:134
double CheckPointCompletionTarget
Definition: checkpointer.c:148

◆ CancelBackup()

void CancelBackup ( void  )

Definition at line 12059 of file xlog.c.

References BACKUP_LABEL_FILE, BACKUP_LABEL_OLD, DEBUG1, durable_rename(), ereport, errcode_for_file_access(), errdetail(), errmsg(), LOG, stat, TABLESPACE_MAP, TABLESPACE_MAP_OLD, and WARNING.

Referenced by PostmasterStateMachine().

12060 {
12061  struct stat stat_buf;
12062 
12063  /* if the backup_label file is not there, return */
12064  if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
12065  return;
12066 
12067  /* remove leftover file from previously canceled backup if it exists */
12068  unlink(BACKUP_LABEL_OLD);
12069 
12071  {
12072  ereport(WARNING,
12074  errmsg("online backup mode was not canceled"),
12075  errdetail("File \"%s\" could not be renamed to \"%s\": %m.",
12077  return;
12078  }
12079 
12080  /* if the tablespace_map file is not there, return */
12081  if (stat(TABLESPACE_MAP, &stat_buf) < 0)
12082  {
12083  ereport(LOG,
12084  (errmsg("online backup mode canceled"),
12085  errdetail("File \"%s\" was renamed to \"%s\".",
12087  return;
12088  }
12089 
12090  /* remove leftover file from previously canceled backup if it exists */
12091  unlink(TABLESPACE_MAP_OLD);
12092 
12094  {
12095  ereport(LOG,
12096  (errmsg("online backup mode canceled"),
12097  errdetail("Files \"%s\" and \"%s\" were renamed to "
12098  "\"%s\" and \"%s\", respectively.",
12101  }
12102  else
12103  {
12104  ereport(WARNING,
12106  errmsg("online backup mode canceled"),
12107  errdetail("File \"%s\" was renamed to \"%s\", but "
12108  "file \"%s\" could not be renamed to \"%s\": %m.",
12111  }
12112 }
#define DEBUG1
Definition: elog.h:25
#define LOG
Definition: elog.h:26
#define BACKUP_LABEL_OLD
Definition: xlog.h:399
#define TABLESPACE_MAP
Definition: xlog.h:401
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int errcode_for_file_access(void)
Definition: elog.c:721
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:692
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
#define TABLESPACE_MAP_OLD
Definition: xlog.h:402
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define BACKUP_LABEL_FILE
Definition: xlog.h:398
#define stat
Definition: win32_port.h:275

◆ check_wal_buffers()

bool check_wal_buffers ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 5041 of file xlog.c.

References XLOGbuffers, and XLOGChooseNumBuffers().

5042 {
5043  /*
5044  * -1 indicates a request for auto-tune.
5045  */
5046  if (*newval == -1)
5047  {
5048  /*
5049  * If we haven't yet changed the boot_val default of -1, just let it
5050  * be. We'll fix it when XLOGShmemSize is called.
5051  */
5052  if (XLOGbuffers == -1)
5053  return true;
5054 
5055  /* Otherwise, substitute the auto-tune value */
5057  }
5058 
5059  /*
5060  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
5061  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
5062  * the case, we just silently treat such values as a request for the
5063  * minimum. (We could throw an error instead, but that doesn't seem very
5064  * helpful.)
5065  */
5066  if (*newval < 4)
5067  *newval = 4;
5068 
5069  return true;
5070 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:5025
#define newval
int XLOGbuffers
Definition: xlog.c:95

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 12871 of file xlog.c.

References CheckPromoteSignal(), ereport, errcode_for_file_access(), errmsg(), ERROR, IsPromoteSignaled(), LocalPromoteIsTriggered, LOG, PromoteTriggerFile, RemovePromoteSignalFiles(), ResetPromoteSignaled(), SetPromoteIsTriggered(), and stat.

Referenced by ReadRecord(), recoveryApplyDelay(), recoveryPausesHere(), RecoveryRequiresIntParameter(), and WaitForWALToBecomeAvailable().

12872 {
12873  struct stat stat_buf;
12874 
12876  return true;
12877 
12879  {
12880  ereport(LOG, (errmsg("received promote request")));
12884  return true;
12885  }
12886 
12887  if (PromoteTriggerFile == NULL || strcmp(PromoteTriggerFile, "") == 0)
12888  return false;
12889 
12890  if (stat(PromoteTriggerFile, &stat_buf) == 0)
12891  {
12892  ereport(LOG,
12893  (errmsg("promote trigger file found: %s", PromoteTriggerFile)));
12894  unlink(PromoteTriggerFile);
12896  return true;
12897  }
12898  else if (errno != ENOENT)
12899  ereport(ERROR,
12901  errmsg("could not stat promote trigger file \"%s\": %m",
12902  PromoteTriggerFile)));
12903 
12904  return false;
12905 }
char * PromoteTriggerFile
Definition: xlog.c:301
bool CheckPromoteSignal(void)
Definition: xlog.c:12920
bool IsPromoteSignaled(void)
Definition: startup.c:274
static bool LocalPromoteIsTriggered
Definition: xlog.c:245
#define LOG
Definition: elog.h:26
static void SetPromoteIsTriggered(void)
Definition: xlog.c:12857
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
void RemovePromoteSignalFiles(void)
Definition: xlog.c:12911
#define ereport(elevel,...)
Definition: elog.h:157
void ResetPromoteSignaled(void)
Definition: startup.c:280
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define stat
Definition: win32_port.h:275

◆ CheckPointGuts()

static void CheckPointGuts ( XLogRecPtr  checkPointRedo,
int  flags 
)
static

Definition at line 9384 of file xlog.c.

References CheckPointBuffers(), CheckPointCLOG(), CheckPointCommitTs(), CheckPointLogicalRewriteHeap(), CheckPointMultiXact(), CheckPointPredicate(), CheckPointRelationMap(), CheckPointReplicationOrigin(), CheckPointReplicationSlots(), CheckPointSnapBuild(), CheckPointSUBTRANS(), CheckPointTwoPhase(), CheckpointStatsData::ckpt_sync_end_t, CheckpointStatsData::ckpt_sync_t, CheckpointStatsData::ckpt_write_t, GetCurrentTimestamp(), and ProcessSyncRequests().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

9385 {
9391 
9392  /* Write out all dirty data in SLRUs and the main buffer pool */
9393  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
9395  CheckPointCLOG();
9400  CheckPointBuffers(flags);
9401 
9402  /* Perform all queued up fsyncs */
9403  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
9407  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
9408 
9409  /* We deliberately delay 2PC checkpointing as long as possible */
9410  CheckPointTwoPhase(checkPointRedo);
9411 }
void ProcessSyncRequests(void)
Definition: sync.c:257
void CheckPointBuffers(int flags)
Definition: bufmgr.c:2734
TimestampTz ckpt_sync_end_t
Definition: xlog.h:259
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1199
void CheckPointReplicationOrigin(void)
Definition: origin.c:557
void CheckPointSnapBuild(void)
Definition: snapbuild.c:1898
void CheckPointCLOG(void)
Definition: clog.c:813
void CheckPointMultiXact(void)
Definition: multixact.c:2152
void CheckPointCommitTs(void)
Definition: commit_ts.c:790
CheckpointStatsData CheckpointStats
Definition: xlog.c:190
TimestampTz ckpt_write_t
Definition: xlog.h:257
void CheckPointSUBTRANS(void)
Definition: subtrans.c:284
void CheckPointRelationMap(void)
Definition: relmapper.c:546
TimestampTz ckpt_sync_t
Definition: xlog.h:258
void CheckPointPredicate(void)
Definition: predicate.c:1069
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1705
void CheckPointReplicationSlots(void)
Definition: slot.c:1283

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 12920 of file xlog.c.

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and sigusr1_handler().

12921 {
12922  struct stat stat_buf;
12923 
12924  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12925  return true;
12926 
12927  return false;
12928 }
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:405
#define stat
Definition: win32_port.h:275

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 8137 of file xlog.c.

References Assert, ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, DEBUG1, elog, ereport, errmsg(), InArchiveRecovery, XLogCtlData::info_lck, InvalidXLogRecPtr, IsUnderPostmaster, XLogCtlData::lastReplayedEndRecPtr, LocalHotStandbyActive, LOG, LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, minRecoveryPoint, PMSIGNAL_BEGIN_HOT_STANDBY, reachedConsistency, SendPostmasterSignal(), XLogCtlData::SharedHotStandbyActive, SpinLockAcquire, SpinLockRelease, STANDBY_SNAPSHOT_READY, standbyState, UpdateControlFile(), XLogCheckInvalidPages(), and XLogRecPtrIsInvalid.

Referenced by ReadRecord(), and StartupXLOG().

8138 {
8139  XLogRecPtr lastReplayedEndRecPtr;
8140 
8141  /*
8142  * During crash recovery, we don't reach a consistent state until we've
8143  * replayed all the WAL.
8144  */
8146  return;
8147 
8149 
8150  /*
8151  * assume that we are called in the startup process, and hence don't need
8152  * a lock to read lastReplayedEndRecPtr
8153  */
8154  lastReplayedEndRecPtr = XLogCtl->lastReplayedEndRecPtr;
8155 
8156  /*
8157  * Have we reached the point where our base backup was completed?
8158  */
8160  ControlFile->backupEndPoint <= lastReplayedEndRecPtr)
8161  {
8162  /*
8163  * We have reached the end of base backup, as indicated by pg_control.
8164  * The data on disk is now consistent. Reset backupStartPoint and
8165  * backupEndPoint, and update minRecoveryPoint to make sure we don't
8166  * allow starting up at an earlier point even if recovery is stopped
8167  * and restarted soon after this.
8168  */
8169  elog(DEBUG1, "end of backup reached");
8170 
8171  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8172 
8173  if (ControlFile->minRecoveryPoint < lastReplayedEndRecPtr)
8174  ControlFile->minRecoveryPoint = lastReplayedEndRecPtr;
8175 
8178  ControlFile->backupEndRequired = false;
8180 
8181  LWLockRelease(ControlFileLock);
8182  }
8183 
8184  /*
8185  * Have we passed our safe starting point? Note that minRecoveryPoint is
8186  * known to be incorrectly set if ControlFile->backupEndRequired, until
8187  * the XLOG_BACKUP_END arrives to advise us of the correct
8188  * minRecoveryPoint. All we know prior to that is that we're not
8189  * consistent yet.
8190  */
8192  minRecoveryPoint <= lastReplayedEndRecPtr &&
8194  {
8195  /*
8196  * Check to see if the XLOG sequence contained any unresolved
8197  * references to uninitialized pages.
8198  */
8200 
8201  reachedConsistency = true;
8202  ereport(LOG,
8203  (errmsg("consistent recovery state reached at %X/%X",
8204  LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
8205  }
8206 
8207  /*
8208  * Have we got a valid starting snapshot that will allow queries to be
8209  * run? If so, we can tell postmaster that the database is consistent now,
8210  * enabling connections.
8211  */
8216  {
8220 
8221  LocalHotStandbyActive = true;
8222 
8224  }
8225 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:223
bool SharedHotStandbyActive
Definition: xlog.c:665
slock_t info_lck
Definition: xlog.c:737
#define LOG
Definition: elog.h:26
bool InArchiveRecovery
Definition: xlog.c:271
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
bool backupEndRequired
Definition: pg_control.h:170
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
static bool LocalHotStandbyActive
Definition: xlog.c:239
void UpdateControlFile(void)
Definition: xlog.c:4956
bool IsUnderPostmaster
Definition: globals.c:112
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static ControlFileData * ControlFile
Definition: xlog.c:748
#define ereport(elevel,...)
Definition: elog.h:157
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
bool reachedConsistency
Definition: xlog.c:870
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:153
HotStandbyState standbyState
Definition: xlog.c:212
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:861
XLogRecPtr lastReplayedEndRecPtr
Definition: xlog.c:715

◆ CheckRequiredParameterValues()

static void CheckRequiredParameterValues ( void  )
static

Definition at line 6407 of file xlog.c.

References ArchiveRecoveryRequested, EnableHotStandby, ereport, errdetail(), errhint(), errmsg(), FATAL, max_locks_per_xact, ControlFileData::max_locks_per_xact, max_prepared_xacts, ControlFileData::max_prepared_xacts, max_wal_senders, ControlFileData::max_wal_senders, max_worker_processes, ControlFileData::max_worker_processes, MaxConnections, ControlFileData::MaxConnections, RecoveryRequiresIntParameter(), ControlFileData::wal_level, and WAL_LEVEL_MINIMAL.

Referenced by StartupXLOG(), and xlog_redo().

6408 {
6409  /*
6410  * For archive recovery, the WAL must be generated with at least 'replica'
6411  * wal_level.
6412  */
6414  {
6415  ereport(FATAL,
6416  (errmsg("WAL was generated with wal_level=minimal, cannot continue recovering"),
6417  errdetail("This happens if you temporarily set wal_level=minimal on the server."),
6418  errhint("Use a backup taken after setting wal_level to higher than minimal.")));
6419  }
6420 
6421  /*
6422  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
6423  * must have at least as many backend slots as the primary.
6424  */
6426  {
6427  /* We ignore autovacuum_max_workers when we make this test. */
6428  RecoveryRequiresIntParameter("max_connections",
6431  RecoveryRequiresIntParameter("max_worker_processes",
6434  RecoveryRequiresIntParameter("max_wal_senders",
6437  RecoveryRequiresIntParameter("max_prepared_transactions",
6440  RecoveryRequiresIntParameter("max_locks_per_transaction",
6443  }
6444 }
bool ArchiveRecoveryRequested
Definition: xlog.c:270
int max_locks_per_xact
Definition: pg_control.h:182
int errhint(const char *fmt,...)
Definition: elog.c:1156
int max_prepared_xacts
Definition: pg_control.h:181
static void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue)
Definition: xlog.c:6326
int max_worker_processes
Definition: pg_control.h:179
int max_prepared_xacts
Definition: twophase.c:117
#define FATAL
Definition: elog.h:49
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int max_locks_per_xact
Definition: lock.c:54
int max_wal_senders
Definition: walsender.c:121
int MaxConnections
Definition: globals.c:136
static ControlFileData * ControlFile
Definition: xlog.c:748
#define ereport(elevel,...)
Definition: elog.h:157
bool EnableHotStandby
Definition: xlog.c:99
int errmsg(const char *fmt,...)
Definition: elog.c:909
int max_worker_processes
Definition: globals.c:137

◆ checkTimeLineSwitch()

static void checkTimeLineSwitch ( XLogRecPtr  lsn,
TimeLineID  newTLI,
TimeLineID  prevTLI 
)
static

Definition at line 10068 of file xlog.c.

References ereport, errmsg(), LSN_FORMAT_ARGS, minRecoveryPoint, minRecoveryPointTLI, PANIC, ThisTimeLineID, tliInHistory(), and XLogRecPtrIsInvalid.

Referenced by StartupXLOG().

10069 {
10070  /* Check that the record agrees on what the current (old) timeline is */
10071  if (prevTLI != ThisTimeLineID)
10072  ereport(PANIC,
10073  (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
10074  prevTLI, ThisTimeLineID)));
10075 
10076  /*
10077  * The new timeline better be in the list of timelines we expect to see,
10078  * according to the timeline history. It should also not decrease.
10079  */
10080  if (newTLI < ThisTimeLineID || !tliInHistory(newTLI, expectedTLEs))
10081  ereport(PANIC,
10082  (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
10083  newTLI, ThisTimeLineID)));
10084 
10085  /*
10086  * If we have not yet reached min recovery point, and we're about to
10087  * switch to a timeline greater than the timeline of the min recovery
10088  * point: trouble. After switching to the new timeline, we could not
10089  * possibly visit the min recovery point on the correct timeline anymore.
10090  * This can happen if there is a newer timeline in the archive that
10091  * branched before the timeline the min recovery point is on, and you
10092  * attempt to do PITR to the new timeline.
10093  */
10095  lsn < minRecoveryPoint &&
10096  newTLI > minRecoveryPointTLI)
10097  ereport(PANIC,
10098  (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
10099  newTLI,
10102 
10103  /* Looks good */
10104 }
static List * expectedTLEs
Definition: xlog.c:346
#define PANIC
Definition: elog.h:50
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:862
TimeLineID ThisTimeLineID
Definition: xlog.c:196
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:534
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:861

◆ checkXLogConsistency()

static void checkXLogConsistency ( XLogReaderState record)
static

Definition at line 1422 of file xlog.c.

References Assert, buf, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, BufferIsValid, RelFileNode::dbNode, elog, XLogReaderState::EndRecPtr, ERROR, FATAL, InvalidBuffer, LockBuffer(), PageGetLSN, primary_image_masked, RBM_NORMAL_NO_LOG, RelFileNode::relNode, replay_image_masked, RestoreBlockImage(), RmgrData::rm_mask, RmgrTable, RelFileNode::spcNode, UnlockReleaseBuffer(), XLogReadBufferExtended(), XLogRecBlockImageApply, XLogRecGetBlockTag(), XLogRecGetInfo, XLogRecGetRmid, XLogRecHasAnyBlockRefs, XLogRecHasBlockImage, XLogRecMaxBlockId, and XLR_CHECK_CONSISTENCY.

Referenced by StartupXLOG().

1423 {
1424  RmgrId rmid = XLogRecGetRmid(record);
1425  RelFileNode rnode;
1426  ForkNumber forknum;
1427  BlockNumber blkno;
1428  int block_id;
1429 
1430  /* Records with no backup blocks have no need for consistency checks. */
1431  if (!XLogRecHasAnyBlockRefs(record))
1432  return;
1433 
1434  Assert((XLogRecGetInfo(record) & XLR_CHECK_CONSISTENCY) != 0);
1435 
1436  for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
1437  {
1438  Buffer buf;
1439  Page page;
1440 
1441  if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
1442  {
1443  /*
1444  * WAL record doesn't contain a block reference with the given id.
1445  * Do nothing.
1446  */
1447  continue;
1448  }
1449 
1450  Assert(XLogRecHasBlockImage(record, block_id));
1451 
1452  if (XLogRecBlockImageApply(record, block_id))
1453  {
1454  /*
1455  * WAL record has already applied the page, so bypass the
1456  * consistency check as that would result in comparing the full
1457  * page stored in the record with itself.
1458  */
1459  continue;
1460  }
1461 
1462  /*
1463  * Read the contents from the current buffer and store it in a
1464  * temporary page.
1465  */
1466  buf = XLogReadBufferExtended(rnode, forknum, blkno,
1468  if (!BufferIsValid(buf))
1469  continue;
1470 
1472  page = BufferGetPage(buf);
1473 
1474  /*
1475  * Take a copy of the local page where WAL has been applied to have a
1476  * comparison base before masking it...
1477  */
1478  memcpy(replay_image_masked, page, BLCKSZ);
1479 
1480  /* No need for this page anymore now that a copy is in. */
1481  UnlockReleaseBuffer(buf);
1482 
1483  /*
1484  * If the block LSN is already ahead of this WAL record, we can't
1485  * expect contents to match. This can happen if recovery is
1486  * restarted.
1487  */
1488  if (PageGetLSN(replay_image_masked) > record->EndRecPtr)
1489  continue;
1490 
1491  /*
1492  * Read the contents from the backup copy, stored in WAL record and
1493  * store it in a temporary page. There is no need to allocate a new
1494  * page here, a local buffer is fine to hold its contents and a mask
1495  * can be directly applied on it.
1496  */
1497  if (!RestoreBlockImage(record, block_id, primary_image_masked))
1498  elog(ERROR, "failed to restore block image");
1499 
1500  /*
1501  * If masking function is defined, mask both the primary and replay
1502  * images
1503  */
1504  if (RmgrTable[rmid].rm_mask != NULL)
1505  {
1506  RmgrTable[rmid].rm_mask(replay_image_masked, blkno);
1507  RmgrTable[rmid].rm_mask(primary_image_masked, blkno);
1508  }
1509 
1510  /* Time to compare the primary and replay images. */
1511  if (memcmp(replay_image_masked, primary_image_masked, BLCKSZ) != 0)
1512  {
1513  elog(FATAL,
1514  "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
1515  rnode.spcNode, rnode.dbNode, rnode.relNode,
1516  forknum, blkno);
1517  }
1518  }
1519 }
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:390
#define InvalidBuffer
Definition: buf.h:25
const RmgrData RmgrTable[RM_MAX_ID+1]
Definition: rmgr.c:36
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:80
XLogRecPtr EndRecPtr
Definition: xlogreader.h:179
static char * replay_image_masked
Definition: xlog.c:280
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)
Definition: xlogutils.c:443
#define ERROR
Definition: elog.h:46
#define FATAL
Definition: elog.h:49
static char * buf
Definition: pg_test_fsync.c:68
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:385
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:377
ForkNumber
Definition: relpath.h:40
void(* rm_mask)(char *pagedata, BlockNumber blkno)
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:2137
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4023
uint8 RmgrId
Definition: rmgr.h:11
#define Assert(condition)
Definition: c.h:804
static char * primary_image_masked
Definition: xlog.c:281
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:2203
#define PageGetLSN(page)
Definition: bufpage.h:366
#define elog(elevel,...)
Definition: elog.h:232
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:384
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:392
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:378

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3976 of file xlog.c.

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

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

3977 {
3978  int save_errno = errno;
3979  XLogSegNo lastRemovedSegNo;
3980 
3982  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3984 
3985  if (segno <= lastRemovedSegNo)
3986  {
3987  char filename[MAXFNAMELEN];
3988 
3989  XLogFileName(filename, tli, segno, wal_segment_size);
3990  errno = save_errno;
3991  ereport(ERROR,
3993  errmsg("requested WAL segment %s has already been removed",
3994  filename)));
3995  }
3996  errno = save_errno;
3997 }
int wal_segment_size
Definition: xlog.c:121
slock_t info_lck
Definition: xlog.c:737
XLogSegNo lastRemovedSegNo
Definition: xlog.c:609
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:46
uint64 XLogSegNo
Definition: xlogdefs.h:48
int errcode_for_file_access(void)
Definition: elog.c:721
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
#define ereport(elevel,...)
Definition: elog.h:157
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static XLogCtlData * XLogCtl
Definition: xlog.c:740
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

Definition at line 4340 of file xlog.c.

References AllocateDir(), dirent::d_name, DEBUG2, elog, FreeDir(), IsBackupHistoryFileName, MAXPGPATH, ReadDir(), snprintf, XLogArchiveCheckDone(), XLogArchiveCleanup(), and XLOGDIR.

Referenced by do_pg_stop_backup().

4341 {
4342  DIR *xldir;
4343  struct dirent *xlde;
4344  char path[MAXPGPATH + sizeof(XLOGDIR)];
4345 
4346  xldir = AllocateDir(XLOGDIR);
4347 
4348  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
4349  {
4350  if (IsBackupHistoryFileName(xlde->d_name))
4351  {
4352  if (XLogArchiveCheckDone(xlde->d_name))
4353  {
4354  elog(DEBUG2, "removing WAL backup history file \"%s\"",
4355  xlde->d_name);
4356  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
4357  unlink(path);
4358  XLogArchiveCleanup(xlde->d_name);
4359  }
4360  }
4361  }
4362 
4363  FreeDir(xldir);
4364 }
Definition: dirent.h:9
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:719
Definition: dirent.c:25
bool XLogArchiveCheckDone(const char *xlog)
Definition: xlogarchive.c:572
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2634
#define IsBackupHistoryFileName(fname)
#define XLOGDIR
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2700
#define elog(elevel,...)
Definition: elog.h:232
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2752

◆ ConfirmRecoveryPaused()

static void ConfirmRecoveryPaused ( void  )
static

Definition at line 6143 of file xlog.c.

References XLogCtlData::info_lck, RECOVERY_PAUSE_REQUESTED, RECOVERY_PAUSED, XLogCtlData::recoveryPauseState, SpinLockAcquire, and SpinLockRelease.

Referenced by recoveryPausesHere(), and RecoveryRequiresIntParameter().

6144 {
6145  /* If recovery pause is requested then set it paused */
6150 }
RecoveryPauseState recoveryPauseState
Definition: xlog.c:728
slock_t info_lck
Definition: xlog.c:737
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
static XLogCtlData * XLogCtl
Definition: xlog.c:740

◆ CopyXLogRecordToWAL()

static void CopyXLogRecordToWAL ( int  write_len,
bool  isLogSwitch,
XLogRecData rdata,
XLogRecPtr  StartPos,
XLogRecPtr  EndPos 
)
static

Definition at line 1526 of file xlog.c.

References Assert, XLogRecData::data, elog, GetXLogBuffer(), INSERT_FREESPACE, XLogRecData::len, MAXALIGN64, MemSet, XLogRecData::next, PANIC, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogShortPHD, wal_segment_size, XLogSegmentOffset, XLP_FIRST_IS_CONTRECORD, XLogPageHeaderData::xlp_info, and XLogPageHeaderData::xlp_rem_len.

Referenced by XLogInsertRecord().

1528 {
1529  char *currpos;
1530  int freespace;
1531  int written;
1532  XLogRecPtr CurrPos;
1533  XLogPageHeader pagehdr;
1534 
1535  /*
1536  * Get a pointer to the right place in the right WAL buffer to start
1537  * inserting to.
1538  */
1539  CurrPos = StartPos;
1540  currpos = GetXLogBuffer(CurrPos);
1541  freespace = INSERT_FREESPACE(CurrPos);
1542 
1543  /*
1544  * there should be enough space for at least the first field (xl_tot_len)
1545  * on this page.
1546  */
1547  Assert(freespace >= sizeof(uint32));
1548 
1549  /* Copy record data */
1550  written = 0;
1551  while (rdata != NULL)
1552  {
1553  char *rdata_data = rdata->data;
1554  int rdata_len = rdata->len;
1555 
1556  while (rdata_len > freespace)
1557  {
1558  /*
1559  * Write what fits on this page, and continue on the next page.
1560  */
1561  Assert(CurrPos % XLOG_BLCKSZ >= SizeOfXLogShortPHD || freespace == 0);
1562  memcpy(currpos, rdata_data, freespace);
1563  rdata_data += freespace;
1564  rdata_len -= freespace;
1565  written += freespace;
1566  CurrPos += freespace;
1567 
1568  /*
1569  * Get pointer to beginning of next page, and set the xlp_rem_len
1570  * in the page header. Set XLP_FIRST_IS_CONTRECORD.
1571  *
1572  * It's safe to set the contrecord flag and xlp_rem_len without a
1573  * lock on the page. All the other flags were already set when the
1574  * page was initialized, in AdvanceXLInsertBuffer, and we're the
1575  * only backend that needs to set the contrecord flag.
1576  */
1577  currpos = GetXLogBuffer(CurrPos);
1578  pagehdr = (XLogPageHeader) currpos;
1579  pagehdr->xlp_rem_len = write_len - written;
1580  pagehdr->xlp_info |= XLP_FIRST_IS_CONTRECORD;
1581 
1582  /* skip over the page header */
1583  if (XLogSegmentOffset(CurrPos, wal_segment_size) == 0)
1584  {
1585  CurrPos += SizeOfXLogLongPHD;
1586  currpos += SizeOfXLogLongPHD;
1587  }
1588  else
1589  {
1590  CurrPos += SizeOfXLogShortPHD;
1591  currpos += SizeOfXLogShortPHD;
1592  }
1593  freespace = INSERT_FREESPACE(CurrPos);
1594  }
1595 
1596  Assert(CurrPos % XLOG_BLCKSZ >= SizeOfXLogShortPHD || rdata_len == 0);
1597  memcpy(currpos, rdata_data, rdata_len);
1598  currpos += rdata_len;
1599  CurrPos += rdata_len;
1600  freespace -= rdata_len;
1601  written += rdata_len;
1602 
1603  rdata = rdata->next;
1604  }
1605  Assert(written == write_len);
1606 
1607  /*
1608  * If this was an xlog-switch, it's not enough to write the switch record,
1609  * we also have to consume all the remaining space in the WAL segment. We
1610  * have already reserved that space, but we need to actually fill it.
1611  */
1612  if (isLogSwitch && XLogSegmentOffset(CurrPos, wal_segment_size) != 0)
1613  {
1614  /* An xlog-switch record doesn't contain any data besides the header */
1615  Assert(write_len == SizeOfXLogRecord);
1616 
1617  /* Assert that we did reserve the right amount of space */
1618  Assert(XLogSegmentOffset(EndPos, wal_segment_size) == 0);
1619 
1620  /* Use up all the remaining space on the current page */
1621  CurrPos += freespace;
1622 
1623  /*
1624  * Cause all remaining pages in the segment to be flushed, leaving the
1625  * XLog position where it should be, at the start of the next segment.
1626  * We do this one page at a time, to make sure we don't deadlock
1627  * against ourselves if wal_buffers < wal_segment_size.
1628  */
1629  while (CurrPos < EndPos)
1630  {
1631  /*
1632  * The minimal action to flush the page would be to call
1633  * WALInsertLockUpdateInsertingAt(CurrPos) followed by
1634  * AdvanceXLInsertBuffer(...). The page would be left initialized
1635  * mostly to zeros, except for the page header (always the short
1636  * variant, as this is never a segment's first page).
1637  *
1638  * The large vistas of zeros are good for compressibility, but the
1639  * headers interrupting them every XLOG_BLCKSZ (with values that
1640  * differ from page to page) are not. The effect varies with
1641  * compression tool, but bzip2 for instance compresses about an
1642  * order of magnitude worse if those headers are left in place.
1643  *
1644  * Rather than complicating AdvanceXLInsertBuffer itself (which is
1645  * called in heavily-loaded circumstances as well as this lightly-
1646  * loaded one) with variant behavior, we just use GetXLogBuffer
1647  * (which itself calls the two methods we need) to get the pointer
1648  * and zero most of the page. Then we just zero the page header.
1649  */
1650  currpos = GetXLogBuffer(CurrPos);
1651  MemSet(currpos, 0, SizeOfXLogShortPHD);
1652 
1653  CurrPos += XLOG_BLCKSZ;
1654  }
1655  }
1656  else
1657  {
1658  /* Align the end position, so that the next record starts aligned */
1659  CurrPos = MAXALIGN64(CurrPos);
1660  }
1661 
1662  if (CurrPos != EndPos)
1663  elog(PANIC, "space reserved for WAL record does not match what was written");
1664 }
int wal_segment_size
Definition: xlog.c:121
#define MemSet(start, val, len)
Definition: c.h:1008
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
#define PANIC
Definition: elog.h:50
static char * GetXLogBuffer(XLogRecPtr ptr)
Definition: xlog.c:1902
#define MAXALIGN64(LEN)
Definition: c.h:782
unsigned int uint32
Definition: c.h:441
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:754
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
#define XLP_FIRST_IS_CONTRECORD
Definition: xlog_internal.h:74
struct XLogRecData * next
#define elog(elevel,...)
Definition: elog.h:232
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 8919 of file xlog.c.

References ControlFileData::checkPoint, CHECKPOINT_END_OF_RECOVERY, CHECKPOINT_FORCE, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStatsData::ckpt_bufs_written, CheckpointStatsData::ckpt_segs_added, CheckpointStatsData::ckpt_segs_recycled, CheckpointStatsData::ckpt_segs_removed, CheckpointStatsData::ckpt_start_t, XLogCtlData::ckptFullXid, XLogCtlInsert::CurrBytePos, DB_SHUTDOWNED, DB_SHUTDOWNING, DEBUG1, elog, END_CRIT_SECTION, ereport, errmsg(), errmsg_internal(), ERROR, CheckPoint::fullPageWrites, XLogCtlInsert::fullPageWrites, GetCurrentTimestamp(), GetLastImportantRecPtr(), GetOldestActiveTransactionId(), GetOldestTransactionIdConsideredRunning(), GetVirtualXIDsDelayingChkpt(), HaveVirtualXIDsDelayingChkpt(), XLogCtlData::info_lck, InitXLogInsert(), Insert(), XLogCtlData::Insert, INSERT_FREESPACE, InvalidateObsoleteReplicationSlots(), InvalidTransactionId, InvalidXLogRecPtr, KeepLogSeg(), LocalSetXLogInsertAllowed(), LocalXLogInsertAllowed, log_checkpoints, LogCheckpointEnd(), LogCheckpointStart(), LogStandbySnapshot(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MultiXactGetCheckptMulti(), NBuffers, CheckPoint::newestCommitTsXid, VariableCacheData::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, CheckPoint::nextXid, VariableCacheData::nextXid, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, VariableCacheData::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, VariableCacheData::oldestXid, CheckPoint::oldestXidDB, VariableCacheData::oldestXidDB, PANIC, pfree(), pg_usleep(), PreallocXlogFiles(), CheckPoint::PrevTimeLineID, XLogCtlData::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, ThisTimeLineID, CheckPoint::time, ControlFileData::time, TruncateSUBTRANS(), XLogCtlData::ulsn_lck, ControlFileData::unloggedLSN, XLogCtlData::unloggedLSN, update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_SHUTDOWN, XLogBeginInsert(), XLogBytePosToRecPtr(), XLogFlush(), XLogInsert(), XLogRegisterData(), XLogSegmentOffset, and XLogStandbyInfoActive.

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

8920 {
8921  bool shutdown;
8922  CheckPoint checkPoint;
8923  XLogRecPtr recptr;
8924  XLogSegNo _logSegNo;
8926  uint32 freespace;
8927  XLogRecPtr PriorRedoPtr;
8928  XLogRecPtr curInsert;
8929  XLogRecPtr last_important_lsn;
8930  VirtualTransactionId *vxids;
8931  int nvxids;
8932 
8933  /*
8934  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
8935  * issued at a different time.
8936  */
8938  shutdown = true;
8939  else
8940  shutdown = false;
8941 
8942  /* sanity check */
8943  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
8944  elog(ERROR, "can't create a checkpoint during recovery");
8945 
8946  /*
8947  * Initialize InitXLogInsert working areas before entering the critical
8948  * section. Normally, this is done by the first call to
8949  * RecoveryInProgress() or LocalSetXLogInsertAllowed(), but when creating
8950  * an end-of-recovery checkpoint, the LocalSetXLogInsertAllowed call is
8951  * done below in a critical section, and InitXLogInsert cannot be called
8952  * in a critical section.
8953  */
8954  InitXLogInsert();
8955 
8956  /*
8957  * Prepare to accumulate statistics.
8958  *
8959  * Note: because it is possible for log_checkpoints to change while a
8960  * checkpoint proceeds, we always accumulate stats, even if
8961  * log_checkpoints is currently off.
8962  */
8963  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
8965 
8966  /*
8967  * Use a critical section to force system panic if we have trouble.
8968  */
8970 
8971  if (shutdown)
8972  {
8973  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8975  ControlFile->time = (pg_time_t) time(NULL);
8977  LWLockRelease(ControlFileLock);
8978  }
8979 
8980  /*
8981  * Let smgr prepare for checkpoint; this has to happen before we determine
8982  * the REDO pointer. Note that smgr must not do anything that'd have to
8983  * be undone if we decide no checkpoint is needed.
8984  */
8986 
8987  /* Begin filling in the checkpoint WAL record */
8988  MemSet(&checkPoint, 0, sizeof(checkPoint));
8989  checkPoint.time = (pg_time_t) time(NULL);
8990 
8991  /*
8992  * For Hot Standby, derive the oldestActiveXid before we fix the redo
8993  * pointer. This allows us to begin accumulating changes to assemble our
8994  * starting snapshot of locks and transactions.
8995  */
8996  if (!shutdown && XLogStandbyInfoActive())
8998  else
9000 
9001  /*
9002  * Get location of last important record before acquiring insert locks (as
9003  * GetLastImportantRecPtr() also locks WAL locks).
9004  */
9005  last_important_lsn = GetLastImportantRecPtr();
9006 
9007  /*
9008  * We must block concurrent insertions while examining insert state to
9009  * determine the checkpoint REDO pointer.
9010  */
9012  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
9013 
9014  /*
9015  * If this isn't a shutdown or forced checkpoint, and if there has been no
9016  * WAL activity requiring a checkpoint, skip it. The idea here is to
9017  * avoid inserting duplicate checkpoints when the system is idle.
9018  */
9019  if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
9020  CHECKPOINT_FORCE)) == 0)
9021  {
9022  if (last_important_lsn == ControlFile->checkPoint)
9023  {
9025  END_CRIT_SECTION();
9026  ereport(DEBUG1,
9027  (errmsg_internal("checkpoint skipped because system is idle")));
9028  return;
9029  }
9030  }
9031 
9032  /*
9033  * An end-of-recovery checkpoint is created before anyone is allowed to
9034  * write WAL. To allow us to write the checkpoint record, temporarily
9035  * enable XLogInsertAllowed. (This also ensures ThisTimeLineID is
9036  * initialized, which we need here and in AdvanceXLInsertBuffer.)
9037  */
9038  if (flags & CHECKPOINT_END_OF_RECOVERY)
9040 
9041  checkPoint.ThisTimeLineID = ThisTimeLineID;
9042  if (flags & CHECKPOINT_END_OF_RECOVERY)
9043  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
9044  else
9045  checkPoint.PrevTimeLineID = ThisTimeLineID;
9046 
9047  checkPoint.fullPageWrites = Insert->fullPageWrites;
9048 
9049  /*
9050  * Compute new REDO record ptr = location of next XLOG record.
9051  *
9052  * NB: this is NOT necessarily where the checkpoint record itself will be,
9053  * since other backends may insert more XLOG records while we're off doing
9054  * the buffer flush work. Those XLOG records are logically after the
9055  * checkpoint, even though physically before it. Got that?
9056  */
9057  freespace = INSERT_FREESPACE(curInsert);
9058  if (freespace == 0)
9059  {
9060  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
9061  curInsert += SizeOfXLogLongPHD;
9062  else
9063  curInsert += SizeOfXLogShortPHD;
9064  }
9065  checkPoint.redo = curInsert;
9066 
9067  /*
9068  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
9069  * must be done while holding all the insertion locks.
9070  *
9071  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
9072  * pointing past where it really needs to point. This is okay; the only
9073  * consequence is that XLogInsert might back up whole buffers that it
9074  * didn't really need to. We can't postpone advancing RedoRecPtr because
9075  * XLogInserts that happen while we are dumping buffers must assume that
9076  * their buffer changes are not included in the checkpoint.
9077  */
9078  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
9079 
9080  /*
9081  * Now we can release the WAL insertion locks, allowing other xacts to
9082  * proceed while we are flushing disk buffers.
9083  */
9085 
9086  /* Update the info_lck-protected copy of RedoRecPtr as well */
9088  XLogCtl->RedoRecPtr = checkPoint.redo;
9090 
9091  /*
9092  * If enabled, log checkpoint start. We postpone this until now so as not
9093  * to log anything if we decided to skip the checkpoint.
9094  */
9095  if (log_checkpoints)
9096  LogCheckpointStart(flags, false);
9097 
9098  /* Update the process title */
9099  update_checkpoint_display(flags, false, false);
9100 
9101  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
9102 
9103  /*
9104  * Get the other info we need for the checkpoint record.
9105  *
9106  * We don't need to save oldestClogXid in the checkpoint, it only matters
9107  * for the short period in which clog is being truncated, and if we crash
9108  * during that we'll redo the clog truncation and fix up oldestClogXid
9109  * there.
9110  */
9111  LWLockAcquire(XidGenLock, LW_SHARED);
9112  checkPoint.nextXid = ShmemVariableCache->nextXid;
9113  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
9115  LWLockRelease(XidGenLock);
9116 
9117  LWLockAcquire(CommitTsLock, LW_SHARED);
9120  LWLockRelease(CommitTsLock);
9121 
9122  LWLockAcquire(OidGenLock, LW_SHARED);
9123  checkPoint.nextOid = ShmemVariableCache->nextOid;
9124  if (!shutdown)
9125  checkPoint.nextOid += ShmemVariableCache->oidCount;
9126  LWLockRelease(OidGenLock);
9127 
9128  MultiXactGetCheckptMulti(shutdown,
9129  &checkPoint.nextMulti,
9130  &checkPoint.nextMultiOffset,
9131  &checkPoint.oldestMulti,
9132  &checkPoint.oldestMultiDB);
9133 
9134  /*
9135  * Having constructed the checkpoint record, ensure all shmem disk buffers
9136  * and commit-log buffers are flushed to disk.
9137  *
9138  * This I/O could fail for various reasons. If so, we will fail to
9139  * complete the checkpoint, but there is no reason to force a system
9140  * panic. Accordingly, exit critical section while doing it.
9141  */
9142  END_CRIT_SECTION();
9143 
9144  /*
9145  * In some cases there are groups of actions that must all occur on one
9146  * side or the other of a checkpoint record. Before flushing the
9147  * checkpoint record we must explicitly wait for any backend currently
9148  * performing those groups of actions.
9149  *
9150  * One example is end of transaction, so we must wait for any transactions
9151  * that are currently in commit critical sections. If an xact inserted
9152  * its commit record into XLOG just before the REDO point, then a crash
9153  * restart from the REDO point would not replay that record, which means
9154  * that our flushing had better include the xact's update of pg_xact. So
9155  * we wait till he's out of his commit critical section before proceeding.
9156  * See notes in RecordTransactionCommit().
9157  *
9158  * Because we've already released the insertion locks, this test is a bit
9159  * fuzzy: it is possible that we will wait for xacts we didn't really need
9160  * to wait for. But the delay should be short and it seems better to make
9161  * checkpoint take a bit longer than to hold off insertions longer than
9162  * necessary. (In fact, the whole reason we have this issue is that xact.c
9163  * does commit record XLOG insertion and clog update as two separate steps
9164  * protected by different locks, but again that seems best on grounds of
9165  * minimizing lock contention.)
9166  *
9167  * A transaction that has not yet set delayChkpt when we look cannot be at
9168  * risk, since he's not inserted his commit record yet; and one that's
9169  * already cleared it is not at risk either, since he's done fixing clog
9170  * and we will correctly flush the update below. So we cannot miss any
9171  * xacts we need to wait for.
9172  */
9173  vxids = GetVirtualXIDsDelayingChkpt(&nvxids);
9174  if (nvxids > 0)
9175  {
9176  do
9177  {
9178  pg_usleep(10000L); /* wait for 10 msec */
9179  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids));
9180  }
9181  pfree(vxids);
9182 
9183  CheckPointGuts(checkPoint.redo, flags);
9184 
9185  /*
9186  * Take a snapshot of running transactions and write this to WAL. This
9187  * allows us to reconstruct the state of running transactions during
9188  * archive recovery, if required. Skip, if this info disabled.
9189  *
9190  * If we are shutting down, or Startup process is completing crash
9191  * recovery we don't need to write running xact data.
9192  */
9193  if (!shutdown && XLogStandbyInfoActive())
9195 
9197 
9198  /*
9199  * Now insert the checkpoint record into XLOG.
9200  */
9201  XLogBeginInsert();
9202  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
9203  recptr = XLogInsert(RM_XLOG_ID,
9204  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
9206 
9207  XLogFlush(recptr);
9208 
9209  /*
9210  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
9211  * overwritten at next startup. No-one should even try, this just allows
9212  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
9213  * to just temporarily disable writing until the system has exited
9214  * recovery.
9215  */
9216  if (shutdown)
9217  {
9218  if (flags & CHECKPOINT_END_OF_RECOVERY)
9219  LocalXLogInsertAllowed = -1; /* return to "check" state */
9220  else
9221  LocalXLogInsertAllowed = 0; /* never again write WAL */
9222  }
9223 
9224  /*
9225  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
9226  * = end of actual checkpoint record.
9227  */
9228  if (shutdown && checkPoint.redo != ProcLastRecPtr)
9229  ereport(PANIC,
9230  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
9231 
9232  /*
9233  * Remember the prior checkpoint's redo ptr for
9234  * UpdateCheckPointDistanceEstimate()
9235  */
9236  PriorRedoPtr = ControlFile->checkPointCopy.redo;
9237 
9238  /*
9239  * Update the control file.
9240  */
9241  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9242  if (shutdown)
9245  ControlFile->checkPointCopy = checkPoint;
9246  ControlFile->time = (pg_time_t) time(NULL);
9247  /* crash recovery should always recover to the end of WAL */
9250 
9251  /*
9252  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
9253  * unused on non-shutdown checkpoints, but seems useful to store it always
9254  * for debugging purposes.
9255  */
9259 
9261  LWLockRelease(ControlFileLock);
9262 
9263  /* Update shared-memory copy of checkpoint XID/epoch */
9265  XLogCtl->ckptFullXid = checkPoint.nextXid;
9267 
9268  /*
9269  * We are now done with critical updates; no need for system panic if we
9270  * have trouble while fooling with old log segments.
9271  */
9272  END_CRIT_SECTION();
9273 
9274  /*
9275  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
9276  */
9278 
9279  /*
9280  * Update the average distance between checkpoints if the prior checkpoint
9281  * exists.
9282  */
9283  if (PriorRedoPtr != InvalidXLogRecPtr)
9285 
9286  /*
9287  * Delete old log files, those no longer needed for last checkpoint to
9288  * prevent the disk holding the xlog from growing full.
9289  */
9291  KeepLogSeg(recptr, &_logSegNo);
9293  _logSegNo--;
9294  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr);
9295 
9296  /*
9297  * Make more log segments if needed. (Do this after recycling old log
9298  * segments, since that may supply some of the needed files.)
9299  */
9300  if (!shutdown)
9301  PreallocXlogFiles(recptr);
9302 
9303  /*
9304  * Truncate pg_subtrans if possible. We can throw away all data before
9305  * the oldest XMIN of any running transaction. No future transaction will
9306  * attempt to reference any pg_subtrans entry older than that (see Asserts
9307  * in subtrans.c). During recovery, though, we mustn't do this because
9308  * StartupSUBTRANS hasn't been called yet.
9309  */
9310  if (!RecoveryInProgress())
9312 
9313  /* Real work is done, but log and update stats before releasing lock. */
9314  LogCheckpointEnd(false);
9315 
9316  /* Reset the process title */
9317  update_checkpoint_display(flags, false, true);
9318 
9319  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
9320  NBuffers,
9324 }
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:8607
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8824
static int LocalXLogInsertAllowed
Definition: xlog.c:257
bool log_checkpoints
Definition: xlog.c:107
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1744
int wal_segment_size
Definition: xlog.c:121
pg_time_t time
Definition: pg_control.h:128
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:68
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
uint32 oidCount
Definition: transam.h:208
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:2013
XLogRecPtr unloggedLSN
Definition: xlog.c:612
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:364
TransactionId oldestActiveXid
Definition: pg_control.h:63
void InitXLogInsert(void)
Definition: xloginsert.c:1197
TimestampTz ckpt_start_t
Definition: xlog.h:256
slock_t info_lck
Definition: xlog.c:737
#define END_CRIT_SECTION()
Definition: miscadmin.h:137
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids)
Definition: procarray.c:2977
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: xlog.c:653
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
#define START_CRIT_SECTION()
Definition: miscadmin.h:135
int ckpt_segs_recycled
Definition: xlog.h:266
TransactionId oldestXid
Definition: transam.h:215
#define MemSet(start, val, len)
Definition: c.h:1008
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2130
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9384
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:600
TransactionId oldestXid
Definition: pg_control.h:47
bool RecoveryInProgress(void)
Definition: xlog.c:8237
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:338
FullTransactionId nextXid
Definition: transam.h:213
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:50
bool fullPageWrites
Definition: xlog.c:575
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2881
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:8862
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define SpinLockAcquire(lock)
Definition: spin.h:62
void pg_usleep(long microsec)
Definition: signal.c:53
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void UpdateControlFile(void)
Definition: xlog.c:4956
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1169
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:1220
#define ERROR
Definition: elog.h:46
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8732
static XLogRecPtr RedoRecPtr
Definition: xlog.c:378
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3943
uint64 XLogSegNo
Definition: xlogdefs.h:48
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:232
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
uint64 CurrBytePos
Definition: xlog.c:550
unsigned int uint32
Definition: c.h:441
XLogRecPtr RedoRecPtr
Definition: xlog.c:604
int ckpt_segs_removed
Definition: xlog.h:265
#define CHECKPOINT_FORCE
Definition: xlog.h:235
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:754
TransactionId oldestCommitTsXid
Definition: transam.h:225
static void Insert(File file)
Definition: fd.c:1222
int ckpt_bufs_written
Definition: xlog.h:262
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8381
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
#define SpinLockRelease(lock)
Definition: spin.h:64
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
TransactionId newestCommitTsXid
Definition: pg_control.h:54
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9803
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
Oid oldestMultiDB
Definition: pg_control.h:50
FullTransactionId ckptFullXid
Definition: xlog.c:605
#define XLogStandbyInfoActive()
Definition: xlog.h:215
static ControlFileData * ControlFile
Definition: xlog.c:748
TimeLineID ThisTimeLineID
Definition: xlog.c:196
Oid nextOid
Definition: pg_control.h:44
#define ereport(elevel,...)
Definition: elog.h:157
bool fullPageWrites
Definition: pg_control.h:42
int errmsg_internal(const char *fmt,...)
Definition: elog.c:996
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXidDB
Definition: pg_control.h:48
TransactionId newestCommitTsXid
Definition: transam.h:226
CheckpointStatsData CheckpointStats
Definition: xlog.c:190
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
MultiXactId nextMulti
Definition: pg_control.h:45
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1715
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:1968
int ckpt_segs_added
Definition: xlog.h:264
slock_t ulsn_lck
Definition: xlog.c:613
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:909
void InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno)
Definition: slot.c:1168
#define elog(elevel,...)
Definition: elog.h:232
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
Definition: xlog.c:4074
void SyncPostCheckpoint(void)
Definition: sync.c:195
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2816
int NBuffers
Definition: globals.c:135
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
Definition: procarray.c:3021
void XLogBeginInsert(void)
Definition: xloginsert.c:123
XLogRecPtr RedoRecPtr
Definition: xlog.c:573
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8700
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:231
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
void SyncPreCheckpoint(void)
Definition: sync.c:180
FullTransactionId nextXid
Definition: pg_control.h:43
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ CreateEndOfRecoveryRecord()

static void CreateEndOfRecoveryRecord ( void  )
static

Definition at line 9335 of file xlog.c.

References elog, END_CRIT_SECTION, xl_end_of_recovery::end_time, ERROR, GetCurrentTimestamp(), LocalSetXLogInsertAllowed(), LocalXLogInsertAllowed, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, xl_end_of_recovery::PrevTimeLineID, XLogCtlData::PrevTimeLineID, RecoveryInProgress(), START_CRIT_SECTION, ThisTimeLineID, xl_end_of_recovery::ThisTimeLineID, ControlFileData::time, UpdateControlFile(), WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLOG_END_OF_RECOVERY, XLogBeginInsert(), XLogFlush(), XLogInsert(), and XLogRegisterData().

Referenced by StartupXLOG().

9336 {
9337  xl_end_of_recovery xlrec;
9338  XLogRecPtr recptr;
9339 
9340  /* sanity check */
9341  if (!RecoveryInProgress())
9342  elog(ERROR, "can only be used to end recovery");
9343 
9344  xlrec.end_time = GetCurrentTimestamp();
9345 
9350 
9352 
9354 
9355  XLogBeginInsert();
9356  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
9357  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
9358 
9359  XLogFlush(recptr);
9360 
9361  /*
9362  * Update the control file so that crash recovery can follow the timeline
9363  * changes to this point.
9364  */
9365  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9366  ControlFile->time = (pg_time_t) time(NULL);
9367  ControlFile->minRecoveryPoint = recptr;
9370  LWLockRelease(ControlFileLock);
9371 
9372  END_CRIT_SECTION();
9373 
9374  LocalXLogInsertAllowed = -1; /* return to "check" state */
9375 }
static int LocalXLogInsertAllowed
Definition: xlog.c:257
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1744
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimeLineID PrevTimeLineID
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
#define END_CRIT_SECTION()
Definition: miscadmin.h:137
TimeLineID PrevTimeLineID
Definition: xlog.c:653
#define START_CRIT_SECTION()
Definition: miscadmin.h:135
bool RecoveryInProgress(void)
Definition: xlog.c:8237
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2881
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
void UpdateControlFile(void)
Definition: xlog.c:4956
#define ERROR
Definition: elog.h:46
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8381
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
static ControlFileData * ControlFile
Definition: xlog.c:748
TimeLineID ThisTimeLineID
Definition: xlog.c:196
TimestampTz end_time
uint64 XLogRecPtr
Definition: xlogdefs.h:21
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1715
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
TimeLineID ThisTimeLineID
#define elog(elevel,...)
Definition: elog.h:232
void XLogBeginInsert(void)
Definition: xloginsert.c:123
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 9465 of file xlog.c.

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

Referenced by CheckpointerMain(), and ShutdownXLOG().

9466 {
9467  XLogRecPtr lastCheckPointRecPtr;
9468  XLogRecPtr lastCheckPointEndPtr;
9469  CheckPoint lastCheckPoint;
9470  XLogRecPtr PriorRedoPtr;
9471  XLogRecPtr receivePtr;
9472  XLogRecPtr replayPtr;
9473  TimeLineID replayTLI;
9474  XLogRecPtr endptr;
9475  XLogSegNo _logSegNo;
9476  TimestampTz xtime;
9477 
9478  /* Get a local copy of the last safe checkpoint record. */
9480  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
9481  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
9482  lastCheckPoint = XLogCtl->lastCheckPoint;
9484 
9485  /*
9486  * Check that we're still in recovery mode. It's ok if we exit recovery
9487  * mode after this check, the restart point is valid anyway.
9488  */
9489  if (!RecoveryInProgress())
9490  {
9491  ereport(DEBUG2,
9492  (errmsg_internal("skipping restartpoint, recovery has already ended")));
9493  return false;
9494  }
9495 
9496  /*
9497  * If the last checkpoint record we've replayed is already our last
9498  * restartpoint, we can't perform a new restart point. We still update
9499  * minRecoveryPoint in that case, so that if this is a shutdown restart
9500  * point, we won't start up earlier than before. That's not strictly
9501  * necessary, but when hot standby is enabled, it would be rather weird if
9502  * the database opened up for read-only connections at a point-in-time
9503  * before the last shutdown. Such time travel is still possible in case of
9504  * immediate shutdown, though.
9505  *
9506  * We don't explicitly advance minRecoveryPoint when we do create a
9507  * restartpoint. It's assumed that flushing the buffers will do that as a
9508  * side-effect.
9509  */
9510  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
9511  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
9512  {
9513  ereport(DEBUG2,
9514  (errmsg_internal("skipping restartpoint, already performed at %X/%X",
9515  LSN_FORMAT_ARGS(lastCheckPoint.redo))));
9516 
9518  if (flags & CHECKPOINT_IS_SHUTDOWN)
9519  {
9520  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9522  ControlFile->time = (pg_time_t) time(NULL);
9524  LWLockRelease(ControlFileLock);
9525  }
9526  return false;
9527  }
9528 
9529  /*
9530  * Update the shared RedoRecPtr so that the startup process can calculate
9531  * the number of segments replayed since last restartpoint, and request a
9532  * restartpoint if it exceeds CheckPointSegments.
9533  *
9534  * Like in CreateCheckPoint(), hold off insertions to update it, although
9535  * during recovery this is just pro forma, because no WAL insertions are
9536  * happening.
9537  */
9539  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
9541 
9542  /* Also update the info_lck-protected copy */
9544  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
9546 
9547  /*
9548  * Prepare to accumulate statistics.
9549  *
9550  * Note: because it is possible for log_checkpoints to change while a
9551  * checkpoint proceeds, we always accumulate stats, even if
9552  * log_checkpoints is currently off.
9553  */
9554  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
9556 
9557  if (log_checkpoints)
9558  LogCheckpointStart(flags, true);
9559 
9560  /* Update the process title */
9561  update_checkpoint_display(flags, true, false);
9562 
9563  CheckPointGuts(lastCheckPoint.redo, flags);
9564 
9565  /*
9566  * Remember the prior checkpoint's redo ptr for
9567  * UpdateCheckPointDistanceEstimate()
9568  */
9569  PriorRedoPtr = ControlFile->checkPointCopy.redo;
9570 
9571  /*
9572  * Update pg_control, using current time. Check that it still shows
9573  * DB_IN_ARCHIVE_RECOVERY state and an older checkpoint, else do nothing;
9574  * this is a quick hack to make sure nothing really bad happens if somehow
9575  * we get here after the end-of-recovery checkpoint.
9576  */
9577  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9579  ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
9580  {
9581  ControlFile->checkPoint = lastCheckPointRecPtr;
9582  ControlFile->checkPointCopy = lastCheckPoint;
9583  ControlFile->time = (pg_time_t) time(NULL);
9584 
9585  /*
9586  * Ensure minRecoveryPoint is past the checkpoint record. Normally,
9587  * this will have happened already while writing out dirty buffers,
9588  * but not necessarily - e.g. because no buffers were dirtied. We do
9589  * this because a non-exclusive base backup uses minRecoveryPoint to
9590  * determine which WAL files must be included in the backup, and the
9591  * file (or files) containing the checkpoint record must be included,
9592  * at a minimum. Note that for an ordinary restart of recovery there's
9593  * no value in having the minimum recovery point any earlier than this
9594  * anyway, because redo will begin just after the checkpoint record.
9595  */
9596  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
9597  {
9598  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
9600 
9601  /* update local copy */
9604  }
9605  if (flags & CHECKPOINT_IS_SHUTDOWN)
9608  }
9609  LWLockRelease(ControlFileLock);
9610 
9611  /*
9612  * Update the average distance between checkpoints/restartpoints if the
9613  * prior checkpoint exists.
9614  */
9615  if (PriorRedoPtr != InvalidXLogRecPtr)
9617 
9618  /*
9619  * Delete old log files, those no longer needed for last restartpoint to
9620  * prevent the disk holding the xlog from growing full.
9621  */
9623 
9624  /*
9625  * Retreat _logSegNo using the current end of xlog replayed or received,
9626  * whichever is later.
9627  */
9628  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
9629  replayPtr = GetXLogReplayRecPtr(&replayTLI);
9630  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
9631  KeepLogSeg(endptr, &_logSegNo);
9633  _logSegNo--;
9634 
9635  /*
9636  * Try to recycle segments on a useful timeline. If we've been promoted
9637  * since the beginning of this restartpoint, use the new timeline chosen
9638  * at end of recovery (RecoveryInProgress() sets ThisTimeLineID in that
9639  * case). If we're still in recovery, use the timeline we're currently
9640  * replaying.
9641  *
9642  * There is no guarantee that the WAL segments will be useful on the
9643  * current timeline; if recovery proceeds to a new timeline right after
9644  * this, the pre-allocated WAL segments on this timeline will not be used,
9645  * and will go wasted until recycled on the next restartpoint. We'll live
9646  * with that.
9647  */
9648  if (RecoveryInProgress())
9649  ThisTimeLineID = replayTLI;
9650 
9651  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr);
9652 
9653  /*
9654  * Make more log segments if needed. (Do this after recycling old log
9655  * segments, since that may supply some of the needed files.)
9656  */
9657  PreallocXlogFiles(endptr);
9658 
9659  /*
9660  * ThisTimeLineID is normally not set when we're still in recovery.
9661  * However, recycling/preallocating segments above needed ThisTimeLineID
9662  * to determine which timeline to install the segments on. Reset it now,
9663  * to restore the normal state of affairs for debugging purposes.
9664  */
9665  if (RecoveryInProgress())
9666  ThisTimeLineID = 0;
9667 
9668  /*
9669  * Truncate pg_subtrans if possible. We can throw away all data before
9670  * the oldest XMIN of any running transaction. No future transaction will
9671  * attempt to reference any pg_subtrans entry older than that (see Asserts
9672  * in subtrans.c). When hot standby is disabled, though, we mustn't do
9673  * this because StartupSUBTRANS hasn't been called yet.
9674  */
9675  if (EnableHotStandby)
9677 
9678  /* Real work is done, but log and update before releasing lock. */
9679  LogCheckpointEnd(true);
9680 
9681  /* Reset the process title */
9682  update_checkpoint_display(flags, true, true);
9683 
9684  xtime = GetLatestXTime();
9686  (errmsg("recovery restart point at %X/%X",
9687  LSN_FORMAT_ARGS(lastCheckPoint.redo)),
9688  xtime ? errdetail("Last completed transaction was at log time %s.",
9689  timestamptz_to_str(xtime)) : 0));
9690 
9691  /*
9692  * Finally, execute archive_cleanup_command, if any.
9693  */
9694  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
9696  "archive_cleanup_command",
9697  false);
9698 
9699  return true;
9700 }
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8824
bool log_checkpoints
Definition: xlog.c:107
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal)
Definition: xlogarchive.c:287
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
uint32 TimeLineID
Definition: xlogdefs.h:59
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1744
int wal_segment_size
Definition: xlog.c:121
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
int64 TimestampTz
Definition: timestamp.h:39
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2797
TimestampTz ckpt_start_t
Definition: xlog.h:256
slock_t info_lck
Definition: xlog.c:737
#define MemSet(start, val, len)
Definition: c.h:1008
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9384
TimestampTz GetLatestXTime(void)
Definition: xlog.c:6263
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:600
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:8237
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:338
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:705
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:8862
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
void UpdateControlFile(void)
Definition: xlog.c:4956
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8732
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
Definition: xlog.c:11728
#define DEBUG2
Definition: elog.h:24
static XLogRecPtr RedoRecPtr
Definition: xlog.c:378
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3943
uint64 XLogSegNo
Definition: xlogdefs.h:48
int errdetail(const char *fmt,...)
Definition: elog.c:1042
XLogRecPtr RedoRecPtr
Definition: xlog.c:604
CheckPoint lastCheckPoint
Definition: xlog.c:707
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:862
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9803
static ControlFileData * ControlFile
Definition: xlog.c:748
TimeLineID ThisTimeLineID
Definition: xlog.c:196
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg_internal(const char *fmt,...)
Definition: elog.c:996
uint64 XLogRecPtr
Definition: xlogdefs.h:21
CheckpointStatsData CheckpointStats
Definition: xlog.c:190
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1715
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:1968
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
bool EnableHotStandby
Definition: xlog.c:99
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:909
void InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno)
Definition: slot.c:1168
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
Definition: xlog.c:4074
XLogRecPtr RedoRecPtr
Definition: xlog.c:573
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:706
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8700
char * archiveCleanupCommand
Definition: xlog.c:286
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:231
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:861
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1774
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ DataChecksumsEnabled()

bool DataChecksumsEnabled ( void  )

Definition at line 4985 of file xlog.c.

References Assert, and ControlFileData::data_checksum_version.

Referenced by PageIsVerifiedExtended(), PageSetChecksumCopy(), PageSetChecksumInplace(), pg_stat_get_db_checksum_failures(), pg_stat_get_db_checksum_last_failure(), ReadControlFile(), and sendFile().

4986 {
4987  Assert(ControlFile != NULL);
4988  return (ControlFile->data_checksum_version > 0);
4989 }
uint32 data_checksum_version
Definition: pg_control.h:220
static ControlFileData * ControlFile
Definition: xlog.c:748
#define Assert(condition)
Definition: c.h:804

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

Definition at line 11680 of file xlog.c.

References Assert, DatumGetBool, ereport, errmsg(), EXCLUSIVE_BACKUP_NONE, XLogCtlInsert::exclusiveBackupState, XLogCtlInsert::forcePageWrites, XLogCtlData::Insert, XLogCtlInsert::nonExclusiveBackups, SESSION_BACKUP_NON_EXCLUSIVE, sessionBackupState, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), and WARNING.

Referenced by perform_base_backup(), and register_persistent_abort_backup_handler().

11681 {
11682  bool emit_warning = DatumGetBool(arg);
11683 
11684  /*
11685  * Quick exit if session is not keeping around a non-exclusive backup
11686  * already started.
11687  */
11689  return;
11690 
11694 
11697  {
11698  XLogCtl->Insert.forcePageWrites = false;
11699  }
11701 
11702  if (emit_warning)
11703  ereport(WARNING,
11704  (errmsg("aborting backup due to backend exiting before pg_stop_backup was called")));
11705 }
static void WALInsertLockRelease(void)
Definition: xlog.c:1744
static SessionBackupState sessionBackupState
Definition: xlog.c:534
XLogCtlInsert Insert
Definition: xlog.c:600
bool forcePageWrites
Definition: xlog.c:574
#define DatumGetBool(X)
Definition: postgres.h:437
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:586
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:585
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1715
static XLogCtlData * XLogCtl
Definition: xlog.c:740
int errmsg(const char *fmt,...)
Definition: elog.c:909
void * arg

◆ do_pg_start_backup()

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

Definition at line 10749 of file xlog.c.

References AllocateDir(), AllocateFile(), appendStringInfo(), appendStringInfoChar(), BACKUP_LABEL_FILE, backup_started_in_recovery, BoolGetDatum, ControlFileData::checkPoint, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, ControlFileData::checkPointCopy, dirent::d_name, StringInfoData::data, DataDir, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, EXCLUSIVE_BACKUP_IN_PROGRESS, EXCLUSIVE_BACKUP_NONE, EXCLUSIVE_BACKUP_STARTING, XLogCtlInsert::exclusiveBackupState, XLogCtlInsert::forcePageWrites, FreeDir(), FreeFile(), CheckPoint::fullPageWrites, XLogCtlData::info_lck, initStringInfo(), XLogCtlData::Insert, IS_DIR_SEP, lappend(), XLogCtlInsert::lastBackupStart, XLogCtlData::lastFpwDisableRecPtr, StringInfoData::len, log_timezone, LSN_FORMAT_ARGS, LW_SHARED, LWLockAcquire(), LWLockRelease(), makeStringInfo(), MAXFNAMELEN, MAXPGPATH, XLogCtlInsert::nonExclusiveBackups, tablespaceinfo::oid, palloc(), tablespaceinfo::path, pfree(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, pg_fsync(), pg_localtime(), pg_start_backup_callback(), pg_strftime(), pstrdup(), ReadDir(), readlink, RecoveryInProgress(), CheckPoint::redo, relpath, RequestCheckpoint(), RequestXLogSwitch(), tablespaceinfo::rpath, SESSION_BACKUP_EXCLUSIVE, SESSION_BACKUP_NON_EXCLUSIVE, sessionBackupState, tablespaceinfo::size, snprintf, SpinLockAcquire, SpinLockRelease, stat, TABLESPACE_MAP, CheckPoint::ThisTimeLineID, wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, XLByteToSeg, XLogFileName, and XLogIsNeeded.

Referenced by perform_base_backup(), and pg_start_backup().

10752 {
10753  bool exclusive = (labelfile == NULL);
10754  bool backup_started_in_recovery = false;
10755  XLogRecPtr checkpointloc;
10756  XLogRecPtr startpoint;
10757  TimeLineID starttli;
10758  pg_time_t stamp_time;
10759  char strfbuf[128];
10760  char xlogfilename[MAXFNAMELEN];
10761  XLogSegNo _logSegNo;
10762  struct stat stat_buf;
10763  FILE *fp;
10764 
10765  backup_started_in_recovery = RecoveryInProgress();
10766 
10767  /*
10768  * Currently only non-exclusive backup can be taken during recovery.
10769  */
10770  if (backup_started_in_recovery && exclusive)
10771  ereport(ERROR,
10772  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10773  errmsg("recovery is in progress"),
10774  errhint("WAL control functions cannot be executed during recovery.")));
10775 
10776  /*
10777  * During recovery, we don't need to check WAL level. Because, if WAL
10778  * level is not sufficient, it's impossible to get here during recovery.
10779  */
10780  if (!backup_started_in_recovery && !XLogIsNeeded())
10781  ereport(ERROR,
10782  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10783  errmsg("WAL level not sufficient for making an online backup"),
10784  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
10785 
10786  if (strlen(backupidstr) > MAXPGPATH)
10787  ereport(ERROR,
10788  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10789  errmsg("backup label too long (max %d bytes)",
10790  MAXPGPATH)));
10791 
10792  /*
10793  * Mark backup active in shared memory. We must do full-page WAL writes
10794  * during an on-line backup even if not doing so at other times, because
10795  * it's quite possible for the backup dump to obtain a "torn" (partially
10796  * written) copy of a database page if it reads the page concurrently with
10797  * our write to the same page. This can be fixed as long as the first
10798  * write to the page in the WAL sequence is a full-page write. Hence, we
10799  * turn on forcePageWrites and then force a CHECKPOINT, to ensure there
10800  * are no dirty pages in shared memory that might get dumped while the
10801  * backup is in progress without having a corresponding WAL record. (Once
10802  * the backup is complete, we need not force full-page writes anymore,
10803  * since we expect that any pages not modified during the backup interval
10804  * must have been correctly captured by the backup.)
10805  *
10806  * Note that forcePageWrites has no effect during an online backup from
10807  * the standby.
10808  *
10809  * We must hold all the insertion locks to change the value of
10810  * forcePageWrites, to ensure adequate interlocking against
10811  * XLogInsertRecord().
10812  */
10814  if (exclusive)
10815  {
10816  /*
10817  * At first, mark that we're now starting an exclusive backup, to
10818  * ensure that there are no other sessions currently running
10819  * pg_start_backup() or pg_stop_backup().
10820  */
10822  {
10824  ereport(ERROR,
10825  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10826  errmsg("a backup is already in progress"),
10827  errhint("Run pg_stop_backup() and try again.")));
10828  }
10830  }
10831  else
10833  XLogCtl->Insert.forcePageWrites = true;
10835 
10836  /* Ensure we release forcePageWrites if fail below */
10838  {
10839  bool gotUniqueStartpoint = false;
10840  DIR *tblspcdir;
10841  struct dirent *de;
10842  tablespaceinfo *ti;
10843  int datadirpathlen;
10844 
10845  /*
10846  * Force an XLOG file switch before the checkpoint, to ensure that the
10847  * WAL segment the checkpoint is written to doesn't contain pages with
10848  * old timeline IDs. That would otherwise happen if you called
10849  * pg_start_backup() right after restoring from a PITR archive: the
10850  * first WAL segment containing the startup checkpoint has pages in
10851  * the beginning with the old timeline ID. That can cause trouble at
10852  * recovery: we won't have a history file covering the old timeline if
10853  * pg_wal directory was not included in the base backup and the WAL
10854  * archive was cleared too before starting the backup.
10855  *
10856  * This also ensures that we have emitted a WAL page header that has
10857  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
10858  * Therefore, if a WAL archiver (such as pglesslog) is trying to
10859  * compress out removable backup blocks, it won't remove any that
10860  * occur after this point.
10861  *
10862  * During recovery, we skip forcing XLOG file switch, which means that
10863  * the backup taken during recovery is not available for the special
10864  * recovery case described above.
10865  */
10866  if (!backup_started_in_recovery)
10867  RequestXLogSwitch(false);
10868 
10869  do
10870  {
10871  bool checkpointfpw;
10872 
10873  /*
10874  * Force a CHECKPOINT. Aside from being necessary to prevent torn
10875  * page problems, this guarantees that two successive backup runs
10876  * will have different checkpoint positions and hence different
10877  * history file names, even if nothing happened in between.
10878  *
10879  * During recovery, establish a restartpoint if possible. We use
10880  * the last restartpoint as the backup starting checkpoint. This
10881  * means that two successive backup runs can have same checkpoint
10882  * positions.
10883  *
10884  * Since the fact that we are executing do_pg_start_backup()
10885  * during recovery means that checkpointer is running, we can use
10886  * RequestCheckpoint() to establish a restartpoint.
10887  *
10888  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
10889  * passing fast = true). Otherwise this can take awhile.
10890  */
10892  (fast ? CHECKPOINT_IMMEDIATE : 0));
10893 
10894  /*
10895  * Now we need to fetch the checkpoint record location, and also
10896  * its REDO pointer. The oldest point in WAL that would be needed
10897  * to restore starting from the checkpoint is precisely the REDO
10898  * pointer.
10899  */
10900  LWLockAcquire(ControlFileLock, LW_SHARED);
10901  checkpointloc = ControlFile->checkPoint;
10902  startpoint = ControlFile->checkPointCopy.redo;
10904  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
10905  LWLockRelease(ControlFileLock);
10906 
10907  if (backup_started_in_recovery)
10908  {
10909  XLogRecPtr recptr;
10910 
10911  /*
10912  * Check to see if all WAL replayed during online backup
10913  * (i.e., since last restartpoint used as backup starting
10914  * checkpoint) contain full-page writes.
10915  */
10917  recptr = XLogCtl->lastFpwDisableRecPtr;
10919 
10920  if (!checkpointfpw || startpoint <= recptr)
10921  ereport(ERROR,
10922  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10923  errmsg("WAL generated with full_page_writes=off was replayed "
10924  "since last restartpoint"),
10925  errhint("This means that the backup being taken on the standby "
10926  "is corrupt and should not be used. "
10927  "Enable full_page_writes and run CHECKPOINT on the primary, "
10928  "and then try an online backup again.")));
10929 
10930  /*
10931  * During recovery, since we don't use the end-of-backup WAL
10932  * record and don't write the backup history file, the
10933  * starting WAL location doesn't need to be unique. This means
10934  * that two base backups started at the same time might use
10935  * the same checkpoint as starting locations.
10936  */
10937  gotUniqueStartpoint = true;
10938  }
10939 
10940  /*
10941  * If two base backups are started at the same time (in WAL sender
10942  * processes), we need to make sure that they use different
10943  * checkpoints as starting locations, because we use the starting
10944  * WAL location as a unique identifier for the base backup in the
10945  * end-of-backup WAL record and when we write the backup history
10946  * file. Perhaps it would be better generate a separate unique ID
10947  * for each backup instead of forcing another checkpoint, but
10948  * taking a checkpoint right after another is not that expensive
10949  * either because only few buffers have been dirtied yet.
10950  */
10952  if (XLogCtl->Insert.lastBackupStart < startpoint)
10953  {
10954  XLogCtl->Insert.lastBackupStart = startpoint;
10955  gotUniqueStartpoint = true;
10956  }
10958  } while (!gotUniqueStartpoint);
10959 
10960  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
10961  XLogFileName(xlogfilename, starttli, _logSegNo, wal_segment_size);
10962 
10963  /*
10964  * Construct tablespace_map file. If caller isn't interested in this,
10965  * we make a local StringInfo.
10966  */
10967  if (tblspcmapfile == NULL)
10968  tblspcmapfile = makeStringInfo();
10969 
10970  datadirpathlen = strlen(DataDir);
10971 
10972  /* Collect information about all tablespaces */
10973  tblspcdir = AllocateDir("pg_tblspc");
10974  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
10975  {
10976  char fullpath[MAXPGPATH + 10];
10977  char linkpath[MAXPGPATH];
10978  char *relpath = NULL;
10979  int rllen;
10980  StringInfoData escapedpath;
10981  char *s;
10982 
10983  /* Skip anything that doesn't look like a tablespace */
10984  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
10985  continue;
10986 
10987  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
10988 
10989 #if defined(HAVE_READLINK) || defined(WIN32)
10990  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
10991  if (rllen < 0)
10992  {
10993  ereport(WARNING,
10994  (errmsg("could not read symbolic link \"%s\": %m",
10995  fullpath)));
10996  continue;
10997  }
10998  else if (rllen >= sizeof(linkpath))
10999  {
11000  ereport(WARNING,
11001  (errmsg("symbolic link \"%s\" target is too long",
11002  fullpath)));
11003  continue;
11004  }
11005  linkpath[rllen] = '\0';
11006 
11007  /*
11008  * Build a backslash-escaped version of the link path to include
11009  * in the tablespace map file.
11010  */
11011  initStringInfo(&escapedpath);
11012  for (s = linkpath; *s; s++)
11013  {
11014  if (*s == '\n' || *s == '\r' || *s == '\\')
11015  appendStringInfoChar(&escapedpath, '\\');
11016  appendStringInfoChar(&escapedpath, *s);
11017  }
11018 
11019  /*
11020  * Relpath holds the relative path of the tablespace directory
11021  * when it's located within PGDATA, or NULL if it's located
11022  * elsewhere.
11023  */
11024  if (rllen > datadirpathlen &&
11025  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
11026  IS_DIR_SEP(linkpath[datadirpathlen]))
11027  relpath = linkpath + datadirpathlen + 1;
11028 
11029  ti = palloc(sizeof(tablespaceinfo));
11030  ti->oid = pstrdup(de->d_name);
11031  ti->path = pstrdup(linkpath);
11032  ti->rpath = relpath ? pstrdup(relpath) : NULL;
11033  ti->size = -1;
11034 
11035  if (tablespaces)
11036  *tablespaces = lappend(*tablespaces, ti);
11037 
11038  appendStringInfo(tblspcmapfile, "%s %s\n",
11039  ti->oid, escapedpath.data);
11040 
11041  pfree(escapedpath.data);
11042 #else
11043 
11044  /*
11045  * If the platform does not have symbolic links, it should not be
11046  * possible to have tablespaces - clearly somebody else created
11047  * them. Warn about it and ignore.
11048  */
11049  ereport(WARNING,
11050  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11051  errmsg("tablespaces are not supported on this platform")));
11052 #endif
11053  }
11054  FreeDir(tblspcdir);
11055 
11056  /*
11057  * Construct backup label file. If caller isn't interested in this,
11058  * we make a local StringInfo.
11059  */
11060  if (labelfile == NULL)
11061  labelfile = makeStringInfo();
11062 
11063  /* Use the log timezone here, not the session timezone */
11064  stamp_time = (pg_time_t) time(NULL);
11065  pg_strftime(strfbuf, sizeof(strfbuf),
11066  "%Y-%m-%d %H:%M:%S %Z",
11067  pg_localtime(&stamp_time, log_timezone));
11068  appendStringInfo(labelfile, "START WAL LOCATION: %X/%X (file %s)\n",
11069  LSN_FORMAT_ARGS(startpoint), xlogfilename);
11070  appendStringInfo(labelfile, "CHECKPOINT LOCATION: %X/%X\n",
11071  LSN_FORMAT_ARGS(checkpointloc));
11072  appendStringInfo(labelfile, "BACKUP METHOD: %s\n",
11073  exclusive ? "pg_start_backup" : "streamed");
11074  appendStringInfo(labelfile, "BACKUP FROM: %s\n",
11075  backup_started_in_recovery ? "standby" : "primary");
11076  appendStringInfo(labelfile, "START TIME: %s\n", strfbuf);
11077  appendStringInfo(labelfile, "LABEL: %s\n", backupidstr);
11078  appendStringInfo(labelfile, "START TIMELINE: %u\n", starttli);
11079 
11080  /*
11081  * Okay, write the file, or return its contents to caller.
11082  */
11083  if (exclusive)
11084  {
11085  /*
11086  * Check for existing backup label --- implies a backup is already
11087  * running. (XXX given that we checked exclusiveBackupState
11088  * above, maybe it would be OK to just unlink any such label
11089  * file?)
11090  */
11091  if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
11092  {
11093  if (errno != ENOENT)
11094  ereport(ERROR,
11096  errmsg("could not stat file \"%s\": %m",
11097  BACKUP_LABEL_FILE)));
11098  }
11099  else
11100  ereport(ERROR,
11101  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11102  errmsg("a backup is already in progress"),
11103  errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
11104  BACKUP_LABEL_FILE)));
11105 
11106  fp = AllocateFile(BACKUP_LABEL_FILE, "w");
11107 
11108  if (!fp)
11109  ereport(ERROR,
11111  errmsg("could not create file \"%s\": %m",
11112  BACKUP_LABEL_FILE)));
11113  if (fwrite(labelfile->data, labelfile->len, 1, fp) != 1 ||
11114  fflush(fp) != 0 ||
11115  pg_fsync(fileno(fp)) != 0 ||
11116  ferror(fp) ||
11117  FreeFile(fp))
11118  ereport(ERROR,
11120  errmsg("could not write file \"%s\": %m",
11121  BACKUP_LABEL_FILE)));
11122  /* Allocated locally for exclusive backups, so free separately */
11123  pfree(labelfile->data);
11124  pfree(labelfile);
11125 
11126  /* Write backup tablespace_map file. */
11127  if (tblspcmapfile->len > 0)
11128  {
11129  if (stat(TABLESPACE_MAP, &stat_buf) != 0)
11130  {
11131  if (errno != ENOENT)
11132  ereport(ERROR,
11134  errmsg("could not stat file \"%s\": %m",
11135  TABLESPACE_MAP)));
11136  }
11137  else
11138  ereport(ERROR,
11139  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11140  errmsg("a backup is already in progress"),
11141  errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
11142  TABLESPACE_MAP)));
11143 
11144  fp = AllocateFile(TABLESPACE_MAP, "w");
11145 
11146  if (!fp)
11147  ereport(ERROR,
11149  errmsg("could not create file \"%s\": %m",
11150  TABLESPACE_MAP)));
11151  if (fwrite(tblspcmapfile->data, tblspcmapfile->len, 1, fp) != 1 ||
11152  fflush(fp) != 0 ||
11153  pg_fsync(fileno(fp)) != 0 ||
11154  ferror(fp) ||
11155  FreeFile(fp))
11156  ereport(ERROR,
11158  errmsg("could not write file \"%s\": %m",
11159  TABLESPACE_MAP)));
11160  }
11161 
11162  /* Allocated locally for exclusive backups, so free separately */
11163  pfree(tblspcmapfile->data);
11164  pfree(tblspcmapfile);
11165  }
11166  }
11168 
11169  /*
11170  * Mark that start phase has correctly finished for an exclusive backup.
11171  * Session-level locks are updated as well to reflect that state.
11172  *
11173  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating backup
11174  * counters and session-level lock. Otherwise they can be updated
11175  * inconsistently, and which might cause do_pg_abort_backup() to fail.
11176  */
11177  if (exclusive)
11178  {
11181 
11182  /* Set session-level lock */
11185  }
11186  else
11188 
11189  /*
11190  * We're done. As a convenience, return the starting WAL location.
11191  */
11192  if (starttli_p)
11193  *starttli_p = starttli;
11194  return startpoint;
11195 }
size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm *tm)
Definition: strftime.c:128
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:9896
int errhint(const char *fmt,...)
Definition: elog.c:1156
uint32 TimeLineID
Definition: xlogdefs.h:59
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1744
int wal_segment_size
Definition: xlog.c:121
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:735
static SessionBackupState sessionBackupState
Definition: xlog.c:534
XLogRecPtr lastBackupStart
Definition: xlog.c:587
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define XLogIsNeeded()
Definition: xlog.h:201
char * rpath
Definition: basebackup.h:32
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
slock_t info_lck
Definition: xlog.c:737
int errcode(int sqlerrcode)
Definition: elog.c:698
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:600
bool RecoveryInProgress(void)
Definition: xlog.c:8237
static bool backup_started_in_recovery
Definition: basebackup.c:88
Definition: dirent.h:9
#define IS_DIR_SEP(ch)
Definition: port.h:84
pg_tz * log_timezone
Definition: pgtz.c:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define TABLESPACE_MAP
Definition: xlog.h:401
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
void pfree(void *pointer)
Definition: mcxt.c:1169
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool forcePageWrites
Definition: xlog.c:574
Definition: dirent.c:25
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:48
#define readlink(path, buf, size)
Definition: win32_port.h:228
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2634
#define CHECKPOINT_FORCE
Definition: xlog.h:235
List * lappend(List *list, void *datum)
Definition: list.c:336
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:586
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
static void pg_start_backup_callback(int code, Datum arg)
Definition: xlog.c:11199
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:585
uintptr_t Datum
Definition: postgres.h:411
static ControlFileData * ControlFile
Definition: xlog.c:748
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ereport(elevel,...)
Definition: elog.h:157
bool fullPageWrites
Definition: pg_control.h:42
#define CHECKPOINT_WAIT
Definition: xlog.h:239
uint64 XLogRecPtr
Definition: xlogdefs.h:21
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2700
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1715
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1342
int FreeFile(FILE *file)
Definition: fd.c:2572
void * palloc(Size size)
Definition: mcxt.c:1062
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:234
#define relpath(rnode, forknum)
Definition: relpath.h:87
char * DataDir
Definition: globals.c:65
#define BACKUP_LABEL_FILE
Definition: xlog.h:398
int pg_fsync(int fd)
Definition: fd.c:352
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
int FreeDir(DIR *dir)
Definition: fd.c:2752
#define stat
Definition: win32_port.h:275
void RequestCheckpoint(int flags)
Definition: checkpointer.c:927
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ do_pg_stop_backup()

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

Definition at line 11267 of file xlog.c.

References AllocateFile(), Assert, BACKUP_LABEL_FILE, backup_started_in_recovery, BackupHistoryFileName, BackupHistoryFilePath, BoolGetDatum, CHECK_FOR_INTERRUPTS, CleanupBackupHistory(), DEBUG1, durable_unlink(), ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, EXCLUSIVE_BACKUP_IN_PROGRESS, EXCLUSIVE_BACKUP_NONE, EXCLUSIVE_BACKUP_STOPPING, XLogCtlInsert::exclusiveBackupState, XLogCtlInsert::forcePageWrites, fprintf, FreeFile(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::lastFpwDisableRecPtr, log_timezone, LSN_FORMAT_ARGS, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXFNAMELEN, MAXPGPATH, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, XLogCtlInsert::nonExclusiveBackups, NOTICE, palloc(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, pg_localtime(), pg_stop_backup_callback(), pg_strftime(), pg_usleep(), pgstat_report_wait_end(), pgstat_report_wait_start(), RecoveryInProgress(), remaining, RequestXLogSwitch(), SESSION_BACKUP_NONE, sessionBackupState, SpinLockAcquire, SpinLockRelease, stat::st_size, stat, TABLESPACE_MAP, ThisTimeLineID, WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE, wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, XLByteToPrevSeg, XLByteToSeg, XLOG_BACKUP_END, XLogArchiveIsBusy(), XLogArchivingActive, XLogArchivingAlways, XLogBeginInsert(), XLogFileName, XLogInsert(), XLogIsNeeded, and XLogRegisterData().

Referenced by perform_base_backup(), pg_stop_backup(), and pg_stop_backup_v2().

11268 {
11269  bool exclusive = (labelfile == NULL);
11270  bool backup_started_in_recovery = false;
11271  XLogRecPtr startpoint;
11272  XLogRecPtr stoppoint;
11273  TimeLineID stoptli;
11274  pg_time_t stamp_time;
11275  char strfbuf[128];
11276  char histfilepath[MAXPGPATH];
11277  char startxlogfilename[MAXFNAMELEN];
11278  char stopxlogfilename[MAXFNAMELEN];
11279  char lastxlogfilename[MAXFNAMELEN];
11280  char histfilename[MAXFNAMELEN];
11281  char backupfrom[20];
11282  XLogSegNo _logSegNo;
11283  FILE *lfp;
11284  FILE *fp;
11285  char ch;
11286  int seconds_before_warning;
11287  int waits = 0;
11288  bool reported_waiting = false;
11289  char *remaining;
11290  char *ptr;
11291  uint32 hi,
11292  lo;
11293 
11294  backup_started_in_recovery = RecoveryInProgress();
11295 
11296  /*
11297  * Currently only non-exclusive backup can be taken during recovery.
11298  */
11299  if (backup_started_in_recovery && exclusive)
11300  ereport(ERROR,
11301  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11302  errmsg("recovery is in progress"),
11303  errhint("WAL control functions cannot be executed during recovery.")));
11304 
11305  /*
11306  * During recovery, we don't need to check WAL level. Because, if WAL
11307  * level is not sufficient, it's impossible to get here during recovery.
11308  */
11309  if (!backup_started_in_recovery && !XLogIsNeeded())
11310  ereport(ERROR,
11311  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11312  errmsg("WAL level not sufficient for making an online backup"),
11313  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
11314 
11315  if (exclusive)
11316  {
11317  /*
11318  * At first, mark that we're now stopping an exclusive backup, to
11319  * ensure that there are no other sessions currently running
11320  * pg_start_backup() or pg_stop_backup().
11321  */
11324  {
11326  ereport(ERROR,
11327  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11328  errmsg("exclusive backup not in progress")));
11329  }
11332 
11333  /*
11334  * Remove backup_label. In case of failure, the state for an exclusive
11335  * backup is switched back to in-progress.
11336  */
11338  {
11339  /*
11340  * Read the existing label file into memory.
11341  */
11342  struct stat statbuf;
11343  int r;
11344 
11345  if (stat(BACKUP_LABEL_FILE, &statbuf))
11346  {
11347  /* should not happen per the upper checks */
11348  if (errno != ENOENT)
11349  ereport(ERROR,
11351  errmsg("could not stat file \"%s\": %m",
11352  BACKUP_LABEL_FILE)));
11353  ereport(ERROR,
11354  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11355  errmsg("a backup is not in progress")));
11356  }
11357 
11358  lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
11359  if (!lfp)
11360  {
11361  ereport(ERROR,
11363  errmsg("could not read file \"%s\": %m",
11364  BACKUP_LABEL_FILE)));
11365  }
11366  labelfile = palloc(statbuf.st_size + 1);
11367  r = fread(labelfile, statbuf.st_size, 1, lfp);
11368  labelfile[statbuf.st_size] = '\0';
11369 
11370  /*
11371  * Close and remove the backup label file
11372  */
11373  if (r != 1 || ferror(lfp) || FreeFile(lfp))
11374  ereport(ERROR,
11376  errmsg("could not read file \"%s\": %m",
11377  BACKUP_LABEL_FILE)));
11379 
11380  /*
11381  * Remove tablespace_map file if present, it is created only if
11382  * there are tablespaces.
11383  */
11385  }
11387  }
11388 
11389  /*
11390  * OK to update backup counters, forcePageWrites and session-level lock.
11391  *
11392  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
11393  * Otherwise they can be updated inconsistently, and which might cause
11394  * do_pg_abort_backup() to fail.
11395  */
11397  if (exclusive)
11398  {
11400  }
11401  else
11402  {
11403  /*
11404  * The user-visible pg_start/stop_backup() functions that operate on
11405  * exclusive backups can be called at any time, but for non-exclusive
11406  * backups, it is expected that each do_pg_start_backup() call is
11407  * matched by exactly one do_pg_stop_backup() call.
11408  */
11411  }
11412 
11415  {
11416  XLogCtl->Insert.forcePageWrites = false;
11417  }
11418 
11419  /*
11420  * Clean up session-level lock.
11421  *
11422  * You might think that WALInsertLockRelease() can be called before
11423  * cleaning up session-level lock because session-level lock doesn't need
11424  * to be protected with WAL insertion lock. But since
11425  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
11426  * cleaned up before it.
11427  */
11429 
11431 
11432  /*
11433  * Read and parse the START WAL LOCATION line (this code is pretty crude,
11434  * but we are not expecting any variability in the file format).
11435  */
11436  if (sscanf(labelfile, "START WAL LOCATION: %X/%X (file %24s)%c",
11437  &hi, &lo, startxlogfilename,
11438  &ch) != 4 || ch != '\n')
11439  ereport(ERROR,
11440  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11441  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
11442  startpoint = ((uint64) hi) << 32 | lo;
11443  remaining = strchr(labelfile, '\n') + 1; /* %n is not portable enough */
11444 
11445  /*
11446  * Parse the BACKUP FROM line. If we are taking an online backup from the
11447  * standby, we confirm that the standby has not been promoted during the
11448  * backup.
11449  */
11450  ptr = strstr(remaining, "BACKUP FROM:");
11451  if (!ptr || sscanf(ptr, "BACKUP FROM: %19s\n", backupfrom) != 1)
11452  ereport(ERROR,
11453  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11454  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
11455  if (strcmp(backupfrom, "standby") == 0 && !backup_started_in_recovery)
11456  ereport(ERROR,
11457  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11458  errmsg("the standby was promoted during online backup"),
11459  errhint("This means that the backup being taken is corrupt "
11460  "and should not be used. "
11461  "Try taking another online backup.")));
11462 
11463  /*
11464  * During recovery, we don't write an end-of-backup record. We assume that
11465  * pg_control was backed up last and its minimum recovery point can be
11466  * available as the backup end location. Since we don't have an
11467  * end-of-backup record, we use the pg_control value to check whether
11468  * we've reached the end of backup when starting recovery from this
11469  * backup. We have no way of checking if pg_control wasn't backed up last
11470  * however.
11471  *
11472  * We don't force a switch to new WAL file but it is still possible to
11473  * wait for all the required files to be archived if waitforarchive is
11474  * true. This is okay if we use the backup to start a standby and fetch
11475  * the missing WAL using streaming replication. But in the case of an
11476  * archive recovery, a user should set waitforarchive to true and wait for
11477  * them to be archived to ensure that all the required files are
11478  * available.
11479  *
11480  * We return the current minimum recovery point as the backup end
11481  * location. Note that it can be greater than the exact backup end
11482  * location if the minimum recovery point is updated after the backup of
11483  * pg_control. This is harmless for current uses.
11484  *
11485  * XXX currently a backup history file is for informational and debug
11486  * purposes only. It's not essential for an online backup. Furthermore,
11487  * even if it's created, it will not be archived during recovery because
11488  * an archiver is not invoked. So it doesn't seem worthwhile to write a
11489  * backup history file during recovery.
11490  */
11491  if (backup_started_in_recovery)
11492  {
11493  XLogRecPtr recptr;
11494 
11495  /*
11496  * Check to see if all WAL replayed during online backup contain
11497  * full-page writes.
11498  */
11500  recptr = XLogCtl->lastFpwDisableRecPtr;
11502 
11503  if (startpoint <= recptr)
11504  ereport(ERROR,
11505  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11506  errmsg("WAL generated with full_page_writes=off was replayed "
11507  "during online backup"),
11508  errhint("This means that the backup being taken on the standby "
11509  "is corrupt and should not be used. "
11510  "Enable full_page_writes and run CHECKPOINT on the primary, "
11511  "and then try an online backup again.")));
11512 
11513 
11514  LWLockAcquire(ControlFileLock, LW_SHARED);
11515  stoppoint = ControlFile->minRecoveryPoint;
11516  stoptli = ControlFile->minRecoveryPointTLI;
11517  LWLockRelease(ControlFileLock);
11518  }
11519  else
11520  {
11521  /*
11522  * Write the backup-end xlog record
11523  */
11524  XLogBeginInsert();
11525  XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
11526  stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
11527  stoptli = ThisTimeLineID;
11528 
11529  /*
11530  * Force a switch to a new xlog segment file, so that the backup is
11531  * valid as soon as archiver moves out the current segment file.
11532  */
11533  RequestXLogSwitch(false);
11534 
11535  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11536  XLogFileName(stopxlogfilename, stoptli, _logSegNo, wal_segment_size);
11537 
11538  /* Use the log timezone here, not the session timezone */
11539  stamp_time = (pg_time_t) time(NULL);
11540  pg_strftime(strfbuf, sizeof(strfbuf),
11541  "%Y-%m-%d %H:%M:%S %Z",
11542  pg_localtime(&stamp_time, log_timezone));
11543 
11544  /*
11545  * Write the backup history file
11546  */
11547  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11548  BackupHistoryFilePath(histfilepath, stoptli, _logSegNo,
11549  startpoint, wal_segment_size);
11550  fp = AllocateFile(histfilepath, "w");
11551  if (!fp)
11552  ereport(ERROR,
11554  errmsg("could not create file \"%s\": %m",
11555  histfilepath)));
11556  fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
11557  LSN_FORMAT_ARGS(startpoint), startxlogfilename);
11558  fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
11559  LSN_FORMAT_ARGS(stoppoint), stopxlogfilename);
11560 
11561  /*
11562  * Transfer remaining lines including label and start timeline to
11563  * history file.
11564  */
11565  fprintf(fp, "%s", remaining);
11566  fprintf(fp, "STOP TIME: %s\n", strfbuf);
11567  fprintf(fp, "STOP TIMELINE: %u\n", stoptli);
11568  if (fflush(fp) || ferror(fp) || FreeFile(fp))
11569  ereport(ERROR,
11571  errmsg("could not write file \"%s\": %m",
11572  histfilepath)));
11573 
11574  /*
11575  * Clean out any no-longer-needed history files. As a side effect,
11576  * this will post a .ready file for the newly created history file,
11577  * notifying the archiver that history file may be archived
11578  * immediately.
11579  */
11581  }
11582 
11583  /*
11584  * If archiving is enabled, wait for all the required WAL files to be
11585  * archived before returning. If archiving isn't enabled, the required WAL
11586  * needs to be transported via streaming replication (hopefully with
11587  * wal_keep_size set high enough), or some more exotic mechanism like
11588  * polling and copying files from pg_wal with script. We have no knowledge
11589  * of those mechanisms, so it's up to the user to ensure that he gets all
11590  * the required WAL.
11591  *
11592  * We wait until both the last WAL file filled during backup and the
11593  * history file have been archived, and assume that the alphabetic sorting
11594  * property of the WAL files ensures any earlier WAL files are safely
11595  * archived as well.
11596  *
11597  * We wait forever, since archive_command is supposed to work and we
11598  * assume the admin wanted his backup to work completely. If you don't
11599  * wish to wait, then either waitforarchive should be passed in as false,
11600  * or you can set statement_timeout. Also, some notices are issued to
11601  * clue in anyone who might be doing this interactively.
11602  */
11603 
11604  if (waitforarchive &&
11605  ((!backup_started_in_recovery && XLogArchivingActive()) ||
11606  (backup_started_in_recovery && XLogArchivingAlways())))
11607  {
11608  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11609  XLogFileName(lastxlogfilename, stoptli, _logSegNo, wal_segment_size);
11610 
11611  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11612  BackupHistoryFileName(histfilename, stoptli, _logSegNo,
11613  startpoint, wal_segment_size);
11614 
11615  seconds_before_warning = 60;
11616  waits = 0;
11617 
11618  while (XLogArchiveIsBusy(lastxlogfilename) ||
11619  XLogArchiveIsBusy(histfilename))
11620  {
11622 
11623  if (!reported_waiting && waits > 5)
11624  {
11625  ereport(NOTICE,
11626  (errmsg("base backup done, waiting for required WAL segments to be archived")));
11627  reported_waiting = true;
11628  }
11629 
11631  pg_usleep(1000000L);
11633 
11634  if (++waits >= seconds_before_warning)
11635  {
11636  seconds_before_warning *= 2; /* This wraps in >10 years... */
11637  ereport(WARNING,
11638  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
11639  waits),
11640  errhint("Check that your archive_command is executing properly. "
11641  "You can safely cancel this backup, "
11642  "but the database backup will not be usable without all the WAL segments.")));
11643  }
11644  }
11645 
11646  ereport(NOTICE,
11647  (errmsg("all required WAL segments have been archived")));
11648  }
11649  else if (waitforarchive)
11650  ereport(NOTICE,
11651  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
11652 
11653  /*
11654  * We're done. As a convenience, return the ending WAL location.
11655  */
11656  if (stoptli_p)
11657  *stoptli_p = stoptli;
11658  return stoppoint;
11659 }
int remaining
Definition: informix.c:667
size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm *tm)
Definition: strftime.c:128
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:9896
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:1156
uint32 TimeLineID
Definition: xlogdefs.h:59
int64 pg_time_t
Definition: pgtime.h:23
static void pgstat_report_wait_end(void)
Definition: wait_event.h:277
static void WALInsertLockRelease(void)
Definition: xlog.c:1744
int wal_segment_size
Definition: xlog.c:121
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:735
static SessionBackupState sessionBackupState
Definition: xlog.c:534
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogIsNeeded()
Definition: xlog.h:201
slock_t info_lck
Definition: xlog.c:737
int errcode(int sqlerrcode)
Definition: elog.c:698
XLogCtlInsert Insert
Definition: xlog.c:600
#define BackupHistoryFileName(fname, tli, logSegNo, startpoint, wal_segsz_bytes)
bool RecoveryInProgress(void)
Definition: xlog.c:8237
static bool backup_started_in_recovery
Definition: basebackup.c:88
#define fprintf
Definition: port.h:220
pg_tz * log_timezone
Definition: pgtz.c:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define TABLESPACE_MAP
Definition: xlog.h:401
#define SpinLockAcquire(lock)
Definition: spin.h:62
void pg_usleep(long microsec)
Definition: signal.c:53
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define XLogArchivingAlways()
Definition: xlog.h:193
bool forcePageWrites
Definition: xlog.c:574
#define ERROR
Definition: elog.h:46
static void CleanupBackupHistory(void)
Definition: xlog.c:4340
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:48
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
unsigned int uint32
Definition: c.h:441
#define XLOG_BACKUP_END
Definition: pg_control.h:72
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:261
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:586
#define MAXFNAMELEN
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
#define SpinLockRelease(lock)
Definition: spin.h:64
#define BackupHistoryFilePath(path, tli, logSegNo, startpoint, wal_segsz_bytes)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:585
uintptr_t Datum
Definition: postgres.h:411
static ControlFileData * ControlFile
Definition: xlog.c:748
#define BoolGetDatum(X)
Definition: postgres.h:446
TimeLineID ThisTimeLineID
Definition: xlog.c:196
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:626
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define XLogArchivingActive()
Definition: xlog.h:190
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1715
static XLogCtlData * XLogCtl
Definition: xlog.c:740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
static void pg_stop_backup_callback(int code, Datum arg)
Definition: xlog.c:11228
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1342
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:782
int FreeFile(FILE *file)
Definition: fd.c:2572
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define BACKUP_LABEL_FILE
Definition: xlog.h:398
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:102
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define stat
Definition: win32_port.h:275
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ emode_for_corrupt_record()

static int emode_for_corrupt_record ( int  emode,
XLogRecPtr  RecPtr 
)
static

Definition at line 12818 of file xlog.c.

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

12819 {
12820  static XLogRecPtr lastComplaint = 0;
12821 
12822  if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
12823  {
12824  if (RecPtr == lastComplaint)
12825  emode = DEBUG1;
12826  else
12827  lastComplaint = RecPtr;
12828  }
12829  return emode;
12830 }
#define DEBUG1
Definition: elog.h:25
static XLogSource readSource
Definition: xlog.c:823
#define LOG
Definition: elog.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ exitArchiveRecovery()

static void exitArchiveRecovery ( TimeLineID  endTLI,
XLogRecPtr  endOfLog 
)
static

Definition at line 5599 of file xlog.c.

References Assert, close, durable_unlink(), ereport, errcode_for_file_access(), errmsg(), ERROR, FATAL, fd(), InArchiveRecovery, InvalidXLogRecPtr, LOG, MAXFNAMELEN, readFile, RECOVERY_SIGNAL_FILE, recovery_signal_file_found, STANDBY_SIGNAL_FILE, standby_signal_file_found, ThisTimeLineID, UpdateMinRecoveryPoint(), wal_segment_size, XLByteToPrevSeg, XLByteToSeg, XLogArchiveCleanup(), XLogFileCopy(), XLogFileInit(), XLogFileName, and XLogSegmentOffset.

Referenced by StartupXLOG().

5600 {
5601  char xlogfname[MAXFNAMELEN];
5602  XLogSegNo endLogSegNo;
5603  XLogSegNo startLogSegNo;
5604 
5605  /* we always switch to a new timeline after archive recovery */
5606  Assert(endTLI != ThisTimeLineID);
5607 
5608  /*
5609  * We are no longer in archive recovery state.
5610  */
5611  InArchiveRecovery = false;
5612 
5613  /*
5614  * Update min recovery point one last time.
5615  */
5617 
5618  /*
5619  * If the ending log segment is still open, close it (to avoid problems on
5620  * Windows with trying to rename or delete an open file).
5621  */
5622  if (readFile >= 0)
5623  {
5624  close(readFile);
5625  readFile = -1;
5626  }
5627 
5628  /*
5629  * Calculate the last segment on the old timeline, and the first segment
5630  * on the new timeline. If the switch happens in the middle of a segment,
5631  * they are the same, but if the switch happens exactly at a segment
5632  * boundary, startLogSegNo will be endLogSegNo + 1.
5633  */
5634  XLByteToPrevSeg(endOfLog, endLogSegNo, wal_segment_size);
5635  XLByteToSeg(endOfLog, startLogSegNo, wal_segment_size);
5636 
5637  /*
5638  * Initialize the starting WAL segment for the new timeline. If the switch
5639  * happens in the middle of a segment, copy data from the last WAL segment
5640  * of the old timeline up to the switch point, to the starting WAL segment
5641  * on the new timeline.
5642  */
5643  if (endLogSegNo == startLogSegNo)
5644  {
5645  /*
5646  * Make a copy of the file on the new timeline.
5647  *
5648  * Writing WAL isn't allowed yet, so there are no locking
5649  * considerations. But we should be just as tense as XLogFileInit to
5650  * avoid emplacing a bogus file.
5651  */
5652  XLogFileCopy(endLogSegNo, endTLI, endLogSegNo,
5653  XLogSegmentOffset(endOfLog, wal_segment_size));
5654  }
5655  else
5656  {
5657  /*
5658  * The switch happened at a segment boundary, so just create the next
5659  * segment on the new timeline.
5660  */
5661  bool use_existent = true;
5662  int fd;
5663 
5664  fd = XLogFileInit(startLogSegNo, &use_existent, true);
5665 
5666  if (close(fd) != 0)
5667  {
5668  char xlogfname[MAXFNAMELEN];
5669  int save_errno = errno;
5670 
5671  XLogFileName(xlogfname, ThisTimeLineID, startLogSegNo,
5673  errno = save_errno;
5674  ereport(ERROR,
5676  errmsg("could not close file \"%s\": %m", xlogfname)));
5677  }
5678  }
5679 
5680  /*
5681  * Let's just make real sure there are not .ready or .done flags posted
5682  * for the new segment.
5683  */
5684  XLogFileName(xlogfname, ThisTimeLineID, startLogSegNo, wal_segment_size);
5685  XLogArchiveCleanup(xlogfname);
5686 
5687