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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Variables

uint32 bootstrap_data_checksum_version
 
int max_wal_size_mb = 1024
 
int min_wal_size_mb = 80
 
int wal_keep_segments = 0
 
int XLOGbuffers = -1
 
int XLogArchiveTimeout = 0
 
int XLogArchiveMode = ARCHIVE_MODE_OFF
 
char * XLogArchiveCommand = NULL
 
bool EnableHotStandby = false
 
bool fullPageWrites = true
 
bool wal_log_hints = false
 
bool wal_compression = false
 
char * wal_consistency_checking_string = NULL
 
boolwal_consistency_checking = NULL
 
bool wal_init_zero = true
 
bool wal_recycle = true
 
bool log_checkpoints = false
 
int sync_method = DEFAULT_SYNC_METHOD
 
int wal_level = WAL_LEVEL_MINIMAL
 
int CommitDelay = 0
 
int CommitSiblings = 5
 
int wal_retrieve_retry_interval = 5000
 
int 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 receivedUpto = 0
 
static TimeLineID receiveTLI = 0
 
static bool lastFullPageWrites
 
static bool LocalRecoveryInProgress = true
 
static bool LocalHotStandbyActive = false
 
static int LocalXLogInsertAllowed = -1
 
bool ArchiveRecoveryRequested = false
 
bool InArchiveRecovery = false
 
static bool standby_signal_file_found = false
 
static bool recovery_signal_file_found = false
 
static bool restoredFromArchive = false
 
static char * replay_image_masked = NULL
 
static char * master_image_masked = NULL
 
char * recoveryRestoreCommand = NULL
 
char * recoveryEndCommand = NULL
 
char * archiveCleanupCommand = NULL
 
RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET
 
bool recoveryTargetInclusive = true
 
int recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE
 
TransactionId recoveryTargetXid
 
char * recovery_target_time_string
 
static TimestampTz recoveryTargetTime
 
const char * recoveryTargetName
 
XLogRecPtr recoveryTargetLSN
 
int recovery_min_apply_delay = 0
 
bool StandbyModeRequested = false
 
char * PrimaryConnInfo = NULL
 
char * PrimarySlotName = NULL
 
char * PromoteTriggerFile = NULL
 
bool StandbyMode = false
 
static bool fast_promote = false
 
static TransactionId recoveryStopXid
 
static TimestampTz recoveryStopTime
 
static XLogRecPtr recoveryStopLSN
 
static char recoveryStopName [MAXFNAMELEN]
 
static bool recoveryStopAfter
 
RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal = RECOVERY_TARGET_TIMELINE_LATEST
 
TimeLineID recoveryTargetTLIRequested = 0
 
TimeLineID recoveryTargetTLI = 0
 
static ListexpectedTLEs
 
static TimeLineID curFileTLI
 
XLogRecPtr ProcLastRecPtr = InvalidXLogRecPtr
 
XLogRecPtr XactLastRecEnd = InvalidXLogRecPtr
 
XLogRecPtr XactLastCommitEnd = InvalidXLogRecPtr
 
static XLogRecPtr RedoRecPtr
 
static bool doPageWrites
 
static bool doRequestWalReceiverReply
 
static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr
 
static SessionBackupState sessionBackupState = SESSION_BACKUP_NONE
 
static XLogCtlDataXLogCtl = NULL
 
static WALInsertLockPaddedWALInsertLocks = NULL
 
static ControlFileDataControlFile = NULL
 
static int UsableBytesInSegment
 
static XLogwrtResult LogwrtResult = {0, 0}
 
static const char *const xlogSourceNames [] = {"any", "archive", "pg_wal", "stream"}
 
static int openLogFile = -1
 
static XLogSegNo openLogSegNo = 0
 
static int readFile = -1
 
static XLogSegNo readSegNo = 0
 
static uint32 readOff = 0
 
static uint32 readLen = 0
 
static XLogSource readSource = 0
 
static XLogSource currentSource = 0
 
static bool lastSourceFailed = false
 
static TimestampTz XLogReceiptTime = 0
 
static XLogSource XLogReceiptSource = 0
 
static XLogRecPtr ReadRecPtr
 
static XLogRecPtr EndRecPtr
 
static XLogRecPtr minRecoveryPoint
 
static TimeLineID minRecoveryPointTLI
 
static bool updateMinRecoveryPoint = true
 
bool reachedConsistency = false
 
static bool InRedo = false
 
static bool bgwriterLaunched = false
 
static int MyLockNo = 0
 
static bool holdingAllLocks = false
 

Macro Definition Documentation

◆ ConvertToXSegs

#define ConvertToXSegs (   x,
  segsize 
)    (x / ((segsize) / (1024 * 1024)))

Definition at line 746 of file xlog.c.

Referenced by CalculateCheckpointSegments(), ReadControlFile(), and XLOGfileslop().

◆ INSERT_FREESPACE

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

Definition at line 726 of file xlog.c.

Referenced by CopyXLogRecordToWAL(), and CreateCheckPoint().

◆ NextBufIdx

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

Definition at line 730 of file xlog.c.

Referenced by XLogWrite().

◆ NUM_XLOGINSERT_LOCKS

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 83 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 82 of file xlog.c.

Referenced by readRecoverySignalFile().

◆ RecoveryRequiresIntParameter

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

Definition at line 6133 of file xlog.c.

Referenced by CheckRequiredParameterValues().

◆ UsableBytesInPage

#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)

◆ XLogRecPtrToBufIdx

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

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

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 762 of file xlog.c.

763 {
764  XLOG_FROM_ANY = 0, /* request to read WAL from any source */
765  XLOG_FROM_ARCHIVE, /* restored using restore_command */
766  XLOG_FROM_PG_WAL, /* existing file in pg_wal */
767  XLOG_FROM_STREAM /* streamed from master */
768 } XLogSource;
XLogSource
Definition: xlog.c:762

Function Documentation

◆ AdvanceXLInsertBuffer()

static void AdvanceXLInsertBuffer ( XLogRecPtr  upto,
bool  opportunistic 
)
static

Definition at line 2085 of file xlog.c.

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

Referenced by GetXLogBuffer(), and XLogBackgroundFlush().

2086 {
2088  int nextidx;
2089  XLogRecPtr OldPageRqstPtr;
2090  XLogwrtRqst WriteRqst;
2091  XLogRecPtr NewPageEndPtr = InvalidXLogRecPtr;
2092  XLogRecPtr NewPageBeginPtr;
2093  XLogPageHeader NewPage;
2094  int npages = 0;
2095 
2096  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2097 
2098  /*
2099  * Now that we have the lock, check if someone initialized the page
2100  * already.
2101  */
2102  while (upto >= XLogCtl->InitializedUpTo || opportunistic)
2103  {
2105 
2106  /*
2107  * Get ending-offset of the buffer page we need to replace (this may
2108  * be zero if the buffer hasn't been used yet). Fall through if it's
2109  * already written out.
2110  */
2111  OldPageRqstPtr = XLogCtl->xlblocks[nextidx];
2112  if (LogwrtResult.Write < OldPageRqstPtr)
2113  {
2114  /*
2115  * Nope, got work to do. If we just want to pre-initialize as much
2116  * as we can without flushing, give up now.
2117  */
2118  if (opportunistic)
2119  break;
2120 
2121  /* Before waiting, get info_lck and update LogwrtResult */
2123  if (XLogCtl->LogwrtRqst.Write < OldPageRqstPtr)
2124  XLogCtl->LogwrtRqst.Write = OldPageRqstPtr;
2127 
2128  /*
2129  * Now that we have an up-to-date LogwrtResult value, see if we
2130  * still need to write it or if someone else already did.
2131  */
2132  if (LogwrtResult.Write < OldPageRqstPtr)
2133  {
2134  /*
2135  * Must acquire write lock. Release WALBufMappingLock first,
2136  * to make sure that all insertions that we need to wait for
2137  * can finish (up to this same position). Otherwise we risk
2138  * deadlock.
2139  */
2140  LWLockRelease(WALBufMappingLock);
2141 
2142  WaitXLogInsertionsToFinish(OldPageRqstPtr);
2143 
2144  LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
2145 
2147  if (LogwrtResult.Write >= OldPageRqstPtr)
2148  {
2149  /* OK, someone wrote it already */
2150  LWLockRelease(WALWriteLock);
2151  }
2152  else
2153  {
2154  /* Have to write it ourselves */
2155  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
2156  WriteRqst.Write = OldPageRqstPtr;
2157  WriteRqst.Flush = 0;
2158  XLogWrite(WriteRqst, false);
2159  LWLockRelease(WALWriteLock);
2160  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
2161  }
2162  /* Re-acquire WALBufMappingLock and retry */
2163  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2164  continue;
2165  }
2166  }
2167 
2168  /*
2169  * Now the next buffer slot is free and we can set it up to be the
2170  * next output page.
2171  */
2172  NewPageBeginPtr = XLogCtl->InitializedUpTo;
2173  NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
2174 
2175  Assert(XLogRecPtrToBufIdx(NewPageBeginPtr) == nextidx);
2176 
2177  NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
2178 
2179  /*
2180  * Be sure to re-zero the buffer so that bytes beyond what we've
2181  * written will look like zeroes and not valid XLOG records...
2182  */
2183  MemSet((char *) NewPage, 0, XLOG_BLCKSZ);
2184 
2185  /*
2186  * Fill the new page's header
2187  */
2188  NewPage->xlp_magic = XLOG_PAGE_MAGIC;
2189 
2190  /* NewPage->xlp_info = 0; */ /* done by memset */
2191  NewPage->xlp_tli = ThisTimeLineID;
2192  NewPage->xlp_pageaddr = NewPageBeginPtr;
2193 
2194  /* NewPage->xlp_rem_len = 0; */ /* done by memset */
2195 
2196  /*
2197  * If online backup is not in progress, mark the header to indicate
2198  * that WAL records beginning in this page have removable backup
2199  * blocks. This allows the WAL archiver to know whether it is safe to
2200  * compress archived WAL data by transforming full-block records into
2201  * the non-full-block format. It is sufficient to record this at the
2202  * page level because we force a page switch (in fact a segment
2203  * switch) when starting a backup, so the flag will be off before any
2204  * records can be written during the backup. At the end of a backup,
2205  * the last page will be marked as all unsafe when perhaps only part
2206  * is unsafe, but at worst the archiver would miss the opportunity to
2207  * compress a few records.
2208  */
2209  if (!Insert->forcePageWrites)
2210  NewPage->xlp_info |= XLP_BKP_REMOVABLE;
2211 
2212  /*
2213  * If first page of an XLOG segment file, make it a long header.
2214  */
2215  if ((XLogSegmentOffset(NewPage->xlp_pageaddr, wal_segment_size)) == 0)
2216  {
2217  XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
2218 
2219  NewLongPage->xlp_sysid = ControlFile->system_identifier;
2220  NewLongPage->xlp_seg_size = wal_segment_size;
2221  NewLongPage->xlp_xlog_blcksz = XLOG_BLCKSZ;
2222  NewPage->xlp_info |= XLP_LONG_HEADER;
2223  }
2224 
2225  /*
2226  * Make sure the initialization of the page becomes visible to others
2227  * before the xlblocks update. GetXLogBuffer() reads xlblocks without
2228  * holding a lock.
2229  */
2230  pg_write_barrier();
2231 
2232  *((volatile XLogRecPtr *) &XLogCtl->xlblocks[nextidx]) = NewPageEndPtr;
2233 
2234  XLogCtl->InitializedUpTo = NewPageEndPtr;
2235 
2236  npages++;
2237  }
2238  LWLockRelease(WALBufMappingLock);
2239 
2240 #ifdef WAL_DEBUG
2241  if (XLOG_DEBUG && npages > 0)
2242  {
2243  elog(DEBUG1, "initialized %d pages, up to %X/%X",
2244  npages, (uint32) (NewPageEndPtr >> 32), (uint32) NewPageEndPtr);
2245  }
2246 #endif
2247 }
XLogRecPtr InitializedUpTo
Definition: xlog.c:624
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
int wal_segment_size
Definition: xlog.c:112
XLogRecPtr * xlblocks
Definition: xlog.c:632
static XLogwrtResult LogwrtResult
Definition: xlog.c:756
slock_t info_lck
Definition: xlog.c:709
#define MemSet(start, val, len)
Definition: c.h:962
static XLogRecPtr WaitXLogInsertionsToFinish(XLogRecPtr upto)
Definition: xlog.c:1748
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
XLogCtlInsert Insert
Definition: xlog.c:589
XLogRecPtr Flush
Definition: xlog.c:432
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define XLP_BKP_REMOVABLE
Definition: xlog_internal.h:81
bool forcePageWrites
Definition: xlog.c:563
uint64 system_identifier
Definition: pg_control.h:106
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
XLogwrtResult LogwrtResult
Definition: xlog.c:612
unsigned int uint32
Definition: c.h:359
static void Insert(File file)
Definition: fd.c:1096
TimeLineID xlp_tli
Definition: xlog_internal.h:40
static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
Definition: xlog.c:2375
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SpinLockRelease(lock)
Definition: spin.h:64
XLogRecPtr Write
Definition: xlog.c:431
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
static ControlFileData * ControlFile
Definition: xlog.c:720
XLogwrtRqst LogwrtRqst
Definition: xlog.c:592
TimeLineID ThisTimeLineID
Definition: xlog.c:187
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
size_t Size
Definition: c.h:467
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:737
XLogRecPtr Write
Definition: xlog.c:437
#define elog(elevel,...)
Definition: elog.h:228
#define pg_write_barrier()
Definition: atomics.h:159
char * pages
Definition: xlog.c:631

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 2290 of file xlog.c.

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

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

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 2283 of file xlog.c.

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

