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/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 "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/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
 
struct  XLogPageReadPrivate
 

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)   (x / ((segsize) / (1024 * 1024)))
 
#define RecoveryRequiresIntParameter(param_name, currValue, minValue)
 

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
 
typedef struct XLogPageReadPrivate XLogPageReadPrivate
 

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 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 int XLogPageRead (XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
 
static bool WaitForWALToBecomeAvailable (XLogRecPtr RecPtr, bool randAccess, bool fetching_ckpt, XLogRecPtr tliRecPtr)
 
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, XLogRecPtr lastredoptr, XLogRecPtr endptr)
 
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_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)
 
bool RecoveryIsPaused (void)
 
void SetRecoveryPause (bool recoveryPause)
 
TimestampTz GetLatestXTime (void)
 
TimestampTz GetCurrentChunkReplayStartTime (void)
 
void GetXLogReceiptTime (TimestampTz *rtime, bool *fromStream)
 
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)
 
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, bool infotbssize, bool needtblspcmapfile)
 
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_segments = 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_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 * master_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 bool fast_promote = 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 XLogSegNo readSegNo = 0
 
static uint32 readOff = 0
 
static uint32 readLen = 0
 
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 
)    (x / ((segsize) / (1024 * 1024)))

◆ INSERT_FREESPACE

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

Definition at line 744 of file xlog.c.

Referenced by CopyXLogRecordToWAL(), and CreateCheckPoint().

◆ NextBufIdx

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

Definition at line 748 of file xlog.c.

Referenced by XLogWrite().

◆ NUM_XLOGINSERT_LOCKS

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 86 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 85 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ RecoveryRequiresIntParameter

#define RecoveryRequiresIntParameter (   param_name,
  currValue,
  minValue 
)
Value:
do { \
if ((currValue) < (minValue)) \
ereport(ERROR, \
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
errmsg("hot standby is not possible because %s = %d is a lower setting than on the master server (its value was %d)", \
param_name, \
currValue, \
minValue))); \
} while(0)
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
int errmsg(const char *fmt,...)
Definition: elog.c:824

Definition at line 6235 of file xlog.c.

Referenced by CheckRequiredParameterValues().

◆ UsableBytesInPage

#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)

◆ XLogRecPtrToBufIdx

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

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

◆ XLogPageReadPrivate

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

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 780 of file xlog.c.

781 {
782  XLOG_FROM_ANY = 0, /* request to read WAL from any source */
783  XLOG_FROM_ARCHIVE, /* restored using restore_command */
784  XLOG_FROM_PG_WAL, /* existing file in pg_wal */
785  XLOG_FROM_STREAM /* streamed from master */
786 } XLogSource;
XLogSource
Definition: xlog.c:780

Function Documentation

◆ AdvanceXLInsertBuffer()

static void AdvanceXLInsertBuffer ( XLogRecPtr  upto,
bool  opportunistic 
)
static

Definition at line 2122 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, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, XLogCtlData::pages, pg_write_barrier, SpinLockAcquire, SpinLockRelease, ControlFileData::system_identifier, ThisTimeLineID, WaitXLogInsertionsToFinish(), wal_segment_size, 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().

2123 {
2125  int nextidx;
2126  XLogRecPtr OldPageRqstPtr;
2127  XLogwrtRqst WriteRqst;
2128  XLogRecPtr NewPageEndPtr = InvalidXLogRecPtr;
2129  XLogRecPtr NewPageBeginPtr;
2130  XLogPageHeader NewPage;
2131  int npages = 0;
2132 
2133  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2134 
2135  /*
2136  * Now that we have the lock, check if someone initialized the page
2137  * already.
2138  */
2139  while (upto >= XLogCtl->InitializedUpTo || opportunistic)
2140  {
2142 
2143  /*
2144  * Get ending-offset of the buffer page we need to replace (this may
2145  * be zero if the buffer hasn't been used yet). Fall through if it's
2146  * already written out.
2147  */
2148  OldPageRqstPtr = XLogCtl->xlblocks[nextidx];
2149  if (LogwrtResult.Write < OldPageRqstPtr)
2150  {
2151  /*
2152  * Nope, got work to do. If we just want to pre-initialize as much
2153  * as we can without flushing, give up now.
2154  */
2155  if (opportunistic)
2156  break;
2157 
2158  /* Before waiting, get info_lck and update LogwrtResult */
2160  if (XLogCtl->LogwrtRqst.Write < OldPageRqstPtr)
2161  XLogCtl->LogwrtRqst.Write = OldPageRqstPtr;
2164 
2165  /*
2166  * Now that we have an up-to-date LogwrtResult value, see if we
2167  * still need to write it or if someone else already did.
2168  */
2169  if (LogwrtResult.Write < OldPageRqstPtr)
2170  {
2171  /*
2172  * Must acquire write lock. Release WALBufMappingLock first,
2173  * to make sure that all insertions that we need to wait for
2174  * can finish (up to this same position). Otherwise we risk
2175  * deadlock.
2176  */
2177  LWLockRelease(WALBufMappingLock);
2178 
2179  WaitXLogInsertionsToFinish(OldPageRqstPtr);
2180 
2181  LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
2182 
2184  if (LogwrtResult.Write >= OldPageRqstPtr)
2185  {
2186  /* OK, someone wrote it already */
2187  LWLockRelease(WALWriteLock);
2188  }
2189  else
2190  {
2191  /* Have to write it ourselves */
2192  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
2193  WriteRqst.Write = OldPageRqstPtr;
2194  WriteRqst.Flush = 0;
2195  XLogWrite(WriteRqst, false);
2196  LWLockRelease(WALWriteLock);
2197  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
2198  }
2199  /* Re-acquire WALBufMappingLock and retry */
2200  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2201  continue;
2202  }
2203  }
2204 
2205  /*
2206  * Now the next buffer slot is free and we can set it up to be the
2207  * next output page.
2208  */
2209  NewPageBeginPtr = XLogCtl->InitializedUpTo;
2210  NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
2211 
2212  Assert(XLogRecPtrToBufIdx(NewPageBeginPtr) == nextidx);
2213 
2214  NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
2215 
2216  /*
2217  * Be sure to re-zero the buffer so that bytes beyond what we've
2218  * written will look like zeroes and not valid XLOG records...
2219  */
2220  MemSet((char *) NewPage, 0, XLOG_BLCKSZ);
2221 
2222  /*
2223  * Fill the new page's header
2224  */
2225  NewPage->xlp_magic = XLOG_PAGE_MAGIC;
2226 
2227  /* NewPage->xlp_info = 0; */ /* done by memset */
2228  NewPage->xlp_tli = ThisTimeLineID;
2229  NewPage->xlp_pageaddr = NewPageBeginPtr;
2230 
2231  /* NewPage->xlp_rem_len = 0; */ /* done by memset */
2232 
2233  /*
2234  * If online backup is not in progress, mark the header to indicate
2235  * that WAL records beginning in this page have removable backup
2236  * blocks. This allows the WAL archiver to know whether it is safe to
2237  * compress archived WAL data by transforming full-block records into
2238  * the non-full-block format. It is sufficient to record this at the
2239  * page level because we force a page switch (in fact a segment
2240  * switch) when starting a backup, so the flag will be off before any
2241  * records can be written during the backup. At the end of a backup,
2242  * the last page will be marked as all unsafe when perhaps only part
2243  * is unsafe, but at worst the archiver would miss the opportunity to
2244  * compress a few records.
2245  */
2246  if (!Insert->forcePageWrites)
2247  NewPage->xlp_info |= XLP_BKP_REMOVABLE;
2248 
2249  /*
2250  * If first page of an XLOG segment file, make it a long header.
2251  */
2252  if ((XLogSegmentOffset(NewPage->xlp_pageaddr, wal_segment_size)) == 0)
2253  {
2254  XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
2255 
2256  NewLongPage->xlp_sysid = ControlFile->system_identifier;
2257  NewLongPage->xlp_seg_size = wal_segment_size;
2258  NewLongPage->xlp_xlog_blcksz = XLOG_BLCKSZ;
2259  NewPage->xlp_info |= XLP_LONG_HEADER;
2260  }
2261 
2262  /*
2263  * Make sure the initialization of the page becomes visible to others
2264  * before the xlblocks update. GetXLogBuffer() reads xlblocks without
2265  * holding a lock.
2266  */
2267  pg_write_barrier();
2268 
2269  *((volatile XLogRecPtr *) &XLogCtl->xlblocks[nextidx]) = NewPageEndPtr;
2270 
2271  XLogCtl->InitializedUpTo = NewPageEndPtr;
2272 
2273  npages++;
2274  }
2275  LWLockRelease(WALBufMappingLock);
2276 
2277 #ifdef WAL_DEBUG
2278  if (XLOG_DEBUG && npages > 0)
2279  {
2280  elog(DEBUG1, "initialized %d pages, up to %X/%X",
2281  npages, (uint32) (NewPageEndPtr >> 32), (uint32) NewPageEndPtr);
2282  }
2283 #endif
2284 }
XLogRecPtr InitializedUpTo
Definition: xlog.c:636
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
int wal_segment_size
Definition: xlog.c:116
XLogRecPtr * xlblocks
Definition: xlog.c:644
static XLogwrtResult LogwrtResult
Definition: xlog.c:774
slock_t info_lck
Definition: xlog.c:727
#define MemSet(start, val, len)
Definition: c.h:971
static XLogRecPtr WaitXLogInsertionsToFinish(XLogRecPtr upto)
Definition: xlog.c:1785
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
XLogCtlInsert Insert
Definition: xlog.c:601
XLogRecPtr Flush
Definition: xlog.c:444
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define XLP_BKP_REMOVABLE
Definition: xlog_internal.h:81
bool forcePageWrites
Definition: xlog.c:575
uint64 system_identifier
Definition: pg_control.h:106
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
XLogwrtResult LogwrtResult
Definition: xlog.c:624
unsigned int uint32
Definition: c.h:367
static void Insert(File file)
Definition: fd.c:1172
TimeLineID xlp_tli
Definition: xlog_internal.h:40
static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
Definition: xlog.c:2412
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SpinLockRelease(lock)
Definition: spin.h:64
XLogRecPtr Write
Definition: xlog.c:443
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
static ControlFileData * ControlFile
Definition: xlog.c:738
XLogwrtRqst LogwrtRqst
Definition: xlog.c:604
TimeLineID ThisTimeLineID
Definition: xlog.c:191
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
size_t Size
Definition: c.h:466
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:755
XLogRecPtr Write
Definition: xlog.c:449
#define elog(elevel,...)
Definition: elog.h:214
#define pg_write_barrier()
Definition: atomics.h:159
char * pages
Definition: xlog.c:643

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 2327 of file xlog.c.

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

