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 "port/pg_iovec.h"
#include "postmaster/bgwriter.h"
#include "postmaster/startup.h"
#include "postmaster/walwriter.h"
#include "replication/basebackup.h"
#include "replication/logical.h"
#include "replication/origin.h"
#include "replication/slot.h"
#include "replication/snapbuild.h"
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/large_object.h"
#include "storage/latch.h"
#include "storage/pmsignal.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/reinit.h"
#include "storage/smgr.h"
#include "storage/spin.h"
#include "storage/sync.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
#include "utils/pg_rusage.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
Include dependency graph for xlog.c:

Go to the source code of this file.

Data Structures

struct  XLogwrtRqst
 
struct  XLogwrtResult
 
struct  WALInsertLock
 
union  WALInsertLockPadded
 
struct  XLogCtlInsert
 
struct  XLogCtlData
 
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)   XLogMBVarToSegs((x), (segsize))
 

Typedefs

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

Variables

uint32 bootstrap_data_checksum_version
 
int max_wal_size_mb = 1024
 
int min_wal_size_mb = 80
 
int wal_keep_size_mb = 0
 
int XLOGbuffers = -1
 
int XLogArchiveTimeout = 0
 
int XLogArchiveMode = ARCHIVE_MODE_OFF
 
char * XLogArchiveCommand = NULL
 
bool EnableHotStandby = false
 
bool fullPageWrites = true
 
bool wal_log_hints = false
 
int wal_compression = WAL_COMPRESSION_NONE
 
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
 
bool track_wal_io_timing = false
 
int wal_segment_size = DEFAULT_XLOG_SEG_SIZE
 
int CheckPointSegments
 
static double CheckPointDistanceEstimate = 0
 
static double PrevCheckPointDistance = 0
 
const struct config_enum_entry sync_method_options []
 
const struct config_enum_entry archive_mode_options []
 
const struct config_enum_entry recovery_target_action_options []
 
CheckpointStatsData CheckpointStats
 
TimeLineID ThisTimeLineID = 0
 
bool InRecovery = false
 
HotStandbyState standbyState = STANDBY_DISABLED
 
static XLogRecPtr LastRec
 
static XLogRecPtr flushedUpto = 0
 
static TimeLineID receiveTLI = 0
 
static bool lastFullPageWrites
 
static bool LocalRecoveryInProgress = true
 
static bool LocalHotStandbyActive = false
 
static bool LocalPromoteIsTriggered = false
 
static int LocalXLogInsertAllowed = -1
 
bool ArchiveRecoveryRequested = false
 
bool InArchiveRecovery = false
 
static bool standby_signal_file_found = false
 
static bool recovery_signal_file_found = false
 
static bool restoredFromArchive = false
 
static char * replay_image_masked = NULL
 
static char * primary_image_masked = NULL
 
char * recoveryRestoreCommand = NULL
 
char * recoveryEndCommand = NULL
 
char * archiveCleanupCommand = NULL
 
RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET
 
bool recoveryTargetInclusive = true
 
int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE
 
TransactionId recoveryTargetXid
 
char * recovery_target_time_string
 
static TimestampTz recoveryTargetTime
 
const char * recoveryTargetName
 
XLogRecPtr recoveryTargetLSN
 
int recovery_min_apply_delay = 0
 
bool StandbyModeRequested = false
 
char * PrimaryConnInfo = NULL
 
char * PrimarySlotName = NULL
 
char * PromoteTriggerFile = NULL
 
bool wal_receiver_create_temp_slot = false
 
bool StandbyMode = false
 
static TransactionId recoveryStopXid
 
static TimestampTz recoveryStopTime
 
static XLogRecPtr recoveryStopLSN
 
static char recoveryStopName [MAXFNAMELEN]
 
static bool recoveryStopAfter
 
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal = RECOVERY_TARGET_TIMELINE_LATEST
 
TimeLineID recoveryTargetTLIRequested = 0
 
TimeLineID recoveryTargetTLI = 0
 
static ListexpectedTLEs
 
static TimeLineID curFileTLI
 
XLogRecPtr ProcLastRecPtr = InvalidXLogRecPtr
 
XLogRecPtr XactLastRecEnd = InvalidXLogRecPtr
 
XLogRecPtr XactLastCommitEnd = InvalidXLogRecPtr
 
static XLogRecPtr RedoRecPtr
 
static bool doPageWrites
 
static bool doRequestWalReceiverReply
 
static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr
 
static SessionBackupState sessionBackupState = SESSION_BACKUP_NONE
 
static XLogCtlDataXLogCtl = NULL
 
static WALInsertLockPaddedWALInsertLocks = NULL
 
static ControlFileDataControlFile = NULL
 
static int UsableBytesInSegment
 
static XLogwrtResult LogwrtResult = {0, 0}
 
static const char *const xlogSourceNames [] = {"any", "archive", "pg_wal", "stream"}
 
static int openLogFile = -1
 
static XLogSegNo openLogSegNo = 0
 
static int readFile = -1
 
static 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 
)    XLogMBVarToSegs((x), (segsize))

◆ INSERT_FREESPACE

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

Definition at line 762 of file xlog.c.

Referenced by CopyXLogRecordToWAL(), and CreateCheckPoint().

◆ NextBufIdx

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

Definition at line 766 of file xlog.c.

Referenced by XLogWrite().

◆ NUM_XLOGINSERT_LOCKS

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 88 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 87 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ UsableBytesInPage

#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)

◆ XLogRecPtrToBufIdx

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

Definition at line 773 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 520 of file xlog.c.

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 800 of file xlog.c.

801 {
802  XLOG_FROM_ANY = 0, /* request to read WAL from any source */
803  XLOG_FROM_ARCHIVE, /* restored using restore_command */
804  XLOG_FROM_PG_WAL, /* existing file in pg_wal */
805  XLOG_FROM_STREAM /* streamed from primary */
806 } XLogSource;
XLogSource
Definition: xlog.c:800

Function Documentation

◆ AdvanceXLInsertBuffer()

static void AdvanceXLInsertBuffer ( XLogRecPtr  upto,
bool  opportunistic 
)
static

Definition at line 2142 of file xlog.c.

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

Referenced by GetXLogBuffer(), and XLogBackgroundFlush().

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

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 2348 of file xlog.c.

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