2284 {
2287 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2254
int max_wal_size_mb
Definition: xlog.c:86
#define newval

◆ assign_xlog_sync_method()

void assign_xlog_sync_method ( int  new_sync_method,
void *  extra 
)

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

10085 {
10086  if (sync_method != new_sync_method)
10087  {
10088  /*
10089  * To ensure that no blocks escape unsynced, force an fsync on the
10090  * currently open log segment (if any). Also, if the open flag is
10091  * changing, close the log file so it will be reopened (with new flag
10092  * bit) at next use.
10093  */
10094  if (openLogFile >= 0)
10095  {
10097  if (pg_fsync(openLogFile) != 0)
10098  {
10099  char xlogfname[MAXFNAMELEN];
10100  int save_errno;
10101 
10102  save_errno = errno;
10105  errno = save_errno;
10106  ereport(PANIC,
10108  errmsg("could not fsync file \"%s\": %m", xlogfname)));
10109  }
10110 
10112  if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
10113  XLogFileClose();
10114  }
10115  }
10116 }
int wal_segment_size
Definition: xlog.c:112
static int get_sync_bit(int method)
Definition: xlog.c:10028
#define PANIC
Definition: elog.h:53
static XLogSegNo openLogSegNo
Definition: xlog.c:779
static void XLogFileClose(void)
Definition: xlog.c:3785
int errcode_for_file_access(void)
Definition: elog.c:631
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1344
#define ereport(elevel, rest)
Definition: elog.h:141
#define MAXFNAMELEN
static int openLogFile
Definition: xlog.c:778
TimeLineID ThisTimeLineID
Definition: xlog.c:187
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1320
int sync_method
Definition: xlog.c:102
int errmsg(const char *fmt,...)
Definition: elog.c:822
int pg_fsync(int fd)
Definition: fd.c:330

◆ BackupInProgress()

bool BackupInProgress ( void  )

Definition at line 11489 of file xlog.c.

References BACKUP_LABEL_FILE, and stat.

Referenced by pg_is_in_backup(), and PostmasterStateMachine().

11490 {
11491  struct stat stat_buf;
11492 
11493  return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
11494 }
struct stat stat_buf
Definition: pg_standby.c:100
#define stat(a, b)
Definition: win32_port.h:255
#define BACKUP_LABEL_FILE
Definition: xlog.h:359

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 5083 of file xlog.c.

References AdvanceOldestClogXid(), Assert, bootstrap_data_checksum_version, BootStrapCLOG(), BootStrapCommitTs(), BootStrapMultiXact(), BootStrapSUBTRANS(), ControlFileData::checkPoint, ControlFileData::checkPointCopy, close, COMP_CRC32C, ControlFileData::data_checksum_version, DB_SHUTDOWNED, ereport, errcode(), errcode_for_file_access(), errmsg(), FIN_CRC32C, FirstBootstrapObjectId, FirstMultiXactId, FirstNormalTransactionId, FirstNormalUnloggedLSN, CheckPoint::fullPageWrites, fullPageWrites, FullTransactionIdFromEpochAndXid(), gettimeofday(), INIT_CRC32C, InvalidTransactionId, 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, MOCK_AUTH_NONCE_LEN, ControlFileData::mock_authentication_nonce, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextFullXid, VariableCacheData::nextFullXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, offsetof, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, palloc(), PANIC, pfree(), pg_fsync(), pg_strong_random(), pgstat_report_wait_end(), pgstat_report_wait_start(), CheckPoint::PrevTimeLineID, ReadControlFile(), CheckPoint::redo, SetCommitTsLimit(), SetMultiXactIdLimit(), SetTransactionIdLimit(), ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, ControlFileData::state, ControlFileData::system_identifier, CheckPoint::ThisTimeLineID, ThisTimeLineID, CheckPoint::time, ControlFileData::time, track_commit_timestamp, ControlFileData::track_commit_timestamp, TYPEALIGN, ControlFileData::unloggedLSN, WAIT_EVENT_WAL_BOOTSTRAP_SYNC, WAIT_EVENT_WAL_BOOTSTRAP_WRITE, wal_level, ControlFileData::wal_level, wal_log_hints, ControlFileData::wal_log_hints, 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().

5084 {
5085  CheckPoint checkPoint;
5086  char *buffer;
5087  XLogPageHeader page;
5088  XLogLongPageHeader longpage;
5089  XLogRecord *record;
5090  char *recptr;
5091  bool use_existent;
5092  uint64 sysidentifier;
5093  char mock_auth_nonce[MOCK_AUTH_NONCE_LEN];
5094  struct timeval tv;
5095  pg_crc32c crc;
5096 
5097  /*
5098  * Select a hopefully-unique system identifier code for this installation.
5099  * We use the result of gettimeofday(), including the fractional seconds
5100  * field, as being about as unique as we can easily get. (Think not to
5101  * use random(), since it hasn't been seeded and there's no portable way
5102  * to seed it other than the system clock value...) The upper half of the
5103  * uint64 value is just the tv_sec part, while the lower half contains the
5104  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
5105  * PID for a little extra uniqueness. A person knowing this encoding can
5106  * determine the initialization time of the installation, which could
5107  * perhaps be useful sometimes.
5108  */
5109  gettimeofday(&tv, NULL);
5110  sysidentifier = ((uint64) tv.tv_sec) << 32;
5111  sysidentifier |= ((uint64) tv.tv_usec) << 12;
5112  sysidentifier |= getpid() & 0xFFF;
5113 
5114  /*
5115  * Generate a random nonce. This is used for authentication requests that
5116  * will fail because the user does not exist. The nonce is used to create
5117  * a genuine-looking password challenge for the non-existent user, in lieu
5118  * of an actual stored password.
5119  */
5120  if (!pg_strong_random(mock_auth_nonce, MOCK_AUTH_NONCE_LEN))
5121  ereport(PANIC,
5122  (errcode(ERRCODE_INTERNAL_ERROR),
5123  errmsg("could not generate secret authorization token")));
5124 
5125  /* First timeline ID is always 1 */
5126  ThisTimeLineID = 1;
5127 
5128  /* page buffer must be aligned suitably for O_DIRECT */
5129  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
5130  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
5131  memset(page, 0, XLOG_BLCKSZ);
5132 
5133  /*
5134  * Set up information for the initial checkpoint record
5135  *
5136  * The initial checkpoint record is written to the beginning of the WAL
5137  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
5138  * used, so that we can use 0/0 to mean "before any valid WAL segment".
5139  */
5140  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
5141  checkPoint.ThisTimeLineID = ThisTimeLineID;
5142  checkPoint.PrevTimeLineID = ThisTimeLineID;
5143  checkPoint.fullPageWrites = fullPageWrites;
5144  checkPoint.nextFullXid =
5146  checkPoint.nextOid = FirstBootstrapObjectId;
5147  checkPoint.nextMulti = FirstMultiXactId;
5148  checkPoint.nextMultiOffset = 0;
5149  checkPoint.oldestXid = FirstNormalTransactionId;
5150  checkPoint.oldestXidDB = TemplateDbOid;
5151  checkPoint.oldestMulti = FirstMultiXactId;
5152  checkPoint.oldestMultiDB = TemplateDbOid;
5155  checkPoint.time = (pg_time_t) time(NULL);
5157 
5159  ShmemVariableCache->nextOid = checkPoint.nextOid;
5161  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5162  AdvanceOldestClogXid(checkPoint.oldestXid);
5163  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5164  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5166 
5167  /* Set up the XLOG page header */
5168  page->xlp_magic = XLOG_PAGE_MAGIC;
5169  page->xlp_info = XLP_LONG_HEADER;
5170  page->xlp_tli = ThisTimeLineID;
5172  longpage = (XLogLongPageHeader) page;
5173  longpage->xlp_sysid = sysidentifier;
5174  longpage->xlp_seg_size = wal_segment_size;
5175  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
5176 
5177  /* Insert the initial checkpoint record */
5178  recptr = ((char *) page + SizeOfXLogLongPHD);
5179  record = (XLogRecord *) recptr;
5180  record->xl_prev = 0;
5181  record->xl_xid = InvalidTransactionId;
5182  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
5184  record->xl_rmid = RM_XLOG_ID;
5185  recptr += SizeOfXLogRecord;
5186  /* fill the XLogRecordDataHeaderShort struct */
5187  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
5188  *(recptr++) = sizeof(checkPoint);
5189  memcpy(recptr, &checkPoint, sizeof(checkPoint));
5190  recptr += sizeof(checkPoint);
5191  Assert(recptr - (char *) record == record->xl_tot_len);
5192 
5193  INIT_CRC32C(crc);
5194  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
5195  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
5196  FIN_CRC32C(crc);
5197  record->xl_crc = crc;
5198 
5199  /* Create first XLOG segment file */
5200  use_existent = false;
5201  openLogFile = XLogFileInit(1, &use_existent, false);
5202 
5203  /* Write the first page with the initial record */
5204  errno = 0;
5206  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
5207  {
5208  /* if write didn't set errno, assume problem is no disk space */
5209  if (errno == 0)
5210  errno = ENOSPC;
5211  ereport(PANIC,
5213  errmsg("could not write bootstrap write-ahead log file: %m")));
5214  }
5216 
5218  if (pg_fsync(openLogFile) != 0)
5219  ereport(PANIC,
5221  errmsg("could not fsync bootstrap write-ahead log file: %m")));
5223 
5224  if (close(openLogFile) != 0)
5225  ereport(PANIC,
5227  errmsg("could not close bootstrap write-ahead log file: %m")));
5228 
5229  openLogFile = -1;
5230 
5231  /* Now create pg_control */
5232 
5233  memset(ControlFile, 0, sizeof(ControlFileData));
5234  /* Initialize pg_control status fields */
5235  ControlFile->system_identifier = sysidentifier;
5236  memcpy(ControlFile->mock_authentication_nonce, mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
5238  ControlFile->time = checkPoint.time;
5239  ControlFile->checkPoint = checkPoint.redo;
5240  ControlFile->checkPointCopy = checkPoint;
5242 
5243  /* Set important parameter values for use when replaying WAL */
5253 
5254  /* some additional ControlFile fields are set in WriteControlFile() */
5255 
5256  WriteControlFile();
5257 
5258  /* Bootstrap the commit log, too */
5259  BootStrapCLOG();
5263 
5264  pfree(buffer);
5265 
5266  /*
5267  * Force control file to be read - in contrast to normal processing we'd
5268  * otherwise never run the checks and GUC related initializations therein.
5269  */
5270  ReadControlFile();
5271 }
static void WriteControlFile(void)
Definition: xlog.c:4498
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
int max_locks_per_xact
Definition: pg_control.h:182
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
int max_prepared_xacts
Definition: pg_control.h:181
int64 pg_time_t
Definition: pgtime.h:23
int wal_segment_size
Definition: xlog.c:112
pg_time_t time
Definition: pg_control.h:128
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:848
uint32 oidCount
Definition: transam.h:159
#define write(a, b, c)
Definition: win32.h:14
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:200
int max_worker_processes
Definition: pg_control.h:179
uint32 pg_crc32c
Definition: pg_crc32c.h:38
TransactionId oldestActiveXid
Definition: pg_control.h:63
int wal_level
Definition: xlog.c:103
int XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
Definition: xlog.c:3211
void BootStrapMultiXact(void)
Definition: multixact.c:1868
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
int errcode(int sqlerrcode)
Definition: elog.c:608
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
FullTransactionId nextFullXid
Definition: transam.h:164
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:53
uint32 bootstrap_data_checksum_version
Definition: bootstrap.c:53
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
#define MOCK_AUTH_NONCE_LEN
Definition: pg_control.h:28
bool fullPageWrites
Definition: xlog.c:94
void BootStrapSUBTRANS(void)
Definition: subtrans.c:212
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:313
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1056
#define FirstNormalTransactionId
Definition: transam.h:34
int max_prepared_xacts
Definition: twophase.c:117
uint64 system_identifier
Definition: pg_control.h:106
uint32 xl_tot_len
Definition: xlogrecord.h:43
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
static void ReadControlFile(void)
Definition: xlog.c:4589
bool track_commit_timestamp
Definition: commit_ts.c:103
uint32 data_checksum_version
Definition: pg_control.h:220
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
int errcode_for_file_access(void)
Definition: elog.c:631
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
#define FirstBootstrapObjectId
Definition: transam.h:140
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1344
#define FirstMultiXactId
Definition: multixact.h:24
#define ereport(elevel, rest)
Definition: elog.h:141
int max_locks_per_xact
Definition: lock.c:54
TimeLineID xlp_tli
Definition: xlog_internal.h:40
int max_wal_senders
Definition: walsender.c:121
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]
Definition: pg_control.h:227
int MaxConnections
Definition: globals.c:132
Oid oldestMultiDB
Definition: pg_control.h:50
static int openLogFile
Definition: xlog.c:778
static ControlFileData * ControlFile
Definition: xlog.c:720
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2196
TimeLineID ThisTimeLineID
Definition: xlog.c:187
Oid nextOid
Definition: pg_control.h:44
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:685
bool fullPageWrites
Definition: pg_control.h:42
bool wal_log_hints
Definition: xlog.c:95
void BootStrapCLOG(void)
Definition: clog.c:705
bool pg_strong_random(void *buf, size_t len)
bool track_commit_timestamp
Definition: pg_control.h:183
#define Assert(condition)
Definition: c.h:739
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1320
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:330
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:45
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:65
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:223
TransactionId xl_xid
Definition: xlogrecord.h:44
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int max_worker_processes
Definition: globals.c:133
int pg_fsync(int fd)
Definition: fd.c:330
#define close(a)
Definition: win32.h:12
void BootStrapCommitTs(void)
Definition: commit_ts.c:523
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:94
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
#define offsetof(type, field)
Definition: c.h:662
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2162

◆ CalculateCheckpointSegments()

static void CalculateCheckpointSegments ( void  )
static

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

2255 {
2256  double target;
2257 
2258  /*-------
2259  * Calculate the distance at which to trigger a checkpoint, to avoid
2260  * exceeding max_wal_size_mb. This is based on two assumptions:
2261  *
2262  * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
2263  * WAL for two checkpoint cycles to allow us to recover from the
2264  * secondary checkpoint if the first checkpoint failed, though we
2265  * only did this on the master anyway, not on standby. Keeping just
2266  * one checkpoint simplifies processing and reduces disk space in
2267  * many smaller databases.)
2268  * b) during checkpoint, we consume checkpoint_completion_target *
2269  * number of segments consumed between checkpoints.
2270  *-------
2271  */
2272  target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
2274 
2275  /* round down */
2276  CheckPointSegments = (int) target;
2277 
2278  if (CheckPointSegments < 1)
2279  CheckPointSegments = 1;
2280 }
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:746
int wal_segment_size
Definition: xlog.c:112
int max_wal_size_mb
Definition: xlog.c:86
int CheckPointSegments
Definition: xlog.c:125
double CheckPointCompletionTarget
Definition: checkpointer.c:148

◆ CancelBackup()

void CancelBackup ( void  )

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