2328 {
2331 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2291
#define newval
double CheckPointCompletionTarget
Definition: checkpointer.c:148

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 2320 of file xlog.c.

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

2321 {
2324 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2291
int max_wal_size_mb
Definition: xlog.c:89
#define newval

◆ assign_xlog_sync_method()

void assign_xlog_sync_method ( int  new_sync_method,
void *  extra 
)

Definition at line 10339 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.

10340 {
10341  if (sync_method != new_sync_method)
10342  {
10343  /*
10344  * To ensure that no blocks escape unsynced, force an fsync on the
10345  * currently open log segment (if any). Also, if the open flag is
10346  * changing, close the log file so it will be reopened (with new flag
10347  * bit) at next use.
10348  */
10349  if (openLogFile >= 0)
10350  {
10352  if (pg_fsync(openLogFile) != 0)
10353  {
10354  char xlogfname[MAXFNAMELEN];
10355  int save_errno;
10356 
10357  save_errno = errno;
10360  errno = save_errno;
10361  ereport(PANIC,
10363  errmsg("could not fsync file \"%s\": %m", xlogfname)));
10364  }
10365 
10367  if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
10368  XLogFileClose();
10369  }
10370  }
10371 }
int wal_segment_size
Definition: xlog.c:116
static int get_sync_bit(int method)
Definition: xlog.c:10283
#define PANIC
Definition: elog.h:53
static XLogSegNo openLogSegNo
Definition: xlog.c:798
static void XLogFileClose(void)
Definition: xlog.c:3850
int errcode_for_file_access(void)
Definition: elog.c:633
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1380
#define MAXFNAMELEN
static int openLogFile
Definition: xlog.c:797
TimeLineID ThisTimeLineID
Definition: xlog.c:191
#define ereport(elevel,...)
Definition: elog.h:144
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1356
int sync_method
Definition: xlog.c:105
int errmsg(const char *fmt,...)
Definition: elog.c:824
int pg_fsync(int fd)
Definition: fd.c:343

◆ BackupInProgress()

bool BackupInProgress ( void  )

Definition at line 11759 of file xlog.c.

References BACKUP_LABEL_FILE, and stat.

Referenced by pg_is_in_backup(), and PostmasterStateMachine().

11760 {
11761  struct stat stat_buf;
11762 
11763  return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
11764 }
struct stat stat_buf
Definition: pg_standby.c:100
#define stat(a, b)
Definition: win32_port.h:255
#define BACKUP_LABEL_FILE
Definition: xlog.h:386

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 5193 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::nextFullXid, VariableCacheData::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, 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().

5194 {
5195  CheckPoint checkPoint;
5196  char *buffer;
5197  XLogPageHeader page;
5198  XLogLongPageHeader longpage;
5199  XLogRecord *record;
5200  char *recptr;
5201  bool use_existent;
5202  uint64 sysidentifier;
5203  struct timeval tv;
5204  pg_crc32c crc;
5205 
5206  /*
5207  * Select a hopefully-unique system identifier code for this installation.
5208  * We use the result of gettimeofday(), including the fractional seconds
5209  * field, as being about as unique as we can easily get. (Think not to
5210  * use random(), since it hasn't been seeded and there's no portable way
5211  * to seed it other than the system clock value...) The upper half of the
5212  * uint64 value is just the tv_sec part, while the lower half contains the
5213  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
5214  * PID for a little extra uniqueness. A person knowing this encoding can
5215  * determine the initialization time of the installation, which could
5216  * perhaps be useful sometimes.
5217  */
5218  gettimeofday(&tv, NULL);
5219  sysidentifier = ((uint64) tv.tv_sec) << 32;
5220  sysidentifier |= ((uint64) tv.tv_usec) << 12;
5221  sysidentifier |= getpid() & 0xFFF;
5222 
5223  /* First timeline ID is always 1 */
5224  ThisTimeLineID = 1;
5225 
5226  /* page buffer must be aligned suitably for O_DIRECT */
5227  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
5228  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
5229  memset(page, 0, XLOG_BLCKSZ);
5230 
5231  /*
5232  * Set up information for the initial checkpoint record
5233  *
5234  * The initial checkpoint record is written to the beginning of the WAL
5235  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
5236  * used, so that we can use 0/0 to mean "before any valid WAL segment".
5237  */
5238  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
5239  checkPoint.ThisTimeLineID = ThisTimeLineID;
5240  checkPoint.PrevTimeLineID = ThisTimeLineID;
5241  checkPoint.fullPageWrites = fullPageWrites;
5242  checkPoint.nextFullXid =
5244  checkPoint.nextOid = FirstBootstrapObjectId;
5245  checkPoint.nextMulti = FirstMultiXactId;
5246  checkPoint.nextMultiOffset = 0;
5247  checkPoint.oldestXid = FirstNormalTransactionId;
5248  checkPoint.oldestXidDB = TemplateDbOid;
5249  checkPoint.oldestMulti = FirstMultiXactId;
5250  checkPoint.oldestMultiDB = TemplateDbOid;
5253  checkPoint.time = (pg_time_t) time(NULL);
5255 
5257  ShmemVariableCache->nextOid = checkPoint.nextOid;
5259  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5260  AdvanceOldestClogXid(checkPoint.oldestXid);
5261  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5262  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5264 
5265  /* Set up the XLOG page header */
5266  page->xlp_magic = XLOG_PAGE_MAGIC;
5267  page->xlp_info = XLP_LONG_HEADER;
5268  page->xlp_tli = ThisTimeLineID;
5270  longpage = (XLogLongPageHeader) page;
5271  longpage->xlp_sysid = sysidentifier;
5272  longpage->xlp_seg_size = wal_segment_size;
5273  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
5274 
5275  /* Insert the initial checkpoint record */
5276  recptr = ((char *) page + SizeOfXLogLongPHD);
5277  record = (XLogRecord *) recptr;
5278  record->xl_prev = 0;
5279  record->xl_xid = InvalidTransactionId;
5280  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
5282  record->xl_rmid = RM_XLOG_ID;
5283  recptr += SizeOfXLogRecord;
5284  /* fill the XLogRecordDataHeaderShort struct */
5285  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
5286  *(recptr++) = sizeof(checkPoint);
5287  memcpy(recptr, &checkPoint, sizeof(checkPoint));
5288  recptr += sizeof(checkPoint);
5289  Assert(recptr - (char *) record == record->xl_tot_len);
5290 
5291  INIT_CRC32C(crc);
5292  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
5293  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
5294  FIN_CRC32C(crc);
5295  record->xl_crc = crc;
5296 
5297  /* Create first XLOG segment file */
5298  use_existent = false;
5299  openLogFile = XLogFileInit(1, &use_existent, false);
5300 
5301  /*
5302  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
5303  * close the file again in a moment.
5304  */
5305 
5306  /* Write the first page with the initial record */
5307  errno = 0;
5309  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
5310  {
5311  /* if write didn't set errno, assume problem is no disk space */
5312  if (errno == 0)
5313  errno = ENOSPC;
5314  ereport(PANIC,
5316  errmsg("could not write bootstrap write-ahead log file: %m")));
5317  }
5319 
5321  if (pg_fsync(openLogFile) != 0)
5322  ereport(PANIC,
5324  errmsg("could not fsync bootstrap write-ahead log file: %m")));
5326 
5327  if (close(openLogFile) != 0)
5328  ereport(PANIC,
5330  errmsg("could not close bootstrap write-ahead log file: %m")));
5331 
5332  openLogFile = -1;
5333 
5334  /* Now create pg_control */
5335  InitControlFile(sysidentifier);
5336  ControlFile->time = checkPoint.time;
5337  ControlFile->checkPoint = checkPoint.redo;
5338  ControlFile->checkPointCopy = checkPoint;
5339 
5340  /* some additional ControlFile fields are set in WriteControlFile() */
5341  WriteControlFile();
5342 
5343  /* Bootstrap the commit log, too */
5344  BootStrapCLOG();
5348 
5349  pfree(buffer);
5350 
5351  /*
5352  * Force control file to be read - in contrast to normal processing we'd
5353  * otherwise never run the checks and GUC related initializations therein.
5354  */
5355  ReadControlFile();
5356 }
static void WriteControlFile(void)
Definition: xlog.c:4610
#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
int wal_segment_size
Definition: xlog.c:116
pg_time_t time
Definition: pg_control.h:128
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:848
uint32 oidCount
Definition: transam.h:173
#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:3251
void BootStrapMultiXact(void)
Definition: multixact.c:1868
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:4575
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
FullTransactionId nextFullXid
Definition: transam.h:178
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:53
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
bool fullPageWrites
Definition: xlog.c:97
void BootStrapSUBTRANS(void)
Definition: subtrans.c:212
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:313
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1056
#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:4701
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
int errcode_for_file_access(void)
Definition: elog.c:633
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
#define FirstBootstrapObjectId
Definition: transam.h:154
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1380
#define FirstMultiXactId
Definition: multixact.h:24
TimeLineID xlp_tli
Definition: xlog_internal.h:40
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:797
static ControlFileData * ControlFile
Definition: xlog.c:738
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2196
TimeLineID ThisTimeLineID
Definition: xlog.c:191
Oid nextOid
Definition: pg_control.h:44
#define ereport(elevel,...)
Definition: elog.h:144
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:684
bool fullPageWrites
Definition: pg_control.h:42
void BootStrapCLOG(void)
Definition: clog.c:705
#define Assert(condition)
Definition: c.h:738
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1356
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:330
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:45
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:69
#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:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int pg_fsync(int fd)
Definition: fd.c:343
#define close(a)
Definition: win32.h:12
void BootStrapCommitTs(void)
Definition: commit_ts.c:523
#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:661
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2162

◆ CalculateCheckpointSegments()

static void CalculateCheckpointSegments ( void  )
static

Definition at line 2291 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().

2292 {
2293  double target;
2294 
2295  /*-------
2296  * Calculate the distance at which to trigger a checkpoint, to avoid
2297  * exceeding max_wal_size_mb. This is based on two assumptions:
2298  *
2299  * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
2300  * WAL for two checkpoint cycles to allow us to recover from the
2301  * secondary checkpoint if the first checkpoint failed, though we
2302  * only did this on the master anyway, not on standby. Keeping just
2303  * one checkpoint simplifies processing and reduces disk space in
2304  * many smaller databases.)
2305  * b) during checkpoint, we consume checkpoint_completion_target *
2306  * number of segments consumed between checkpoints.
2307  *-------
2308  */
2309  target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
2311 
2312  /* round down */
2313  CheckPointSegments = (int) target;
2314 
2315  if (CheckPointSegments < 1)
2316  CheckPointSegments = 1;
2317 }
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:764
int wal_segment_size
Definition: xlog.c:116
int max_wal_size_mb
Definition: xlog.c:89
int CheckPointSegments
Definition: xlog.c:129
double CheckPointCompletionTarget
Definition: checkpointer.c:148

◆ CancelBackup()

void CancelBackup ( void  )

Definition at line 11779 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().