2349 {
2352 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2312
#define newval
double CheckPointCompletionTarget
Definition: checkpointer.c:148

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 2341 of file xlog.c.

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

2342 {
2345 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2312
int max_wal_size_mb
Definition: xlog.c:91
#define newval

◆ assign_xlog_sync_method()

void assign_xlog_sync_method ( int  new_sync_method,
void *  extra 
)

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

10631 {
10632  if (sync_method != new_sync_method)
10633  {
10634  /*
10635  * To ensure that no blocks escape unsynced, force an fsync on the
10636  * currently open log segment (if any). Also, if the open flag is
10637  * changing, close the log file so it will be reopened (with new flag
10638  * bit) at next use.
10639  */
10640  if (openLogFile >= 0)
10641  {
10643  if (pg_fsync(openLogFile) != 0)
10644  {
10645  char xlogfname[MAXFNAMELEN];
10646  int save_errno;
10647 
10648  save_errno = errno;
10651  errno = save_errno;
10652  ereport(PANIC,
10654  errmsg("could not fsync file \"%s\": %m", xlogfname)));
10655  }
10656 
10658  if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
10659  XLogFileClose();
10660  }
10661  }
10662 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:278
int wal_segment_size
Definition: xlog.c:119
static int get_sync_bit(int method)
Definition: xlog.c:10574
#define PANIC
Definition: elog.h:50
static XLogSegNo openLogSegNo
Definition: xlog.c:818
static void XLogFileClose(void)
Definition: xlog.c:3907
int errcode_for_file_access(void)
Definition: elog.c:721
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:262
#define MAXFNAMELEN
static int openLogFile
Definition: xlog.c:817
TimeLineID ThisTimeLineID
Definition: xlog.c:194
#define ereport(elevel,...)
Definition: elog.h:157
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
int sync_method
Definition: xlog.c:107
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pg_fsync(int fd)
Definition: fd.c:352

◆ BackupInProgress()

bool BackupInProgress ( void  )

Definition at line 12084 of file xlog.c.

References BACKUP_LABEL_FILE, and stat.

Referenced by pg_is_in_backup(), and PostmasterStateMachine().

12085 {
12086  struct stat stat_buf;
12087 
12088  return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
12089 }
#define BACKUP_LABEL_FILE
Definition: xlog.h:405
#define stat
Definition: win32_port.h:275

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 5266 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, FirstGenbkiObjectId, FirstMultiXactId, FirstNormalTransactionId, CheckPoint::fullPageWrites, fullPageWrites, FullTransactionIdFromEpochAndXid(), gettimeofday(), INIT_CRC32C, InitControlFile(), XLogCtlData::InstallXLogFileSegmentActive, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, CheckPoint::nextXid, VariableCacheData::nextXid, offsetof, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, palloc(), PANIC, pfree(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), CheckPoint::PrevTimeLineID, ReadControlFile(), CheckPoint::redo, SetCommitTsLimit(), SetMultiXactIdLimit(), SetTransactionIdLimit(), ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, CheckPoint::ThisTimeLineID, ThisTimeLineID, CheckPoint::time, ControlFileData::time, TYPEALIGN, WAIT_EVENT_WAL_BOOTSTRAP_SYNC, WAIT_EVENT_WAL_BOOTSTRAP_WRITE, wal_segment_size, write, WriteControlFile(), XLogRecord::xl_info, XLogRecord::xl_prev, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLogRecord::xl_xid, XLOG_CHECKPOINT_SHUTDOWN, XLOG_PAGE_MAGIC, XLogFileInit(), XLogPageHeaderData::xlp_info, XLP_LONG_HEADER, XLogPageHeaderData::xlp_magic, XLogPageHeaderData::xlp_pageaddr, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, XLogPageHeaderData::xlp_tli, XLogLongPageHeaderData::xlp_xlog_blcksz, and XLR_BLOCK_ID_DATA_SHORT.

Referenced by AuxiliaryProcessMain().

5267 {
5268  CheckPoint checkPoint;
5269  char *buffer;
5270  XLogPageHeader page;
5271  XLogLongPageHeader longpage;
5272  XLogRecord *record;
5273  char *recptr;
5274  uint64 sysidentifier;
5275  struct timeval tv;
5276  pg_crc32c crc;
5277 
5278  /* allow ordinary WAL segment creation, like StartupXLOG() would */
5279  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5281  LWLockRelease(ControlFileLock);
5282 
5283  /*
5284  * Select a hopefully-unique system identifier code for this installation.
5285  * We use the result of gettimeofday(), including the fractional seconds
5286  * field, as being about as unique as we can easily get. (Think not to
5287  * use random(), since it hasn't been seeded and there's no portable way
5288  * to seed it other than the system clock value...) The upper half of the
5289  * uint64 value is just the tv_sec part, while the lower half contains the
5290  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
5291  * PID for a little extra uniqueness. A person knowing this encoding can
5292  * determine the initialization time of the installation, which could
5293  * perhaps be useful sometimes.
5294  */
5295  gettimeofday(&tv, NULL);
5296  sysidentifier = ((uint64) tv.tv_sec) << 32;
5297  sysidentifier |= ((uint64) tv.tv_usec) << 12;
5298  sysidentifier |= getpid() & 0xFFF;
5299 
5300  /* First timeline ID is always 1 */
5301  ThisTimeLineID = 1;
5302 
5303  /* page buffer must be aligned suitably for O_DIRECT */
5304  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
5305  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
5306  memset(page, 0, XLOG_BLCKSZ);
5307 
5308  /*
5309  * Set up information for the initial checkpoint record
5310  *
5311  * The initial checkpoint record is written to the beginning of the WAL
5312  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
5313  * used, so that we can use 0/0 to mean "before any valid WAL segment".
5314  */
5315  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
5316  checkPoint.ThisTimeLineID = ThisTimeLineID;
5317  checkPoint.PrevTimeLineID = ThisTimeLineID;
5318  checkPoint.fullPageWrites = fullPageWrites;
5319  checkPoint.nextXid =
5321  checkPoint.nextOid = FirstGenbkiObjectId;
5322  checkPoint.nextMulti = FirstMultiXactId;
5323  checkPoint.nextMultiOffset = 0;
5324  checkPoint.oldestXid = FirstNormalTransactionId;
5325  checkPoint.oldestXidDB = TemplateDbOid;
5326  checkPoint.oldestMulti = FirstMultiXactId;
5327  checkPoint.oldestMultiDB = TemplateDbOid;
5330  checkPoint.time = (pg_time_t) time(NULL);
5332 
5333  ShmemVariableCache->nextXid = checkPoint.nextXid;
5334  ShmemVariableCache->nextOid = checkPoint.nextOid;
5336  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5337  AdvanceOldestClogXid(checkPoint.oldestXid);
5338  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5339  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5341 
5342  /* Set up the XLOG page header */
5343  page->xlp_magic = XLOG_PAGE_MAGIC;
5344  page->xlp_info = XLP_LONG_HEADER;
5345  page->xlp_tli = ThisTimeLineID;
5347  longpage = (XLogLongPageHeader) page;
5348  longpage->xlp_sysid = sysidentifier;
5349  longpage->xlp_seg_size = wal_segment_size;
5350  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
5351 
5352  /* Insert the initial checkpoint record */
5353  recptr = ((char *) page + SizeOfXLogLongPHD);
5354  record = (XLogRecord *) recptr;
5355  record->xl_prev = 0;
5356  record->xl_xid = InvalidTransactionId;
5357  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
5359  record->xl_rmid = RM_XLOG_ID;
5360  recptr += SizeOfXLogRecord;
5361  /* fill the XLogRecordDataHeaderShort struct */
5362  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
5363  *(recptr++) = sizeof(checkPoint);
5364  memcpy(recptr, &checkPoint, sizeof(checkPoint));
5365  recptr += sizeof(checkPoint);
5366  Assert(recptr - (char *) record == record->xl_tot_len);
5367 
5368  INIT_CRC32C(crc);
5369  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
5370  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
5371  FIN_CRC32C(crc);
5372  record->xl_crc = crc;
5373 
5374  /* Create first XLOG segment file */
5376 
5377  /*
5378  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
5379  * close the file again in a moment.
5380  */
5381 
5382  /* Write the first page with the initial record */
5383  errno = 0;
5385  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
5386  {
5387  /* if write didn't set errno, assume problem is no disk space */
5388  if (errno == 0)
5389  errno = ENOSPC;
5390  ereport(PANIC,
5392  errmsg("could not write bootstrap write-ahead log file: %m")));
5393  }
5395 
5397  if (pg_fsync(openLogFile) != 0)
5398  ereport(PANIC,
5400  errmsg("could not fsync bootstrap write-ahead log file: %m")));
5402 
5403  if (close(openLogFile) != 0)
5404  ereport(PANIC,
5406  errmsg("could not close bootstrap write-ahead log file: %m")));
5407 
5408  openLogFile = -1;
5409 
5410  /* Now create pg_control */
5411  InitControlFile(sysidentifier);
5412  ControlFile->time = checkPoint.time;
5413  ControlFile->checkPoint = checkPoint.redo;
5414  ControlFile->checkPointCopy = checkPoint;
5415 
5416  /* some additional ControlFile fields are set in WriteControlFile() */
5417  WriteControlFile();
5418 
5419  /* Bootstrap the commit log, too */
5420  BootStrapCLOG();
5424 
5425  pfree(buffer);
5426 
5427  /*
5428  * Force control file to be read - in contrast to normal processing we'd
5429  * otherwise never run the checks and GUC related initializations therein.
5430  */
5431  ReadControlFile();
5432 }
static void WriteControlFile(void)
Definition: xlog.c:4681
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
int64 pg_time_t
Definition: pgtime.h:23
static void pgstat_report_wait_end(void)
Definition: wait_event.h:278
int wal_segment_size
Definition: xlog.c:119
pg_time_t time
Definition: pg_control.h:128
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:876
uint32 oidCount
Definition: transam.h:215
#define write(a, b, c)
Definition: win32.h:14
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:204
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:63
void BootStrapMultiXact(void)
Definition: multixact.c:1894
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:4646
int XLogFileInit(XLogSegNo logsegno)
Definition: xlog.c:3466
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
FullTransactionId nextXid
Definition: transam.h:220
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:50
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool fullPageWrites
Definition: xlog.c:99
void BootStrapSUBTRANS(void)
Definition: subtrans.c:211
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1169
#define FirstNormalTransactionId
Definition: transam.h:34
uint32 xl_tot_len
Definition: xlogrecord.h:43
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
static void ReadControlFile(void)
Definition: xlog.c:4772
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
int errcode_for_file_access(void)
Definition: elog.c:721
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
#define FirstMultiXactId
Definition: multixact.h:25
bool InstallXLogFileSegmentActive
Definition: xlog.c:673
TimeLineID xlp_tli
Definition: xlog_internal.h:40
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:262
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:817
static ControlFileData * ControlFile
Definition: xlog.c:756
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2213
TimeLineID ThisTimeLineID
Definition: xlog.c:194
Oid nextOid
Definition: pg_control.h:44
#define ereport(elevel,...)
Definition: elog.h:157
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:750
bool fullPageWrites
Definition: pg_control.h:42
void BootStrapCLOG(void)
Definition: clog.c:712
#define Assert(condition)
Definition: c.h:804
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
Oid oldestXidDB
Definition: pg_control.h:48
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:345
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:45
static XLogCtlData * XLogCtl
Definition: xlog.c:748
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:227
TransactionId xl_xid
Definition: xlogrecord.h:44
#define FirstGenbkiObjectId
Definition: transam.h:195
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pg_fsync(int fd)
Definition: fd.c:352
#define close(a)
Definition: win32.h:12
void BootStrapCommitTs(void)
Definition: commit_ts.c:569
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
#define offsetof(type, field)
Definition: c.h:727
FullTransactionId nextXid
Definition: pg_control.h:43
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2179