11510 {
11511  struct stat stat_buf;
11512 
11513  /* if the backup_label file is not there, return */
11514  if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
11515  return;
11516 
11517  /* remove leftover file from previously canceled backup if it exists */
11518  unlink(BACKUP_LABEL_OLD);
11519 
11521  {
11522  ereport(WARNING,
11524  errmsg("online backup mode was not canceled"),
11525  errdetail("File \"%s\" could not be renamed to \"%s\": %m.",
11527  return;
11528  }
11529 
11530  /* if the tablespace_map file is not there, return */
11531  if (stat(TABLESPACE_MAP, &stat_buf) < 0)
11532  {
11533  ereport(LOG,
11534  (errmsg("online backup mode canceled"),
11535  errdetail("File \"%s\" was renamed to \"%s\".",
11537  return;
11538  }
11539 
11540  /* remove leftover file from previously canceled backup if it exists */
11541  unlink(TABLESPACE_MAP_OLD);
11542 
11544  {
11545  ereport(LOG,
11546  (errmsg("online backup mode canceled"),
11547  errdetail("Files \"%s\" and \"%s\" were renamed to "
11548  "\"%s\" and \"%s\", respectively.",
11551  }
11552  else
11553  {
11554  ereport(WARNING,
11556  errmsg("online backup mode canceled"),
11557  errdetail("File \"%s\" was renamed to \"%s\", but "
11558  "file \"%s\" could not be renamed to \"%s\": %m.",
11561  }
11562 }
#define DEBUG1
Definition: elog.h:25
#define LOG
Definition: elog.h:26
#define BACKUP_LABEL_OLD
Definition: xlog.h:360
#define TABLESPACE_MAP
Definition: xlog.h:362
struct stat stat_buf
Definition: pg_standby.c:100
int errdetail(const char *fmt,...)
Definition: elog.c:955
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:643
#define WARNING
Definition: elog.h:40
#define stat(a, b)
Definition: win32_port.h:255
#define TABLESPACE_MAP_OLD
Definition: xlog.h:363
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define BACKUP_LABEL_FILE
Definition: xlog.h:359

◆ check_wal_buffers()

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

Definition at line 4874 of file xlog.c.

References XLOGbuffers, and XLOGChooseNumBuffers().

4875 {
4876  /*
4877  * -1 indicates a request for auto-tune.
4878  */
4879  if (*newval == -1)
4880  {
4881  /*
4882  * If we haven't yet changed the boot_val default of -1, just let it
4883  * be. We'll fix it when XLOGShmemSize is called.
4884  */
4885  if (XLOGbuffers == -1)
4886  return true;
4887 
4888  /* Otherwise, substitute the auto-tune value */
4890  }
4891 
4892  /*
4893  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
4894  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
4895  * the case, we just silently treat such values as a request for the
4896  * minimum. (We could throw an error instead, but that doesn't seem very
4897  * helpful.)
4898  */
4899  if (*newval < 4)
4900  *newval = 4;
4901 
4902  return true;
4903 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:4858
#define newval
int XLOGbuffers
Definition: xlog.c:89

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 12212 of file xlog.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, FALLBACK_PROMOTE_SIGNAL_FILE, fast_promote, IsPromoteTriggered(), LOG, PROMOTE_SIGNAL_FILE, PromoteTriggerFile, ResetPromoteTriggered(), and stat.

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

12213 {
12214  struct stat stat_buf;
12215  static bool triggered = false;
12216 
12217  if (triggered)
12218  return true;
12219 
12220  if (IsPromoteTriggered())
12221  {
12222  /*
12223  * In 9.1 and 9.2 the postmaster unlinked the promote file inside the
12224  * signal handler. It now leaves the file in place and lets the
12225  * Startup process do the unlink. This allows Startup to know whether
12226  * it should create a full checkpoint before starting up (fallback
12227  * mode). Fast promotion takes precedence.
12228  */
12229  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12230  {
12231  unlink(PROMOTE_SIGNAL_FILE);
12233  fast_promote = true;
12234  }
12235  else if (stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12236  {
12238  fast_promote = false;
12239  }
12240 
12241  ereport(LOG, (errmsg("received promote request")));
12242 
12244  triggered = true;
12245  return true;
12246  }
12247 
12248  if (PromoteTriggerFile == NULL || strcmp(PromoteTriggerFile, "") == 0)
12249  return false;
12250 
12251  if (stat(PromoteTriggerFile, &stat_buf) == 0)
12252  {
12253  ereport(LOG,
12254  (errmsg("promote trigger file found: %s", PromoteTriggerFile)));
12255  unlink(PromoteTriggerFile);
12256  triggered = true;
12257  fast_promote = true;
12258  return true;
12259  }
12260  else if (errno != ENOENT)
12261  ereport(ERROR,
12263  errmsg("could not stat promote trigger file \"%s\": %m",
12264  PromoteTriggerFile)));
12265 
12266  return false;
12267 }
char * PromoteTriggerFile
Definition: xlog.c:285
void ResetPromoteTriggered(void)
Definition: startup.c:206
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:366
#define LOG
Definition: elog.h:26
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:100
int errcode_for_file_access(void)
Definition: elog.c:631
bool IsPromoteTriggered(void)
Definition: startup.c:200
#define ereport(elevel, rest)
Definition: elog.h:141
#define FALLBACK_PROMOTE_SIGNAL_FILE
Definition: xlog.h:367
#define stat(a, b)
Definition: win32_port.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:822
static bool fast_promote
Definition: xlog.c:291

◆ CheckPointGuts()

static void CheckPointGuts ( XLogRecPtr  checkPointRedo,
int  flags 
)
static

Definition at line 9012 of file xlog.c.

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

Referenced by CreateCheckPoint(), and CreateRestartPoint().

9013 {
9014  CheckPointCLOG();
9023  CheckPointBuffers(flags); /* performs all required fsyncs */
9025  /* We deliberately delay 2PC checkpointing as long as possible */
9026  CheckPointTwoPhase(checkPointRedo);
9027 }
void CheckPointBuffers(int flags)
Definition: bufmgr.c:2592
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1213
void CheckPointReplicationOrigin(void)
Definition: origin.c:542
void CheckPointSnapBuild(void)
Definition: snapbuild.c:1932
void CheckPointCLOG(void)
Definition: clog.c:835
void CheckPointMultiXact(void)
Definition: multixact.c:2142
void CheckPointCommitTs(void)
Definition: commit_ts.c:760
void CheckPointSUBTRANS(void)
Definition: subtrans.c:302
void CheckPointRelationMap(void)
Definition: relmapper.c:546
void CheckPointPredicate(void)
Definition: predicate.c:1018
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1695
void CheckPointReplicationSlots(void)
Definition: slot.c:1074

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 12284 of file xlog.c.

References FALLBACK_PROMOTE_SIGNAL_FILE, PROMOTE_SIGNAL_FILE, and stat.

Referenced by sigusr1_handler().

12285 {
12286  struct stat stat_buf;
12287 
12288  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 ||
12290  return true;
12291 
12292  return false;
12293 }
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:366
struct stat stat_buf
Definition: pg_standby.c:100
#define FALLBACK_PROMOTE_SIGNAL_FILE
Definition: xlog.h:367
#define stat(a, b)
Definition: win32_port.h:255

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 7829 of file xlog.c.

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

Referenced by ReadRecord(), and StartupXLOG().

7830 {
7831  XLogRecPtr lastReplayedEndRecPtr;
7832 
7833  /*
7834  * During crash recovery, we don't reach a consistent state until we've
7835  * replayed all the WAL.
7836  */
7838  return;
7839 
7841 
7842  /*
7843  * assume that we are called in the startup process, and hence don't need
7844  * a lock to read lastReplayedEndRecPtr
7845  */
7846  lastReplayedEndRecPtr = XLogCtl->lastReplayedEndRecPtr;
7847 
7848  /*
7849  * Have we reached the point where our base backup was completed?
7850  */
7852  ControlFile->backupEndPoint <= lastReplayedEndRecPtr)
7853  {
7854  /*
7855  * We have reached the end of base backup, as indicated by pg_control.
7856  * The data on disk is now consistent. Reset backupStartPoint and
7857  * backupEndPoint, and update minRecoveryPoint to make sure we don't
7858  * allow starting up at an earlier point even if recovery is stopped
7859  * and restarted soon after this.
7860  */
7861  elog(DEBUG1, "end of backup reached");
7862 
7863  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7864 
7865  if (ControlFile->minRecoveryPoint < lastReplayedEndRecPtr)
7866  ControlFile->minRecoveryPoint = lastReplayedEndRecPtr;
7867 
7870  ControlFile->backupEndRequired = false;
7872 
7873  LWLockRelease(ControlFileLock);
7874  }
7875 
7876  /*
7877  * Have we passed our safe starting point? Note that minRecoveryPoint is
7878  * known to be incorrectly set if ControlFile->backupEndRequired, until
7879  * the XLOG_BACKUP_END arrives to advise us of the correct
7880  * minRecoveryPoint. All we know prior to that is that we're not
7881  * consistent yet.
7882  */
7884  minRecoveryPoint <= lastReplayedEndRecPtr &&
7886  {
7887  /*
7888  * Check to see if the XLOG sequence contained any unresolved
7889  * references to uninitialized pages.
7890  */
7892 
7893  reachedConsistency = true;
7894  ereport(LOG,
7895  (errmsg("consistent recovery state reached at %X/%X",
7896  (uint32) (lastReplayedEndRecPtr >> 32),
7897  (uint32) lastReplayedEndRecPtr)));
7898  }
7899 
7900  /*
7901  * Have we got a valid starting snapshot that will allow queries to be
7902  * run? If so, we can tell postmaster that the database is consistent now,
7903  * enabling connections.
7904  */
7909  {
7913 
7914  LocalHotStandbyActive = true;
7915 
7917  }
7918 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:220
bool SharedHotStandbyActive
Definition: xlog.c:654
slock_t info_lck
Definition: xlog.c:709
#define LOG
Definition: elog.h:26
bool InArchiveRecovery
Definition: xlog.c:255
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool backupEndRequired
Definition: pg_control.h:170
#define SpinLockAcquire(lock)
Definition: spin.h:62
static bool LocalHotStandbyActive
Definition: xlog.c:229
void UpdateControlFile(void)
Definition: xlog.c:4789
bool IsUnderPostmaster
Definition: globals.c:109
unsigned int uint32
Definition: c.h:359
#define ereport(elevel, rest)
Definition: elog.h:141
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static ControlFileData * ControlFile
Definition: xlog.c:720
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
bool reachedConsistency
Definition: xlog.c:843
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:146
HotStandbyState standbyState
Definition: xlog.c:203
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:834
XLogRecPtr lastReplayedEndRecPtr
Definition: xlog.c:688

◆ CheckRequiredParameterValues()

static void CheckRequiredParameterValues ( void  )
static

Definition at line 6153 of file xlog.c.

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

Referenced by StartupXLOG(), and xlog_redo().

6154 {
6155  /*
6156  * For archive recovery, the WAL must be generated with at least 'replica'
6157  * wal_level.
6158  */
6160  {
6161  ereport(WARNING,
6162  (errmsg("WAL was generated with wal_level=minimal, data may be missing"),
6163  errhint("This happens if you temporarily set wal_level=minimal without taking a new base backup.")));
6164  }
6165 
6166  /*
6167  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
6168  * must have at least as many backend slots as the primary.
6169  */
6171  {
6173  ereport(ERROR,
6174  (errmsg("hot standby is not possible because wal_level was not set to \"replica\" or higher on the master server"),
6175  errhint("Either set wal_level to \"replica\" on the master, or turn off hot_standby here.")));
6176 
6177  /* We ignore autovacuum_max_workers when we make this test. */
6178  RecoveryRequiresIntParameter("max_connections",
6181  RecoveryRequiresIntParameter("max_worker_processes",
6184  RecoveryRequiresIntParameter("max_wal_senders",
6187  RecoveryRequiresIntParameter("max_prepared_transactions",
6190  RecoveryRequiresIntParameter("max_locks_per_transaction",
6193  }
6194 }
bool ArchiveRecoveryRequested
Definition: xlog.c:254
int max_locks_per_xact
Definition: pg_control.h:182
int errhint(const char *fmt,...)
Definition: elog.c:1069
int max_prepared_xacts
Definition: pg_control.h:181
int max_worker_processes
Definition: pg_control.h:179
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
#define ereport(elevel, rest)
Definition: elog.h:141
int max_locks_per_xact
Definition: lock.c:54
int max_wal_senders
Definition: walsender.c:121
#define WARNING
Definition: elog.h:40
int MaxConnections
Definition: globals.c:132
static ControlFileData * ControlFile
Definition: xlog.c:720
bool EnableHotStandby
Definition: xlog.c:93
int errmsg(const char *fmt,...)
Definition: elog.c:822
int max_worker_processes
Definition: globals.c:133
#define RecoveryRequiresIntParameter(param_name, currValue, minValue)
Definition: xlog.c:6133

◆ checkTimeLineSwitch()

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

Definition at line 9577 of file xlog.c.

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

Referenced by StartupXLOG().

9578 {
9579  /* Check that the record agrees on what the current (old) timeline is */
9580  if (prevTLI != ThisTimeLineID)
9581  ereport(PANIC,
9582  (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
9583  prevTLI, ThisTimeLineID)));
9584 
9585  /*
9586  * The new timeline better be in the list of timelines we expect to see,
9587  * according to the timeline history. It should also not decrease.
9588  */
9589  if (newTLI < ThisTimeLineID || !tliInHistory(newTLI, expectedTLEs))
9590  ereport(PANIC,
9591  (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
9592  newTLI, ThisTimeLineID)));
9593 
9594  /*
9595  * If we have not yet reached min recovery point, and we're about to
9596  * switch to a timeline greater than the timeline of the min recovery
9597  * point: trouble. After switching to the new timeline, we could not
9598  * possibly visit the min recovery point on the correct timeline anymore.
9599  * This can happen if there is a newer timeline in the archive that
9600  * branched before the timeline the min recovery point is on, and you
9601  * attempt to do PITR to the new timeline.
9602  */
9604  lsn < minRecoveryPoint &&
9605  newTLI > minRecoveryPointTLI)
9606  ereport(PANIC,
9607  (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
9608  newTLI,
9609  (uint32) (minRecoveryPoint >> 32),
9612 
9613  /* Looks good */
9614 }
static List * expectedTLEs
Definition: xlog.c:332
#define PANIC
Definition: elog.h:53
unsigned int uint32
Definition: c.h:359
#define ereport(elevel, rest)
Definition: elog.h:141
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:835
TimeLineID ThisTimeLineID
Definition: xlog.c:187
int errmsg(const char *fmt,...)
Definition: elog.c:822
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:517
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:834

◆ checkXLogConsistency()

static void checkXLogConsistency ( XLogReaderState record)
static

Definition at line 1367 of file xlog.c.

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

Referenced by StartupXLOG().

1368 {
1369  RmgrId rmid = XLogRecGetRmid(record);
1370  RelFileNode rnode;
1371  ForkNumber forknum;
1372  BlockNumber blkno;
1373  int block_id;
1374 
1375  /* Records with no backup blocks have no need for consistency checks. */
1376  if (!XLogRecHasAnyBlockRefs(record))
1377  return;
1378 
1379  Assert((XLogRecGetInfo(record) & XLR_CHECK_CONSISTENCY) != 0);
1380 
1381  for (block_id = 0; block_id <= record->max_block_id; block_id++)
1382  {
1383  Buffer buf;
1384  Page page;
1385 
1386  if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
1387  {
1388  /*
1389  * WAL record doesn't contain a block reference with the given id.
1390  * Do nothing.
1391  */
1392  continue;
1393  }
1394 
1395  Assert(XLogRecHasBlockImage(record, block_id));
1396 
1397  if (XLogRecBlockImageApply(record, block_id))
1398  {
1399  /*
1400  * WAL record has already applied the page, so bypass the
1401  * consistency check as that would result in comparing the full
1402  * page stored in the record with itself.
1403  */
1404  continue;
1405  }
1406 
1407  /*
1408  * Read the contents from the current buffer and store it in a
1409  * temporary page.
1410  */
1411  buf = XLogReadBufferExtended(rnode, forknum, blkno,
1413  if (!BufferIsValid(buf))
1414  continue;
1415 
1417  page = BufferGetPage(buf);
1418 
1419  /*
1420  * Take a copy of the local page where WAL has been applied to have a
1421  * comparison base before masking it...
1422  */
1423  memcpy(replay_image_masked, page, BLCKSZ);
1424 
1425  /* No need for this page anymore now that a copy is in. */
1426  UnlockReleaseBuffer(buf);
1427 
1428  /*
1429  * If the block LSN is already ahead of this WAL record, we can't
1430  * expect contents to match. This can happen if recovery is
1431  * restarted.
1432  */
1433  if (PageGetLSN(replay_image_masked) > record->EndRecPtr)
1434  continue;
1435 
1436  /*
1437  * Read the contents from the backup copy, stored in WAL record and
1438  * store it in a temporary page. There is no need to allocate a new
1439  * page here, a local buffer is fine to hold its contents and a mask
1440  * can be directly applied on it.
1441  */
1442  if (!RestoreBlockImage(record, block_id, master_image_masked))
1443  elog(ERROR, "failed to restore block image");
1444 
1445  /*
1446  * If masking function is defined, mask both the master and replay
1447  * images
1448  */
1449  if (RmgrTable[rmid].rm_mask != NULL)
1450  {
1451  RmgrTable[rmid].rm_mask(replay_image_masked, blkno);
1452  RmgrTable[rmid].rm_mask(master_image_masked, blkno);
1453  }
1454 
1455  /* Time to compare the master and replay images. */
1456  if (memcmp(replay_image_masked, master_image_masked, BLCKSZ) != 0)
1457  {
1458  elog(FATAL,
1459  "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
1460  rnode.spcNode, rnode.dbNode, rnode.relNode,
1461  forknum, blkno);
1462  }
1463  }
1464 }
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:288
Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode)
Definition: xlogutils.c:437
const RmgrData RmgrTable[RM_MAX_ID+1]
Definition: rmgr.c:36
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:80
XLogRecPtr EndRecPtr
Definition: xlogreader.h:132
static char * replay_image_masked
Definition: xlog.c:264
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:279
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:1460
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3612
uint8 RmgrId
Definition: rmgr.h:11
#define Assert(condition)
Definition: c.h:739
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:1513
#define PageGetLSN(page)
Definition: bufpage.h:366
#define elog(elevel,...)
Definition: elog.h:228
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:285
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:290
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:280
static char * master_image_masked
Definition: xlog.c:265

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

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

3860 {
3861  int save_errno = errno;
3862  XLogSegNo lastRemovedSegNo;
3863 
3865  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3867 
3868  if (segno <= lastRemovedSegNo)
3869  {
3870  char filename[MAXFNAMELEN];
3871 
3872  XLogFileName(filename, tli, segno, wal_segment_size);
3873  errno = save_errno;
3874  ereport(ERROR,
3876  errmsg("requested WAL segment %s has already been removed",
3877  filename)));
3878  }
3879  errno = save_errno;
3880 }
int wal_segment_size
Definition: xlog.c:112
slock_t info_lck
Definition: xlog.c:709
XLogSegNo lastRemovedSegNo
Definition: xlog.c:598
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
uint64 XLogSegNo
Definition: xlogdefs.h:41
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static XLogCtlData * XLogCtl
Definition: xlog.c:712
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

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

4223 {
4224  DIR *xldir;
4225  struct dirent *xlde;
4226  char path[MAXPGPATH + sizeof(XLOGDIR)];
4227 
4228  xldir = AllocateDir(XLOGDIR);
4229 
4230  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
4231  {
4232  if (IsBackupHistoryFileName(xlde->d_name))
4233  {
4234  if (XLogArchiveCheckDone(xlde->d_name))
4235  {
4236  elog(DEBUG2, "removing WAL backup history file \"%s\"",
4237  xlde->d_name);
4238  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
4239  unlink(path);
4240  XLogArchiveCleanup(xlde->d_name);
4241  }
4242  }
4243  }
4244 
4245  FreeDir(xldir);
4246 }
Definition: dirent.h:9
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:756
Definition: dirent.c:25
bool XLogArchiveCheckDone(const char *xlog)
Definition: xlogarchive.c:616
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
#define IsBackupHistoryFileName(fname)
#define XLOGDIR
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2569
#define elog(elevel,...)
Definition: elog.h:228
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ CopyXLogRecordToWAL()

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

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

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

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 8542 of file xlog.c.

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

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

8543 {
8544  bool shutdown;
8545  CheckPoint checkPoint;
8546  XLogRecPtr recptr;
8547  XLogSegNo _logSegNo;
8549  uint32 freespace;
8550  XLogRecPtr PriorRedoPtr;
8551  XLogRecPtr curInsert;
8552  XLogRecPtr last_important_lsn;
8553  VirtualTransactionId *vxids;
8554  int nvxids;
8555 
8556  /*
8557  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
8558  * issued at a different time.
8559  */
8561  shutdown = true;
8562  else
8563  shutdown = false;
8564 
8565  /* sanity check */
8566  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
8567  elog(ERROR, "can't create a checkpoint during recovery");
8568 
8569  /*
8570  * Initialize InitXLogInsert working areas before entering the critical
8571  * section. Normally, this is done by the first call to
8572  * RecoveryInProgress() or LocalSetXLogInsertAllowed(), but when creating
8573  * an end-of-recovery checkpoint, the LocalSetXLogInsertAllowed call is
8574  * done below in a critical section, and InitXLogInsert cannot be called
8575  * in a critical section.
8576  */
8577  InitXLogInsert();
8578 
8579  /*
8580  * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
8581  * (This is just pro forma, since in the present system structure there is
8582  * only one process that is allowed to issue checkpoints at any given
8583  * time.)
8584  */
8585  LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
8586 
8587  /*
8588  * Prepare to accumulate statistics.
8589  *
8590  * Note: because it is possible for log_checkpoints to change while a
8591  * checkpoint proceeds, we always accumulate stats, even if
8592  * log_checkpoints is currently off.
8593  */
8594  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
8596 
8597  /*
8598  * Use a critical section to force system panic if we have trouble.
8599  */
8601 
8602  if (shutdown)
8603  {
8604  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8606  ControlFile->time = (pg_time_t) time(NULL);
8608  LWLockRelease(ControlFileLock);
8609  }
8610 
8611  /*
8612  * Let smgr prepare for checkpoint; this has to happen before we determine
8613  * the REDO pointer. Note that smgr must not do anything that'd have to
8614  * be undone if we decide no checkpoint is needed.
8615  */
8617 
8618  /* Begin filling in the checkpoint WAL record */
8619  MemSet(&checkPoint, 0, sizeof(checkPoint));
8620  checkPoint.time = (pg_time_t) time(NULL);
8621 
8622  /*
8623  * For Hot Standby, derive the oldestActiveXid before we fix the redo
8624  * pointer. This allows us to begin accumulating changes to assemble our
8625  * starting snapshot of locks and transactions.
8626  */
8627  if (!shutdown && XLogStandbyInfoActive())
8629  else
8631 
8632  /*
8633  * Get location of last important record before acquiring insert locks (as
8634  * GetLastImportantRecPtr() also locks WAL locks).
8635  */
8636  last_important_lsn = GetLastImportantRecPtr();
8637 
8638  /*
8639  * We must block concurrent insertions while examining insert state to
8640  * determine the checkpoint REDO pointer.
8641  */
8643  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
8644 
8645  /*
8646  * If this isn't a shutdown or forced checkpoint, and if there has been no
8647  * WAL activity requiring a checkpoint, skip it. The idea here is to
8648  * avoid inserting duplicate checkpoints when the system is idle.
8649  */
8650  if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
8651  CHECKPOINT_FORCE)) == 0)
8652  {
8653  if (last_important_lsn == ControlFile->checkPoint)
8654  {
8656  LWLockRelease(CheckpointLock);
8657  END_CRIT_SECTION();
8658  ereport(DEBUG1,
8659  (errmsg("checkpoint skipped because system is idle")));
8660  return;
8661  }
8662  }
8663 
8664  /*
8665  * An end-of-recovery checkpoint is created before anyone is allowed to
8666  * write WAL. To allow us to write the checkpoint record, temporarily
8667  * enable XLogInsertAllowed. (This also ensures ThisTimeLineID is
8668  * initialized, which we need here and in AdvanceXLInsertBuffer.)
8669  */
8670  if (flags & CHECKPOINT_END_OF_RECOVERY)
8672 
8673  checkPoint.ThisTimeLineID = ThisTimeLineID;
8674  if (flags & CHECKPOINT_END_OF_RECOVERY)
8675  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
8676  else
8677  checkPoint.PrevTimeLineID = ThisTimeLineID;
8678 
8679  checkPoint.fullPageWrites = Insert->fullPageWrites;
8680 
8681  /*
8682  * Compute new REDO record ptr = location of next XLOG record.
8683  *
8684  * NB: this is NOT necessarily where the checkpoint record itself will be,
8685  * since other backends may insert more XLOG records while we're off doing
8686  * the buffer flush work. Those XLOG records are logically after the
8687  * checkpoint, even though physically before it. Got that?
8688  */
8689  freespace = INSERT_FREESPACE(curInsert);
8690  if (freespace == 0)
8691  {
8692  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
8693  curInsert += SizeOfXLogLongPHD;
8694  else
8695  curInsert += SizeOfXLogShortPHD;
8696  }
8697  checkPoint.redo = curInsert;
8698 
8699  /*
8700  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
8701  * must be done while holding all the insertion locks.
8702  *
8703  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
8704  * pointing past where it really needs to point. This is okay; the only
8705  * consequence is that XLogInsert might back up whole buffers that it
8706  * didn't really need to. We can't postpone advancing RedoRecPtr because
8707  * XLogInserts that happen while we are dumping buffers must assume that
8708  * their buffer changes are not included in the checkpoint.
8709  */
8710  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
8711 
8712  /*
8713  * Now we can release the WAL insertion locks, allowing other xacts to
8714  * proceed while we are flushing disk buffers.
8715  */
8717 
8718  /* Update the info_lck-protected copy of RedoRecPtr as well */
8720  XLogCtl->RedoRecPtr = checkPoint.redo;
8722 
8723  /*
8724  * If enabled, log checkpoint start. We postpone this until now so as not
8725  * to log anything if we decided to skip the checkpoint.
8726  */
8727  if (log_checkpoints)
8728  LogCheckpointStart(flags, false);
8729 
8730  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
8731 
8732  /*
8733  * Get the other info we need for the checkpoint record.
8734  *
8735  * We don't need to save oldestClogXid in the checkpoint, it only matters
8736  * for the short period in which clog is being truncated, and if we crash
8737  * during that we'll redo the clog truncation and fix up oldestClogXid
8738  * there.
8739  */
8740  LWLockAcquire(XidGenLock, LW_SHARED);
8742  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
8744  LWLockRelease(XidGenLock);
8745 
8746  LWLockAcquire(CommitTsLock, LW_SHARED);
8749  LWLockRelease(CommitTsLock);
8750 
8751  LWLockAcquire(OidGenLock, LW_SHARED);
8752  checkPoint.nextOid = ShmemVariableCache->nextOid;
8753  if (!shutdown)
8754  checkPoint.nextOid += ShmemVariableCache->oidCount;
8755  LWLockRelease(OidGenLock);
8756 
8757  MultiXactGetCheckptMulti(shutdown,
8758  &checkPoint.nextMulti,
8759  &checkPoint.nextMultiOffset,
8760  &checkPoint.oldestMulti,
8761  &checkPoint.oldestMultiDB);
8762 
8763  /*
8764  * Having constructed the checkpoint record, ensure all shmem disk buffers
8765  * and commit-log buffers are flushed to disk.
8766  *
8767  * This I/O could fail for various reasons. If so, we will fail to
8768  * complete the checkpoint, but there is no reason to force a system
8769  * panic. Accordingly, exit critical section while doing it.
8770  */
8771  END_CRIT_SECTION();
8772 
8773  /*
8774  * In some cases there are groups of actions that must all occur on one
8775  * side or the other of a checkpoint record. Before flushing the
8776  * checkpoint record we must explicitly wait for any backend currently
8777  * performing those groups of actions.
8778  *
8779  * One example is end of transaction, so we must wait for any transactions
8780  * that are currently in commit critical sections. If an xact inserted
8781  * its commit record into XLOG just before the REDO point, then a crash
8782  * restart from the REDO point would not replay that record, which means
8783  * that our flushing had better include the xact's update of pg_xact. So
8784  * we wait till he's out of his commit critical section before proceeding.
8785  * See notes in RecordTransactionCommit().
8786  *
8787  * Because we've already released the insertion locks, this test is a bit
8788  * fuzzy: it is possible that we will wait for xacts we didn't really need
8789  * to wait for. But the delay should be short and it seems better to make
8790  * checkpoint take a bit longer than to hold off insertions longer than
8791  * necessary. (In fact, the whole reason we have this issue is that xact.c
8792  * does commit record XLOG insertion and clog update as two separate steps
8793  * protected by different locks, but again that seems best on grounds of
8794  * minimizing lock contention.)
8795  *
8796  * A transaction that has not yet set delayChkpt when we look cannot be at
8797  * risk, since he's not inserted his commit record yet; and one that's
8798  * already cleared it is not at risk either, since he's done fixing clog
8799  * and we will correctly flush the update below. So we cannot miss any
8800  * xacts we need to wait for.
8801  */
8802  vxids = GetVirtualXIDsDelayingChkpt(&nvxids);
8803  if (nvxids > 0)
8804  {
8805  do
8806  {
8807  pg_usleep(10000L); /* wait for 10 msec */
8808  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids));
8809  }
8810  pfree(vxids);
8811 
8812  CheckPointGuts(checkPoint.redo, flags);
8813 
8814  /*
8815  * Take a snapshot of running transactions and write this to WAL. This
8816  * allows us to reconstruct the state of running transactions during
8817  * archive recovery, if required. Skip, if this info disabled.
8818  *
8819  * If we are shutting down, or Startup process is completing crash
8820  * recovery we don't need to write running xact data.
8821  */
8822  if (!shutdown && XLogStandbyInfoActive())
8824 
8826 
8827  /*
8828  * Now insert the checkpoint record into XLOG.
8829  */
8830  XLogBeginInsert();
8831  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
8832  recptr = XLogInsert(RM_XLOG_ID,
8833  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
8835 
8836  XLogFlush(recptr);
8837 
8838  /*
8839  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
8840  * overwritten at next startup. No-one should even try, this just allows
8841  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
8842  * to just temporarily disable writing until the system has exited
8843  * recovery.
8844  */
8845  if (shutdown)
8846  {
8847  if (flags & CHECKPOINT_END_OF_RECOVERY)
8848  LocalXLogInsertAllowed = -1; /* return to "check" state */
8849  else
8850  LocalXLogInsertAllowed = 0; /* never again write WAL */
8851  }
8852 
8853  /*
8854  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
8855  * = end of actual checkpoint record.
8856  */
8857  if (shutdown && checkPoint.redo != ProcLastRecPtr)
8858  ereport(PANIC,
8859  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
8860 
8861  /*
8862  * Remember the prior checkpoint's redo ptr for
8863  * UpdateCheckPointDistanceEstimate()
8864  */
8865  PriorRedoPtr = ControlFile->checkPointCopy.redo;
8866 
8867  /*
8868  * Update the control file.
8869  */
8870  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8871  if (shutdown)
8874  ControlFile->checkPointCopy = checkPoint;
8875  ControlFile->time = (pg_time_t) time(NULL);
8876  /* crash recovery should always recover to the end of WAL */
8879 
8880  /*
8881  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
8882  * unused on non-shutdown checkpoints, but seems useful to store it always
8883  * for debugging purposes.
8884  */
8888 
8890  LWLockRelease(ControlFileLock);
8891 
8892  /* Update shared-memory copy of checkpoint XID/epoch */
8894  XLogCtl->ckptFullXid = checkPoint.nextFullXid;
8896 
8897  /*
8898  * We are now done with critical updates; no need for system panic if we
8899  * have trouble while fooling with old log segments.
8900  */
8901  END_CRIT_SECTION();
8902 
8903  /*
8904  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
8905  */
8907 
8908  /*
8909  * Update the average distance between checkpoints if the prior checkpoint
8910  * exists.
8911  */
8912  if (PriorRedoPtr != InvalidXLogRecPtr)
8914 
8915  /*
8916  * Delete old log files, those no longer needed for last checkpoint to
8917  * prevent the disk holding the xlog from growing full.
8918  */
8920  KeepLogSeg(recptr, &_logSegNo);
8921  _logSegNo--;
8922  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr);
8923 
8924  /*
8925  * Make more log segments if needed. (Do this after recycling old log
8926  * segments, since that may supply some of the needed files.)
8927  */
8928  if (!shutdown)
8929  PreallocXlogFiles(recptr);
8930 
8931  /*
8932  * Truncate pg_subtrans if possible. We can throw away all data before
8933  * the oldest XMIN of any running transaction. No future transaction will
8934  * attempt to reference any pg_subtrans entry older than that (see Asserts
8935  * in subtrans.c). During recovery, though, we mustn't do this because
8936  * StartupSUBTRANS hasn't been called yet.
8937  */
8938  if (!RecoveryInProgress())
8940 
8941  /* Real work is done, but log and update stats before releasing lock. */
8942  LogCheckpointEnd(false);
8943 
8944  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
8945  NBuffers,
8949 
8950  LWLockRelease(CheckpointLock);
8951 }
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:8280
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8480
static int LocalXLogInsertAllowed
Definition: xlog.c:241
bool log_checkpoints
Definition: xlog.c:101
#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:1689
int wal_segment_size
Definition: xlog.c:112
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:159
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1958
XLogRecPtr unloggedLSN
Definition: xlog.c:601
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:350
TransactionId oldestActiveXid
Definition: pg_control.h:63
void InitXLogInsert(void)
Definition: xloginsert.c:1110
TimestampTz ckpt_start_t
Definition: xlog.h:235
slock_t info_lck
Definition: xlog.c:709
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids)
Definition: procarray.c:2273
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: xlog.c:642
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
int ckpt_segs_recycled
Definition: xlog.h:245
TransactionId oldestXid
Definition: transam.h:166
#define MemSet(start, val, len)
Definition: c.h:962
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2120
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9012
FullTransactionId nextFullXid
Definition: transam.h:164
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:589
TransactionId oldestXid
Definition: pg_control.h:47
bool RecoveryInProgress(void)
Definition: xlog.c:7930
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:356
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:53
bool fullPageWrites
Definition: xlog.c:564
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2804
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#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:4789
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1056
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:901
#define ERROR
Definition: elog.h:43
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8395
static XLogRecPtr RedoRecPtr
Definition: xlog.c:364
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3826
uint64 XLogSegNo
Definition: xlogdefs.h:41
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:212
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
uint64 CurrBytePos
Definition: xlog.c:540
unsigned int uint32
Definition: c.h:359
XLogRecPtr RedoRecPtr
Definition: xlog.c:593
int ckpt_segs_removed
Definition: xlog.h:244
#define CHECKPOINT_FORCE
Definition: xlog.h:215
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:726
#define ereport(elevel, rest)
Definition: elog.h:141
TransactionId oldestCommitTsXid
Definition: transam.h:176
static void Insert(File file)
Definition: fd.c:1096
int ckpt_bufs_written
Definition: xlog.h:241
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8056
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
#define SpinLockRelease(lock)
Definition: spin.h:64
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
TransactionId newestCommitTsXid
Definition: pg_control.h:54
#define PROCARRAY_FLAGS_DEFAULT
Definition: procarray.h:50
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9332
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
Oid oldestMultiDB
Definition: pg_control.h:50
FullTransactionId ckptFullXid
Definition: xlog.c:594
#define XLogStandbyInfoActive()
Definition: xlog.h:195
static ControlFileData * ControlFile
Definition: xlog.c:720
TimeLineID ThisTimeLineID
Definition: xlog.c:187
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:42
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1306
uint64 XLogRecPtr
Definition: xlogdefs.h:21
FullTransactionId nextFullXid
Definition: pg_control.h:43
Oid oldestXidDB
Definition: pg_control.h:48
TransactionId newestCommitTsXid
Definition: transam.h:177
CheckpointStatsData CheckpointStats
Definition: xlog.c:181
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:55
MultiXactId nextMulti
Definition: pg_control.h:45
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1660
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int ckpt_segs_added
Definition: xlog.h:243
slock_t ulsn_lck
Definition: xlog.c:602
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
Definition: xlog.c:3956
void SyncPostCheckpoint(void)
Definition: sync.c:174
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2111
int NBuffers
Definition: globals.c:131
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
Definition: procarray.c:2318
void XLogBeginInsert(void)
Definition: xloginsert.c:120
XLogRecPtr RedoRecPtr
Definition: xlog.c:562
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8377
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:211
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
void SyncPreCheckpoint(void)
Definition: sync.c:159
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ CreateEndOfRecoveryRecord()

static void CreateEndOfRecoveryRecord ( void  )
static

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

8964 {
8965  xl_end_of_recovery xlrec;
8966  XLogRecPtr recptr;
8967 
8968  /* sanity check */
8969  if (!RecoveryInProgress())
8970  elog(ERROR, "can only be used to end recovery");
8971 
8972  xlrec.end_time = GetCurrentTimestamp();
8973 
8978 
8980 
8982 
8983  XLogBeginInsert();
8984  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
8985  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
8986 
8987  XLogFlush(recptr);
8988 
8989  /*
8990  * Update the control file so that crash recovery can follow the timeline
8991  * changes to this point.
8992  */
8993  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8994  ControlFile->time = (pg_time_t) time(NULL);
8995  ControlFile->minRecoveryPoint = recptr;
8998  LWLockRelease(ControlFileLock);
8999 
9000  END_CRIT_SECTION();
9001 
9002  LocalXLogInsertAllowed = -1; /* return to "check" state */
9003 }
static int LocalXLogInsertAllowed
Definition: xlog.c:241
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1689
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimeLineID PrevTimeLineID
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
TimeLineID PrevTimeLineID
Definition: xlog.c:642
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
bool RecoveryInProgress(void)
Definition: xlog.c:7930
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2804
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
void UpdateControlFile(void)
Definition: xlog.c:4789
#define ERROR
Definition: elog.h:43
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8056
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
static ControlFileData * ControlFile
Definition: xlog.c:720
TimeLineID ThisTimeLineID
Definition: xlog.c:187
TimestampTz end_time
uint64 XLogRecPtr
Definition: xlogdefs.h:21
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1660
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
TimeLineID ThisTimeLineID
#define elog(elevel,...)
Definition: elog.h:228
void XLogBeginInsert(void)
Definition: xloginsert.c:120
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 9082 of file xlog.c.

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

Referenced by CheckpointerMain(), and ShutdownXLOG().

9083 {
9084  XLogRecPtr lastCheckPointRecPtr;
9085  XLogRecPtr lastCheckPointEndPtr;
9086  CheckPoint lastCheckPoint;
9087  XLogRecPtr PriorRedoPtr;
9088  XLogRecPtr receivePtr;
9089  XLogRecPtr replayPtr;
9090  TimeLineID replayTLI;
9091  XLogRecPtr endptr;
9092  XLogSegNo _logSegNo;
9093  TimestampTz xtime;
9094 
9095  /*
9096  * Acquire CheckpointLock to ensure only one restartpoint or checkpoint
9097  * happens at a time.
9098  */
9099  LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
9100 
9101  /* Get a local copy of the last safe checkpoint record. */
9103  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
9104  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
9105  lastCheckPoint = XLogCtl->lastCheckPoint;
9107 
9108  /*
9109  * Check that we're still in recovery mode. It's ok if we exit recovery
9110  * mode after this check, the restart point is valid anyway.
9111  */
9112  if (!RecoveryInProgress())
9113  {
9114  ereport(DEBUG2,
9115  (errmsg("skipping restartpoint, recovery has already ended")));
9116  LWLockRelease(CheckpointLock);
9117  return false;
9118  }
9119 
9120  /*
9121  * If the last checkpoint record we've replayed is already our last
9122  * restartpoint, we can't perform a new restart point. We still update
9123  * minRecoveryPoint in that case, so that if this is a shutdown restart
9124  * point, we won't start up earlier than before. That's not strictly
9125  * necessary, but when hot standby is enabled, it would be rather weird if
9126  * the database opened up for read-only connections at a point-in-time
9127  * before the last shutdown. Such time travel is still possible in case of
9128  * immediate shutdown, though.
9129  *
9130  * We don't explicitly advance minRecoveryPoint when we do create a
9131  * restartpoint. It's assumed that flushing the buffers will do that as a
9132  * side-effect.
9133  */
9134  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
9135  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
9136  {
9137  ereport(DEBUG2,
9138  (errmsg("skipping restartpoint, already performed at %X/%X",
9139  (uint32) (lastCheckPoint.redo >> 32),
9140  (uint32) lastCheckPoint.redo)));
9141 
9143  if (flags & CHECKPOINT_IS_SHUTDOWN)
9144  {
9145  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9147  ControlFile->time = (pg_time_t) time(NULL);
9149  LWLockRelease(ControlFileLock);
9150  }
9151  LWLockRelease(CheckpointLock);
9152  return false;
9153  }
9154 
9155  /*
9156  * Update the shared RedoRecPtr so that the startup process can calculate
9157  * the number of segments replayed since last restartpoint, and request a
9158  * restartpoint if it exceeds CheckPointSegments.
9159  *
9160  * Like in CreateCheckPoint(), hold off insertions to update it, although
9161  * during recovery this is just pro forma, because no WAL insertions are
9162  * happening.
9163  */
9165  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
9167 
9168  /* Also update the info_lck-protected copy */
9170  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
9172 
9173  /*
9174  * Prepare to accumulate statistics.
9175  *
9176  * Note: because it is possible for log_checkpoints to change while a
9177  * checkpoint proceeds, we always accumulate stats, even if
9178  * log_checkpoints is currently off.
9179  */
9180  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
9182 
9183  if (log_checkpoints)
9184  LogCheckpointStart(flags, true);
9185 
9186  CheckPointGuts(lastCheckPoint.redo, flags);
9187 
9188  /*
9189  * Remember the prior checkpoint's redo ptr for
9190  * UpdateCheckPointDistanceEstimate()
9191  */
9192  PriorRedoPtr = ControlFile->checkPointCopy.redo;
9193 
9194  /*
9195  * Update pg_control, using current time. Check that it still shows
9196  * DB_IN_ARCHIVE_RECOVERY state and an older checkpoint, else do nothing;
9197  * this is a quick hack to make sure nothing really bad happens if somehow
9198  * we get here after the end-of-recovery checkpoint.
9199  */
9200  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9202  ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
9203  {
9204  ControlFile->checkPoint = lastCheckPointRecPtr;
9205  ControlFile->checkPointCopy = lastCheckPoint;
9206  ControlFile->time = (pg_time_t) time(NULL);
9207 
9208  /*
9209  * Ensure minRecoveryPoint is past the checkpoint record. Normally,
9210  * this will have happened already while writing out dirty buffers,
9211  * but not necessarily - e.g. because no buffers were dirtied. We do
9212  * this because a non-exclusive base backup uses minRecoveryPoint to
9213  * determine which WAL files must be included in the backup, and the
9214  * file (or files) containing the checkpoint record must be included,
9215  * at a minimum. Note that for an ordinary restart of recovery there's
9216  * no value in having the minimum recovery point any earlier than this
9217  * anyway, because redo will begin just after the checkpoint record.
9218  */
9219  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
9220  {
9221  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
9223 
9224  /* update local copy */
9227  }
9228  if (flags & CHECKPOINT_IS_SHUTDOWN)
9231  }
9232  LWLockRelease(ControlFileLock);
9233 
9234  /*
9235  * Update the average distance between checkpoints/restartpoints if the
9236  * prior checkpoint exists.
9237  */
9238  if (PriorRedoPtr != InvalidXLogRecPtr)
9240 
9241  /*
9242  * Delete old log files, those no longer needed for last restartpoint to
9243  * prevent the disk holding the xlog from growing full.
9244  */
9246 
9247  /*
9248  * Retreat _logSegNo using the current end of xlog replayed or received,
9249  * whichever is later.
9250  */
9251  receivePtr = GetWalRcvWriteRecPtr(NULL, NULL);
9252  replayPtr = GetXLogReplayRecPtr(&replayTLI);
9253  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
9254  KeepLogSeg(endptr, &_logSegNo);
9255  _logSegNo--;
9256 
9257  /*
9258  * Try to recycle segments on a useful timeline. If we've been promoted
9259  * since the beginning of this restartpoint, use the new timeline chosen
9260  * at end of recovery (RecoveryInProgress() sets ThisTimeLineID in that
9261  * case). If we're still in recovery, use the timeline we're currently
9262  * replaying.
9263  *
9264  * There is no guarantee that the WAL segments will be useful on the
9265  * current timeline; if recovery proceeds to a new timeline right after
9266  * this, the pre-allocated WAL segments on this timeline will not be used,
9267  * and will go wasted until recycled on the next restartpoint. We'll live
9268  * with that.
9269  */
9270  if (RecoveryInProgress())
9271  ThisTimeLineID = replayTLI;
9272 
9273  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr);
9274 
9275  /*
9276  * Make more log segments if needed. (Do this after recycling old log
9277  * segments, since that may supply some of the needed files.)
9278  */
9279  PreallocXlogFiles(endptr);
9280 
9281  /*
9282  * ThisTimeLineID is normally not set when we're still in recovery.
9283  * However, recycling/preallocating segments above needed ThisTimeLineID
9284  * to determine which timeline to install the segments on. Reset it now,
9285  * to restore the normal state of affairs for debugging purposes.
9286  */
9287  if (RecoveryInProgress())
9288  ThisTimeLineID = 0;
9289 
9290  /*
9291  * Truncate pg_subtrans if possible. We can throw away all data before
9292  * the oldest XMIN of any running transaction. No future transaction will
9293  * attempt to reference any pg_subtrans entry older than that (see Asserts
9294  * in subtrans.c). When hot standby is disabled, though, we mustn't do
9295  * this because StartupSUBTRANS hasn't been called yet.
9296  */
9297  if (EnableHotStandby)
9299 
9300  /* Real work is done, but log and update before releasing lock. */
9301  LogCheckpointEnd(true);
9302 
9303  xtime = GetLatestXTime();
9305  (errmsg("recovery restart point at %X/%X",
9306  (uint32) (lastCheckPoint.redo >> 32), (uint32) lastCheckPoint.redo),
9307  xtime ? errdetail("Last completed transaction was at log time %s.",
9308  timestamptz_to_str(xtime)) : 0));
9309 
9310  LWLockRelease(CheckpointLock);
9311 
9312  /*
9313  * Finally, execute archive_cleanup_command, if any.
9314  */
9315  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
9317  "archive_cleanup_command",
9318  false);
9319 
9320  return true;
9321 }
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8480
bool log_checkpoints
Definition: xlog.c:101
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal)
Definition: xlogarchive.c:331
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
uint32 TimeLineID
Definition: xlogdefs.h:52
int64 pg_time_t
Definition: pgtime.h:23
XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
static void WALInsertLockRelease(void)
Definition: xlog.c:1689
int wal_segment_size
Definition: xlog.c:112
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
int64 TimestampTz
Definition: timestamp.h:39
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2717
TimestampTz ckpt_start_t
Definition: xlog.h:235
slock_t info_lck
Definition: xlog.c:709
#define MemSet(start, val, len)
Definition: c.h:962
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9012
TimestampTz GetLatestXTime(void)
Definition: xlog.c:6071
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:589
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:7930
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:356
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:678
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SpinLockAcquire(lock)
Definition: spin.h:62
void UpdateControlFile(void)
Definition: xlog.c:4789
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8395
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
Definition: xlog.c:11193
#define DEBUG2
Definition: elog.h:24
static XLogRecPtr RedoRecPtr
Definition: xlog.c:364
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3826
uint64 XLogSegNo
Definition: xlogdefs.h:41
int errdetail(const char *fmt,...)
Definition: elog.c:955
unsigned int uint32
Definition: c.h:359
XLogRecPtr RedoRecPtr
Definition: xlog.c:593
#define ereport(elevel, rest)
Definition: elog.h:141
CheckPoint lastCheckPoint
Definition: xlog.c:680
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:835
#define PROCARRAY_FLAGS_DEFAULT
Definition: procarray.h:50
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9332
static ControlFileData * ControlFile
Definition: xlog.c:720
TimeLineID ThisTimeLineID
Definition: xlog.c:187
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1306
uint64 XLogRecPtr
Definition: xlogdefs.h:21
CheckpointStatsData CheckpointStats
Definition: xlog.c:181
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1660
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
bool EnableHotStandby
Definition: xlog.c:93
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:822
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr)
Definition: xlog.c:3956
XLogRecPtr RedoRecPtr
Definition: xlog.c:562
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:679
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8377
char * archiveCleanupCommand
Definition: xlog.c:270
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:211
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:834
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1743
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ DataChecksumsEnabled()

bool DataChecksumsEnabled ( void  )

Definition at line 4818 of file xlog.c.

References Assert, and ControlFileData::data_checksum_version.

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

4819 {
4820  Assert(ControlFile != NULL);
4821  return (ControlFile->data_checksum_version > 0);
4822 }
uint32 data_checksum_version
Definition: pg_control.h:220
static ControlFileData * ControlFile
Definition: xlog.c:720
#define Assert(condition)
Definition: c.h:739

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

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

11146 {
11147  bool emit_warning = DatumGetBool(arg);
11148 
11149  /*
11150  * Quick exit if session is not keeping around a non-exclusive backup
11151  * already started.
11152  */
11154  return;
11155 
11159 
11162  {
11163  XLogCtl->Insert.forcePageWrites = false;
11164  }
11166 
11167  if (emit_warning)
11168  ereport(WARNING,
11169  (errmsg("aborting backup due to backend exiting before pg_stop_back up was called")));
11170 }
static void WALInsertLockRelease(void)
Definition: xlog.c:1689
static SessionBackupState sessionBackupState
Definition: xlog.c:524
XLogCtlInsert Insert
Definition: xlog.c:589
bool forcePageWrites
Definition: xlog.c:563
#define DatumGetBool(X)
Definition: postgres.h:393
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:575
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:574
#define Assert(condition)
Definition: c.h:739
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1660
static XLogCtlData * XLogCtl
Definition: xlog.c:712
int errmsg(const char *fmt,...)
Definition: elog.c:822
void * arg

◆ do_pg_start_backup()

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

Definition at line 10215 of file xlog.c.

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

Referenced by perform_base_backup(), and pg_start_backup().

10219 {
10220  bool exclusive = (labelfile == NULL);
10221  bool backup_started_in_recovery = false;
10222  XLogRecPtr checkpointloc;
10223  XLogRecPtr startpoint;
10224  TimeLineID starttli;
10225  pg_time_t stamp_time;
10226  char strfbuf[128];
10227  char xlogfilename[MAXFNAMELEN];
10228  XLogSegNo _logSegNo;
10229  struct stat stat_buf;
10230  FILE *fp;
10231 
10232  backup_started_in_recovery = RecoveryInProgress();
10233 
10234  /*
10235  * Currently only non-exclusive backup can be taken during recovery.
10236  */
10237  if (backup_started_in_recovery && exclusive)
10238  ereport(ERROR,
10239  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10240  errmsg("recovery is in progress"),
10241  errhint("WAL control functions cannot be executed during recovery.")));
10242 
10243  /*
10244  * During recovery, we don't need to check WAL level. Because, if WAL
10245  * level is not sufficient, it's impossible to get here during recovery.
10246  */
10247  if (!backup_started_in_recovery && !XLogIsNeeded())
10248  ereport(ERROR,
10249  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10250  errmsg("WAL level not sufficient for making an online backup"),
10251  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
10252 
10253  if (strlen(backupidstr) > MAXPGPATH)
10254  ereport(ERROR,
10255  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10256  errmsg("backup label too long (max %d bytes)",
10257  MAXPGPATH)));
10258 
10259  /*
10260  * Mark backup active in shared memory. We must do full-page WAL writes
10261  * during an on-line backup even if not doing so at other times, because
10262  * it's quite possible for the backup dump to obtain a "torn" (partially
10263  * written) copy of a database page if it reads the page concurrently with
10264  * our write to the same page. This can be fixed as long as the first
10265  * write to the page in the WAL sequence is a full-page write. Hence, we
10266  * turn on forcePageWrites and then force a CHECKPOINT, to ensure there
10267  * are no dirty pages in shared memory that might get dumped while the
10268  * backup is in progress without having a corresponding WAL record. (Once
10269  * the backup is complete, we need not force full-page writes anymore,
10270  * since we expect that any pages not modified during the backup interval
10271  * must have been correctly captured by the backup.)
10272  *
10273  * Note that forcePageWrites has no effect during an online backup from
10274  * the standby.
10275  *
10276  * We must hold all the insertion locks to change the value of
10277  * forcePageWrites, to ensure adequate interlocking against
10278  * XLogInsertRecord().
10279  */
10281  if (exclusive)
10282  {
10283  /*
10284  * At first, mark that we're now starting an exclusive backup, to
10285  * ensure that there are no other sessions currently running
10286  * pg_start_backup() or pg_stop_backup().
10287  */
10289  {
10291  ereport(ERROR,
10292  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10293  errmsg("a backup is already in progress"),
10294  errhint("Run pg_stop_backup() and try again.")));
10295  }
10297  }
10298  else
10300  XLogCtl->Insert.forcePageWrites = true;
10302 
10303  /* Ensure we release forcePageWrites if fail below */
10305  {
10306  bool gotUniqueStartpoint = false;
10307  DIR *tblspcdir;
10308  struct dirent *de;
10309  tablespaceinfo *ti;
10310  int datadirpathlen;
10311 
10312  /*
10313  * Force an XLOG file switch before the checkpoint, to ensure that the
10314  * WAL segment the checkpoint is written to doesn't contain pages with
10315  * old timeline IDs. That would otherwise happen if you called
10316  * pg_start_backup() right after restoring from a PITR archive: the
10317  * first WAL segment containing the startup checkpoint has pages in
10318  * the beginning with the old timeline ID. That can cause trouble at
10319  * recovery: we won't have a history file covering the old timeline if
10320  * pg_wal directory was not included in the base backup and the WAL
10321  * archive was cleared too before starting the backup.
10322  *
10323  * This also ensures that we have emitted a WAL page header that has
10324  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
10325  * Therefore, if a WAL archiver (such as pglesslog) is trying to
10326  * compress out removable backup blocks, it won't remove any that
10327  * occur after this point.
10328  *
10329  * During recovery, we skip forcing XLOG file switch, which means that
10330  * the backup taken during recovery is not available for the special
10331  * recovery case described above.
10332  */
10333  if (!backup_started_in_recovery)
10334  RequestXLogSwitch(false);
10335 
10336  do
10337  {
10338  bool checkpointfpw;
10339 
10340  /*
10341  * Force a CHECKPOINT. Aside from being necessary to prevent torn
10342  * page problems, this guarantees that two successive backup runs
10343  * will have different checkpoint positions and hence different
10344  * history file names, even if nothing happened in between.
10345  *
10346  * During recovery, establish a restartpoint if possible. We use
10347  * the last restartpoint as the backup starting checkpoint. This
10348  * means that two successive backup runs can have same checkpoint
10349  * positions.
10350  *
10351  * Since the fact that we are executing do_pg_start_backup()
10352  * during recovery means that checkpointer is running, we can use
10353  * RequestCheckpoint() to establish a restartpoint.
10354  *
10355  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
10356  * passing fast = true). Otherwise this can take awhile.
10357  */
10359  (fast ? CHECKPOINT_IMMEDIATE : 0));
10360 
10361  /*
10362  * Now we need to fetch the checkpoint record location, and also
10363  * its REDO pointer. The oldest point in WAL that would be needed
10364  * to restore starting from the checkpoint is precisely the REDO
10365  * pointer.
10366  */
10367  LWLockAcquire(ControlFileLock, LW_SHARED);
10368  checkpointloc = ControlFile->checkPoint;
10369  startpoint = ControlFile->checkPointCopy.redo;
10371  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
10372  LWLockRelease(ControlFileLock);
10373 
10374  if (backup_started_in_recovery)
10375  {
10376  XLogRecPtr recptr;
10377 
10378  /*
10379  * Check to see if all WAL replayed during online backup
10380  * (i.e., since last restartpoint used as backup starting
10381  * checkpoint) contain full-page writes.
10382  */
10384  recptr = XLogCtl->lastFpwDisableRecPtr;
10386 
10387  if (!checkpointfpw || startpoint <= recptr)
10388  ereport(ERROR,
10389  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10390  errmsg("WAL generated with full_page_writes=off was replayed "
10391  "since last restartpoint"),
10392  errhint("This means that the backup being taken on the standby "
10393  "is corrupt and should not be used. "
10394  "Enable full_page_writes and run CHECKPOINT on the master, "
10395  "and then try an online backup again.")));
10396 
10397  /*
10398  * During recovery, since we don't use the end-of-backup WAL
10399  * record and don't write the backup history file, the
10400  * starting WAL location doesn't need to be unique. This means
10401  * that two base backups started at the same time might use
10402  * the same checkpoint as starting locations.
10403  */
10404  gotUniqueStartpoint = true;
10405  }
10406 
10407  /*
10408  * If two base backups are started at the same time (in WAL sender
10409  * processes), we need to make sure that they use different
10410  * checkpoints as starting locations, because we use the starting
10411  * WAL location as a unique identifier for the base backup in the
10412  * end-of-backup WAL record and when we write the backup history
10413  * file. Perhaps it would be better generate a separate unique ID
10414  * for each backup instead of forcing another checkpoint, but
10415  * taking a checkpoint right after another is not that expensive
10416  * either because only few buffers have been dirtied yet.
10417  */
10419  if (XLogCtl->Insert.lastBackupStart < startpoint)
10420  {
10421  XLogCtl->Insert.lastBackupStart = startpoint;
10422  gotUniqueStartpoint = true;
10423  }
10425  } while (!gotUniqueStartpoint);
10426 
10427  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
10428  XLogFileName(xlogfilename, starttli, _logSegNo, wal_segment_size);
10429 
10430  /*
10431  * Construct tablespace_map file
10432  */
10433  if (exclusive)
10434  tblspcmapfile = makeStringInfo();
10435 
10436  datadirpathlen = strlen(DataDir);
10437 
10438  /* Collect information about all tablespaces */
10439  tblspcdir = AllocateDir("pg_tblspc");
10440  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
10441  {
10442  char fullpath[MAXPGPATH + 10];
10443  char linkpath[MAXPGPATH];
10444  char *relpath = NULL;
10445  int rllen;
10446  StringInfoData buflinkpath;
10447  char *s = linkpath;
10448 
10449  /* Skip special stuff */
10450  if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
10451  continue;
10452 
10453  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
10454 
10455 #if defined(HAVE_READLINK) || defined(WIN32)
10456  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
10457  if (rllen < 0)
10458  {
10459  ereport(WARNING,
10460  (errmsg("could not read symbolic link \"%s\": %m",
10461  fullpath)));
10462  continue;
10463  }
10464  else if (rllen >= sizeof(linkpath))
10465  {
10466  ereport(WARNING,
10467  (errmsg("symbolic link \"%s\" target is too long",
10468  fullpath)));
10469  continue;
10470  }
10471  linkpath[rllen] = '\0';
10472 
10473  /*
10474  * Add the escape character '\\' before newline in a string to
10475  * ensure that we can distinguish between the newline in the
10476  * tablespace path and end of line while reading tablespace_map
10477  * file during archive recovery.
10478  */
10479  initStringInfo(&buflinkpath);
10480 
10481  while (*s)
10482  {
10483  if ((*s == '\n' || *s == '\r') && needtblspcmapfile)
10484  appendStringInfoChar(&buflinkpath, '\\');
10485  appendStringInfoChar(&buflinkpath, *s++);
10486  }
10487 
10488  /*
10489  * Relpath holds the relative path of the tablespace directory
10490  * when it's located within PGDATA, or NULL if it's located
10491  * elsewhere.
10492  */
10493  if (rllen > datadirpathlen &&
10494  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
10495  IS_DIR_SEP(linkpath[datadirpathlen]))
10496  relpath = linkpath + datadirpathlen + 1;
10497 
10498  ti = palloc(sizeof(tablespaceinfo));
10499  ti->oid = pstrdup(de->d_name);
10500  ti->path = pstrdup(buflinkpath.data);
10501  ti->rpath = relpath ? pstrdup(relpath) : NULL;
10502  ti->size = infotbssize ? sendTablespace(fullpath, true) : -1;
10503 
10504  if (tablespaces)
10505  *tablespaces = lappend(*tablespaces, ti);
10506 
10507  appendStringInfo(tblspcmapfile, "%s %s\n", ti->oid, ti->path);
10508 
10509  pfree(buflinkpath.data);
10510 #else
10511 
10512  /*
10513  * If the platform does not have symbolic links, it should not be
10514  * possible to have tablespaces - clearly somebody else created
10515  * them. Warn about it and ignore.
10516  */
10517  ereport(WARNING,
10518  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10519  errmsg("tablespaces are not supported on this platform")));
10520 #endif
10521  }
10522  FreeDir(tblspcdir);
10523 
10524  /*
10525  * Construct backup label file
10526  */
10527  if (exclusive)
10528  labelfile = makeStringInfo();
10529 
10530  /* Use the log timezone here, not the session timezone */
10531  stamp_time = (pg_time_t) time(NULL);
10532  pg_strftime(strfbuf, sizeof(strfbuf),
10533  "%Y-%m-%d %H:%M:%S %Z",
10534  pg_localtime(&stamp_time, log_timezone));
10535  appendStringInfo(labelfile, "START WAL LOCATION: %X/%X (file %s)\n",
10536  (uint32) (startpoint >> 32), (uint32) startpoint, xlogfilename);
10537  appendStringInfo(labelfile, "CHECKPOINT LOCATION: %X/%X\n",
10538  (uint32) (checkpointloc >> 32), (uint32) checkpointloc);
10539  appendStringInfo(labelfile, "BACKUP METHOD: %s\n",
10540  exclusive ? "pg_start_backup" : "streamed");
10541  appendStringInfo(labelfile, "BACKUP FROM: %s\n",
10542  backup_started_in_recovery ? "standby" : "master");
10543  appendStringInfo(labelfile, "START TIME: %s\n", strfbuf);
10544  appendStringInfo(labelfile, "LABEL: %s\n", backupidstr);
10545  appendStringInfo(labelfile, "START TIMELINE: %u\n", starttli);
10546 
10547  /*
10548  * Okay, write the file, or return its contents to caller.
10549  */
10550  if (exclusive)
10551  {
10552  /*
10553  * Check for existing backup label --- implies a backup is already
10554  * running. (XXX given that we checked exclusiveBackupState
10555  * above, maybe it would be OK to just unlink any such label
10556  * file?)
10557  */
10558  if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
10559  {
10560  if (errno != ENOENT)
10561  ereport(ERROR,
10563  errmsg("could not stat file \"%s\": %m",
10564  BACKUP_LABEL_FILE)));
10565  }
10566  else
10567  ereport(ERROR,
10568  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10569  errmsg("a backup is already in progress"),
10570  errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
10571  BACKUP_LABEL_FILE)));
10572 
10573  fp = AllocateFile(BACKUP_LABEL_FILE, "w");
10574 
10575  if (!fp)
10576  ereport(ERROR,
10578  errmsg("could not create file \"%s\": %m",
10579  BACKUP_LABEL_FILE)));
10580  if (fwrite(labelfile->data, labelfile->len, 1, fp) != 1 ||
10581  fflush(fp) != 0 ||
10582  pg_fsync(fileno(fp)) != 0 ||
10583  ferror(fp) ||
10584  FreeFile(fp))
10585  ereport(ERROR,
10587  errmsg("could not write file \"%s\": %m",
10588  BACKUP_LABEL_FILE)));
10589  /* Allocated locally for exclusive backups, so free separately */
10590  pfree(labelfile->data);
10591  pfree(labelfile);
10592 
10593  /* Write backup tablespace_map file. */
10594  if (tblspcmapfile->len > 0)
10595  {
10596  if (stat(TABLESPACE_MAP, &stat_buf) != 0)
10597  {
10598  if (errno != ENOENT)
10599  ereport(ERROR,
10601  errmsg("could not stat file \"%s\": %m",
10602  TABLESPACE_MAP)));
10603  }
10604  else
10605  ereport(ERROR,
10606  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10607  errmsg("a backup is already in progress"),
10608  errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
10609  TABLESPACE_MAP)));
10610 
10611  fp = AllocateFile(TABLESPACE_MAP, "w");
10612 
10613  if (!fp)
10614  ereport(ERROR,
10616  errmsg("could not create file \"%s\": %m",
10617  TABLESPACE_MAP)));
10618  if (fwrite(tblspcmapfile->data, tblspcmapfile->len, 1, fp) != 1 ||
10619  fflush(fp) != 0 ||
10620  pg_fsync(fileno(fp)) != 0 ||
10621  ferror(fp) ||
10622  FreeFile(fp))
10623  ereport(ERROR,
10625  errmsg("could not write file \"%s\": %m",
10626  TABLESPACE_MAP)));
10627  }
10628 
10629  /* Allocated locally for exclusive backups, so free separately */
10630  pfree(tblspcmapfile->data);
10631  pfree(tblspcmapfile);
10632  }
10633  }
10635 
10636  /*
10637  * Mark that start phase has correctly finished for an exclusive backup.
10638  * Session-level locks are updated as well to reflect that state.
10639  *
10640  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating backup
10641  * counters and session-level lock. Otherwise they can be updated
10642  * inconsistently, and which might cause do_pg_abort_backup() to fail.
10643  */
10644  if (exclusive)
10645  {
10648 
10649  /* Set session-level lock */
10652  }
10653  else
10655 
10656  /*
10657  * We're done. As a convenience, return the starting WAL location.
10658  */
10659  if (starttli_p)
10660  *starttli_p = starttli;
10661  return startpoint;
10662 }
size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm *tm)
Definition: strftime.c:122
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:9409
int errhint(const char *fmt,...)
Definition: elog.c:1069
uint32 TimeLineID
Definition: xlogdefs.h:52
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1689
int wal_segment_size
Definition: xlog.c:112
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:707
static SessionBackupState sessionBackupState
Definition: xlog.c:524
XLogRecPtr lastBackupStart
Definition: xlog.c:576
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#define XLogIsNeeded()
Definition: xlog.h:181
char * rpath
Definition: basebackup.h:28
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
slock_t info_lck
Definition: xlog.c:709
int errcode(int sqlerrcode)
Definition: elog.c:608
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:589
bool RecoveryInProgress(void)
Definition: xlog.c:7930
static bool backup_started_in_recovery
Definition: basebackup.c:76
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:1726
#define TABLESPACE_MAP
Definition: xlog.h:362
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool forcePageWrites
Definition: xlog.c:563
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:100
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:41
#define readlink(path, buf, size)
Definition: win32_port.h:222
int errcode_for_file_access(void)
Definition: elog.c:631
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2242
unsigned int uint32
Definition: c.h:359
int64 sendTablespace(char *path, bool sizeonly)
Definition: basebackup.c:958
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
#define CHECKPOINT_FORCE
Definition: xlog.h:215
#define ereport(elevel, rest)
Definition: elog.h:141
List * lappend(List *list, void *datum)
Definition: list.c:322
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:575
#define stat(a, b)
Definition: win32_port.h:255
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
static void pg_start_backup_callback(int code, Datum arg)
Definition: xlog.c:10666
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:574
uintptr_t Datum
Definition: postgres.h:367
static ControlFileData * ControlFile
Definition: xlog.c:720
#define BoolGetDatum(X)
Definition: postgres.h:402
bool fullPageWrites
Definition: pg_control.h:42
#define CHECKPOINT_WAIT
Definition: xlog.h:219
uint64 XLogRecPtr
Definition: xlogdefs.h:21
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2569
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1660
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1375
int FreeFile(FILE *file)
Definition: fd.c:2441
void * palloc(Size size)
Definition: mcxt.c:949
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:214
#define relpath(rnode, forknum)
Definition: relpath.h:87
char * DataDir
Definition: globals.c:62
#define BACKUP_LABEL_FILE
Definition: xlog.h:359
int pg_fsync(int fd)
Definition: fd.c:330
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:37
int FreeDir(DIR *dir)
Definition: fd.c:2621
void RequestCheckpoint(int flags)
Definition: checkpointer.c:896
#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 10734 of file xlog.c.

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

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