11780 {
11781  struct stat stat_buf;
11782 
11783  /* if the backup_label file is not there, return */
11784  if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
11785  return;
11786 
11787  /* remove leftover file from previously canceled backup if it exists */
11788  unlink(BACKUP_LABEL_OLD);
11789 
11791  {
11792  ereport(WARNING,
11794  errmsg("online backup mode was not canceled"),
11795  errdetail("File \"%s\" could not be renamed to \"%s\": %m.",
11797  return;
11798  }
11799 
11800  /* if the tablespace_map file is not there, return */
11801  if (stat(TABLESPACE_MAP, &stat_buf) < 0)
11802  {
11803  ereport(LOG,
11804  (errmsg("online backup mode canceled"),
11805  errdetail("File \"%s\" was renamed to \"%s\".",
11807  return;
11808  }
11809 
11810  /* remove leftover file from previously canceled backup if it exists */
11811  unlink(TABLESPACE_MAP_OLD);
11812 
11814  {
11815  ereport(LOG,
11816  (errmsg("online backup mode canceled"),
11817  errdetail("Files \"%s\" and \"%s\" were renamed to "
11818  "\"%s\" and \"%s\", respectively.",
11821  }
11822  else
11823  {
11824  ereport(WARNING,
11826  errmsg("online backup mode canceled"),
11827  errdetail("File \"%s\" was renamed to \"%s\", but "
11828  "file \"%s\" could not be renamed to \"%s\": %m.",
11831  }
11832 }
#define DEBUG1
Definition: elog.h:25
#define LOG
Definition: elog.h:26
#define BACKUP_LABEL_OLD
Definition: xlog.h:387
#define TABLESPACE_MAP
Definition: xlog.h:389
struct stat stat_buf
Definition: pg_standby.c:100
int errdetail(const char *fmt,...)
Definition: elog.c:957
int errcode_for_file_access(void)
Definition: elog.c:633
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:656
#define WARNING
Definition: elog.h:40
#define stat(a, b)
Definition: win32_port.h:255
#define ereport(elevel,...)
Definition: elog.h:144
#define TABLESPACE_MAP_OLD
Definition: xlog.h:390
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define BACKUP_LABEL_FILE
Definition: xlog.h:386

◆ check_wal_buffers()

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

Definition at line 4986 of file xlog.c.

References XLOGbuffers, and XLOGChooseNumBuffers().

4987 {
4988  /*
4989  * -1 indicates a request for auto-tune.
4990  */
4991  if (*newval == -1)
4992  {
4993  /*
4994  * If we haven't yet changed the boot_val default of -1, just let it
4995  * be. We'll fix it when XLOGShmemSize is called.
4996  */
4997  if (XLOGbuffers == -1)
4998  return true;
4999 
5000  /* Otherwise, substitute the auto-tune value */
5002  }
5003 
5004  /*
5005  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
5006  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
5007  * the case, we just silently treat such values as a request for the
5008  * minimum. (We could throw an error instead, but that doesn't seem very
5009  * helpful.)
5010  */
5011  if (*newval < 4)
5012  *newval = 4;
5013 
5014  return true;
5015 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:4970
#define newval
int XLOGbuffers
Definition: xlog.c:92

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 12573 of file xlog.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, FALLBACK_PROMOTE_SIGNAL_FILE, fast_promote, IsPromoteSignaled(), LocalPromoteIsTriggered, LOG, PROMOTE_SIGNAL_FILE, PromoteTriggerFile, ResetPromoteSignaled(), SetPromoteIsTriggered(), and stat.

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

12574 {
12575  struct stat stat_buf;
12576 
12578  return true;
12579 
12580  if (IsPromoteSignaled())
12581  {
12582  /*
12583  * In 9.1 and 9.2 the postmaster unlinked the promote file inside the
12584  * signal handler. It now leaves the file in place and lets the
12585  * Startup process do the unlink. This allows Startup to know whether
12586  * it should create a full checkpoint before starting up (fallback
12587  * mode). Fast promotion takes precedence.
12588  */
12589  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12590  {
12591  unlink(PROMOTE_SIGNAL_FILE);
12593  fast_promote = true;
12594  }
12595  else if (stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12596  {
12598  fast_promote = false;
12599  }
12600 
12601  ereport(LOG, (errmsg("received promote request")));
12602 
12605  return true;
12606  }
12607 
12608  if (PromoteTriggerFile == NULL || strcmp(PromoteTriggerFile, "") == 0)
12609  return false;
12610 
12611  if (stat(PromoteTriggerFile, &stat_buf) == 0)
12612  {
12613  ereport(LOG,
12614  (errmsg("promote trigger file found: %s", PromoteTriggerFile)));
12615  unlink(PromoteTriggerFile);
12617  fast_promote = true;
12618  return true;
12619  }
12620  else if (errno != ENOENT)
12621  ereport(ERROR,
12623  errmsg("could not stat promote trigger file \"%s\": %m",
12624  PromoteTriggerFile)));
12625 
12626  return false;
12627 }
char * PromoteTriggerFile
Definition: xlog.c:296
bool IsPromoteSignaled(void)
Definition: startup.c:234
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:393
static bool LocalPromoteIsTriggered
Definition: xlog.c:240
#define LOG
Definition: elog.h:26
static void SetPromoteIsTriggered(void)
Definition: xlog.c:12559
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:100
int errcode_for_file_access(void)
Definition: elog.c:633
#define FALLBACK_PROMOTE_SIGNAL_FILE
Definition: xlog.h:394
#define stat(a, b)
Definition: win32_port.h:255
#define ereport(elevel,...)
Definition: elog.h:144
void ResetPromoteSignaled(void)
Definition: startup.c:240
int errmsg(const char *fmt,...)
Definition: elog.c:824
static bool fast_promote
Definition: xlog.c:303

◆ CheckPointGuts()

static void CheckPointGuts ( XLogRecPtr  checkPointRedo,
int  flags 
)
static

Definition at line 9171 of file xlog.c.

References CheckPointBuffers(), CheckPointCLOG(), CheckPointCommitTs(), CheckPointLogicalRewriteHeap(), CheckPointMultiXact(), CheckPointPredicate(), CheckPointRelationMap(), CheckPointReplicationOrigin(), CheckPointReplicationSlots(), CheckPointSnapBuild(), CheckPointSUBTRANS(), and CheckPointTwoPhase().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

9172 {
9173  CheckPointCLOG();
9182  CheckPointBuffers(flags); /* performs all required fsyncs */
9184  /* We deliberately delay 2PC checkpointing as long as possible */
9185  CheckPointTwoPhase(checkPointRedo);
9186 }
void CheckPointBuffers(int flags)
Definition: bufmgr.c:2602
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1195
void CheckPointReplicationOrigin(void)
Definition: origin.c:545
void CheckPointSnapBuild(void)
Definition: snapbuild.c:1932
void CheckPointCLOG(void)
Definition: clog.c:835
void CheckPointMultiXact(void)
Definition: multixact.c:2142
void CheckPointCommitTs(void)
Definition: commit_ts.c:760
void CheckPointSUBTRANS(void)
Definition: subtrans.c:302
void CheckPointRelationMap(void)
Definition: relmapper.c:546
void CheckPointPredicate(void)
Definition: predicate.c:1015
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1699
void CheckPointReplicationSlots(void)
Definition: slot.c:1165

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 12644 of file xlog.c.

References FALLBACK_PROMOTE_SIGNAL_FILE, PROMOTE_SIGNAL_FILE, and stat.

Referenced by sigusr1_handler().

12645 {
12646  struct stat stat_buf;
12647 
12648  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 ||
12650  return true;
12651 
12652  return false;
12653 }
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:393
struct stat stat_buf
Definition: pg_standby.c:100
#define FALLBACK_PROMOTE_SIGNAL_FILE
Definition: xlog.h:394
#define stat(a, b)
Definition: win32_port.h:255

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 7968 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, 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().

7969 {
7970  XLogRecPtr lastReplayedEndRecPtr;
7971 
7972  /*
7973  * During crash recovery, we don't reach a consistent state until we've
7974  * replayed all the WAL.
7975  */
7977  return;
7978 
7980 
7981  /*
7982  * assume that we are called in the startup process, and hence don't need
7983  * a lock to read lastReplayedEndRecPtr
7984  */
7985  lastReplayedEndRecPtr = XLogCtl->lastReplayedEndRecPtr;
7986 
7987  /*
7988  * Have we reached the point where our base backup was completed?
7989  */
7991  ControlFile->backupEndPoint <= lastReplayedEndRecPtr)
7992  {
7993  /*
7994  * We have reached the end of base backup, as indicated by pg_control.
7995  * The data on disk is now consistent. Reset backupStartPoint and
7996  * backupEndPoint, and update minRecoveryPoint to make sure we don't
7997  * allow starting up at an earlier point even if recovery is stopped
7998  * and restarted soon after this.
7999  */
8000  elog(DEBUG1, "end of backup reached");
8001 
8002  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8003 
8004  if (ControlFile->minRecoveryPoint < lastReplayedEndRecPtr)
8005  ControlFile->minRecoveryPoint = lastReplayedEndRecPtr;
8006 
8009  ControlFile->backupEndRequired = false;
8011 
8012  LWLockRelease(ControlFileLock);
8013  }
8014 
8015  /*
8016  * Have we passed our safe starting point? Note that minRecoveryPoint is
8017  * known to be incorrectly set if ControlFile->backupEndRequired, until
8018  * the XLOG_BACKUP_END arrives to advise us of the correct
8019  * minRecoveryPoint. All we know prior to that is that we're not
8020  * consistent yet.
8021  */
8023  minRecoveryPoint <= lastReplayedEndRecPtr &&
8025  {
8026  /*
8027  * Check to see if the XLOG sequence contained any unresolved
8028  * references to uninitialized pages.
8029  */
8031 
8032  reachedConsistency = true;
8033  ereport(LOG,
8034  (errmsg("consistent recovery state reached at %X/%X",
8035  (uint32) (lastReplayedEndRecPtr >> 32),
8036  (uint32) lastReplayedEndRecPtr)));
8037  }
8038 
8039  /*
8040  * Have we got a valid starting snapshot that will allow queries to be
8041  * run? If so, we can tell postmaster that the database is consistent now,
8042  * enabling connections.
8043  */
8048  {
8052 
8053  LocalHotStandbyActive = true;
8054 
8056  }
8057 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:224
bool SharedHotStandbyActive
Definition: xlog.c:666
slock_t info_lck
Definition: xlog.c:727
#define LOG
Definition: elog.h:26
bool InArchiveRecovery
Definition: xlog.c:266
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool backupEndRequired
Definition: pg_control.h:170
#define SpinLockAcquire(lock)
Definition: spin.h:62
static bool LocalHotStandbyActive
Definition: xlog.c:234
void UpdateControlFile(void)
Definition: xlog.c:4901
bool IsUnderPostmaster
Definition: globals.c:109
unsigned int uint32
Definition: c.h:367
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static ControlFileData * ControlFile
Definition: xlog.c:738
#define ereport(elevel,...)
Definition: elog.h:144
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
bool reachedConsistency
Definition: xlog.c:869
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:146
HotStandbyState standbyState
Definition: xlog.c:207
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:860
XLogRecPtr lastReplayedEndRecPtr
Definition: xlog.c:706

◆ CheckRequiredParameterValues()

static void CheckRequiredParameterValues ( void  )
static

Definition at line 6255 of file xlog.c.

References ArchiveRecoveryRequested, EnableHotStandby, ereport, errhint(), errmsg(), ERROR, 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, WAL_LEVEL_MINIMAL, WAL_LEVEL_REPLICA, and WARNING.

Referenced by StartupXLOG(), and xlog_redo().

6256 {
6257  /*
6258  * For archive recovery, the WAL must be generated with at least 'replica'
6259  * wal_level.
6260  */
6262  {
6263  ereport(WARNING,
6264  (errmsg("WAL was generated with wal_level=minimal, data may be missing"),
6265  errhint("This happens if you temporarily set wal_level=minimal without taking a new base backup.")));
6266  }
6267 
6268  /*
6269  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
6270  * must have at least as many backend slots as the primary.
6271  */
6273  {
6275  ereport(ERROR,
6276  (errmsg("hot standby is not possible because wal_level was not set to \"replica\" or higher on the master server"),
6277  errhint("Either set wal_level to \"replica\" on the master, or turn off hot_standby here.")));
6278 
6279  /* We ignore autovacuum_max_workers when we make this test. */
6280  RecoveryRequiresIntParameter("max_connections",
6283  RecoveryRequiresIntParameter("max_worker_processes",
6286  RecoveryRequiresIntParameter("max_wal_senders",
6289  RecoveryRequiresIntParameter("max_prepared_transactions",
6292  RecoveryRequiresIntParameter("max_locks_per_transaction",
6295  }
6296 }
bool ArchiveRecoveryRequested
Definition: xlog.c:265
int max_locks_per_xact
Definition: pg_control.h:182
int errhint(const char *fmt,...)
Definition: elog.c:1071
int max_prepared_xacts
Definition: pg_control.h:181
int max_worker_processes
Definition: pg_control.h:179
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
int max_locks_per_xact
Definition: lock.c:54
int max_wal_senders
Definition: walsender.c:121
#define WARNING
Definition: elog.h:40
int MaxConnections
Definition: globals.c:132
static ControlFileData * ControlFile
Definition: xlog.c:738
#define ereport(elevel,...)
Definition: elog.h:144
bool EnableHotStandby
Definition: xlog.c:96
int errmsg(const char *fmt,...)
Definition: elog.c:824
int max_worker_processes
Definition: globals.c:133
#define RecoveryRequiresIntParameter(param_name, currValue, minValue)
Definition: xlog.c:6235

◆ checkTimeLineSwitch()

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

Definition at line 9832 of file xlog.c.

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

Referenced by StartupXLOG().

9833 {
9834  /* Check that the record agrees on what the current (old) timeline is */
9835  if (prevTLI != ThisTimeLineID)
9836  ereport(PANIC,
9837  (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
9838  prevTLI, ThisTimeLineID)));
9839 
9840  /*
9841  * The new timeline better be in the list of timelines we expect to see,
9842  * according to the timeline history. It should also not decrease.
9843  */
9844  if (newTLI < ThisTimeLineID || !tliInHistory(newTLI, expectedTLEs))
9845  ereport(PANIC,
9846  (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
9847  newTLI, ThisTimeLineID)));
9848 
9849  /*
9850  * If we have not yet reached min recovery point, and we're about to
9851  * switch to a timeline greater than the timeline of the min recovery
9852  * point: trouble. After switching to the new timeline, we could not
9853  * possibly visit the min recovery point on the correct timeline anymore.
9854  * This can happen if there is a newer timeline in the archive that
9855  * branched before the timeline the min recovery point is on, and you
9856  * attempt to do PITR to the new timeline.
9857  */
9859  lsn < minRecoveryPoint &&
9860  newTLI > minRecoveryPointTLI)
9861  ereport(PANIC,
9862  (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
9863  newTLI,
9864  (uint32) (minRecoveryPoint >> 32),
9867 
9868  /* Looks good */
9869 }
static List * expectedTLEs
Definition: xlog.c:344
#define PANIC
Definition: elog.h:53
unsigned int uint32
Definition: c.h:367
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:861
TimeLineID ThisTimeLineID
Definition: xlog.c:191
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:534
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:860

◆ checkXLogConsistency()

static void checkXLogConsistency ( XLogReaderState record)
static

Definition at line 1404 of file xlog.c.

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

Referenced by StartupXLOG().

1405 {
1406  RmgrId rmid = XLogRecGetRmid(record);
1407  RelFileNode rnode;
1408  ForkNumber forknum;
1409  BlockNumber blkno;
1410  int block_id;
1411 
1412  /* Records with no backup blocks have no need for consistency checks. */
1413  if (!XLogRecHasAnyBlockRefs(record))
1414  return;
1415 
1416  Assert((XLogRecGetInfo(record) & XLR_CHECK_CONSISTENCY) != 0);
1417 
1418  for (block_id = 0; block_id <= record->max_block_id; block_id++)
1419  {
1420  Buffer buf;
1421  Page page;
1422 
1423  if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
1424  {
1425  /*
1426  * WAL record doesn't contain a block reference with the given id.
1427  * Do nothing.
1428  */
1429  continue;
1430  }
1431 
1432  Assert(XLogRecHasBlockImage(record, block_id));
1433 
1434  if (XLogRecBlockImageApply(record, block_id))
1435  {
1436  /*
1437  * WAL record has already applied the page, so bypass the
1438  * consistency check as that would result in comparing the full
1439  * page stored in the record with itself.
1440  */
1441  continue;
1442  }
1443 
1444  /*
1445  * Read the contents from the current buffer and store it in a
1446  * temporary page.
1447  */
1448  buf = XLogReadBufferExtended(rnode, forknum, blkno,
1450  if (!BufferIsValid(buf))
1451  continue;
1452 
1454  page = BufferGetPage(buf);
1455 
1456  /*
1457  * Take a copy of the local page where WAL has been applied to have a
1458  * comparison base before masking it...
1459  */
1460  memcpy(replay_image_masked, page, BLCKSZ);
1461 
1462  /* No need for this page anymore now that a copy is in. */
1463  UnlockReleaseBuffer(buf);
1464 
1465  /*
1466  * If the block LSN is already ahead of this WAL record, we can't
1467  * expect contents to match. This can happen if recovery is
1468  * restarted.
1469  */
1470  if (PageGetLSN(replay_image_masked) > record->EndRecPtr)
1471  continue;
1472 
1473  /*
1474  * Read the contents from the backup copy, stored in WAL record and
1475  * store it in a temporary page. There is no need to allocate a new
1476  * page here, a local buffer is fine to hold its contents and a mask
1477  * can be directly applied on it.
1478  */
1479  if (!RestoreBlockImage(record, block_id, master_image_masked))
1480  elog(ERROR, "failed to restore block image");
1481 
1482  /*
1483  * If masking function is defined, mask both the master and replay
1484  * images
1485  */
1486  if (RmgrTable[rmid].rm_mask != NULL)
1487  {
1488  RmgrTable[rmid].rm_mask(replay_image_masked, blkno);
1489  RmgrTable[rmid].rm_mask(master_image_masked, blkno);
1490  }
1491 
1492  /* Time to compare the master and replay images. */
1493  if (memcmp(replay_image_masked, master_image_masked, BLCKSZ) != 0)
1494  {
1495  elog(FATAL,
1496  "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
1497  rnode.spcNode, rnode.dbNode, rnode.relNode,
1498  forknum, blkno);
1499  }
1500  }
1501 }
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:316
Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode)
Definition: xlogutils.c:442
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:176
static char * replay_image_masked
Definition: xlog.c:275
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3506
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:307
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:1490
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3722
uint8 RmgrId
Definition: rmgr.h:11
#define Assert(condition)
Definition: c.h:738
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:1543
#define PageGetLSN(page)
Definition: bufpage.h:366
#define elog(elevel,...)
Definition: elog.h:214
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:313
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:318
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:308
static char * master_image_masked
Definition: xlog.c:276

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3925 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().

3926 {
3927  int save_errno = errno;
3928  XLogSegNo lastRemovedSegNo;
3929 
3931  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3933 
3934  if (segno <= lastRemovedSegNo)
3935  {
3936  char filename[MAXFNAMELEN];
3937 
3938  XLogFileName(filename, tli, segno, wal_segment_size);
3939  errno = save_errno;
3940  ereport(ERROR,
3942  errmsg("requested WAL segment %s has already been removed",
3943  filename)));
3944  }
3945  errno = save_errno;
3946 }
int wal_segment_size
Definition: xlog.c:116
slock_t info_lck
Definition: xlog.c:727
XLogSegNo lastRemovedSegNo
Definition: xlog.c:610
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
uint64 XLogSegNo
Definition: xlogdefs.h:41
int errcode_for_file_access(void)
Definition: elog.c:633
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
#define ereport(elevel,...)
Definition: elog.h:144
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static XLogCtlData * XLogCtl
Definition: xlog.c:730
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

Definition at line 4289 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().

4290 {
4291  DIR *xldir;
4292  struct dirent *xlde;
4293  char path[MAXPGPATH + sizeof(XLOGDIR)];
4294 
4295  xldir = AllocateDir(XLOGDIR);
4296 
4297  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
4298  {
4299  if (IsBackupHistoryFileName(xlde->d_name))
4300  {
4301  if (XLogArchiveCheckDone(xlde->d_name))
4302  {
4303  elog(DEBUG2, "removing WAL backup history file \"%s\"",
4304  xlde->d_name);
4305  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
4306  unlink(path);
4307  XLogArchiveCleanup(xlde->d_name);
4308  }
4309  }
4310  }
4311 
4312  FreeDir(xldir);
4313 }
Definition: dirent.h:9
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:718
Definition: dirent.c:25
bool XLogArchiveCheckDone(const char *xlog)
Definition: xlogarchive.c:571
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
#define IsBackupHistoryFileName(fname)
#define XLOGDIR
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2647
#define elog(elevel,...)
Definition: elog.h:214
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:193
int FreeDir(DIR *dir)
Definition: fd.c:2699

◆ CopyXLogRecordToWAL()

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

Definition at line 1508 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().

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

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 8700 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(), ERROR, CheckPoint::fullPageWrites, XLogCtlInsert::fullPageWrites, GetCurrentTimestamp(), GetLastImportantRecPtr(), GetOldestActiveTransactionId(), GetOldestXmin(), 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::nextFullXid, VariableCacheData::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, 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, PROCARRAY_FLAGS_DEFAULT, 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, 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().

8701 {
8702  bool shutdown;
8703  CheckPoint checkPoint;
8704  XLogRecPtr recptr;
8705  XLogSegNo _logSegNo;
8707  uint32 freespace;
8708  XLogRecPtr PriorRedoPtr;
8709  XLogRecPtr curInsert;
8710  XLogRecPtr last_important_lsn;
8711  VirtualTransactionId *vxids;
8712  int nvxids;
8713 
8714  /*
8715  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
8716  * issued at a different time.
8717  */
8719  shutdown = true;
8720  else
8721  shutdown = false;
8722 
8723  /* sanity check */
8724  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
8725  elog(ERROR, "can't create a checkpoint during recovery");
8726 
8727  /*
8728  * Initialize InitXLogInsert working areas before entering the critical
8729  * section. Normally, this is done by the first call to
8730  * RecoveryInProgress() or LocalSetXLogInsertAllowed(), but when creating
8731  * an end-of-recovery checkpoint, the LocalSetXLogInsertAllowed call is
8732  * done below in a critical section, and InitXLogInsert cannot be called
8733  * in a critical section.
8734  */
8735  InitXLogInsert();
8736 
8737  /*
8738  * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
8739  * (This is just pro forma, since in the present system structure there is
8740  * only one process that is allowed to issue checkpoints at any given
8741  * time.)
8742  */
8743  LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
8744 
8745  /*
8746  * Prepare to accumulate statistics.
8747  *
8748  * Note: because it is possible for log_checkpoints to change while a
8749  * checkpoint proceeds, we always accumulate stats, even if
8750  * log_checkpoints is currently off.
8751  */
8752  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
8754 
8755  /*
8756  * Use a critical section to force system panic if we have trouble.
8757  */
8759 
8760  if (shutdown)
8761  {
8762  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8764  ControlFile->time = (pg_time_t) time(NULL);
8766  LWLockRelease(ControlFileLock);
8767  }
8768 
8769  /*
8770  * Let smgr prepare for checkpoint; this has to happen before we determine
8771  * the REDO pointer. Note that smgr must not do anything that'd have to
8772  * be undone if we decide no checkpoint is needed.
8773  */
8775 
8776  /* Begin filling in the checkpoint WAL record */
8777  MemSet(&checkPoint, 0, sizeof(checkPoint));
8778  checkPoint.time = (pg_time_t) time(NULL);
8779 
8780  /*
8781  * For Hot Standby, derive the oldestActiveXid before we fix the redo
8782  * pointer. This allows us to begin accumulating changes to assemble our
8783  * starting snapshot of locks and transactions.
8784  */
8785  if (!shutdown && XLogStandbyInfoActive())
8787  else
8789 
8790  /*
8791  * Get location of last important record before acquiring insert locks (as
8792  * GetLastImportantRecPtr() also locks WAL locks).
8793  */
8794  last_important_lsn = GetLastImportantRecPtr();
8795 
8796  /*
8797  * We must block concurrent insertions while examining insert state to
8798  * determine the checkpoint REDO pointer.
8799  */
8801  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
8802 
8803  /*
8804  * If this isn't a shutdown or forced checkpoint, and if there has been no
8805  * WAL activity requiring a checkpoint, skip it. The idea here is to
8806  * avoid inserting duplicate checkpoints when the system is idle.
8807  */
8808  if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
8809  CHECKPOINT_FORCE)) == 0)
8810  {
8811  if (last_important_lsn == ControlFile->checkPoint)
8812  {
8814  LWLockRelease(CheckpointLock);
8815  END_CRIT_SECTION();
8816  ereport(DEBUG1,
8817  (errmsg("checkpoint skipped because system is idle")));
8818  return;
8819  }
8820  }
8821 
8822  /*
8823  * An end-of-recovery checkpoint is created before anyone is allowed to
8824  * write WAL. To allow us to write the checkpoint record, temporarily
8825  * enable XLogInsertAllowed. (This also ensures ThisTimeLineID is
8826  * initialized, which we need here and in AdvanceXLInsertBuffer.)
8827  */
8828  if (flags & CHECKPOINT_END_OF_RECOVERY)
8830 
8831  checkPoint.ThisTimeLineID = ThisTimeLineID;
8832  if (flags & CHECKPOINT_END_OF_RECOVERY)
8833  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
8834  else
8835  checkPoint.PrevTimeLineID = ThisTimeLineID;
8836 
8837  checkPoint.fullPageWrites = Insert->fullPageWrites;
8838 
8839  /*
8840  * Compute new REDO record ptr = location of next XLOG record.
8841  *
8842  * NB: this is NOT necessarily where the checkpoint record itself will be,
8843  * since other backends may insert more XLOG records while we're off doing
8844  * the buffer flush work. Those XLOG records are logically after the
8845  * checkpoint, even though physically before it. Got that?
8846  */
8847  freespace = INSERT_FREESPACE(curInsert);
8848  if (freespace == 0)
8849  {
8850  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
8851  curInsert += SizeOfXLogLongPHD;
8852  else
8853  curInsert += SizeOfXLogShortPHD;
8854  }
8855  checkPoint.redo = curInsert;
8856 
8857  /*
8858  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
8859  * must be done while holding all the insertion locks.
8860  *
8861  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
8862  * pointing past where it really needs to point. This is okay; the only
8863  * consequence is that XLogInsert might back up whole buffers that it
8864  * didn't really need to. We can't postpone advancing RedoRecPtr because
8865  * XLogInserts that happen while we are dumping buffers must assume that
8866  * their buffer changes are not included in the checkpoint.
8867  */
8868  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
8869 
8870  /*
8871  * Now we can release the WAL insertion locks, allowing other xacts to
8872  * proceed while we are flushing disk buffers.
8873  */
8875 
8876  /* Update the info_lck-protected copy of RedoRecPtr as well */
8878  XLogCtl->RedoRecPtr = checkPoint.redo;
8880 
8881  /*
8882  * If enabled, log checkpoint start. We postpone this until now so as not
8883  * to log anything if we decided to skip the checkpoint.
8884  */
8885  if (log_checkpoints)
8886  LogCheckpointStart(flags, false);
8887 
8888  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
8889 
8890  /*
8891  * Get the other info we need for the checkpoint record.
8892  *
8893  * We don't need to save oldestClogXid in the checkpoint, it only matters
8894  * for the short period in which clog is being truncated, and if we crash
8895  * during that we'll redo the clog truncation and fix up oldestClogXid
8896  * there.
8897  */
8898  LWLockAcquire(XidGenLock, LW_SHARED);
8900  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
8902  LWLockRelease(XidGenLock);
8903 
8904  LWLockAcquire(CommitTsLock, LW_SHARED);
8907  LWLockRelease(CommitTsLock);
8908 
8909  LWLockAcquire(OidGenLock, LW_SHARED);
8910  checkPoint.nextOid = ShmemVariableCache->nextOid;
8911  if (!shutdown)
8912  checkPoint.nextOid += ShmemVariableCache->oidCount;
8913  LWLockRelease(OidGenLock);
8914 
8915  MultiXactGetCheckptMulti(shutdown,
8916  &checkPoint.nextMulti,
8917  &checkPoint.nextMultiOffset,
8918  &checkPoint.oldestMulti,
8919  &checkPoint.oldestMultiDB);
8920 
8921  /*
8922  * Having constructed the checkpoint record, ensure all shmem disk buffers
8923  * and commit-log buffers are flushed to disk.
8924  *
8925  * This I/O could fail for various reasons. If so, we will fail to
8926  * complete the checkpoint, but there is no reason to force a system
8927  * panic. Accordingly, exit critical section while doing it.
8928  */
8929  END_CRIT_SECTION();
8930 
8931  /*
8932  * In some cases there are groups of actions that must all occur on one
8933  * side or the other of a checkpoint record. Before flushing the
8934  * checkpoint record we must explicitly wait for any backend currently
8935  * performing those groups of actions.
8936  *
8937  * One example is end of transaction, so we must wait for any transactions
8938  * that are currently in commit critical sections. If an xact inserted
8939  * its commit record into XLOG just before the REDO point, then a crash
8940  * restart from the REDO point would not replay that record, which means
8941  * that our flushing had better include the xact's update of pg_xact. So
8942  * we wait till he's out of his commit critical section before proceeding.
8943  * See notes in RecordTransactionCommit().
8944  *
8945  * Because we've already released the insertion locks, this test is a bit
8946  * fuzzy: it is possible that we will wait for xacts we didn't really need
8947  * to wait for. But the delay should be short and it seems better to make
8948  * checkpoint take a bit longer than to hold off insertions longer than
8949  * necessary. (In fact, the whole reason we have this issue is that xact.c
8950  * does commit record XLOG insertion and clog update as two separate steps
8951  * protected by different locks, but again that seems best on grounds of
8952  * minimizing lock contention.)
8953  *
8954  * A transaction that has not yet set delayChkpt when we look cannot be at
8955  * risk, since he's not inserted his commit record yet; and one that's
8956  * already cleared it is not at risk either, since he's done fixing clog
8957  * and we will correctly flush the update below. So we cannot miss any
8958  * xacts we need to wait for.
8959  */
8960  vxids = GetVirtualXIDsDelayingChkpt(&nvxids);
8961  if (nvxids > 0)
8962  {
8963  do
8964  {
8965  pg_usleep(10000L); /* wait for 10 msec */
8966  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids));
8967  }
8968  pfree(vxids);
8969 
8970  CheckPointGuts(checkPoint.redo, flags);
8971 
8972  /*
8973  * Take a snapshot of running transactions and write this to WAL. This
8974  * allows us to reconstruct the state of running transactions during
8975  * archive recovery, if required. Skip, if this info disabled.
8976  *
8977  * If we are shutting down, or Startup process is completing crash
8978  * recovery we don't need to write running xact data.
8979  */
8980  if (!shutdown && XLogStandbyInfoActive())
8982 
8984 
8985  /*
8986  * Now insert the checkpoint record into XLOG.
8987  */
8988  XLogBeginInsert();
8989  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
8990  recptr = XLogInsert(RM_XLOG_ID,
8991  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
8993 
8994  XLogFlush(recptr);
8995 
8996  /*
8997  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
8998  * overwritten at next startup. No-one should even try, this just allows
8999  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
9000  * to just temporarily disable writing until the system has exited
9001  * recovery.
9002  */
9003  if (shutdown)
9004  {
9005  if (flags & CHECKPOINT_END_OF_RECOVERY)
9006  LocalXLogInsertAllowed = -1; /* return to "check" state */
9007  else
9008  LocalXLogInsertAllowed = 0; /* never again write WAL */
9009  }
9010 
9011  /*
9012  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
9013  * = end of actual checkpoint record.
9014  */
9015  if (shutdown && checkPoint.redo != ProcLastRecPtr)
9016  ereport(PANIC,
9017  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
9018 
9019  /*
9020  * Remember the prior checkpoint's redo ptr for
9021  * UpdateCheckPointDistanceEstimate()
9022  */
9023  PriorRedoPtr = ControlFile->checkPointCopy.redo;
9024 
9025  /*
9026  * Update the control file.
9027  */
9028  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9029  if (shutdown)
9032  ControlFile->checkPointCopy = checkPoint;
9033  ControlFile->time = (pg_time_t) time(NULL);
9034  /* crash recovery should always recover to the end of WAL */
9037 
9038  /*
9039  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
9040  * unused on non-shutdown checkpoints, but seems useful to store it always
9041  * for debugging purposes.
9042  */
9046 
9048  LWLockRelease(ControlFileLock);
9049 
9050  /* Update shared-memory copy of checkpoint XID/epoch */
9052  XLogCtl->ckptFullXid = checkPoint.nextFullXid;
9054 
9055  /*
9056  * We are now done with critical updates; no need for system panic if we
9057  * have trouble while fooling with old log segments.
9058  */
9059  END_CRIT_SECTION();
9060 
9061  /*
9062  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
9063  */
9065 
9066  /*
9067  * Update the average distance between checkpoints if the prior checkpoint
9068  * exists.
9069  */
9070  if (PriorRedoPtr != InvalidXLogRecPtr)
9072 
9073  /*
9074  * Delete old log files, those no longer needed for last checkpoint to
9075  * prevent the disk holding the xlog from growing full.
9076  */
9078  KeepLogSeg(recptr, &_logSegNo);
9080  _logSegNo--;
9081  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr);
9082 
9083  /*
9084  * Make more log segments if needed. (Do this after recycling old log
9085  * segments, since that may supply some of the needed files.)
9086  */
9087  if (!shutdown)
9088  PreallocXlogFiles(recptr);
9089 
9090  /*
9091  * Truncate pg_subtrans if possible. We can throw away all data before
9092  * the oldest XMIN of any running transaction. No future transaction will
9093  * attempt to reference any pg_subtrans entry older than that (see Asserts
9094  * in subtrans.c). During recovery, though, we mustn't do this because
9095  * StartupSUBTRANS hasn't been called yet.
9096  */
9097  if (!RecoveryInProgress())
9099 
9100  /* Real work is done, but log and update stats before releasing lock. */
9101  LogCheckpointEnd(false);
9102 
9103  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
9104  NBuffers,
9108 
9109  LWLockRelease(CheckpointLock);
9110 }
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:8438
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8638
static int LocalXLogInsertAllowed
Definition: xlog.c:252
bool log_checkpoints
Definition: xlog.c:104
#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:1726
int wal_segment_size
Definition: xlog.c:116
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:173
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1995
XLogRecPtr unloggedLSN
Definition: xlog.c:613
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:362
TransactionId oldestActiveXid
Definition: pg_control.h:63
void InitXLogInsert(void)
Definition: xloginsert.c:1121
TimestampTz ckpt_start_t
Definition: xlog.h:245
slock_t info_lck
Definition: xlog.c:727
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids)
Definition: procarray.c:2272
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: xlog.c:654
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
int ckpt_segs_recycled
Definition: xlog.h:255
TransactionId oldestXid
Definition: transam.h:180
#define MemSet(start, val, len)
Definition: c.h:971
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2120
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9171
FullTransactionId nextFullXid
Definition: transam.h:178
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:601
TransactionId oldestXid
Definition: pg_control.h:47
bool RecoveryInProgress(void)
Definition: xlog.c:8069
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:356
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:53
bool fullPageWrites
Definition: xlog.c:576
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2844
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#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:4901
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1056
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:923
#define ERROR
Definition: elog.h:43
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8553
static XLogRecPtr RedoRecPtr
Definition: xlog.c:376
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3892
uint64 XLogSegNo
Definition: xlogdefs.h:41
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:222
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
uint64 CurrBytePos
Definition: xlog.c:552
unsigned int uint32
Definition: c.h:367
XLogRecPtr RedoRecPtr
Definition: xlog.c:605
int ckpt_segs_removed
Definition: xlog.h:254
#define CHECKPOINT_FORCE
Definition: xlog.h:225
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:744
TransactionId oldestCommitTsXid
Definition: transam.h:190
static void Insert(File file)
Definition: fd.c:1172
int ckpt_bufs_written
Definition: xlog.h:251
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8213
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:324
#define SpinLockRelease(lock)
Definition: spin.h:64
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:416
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PROCARRAY_FLAGS_DEFAULT
Definition: procarray.h:50
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9577
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
Oid oldestMultiDB
Definition: pg_control.h:50
FullTransactionId ckptFullXid
Definition: xlog.c:606
#define XLogStandbyInfoActive()
Definition: xlog.h:205
static ControlFileData * ControlFile
Definition: xlog.c:738
TimeLineID ThisTimeLineID
Definition: xlog.c:191
Oid nextOid
Definition: pg_control.h:44
#define ereport(elevel,...)
Definition: elog.h:144
bool fullPageWrites
Definition: pg_control.h:42
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1305
uint64 XLogRecPtr
Definition: xlogdefs.h:21
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
TransactionId newestCommitTsXid
Definition: transam.h:191
CheckpointStatsData CheckpointStats
Definition: xlog.c:185
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:55
MultiXactId nextMulti
Definition: pg_control.h:45
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1697
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int ckpt_segs_added
Definition: xlog.h:253
slock_t ulsn_lck
Definition: xlog.c:614
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:824
void InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno)
Definition: slot.c:1090
#define elog(elevel,...)
Definition: elog.h:214
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
Definition: xlog.c:4023
void SyncPostCheckpoint(void)
Definition: sync.c:174
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2110
int NBuffers
Definition: globals.c:131
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
Definition: procarray.c:2316
void XLogBeginInsert(void)
Definition: xloginsert.c:121
XLogRecPtr RedoRecPtr
Definition: xlog.c:574
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8535
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:221
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
void SyncPreCheckpoint(void)
Definition: sync.c:159
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ CreateEndOfRecoveryRecord()

static void CreateEndOfRecoveryRecord ( void  )
static

Definition at line 9122 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().

9123 {
9124  xl_end_of_recovery xlrec;
9125  XLogRecPtr recptr;
9126 
9127  /* sanity check */
9128  if (!RecoveryInProgress())
9129  elog(ERROR, "can only be used to end recovery");
9130 
9131  xlrec.end_time = GetCurrentTimestamp();
9132 
9137 
9139 
9141 
9142  XLogBeginInsert();
9143  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
9144  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
9145 
9146  XLogFlush(recptr);
9147 
9148  /*
9149  * Update the control file so that crash recovery can follow the timeline
9150  * changes to this point.
9151  */
9152  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9153  ControlFile->time = (pg_time_t) time(NULL);
9154  ControlFile->minRecoveryPoint = recptr;
9157  LWLockRelease(ControlFileLock);
9158 
9159  END_CRIT_SECTION();
9160 
9161  LocalXLogInsertAllowed = -1; /* return to "check" state */
9162 }
static int LocalXLogInsertAllowed
Definition: xlog.c:252
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1726
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimeLineID PrevTimeLineID
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
TimeLineID PrevTimeLineID
Definition: xlog.c:654
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
bool RecoveryInProgress(void)
Definition: xlog.c:8069
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2844
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
void UpdateControlFile(void)
Definition: xlog.c:4901
#define ERROR
Definition: elog.h:43
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8213
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:324
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:416
static ControlFileData * ControlFile
Definition: xlog.c:738
TimeLineID ThisTimeLineID
Definition: xlog.c:191
TimestampTz end_time
uint64 XLogRecPtr
Definition: xlogdefs.h:21
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1697
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
TimeLineID ThisTimeLineID
#define elog(elevel,...)
Definition: elog.h:214
void XLogBeginInsert(void)
Definition: xloginsert.c:121
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 9241 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(), ExecuteRecoveryCommand(), GetCurrentTimestamp(), GetLatestXTime(), GetOldestXmin(), GetWalRcvFlushRecPtr(), GetXLogReplayRecPtr(), XLogCtlData::info_lck, XLogCtlData::Insert, InvalidateObsoleteReplicationSlots(), InvalidXLogRecPtr, KeepLogSeg(), XLogCtlData::lastCheckPoint, XLogCtlData::lastCheckPointEndPtr, XLogCtlData::lastCheckPointRecPtr, LOG, log_checkpoints, LogCheckpointEnd(), LogCheckpointStart(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, ControlFileData::minRecoveryPoint, minRecoveryPoint, ControlFileData::minRecoveryPointTLI, minRecoveryPointTLI, PreallocXlogFiles(), PROCARRAY_FLAGS_DEFAULT, RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), SpinLockAcquire, SpinLockRelease, ControlFileData::state, CheckPoint::ThisTimeLineID, ThisTimeLineID, ControlFileData::time, timestamptz_to_str(), TruncateSUBTRANS(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), UpdateMinRecoveryPoint(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, and XLogRecPtrIsInvalid.

Referenced by CheckpointerMain(), and ShutdownXLOG().

9242 {
9243  XLogRecPtr lastCheckPointRecPtr;
9244  XLogRecPtr lastCheckPointEndPtr;
9245  CheckPoint lastCheckPoint;
9246  XLogRecPtr PriorRedoPtr;
9247  XLogRecPtr receivePtr;
9248  XLogRecPtr replayPtr;
9249  TimeLineID replayTLI;
9250  XLogRecPtr endptr;
9251  XLogSegNo _logSegNo;
9252  TimestampTz xtime;
9253 
9254  /*
9255  * Acquire CheckpointLock to ensure only one restartpoint or checkpoint
9256  * happens at a time.
9257  */
9258  LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
9259 
9260  /* Get a local copy of the last safe checkpoint record. */
9262  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
9263  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
9264  lastCheckPoint = XLogCtl->lastCheckPoint;
9266 
9267  /*
9268  * Check that we're still in recovery mode. It's ok if we exit recovery
9269  * mode after this check, the restart point is valid anyway.
9270  */
9271  if (!RecoveryInProgress())
9272  {
9273  ereport(DEBUG2,
9274  (errmsg("skipping restartpoint, recovery has already ended")));
9275  LWLockRelease(CheckpointLock);
9276  return false;
9277  }
9278 
9279  /*
9280  * If the last checkpoint record we've replayed is already our last
9281  * restartpoint, we can't perform a new restart point. We still update
9282  * minRecoveryPoint in that case, so that if this is a shutdown restart
9283  * point, we won't start up earlier than before. That's not strictly
9284  * necessary, but when hot standby is enabled, it would be rather weird if
9285  * the database opened up for read-only connections at a point-in-time
9286  * before the last shutdown. Such time travel is still possible in case of
9287  * immediate shutdown, though.
9288  *
9289  * We don't explicitly advance minRecoveryPoint when we do create a
9290  * restartpoint. It's assumed that flushing the buffers will do that as a
9291  * side-effect.
9292  */
9293  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
9294  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
9295  {
9296  ereport(DEBUG2,
9297  (errmsg("skipping restartpoint, already performed at %X/%X",
9298  (uint32) (lastCheckPoint.redo >> 32),
9299  (uint32) lastCheckPoint.redo)));
9300 
9302  if (flags & CHECKPOINT_IS_SHUTDOWN)
9303  {
9304  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9306  ControlFile->time = (pg_time_t) time(NULL);
9308  LWLockRelease(ControlFileLock);
9309  }
9310  LWLockRelease(CheckpointLock);
9311  return false;
9312  }
9313 
9314  /*
9315  * Update the shared RedoRecPtr so that the startup process can calculate
9316  * the number of segments replayed since last restartpoint, and request a
9317  * restartpoint if it exceeds CheckPointSegments.
9318  *
9319  * Like in CreateCheckPoint(), hold off insertions to update it, although
9320  * during recovery this is just pro forma, because no WAL insertions are
9321  * happening.
9322  */
9324  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
9326 
9327  /* Also update the info_lck-protected copy */
9329  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
9331 
9332  /*
9333  * Prepare to accumulate statistics.
9334  *
9335  * Note: because it is possible for log_checkpoints to change while a
9336  * checkpoint proceeds, we always accumulate stats, even if
9337  * log_checkpoints is currently off.
9338  */
9339  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
9341 
9342  if (log_checkpoints)
9343  LogCheckpointStart(flags, true);
9344 
9345  CheckPointGuts(lastCheckPoint.redo, flags);
9346 
9347  /*
9348  * Remember the prior checkpoint's redo ptr for
9349  * UpdateCheckPointDistanceEstimate()
9350  */
9351  PriorRedoPtr = ControlFile->checkPointCopy.redo;
9352 
9353  /*
9354  * Update pg_control, using current time. Check that it still shows
9355  * DB_IN_ARCHIVE_RECOVERY state and an older checkpoint, else do nothing;
9356  * this is a quick hack to make sure nothing really bad happens if somehow
9357  * we get here after the end-of-recovery checkpoint.
9358  */
9359  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9361  ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
9362  {
9363  ControlFile->checkPoint = lastCheckPointRecPtr;
9364  ControlFile->checkPointCopy = lastCheckPoint;
9365  ControlFile->time = (pg_time_t) time(NULL);
9366 
9367  /*
9368  * Ensure minRecoveryPoint is past the checkpoint record. Normally,
9369  * this will have happened already while writing out dirty buffers,
9370  * but not necessarily - e.g. because no buffers were dirtied. We do
9371  * this because a non-exclusive base backup uses minRecoveryPoint to
9372  * determine which WAL files must be included in the backup, and the
9373  * file (or files) containing the checkpoint record must be included,
9374  * at a minimum. Note that for an ordinary restart of recovery there's
9375  * no value in having the minimum recovery point any earlier than this
9376  * anyway, because redo will begin just after the checkpoint record.
9377  */
9378  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
9379  {
9380  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
9382 
9383  /* update local copy */
9386  }
9387  if (flags & CHECKPOINT_IS_SHUTDOWN)
9390  }
9391  LWLockRelease(ControlFileLock);
9392 
9393  /*
9394  * Update the average distance between checkpoints/restartpoints if the
9395  * prior checkpoint exists.
9396  */
9397  if (PriorRedoPtr != InvalidXLogRecPtr)
9399 
9400  /*
9401  * Delete old log files, those no longer needed for last restartpoint to
9402  * prevent the disk holding the xlog from growing full.
9403  */
9405 
9406  /*
9407  * Retreat _logSegNo using the current end of xlog replayed or received,
9408  * whichever is later.
9409  */
9410  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
9411  replayPtr = GetXLogReplayRecPtr(&replayTLI);
9412  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
9413  KeepLogSeg(endptr, &_logSegNo);
9415  _logSegNo--;
9416 
9417  /*
9418  * Try to recycle segments on a useful timeline. If we've been promoted
9419  * since the beginning of this restartpoint, use the new timeline chosen
9420  * at end of recovery (RecoveryInProgress() sets ThisTimeLineID in that
9421  * case). If we're still in recovery, use the timeline we're currently
9422  * replaying.
9423  *
9424  * There is no guarantee that the WAL segments will be useful on the
9425  * current timeline; if recovery proceeds to a new timeline right after
9426  * this, the pre-allocated WAL segments on this timeline will not be used,
9427  * and will go wasted until recycled on the next restartpoint. We'll live
9428  * with that.
9429  */
9430  if (RecoveryInProgress())
9431  ThisTimeLineID = replayTLI;
9432 
9433  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr);
9434 
9435  /*
9436  * Make more log segments if needed. (Do this after recycling old log
9437  * segments, since that may supply some of the needed files.)
9438  */
9439  PreallocXlogFiles(endptr);
9440 
9441  /*
9442  * ThisTimeLineID is normally not set when we're still in recovery.
9443  * However, recycling/preallocating segments above needed ThisTimeLineID
9444  * to determine which timeline to install the segments on. Reset it now,
9445  * to restore the normal state of affairs for debugging purposes.
9446  */
9447  if (RecoveryInProgress())
9448  ThisTimeLineID = 0;
9449 
9450  /*
9451  * Truncate pg_subtrans if possible. We can throw away all data before
9452  * the oldest XMIN of any running transaction. No future transaction will
9453  * attempt to reference any pg_subtrans entry older than that (see Asserts
9454  * in subtrans.c). When hot standby is disabled, though, we mustn't do
9455  * this because StartupSUBTRANS hasn't been called yet.
9456  */
9457  if (EnableHotStandby)
9459 
9460  /* Real work is done, but log and update before releasing lock. */
9461  LogCheckpointEnd(true);
9462 
9463  xtime = GetLatestXTime();
9465  (errmsg("recovery restart point at %X/%X",
9466  (uint32) (lastCheckPoint.redo >> 32), (uint32) lastCheckPoint.redo),
9467  xtime ? errdetail("Last completed transaction was at log time %s.",
9468  timestamptz_to_str(xtime)) : 0));
9469 
9470  LWLockRelease(CheckpointLock);
9471 
9472  /*
9473  * Finally, execute archive_cleanup_command, if any.
9474  */
9475  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
9477  "archive_cleanup_command",
9478  false);
9479 
9480  return true;
9481 }
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8638
bool log_checkpoints
Definition: xlog.c:104
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal)
Definition: xlogarchive.c:286
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
uint32 TimeLineID
Definition: xlogdefs.h:52
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1726
int wal_segment_size
Definition: xlog.c:116
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
int64 TimestampTz
Definition: timestamp.h:39
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2757
TimestampTz ckpt_start_t
Definition: xlog.h:245
slock_t info_lck
Definition: xlog.c:727
#define MemSet(start, val, len)
Definition: c.h:971
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9171
TimestampTz GetLatestXTime(void)
Definition: xlog.c:6173
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:601
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:8069
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:356
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:696
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SpinLockAcquire(lock)
Definition: spin.h:62
void UpdateControlFile(void)
Definition: xlog.c:4901
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8553
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
Definition: xlog.c:11463
#define DEBUG2
Definition: elog.h:24
static XLogRecPtr RedoRecPtr
Definition: xlog.c:376
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3892
uint64 XLogSegNo
Definition: xlogdefs.h:41
int errdetail(const char *fmt,...)
Definition: elog.c:957
unsigned int uint32
Definition: c.h:367
XLogRecPtr RedoRecPtr
Definition: xlog.c:605
CheckPoint lastCheckPoint
Definition: xlog.c:698
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:861
#define PROCARRAY_FLAGS_DEFAULT
Definition: procarray.h:50
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9577
static ControlFileData * ControlFile
Definition: xlog.c:738
TimeLineID ThisTimeLineID
Definition: xlog.c:191
#define ereport(elevel,...)
Definition: elog.h:144
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1305
uint64 XLogRecPtr
Definition: xlogdefs.h:21
CheckpointStatsData CheckpointStats
Definition: xlog.c:185
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1697
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
bool EnableHotStandby
Definition: xlog.c:96
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:824
void InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno)
Definition: slot.c:1090
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
Definition: xlog.c:4023
XLogRecPtr RedoRecPtr
Definition: xlog.c:574
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:697
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8535
char * archiveCleanupCommand
Definition: xlog.c:281
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:221
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:860
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1736
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ DataChecksumsEnabled()

bool DataChecksumsEnabled ( void  )

Definition at line 4930 of file xlog.c.

References Assert, and ControlFileData::data_checksum_version.

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

4931 {
4932  Assert(ControlFile != NULL);
4933  return (ControlFile->data_checksum_version > 0);
4934 }
uint32 data_checksum_version
Definition: pg_control.h:220
static ControlFileData * ControlFile
Definition: xlog.c:738
#define Assert(condition)
Definition: c.h:738

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

Definition at line 11415 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().

11416 {
11417  bool emit_warning = DatumGetBool(arg);
11418 
11419  /*
11420  * Quick exit if session is not keeping around a non-exclusive backup
11421  * already started.
11422  */
11424  return;
11425 
11429 
11432  {
11433  XLogCtl->Insert.forcePageWrites = false;
11434  }
11436 
11437  if (emit_warning)
11438  ereport(WARNING,
11439  (errmsg("aborting backup due to backend exiting before pg_stop_backup was called")));
11440 }
static void WALInsertLockRelease(void)
Definition: xlog.c:1726
static SessionBackupState sessionBackupState
Definition: xlog.c:536
XLogCtlInsert Insert
Definition: xlog.c:601
bool forcePageWrites
Definition: xlog.c:575
#define DatumGetBool(X)
Definition: postgres.h:393
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:587
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:586
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1697
static XLogCtlData * XLogCtl
Definition: xlog.c:730
int errmsg(const char *fmt,...)
Definition: elog.c:824
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,
bool  infotbssize,
bool  needtblspcmapfile 
)

Definition at line 10474 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, 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(), pgstat_progress_update_param(), PROGRESS_BASEBACKUP_PHASE, PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE, pstrdup(), ReadDir(), readlink, RecoveryInProgress(), CheckPoint::redo, relpath, RequestCheckpoint(), RequestXLogSwitch(), tablespaceinfo::rpath, sendTablespace(), 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().

10478 {
10479  bool exclusive = (labelfile == NULL);
10480  bool backup_started_in_recovery = false;
10481  XLogRecPtr checkpointloc;
10482  XLogRecPtr startpoint;
10483  TimeLineID starttli;
10484  pg_time_t stamp_time;
10485  char strfbuf[128];
10486  char xlogfilename[MAXFNAMELEN];
10487  XLogSegNo _logSegNo;
10488  struct stat stat_buf;
10489  FILE *fp;
10490 
10491  backup_started_in_recovery = RecoveryInProgress();
10492 
10493  /*
10494  * Currently only non-exclusive backup can be taken during recovery.
10495  */
10496  if (backup_started_in_recovery && exclusive)
10497  ereport(ERROR,
10498  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10499  errmsg("recovery is in progress"),
10500  errhint("WAL control functions cannot be executed during recovery.")));
10501 
10502  /*
10503  * During recovery, we don't need to check WAL level. Because, if WAL
10504  * level is not sufficient, it's impossible to get here during recovery.
10505  */
10506  if (!backup_started_in_recovery && !XLogIsNeeded())
10507  ereport(ERROR,
10508  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10509  errmsg("WAL level not sufficient for making an online backup"),
10510  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
10511 
10512  if (strlen(backupidstr) > MAXPGPATH)
10513  ereport(ERROR,
10514  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10515  errmsg("backup label too long (max %d bytes)",
10516  MAXPGPATH)));
10517 
10518  /*
10519  * Mark backup active in shared memory. We must do full-page WAL writes
10520  * during an on-line backup even if not doing so at other times, because
10521  * it's quite possible for the backup dump to obtain a "torn" (partially
10522  * written) copy of a database page if it reads the page concurrently with
10523  * our write to the same page. This can be fixed as long as the first
10524  * write to the page in the WAL sequence is a full-page write. Hence, we
10525  * turn on forcePageWrites and then force a CHECKPOINT, to ensure there
10526  * are no dirty pages in shared memory that might get dumped while the
10527  * backup is in progress without having a corresponding WAL record. (Once
10528  * the backup is complete, we need not force full-page writes anymore,
10529  * since we expect that any pages not modified during the backup interval
10530  * must have been correctly captured by the backup.)
10531  *
10532  * Note that forcePageWrites has no effect during an online backup from
10533  * the standby.
10534  *
10535  * We must hold all the insertion locks to change the value of
10536  * forcePageWrites, to ensure adequate interlocking against
10537  * XLogInsertRecord().
10538  */
10540  if (exclusive)
10541  {
10542  /*
10543  * At first, mark that we're now starting an exclusive backup, to
10544  * ensure that there are no other sessions currently running
10545  * pg_start_backup() or pg_stop_backup().
10546  */
10548  {
10550  ereport(ERROR,
10551  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10552  errmsg("a backup is already in progress"),
10553  errhint("Run pg_stop_backup() and try again.")));
10554  }
10556  }
10557  else
10559  XLogCtl->Insert.forcePageWrites = true;
10561 
10562  /* Ensure we release forcePageWrites if fail below */
10564  {
10565  bool gotUniqueStartpoint = false;
10566  DIR *tblspcdir;
10567  struct dirent *de;
10568  tablespaceinfo *ti;
10569  int datadirpathlen;
10570 
10571  /*
10572  * Force an XLOG file switch before the checkpoint, to ensure that the
10573  * WAL segment the checkpoint is written to doesn't contain pages with
10574  * old timeline IDs. That would otherwise happen if you called
10575  * pg_start_backup() right after restoring from a PITR archive: the
10576  * first WAL segment containing the startup checkpoint has pages in
10577  * the beginning with the old timeline ID. That can cause trouble at
10578  * recovery: we won't have a history file covering the old timeline if
10579  * pg_wal directory was not included in the base backup and the WAL
10580  * archive was cleared too before starting the backup.
10581  *
10582  * This also ensures that we have emitted a WAL page header that has
10583  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
10584  * Therefore, if a WAL archiver (such as pglesslog) is trying to
10585  * compress out removable backup blocks, it won't remove any that
10586  * occur after this point.
10587  *
10588  * During recovery, we skip forcing XLOG file switch, which means that
10589  * the backup taken during recovery is not available for the special
10590  * recovery case described above.
10591  */
10592  if (!backup_started_in_recovery)
10593  RequestXLogSwitch(false);
10594 
10595  do
10596  {
10597  bool checkpointfpw;
10598 
10599  /*
10600  * Force a CHECKPOINT. Aside from being necessary to prevent torn
10601  * page problems, this guarantees that two successive backup runs
10602  * will have different checkpoint positions and hence different
10603  * history file names, even if nothing happened in between.
10604  *
10605  * During recovery, establish a restartpoint if possible. We use
10606  * the last restartpoint as the backup starting checkpoint. This
10607  * means that two successive backup runs can have same checkpoint
10608  * positions.
10609  *
10610  * Since the fact that we are executing do_pg_start_backup()
10611  * during recovery means that checkpointer is running, we can use
10612  * RequestCheckpoint() to establish a restartpoint.
10613  *
10614  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
10615  * passing fast = true). Otherwise this can take awhile.
10616  */
10618  (fast ? CHECKPOINT_IMMEDIATE : 0));
10619 
10620  /*
10621  * Now we need to fetch the checkpoint record location, and also
10622  * its REDO pointer. The oldest point in WAL that would be needed
10623  * to restore starting from the checkpoint is precisely the REDO
10624  * pointer.
10625  */
10626  LWLockAcquire(ControlFileLock, LW_SHARED);
10627  checkpointloc = ControlFile->checkPoint;
10628  startpoint = ControlFile->checkPointCopy.redo;
10630  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
10631  LWLockRelease(ControlFileLock);
10632 
10633  if (backup_started_in_recovery)
10634  {
10635  XLogRecPtr recptr;
10636 
10637  /*
10638  * Check to see if all WAL replayed during online backup
10639  * (i.e., since last restartpoint used as backup starting
10640  * checkpoint) contain full-page writes.
10641  */
10643  recptr = XLogCtl->lastFpwDisableRecPtr;
10645 
10646  if (!checkpointfpw || startpoint <= recptr)
10647  ereport(ERROR,
10648  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10649  errmsg("WAL generated with full_page_writes=off was replayed "
10650  "since last restartpoint"),
10651  errhint("This means that the backup being taken on the standby "
10652  "is corrupt and should not be used. "
10653  "Enable full_page_writes and run CHECKPOINT on the master, "
10654  "and then try an online backup again.")));
10655 
10656  /*
10657  * During recovery, since we don't use the end-of-backup WAL
10658  * record and don't write the backup history file, the
10659  * starting WAL location doesn't need to be unique. This means
10660  * that two base backups started at the same time might use
10661  * the same checkpoint as starting locations.
10662  */
10663  gotUniqueStartpoint = true;
10664  }
10665 
10666  /*
10667  * If two base backups are started at the same time (in WAL sender
10668  * processes), we need to make sure that they use different
10669  * checkpoints as starting locations, because we use the starting
10670  * WAL location as a unique identifier for the base backup in the
10671  * end-of-backup WAL record and when we write the backup history
10672  * file. Perhaps it would be better generate a separate unique ID
10673  * for each backup instead of forcing another checkpoint, but
10674  * taking a checkpoint right after another is not that expensive
10675  * either because only few buffers have been dirtied yet.
10676  */
10678  if (XLogCtl->Insert.lastBackupStart < startpoint)
10679  {
10680  XLogCtl->Insert.lastBackupStart = startpoint;
10681  gotUniqueStartpoint = true;
10682  }
10684  } while (!gotUniqueStartpoint);
10685 
10686  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
10687  XLogFileName(xlogfilename, starttli, _logSegNo, wal_segment_size);
10688 
10689  /*
10690  * Construct tablespace_map file
10691  */
10692  if (exclusive)
10693  tblspcmapfile = makeStringInfo();
10694 
10695  datadirpathlen = strlen(DataDir);
10696 
10697  /*
10698  * Report that we are now estimating the total backup size if we're
10699  * streaming base backup as requested by pg_basebackup
10700  */
10701  if (tablespaces)
10704 
10705  /* Collect information about all tablespaces */
10706  tblspcdir = AllocateDir("pg_tblspc");
10707  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
10708  {
10709  char fullpath[MAXPGPATH + 10];
10710  char linkpath[MAXPGPATH];
10711  char *relpath = NULL;
10712  int rllen;
10713  StringInfoData buflinkpath;
10714  char *s = linkpath;
10715 
10716  /* Skip special stuff */
10717  if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
10718  continue;
10719 
10720  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
10721 
10722 #if defined(HAVE_READLINK) || defined(WIN32)
10723  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
10724  if (rllen < 0)
10725  {
10726  ereport(WARNING,
10727  (errmsg("could not read symbolic link \"%s\": %m",
10728  fullpath)));
10729  continue;
10730  }
10731  else if (rllen >= sizeof(linkpath))
10732  {
10733  ereport(WARNING,
10734  (errmsg("symbolic link \"%s\" target is too long",
10735  fullpath)));
10736  continue;
10737  }
10738  linkpath[rllen] = '\0';
10739 
10740  /*
10741  * Add the escape character '\\' before newline in a string to
10742  * ensure that we can distinguish between the newline in the
10743  * tablespace path and end of line while reading tablespace_map
10744  * file during archive recovery.
10745  */
10746  initStringInfo(&buflinkpath);
10747 
10748  while (*s)
10749  {
10750  if ((*s == '\n' || *s == '\r') && needtblspcmapfile)
10751  appendStringInfoChar(&buflinkpath, '\\');
10752  appendStringInfoChar(&buflinkpath, *s++);
10753  }
10754 
10755  /*
10756  * Relpath holds the relative path of the tablespace directory
10757  * when it's located within PGDATA, or NULL if it's located
10758  * elsewhere.
10759  */
10760  if (rllen > datadirpathlen &&
10761  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
10762  IS_DIR_SEP(linkpath[datadirpathlen]))
10763  relpath = linkpath + datadirpathlen + 1;
10764 
10765  ti = palloc(sizeof(tablespaceinfo));
10766  ti->oid = pstrdup(de->d_name);
10767  ti->path = pstrdup(buflinkpath.data);
10768  ti->rpath = relpath ? pstrdup(relpath) : NULL;
10769  ti->size = infotbssize ?
10770  sendTablespace(fullpath, ti->oid, true, NULL) : -1;
10771 
10772  if (tablespaces)
10773  *tablespaces = lappend(*tablespaces, ti);
10774 
10775  appendStringInfo(tblspcmapfile, "%s %s\n", ti->oid, ti->path);
10776 
10777  pfree(buflinkpath.data);
10778 #else
10779 
10780  /*
10781  * If the platform does not have symbolic links, it should not be
10782  * possible to have tablespaces - clearly somebody else created
10783  * them. Warn about it and ignore.
10784  */
10785  ereport(WARNING,
10786  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10787  errmsg("tablespaces are not supported on this platform")));
10788 #endif
10789  }
10790  FreeDir(tblspcdir);
10791 
10792  /*
10793  * Construct backup label file
10794  */
10795  if (exclusive)
10796  labelfile = makeStringInfo();
10797 
10798  /* Use the log timezone here, not the session timezone */
10799  stamp_time = (pg_time_t) time(NULL);
10800  pg_strftime(strfbuf, sizeof(strfbuf),
10801  "%Y-%m-%d %H:%M:%S %Z",
10802  pg_localtime(&stamp_time, log_timezone));
10803  appendStringInfo(labelfile, "START WAL LOCATION: %X/%X (file %s)\n",
10804  (uint32) (startpoint >> 32), (uint32) startpoint, xlogfilename);
10805  appendStringInfo(labelfile, "CHECKPOINT LOCATION: %X/%X\n",
10806  (uint32) (checkpointloc >> 32), (uint32) checkpointloc);
10807  appendStringInfo(labelfile, "BACKUP METHOD: %s\n",
10808  exclusive ? "pg_start_backup" : "streamed");
10809  appendStringInfo(labelfile, "BACKUP FROM: %s\n",
10810  backup_started_in_recovery ? "standby" : "master");
10811  appendStringInfo(labelfile, "START TIME: %s\n", strfbuf);
10812  appendStringInfo(labelfile, "LABEL: %s\n", backupidstr);
10813  appendStringInfo(labelfile, "START TIMELINE: %u\n", starttli);
10814 
10815  /*
10816  * Okay, write the file, or return its contents to caller.
10817  */
10818  if (exclusive)
10819  {
10820  /*
10821  * Check for existing backup label --- implies a backup is already
10822  * running. (XXX given that we checked exclusiveBackupState
10823  * above, maybe it would be OK to just unlink any such label
10824  * file?)
10825  */
10826  if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
10827  {
10828  if (errno != ENOENT)
10829  ereport(ERROR,
10831  errmsg("could not stat file \"%s\": %m",
10832  BACKUP_LABEL_FILE)));
10833  }
10834  else
10835  ereport(ERROR,
10836  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10837  errmsg("a backup is already in progress"),
10838  errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
10839  BACKUP_LABEL_FILE)));
10840 
10841  fp = AllocateFile(BACKUP_LABEL_FILE, "w");
10842 
10843  if (!fp)
10844  ereport(ERROR,
10846  errmsg("could not create file \"%s\": %m",
10847  BACKUP_LABEL_FILE)));
10848  if (fwrite(labelfile->data, labelfile->len, 1, fp) != 1 ||
10849  fflush(fp) != 0 ||
10850  pg_fsync(fileno(fp)) != 0 ||
10851  ferror(fp) ||
10852  FreeFile(fp))
10853  ereport(ERROR,
10855  errmsg("could not write file \"%s\": %m",
10856  BACKUP_LABEL_FILE)));
10857  /* Allocated locally for exclusive backups, so free separately */
10858  pfree(labelfile->data);
10859  pfree(labelfile);
10860 
10861  /* Write backup tablespace_map file. */
10862  if (tblspcmapfile->len > 0)
10863  {
10864  if (stat(TABLESPACE_MAP, &stat_buf) != 0)
10865  {
10866  if (errno != ENOENT)
10867  ereport(ERROR,
10869  errmsg("could not stat file \"%s\": %m",
10870  TABLESPACE_MAP)));
10871  }
10872  else
10873  ereport(ERROR,
10874  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10875  errmsg("a backup is already in progress"),
10876  errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
10877  TABLESPACE_MAP)));
10878 
10879  fp = AllocateFile(TABLESPACE_MAP, "w");
10880 
10881  if (!fp)
10882  ereport(ERROR,
10884  errmsg("could not create file \"%s\": %m",
10885  TABLESPACE_MAP)));
10886  if (fwrite(tblspcmapfile->data, tblspcmapfile->len, 1, fp) != 1 ||
10887  fflush(fp) != 0 ||
10888  pg_fsync(fileno(fp)) != 0 ||
10889  ferror(fp) ||
10890  FreeFile(fp))
10891  ereport(ERROR,
10893  errmsg("could not write file \"%s\": %m",
10894  TABLESPACE_MAP)));
10895  }
10896 
10897  /* Allocated locally for exclusive backups, so free separately */
10898  pfree(tblspcmapfile->data);
10899  pfree(tblspcmapfile);
10900  }
10901  }
10903 
10904  /*
10905  * Mark that start phase has correctly finished for an exclusive backup.
10906  * Session-level locks are updated as well to reflect that state.
10907  *
10908  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating backup
10909  * counters and session-level lock. Otherwise they can be updated
10910  * inconsistently, and which might cause do_pg_abort_backup() to fail.
10911  */
10912  if (exclusive)
10913  {
10916 
10917  /* Set session-level lock */
10920  }
10921  else
10923 
10924  /*
10925  * We're done. As a convenience, return the starting WAL location.
10926  */
10927  if (starttli_p)
10928  *starttli_p = starttli;
10929  return startpoint;
10930 }
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:9664
int errhint(const char *fmt,...)
Definition: elog.c:1071
uint32 TimeLineID
Definition: xlogdefs.h:52
int64 pg_time_t
Definition: pgtime.h:23
#define PROGRESS_BASEBACKUP_PHASE
Definition: progress.h:123
static void WALInsertLockRelease(void)
Definition: xlog.c:1726
int wal_segment_size
Definition: xlog.c:116
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:725
static SessionBackupState sessionBackupState
Definition: xlog.c:536
XLogRecPtr lastBackupStart
Definition: xlog.c:588
void pgstat_progress_update_param(int index, int64 val)
Definition: pgstat.c:3235
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#define XLogIsNeeded()
Definition: xlog.h:191
char * rpath
Definition: basebackup.h:30
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
slock_t info_lck
Definition: xlog.c:727
int errcode(int sqlerrcode)
Definition: elog.c:610
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:601
bool RecoveryInProgress(void)
Definition: xlog.c:8069
static bool backup_started_in_recovery
Definition: basebackup.c:84
Definition: dirent.h:9
int64 sendTablespace(char *path, char *spcoid, bool sizeonly, backup_manifest_info *manifest)
Definition: basebackup.c:1145
#define IS_DIR_SEP(ch)
Definition: port.h:84
pg_tz * log_timezone
Definition: pgtz.c:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define TABLESPACE_MAP
Definition: xlog.h:389
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool forcePageWrites
Definition: xlog.c:575
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:100
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:41
#define readlink(path, buf, size)
Definition: win32_port.h:222
int errcode_for_file_access(void)
Definition: elog.c:633
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2320
unsigned int uint32
Definition: c.h:367
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
#define CHECKPOINT_FORCE
Definition: xlog.h:225
List * lappend(List *list, void *datum)
Definition: list.c:321
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:587
#define stat(a, b)
Definition: win32_port.h:255
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
static void pg_start_backup_callback(int code, Datum arg)
Definition: xlog.c:10934
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:586
uintptr_t Datum
Definition: postgres.h:367
static ControlFileData * ControlFile
Definition: xlog.c:738
#define BoolGetDatum(X)
Definition: postgres.h:402
#define ereport(elevel,...)
Definition: elog.h:144
bool fullPageWrites
Definition: pg_control.h:42
#define CHECKPOINT_WAIT
Definition: xlog.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2647
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1697
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#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:1375
#define PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE
Definition: progress.h:131
int FreeFile(FILE *file)
Definition: fd.c:2519
void * palloc(Size size)
Definition: mcxt.c:949
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:224
#define relpath(rnode, forknum)
Definition: relpath.h:87
char * DataDir
Definition: globals.c:62
#define BACKUP_LABEL_FILE
Definition: xlog.h:386
int pg_fsync(int fd)
Definition: fd.c:343
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:193
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
int FreeDir(DIR *dir)
Definition: fd.c:2699
void RequestCheckpoint(int flags)
Definition: checkpointer.c:903
#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 11002 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, 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, 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().