◆ CalculateCheckpointSegments()

static void CalculateCheckpointSegments ( void  )
static

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

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

◆ CancelBackup()

void CancelBackup ( void  )

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

12105 {
12106  struct stat stat_buf;
12107 
12108  /* if the backup_label file is not there, return */
12109  if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
12110  return;
12111 
12112  /* remove leftover file from previously canceled backup if it exists */
12113  unlink(BACKUP_LABEL_OLD);
12114 
12116  {
12117  ereport(WARNING,
12119  errmsg("online backup mode was not canceled"),
12120  errdetail("File \"%s\" could not be renamed to \"%s\": %m.",
12122  return;
12123  }
12124 
12125  /* if the tablespace_map file is not there, return */
12126  if (stat(TABLESPACE_MAP, &stat_buf) < 0)
12127  {
12128  ereport(LOG,
12129  (errmsg("online backup mode canceled"),
12130  errdetail("File \"%s\" was renamed to \"%s\".",
12132  return;
12133  }
12134 
12135  /* remove leftover file from previously canceled backup if it exists */
12136  unlink(TABLESPACE_MAP_OLD);
12137 
12139  {
12140  ereport(LOG,
12141  (errmsg("online backup mode canceled"),
12142  errdetail("Files \"%s\" and \"%s\" were renamed to "
12143  "\"%s\" and \"%s\", respectively.",
12146  }
12147  else
12148  {
12149  ereport(WARNING,
12151  errmsg("online backup mode canceled"),
12152  errdetail("File \"%s\" was renamed to \"%s\", but "
12153  "file \"%s\" could not be renamed to \"%s\": %m.",
12156  }
12157 }
#define DEBUG1
Definition: elog.h:25
#define LOG
Definition: elog.h:26
#define BACKUP_LABEL_OLD
Definition: xlog.h:406
#define TABLESPACE_MAP
Definition: xlog.h:408
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int errcode_for_file_access(void)
Definition: elog.c:721
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:692
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
#define TABLESPACE_MAP_OLD
Definition: xlog.h:409
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define BACKUP_LABEL_FILE
Definition: xlog.h:405
#define stat
Definition: win32_port.h:275

◆ check_wal_buffers()

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

Definition at line 5057 of file xlog.c.

References XLOGbuffers, and XLOGChooseNumBuffers().

5058 {
5059  /*
5060  * -1 indicates a request for auto-tune.
5061  */
5062  if (*newval == -1)
5063  {
5064  /*
5065  * If we haven't yet changed the boot_val default of -1, just let it
5066  * be. We'll fix it when XLOGShmemSize is called.
5067  */
5068  if (XLOGbuffers == -1)
5069  return true;
5070 
5071  /* Otherwise, substitute the auto-tune value */
5073  }
5074 
5075  /*
5076  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
5077  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
5078  * the case, we just silently treat such values as a request for the
5079  * minimum. (We could throw an error instead, but that doesn't seem very
5080  * helpful.)
5081  */
5082  if (*newval < 4)
5083  *newval = 4;
5084 
5085  return true;
5086 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:5041
#define newval
int XLOGbuffers
Definition: xlog.c:94

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 12936 of file xlog.c.

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

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

12937 {
12938  struct stat stat_buf;
12939 
12941  return true;
12942 
12944  {
12945  ereport(LOG, (errmsg("received promote request")));
12949  return true;
12950  }
12951 
12952  if (PromoteTriggerFile == NULL || strcmp(PromoteTriggerFile, "") == 0)
12953  return false;
12954 
12955  if (stat(PromoteTriggerFile, &stat_buf) == 0)
12956  {
12957  ereport(LOG,
12958  (errmsg("promote trigger file found: %s", PromoteTriggerFile)));
12959  unlink(PromoteTriggerFile);
12961  return true;
12962  }
12963  else if (errno != ENOENT)
12964  ereport(ERROR,
12966  errmsg("could not stat promote trigger file \"%s\": %m",
12967  PromoteTriggerFile)));
12968 
12969  return false;
12970 }
char * PromoteTriggerFile
Definition: xlog.c:299
bool CheckPromoteSignal(void)
Definition: xlog.c:12985
bool IsPromoteSignaled(void)
Definition: startup.c:274
static bool LocalPromoteIsTriggered
Definition: xlog.c:243
#define LOG
Definition: elog.h:26
static void SetPromoteIsTriggered(void)
Definition: xlog.c:12914
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
void RemovePromoteSignalFiles(void)
Definition: xlog.c:12976
#define ereport(elevel,...)
Definition: elog.h:157
void ResetPromoteSignaled(void)
Definition: startup.c:280
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define stat
Definition: win32_port.h:275

◆ CheckPointGuts()

static void CheckPointGuts ( XLogRecPtr  checkPointRedo,
int  flags 
)
static

Definition at line 9403 of file xlog.c.

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

Referenced by CreateCheckPoint(), and CreateRestartPoint().

9404 {
9410 
9411  /* Write out all dirty data in SLRUs and the main buffer pool */
9412  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
9414  CheckPointCLOG();
9419  CheckPointBuffers(flags);
9420 
9421  /* Perform all queued up fsyncs */
9422  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
9426  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
9427 
9428  /* We deliberately delay 2PC checkpointing as long as possible */
9429  CheckPointTwoPhase(checkPointRedo);
9430 }
void ProcessSyncRequests(void)
Definition: sync.c:257
void CheckPointBuffers(int flags)
Definition: bufmgr.c:2728
TimestampTz ckpt_sync_end_t
Definition: xlog.h:266
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1192
void CheckPointReplicationOrigin(void)
Definition: origin.c:557
void CheckPointSnapBuild(void)
Definition: snapbuild.c:1907
void CheckPointCLOG(void)
Definition: clog.c:818
void CheckPointMultiXact(void)
Definition: multixact.c:2155
void CheckPointCommitTs(void)
Definition: commit_ts.c:790
CheckpointStatsData CheckpointStats
Definition: xlog.c:188
TimestampTz ckpt_write_t
Definition: xlog.h:264
void CheckPointSUBTRANS(void)
Definition: subtrans.c:284
void CheckPointRelationMap(void)
Definition: relmapper.c:546
TimestampTz ckpt_sync_t
Definition: xlog.h:265
void CheckPointPredicate(void)
Definition: predicate.c:1069
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1703
void CheckPointReplicationSlots(void)
Definition: slot.c:1348

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 12985 of file xlog.c.

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and sigusr1_handler().

12986 {
12987  struct stat stat_buf;
12988 
12989  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12990  return true;
12991 
12992  return false;
12993 }
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:412
#define stat
Definition: win32_port.h:275

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 8148 of file xlog.c.

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

Referenced by ReadRecord(), and StartupXLOG().

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

◆ CheckRequiredParameterValues()

static void CheckRequiredParameterValues ( void  )
static

Definition at line 6430 of file xlog.c.

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

Referenced by StartupXLOG(), and xlog_redo().

6431 {
6432  /*
6433  * For archive recovery, the WAL must be generated with at least 'replica'
6434  * wal_level.
6435  */
6437  {
6438  ereport(FATAL,
6439  (errmsg("WAL was generated with wal_level=minimal, cannot continue recovering"),
6440  errdetail("This happens if you temporarily set wal_level=minimal on the server."),
6441  errhint("Use a backup taken after setting wal_level to higher than minimal.")));
6442  }
6443 
6444  /*
6445  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
6446  * must have at least as many backend slots as the primary.
6447  */
6449  {
6450  /* We ignore autovacuum_max_workers when we make this test. */
6451  RecoveryRequiresIntParameter("max_connections",
6454  RecoveryRequiresIntParameter("max_worker_processes",
6457  RecoveryRequiresIntParameter("max_wal_senders",
6460  RecoveryRequiresIntParameter("max_prepared_transactions",
6463  RecoveryRequiresIntParameter("max_locks_per_transaction",
6466  }
6467 }
bool ArchiveRecoveryRequested
Definition: xlog.c:268
int max_locks_per_xact
Definition: pg_control.h:182
int errhint(const char *fmt,...)
Definition: elog.c:1156
int max_prepared_xacts
Definition: pg_control.h:181
static void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue)
Definition: xlog.c:6345
int max_worker_processes
Definition: pg_control.h:179
int max_prepared_xacts
Definition: twophase.c:117
#define FATAL
Definition: elog.h:49
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int max_locks_per_xact
Definition: lock.c:54
int max_wal_senders
Definition: walsender.c:121
int MaxConnections
Definition: globals.c:136
static ControlFileData * ControlFile
Definition: xlog.c:756
#define ereport(elevel,...)
Definition: elog.h:157
bool EnableHotStandby
Definition: xlog.c:98
int errmsg(const char *fmt,...)
Definition: elog.c:909
int max_worker_processes
Definition: globals.c:137

◆ checkTimeLineSwitch()

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

Definition at line 10101 of file xlog.c.

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

Referenced by StartupXLOG().

10102 {
10103  /* Check that the record agrees on what the current (old) timeline is */
10104  if (prevTLI != ThisTimeLineID)
10105  ereport(PANIC,
10106  (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
10107  prevTLI, ThisTimeLineID)));
10108 
10109  /*
10110  * The new timeline better be in the list of timelines we expect to see,
10111  * according to the timeline history. It should also not decrease.
10112  */
10113  if (newTLI < ThisTimeLineID || !tliInHistory(newTLI, expectedTLEs))
10114  ereport(PANIC,
10115  (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
10116  newTLI, ThisTimeLineID)));
10117 
10118  /*
10119  * If we have not yet reached min recovery point, and we're about to
10120  * switch to a timeline greater than the timeline of the min recovery
10121  * point: trouble. After switching to the new timeline, we could not
10122  * possibly visit the min recovery point on the correct timeline anymore.
10123  * This can happen if there is a newer timeline in the archive that
10124  * branched before the timeline the min recovery point is on, and you
10125  * attempt to do PITR to the new timeline.
10126  */
10128  lsn < minRecoveryPoint &&
10129  newTLI > minRecoveryPointTLI)
10130  ereport(PANIC,
10131  (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
10132  newTLI,
10135 
10136  /* Looks good */
10137 }
static List * expectedTLEs
Definition: xlog.c:344
#define PANIC
Definition: elog.h:50
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:879
TimeLineID ThisTimeLineID
Definition: xlog.c:194
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:534
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:878

◆ checkXLogConsistency()

static void checkXLogConsistency ( XLogReaderState record)
static

Definition at line 1424 of file xlog.c.

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

Referenced by StartupXLOG().

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

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

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

3996 {
3997  int save_errno = errno;
3998  XLogSegNo lastRemovedSegNo;
3999 
4001  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
4003 
4004  if (segno <= lastRemovedSegNo)
4005  {
4006  char filename[MAXFNAMELEN];
4007 
4008  XLogFileName(filename, tli, segno, wal_segment_size);
4009  errno = save_errno;
4010  ereport(ERROR,
4012  errmsg("requested WAL segment %s has already been removed",
4013  filename)));
4014  }
4015  errno = save_errno;
4016 }
int wal_segment_size
Definition: xlog.c:119
slock_t info_lck
Definition: xlog.c:745
XLogSegNo lastRemovedSegNo
Definition: xlog.c:607
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:46
uint64 XLogSegNo
Definition: xlogdefs.h:48
int errcode_for_file_access(void)
Definition: elog.c:721
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
#define ereport(elevel,...)
Definition: elog.h:157
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static XLogCtlData * XLogCtl
Definition: xlog.c:748
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

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

4361 {
4362  DIR *xldir;
4363  struct dirent *xlde;
4364  char path[MAXPGPATH + sizeof(XLOGDIR)];
4365 
4366  xldir = AllocateDir(XLOGDIR);
4367 
4368  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
4369  {
4370  if (IsBackupHistoryFileName(xlde->d_name))
4371  {
4372  if (XLogArchiveCheckDone(xlde->d_name))
4373  {
4374  elog(DEBUG2, "removing WAL backup history file \"%s\"",
4375  xlde->d_name);
4376  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
4377  unlink(path);
4378  XLogArchiveCleanup(xlde->d_name);
4379  }
4380  }
4381  }
4382 
4383  FreeDir(xldir);
4384 }
Definition: dirent.h:9
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:719
Definition: dirent.c:25
bool XLogArchiveCheckDone(const char *xlog)
Definition: xlogarchive.c:572
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2678
#define IsBackupHistoryFileName(fname)
#define XLOGDIR
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2744
#define elog(elevel,...)
Definition: elog.h:232
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2796

◆ ConfirmRecoveryPaused()

static void ConfirmRecoveryPaused ( void  )
static

Definition at line 6162 of file xlog.c.

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

Referenced by recoveryPausesHere(), and RecoveryRequiresIntParameter().

6163 {
6164  /* If recovery pause is requested then set it paused */
6169 }
RecoveryPauseState recoveryPauseState
Definition: xlog.c:736
slock_t info_lck
Definition: xlog.c:745
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
static XLogCtlData * XLogCtl
Definition: xlog.c:748

◆ CopyXLogRecordToWAL()

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

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

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

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 8930 of file xlog.c.

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

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

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

◆ CreateEndOfRecoveryRecord()

static void CreateEndOfRecoveryRecord ( void  )
static

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

9355 {
9356  xl_end_of_recovery xlrec;
9357  XLogRecPtr recptr;
9358 
9359  /* sanity check */
9360  if (!RecoveryInProgress())
9361  elog(ERROR, "can only be used to end recovery");
9362 
9363  xlrec.end_time = GetCurrentTimestamp();
9364 
9369 
9371 
9373 
9374  XLogBeginInsert();
9375  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
9376  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
9377 
9378  XLogFlush(recptr);
9379 
9380  /*
9381  * Update the control file so that crash recovery can follow the timeline
9382  * changes to this point.
9383  */
9384  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9385  ControlFile->time = (pg_time_t) time(NULL);
9386  ControlFile->minRecoveryPoint = recptr;
9389  LWLockRelease(ControlFileLock);
9390 
9391  END_CRIT_SECTION();
9392 
9393  LocalXLogInsertAllowed = -1; /* return to "check" state */
9394 }
static int LocalXLogInsertAllowed
Definition: xlog.c:255
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1746
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimeLineID PrevTimeLineID
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1580
#define END_CRIT_SECTION()
Definition: miscadmin.h:149
TimeLineID PrevTimeLineID
Definition: xlog.c:651
#define START_CRIT_SECTION()
Definition: miscadmin.h:147
bool RecoveryInProgress(void)
Definition: xlog.c:8248
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2881
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
void UpdateControlFile(void)
Definition: xlog.c:4972
#define ERROR
Definition: elog.h:46
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8392
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:432
static ControlFileData * ControlFile
Definition: xlog.c:756
TimeLineID ThisTimeLineID
Definition: xlog.c:194
TimestampTz end_time
uint64 XLogRecPtr
Definition: xlogdefs.h:21
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1717
static XLogCtlData * XLogCtl
Definition: xlog.c:748
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
TimeLineID ThisTimeLineID
#define elog(elevel,...)
Definition: elog.h:232
void XLogBeginInsert(void)
Definition: xloginsert.c:135
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 9484 of file xlog.c.

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

Referenced by CheckpointerMain(), and ShutdownXLOG().

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

◆ DataChecksumsEnabled()

bool DataChecksumsEnabled ( void  )

Definition at line 5001 of file xlog.c.

References Assert, and ControlFileData::data_checksum_version.

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

5002 {
5003  Assert(ControlFile != NULL);
5004  return (ControlFile->data_checksum_version > 0);
5005 }
uint32 data_checksum_version
Definition: pg_control.h:220
static ControlFileData * ControlFile
Definition: xlog.c:756
#define Assert(condition)
Definition: c.h:804

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

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

11726 {
11727  bool emit_warning = DatumGetBool(arg);
11728 
11729  /*
11730  * Quick exit if session is not keeping around a non-exclusive backup
11731  * already started.
11732  */
11734  return;
11735 
11739 
11742  {
11743  XLogCtl->Insert.forcePageWrites = false;
11744  }
11746 
11747  if (emit_warning)
11748  ereport(WARNING,
11749  (errmsg("aborting backup due to backend exiting before pg_stop_backup was called")));
11750 }
static void WALInsertLockRelease(void)
Definition: xlog.c:1746
static SessionBackupState sessionBackupState
Definition: xlog.c:532
XLogCtlInsert Insert
Definition: xlog.c:598
bool forcePageWrites
Definition: xlog.c:572
#define DatumGetBool(X)
Definition: postgres.h:437
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:584
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:583
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1717
static XLogCtlData * XLogCtl
Definition: xlog.c:748
int errmsg(const char *fmt,...)
Definition: elog.c:909
void * arg

◆ do_pg_start_backup()

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

Definition at line 10792 of file xlog.c.

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

Referenced by perform_base_backup(), and pg_start_backup().

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

◆ do_pg_stop_backup()

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

Definition at line 11310 of file xlog.c.

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

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

11311 {
11312  bool exclusive = (labelfile == NULL);
11313  bool backup_started_in_recovery = false;
11314  XLogRecPtr startpoint;
11315  XLogRecPtr stoppoint;
11316  TimeLineID stoptli;
11317  pg_time_t stamp_time;
11318  char strfbuf[128];
11319  char histfilepath[MAXPGPATH];
11320  char startxlogfilename[MAXFNAMELEN];
11321  char stopxlogfilename[MAXFNAMELEN];
11322  char lastxlogfilename[MAXFNAMELEN];
11323  char histfilename[MAXFNAMELEN];
11324  char backupfrom[20];
11325  XLogSegNo _logSegNo;
11326  FILE *lfp;
11327  FILE *fp;
11328  char ch;
11329  int seconds_before_warning;
11330  int waits = 0;
11331  bool reported_waiting = false;
11332  char *remaining;
11333  char *ptr;
11334  uint32 hi,
11335  lo;
11336 
11337  backup_started_in_recovery = RecoveryInProgress();
11338 
11339  /*
11340  * Currently only non-exclusive backup can be taken during recovery.
11341  */
11342  if (backup_started_in_recovery && exclusive)
11343  ereport(ERROR,
11344  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11345  errmsg("recovery is in progress"),
11346  errhint("WAL control functions cannot be executed during recovery.")));
11347 
11348  /*
11349  * During recovery, we don't need to check WAL level. Because, if WAL
11350  * level is not sufficient, it's impossible to get here during recovery.
11351  */
11352  if (!backup_started_in_recovery && !XLogIsNeeded())
11353  ereport(ERROR,
11354  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11355  errmsg("WAL level not sufficient for making an online backup"),
11356  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
11357 
11358  if (exclusive)
11359  {
11360  /*
11361  * At first, mark that we're now stopping an exclusive backup, to
11362  * ensure that there are no other sessions currently running
11363  * pg_start_backup() or pg_stop_backup().
11364  */
11367  {
11369  ereport(ERROR,
11370  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11371  errmsg("exclusive backup not in progress")));
11372  }
11375 
11376  /*
11377  * Remove backup_label. In case of failure, the state for an exclusive
11378  * backup is switched back to in-progress.
11379  */
11381  {
11382  /*
11383  * Read the existing label file into memory.
11384  */
11385  struct stat statbuf;
11386  int r;
11387 
11388  if (stat(BACKUP_LABEL_FILE, &statbuf))
11389  {
11390  /* should not happen per the upper checks */
11391  if (errno != ENOENT)
11392  ereport(ERROR,
11394  errmsg("could not stat file \"%s\": %m",
11395  BACKUP_LABEL_FILE)));
11396  ereport(ERROR,
11397  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11398  errmsg("a backup is not in progress")));
11399  }
11400 
11401  lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
11402  if (!lfp)
11403  {
11404  ereport(ERROR,
11406  errmsg("could not read file \"%s\": %m",
11407  BACKUP_LABEL_FILE)));
11408  }
11409  labelfile = palloc(statbuf.st_size + 1);
11410  r = fread(labelfile, statbuf.st_size, 1, lfp);
11411  labelfile[statbuf.st_size] = '\0';
11412 
11413  /*
11414  * Close and remove the backup label file
11415  */
11416  if (r != 1 || ferror(lfp) || FreeFile(lfp))
11417  ereport(ERROR,
11419  errmsg("could not read file \"%s\": %m",
11420  BACKUP_LABEL_FILE)));
11422 
11423  /*
11424  * Remove tablespace_map file if present, it is created only if
11425  * there are tablespaces.
11426  */
11428  }
11430  }
11431 
11432  /*
11433  * OK to update backup counters, forcePageWrites and session-level lock.
11434  *
11435  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
11436  * Otherwise they can be updated inconsistently, and which might cause
11437  * do_pg_abort_backup() to fail.
11438  */
11440  if (exclusive)
11441  {
11443  }
11444  else
11445  {
11446  /*
11447  * The user-visible pg_start/stop_backup() functions that operate on
11448  * exclusive backups can be called at any time, but for non-exclusive
11449  * backups, it is expected that each do_pg_start_backup() call is
11450  * matched by exactly one do_pg_stop_backup() call.
11451  */
11454  }
11455 
11458  {
11459  XLogCtl->Insert.forcePageWrites = false;
11460  }
11461 
11462  /*
11463  * Clean up session-level lock.
11464  *
11465  * You might think that WALInsertLockRelease() can be called before
11466  * cleaning up session-level lock because session-level lock doesn't need
11467  * to be protected with WAL insertion lock. But since
11468  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
11469  * cleaned up before it.
11470  */
11472 
11474 
11475  /*
11476  * Read and parse the START WAL LOCATION line (this code is pretty crude,
11477  * but we are not expecting any variability in the file format).
11478  */
11479  if (sscanf(labelfile, "START WAL LOCATION: %X/%X (file %24s)%c",
11480  &hi, &lo, startxlogfilename,
11481  &ch) != 4 || ch != '\n')
11482  ereport(ERROR,
11483  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11484  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
11485  startpoint = ((uint64) hi) << 32 | lo;
11486  remaining = strchr(labelfile, '\n') + 1; /* %n is not portable enough */
11487 
11488  /*
11489  * Parse the BACKUP FROM line. If we are taking an online backup from the
11490  * standby, we confirm that the standby has not been promoted during the
11491  * backup.
11492  */
11493  ptr = strstr(remaining, "BACKUP FROM:");
11494  if (!ptr || sscanf(ptr, "BACKUP FROM: %19s\n", backupfrom) != 1)
11495  ereport(ERROR,
11496  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11497  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
11498  if (strcmp(backupfrom, "standby") == 0 && !backup_started_in_recovery)
11499  ereport(ERROR,
11500  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11501  errmsg("the standby was promoted during online backup"),
11502  errhint("This means that the backup being taken is corrupt "
11503  "and should not be used. "
11504  "Try taking another online backup.")));
11505 
11506  /*
11507  * During recovery, we don't write an end-of-backup record. We assume that
11508  * pg_control was backed up last and its minimum recovery point can be
11509  * available as the backup end location. Since we don't have an
11510  * end-of-backup record, we use the pg_control value to check whether
11511  * we've reached the end of backup when starting recovery from this
11512  * backup. We have no way of checking if pg_control wasn't backed up last
11513  * however.
11514  *
11515  * We don't force a switch to new WAL file but it is still possible to
11516  * wait for all the required files to be archived if waitforarchive is
11517  * true. This is okay if we use the backup to start a standby and fetch
11518  * the missing WAL using streaming replication. But in the case of an
11519  * archive recovery, a user should set waitforarchive to true and wait for
11520  * them to be archived to ensure that all the required files are
11521  * available.
11522  *
11523  * We return the current minimum recovery point as the backup end
11524  * location. Note that it can be greater than the exact backup end
11525  * location if the minimum recovery point is updated after the backup of
11526  * pg_control. This is harmless for current uses.
11527  *
11528  * XXX currently a backup history file is for informational and debug
11529  * purposes only. It's not essential for an online backup. Furthermore,
11530  * even if it's created, it will not be archived during recovery because
11531  * an archiver is not invoked. So it doesn't seem worthwhile to write a
11532  * backup history file during recovery.
11533  */
11534  if (backup_started_in_recovery)
11535  {
11536  XLogRecPtr recptr;
11537 
11538  /*
11539  * Check to see if all WAL replayed during online backup contain
11540  * full-page writes.
11541  */
11543  recptr = XLogCtl->lastFpwDisableRecPtr;
11545 
11546  if (startpoint <= recptr)
11547  ereport(ERROR,
11548  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11549  errmsg("WAL generated with full_page_writes=off was replayed "
11550  "during online backup"),
11551  errhint("This means that the backup being taken on the standby "
11552  "is corrupt and should not be used. "
11553  "Enable full_page_writes and run CHECKPOINT on the primary, "
11554  "and then try an online backup again.")));
11555 
11556 
11557  LWLockAcquire(ControlFileLock, LW_SHARED);
11558  stoppoint = ControlFile->minRecoveryPoint;
11559  stoptli = ControlFile->minRecoveryPointTLI;
11560  LWLockRelease(ControlFileLock);
11561  }
11562  else
11563  {
11564  /*
11565  * Write the backup-end xlog record
11566  */
11567  XLogBeginInsert();
11568  XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
11569  stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
11570  stoptli = ThisTimeLineID;
11571 
11572  /*
11573  * Force a switch to a new xlog segment file, so that the backup is
11574  * valid as soon as archiver moves out the current segment file.
11575  */
11576  RequestXLogSwitch(false);
11577 
11578  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11579  XLogFileName(stopxlogfilename, stoptli, _logSegNo, wal_segment_size);
11580 
11581  /* Use the log timezone here, not the session timezone */
11582  stamp_time = (pg_time_t) time(NULL);
11583  pg_strftime(strfbuf, sizeof(strfbuf),
11584  "%Y-%m-%d %H:%M:%S %Z",
11585  pg_localtime(&stamp_time, log_timezone));
11586 
11587  /*
11588  * Write the backup history file
11589  */
11590  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11591  BackupHistoryFilePath(histfilepath, stoptli, _logSegNo,
11592  startpoint, wal_segment_size);
11593  fp = AllocateFile(histfilepath, "w");
11594  if (!fp)
11595  ereport(ERROR,
11597  errmsg("could not create file \"%s\": %m",
11598  histfilepath)));
11599  fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
11600  LSN_FORMAT_ARGS(startpoint), startxlogfilename);
11601  fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
11602  LSN_FORMAT_ARGS(stoppoint), stopxlogfilename);
11603 
11604  /*
11605  * Transfer remaining lines including label and start timeline to
11606  * history file.
11607  */
11608  fprintf(fp, "%s", remaining);
11609  fprintf(fp, "STOP TIME: %s\n", strfbuf);
11610  fprintf(fp, "STOP TIMELINE: %u\n", stoptli);
11611  if (fflush(fp) || ferror(fp) || FreeFile(fp))
11612  ereport(ERROR,
11614  errmsg("could not write file \"%s\": %m",
11615  histfilepath)));
11616 
11617  /*
11618  * Clean out any no-longer-needed history files. As a side effect,
11619  * this will post a .ready file for the newly created history file,
11620  * notifying the archiver that history file may be archived
11621  * immediately.
11622  */
11624  }
11625 
11626  /*
11627  * If archiving is enabled, wait for all the required WAL files to be
11628  * archived before returning. If archiving isn't enabled, the required WAL
11629  * needs to be transported via streaming replication (hopefully with
11630  * wal_keep_size set high enough), or some more exotic mechanism like
11631  * polling and copying files from pg_wal with script. We have no knowledge
11632  * of those mechanisms, so it's up to the user to ensure that he gets all
11633  * the required WAL.
11634  *
11635  * We wait until both the last WAL file filled during backup and the
11636  * history file have been archived, and assume that the alphabetic sorting
11637  * property of the WAL files ensures any earlier WAL files are safely
11638  * archived as well.
11639  *
11640  * We wait forever, since archive_command is supposed to work and we
11641  * assume the admin wanted his backup to work completely. If you don't
11642  * wish to wait, then either waitforarchive should be passed in as false,
11643  * or you can set statement_timeout. Also, some notices are issued to
11644  * clue in anyone who might be doing this interactively.
11645  */
11646 
11647  if (waitforarchive &&
11648  ((!backup_started_in_recovery && XLogArchivingActive()) ||
11649  (backup_started_in_recovery && XLogArchivingAlways())))
11650  {
11651  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11652  XLogFileName(lastxlogfilename, stoptli, _logSegNo, wal_segment_size);
11653 
11654  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11655  BackupHistoryFileName(histfilename, stoptli, _logSegNo,
11656  startpoint, wal_segment_size);
11657 
11658  seconds_before_warning = 60;
11659  waits = 0;
11660 
11661  while (XLogArchiveIsBusy(lastxlogfilename) ||
11662  XLogArchiveIsBusy(histfilename))
11663  {
11665 
11666  if (!reported_waiting && waits > 5)
11667  {
11668  ereport(NOTICE,
11669  (errmsg("base backup done, waiting for required WAL segments to be archived")));
11670  reported_waiting = true;
11671  }
11672 
11673  (void) WaitLatch(MyLatch,
11675  1000L,
11678 
11679  if (++waits >= seconds_before_warning)
11680  {
11681  seconds_before_warning *= 2; /* This wraps in >10 years... */
11682  ereport(WARNING,
11683  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
11684  waits),
11685  errhint("Check that your archive_command is executing properly. "
11686  "You can safely cancel this backup, "
11687  "but the database backup will not be usable without all the WAL segments.")));
11688  }
11689  }
11690 
11691  ereport(NOTICE,
11692  (errmsg("all required WAL segments have been archived")));
11693  }
11694  else if (waitforarchive)
11695  ereport(NOTICE,
11696  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
11697 
11698  /*
11699  * We're done. As a convenience, return the ending WAL location.
11700  */
11701  if (stoptli_p)
11702  *stoptli_p = stoptli;
11703  return stoppoint;
11704 }
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:9929
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:1156
uint32 TimeLineID
Definition: xlogdefs.h:59
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1746
#define WL_TIMEOUT
Definition: latch.h:128
int wal_segment_size
Definition: xlog.c:119
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:743
static SessionBackupState sessionBackupState
Definition: xlog.c:532
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogIsNeeded()
Definition: xlog.h:208
slock_t info_lck
Definition: xlog.c:745
int errcode(int sqlerrcode)
Definition: elog.c:698
XLogCtlInsert Insert
Definition: xlog.c:598
#define BackupHistoryFileName(fname, tli, logSegNo, startpoint, wal_segsz_bytes)
bool RecoveryInProgress(void)
Definition: xlog.c:8248
static bool backup_started_in_recovery
Definition: basebackup.c:88
#define fprintf
Definition: port.h:220
void ResetLatch(Latch *latch)
Definition: latch.c:660
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:452
pg_tz * log_timezone
Definition: pgtz.c:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define TABLESPACE_MAP
Definition: xlog.h:408
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define XLogArchivingAlways()
Definition: xlog.h:200
bool forcePageWrites
Definition: xlog.c:572
#define ERROR
Definition: elog.h:46
static void CleanupBackupHistory(void)
Definition: xlog.c:4360
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:48
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2417
unsigned int uint32
Definition: c.h:441
#define XLOG_BACKUP_END
Definition: pg_control.h:72
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:584
#define MAXFNAMELEN
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:340
#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:432
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:583
uintptr_t Datum
Definition: postgres.h:411
static ControlFileData * ControlFile
Definition: xlog.c:756
#define BoolGetDatum(X)
Definition: postgres.h:446
TimeLineID ThisTimeLineID
Definition: xlog.c:194
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:626
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define XLogArchivingActive()
Definition: xlog.h:197
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1717
static XLogCtlData * XLogCtl
Definition: xlog.c:748
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static void pg_stop_backup_callback(int code, Datum arg)
Definition: xlog.c:11271
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1342
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:782
int FreeFile(FILE *file)
Definition: fd.c:2616
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
struct Latch * MyLatch
Definition: globals.c:57
#define BACKUP_LABEL_FILE
Definition: xlog.h:405
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
void XLogBeginInsert(void)
Definition: xloginsert.c:135
#define WL_LATCH_SET
Definition: latch.h:125
#define stat
Definition: win32_port.h:275
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
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 12875 of file xlog.c.

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

12876 {
12877  static XLogRecPtr lastComplaint = 0;
12878 
12879  if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
12880  {
12881  if (RecPtr == lastComplaint)
12882  emode = DEBUG1;
12883  else
12884  lastComplaint = RecPtr;
12885  }
12886  return emode;
12887 }
#define DEBUG1
Definition: elog.h:25
static XLogSource readSource
Definition: xlog.c:833
#define LOG
Definition: elog.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ exitArchiveRecovery()

static void exitArchiveRecovery ( TimeLineID  endTLI,
XLogRecPtr  endOfLog 
)
static

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

5620 {
5621  char xlogfname[MAXFNAMELEN];
5622  XLogSegNo endLogSegNo;
5623  XLogSegNo startLogSegNo;
5624 
5625  /* we always switch to a new timeline after archive recovery */
5626  Assert(endTLI != ThisTimeLineID);
5627 
5628  /*
5629  * We are no longer in archive recovery state.
5630  */
5631  InArchiveRecovery = false;
5632 
5633  /*
5634  * Update min recovery point one last time.
5635  */
5637 
5638  /*
5639  * If the ending log segment is still open, close it (to avoid problems on
5640  * Windows with trying to rename or delete an open file).
5641  */
5642  if (readFile >= 0)
5643  {
5644  close(readFile);
5645  readFile = -1;
5646  }
5647 
5648  /*
5649  * Calculate the last segment on the old timeline, and the first segment
5650  * on the new timeline. If the switch happens in the middle of a segment,
5651  * they are the same, but if the switch happens exactly at a segment