10735 {
10736  bool exclusive = (labelfile == NULL);
10737  bool backup_started_in_recovery = false;
10738  XLogRecPtr startpoint;
10739  XLogRecPtr stoppoint;
10740  TimeLineID stoptli;
10741  pg_time_t stamp_time;
10742  char strfbuf[128];
10743  char histfilepath[MAXPGPATH];
10744  char startxlogfilename[MAXFNAMELEN];
10745  char stopxlogfilename[MAXFNAMELEN];
10746  char lastxlogfilename[MAXFNAMELEN];
10747  char histfilename[MAXFNAMELEN];
10748  char backupfrom[20];
10749  XLogSegNo _logSegNo;
10750  FILE *lfp;
10751  FILE *fp;
10752  char ch;
10753  int seconds_before_warning;
10754  int waits = 0;
10755  bool reported_waiting = false;
10756  char *remaining;
10757  char *ptr;
10758  uint32 hi,
10759  lo;
10760 
10761  backup_started_in_recovery = RecoveryInProgress();
10762 
10763  /*
10764  * Currently only non-exclusive backup can be taken during recovery.
10765  */
10766  if (backup_started_in_recovery && exclusive)
10767  ereport(ERROR,
10768  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10769  errmsg("recovery is in progress"),
10770  errhint("WAL control functions cannot be executed during recovery.")));
10771 
10772  /*
10773  * During recovery, we don't need to check WAL level. Because, if WAL
10774  * level is not sufficient, it's impossible to get here during recovery.
10775  */
10776  if (!backup_started_in_recovery && !XLogIsNeeded())
10777  ereport(ERROR,
10778  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10779  errmsg("WAL level not sufficient for making an online backup"),
10780  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
10781 
10782  if (exclusive)
10783  {
10784  /*
10785  * At first, mark that we're now stopping an exclusive backup, to
10786  * ensure that there are no other sessions currently running
10787  * pg_start_backup() or pg_stop_backup().
10788  */
10791  {
10793  ereport(ERROR,
10794  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10795  errmsg("exclusive backup not in progress")));
10796  }
10799 
10800  /*
10801  * Remove backup_label. In case of failure, the state for an exclusive
10802  * backup is switched back to in-progress.
10803  */
10805  {
10806  /*
10807  * Read the existing label file into memory.
10808  */
10809  struct stat statbuf;
10810  int r;
10811 
10812  if (stat(BACKUP_LABEL_FILE, &statbuf))
10813  {
10814  /* should not happen per the upper checks */
10815  if (errno != ENOENT)
10816  ereport(ERROR,
10818  errmsg("could not stat file \"%s\": %m",
10819  BACKUP_LABEL_FILE)));
10820  ereport(ERROR,
10821  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10822  errmsg("a backup is not in progress")));
10823  }
10824 
10825  lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
10826  if (!lfp)
10827  {
10828  ereport(ERROR,
10830  errmsg("could not read file \"%s\": %m",
10831  BACKUP_LABEL_FILE)));
10832  }
10833  labelfile = palloc(statbuf.st_size + 1);
10834  r = fread(labelfile, statbuf.st_size, 1, lfp);
10835  labelfile[statbuf.st_size] = '\0';
10836 
10837  /*
10838  * Close and remove the backup label file
10839  */
10840  if (r != 1 || ferror(lfp) || FreeFile(lfp))
10841  ereport(ERROR,
10843  errmsg("could not read file \"%s\": %m",
10844  BACKUP_LABEL_FILE)));
10846 
10847  /*
10848  * Remove tablespace_map file if present, it is created only if
10849  * there are tablespaces.
10850  */
10852  }
10854  }
10855 
10856  /*
10857  * OK to update backup counters, forcePageWrites and session-level lock.
10858  *
10859  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
10860  * Otherwise they can be updated inconsistently, and which might cause
10861  * do_pg_abort_backup() to fail.
10862  */
10864  if (exclusive)
10865  {
10867  }
10868  else
10869  {
10870  /*
10871  * The user-visible pg_start/stop_backup() functions that operate on
10872  * exclusive backups can be called at any time, but for non-exclusive
10873  * backups, it is expected that each do_pg_start_backup() call is
10874  * matched by exactly one do_pg_stop_backup() call.
10875  */
10878  }
10879 
10882  {
10883  XLogCtl->Insert.forcePageWrites = false;
10884  }
10885 
10886  /*
10887  * Clean up session-level lock.
10888  *
10889  * You might think that WALInsertLockRelease() can be called before
10890  * cleaning up session-level lock because session-level lock doesn't need
10891  * to be protected with WAL insertion lock. But since
10892  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
10893  * cleaned up before it.
10894  */
10896 
10898 
10899  /*
10900  * Read and parse the START WAL LOCATION line (this code is pretty crude,
10901  * but we are not expecting any variability in the file format).
10902  */
10903  if (sscanf(labelfile, "START WAL LOCATION: %X/%X (file %24s)%c",
10904  &hi, &lo, startxlogfilename,
10905  &ch) != 4 || ch != '\n')
10906  ereport(ERROR,
10907  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10908  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
10909  startpoint = ((uint64) hi) << 32 | lo;
10910  remaining = strchr(labelfile, '\n') + 1; /* %n is not portable enough */
10911 
10912  /*
10913  * Parse the BACKUP FROM line. If we are taking an online backup from the
10914  * standby, we confirm that the standby has not been promoted during the
10915  * backup.
10916  */
10917  ptr = strstr(remaining, "BACKUP FROM:");
10918  if (!ptr || sscanf(ptr, "BACKUP FROM: %19s\n", backupfrom) != 1)
10919  ereport(ERROR,
10920  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10921  errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
10922  if (strcmp(backupfrom, "standby") == 0 && !backup_started_in_recovery)
10923  ereport(ERROR,
10924  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10925  errmsg("the standby was promoted during online backup"),
10926  errhint("This means that the backup being taken is corrupt "
10927  "and should not be used. "
10928  "Try taking another online backup.")));
10929 
10930  /*
10931  * During recovery, we don't write an end-of-backup record. We assume that
10932  * pg_control was backed up last and its minimum recovery point can be
10933  * available as the backup end location. Since we don't have an
10934  * end-of-backup record, we use the pg_control value to check whether
10935  * we've reached the end of backup when starting recovery from this
10936  * backup. We have no way of checking if pg_control wasn't backed up last
10937  * however.
10938  *
10939  * We don't force a switch to new WAL file but it is still possible to
10940  * wait for all the required files to be archived if waitforarchive is
10941  * true. This is okay if we use the backup to start a standby and fetch
10942  * the missing WAL using streaming replication. But in the case of an
10943  * archive recovery, a user should set waitforarchive to true and wait for
10944  * them to be archived to ensure that all the required files are
10945  * available.
10946  *
10947  * We return the current minimum recovery point as the backup end
10948  * location. Note that it can be greater than the exact backup end
10949  * location if the minimum recovery point is updated after the backup of
10950  * pg_control. This is harmless for current uses.
10951  *
10952  * XXX currently a backup history file is for informational and debug
10953  * purposes only. It's not essential for an online backup. Furthermore,
10954  * even if it's created, it will not be archived during recovery because
10955  * an archiver is not invoked. So it doesn't seem worthwhile to write a
10956  * backup history file during recovery.
10957  */
10958  if (backup_started_in_recovery)
10959  {
10960  XLogRecPtr recptr;
10961 
10962  /*
10963  * Check to see if all WAL replayed during online backup contain
10964  * full-page writes.
10965  */
10967  recptr = XLogCtl->lastFpwDisableRecPtr;
10969 
10970  if (startpoint <= recptr)
10971  ereport(ERROR,
10972  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
10973  errmsg("WAL generated with full_page_writes=off was replayed "
10974  "during online backup"),
10975  errhint("This means that the backup being taken on the standby "
10976  "is corrupt and should not be used. "
10977  "Enable full_page_writes and run CHECKPOINT on the master, "
10978  "and then try an online backup again.")));
10979 
10980 
10981  LWLockAcquire(ControlFileLock, LW_SHARED);
10982  stoppoint = ControlFile->minRecoveryPoint;
10983  stoptli = ControlFile->minRecoveryPointTLI;
10984  LWLockRelease(ControlFileLock);
10985  }
10986  else
10987  {
10988  /*
10989  * Write the backup-end xlog record
10990  */
10991  XLogBeginInsert();
10992  XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
10993  stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
10994  stoptli = ThisTimeLineID;
10995 
10996  /*
10997  * Force a switch to a new xlog segment file, so that the backup is
10998  * valid as soon as archiver moves out the current segment file.
10999  */
11000  RequestXLogSwitch(false);
11001 
11002  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11003  XLogFileName(stopxlogfilename, stoptli, _logSegNo, wal_segment_size);
11004 
11005  /* Use the log timezone here, not the session timezone */
11006  stamp_time = (pg_time_t) time(NULL);
11007  pg_strftime(strfbuf, sizeof(strfbuf),
11008  "%Y-%m-%d %H:%M:%S %Z",
11009  pg_localtime(&stamp_time, log_timezone));
11010 
11011  /*
11012  * Write the backup history file
11013  */
11014  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11015  BackupHistoryFilePath(histfilepath, stoptli, _logSegNo,
11016  startpoint, wal_segment_size);
11017  fp = AllocateFile(histfilepath, "w");
11018  if (!fp)
11019  ereport(ERROR,
11021  errmsg("could not create file \"%s\": %m",
11022  histfilepath)));
11023  fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
11024  (uint32) (startpoint >> 32), (uint32) startpoint, startxlogfilename);
11025  fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
11026  (uint32) (stoppoint >> 32), (uint32) stoppoint, stopxlogfilename);
11027 
11028  /*
11029  * Transfer remaining lines including label and start timeline to
11030  * history file.
11031  */
11032  fprintf(fp, "%s", remaining);
11033  fprintf(fp, "STOP TIME: %s\n", strfbuf);
11034  fprintf(fp, "STOP TIMELINE: %u\n", stoptli);
11035  if (fflush(fp) || ferror(fp) || FreeFile(fp))
11036  ereport(ERROR,
11038  errmsg("could not write file \"%s\": %m",
11039  histfilepath)));
11040 
11041  /*
11042  * Clean out any no-longer-needed history files. As a side effect,
11043  * this will post a .ready file for the newly created history file,
11044  * notifying the archiver that history file may be archived
11045  * immediately.
11046  */
11048  }
11049 
11050  /*
11051  * If archiving is enabled, wait for all the required WAL files to be
11052  * archived before returning. If archiving isn't enabled, the required WAL
11053  * needs to be transported via streaming replication (hopefully with
11054  * wal_keep_segments set high enough), or some more exotic mechanism like
11055  * polling and copying files from pg_wal with script. We have no knowledge
11056  * of those mechanisms, so it's up to the user to ensure that he gets all
11057  * the required WAL.
11058  *
11059  * We wait until both the last WAL file filled during backup and the
11060  * history file have been archived, and assume that the alphabetic sorting
11061  * property of the WAL files ensures any earlier WAL files are safely
11062  * archived as well.
11063  *
11064  * We wait forever, since archive_command is supposed to work and we
11065  * assume the admin wanted his backup to work completely. If you don't
11066  * wish to wait, then either waitforarchive should be passed in as false,
11067  * or you can set statement_timeout. Also, some notices are issued to
11068  * clue in anyone who might be doing this interactively.
11069  */
11070 
11071  if (waitforarchive &&
11072  ((!backup_started_in_recovery && XLogArchivingActive()) ||
11073  (backup_started_in_recovery && XLogArchivingAlways())))
11074  {
11075  XLByteToPrevSeg(stoppoint, _logSegNo, wal_segment_size);
11076  XLogFileName(lastxlogfilename, stoptli, _logSegNo, wal_segment_size);
11077 
11078  XLByteToSeg(startpoint, _logSegNo, wal_segment_size);
11079  BackupHistoryFileName(histfilename, stoptli, _logSegNo,
11080  startpoint, wal_segment_size);
11081 
11082  seconds_before_warning = 60;
11083  waits = 0;
11084 
11085  while (XLogArchiveIsBusy(lastxlogfilename) ||
11086  XLogArchiveIsBusy(histfilename))
11087  {
11089 
11090  if (!reported_waiting && waits > 5)
11091  {
11092  ereport(NOTICE,
11093  (errmsg("base backup done, waiting for required WAL segments to be archived")));
11094  reported_waiting = true;
11095  }
11096 
11097  pg_usleep(1000000L);
11098 
11099  if (++waits >= seconds_before_warning)
11100  {
11101  seconds_before_warning *= 2; /* This wraps in >10 years... */
11102  ereport(WARNING,
11103  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
11104  waits),
11105  errhint("Check that your archive_command is executing properly. "
11106  "You can safely cancel this backup, "
11107  "but the database backup will not be usable without all the WAL segments.")));
11108  }
11109  }
11110 
11111  ereport(NOTICE,
11112  (errmsg("all required WAL segments have been archived")));
11113  }
11114  else if (waitforarchive)
11115  ereport(NOTICE,
11116  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
11117 
11118  /*
11119  * We're done. As a convenience, return the ending WAL location.
11120  */
11121  if (stoptli_p)
11122  *stoptli_p = stoptli;
11123  return stoppoint;
11124 }
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:122
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:9409
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:1069
uint32 TimeLineID
Definition: xlogdefs.h:52
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1689
int wal_segment_size
Definition: xlog.c:112
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:707
static SessionBackupState sessionBackupState
Definition: xlog.c:524
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogIsNeeded()
Definition: xlog.h:181
slock_t info_lck
Definition: xlog.c:709
int errcode(int sqlerrcode)
Definition: elog.c:608
XLogCtlInsert Insert
Definition: xlog.c:589
#define BackupHistoryFileName(fname, tli, logSegNo, startpoint, wal_segsz_bytes)
bool RecoveryInProgress(void)
Definition: xlog.c:7930
static bool backup_started_in_recovery
Definition: basebackup.c:76
#define fprintf
Definition: port.h:196
pg_tz * log_timezone
Definition: pgtz.c:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define TABLESPACE_MAP
Definition: xlog.h:362
#define SpinLockAcquire(lock)
Definition: spin.h:62
void pg_usleep(long microsec)
Definition: signal.c:53
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define XLogArchivingAlways()
Definition: xlog.h:173
bool forcePageWrites
Definition: xlog.c:563
#define ERROR
Definition: elog.h:43
static void CleanupBackupHistory(void)
Definition: xlog.c:4222
#define MAXPGPATH
uint64 XLogSegNo
Definition: xlogdefs.h:41
int errcode_for_file_access(void)
Definition: elog.c:631
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2242
unsigned int uint32
Definition: c.h:359
#define ereport(elevel, rest)
Definition: elog.h:141
#define XLOG_BACKUP_END
Definition: pg_control.h:72
#define WARNING
Definition: elog.h:40
int nonExclusiveBackups
Definition: xlog.c:575
#define stat(a, b)
Definition: win32_port.h:255
#define MAXFNAMELEN
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
#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:415
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:574
uintptr_t Datum
Definition: postgres.h:367
static ControlFileData * ControlFile
Definition: xlog.c:720
#define BoolGetDatum(X)
Definition: postgres.h:402
TimeLineID ThisTimeLineID
Definition: xlog.c:187
#define NOTICE
Definition: elog.h:37
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:663
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
#define XLogArchivingActive()
Definition: xlog.h:170
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1660
static XLogCtlData * XLogCtl
Definition: xlog.c:712
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static void pg_stop_backup_callback(int code, Datum arg)
Definition: xlog.c:10695
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1375
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:733
int FreeFile(FILE *file)
Definition: fd.c:2441
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define BACKUP_LABEL_FILE
Definition: xlog.h:359
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
void XLogBeginInsert(void)
Definition: xloginsert.c:120
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 12193 of file xlog.c.

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