11003 {
11004  bool exclusive = (labelfile == NULL);
11005  bool backup_started_in_recovery = false;
11006  XLogRecPtr startpoint;
11007  XLogRecPtr stoppoint;
11008  TimeLineID stoptli;
11009  pg_time_t stamp_time;
11010  char strfbuf[128];
11011  char histfilepath[MAXPGPATH];
11012  char startxlogfilename[MAXFNAMELEN];
11013  char stopxlogfilename[MAXFNAMELEN];
11014  char lastxlogfilename[MAXFNAMELEN];
11015  char histfilename[MAXFNAMELEN];
11016  char backupfrom[20];
11017  XLogSegNo _logSegNo;
11018  FILE *lfp;
11019  FILE *fp;
11020  char ch;
11021  int seconds_before_warning;
11022  int waits = 0;
11023  bool reported_waiting = false;
11024  char *remaining;
11025  char *ptr;
11026  uint32 hi,
11027  lo;
11028 
11029  backup_started_in_recovery = RecoveryInProgress();
11030 
11031  /*
11032  * Currently only non-exclusive backup can be taken during recovery.
11033  */
11034  if (backup_started_in_recovery && exclusive)
11035  ereport(ERROR,
11036  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11037  errmsg("recovery is in progress"),
11038  errhint("WAL control functions cannot be executed during recovery.")));
11039 
11040  /*
11041  * During recovery, we don't need to check WAL level. Because, if WAL
11042  * level is not sufficient, it's impossible to get here during recovery.
11043  */
11044  if (!backup_started_in_recovery && !XLogIsNeeded())
11045  ereport(ERROR,
11046  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11047  errmsg("WAL level not sufficient for making an online backup"),
11048  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
11049 
11050  if (exclusive)
11051  {
11052  /*
11053  * At first, mark that we're now stopping an exclusive backup, to
11054  * ensure that there are no other sessions currently running
11055  * pg_start_backup() or pg_stop_backup().
11056  */
11059  {
11061  ereport(ERROR,
11062  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11063  errmsg("exclusive backup not in progress")));
11064  }
11067 
11068  /*
11069  * Remove backup_label. In case of failure, the state for an exclusive
11070  * backup is switched back to in-progress.
11071  */
11073  {
11074  /*
11075  * Read the existing label file into memory.
11076  */
11077  struct stat statbuf;
11078  int r;
11079 
11080  if (stat(BACKUP_LABEL_FILE, &statbuf))
11081  {
11082  /* should not happen per the upper checks */
11083  if (errno != ENOENT)
11084  ereport(ERROR,
11086  errmsg("could not stat file \"%s\": %m",
11087  BACKUP_LABEL_FILE)));
11088  ereport(ERROR,
11089  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11090  errmsg("a backup is not in progress")));
11091  }
11092 
11093  lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
11094  if (!lfp)
11095  {
11096  ereport(ERROR,
11098  errmsg("could not read file \"%s\": %m",
11099  BACKUP_LABEL_FILE)));
11100  }
11101  labelfile = palloc(statbuf.st_size + 1);
11102  r = fread(labelfile, statbuf.st_size, 1, lfp);
11103  labelfile[statbuf.st_size] = '\0';
11104 
11105  /*
11106  * Close and remove the backup label file
11107  */
11108  if (r != 1 || ferror(lfp) || FreeFile(lfp))
11109  ereport(ERROR,
11111  errmsg("could not read file \"%s\": %m",
11112  BACKUP_LABEL_FILE)));
11114 
11115  /*
11116  * Remove tablespace_map file if present, it is created only if
11117  * there are tablespaces.
11118  */
11120  }
11122  }
11123 
11124  /*
11125  * OK to update backup counters, forcePageWrites and session-level lock.
11126  *
11127  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
11128  * Otherwise they can be updated inconsistently, and which might cause
11129  * do_pg_abort_backup() to fail.
11130  */
11132  if (exclusive)
11133  {
11135  }
11136  else
11137  {
11138  /*
11139  * The user-visible pg_start/stop_backup() functions that operate on
11140  * exclusive backups can be called at any time, but for non-exclusive
11141  * backups, it is expected that each do_pg_start_backup() call is
11142  * matched by exactly one do_pg_stop_backup() call.
11143  */
11146  }
11147 
11150  {
11151  XLogCtl->Insert.forcePageWrites = false;
11152  }
11153 
11154  /*
11155  * Clean up session-level lock.
11156  *
11157  * You might think that WALInsertLockRelease() can be called before
11158  * cleaning up session-level lock because session-level lock doesn't need
11159  * to be protected with WAL insertion lock. But since
11160  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
11161  * cleaned up before it.
11162  */
11164 
11166 
11167  /*
11168  * Read and parse the START WAL LOCATION line (this code is pretty crude,
11169  * but we are not expecting any variability in the file format).
11170  */
11171  if (sscanf(labelfile, "START WAL LOCATION: %X/%X (file %24s)%c",
11172  &hi, &lo, startxlogfilename,
11173  &ch) != 4 || ch != '\n')
11174  ereport(ERROR,
11175  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11176  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
11177  startpoint = ((uint64) hi) << 32 | lo;
11178  remaining = strchr(labelfile, '\n') + 1; /* %n is not portable enough */
11179 
11180  /*
11181  * Parse the BACKUP FROM line. If we are taking an online backup from the
11182  * standby, we confirm that the standby has not been promoted during the
11183  * backup.
11184  */
11185  ptr = strstr(remaining, "BACKUP FROM:");
11186  if (!ptr || sscanf(ptr, "BACKUP FROM: %19s\n", backupfrom) != 1)
11187  ereport(ERROR,
11188  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11189  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
11190  if (strcmp(backupfrom, "standby") == 0 && !backup_started_in_recovery)
11191  ereport(ERROR,
11192  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11193  errmsg("the standby was promoted during online backup"),
11194  errhint("This means that the backup being taken is corrupt "
11195  "and should not be used. "
11196  "Try taking another online backup.")));
11197 
11198  /*
11199  * During recovery, we don't write an end-of-backup record. We assume that
11200  * pg_control was backed up last and its minimum recovery point can be
11201  * available as the backup end location. Since we don't have an
11202  * end-of-backup record, we use the pg_control value to check whether
11203  * we've reached the end of backup when starting recovery from this
11204  * backup. We have no way of checking if pg_control wasn't backed up last
11205  * however.
11206  *
11207  * We don't force a switch to new WAL file but it is still possible to
11208  * wait for all the required files to be archived if waitforarchive is
11209  * true. This is okay if we use the backup to start a standby and fetch
11210  * the missing WAL using streaming replication. But in the case of an
11211  * archive recovery, a user should set waitforarchive to true and wait for
11212  * them to be archived to ensure that all the required files are
11213  * available.
11214  *
11215  * We return the current minimum recovery point as the backup end
11216  * location. Note that it can be greater than the exact backup end
11217  * location if the minimum recovery point is updated after the backup of
11218  * pg_control. This is harmless for current uses.
11219  *
11220  * XXX currently a backup history file is for informational and debug
11221  * purposes only. It's not essential for an online backup. Furthermore,
11222  * even if it's created, it will not be archived during recovery because
11223  * an archiver is not invoked. So it doesn't seem worthwhile to write a
11224  * backup history file during recovery.
11225  */
11226  if (backup_started_in_recovery)
11227  {
11228  XLogRecPtr recptr;
11229 
11230  /*
11231  * Check to see if all WAL replayed during online backup contain
11232  * full-page writes.
11233  */
11235  recptr = XLogCtl->lastFpwDisableRecPtr;
11237 
11238  if (startpoint <= recptr)
11239  ereport(ERROR,
11240  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11241  errmsg("WAL generated with full_page_writes=off was replayed "
11242  "during online backup"),
11243  errhint("This means that the backup being taken on the standby "
11244  "is corrupt and should not be used. "
11245  "Enable full_page_writes and run CHECKPOINT on the master, "
11246  "and then try an online backup again.")));
11247 
11248 
11249  LWLockAcquire(ControlFileLock, LW_SHARED);
11250  stoppoint = ControlFile->minRecoveryPoint;
11251  stoptli = ControlFile->minRecoveryPointTLI;
11252  LWLockRelease(ControlFileLock);
11253  }
11254  else
11255  {
11256  /*
11257  * Write the backup-end xlog record
11258  */
11259  XLogBeginInsert();
11260  XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
11261  stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
11262  stoptli = ThisTimeLineID;
11263 
11264  /*
11265  * Force a switch to a new xlog segment file, so that the backup is
11266  * valid as soon as archiver moves out the current segment file.
11267  */
11268  RequestXLogSwitch(false);
11269 
11270  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11271  XLogFileName(stopxlogfilename, stoptli, _logSegNo, wal_segment_size);
11272 
11273  /* Use the log timezone here, not the session timezone */
11274  stamp_time = (pg_time_t) time(NULL);
11275  pg_strftime(strfbuf, sizeof(strfbuf),
11276  "%Y-%m-%d %H:%M:%S %Z",
11277  pg_localtime(&stamp_time, log_timezone));
11278 
11279  /*
11280  * Write the backup history file
11281  */
11282  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11283  BackupHistoryFilePath(histfilepath, stoptli, _logSegNo,
11284  startpoint, wal_segment_size);
11285  fp = AllocateFile(histfilepath, "w");
11286  if (!fp)
11287  ereport(ERROR,
11289  errmsg("could not create file \"%s\": %m",
11290  histfilepath)));
11291  fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
11292  (uint32) (startpoint >> 32), (uint32) startpoint, startxlogfilename);
11293  fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
11294  (uint32) (stoppoint >> 32), (uint32) stoppoint, stopxlogfilename);
11295 
11296  /*
11297  * Transfer remaining lines including label and start timeline to
11298  * history file.
11299  */
11300  fprintf(fp, "%s", remaining);
11301  fprintf(fp, "STOP TIME: %s\n", strfbuf);
11302  fprintf(fp, "STOP TIMELINE: %u\n", stoptli);
11303  if (fflush(fp) || ferror(fp) || FreeFile(fp))
11304  ereport(ERROR,
11306  errmsg("could not write file \"%s\": %m",
11307  histfilepath)));
11308 
11309  /*
11310  * Clean out any no-longer-needed history files. As a side effect,
11311  * this will post a .ready file for the newly created history file,
11312  * notifying the archiver that history file may be archived
11313  * immediately.
11314  */
11316  }
11317 
11318  /*
11319  * If archiving is enabled, wait for all the required WAL files to be
11320  * archived before returning. If archiving isn't enabled, the required WAL
11321  * needs to be transported via streaming replication (hopefully with
11322  * wal_keep_segments set high enough), or some more exotic mechanism like
11323  * polling and copying files from pg_wal with script. We have no knowledge
11324  * of those mechanisms, so it's up to the user to ensure that he gets all
11325  * the required WAL.
11326  *
11327  * We wait until both the last WAL file filled during backup and the
11328  * history file have been archived, and assume that the alphabetic sorting
11329  * property of the WAL files ensures any earlier WAL files are safely
11330  * archived as well.
11331  *
11332  * We wait forever, since archive_command is supposed to work and we
11333  * assume the admin wanted his backup to work completely. If you don't
11334  * wish to wait, then either waitforarchive should be passed in as false,
11335  * or you can set statement_timeout. Also, some notices are issued to
11336  * clue in anyone who might be doing this interactively.
11337  */
11338 
11339  if (waitforarchive &&
11340  ((!backup_started_in_recovery && XLogArchivingActive()) ||
11341  (backup_started_in_recovery && XLogArchivingAlways())))
11342  {
11343  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11344  XLogFileName(lastxlogfilename, stoptli, _logSegNo, wal_segment_size);
11345 
11346  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11347  BackupHistoryFileName(histfilename, stoptli, _logSegNo,
11348  startpoint, wal_segment_size);
11349 
11350  seconds_before_warning = 60;
11351  waits = 0;
11352 
11353  while (XLogArchiveIsBusy(lastxlogfilename) ||
11354  XLogArchiveIsBusy(histfilename))
11355  {
11357 
11358  if (!reported_waiting && waits > 5)
11359  {
11360  ereport(NOTICE,
11361  (errmsg("base backup done, waiting for required WAL segments to be archived")));
11362  reported_waiting = true;
11363  }
11364 
11366  pg_usleep(1000000L);
11368 
11369  if (++waits >= seconds_before_warning)
11370  {
11371  seconds_before_warning *= 2; /* This wraps in >10 years... */
11372  ereport(WARNING,
11373  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
11374  waits),
11375  errhint("Check that your archive_command is executing properly. "
11376  "You can safely cancel this backup, "
11377  "but the database backup will not be usable without all the WAL segments.")));
11378  }
11379  }
11380 
11381  ereport(NOTICE,
11382  (errmsg("all required WAL segments have been archived")));
11383  }
11384  else if (waitforarchive)
11385  ereport(NOTICE,
11386  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
11387 
11388  /*
11389  * We're done. As a convenience, return the ending WAL location.
11390  */
11391  if (stoptli_p)
11392  *stoptli_p = stoptli;
11393  return stoppoint;
11394 }
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:9664
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:1071
uint32 TimeLineID
Definition: xlogdefs.h:52
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1726
int wal_segment_size
Definition: xlog.c:116
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:725
static SessionBackupState sessionBackupState
Definition: xlog.c:536
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogIsNeeded()
Definition: xlog.h:191
slock_t info_lck
Definition: xlog.c:727
int errcode(int sqlerrcode)
Definition: elog.c:610
XLogCtlInsert Insert
Definition: xlog.c:601
#define BackupHistoryFileName(fname, tli, logSegNo, startpoint, wal_segsz_bytes)
bool RecoveryInProgress(void)
Definition: xlog.c:8069
static bool backup_started_in_recovery
Definition: basebackup.c:84
#define fprintf
Definition: port.h:197
pg_tz * log_timezone
Definition: pgtz.c:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define TABLESPACE_MAP
Definition: xlog.h:389
#define SpinLockAcquire(lock)
Definition: spin.h:62
void pg_usleep(long microsec)
Definition: signal.c:53
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define XLogArchivingAlways()
Definition: xlog.h:183
bool forcePageWrites
Definition: xlog.c:575
#define ERROR
Definition: elog.h:43
static void CleanupBackupHistory(void)
Definition: xlog.c:4289
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:41
int errcode_for_file_access(void)
Definition: elog.c:633
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2320
unsigned int uint32
Definition: c.h:367
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1380
#define XLOG_BACKUP_END
Definition: pg_control.h:72
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:587
#define stat(a, b)
Definition: win32_port.h:255
#define MAXFNAMELEN
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:324
#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:416
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:586
uintptr_t Datum
Definition: postgres.h:367
static ControlFileData * ControlFile
Definition: xlog.c:738
#define BoolGetDatum(X)
Definition: postgres.h:402
TimeLineID ThisTimeLineID
Definition: xlog.c:191
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:625
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
#define XLogArchivingActive()
Definition: xlog.h:180
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1356
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1697
static XLogCtlData * XLogCtl
Definition: xlog.c:730
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static void pg_stop_backup_callback(int code, Datum arg)
Definition: xlog.c:10963
#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:1375
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:746
int FreeFile(FILE *file)
Definition: fd.c:2519
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define BACKUP_LABEL_FILE
Definition: xlog.h:386
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
void XLogBeginInsert(void)
Definition: xloginsert.c:121
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 12520 of file xlog.c.

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