12194 {
12195  static XLogRecPtr lastComplaint = 0;
12196 
12197  if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
12198  {
12199  if (RecPtr == lastComplaint)
12200  emode = DEBUG1;
12201  else
12202  lastComplaint = RecPtr;
12203  }
12204  return emode;
12205 }
#define DEBUG1
Definition: elog.h:25
static XLogSource readSource
Definition: xlog.c:793
#define LOG
Definition: elog.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ exitArchiveRecovery()

static void exitArchiveRecovery ( TimeLineID  endTLI,
XLogRecPtr  endOfLog 
)
static

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

5459 {
5460  char xlogfname[MAXFNAMELEN];
5461  XLogSegNo endLogSegNo;
5462  XLogSegNo startLogSegNo;
5463 
5464  /* we always switch to a new timeline after archive recovery */
5465  Assert(endTLI != ThisTimeLineID);
5466 
5467  /*
5468  * We are no longer in archive recovery state.
5469  */
5470  InArchiveRecovery = false;
5471 
5472  /*
5473  * Update min recovery point one last time.
5474  */
5476 
5477  /*
5478  * If the ending log segment is still open, close it (to avoid problems on
5479  * Windows with trying to rename or delete an open file).
5480  */
5481  if (readFile >= 0)
5482  {
5483  close(readFile);
5484  readFile = -1;
5485  }
5486 
5487  /*
5488  * Calculate the last segment on the old timeline, and the first segment
5489  * on the new timeline. If the switch happens in the middle of a segment,
5490  * they are the same, but if the switch happens exactly at a segment
5491  * boundary, startL