12521 {
12522  static XLogRecPtr lastComplaint = 0;
12523 
12524  if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
12525  {
12526  if (RecPtr == lastComplaint)
12527  emode = DEBUG1;
12528  else
12529  lastComplaint = RecPtr;
12530  }
12531  return emode;
12532 }
#define DEBUG1
Definition: elog.h:25
static XLogSource readSource
Definition: xlog.c:815
#define LOG
Definition: elog.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ exitArchiveRecovery()

static void exitArchiveRecovery ( TimeLineID  endTLI,
XLogRecPtr  endOfLog 
)
static

Definition at line 5543 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().

5544 {
5545  char xlogfname[MAXFNAMELEN];
5546  XLogSegNo endLogSegNo;
5547  XLogSegNo startLogSegNo;
5548 
5549  /* we always switch to a new timeline after archive recovery */
5550  Assert(endTLI != ThisTimeLineID);
5551 
5552  /*
5553  * We are no longer in archive recovery state.
5554  */
5555  InArchiveRecovery = false;
5556 
5557  /*
5558  * Update min recovery point one last time.
5559  */
5561 
5562  /*
5563  * If the ending log segment is still open, close it (to avoid problems on
5564  * Windows with trying to rename or delete an open file).
5565  */
5566  if (readFile >= 0)
5567  {
5568  close(readFile);
5569  readFile = -1;
5570  }
5571 
5572  /*
5573  * Calculate the last segment on the old timeline, and the first segment
5574  * on the new timeline. If the switch happens in the middle of a segment,
5575  * they are the same, but if the switch happens exactly at a segment
5576  * boundary, startLogSegNo will be endLogSegNo + 1.
5577  */
5578  XLByteToPrevSeg(endOfLog, endLogSegNo, wal_segment_size);
5579  XLByteToSeg(endOfLog, startLogSegNo, wal_segment_size);
5580 
5581  /*
5582  * Initialize the starting WAL segment for the new timeline. If the switch
5583  * happens in the middle of a segment, copy data from the last WAL segment
5584  * of the old timeline up to the switch point, to the starting WAL segment
5585  * on the new timeline.
5586  */
5587  if (endLogSegNo == startLogSegNo)
5588  {
5589  /*
5590  * Make a copy of the file on the new timeline.
5591  *
5592  * Writing WAL isn't allowed yet, so there are no locking
5593  * considerations. But we should be just as tense as XLogFileInit to
5594  * avoid emplacing a bogus file.
5595  */
5596  XLogFileCopy(endLogSegNo, endTLI, endLogSegNo,
5597  XLogSegmentOffset(endOfLog, wal_segment_size));
5598  }
5599  else
5600  {
5601  /*
5602  * The switch happened at a segment boundary, so just create the next
5603  * segment on the new timeline.
5604  */
5605  bool use_existent = true;
5606  int fd;
5607 
5608  fd = XLogFileInit(startLogSegNo, &use_existent, true);
5609 
5610  if (close(fd) != 0)
5611  {
5612  char xlogfname[