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/multixact.h"
#include "access/rewriteheap.h"
#include "access/subtrans.h"
#include "access/timeline.h"
#include "access/transam.h"
#include "access/tuptoaster.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 "miscadmin.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "postmaster/bgwriter.h"
#include "postmaster/walwriter.h"
#include "postmaster/startup.h"
#include "replication/basebackup.h"
#include "replication/logical.h"
#include "replication/slot.h"
#include "replication/origin.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 "utils/backend_random.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/pg_lsn.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
#include "pg_trace.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 PROMOTE_SIGNAL_FILE   "promote"
 
#define FALLBACK_PROMOTE_SIGNAL_FILE   "fallback_promote"
 
#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 readRecoveryCommandFile (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, TimeLineID *readTLI)
 
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 RemoveOldXlogFiles (XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
 
static void RemoveXlogFile (const char *segname, XLogRecPtr PriorRedoPtr, 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 whichChkpti, 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 PriorRedoPtr)
 
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 GetNextXidAndEpoch (TransactionId *xid, uint32 *epoch)
 
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)
 
char * XLogFileNameP (TimeLineID tli, 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 (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 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 []
 
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 restoredFromArchive = false
 
static char * replay_image_masked = NULL
 
static char * master_image_masked = NULL
 
char * recoveryRestoreCommand = NULL
 
static char * recoveryEndCommand = NULL
 
static char * archiveCleanupCommand = NULL
 
static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET
 
static bool recoveryTargetInclusive = true
 
static RecoveryTargetAction recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE
 
static TransactionId recoveryTargetXid
 
static TimestampTz recoveryTargetTime
 
static char * recoveryTargetName
 
static XLogRecPtr recoveryTargetLSN
 
static int recovery_min_apply_delay = 0
 
static TimestampTz recoveryDelayUntilTime
 
static bool StandbyModeRequested = false
 
static char * PrimaryConnInfo = NULL
 
static char * PrimarySlotName = NULL
 
static char * TriggerFile = 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
 
static TimeLineID recoveryTargetTLI
 
static bool recoveryTargetIsLatest = false
 
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 * xlogSourceNames [] = {"any", "archive", "pg_wal", "stream"}
 
static int openLogFile = -1
 
static XLogSegNo openLogSegNo = 0
 
static uint32 openLogOff = 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 741 of file xlog.c.

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

◆ FALLBACK_PROMOTE_SIGNAL_FILE

#define FALLBACK_PROMOTE_SIGNAL_FILE   "fallback_promote"

Definition at line 85 of file xlog.c.

Referenced by CheckForStandbyTrigger(), CheckPromoteSignal(), and RemovePromoteSignalFiles().

◆ INSERT_FREESPACE

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

Definition at line 721 of file xlog.c.

Referenced by CopyXLogRecordToWAL(), and CreateCheckPoint().

◆ NextBufIdx

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

Definition at line 725 of file xlog.c.

Referenced by XLogWrite().

◆ NUM_XLOGINSERT_LOCKS

◆ PROMOTE_SIGNAL_FILE

#define PROMOTE_SIGNAL_FILE   "promote"

Definition at line 84 of file xlog.c.

Referenced by CheckForStandbyTrigger(), CheckPromoteSignal(), and RemovePromoteSignalFiles().

◆ RECOVERY_COMMAND_DONE

#define RECOVERY_COMMAND_DONE   "recovery.done"

Definition at line 83 of file xlog.c.

Referenced by exitArchiveRecovery().

◆ RECOVERY_COMMAND_FILE

#define RECOVERY_COMMAND_FILE   "recovery.conf"

Definition at line 82 of file xlog.c.

Referenced by exitArchiveRecovery(), and readRecoveryCommandFile().

◆ 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:575
#define ERROR
Definition: elog.h:43
int errmsg(const char *fmt,...)
Definition: elog.c:797

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

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

Typedef Documentation

◆ ExclusiveBackupState

◆ WALInsertLockPadded

◆ XLogCtlData

◆ XLogCtlInsert

◆ XLogPageReadPrivate

◆ XLogwrtResult

◆ XLogwrtRqst

Enumeration Type Documentation

◆ ExclusiveBackupState

Enumerator
EXCLUSIVE_BACKUP_NONE 
EXCLUSIVE_BACKUP_STARTING 
EXCLUSIVE_BACKUP_IN_PROGRESS 
EXCLUSIVE_BACKUP_STOPPING 

Definition at line 500 of file xlog.c.

◆ XLogSource

enum XLogSource
Enumerator
XLOG_FROM_ANY 
XLOG_FROM_ARCHIVE 
XLOG_FROM_PG_WAL 
XLOG_FROM_STREAM 

Definition at line 757 of file xlog.c.

758 {
759  XLOG_FROM_ANY = 0, /* request to read WAL from any source */
760  XLOG_FROM_ARCHIVE, /* restored using restore_command */
761  XLOG_FROM_PG_WAL, /* existing file in pg_wal */
762  XLOG_FROM_STREAM /* streamed from master */
763 } XLogSource;
XLogSource
Definition: xlog.c:757

Function Documentation

◆ AdvanceXLInsertBuffer()

static void AdvanceXLInsertBuffer ( XLogRecPtr  upto,
bool  opportunistic 
)
static

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

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

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 2272 of file xlog.c.

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

2273 {
2276 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2236
#define newval
double CheckPointCompletionTarget
Definition: checkpointer.c:147

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 2265 of file xlog.c.

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

2266 {
2269 }
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2236
int max_wal_size_mb
Definition: xlog.c:89
#define newval

◆ assign_xlog_sync_method()

void assign_xlog_sync_method ( int  new_sync_method,
void *  extra 
)

Definition at line 10121 of file xlog.c.

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

10122 {
10123  if (sync_method != new_sync_method)
10124  {
10125  /*
10126  * To ensure that no blocks escape unsynced, force an fsync on the
10127  * currently open log segment (if any). Also, if the open flag is
10128  * changing, close the log file so it will be reopened (with new flag
10129  * bit) at next use.
10130  */
10131  if (openLogFile >= 0)
10132  {
10134  if (pg_fsync(openLogFile) != 0)
10135  ereport(PANIC,
10137  errmsg("could not fsync log segment %s: %m",
10140  if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
10141  XLogFileClose();
10142  }
10143  }
10144 }
static int get_sync_bit(int method)
Definition: xlog.c:10065
#define PANIC
Definition: elog.h:53
static XLogSegNo openLogSegNo
Definition: xlog.c:775
static void XLogFileClose(void)
Definition: xlog.c:3727
char * XLogFileNameP(TimeLineID tli, XLogSegNo segno)
Definition: xlog.c:10197
int errcode_for_file_access(void)
Definition: elog.c:598
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
#define ereport(elevel, rest)
Definition: elog.h:122
static int openLogFile
Definition: xlog.c:774
TimeLineID ThisTimeLineID
Definition: xlog.c:181
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
int sync_method
Definition: xlog.c:103
int errmsg(const char *fmt,...)
Definition: elog.c:797
int pg_fsync(int fd)
Definition: fd.c:341

◆ BackupInProgress()

bool BackupInProgress ( void  )

Definition at line 11490 of file xlog.c.

References BACKUP_LABEL_FILE, and stat.

Referenced by pg_is_in_backup(), and PostmasterStateMachine().

11491 {
11492  struct stat stat_buf;
11493 
11494  return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
11495 }
struct stat stat_buf
Definition: pg_standby.c:103
#define stat(a, b)
Definition: win32_port.h:266
#define BACKUP_LABEL_FILE
Definition: xlog.h:322

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 5026 of file xlog.c.

References AdvanceOldestClogXid(), Assert, bootstrap_data_checksum_version, BootStrapCLOG(), BootStrapCommitTs(), BootStrapMultiXact(), BootStrapSUBTRANS(), buffer, 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, CheckPoint::fullPageWrites, fullPageWrites, gettimeofday(), INIT_CRC32C, InvalidTransactionId, max_locks_per_xact, ControlFileData::max_locks_per_xact, max_prepared_xacts, ControlFileData::max_prepared_xacts, max_worker_processes, ControlFileData::max_worker_processes, MaxConnections, ControlFileData::MaxConnections, MOCK_AUTH_NONCE_LEN, ControlFileData::mock_authentication_nonce, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, CheckPoint::nextXid, VariableCacheData::nextXid, CheckPoint::nextXidEpoch, offsetof, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, palloc(), PANIC, pfree(), pg_backend_random(), pg_fsync(), 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().

5027 {
5028  CheckPoint checkPoint;
5029  char *buffer;
5030  XLogPageHeader page;
5031  XLogLongPageHeader longpage;
5032  XLogRecord *record;
5033  char *recptr;
5034  bool use_existent;
5035  uint64 sysidentifier;
5036  char mock_auth_nonce[MOCK_AUTH_NONCE_LEN];
5037  struct timeval tv;
5038  pg_crc32c crc;
5039 
5040  /*
5041  * Select a hopefully-unique system identifier code for this installation.
5042  * We use the result of gettimeofday(), including the fractional seconds
5043  * field, as being about as unique as we can easily get. (Think not to
5044  * use random(), since it hasn't been seeded and there's no portable way
5045  * to seed it other than the system clock value...) The upper half of the
5046  * uint64 value is just the tv_sec part, while the lower half contains the
5047  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
5048  * PID for a little extra uniqueness. A person knowing this encoding can
5049  * determine the initialization time of the installation, which could
5050  * perhaps be useful sometimes.
5051  */
5052  gettimeofday(&tv, NULL);
5053  sysidentifier = ((uint64) tv.tv_sec) << 32;
5054  sysidentifier |= ((uint64) tv.tv_usec) << 12;
5055  sysidentifier |= getpid() & 0xFFF;
5056 
5057  /*
5058  * Generate a random nonce. This is used for authentication requests that
5059  * will fail because the user does not exist. The nonce is used to create
5060  * a genuine-looking password challenge for the non-existent user, in lieu
5061  * of an actual stored password.
5062  */
5063  if (!pg_backend_random(mock_auth_nonce, MOCK_AUTH_NONCE_LEN))
5064  ereport(PANIC,
5065  (errcode(ERRCODE_INTERNAL_ERROR),
5066  errmsg("could not generate secret authorization token")));
5067 
5068  /* First timeline ID is always 1 */
5069  ThisTimeLineID = 1;
5070 
5071  /* page buffer must be aligned suitably for O_DIRECT */
5072  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
5073  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
5074  memset(page, 0, XLOG_BLCKSZ);
5075 
5076  /*
5077  * Set up information for the initial checkpoint record
5078  *
5079  * The initial checkpoint record is written to the beginning of the WAL
5080  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
5081  * used, so that we can use 0/0 to mean "before any valid WAL segment".
5082  */
5083  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
5084  checkPoint.ThisTimeLineID = ThisTimeLineID;
5085  checkPoint.PrevTimeLineID = ThisTimeLineID;
5086  checkPoint.fullPageWrites = fullPageWrites;
5087  checkPoint.nextXidEpoch = 0;
5088  checkPoint.nextXid = FirstNormalTransactionId;
5089  checkPoint.nextOid = FirstBootstrapObjectId;
5090  checkPoint.nextMulti = FirstMultiXactId;
5091  checkPoint.nextMultiOffset = 0;
5092  checkPoint.oldestXid = FirstNormalTransactionId;
5093  checkPoint.oldestXidDB = TemplateDbOid;
5094  checkPoint.oldestMulti = FirstMultiXactId;
5095  checkPoint.oldestMultiDB = TemplateDbOid;
5098  checkPoint.time = (pg_time_t) time(NULL);
5100 
5101  ShmemVariableCache->nextXid = checkPoint.nextXid;
5102  ShmemVariableCache->nextOid = checkPoint.nextOid;
5104  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5105  AdvanceOldestClogXid(checkPoint.oldestXid);
5106  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5107  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5109 
5110  /* Set up the XLOG page header */
5111  page->xlp_magic = XLOG_PAGE_MAGIC;
5112  page->xlp_info = XLP_LONG_HEADER;
5113  page->xlp_tli = ThisTimeLineID;
5115  longpage = (XLogLongPageHeader) page;
5116  longpage->xlp_sysid = sysidentifier;
5117  longpage->xlp_seg_size = wal_segment_size;
5118  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
5119 
5120  /* Insert the initial checkpoint record */
5121  recptr = ((char *) page + SizeOfXLogLongPHD);
5122  record = (XLogRecord *) recptr;
5123  record->xl_prev = 0;
5124  record->xl_xid = InvalidTransactionId;
5125  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
5127  record->xl_rmid = RM_XLOG_ID;
5128  recptr += SizeOfXLogRecord;
5129  /* fill the XLogRecordDataHeaderShort struct */
5130  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
5131  *(recptr++) = sizeof(checkPoint);
5132  memcpy(recptr, &checkPoint, sizeof(checkPoint));
5133  recptr += sizeof(checkPoint);
5134  Assert(recptr - (char *) record == record->xl_tot_len);
5135 
5136  INIT_CRC32C(crc);
5137  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
5138  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
5139  FIN_CRC32C(crc);
5140  record->xl_crc = crc;
5141 
5142  /* Create first XLOG segment file */
5143  use_existent = false;
5144  openLogFile = XLogFileInit(1, &use_existent, false);
5145 
5146  /* Write the first page with the initial record */
5147  errno = 0;
5149  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
5150  {
5151  /* if write didn't set errno, assume problem is no disk space */
5152  if (errno == 0)
5153  errno = ENOSPC;
5154  ereport(PANIC,
5156  errmsg("could not write bootstrap write-ahead log file: %m")));
5157  }
5159 
5161  if (pg_fsync(openLogFile) != 0)
5162  ereport(PANIC,
5164  errmsg("could not fsync bootstrap write-ahead log file: %m")));
5166 
5167  if (close(openLogFile))
5168  ereport(PANIC,
5170  errmsg("could not close bootstrap write-ahead log file: %m")));
5171 
5172  openLogFile = -1;
5173 
5174  /* Now create pg_control */
5175 
5176  memset(ControlFile, 0, sizeof(ControlFileData));
5177  /* Initialize pg_control status fields */
5178  ControlFile->system_identifier = sysidentifier;
5179  memcpy(ControlFile->mock_authentication_nonce, mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
5181  ControlFile->time = checkPoint.time;
5182  ControlFile->checkPoint = checkPoint.redo;
5183  ControlFile->checkPointCopy = checkPoint;
5184  ControlFile->unloggedLSN = 1;
5185 
5186  /* Set important parameter values for use when replaying WAL */
5195 
5196  /* some additional ControlFile fields are set in WriteControlFile() */
5197 
5198  WriteControlFile();
5199 
5200  /* Bootstrap the commit log, too */
5201  BootStrapCLOG();
5205 
5206  pfree(buffer);
5207 
5208  /*
5209  * Force control file to be read - in contrast to normal processing we'd
5210  * otherwise never run the checks and GUC related initializations therein.
5211  */
5212  ReadControlFile();
5213 }
static void WriteControlFile(void)
Definition: xlog.c:4395
#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:181
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
int max_prepared_xacts
Definition: pg_control.h:180
int64 pg_time_t
Definition: pgtime.h:23
int wal_segment_size
Definition: xlog.c:113
pg_time_t time
Definition: pg_control.h:128
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:849
uint32 oidCount
Definition: transam.h:112
#define write(a, b, c)
Definition: win32.h:14
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:201
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:104
int XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
Definition: xlog.c:3180
void BootStrapMultiXact(void)
Definition: multixact.c:1866
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
int errcode(int sqlerrcode)
Definition: elog.c:575
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:57
CheckPoint checkPointCopy
Definition: pg_control.h:131
TransactionId oldestXid
Definition: pg_control.h:47
TransactionId nextXid
Definition: pg_control.h:43
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:53
uint32 bootstrap_data_checksum_version
Definition: bootstrap.c:50
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
#define MOCK_AUTH_NONCE_LEN
Definition: pg_control.h:27
bool fullPageWrites
Definition: xlog.c:97
void BootStrapSUBTRANS(void)
Definition: subtrans.c:212
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:271
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1031
#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
TransactionId nextXid
Definition: transam.h:117
static void ReadControlFile(void)
Definition: xlog.c:4484
uint32 nextXidEpoch
Definition: pg_control.h:42
bool track_commit_timestamp
Definition: commit_ts.c:103
uint32 data_checksum_version
Definition: pg_control.h:221
bool pg_backend_random(char *dst, int len)
#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:598
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
#define FirstBootstrapObjectId
Definition: transam.h:93
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
#define FirstMultiXactId
Definition: multixact.h:24
#define ereport(elevel, rest)
Definition: elog.h:122
int max_locks_per_xact
Definition: lock.c:54
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
TransactionId newestCommitTsXid
Definition: pg_control.h:54
char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]
Definition: pg_control.h:228
int MaxConnections
Definition: globals.c:131
Oid oldestMultiDB
Definition: pg_control.h:50
static int openLogFile
Definition: xlog.c:774
static ControlFileData * ControlFile
Definition: xlog.c:715
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2194
TimeLineID ThisTimeLineID
Definition: xlog.c:181
Oid nextOid
Definition: pg_control.h:44
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:645
bool fullPageWrites
Definition: pg_control.h:41
bool wal_log_hints
Definition: xlog.c:98
void BootStrapCLOG(void)
Definition: clog.c:712
bool track_commit_timestamp
Definition: pg_control.h:182
#define Assert(condition)
Definition: c.h:699
#define XLP_LONG_HEADER
Definition: xlog_internal.h:79
Oid oldestXidDB
Definition: pg_control.h:48
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:288
uint8 xl_info
Definition: xlogrecord.h:46
MultiXactId nextMulti
Definition: pg_control.h:45
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:224
TransactionId xl_xid
Definition: xlogrecord.h:44
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
int max_worker_processes
Definition: globals.c:132
int pg_fsync(int fd)
Definition: fd.c:341
#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:36
#define offsetof(type, field)
Definition: c.h:622
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2160

◆ CalculateCheckpointSegments()

static void CalculateCheckpointSegments ( void  )
static

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

2237 {
2238  double target;
2239 
2240  /*-------
2241  * Calculate the distance at which to trigger a checkpoint, to avoid
2242  * exceeding max_wal_size_mb. This is based on two assumptions:
2243  *
2244  * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
2245  * WAL for two checkpoint cycles to allow us to recover from the
2246  * secondary checkpoint if the first checkpoint failed, though we
2247  * only did this on the master anyway, not on standby. Keeping just
2248  * one checkpoint simplifies processing and reduces disk space in
2249  * many smaller databases.)
2250  * b) during checkpoint, we consume checkpoint_completion_target *
2251  * number of segments consumed between checkpoints.
2252  *-------
2253  */
2254  target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
2256 
2257  /* round down */
2258  CheckPointSegments = (int) target;
2259 
2260  if (CheckPointSegments < 1)
2261  CheckPointSegments = 1;
2262 }
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:741
int wal_segment_size
Definition: xlog.c:113
int max_wal_size_mb
Definition: xlog.c:89
int CheckPointSegments
Definition: xlog.c:126
double CheckPointCompletionTarget
Definition: checkpointer.c:147

◆ CancelBackup()

void CancelBackup ( void  )

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

11511 {
11512  struct stat stat_buf;
11513 
11514  /* if the backup_label file is not there, return */
11515  if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
11516  return;
11517 
11518  /* remove leftover file from previously canceled backup if it exists */
11519  unlink(BACKUP_LABEL_OLD);
11520 
11522  {
11523  ereport(WARNING,
11525  errmsg("online backup mode was not canceled"),
11526  errdetail("File \"%s\" could not be renamed to \"%s\": %m.",
11528  return;
11529  }
11530 
11531  /* if the tablespace_map file is not there, return */
11532  if (stat(TABLESPACE_MAP, &stat_buf) < 0)
11533  {
11534  ereport(LOG,
11535  (errmsg("online backup mode canceled"),
11536  errdetail("File \"%s\" was renamed to \"%s\".",
11538  return;
11539  }
11540 
11541  /* remove leftover file from previously canceled backup if it exists */
11542  unlink(TABLESPACE_MAP_OLD);
11543 
11545  {
11546  ereport(LOG,
11547  (errmsg("online backup mode canceled"),
11548  errdetail("Files \"%s\" and \"%s\" were renamed to "
11549  "\"%s\" and \"%s\", respectively.",
11552  }
11553  else
11554  {
11555  ereport(WARNING,
11557  errmsg("online backup mode canceled"),
11558  errdetail("File \"%s\" was renamed to \"%s\", but "
11559  "file \"%s\" could not be renamed to \"%s\": %m.",
11562  }
11563 }
#define DEBUG1
Definition: elog.h:25
#define LOG
Definition: elog.h:26
#define BACKUP_LABEL_OLD
Definition: xlog.h:323
#define TABLESPACE_MAP
Definition: xlog.h:325
struct stat stat_buf
Definition: pg_standby.c:103
int errdetail(const char *fmt,...)
Definition: elog.c:873
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:601
#define WARNING
Definition: elog.h:40
#define stat(a, b)
Definition: win32_port.h:266
#define TABLESPACE_MAP_OLD
Definition: xlog.h:326
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define BACKUP_LABEL_FILE
Definition: xlog.h:322

◆ check_wal_buffers()

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

Definition at line 4817 of file xlog.c.

References XLOGbuffers, and XLOGChooseNumBuffers().

4818 {
4819  /*
4820  * -1 indicates a request for auto-tune.
4821  */
4822  if (*newval == -1)
4823  {
4824  /*
4825  * If we haven't yet changed the boot_val default of -1, just let it
4826  * be. We'll fix it when XLOGShmemSize is called.
4827  */
4828  if (XLOGbuffers == -1)
4829  return true;
4830 
4831  /* Otherwise, substitute the auto-tune value */
4833  }
4834 
4835  /*
4836  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
4837  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
4838  * the case, we just silently treat such values as a request for the
4839  * minimum. (We could throw an error instead, but that doesn't seem very
4840  * helpful.)
4841  */
4842  if (*newval < 4)
4843  *newval = 4;
4844 
4845  return true;
4846 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:4801
#define newval
int XLOGbuffers
Definition: xlog.c:92

◆ CheckForStandbyTrigger()

static bool CheckForStandbyTrigger ( void  )
static

Definition at line 12196 of file xlog.c.

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

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

12197 {
12198  struct stat stat_buf;
12199  static bool triggered = false;
12200 
12201  if (triggered)
12202  return true;
12203 
12204  if (IsPromoteTriggered())
12205  {
12206  /*
12207  * In 9.1 and 9.2 the postmaster unlinked the promote file inside the
12208  * signal handler. It now leaves the file in place and lets the
12209  * Startup process do the unlink. This allows Startup to know whether
12210  * it should create a full checkpoint before starting up (fallback
12211  * mode). Fast promotion takes precedence.
12212  */
12213  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12214  {
12215  unlink(PROMOTE_SIGNAL_FILE);
12217  fast_promote = true;
12218  }
12219  else if (stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
12220  {
12222  fast_promote = false;
12223  }
12224 
12225  ereport(LOG, (errmsg("received promote request")));
12226 
12228  triggered = true;
12229  return true;
12230  }
12231 
12232  if (TriggerFile == NULL)
12233  return false;
12234 
12235  if (stat(TriggerFile, &stat_buf) == 0)
12236  {
12237  ereport(LOG,
12238  (errmsg("trigger file found: %s", TriggerFile)));
12239  unlink(TriggerFile);
12240  triggered = true;
12241  fast_promote = true;
12242  return true;
12243  }
12244  else if (errno != ENOENT)
12245  ereport(ERROR,
12247  errmsg("could not stat trigger file \"%s\": %m",
12248  TriggerFile)));
12249 
12250  return false;
12251 }
void ResetPromoteTriggered(void)
Definition: startup.c:253
#define FALLBACK_PROMOTE_SIGNAL_FILE
Definition: xlog.c:85
#define LOG
Definition: elog.h:26
static char * TriggerFile
Definition: xlog.c:276
#define ERROR
Definition: elog.h:43
struct stat stat_buf
Definition: pg_standby.c:103
#define PROMOTE_SIGNAL_FILE
Definition: xlog.c:84
int errcode_for_file_access(void)
Definition: elog.c:598
bool IsPromoteTriggered(void)
Definition: startup.c:247
#define ereport(elevel, rest)
Definition: elog.h:122
#define stat(a, b)
Definition: win32_port.h:266
int errmsg(const char *fmt,...)
Definition: elog.c:797
static bool fast_promote
Definition: xlog.c:282

◆ CheckPointGuts()

static void CheckPointGuts ( XLogRecPtr  checkPointRedo,
int  flags 
)
static

Definition at line 9063 of file xlog.c.

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

Referenced by CreateCheckPoint(), and CreateRestartPoint().

9064 {
9065  CheckPointCLOG();
9074  CheckPointBuffers(flags); /* performs all required fsyncs */
9076  /* We deliberately delay 2PC checkpointing as long as possible */
9077  CheckPointTwoPhase(checkPointRedo);
9078 }
void CheckPointBuffers(int flags)
Definition: bufmgr.c:2574
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1202
void CheckPointReplicationOrigin(void)
Definition: origin.c:545
void CheckPointSnapBuild(void)
Definition: snapbuild.c:1861
void CheckPointCLOG(void)
Definition: clog.c:842
void CheckPointMultiXact(void)
Definition: multixact.c:2140
void CheckPointCommitTs(void)
Definition: commit_ts.c:761
void CheckPointSUBTRANS(void)
Definition: subtrans.c:300
void CheckPointRelationMap(void)
Definition: relmapper.c:524
void CheckPointPredicate(void)
Definition: predicate.c:997
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1722
void CheckPointReplicationSlots(void)
Definition: slot.c:1062

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 12268 of file xlog.c.

References FALLBACK_PROMOTE_SIGNAL_FILE, PROMOTE_SIGNAL_FILE, and stat.

Referenced by sigusr1_handler().

12269 {
12270  struct stat stat_buf;
12271 
12272  if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 ||
12274  return true;
12275 
12276  return false;
12277 }
#define FALLBACK_PROMOTE_SIGNAL_FILE
Definition: xlog.c:85
struct stat stat_buf
Definition: pg_standby.c:103
#define PROMOTE_SIGNAL_FILE
Definition: xlog.c:84
#define stat(a, b)
Definition: win32_port.h:266

◆ CheckRecoveryConsistency()

static void CheckRecoveryConsistency ( void  )
static

Definition at line 7850 of file xlog.c.

References ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, DEBUG1, elog, ereport, errmsg(), 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().

7851 {
7852  XLogRecPtr lastReplayedEndRecPtr;
7853 
7854  /*
7855  * During crash recovery, we don't reach a consistent state until we've
7856  * replayed all the WAL.
7857  */
7859  return;
7860 
7861  /*
7862  * assume that we are called in the startup process, and hence don't need
7863  * a lock to read lastReplayedEndRecPtr
7864  */
7865  lastReplayedEndRecPtr = XLogCtl->lastReplayedEndRecPtr;
7866 
7867  /*
7868  * Have we reached the point where our base backup was completed?
7869  */
7871  ControlFile->backupEndPoint <= lastReplayedEndRecPtr)
7872  {
7873  /*
7874  * We have reached the end of base backup, as indicated by pg_control.
7875  * The data on disk is now consistent. Reset backupStartPoint and
7876  * backupEndPoint, and update minRecoveryPoint to make sure we don't
7877  * allow starting up at an earlier point even if recovery is stopped
7878  * and restarted soon after this.
7879  */
7880  elog(DEBUG1, "end of backup reached");
7881 
7882  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7883 
7884  if (ControlFile->minRecoveryPoint < lastReplayedEndRecPtr)
7885  ControlFile->minRecoveryPoint = lastReplayedEndRecPtr;
7886 
7889  ControlFile->backupEndRequired = false;
7891 
7892  LWLockRelease(ControlFileLock);
7893  }
7894 
7895  /*
7896  * Have we passed our safe starting point? Note that minRecoveryPoint is
7897  * known to be incorrectly set if ControlFile->backupEndRequired, until
7898  * the XLOG_BACKUP_END arrives to advise us of the correct
7899  * minRecoveryPoint. All we know prior to that is that we're not
7900  * consistent yet.
7901  */
7903  minRecoveryPoint <= lastReplayedEndRecPtr &&
7905  {
7906  /*
7907  * Check to see if the XLOG sequence contained any unresolved
7908  * references to uninitialized pages.
7909  */
7911 
7912  reachedConsistency = true;
7913  ereport(LOG,
7914  (errmsg("consistent recovery state reached at %X/%X",
7915  (uint32) (lastReplayedEndRecPtr >> 32),
7916  (uint32) lastReplayedEndRecPtr)));
7917  }
7918 
7919  /*
7920  * Have we got a valid starting snapshot that will allow queries to be
7921  * run? If so, we can tell postmaster that the database is consistent now,
7922  * enabling connections.
7923  */
7928  {
7932 
7933  LocalHotStandbyActive = true;
7934 
7936  }
7937 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
void XLogCheckInvalidPages(void)
Definition: xlogutils.c:220
bool SharedHotStandbyActive
Definition: xlog.c:649
slock_t info_lck
Definition: xlog.c:704
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool backupEndRequired
Definition: pg_control.h:170
#define SpinLockAcquire(lock)
Definition: spin.h:62
static bool LocalHotStandbyActive
Definition: xlog.c:223
void UpdateControlFile(void)
Definition: xlog.c:4693
bool IsUnderPostmaster
Definition: globals.c:108
unsigned int uint32
Definition: c.h:325
#define ereport(elevel, rest)
Definition: elog.h:122
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static ControlFileData * ControlFile
Definition: xlog.c:715
XLogRecPtr backupEndPoint
Definition: pg_control.h:169
bool reachedConsistency
Definition: xlog.c:834
uint64 XLogRecPtr
Definition: xlogdefs.h:21
static XLogCtlData * XLogCtl
Definition: xlog.c:707
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:113
#define elog
Definition: elog.h:219
HotStandbyState standbyState
Definition: xlog.c:197
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:824
XLogRecPtr lastReplayedEndRecPtr
Definition: xlog.c:683

◆ CheckRequiredParameterValues()

static void CheckRequiredParameterValues ( void  )
static

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

6244 {
6245  /*
6246  * For archive recovery, the WAL must be generated with at least 'replica'
6247  * wal_level.
6248  */
6250  {
6251  ereport(WARNING,
6252  (errmsg("WAL was generated with wal_level=minimal, data may be missing"),
6253  errhint("This happens if you temporarily set wal_level=minimal without taking a new base backup.")));
6254  }
6255 
6256  /*
6257  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
6258  * must have at least as many backend slots as the primary.
6259  */
6261  {
6263  ereport(ERROR,
6264  (errmsg("hot standby is not possible because wal_level was not set to \"replica\" or higher on the master server"),
6265  errhint("Either set wal_level to \"replica\" on the master, or turn off hot_standby here.")));
6266 
6267  /* We ignore autovacuum_max_workers when we make this test. */
6268  RecoveryRequiresIntParameter("max_connections",
6271  RecoveryRequiresIntParameter("max_worker_processes",
6274  RecoveryRequiresIntParameter("max_prepared_transactions",
6277  RecoveryRequiresIntParameter("max_locks_per_transaction",
6280  }
6281 }
bool ArchiveRecoveryRequested
Definition: xlog.c:248
int max_locks_per_xact
Definition: pg_control.h:181
int errhint(const char *fmt,...)
Definition: elog.c:987
int max_prepared_xacts
Definition: pg_control.h:180
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:122
int max_locks_per_xact
Definition: lock.c:54
#define WARNING
Definition: elog.h:40
int MaxConnections
Definition: globals.c:131
static ControlFileData * ControlFile
Definition: xlog.c:715
bool EnableHotStandby
Definition: xlog.c:96
int errmsg(const char *fmt,...)
Definition: elog.c:797
int max_worker_processes
Definition: globals.c:132
#define RecoveryRequiresIntParameter(param_name, currValue, minValue)
Definition: xlog.c:6221

◆ checkTimeLineSwitch()

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

Definition at line 9620 of file xlog.c.

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

Referenced by StartupXLOG().

9621 {
9622  /* Check that the record agrees on what the current (old) timeline is */
9623  if (prevTLI != ThisTimeLineID)
9624  ereport(PANIC,
9625  (errmsg("unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
9626  prevTLI, ThisTimeLineID)));
9627 
9628  /*
9629  * The new timeline better be in the list of timelines we expect to see,
9630  * according to the timeline history. It should also not decrease.
9631  */
9632  if (newTLI < ThisTimeLineID || !tliInHistory(newTLI, expectedTLEs))
9633  ereport(PANIC,
9634  (errmsg("unexpected timeline ID %u (after %u) in checkpoint record",
9635  newTLI, ThisTimeLineID)));
9636 
9637  /*
9638  * If we have not yet reached min recovery point, and we're about to
9639  * switch to a timeline greater than the timeline of the min recovery
9640  * point: trouble. After switching to the new timeline, we could not
9641  * possibly visit the min recovery point on the correct timeline anymore.
9642  * This can happen if there is a newer timeline in the archive that
9643  * branched before the timeline the min recovery point is on, and you
9644  * attempt to do PITR to the new timeline.
9645  */
9647  lsn < minRecoveryPoint &&
9648  newTLI > minRecoveryPointTLI)
9649  ereport(PANIC,
9650  (errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
9651  newTLI,
9652  (uint32) (minRecoveryPoint >> 32),
9655 
9656  /* Looks good */
9657 }
static List * expectedTLEs
Definition: xlog.c:320
#define PANIC
Definition: elog.h:53
unsigned int uint32
Definition: c.h:325
#define ereport(elevel, rest)
Definition: elog.h:122
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:826
TimeLineID ThisTimeLineID
Definition: xlog.c:181
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
Definition: timeline.c:515
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:824

◆ checkXLogConsistency()

static void checkXLogConsistency ( XLogReaderState record)
static

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

1350 {
1351  RmgrId rmid = XLogRecGetRmid(record);
1352  RelFileNode rnode;
1353  ForkNumber forknum;
1354  BlockNumber blkno;
1355  int block_id;
1356 
1357  /* Records with no backup blocks have no need for consistency checks. */
1358  if (!XLogRecHasAnyBlockRefs(record))
1359  return;
1360 
1361  Assert((XLogRecGetInfo(record) & XLR_CHECK_CONSISTENCY) != 0);
1362 
1363  for (block_id = 0; block_id <= record->max_block_id; block_id++)
1364  {
1365  Buffer buf;
1366  Page page;
1367 
1368  if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
1369  {
1370  /*
1371  * WAL record doesn't contain a block reference with the given id.
1372  * Do nothing.
1373  */
1374  continue;
1375  }
1376 
1377  Assert(XLogRecHasBlockImage(record, block_id));
1378 
1379  if (XLogRecBlockImageApply(record, block_id))
1380  {
1381  /*
1382  * WAL record has already applied the page, so bypass the
1383  * consistency check as that would result in comparing the full
1384  * page stored in the record with itself.
1385  */
1386  continue;
1387  }
1388 
1389  /*
1390  * Read the contents from the current buffer and store it in a
1391  * temporary page.
1392  */
1393  buf = XLogReadBufferExtended(rnode, forknum, blkno,
1395  if (!BufferIsValid(buf))
1396  continue;
1397 
1399  page = BufferGetPage(buf);
1400 
1401  /*
1402  * Take a copy of the local page where WAL has been applied to have a
1403  * comparison base before masking it...
1404  */
1405  memcpy(replay_image_masked, page, BLCKSZ);
1406 
1407  /* No need for this page anymore now that a copy is in. */
1408  UnlockReleaseBuffer(buf);
1409 
1410  /*
1411  * If the block LSN is already ahead of this WAL record, we can't
1412  * expect contents to match. This can happen if recovery is
1413  * restarted.
1414  */
1415  if (PageGetLSN(replay_image_masked) > record->EndRecPtr)
1416  continue;
1417 
1418  /*
1419  * Read the contents from the backup copy, stored in WAL record and
1420  * store it in a temporary page. There is no need to allocate a new
1421  * page here, a local buffer is fine to hold its contents and a mask
1422  * can be directly applied on it.
1423  */
1424  if (!RestoreBlockImage(record, block_id, master_image_masked))
1425  elog(ERROR, "failed to restore block image");
1426 
1427  /*
1428  * If masking function is defined, mask both the master and replay
1429  * images
1430  */
1431  if (RmgrTable[rmid].rm_mask != NULL)
1432  {
1433  RmgrTable[rmid].rm_mask(replay_image_masked, blkno);
1434  RmgrTable[rmid].rm_mask(master_image_masked, blkno);
1435  }
1436 
1437  /* Time to compare the master and replay images. */
1438  if (memcmp(replay_image_masked, master_image_masked, BLCKSZ) != 0)
1439  {
1440  elog(FATAL,
1441  "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
1442  rnode.spcNode, rnode.dbNode, rnode.relNode,
1443  forknum, blkno);
1444  }
1445  }
1446 }
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:235
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:89
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:80
XLogRecPtr EndRecPtr
Definition: xlogreader.h:120
static char * replay_image_masked
Definition: xlog.c:255
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#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:160
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:226
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:1358
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint8 RmgrId
Definition: rmgr.h:11
#define Assert(condition)
Definition: c.h:699
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:1411
#define PageGetLSN(page)
Definition: bufpage.h:362
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:232
#define elog
Definition: elog.h:219
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:237
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:227
static char * master_image_masked
Definition: xlog.c:256

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3794 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 perform_base_backup(), and XLogRead().

3795 {
3796  int save_errno = errno;
3797  XLogSegNo lastRemovedSegNo;
3798 
3800  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3802 
3803  if (segno <= lastRemovedSegNo)
3804  {
3805  char filename[MAXFNAMELEN];
3806 
3807  XLogFileName(filename, tli, segno, wal_segment_size);
3808  errno = save_errno;
3809  ereport(ERROR,
3811  errmsg("requested WAL segment %s has already been removed",
3812  filename)));
3813  }
3814  errno = save_errno;
3815 }
int wal_segment_size
Definition: xlog.c:113
slock_t info_lck
Definition: xlog.c:704
XLogSegNo lastRemovedSegNo
Definition: xlog.c:587
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
uint64 XLogSegNo
Definition: xlogdefs.h:34
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
#define MAXFNAMELEN
#define SpinLockRelease(lock)
Definition: spin.h:64
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
static XLogCtlData * XLogCtl
Definition: xlog.c:707
static char * filename
Definition: pg_dumpall.c:87
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

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

4123 {
4124  DIR *xldir;
4125  struct dirent *xlde;
4126  char path[MAXPGPATH + sizeof(XLOGDIR)];
4127 
4128  xldir = AllocateDir(XLOGDIR);
4129 
4130  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
4131  {
4132  if (IsBackupHistoryFileName(xlde->d_name))
4133  {
4134  if (XLogArchiveCheckDone(xlde->d_name))
4135  {
4136  elog(DEBUG2, "removing WAL backup history file \"%s\"",
4137  xlde->d_name);
4138  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
4139  unlink(path);
4140  XLogArchiveCleanup(xlde->d_name);
4141  }
4142  }
4143  }
4144 
4145  FreeDir(xldir);
4146 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:752
Definition: dirent.c:25
bool XLogArchiveCheckDone(const char *xlog)
Definition: xlogarchive.c:619
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2590
#define IsBackupHistoryFileName(fname)
#define XLOGDIR
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2656
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2708

◆ CopyXLogRecordToWAL()

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

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

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

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 8587 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::ckptXid, XLogCtlData::ckptXidEpoch, 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::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, VariableCacheData::nextOid, CheckPoint::nextXid, VariableCacheData::nextXid, CheckPoint::nextXidEpoch, 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, smgrpostckpt(), smgrpreckpt(), SpinLockAcquire, SpinLockRelease, START_CRIT_SECTION, ControlFileData::state, 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().

8588 {
8589  bool shutdown;
8590  CheckPoint checkPoint;
8591  XLogRecPtr recptr;
8593  uint32 freespace;
8594  XLogRecPtr PriorRedoPtr;
8595  XLogRecPtr curInsert;
8596  XLogRecPtr last_important_lsn;
8597  VirtualTransactionId *vxids;
8598  int nvxids;
8599 
8600  /*
8601  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
8602  * issued at a different time.
8603  */
8605  shutdown = true;
8606  else
8607  shutdown = false;
8608 
8609  /* sanity check */
8610  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
8611  elog(ERROR, "can't create a checkpoint during recovery");
8612 
8613  /*
8614  * Initialize InitXLogInsert working areas before entering the critical
8615  * section. Normally, this is done by the first call to
8616  * RecoveryInProgress() or LocalSetXLogInsertAllowed(), but when creating
8617  * an end-of-recovery checkpoint, the LocalSetXLogInsertAllowed call is
8618  * done below in a critical section, and InitXLogInsert cannot be called
8619  * in a critical section.
8620  */
8621  InitXLogInsert();
8622 
8623  /*
8624  * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
8625  * (This is just pro forma, since in the present system structure there is
8626  * only one process that is allowed to issue checkpoints at any given
8627  * time.)
8628  */
8629  LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
8630 
8631  /*
8632  * Prepare to accumulate statistics.
8633  *
8634  * Note: because it is possible for log_checkpoints to change while a
8635  * checkpoint proceeds, we always accumulate stats, even if
8636  * log_checkpoints is currently off.
8637  */
8638  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
8640 
8641  /*
8642  * Use a critical section to force system panic if we have trouble.
8643  */
8645 
8646  if (shutdown)
8647  {
8648  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8650  ControlFile->time = (pg_time_t) time(NULL);
8652  LWLockRelease(ControlFileLock);
8653  }
8654 
8655  /*
8656  * Let smgr prepare for checkpoint; this has to happen before we determine
8657  * the REDO pointer. Note that smgr must not do anything that'd have to
8658  * be undone if we decide no checkpoint is needed.
8659  */
8660  smgrpreckpt();
8661 
8662  /* Begin filling in the checkpoint WAL record */
8663  MemSet(&checkPoint, 0, sizeof(checkPoint));
8664  checkPoint.time = (pg_time_t) time(NULL);
8665 
8666  /*
8667  * For Hot Standby, derive the oldestActiveXid before we fix the redo
8668  * pointer. This allows us to begin accumulating changes to assemble our
8669  * starting snapshot of locks and transactions.
8670  */
8671  if (!shutdown && XLogStandbyInfoActive())
8673  else
8675 
8676  /*
8677  * Get location of last important record before acquiring insert locks (as
8678  * GetLastImportantRecPtr() also locks WAL locks).
8679  */
8680  last_important_lsn = GetLastImportantRecPtr();
8681 
8682  /*
8683  * We must block concurrent insertions while examining insert state to
8684  * determine the checkpoint REDO pointer.
8685  */
8687  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
8688 
8689  /*
8690  * If this isn't a shutdown or forced checkpoint, and if there has been no
8691  * WAL activity requiring a checkpoint, skip it. The idea here is to
8692  * avoid inserting duplicate checkpoints when the system is idle.
8693  */
8694  if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
8695  CHECKPOINT_FORCE)) == 0)
8696  {
8697  if (last_important_lsn == ControlFile->checkPoint)
8698  {
8700  LWLockRelease(CheckpointLock);
8701  END_CRIT_SECTION();
8702  ereport(DEBUG1,
8703  (errmsg("checkpoint skipped because system is idle")));
8704  return;
8705  }
8706  }
8707 
8708  /*
8709  * An end-of-recovery checkpoint is created before anyone is allowed to
8710  * write WAL. To allow us to write the checkpoint record, temporarily
8711  * enable XLogInsertAllowed. (This also ensures ThisTimeLineID is
8712  * initialized, which we need here and in AdvanceXLInsertBuffer.)
8713  */
8714  if (flags & CHECKPOINT_END_OF_RECOVERY)
8716 
8717  checkPoint.ThisTimeLineID = ThisTimeLineID;
8718  if (flags & CHECKPOINT_END_OF_RECOVERY)
8719  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
8720  else
8721  checkPoint.PrevTimeLineID = ThisTimeLineID;
8722 
8723  checkPoint.fullPageWrites = Insert->fullPageWrites;
8724 
8725  /*
8726  * Compute new REDO record ptr = location of next XLOG record.
8727  *
8728  * NB: this is NOT necessarily where the checkpoint record itself will be,
8729  * since other backends may insert more XLOG records while we're off doing
8730  * the buffer flush work. Those XLOG records are logically after the
8731  * checkpoint, even though physically before it. Got that?
8732  */
8733  freespace = INSERT_FREESPACE(curInsert);
8734  if (freespace == 0)
8735  {
8736  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
8737  curInsert += SizeOfXLogLongPHD;
8738  else
8739  curInsert += SizeOfXLogShortPHD;
8740  }
8741  checkPoint.redo = curInsert;
8742 
8743  /*
8744  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
8745  * must be done while holding all the insertion locks.
8746  *
8747  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
8748  * pointing past where it really needs to point. This is okay; the only
8749  * consequence is that XLogInsert might back up whole buffers that it
8750  * didn't really need to. We can't postpone advancing RedoRecPtr because
8751  * XLogInserts that happen while we are dumping buffers must assume that
8752  * their buffer changes are not included in the checkpoint.
8753  */
8754  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
8755 
8756  /*
8757  * Now we can release the WAL insertion locks, allowing other xacts to
8758  * proceed while we are flushing disk buffers.
8759  */
8761 
8762  /* Update the info_lck-protected copy of RedoRecPtr as well */
8764  XLogCtl->RedoRecPtr = checkPoint.redo;
8766 
8767  /*
8768  * If enabled, log checkpoint start. We postpone this until now so as not
8769  * to log anything if we decided to skip the checkpoint.
8770  */
8771  if (log_checkpoints)
8772  LogCheckpointStart(flags, false);
8773 
8774  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
8775 
8776  /*
8777  * Get the other info we need for the checkpoint record.
8778  *
8779  * We don't need to save oldestClogXid in the checkpoint, it only matters
8780  * for the short period in which clog is being truncated, and if we crash
8781  * during that we'll redo the clog truncation and fix up oldestClogXid
8782  * there.
8783  */
8784  LWLockAcquire(XidGenLock, LW_SHARED);
8785  checkPoint.nextXid = ShmemVariableCache->nextXid;
8786  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
8788  LWLockRelease(XidGenLock);
8789 
8790  LWLockAcquire(CommitTsLock, LW_SHARED);
8793  LWLockRelease(CommitTsLock);
8794 
8795  /* Increase XID epoch if we've wrapped around since last checkpoint */
8797  if (checkPoint.nextXid < ControlFile->checkPointCopy.nextXid)
8798  checkPoint.nextXidEpoch++;
8799 
8800  LWLockAcquire(OidGenLock, LW_SHARED);
8801  checkPoint.nextOid = ShmemVariableCache->nextOid;
8802  if (!shutdown)
8803  checkPoint.nextOid += ShmemVariableCache->oidCount;
8804  LWLockRelease(OidGenLock);
8805 
8806  MultiXactGetCheckptMulti(shutdown,
8807  &checkPoint.nextMulti,
8808  &checkPoint.nextMultiOffset,
8809  &checkPoint.oldestMulti,
8810  &checkPoint.oldestMultiDB);
8811 
8812  /*
8813  * Having constructed the checkpoint record, ensure all shmem disk buffers
8814  * and commit-log buffers are flushed to disk.
8815  *
8816  * This I/O could fail for various reasons. If so, we will fail to
8817  * complete the checkpoint, but there is no reason to force a system
8818  * panic. Accordingly, exit critical section while doing it.
8819  */
8820  END_CRIT_SECTION();
8821 
8822  /*
8823  * In some cases there are groups of actions that must all occur on one
8824  * side or the other of a checkpoint record. Before flushing the
8825  * checkpoint record we must explicitly wait for any backend currently
8826  * performing those groups of actions.
8827  *
8828  * One example is end of transaction, so we must wait for any transactions
8829  * that are currently in commit critical sections. If an xact inserted
8830  * its commit record into XLOG just before the REDO point, then a crash
8831  * restart from the REDO point would not replay that record, which means
8832  * that our flushing had better include the xact's update of pg_xact. So
8833  * we wait till he's out of his commit critical section before proceeding.
8834  * See notes in RecordTransactionCommit().
8835  *
8836  * Because we've already released the insertion locks, this test is a bit
8837  * fuzzy: it is possible that we will wait for xacts we didn't really need
8838  * to wait for. But the delay should be short and it seems better to make
8839  * checkpoint take a bit longer than to hold off insertions longer than
8840  * necessary. (In fact, the whole reason we have this issue is that xact.c
8841  * does commit record XLOG insertion and clog update as two separate steps
8842  * protected by different locks, but again that seems best on grounds of
8843  * minimizing lock contention.)
8844  *
8845  * A transaction that has not yet set delayChkpt when we look cannot be at
8846  * risk, since he's not inserted his commit record yet; and one that's
8847  * already cleared it is not at risk either, since he's done fixing clog
8848  * and we will correctly flush the update below. So we cannot miss any
8849  * xacts we need to wait for.
8850  */
8851  vxids = GetVirtualXIDsDelayingChkpt(&nvxids);
8852  if (nvxids > 0)
8853  {
8854  do
8855  {
8856  pg_usleep(10000L); /* wait for 10 msec */
8857  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids));
8858  }
8859  pfree(vxids);
8860 
8861  CheckPointGuts(checkPoint.redo, flags);
8862 
8863  /*
8864  * Take a snapshot of running transactions and write this to WAL. This
8865  * allows us to reconstruct the state of running transactions during
8866  * archive recovery, if required. Skip, if this info disabled.
8867  *
8868  * If we are shutting down, or Startup process is completing crash
8869  * recovery we don't need to write running xact data.
8870  */
8871  if (!shutdown && XLogStandbyInfoActive())
8873 
8875 
8876  /*
8877  * Now insert the checkpoint record into XLOG.
8878  */
8879  XLogBeginInsert();
8880  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
8881  recptr = XLogInsert(RM_XLOG_ID,
8882  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
8884 
8885  XLogFlush(recptr);
8886 
8887  /*
8888  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
8889  * overwritten at next startup. No-one should even try, this just allows
8890  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
8891  * to just temporarily disable writing until the system has exited
8892  * recovery.
8893  */
8894  if (shutdown)
8895  {
8896  if (flags & CHECKPOINT_END_OF_RECOVERY)
8897  LocalXLogInsertAllowed = -1; /* return to "check" state */
8898  else
8899  LocalXLogInsertAllowed = 0; /* never again write WAL */
8900  }
8901 
8902  /*
8903  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
8904  * = end of actual checkpoint record.
8905  */
8906  if (shutdown && checkPoint.redo != ProcLastRecPtr)
8907  ereport(PANIC,
8908  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
8909 
8910  /*
8911  * Remember the prior checkpoint's redo ptr for
8912  * UpdateCheckPointDistanceEstimate()
8913  */
8914  PriorRedoPtr = ControlFile->checkPointCopy.redo;
8915 
8916  /*
8917  * Update the control file.
8918  */
8919  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
8920  if (shutdown)
8923  ControlFile->checkPointCopy = checkPoint;
8924  ControlFile->time = (pg_time_t) time(NULL);
8925  /* crash recovery should always recover to the end of WAL */
8928 
8929  /*
8930  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
8931  * unused on non-shutdown checkpoints, but seems useful to store it always
8932  * for debugging purposes.
8933  */
8937 
8939  LWLockRelease(ControlFileLock);
8940 
8941  /* Update shared-memory copy of checkpoint XID/epoch */
8943  XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
8944  XLogCtl->ckptXid = checkPoint.nextXid;
8946 
8947  /*
8948  * We are now done with critical updates; no need for system panic if we
8949  * have trouble while fooling with old log segments.
8950  */
8951  END_CRIT_SECTION();
8952 
8953  /*
8954  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
8955  */
8956  smgrpostckpt();
8957 
8958  /*
8959  * Delete old log files and recycle them
8960  */
8961  if (PriorRedoPtr != InvalidXLogRecPtr)
8962  {
8963  XLogSegNo _logSegNo;
8964 
8965  /* Update the average distance between checkpoints. */
8967 
8968  /* Trim from the last checkpoint, not the last - 1 */
8970  KeepLogSeg(recptr, &_logSegNo);
8971  _logSegNo--;
8972  RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, recptr);
8973  }
8974 
8975  /*
8976  * Make more log segments if needed. (Do this after recycling old log
8977  * segments, since that may supply some of the needed files.)
8978  */
8979  if (!shutdown)
8980  PreallocXlogFiles(recptr);
8981 
8982  /*
8983  * Truncate pg_subtrans if possible. We can throw away all data before
8984  * the oldest XMIN of any running transaction. No future transaction will
8985  * attempt to reference any pg_subtrans entry older than that (see Asserts
8986  * in subtrans.c). During recovery, though, we mustn't do this because
8987  * StartupSUBTRANS hasn't been called yet.
8988  */
8989  if (!RecoveryInProgress())
8991 
8992  /* Real work is done, but log and update stats before releasing lock. */
8993  LogCheckpointEnd(false);
8994 
8995  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
8996  NBuffers,
9000 
9001  LWLockRelease(CheckpointLock);
9002 }
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:8299
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8525
static int LocalXLogInsertAllowed
Definition: xlog.c:235
bool log_checkpoints
Definition: xlog.c:102
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
int64 pg_time_t
Definition: pgtime.h:23
TransactionId ckptXid
Definition: xlog.c:583
static void WALInsertLockRelease(void)
Definition: xlog.c:1671
int wal_segment_size
Definition: xlog.c:113
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:112
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1940
XLogRecPtr unloggedLSN
Definition: xlog.c:590
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:338
TransactionId oldestActiveXid
Definition: pg_control.h:63
void InitXLogInsert(void)
Definition: xloginsert.c:1028
TimestampTz ckpt_start_t
Definition: xlog.h:199
slock_t info_lck
Definition: xlog.c:704
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids)
Definition: procarray.c:2262
MultiXactId oldestMulti
Definition: pg_control.h:49
TimeLineID PrevTimeLineID
Definition: xlog.c:631
TimeLineID PrevTimeLineID
Definition: pg_control.h:39
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int ckpt_segs_recycled
Definition: xlog.h:209
TransactionId oldestXid
Definition: transam.h:119
#define MemSet(start, val, len)
Definition: c.h:908
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
Definition: xlog.c:3862
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2118
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9063
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:577
TransactionId oldestXid
Definition: pg_control.h:47
bool RecoveryInProgress(void)
Definition: xlog.c:7949
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:354
uint32 ckptXidEpoch
Definition: xlog.c:582
TransactionId nextXid
Definition: pg_control.h:43
pg_time_t time
Definition: pg_control.h:51
#define PANIC
Definition: elog.h:53
bool fullPageWrites
Definition: xlog.c:552
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2783
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#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:4693
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
void pfree(void *pointer)
Definition: mcxt.c:1031
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:891
#define ERROR
Definition: elog.h:43
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8440
TransactionId nextXid
Definition: transam.h:117
uint32 nextXidEpoch
Definition: pg_control.h:42
static XLogRecPtr RedoRecPtr
Definition: xlog.c:352
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
XLogRecPtr unloggedLSN
Definition: pg_control.h:133
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3761
uint64 XLogSegNo
Definition: xlogdefs.h:34
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:177
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
uint64 CurrBytePos
Definition: xlog.c:528
unsigned int uint32
Definition: c.h:325
XLogRecPtr RedoRecPtr
Definition: xlog.c:581
int ckpt_segs_removed
Definition: xlog.h:208
#define CHECKPOINT_FORCE
Definition: xlog.h:180
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:721
#define ereport(elevel, rest)
Definition: elog.h:122
TransactionId oldestCommitTsXid
Definition: transam.h:129
static void Insert(File file)
Definition: fd.c:1062
int ckpt_bufs_written
Definition: xlog.h:205
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8075
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:9386
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
Oid oldestMultiDB
Definition: pg_control.h:50
#define XLogStandbyInfoActive()
Definition: xlog.h:160
static ControlFileData * ControlFile
Definition: xlog.c:715
TimeLineID ThisTimeLineID
Definition: xlog.c:181
Oid nextOid
Definition: pg_control.h:44
bool fullPageWrites
Definition: pg_control.h:41
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1312
void smgrpreckpt(void)
Definition: smgr.c:744
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXidDB
Definition: pg_control.h:48
TransactionId newestCommitTsXid
Definition: transam.h:130
CheckpointStatsData CheckpointStats
Definition: xlog.c:175
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:55
MultiXactId nextMulti
Definition: pg_control.h:45
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1642
static XLogCtlData * XLogCtl
Definition: xlog.c:707
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int ckpt_segs_added
Definition: xlog.h:207
slock_t ulsn_lck
Definition: xlog.c:591
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
int errmsg(const char *fmt,...)
Definition: elog.c:797
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2100
int NBuffers
Definition: globals.c:130
#define elog
Definition: elog.h:219
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
Definition: procarray.c:2307
void XLogBeginInsert(void)
Definition: xloginsert.c:120
XLogRecPtr RedoRecPtr
Definition: xlog.c:550
void smgrpostckpt(void)
Definition: smgr.c:774
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:36
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8422
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:176
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:72
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ CreateEndOfRecoveryRecord()

static void CreateEndOfRecoveryRecord ( void  )
static

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

9015 {
9016  xl_end_of_recovery xlrec;
9017  XLogRecPtr recptr;
9018 
9019  /* sanity check */
9020  if (!RecoveryInProgress())
9021  elog(ERROR, "can only be used to end recovery");
9022 
9023  xlrec.end_time = GetCurrentTimestamp();
9024 
9029 
9031 
9033 
9034  XLogBeginInsert();
9035  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
9036  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
9037 
9038  XLogFlush(recptr);
9039 
9040  /*
9041  * Update the control file so that crash recovery can follow the timeline
9042  * changes to this point.
9043  */
9044  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9045  ControlFile->time = (pg_time_t) time(NULL);
9046  ControlFile->minRecoveryPoint = recptr;
9049  LWLockRelease(ControlFileLock);
9050 
9051  END_CRIT_SECTION();
9052 
9053  LocalXLogInsertAllowed = -1; /* return to "check" state */
9054 }
static int LocalXLogInsertAllowed
Definition: xlog.c:235
int64 pg_time_t
Definition: pgtime.h:23
static void WALInsertLockRelease(void)
Definition: xlog.c:1671
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimeLineID PrevTimeLineID
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
TimeLineID PrevTimeLineID
Definition: xlog.c:631
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
bool RecoveryInProgress(void)
Definition: xlog.c:7949
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2783
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
void UpdateControlFile(void)
Definition: xlog.c:4693
#define ERROR
Definition: elog.h:43
static void LocalSetXLogInsertAllowed(void)
Definition: xlog.c:8075
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:715
TimeLineID ThisTimeLineID
Definition: xlog.c:181
TimestampTz end_time
uint64 XLogRecPtr
Definition: xlogdefs.h:21
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1642
static XLogCtlData * XLogCtl
Definition: xlog.c:707
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
TimeLineID ThisTimeLineID
#define elog
Definition: elog.h:219
void XLogBeginInsert(void)
Definition: xloginsert.c:120
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 9133 of file xlog.c.

References XLogCtlData::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().

9134 {
9135  XLogRecPtr lastCheckPointRecPtr;
9136  XLogRecPtr lastCheckPointEndPtr;
9137  CheckPoint lastCheckPoint;
9138  XLogRecPtr PriorRedoPtr;
9139  TimestampTz xtime;
9140 
9141  /*
9142  * Acquire CheckpointLock to ensure only one restartpoint or checkpoint
9143  * happens at a time.
9144  */
9145  LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
9146 
9147  /* Get a local copy of the last safe checkpoint record. */
9149  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
9150  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
9151  lastCheckPoint = XLogCtl->lastCheckPoint;
9153 
9154  /*
9155  * Check that we're still in recovery mode. It's ok if we exit recovery
9156  * mode after this check, the restart point is valid anyway.
9157  */
9158  if (!RecoveryInProgress())
9159  {
9160  ereport(DEBUG2,
9161  (errmsg("skipping restartpoint, recovery has already ended")));
9162  LWLockRelease(CheckpointLock);
9163  return false;
9164  }
9165 
9166  /*
9167  * If the last checkpoint record we've replayed is already our last
9168  * restartpoint, we can't perform a new restart point. We still update
9169  * minRecoveryPoint in that case, so that if this is a shutdown restart
9170  * point, we won't start up earlier than before. That's not strictly
9171  * necessary, but when hot standby is enabled, it would be rather weird if
9172  * the database opened up for read-only connections at a point-in-time
9173  * before the last shutdown. Such time travel is still possible in case of
9174  * immediate shutdown, though.
9175  *
9176  * We don't explicitly advance minRecoveryPoint when we do create a
9177  * restartpoint. It's assumed that flushing the buffers will do that as a
9178  * side-effect.
9179  */
9180  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
9181  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
9182  {
9183  ereport(DEBUG2,
9184  (errmsg("skipping restartpoint, already performed at %X/%X",
9185  (uint32) (lastCheckPoint.redo >> 32),
9186  (uint32) lastCheckPoint.redo)));
9187 
9189  if (flags & CHECKPOINT_IS_SHUTDOWN)
9190  {
9191  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9193  ControlFile->time = (pg_time_t) time(NULL);
9195  LWLockRelease(ControlFileLock);
9196  }
9197  LWLockRelease(CheckpointLock);
9198  return false;
9199  }
9200 
9201  /*
9202  * Update the shared RedoRecPtr so that the startup process can calculate
9203  * the number of segments replayed since last restartpoint, and request a
9204  * restartpoint if it exceeds CheckPointSegments.
9205  *
9206  * Like in CreateCheckPoint(), hold off insertions to update it, although
9207  * during recovery this is just pro forma, because no WAL insertions are
9208  * happening.
9209  */
9211  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
9213 
9214  /* Also update the info_lck-protected copy */
9216  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
9218 
9219  /*
9220  * Prepare to accumulate statistics.
9221  *
9222  * Note: because it is possible for log_checkpoints to change while a
9223  * checkpoint proceeds, we always accumulate stats, even if
9224  * log_checkpoints is currently off.
9225  */
9226  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
9228 
9229  if (log_checkpoints)
9230  LogCheckpointStart(flags, true);
9231 
9232  CheckPointGuts(lastCheckPoint.redo, flags);
9233 
9234  /*
9235  * Remember the prior checkpoint's redo ptr for
9236  * UpdateCheckPointDistanceEstimate()
9237  */
9238  PriorRedoPtr = ControlFile->checkPointCopy.redo;
9239 
9240  /*
9241  * Update pg_control, using current time. Check that it still shows
9242  * IN_ARCHIVE_RECOVERY state and an older checkpoint, else do nothing;
9243  * this is a quick hack to make sure nothing really bad happens if somehow
9244  * we get here after the end-of-recovery checkpoint.
9245  */
9246  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9248  ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
9249  {
9250  ControlFile->checkPoint = lastCheckPointRecPtr;
9251  ControlFile->checkPointCopy = lastCheckPoint;
9252  ControlFile->time = (pg_time_t) time(NULL);
9253 
9254  /*
9255  * Ensure minRecoveryPoint is past the checkpoint record. Normally,
9256  * this will have happened already while writing out dirty buffers,
9257  * but not necessarily - e.g. because no buffers were dirtied. We do
9258  * this because a non-exclusive base backup uses minRecoveryPoint to
9259  * determine which WAL files must be included in the backup, and the
9260  * file (or files) containing the checkpoint record must be included,
9261  * at a minimum. Note that for an ordinary restart of recovery there's
9262  * no value in having the minimum recovery point any earlier than this
9263  * anyway, because redo will begin just after the checkpoint record.
9264  */
9265  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
9266  {
9267  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
9269 
9270  /* update local copy */
9273  }
9274  if (flags & CHECKPOINT_IS_SHUTDOWN)
9277  }
9278  LWLockRelease(ControlFileLock);
9279 
9280  /*
9281  * Delete old log files (those no longer needed even for previous
9282  * checkpoint/restartpoint) to prevent the disk holding the xlog from
9283  * growing full.
9284  */
9285  if (PriorRedoPtr != InvalidXLogRecPtr)
9286  {
9287  XLogRecPtr receivePtr;
9288  XLogRecPtr replayPtr;
9289  TimeLineID replayTLI;
9290  XLogRecPtr endptr;
9291  XLogSegNo _logSegNo;
9292 
9293  /* Update the average distance between checkpoints/restartpoints. */
9295 
9296  XLByteToSeg(PriorRedoPtr, _logSegNo, wal_segment_size);
9297 
9298  /*
9299  * Get the current end of xlog replayed or received, whichever is
9300  * later.
9301  */
9302  receivePtr = GetWalRcvWriteRecPtr(NULL, NULL);
9303  replayPtr = GetXLogReplayRecPtr(&replayTLI);
9304  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
9305 
9306  KeepLogSeg(endptr, &_logSegNo);
9307  _logSegNo--;
9308 
9309  /*
9310  * Try to recycle segments on a useful timeline. If we've been
9311  * promoted since the beginning of this restartpoint, use the new
9312  * timeline chosen at end of recovery (RecoveryInProgress() sets
9313  * ThisTimeLineID in that case). If we're still in recovery, use the
9314  * timeline we're currently replaying.
9315  *
9316  * There is no guarantee that the WAL segments will be useful on the
9317  * current timeline; if recovery proceeds to a new timeline right
9318  * after this, the pre-allocated WAL segments on this timeline will
9319  * not be used, and will go wasted until recycled on the next
9320  * restartpoint. We'll live with that.
9321  */
9322  if (RecoveryInProgress())
9323  ThisTimeLineID = replayTLI;
9324 
9325  RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, endptr);
9326 
9327  /*
9328  * Make more log segments if needed. (Do this after recycling old log
9329  * segments, since that may supply some of the needed files.)
9330  */
9331  PreallocXlogFiles(endptr);
9332 
9333  /*
9334  * ThisTimeLineID is normally not set when we're still in recovery.
9335  * However, recycling/preallocating segments above needed
9336  * ThisTimeLineID to determine which timeline to install the segments
9337  * on. Reset it now, to restore the normal state of affairs for
9338  * debugging purposes.
9339  */
9340  if (RecoveryInProgress())
9341  ThisTimeLineID = 0;
9342  }
9343 
9344  /*
9345  * Truncate pg_subtrans if possible. We can throw away all data before
9346  * the oldest XMIN of any running transaction. No future transaction will
9347  * attempt to reference any pg_subtrans entry older than that (see Asserts
9348  * in subtrans.c). When hot standby is disabled, though, we mustn't do
9349  * this because StartupSUBTRANS hasn't been called yet.
9350  */
9351  if (EnableHotStandby)
9353 
9354  /* Real work is done, but log and update before releasing lock. */
9355  LogCheckpointEnd(true);
9356 
9357  xtime = GetLatestXTime();
9359  (errmsg("recovery restart point at %X/%X",
9360  (uint32) (lastCheckPoint.redo >> 32), (uint32) lastCheckPoint.redo),
9361  xtime ? errdetail("Last completed transaction was at log time %s.",
9362  timestamptz_to_str(xtime)) : 0));
9363 
9364  LWLockRelease(CheckpointLock);
9365 
9366  /*
9367  * Finally, execute archive_cleanup_command, if any.
9368  */
9371  "archive_cleanup_command",
9372  false);
9373 
9374  return true;
9375 }
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:8525
bool log_checkpoints
Definition: xlog.c:102
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal)
Definition: xlogarchive.c:330
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
uint32 TimeLineID
Definition: xlogdefs.h:45
int64 pg_time_t
Definition: pgtime.h:23
XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
static void WALInsertLockRelease(void)
Definition: xlog.c:1671
int wal_segment_size
Definition: xlog.c:113
pg_time_t time
Definition: pg_control.h:128
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2708
TimestampTz ckpt_start_t
Definition: xlog.h:199
slock_t info_lck
Definition: xlog.c:704
#define MemSet(start, val, len)
Definition: c.h:908
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
Definition: xlog.c:3862
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:9063
TimestampTz GetLatestXTime(void)
Definition: xlog.c:6159
CheckPoint checkPointCopy
Definition: pg_control.h:131
XLogCtlInsert Insert
Definition: xlog.c:577
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:7949
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:354
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:673
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SpinLockAcquire(lock)
Definition: spin.h:62
void UpdateControlFile(void)
Definition: xlog.c:4693
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:8440
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
Definition: xlog.c:11194
#define DEBUG2
Definition: elog.h:24
static XLogRecPtr RedoRecPtr
Definition: xlog.c:352
static void PreallocXlogFiles(XLogRecPtr endptr)
Definition: xlog.c:3761
uint64 XLogSegNo
Definition: xlogdefs.h:34
int errdetail(const char *fmt,...)
Definition: elog.c:873
unsigned int uint32
Definition: c.h:325
XLogRecPtr RedoRecPtr
Definition: xlog.c:581
#define ereport(elevel, rest)
Definition: elog.h:122
CheckPoint lastCheckPoint
Definition: xlog.c:675
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define SpinLockRelease(lock)
Definition: spin.h:64
static TimeLineID minRecoveryPointTLI
Definition: xlog.c:826
#define PROCARRAY_FLAGS_DEFAULT
Definition: procarray.h:50
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:9386
static ControlFileData * ControlFile
Definition: xlog.c:715
TimeLineID ThisTimeLineID
Definition: xlog.c:181
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1312
uint64 XLogRecPtr
Definition: xlogdefs.h:21
CheckpointStatsData CheckpointStats
Definition: xlog.c:175
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1642
static XLogCtlData * XLogCtl
Definition: xlog.c:707
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
char archiveCleanupCommand[MAXPGPATH]
Definition: xlog.c:637
bool EnableHotStandby
Definition: xlog.c:96
TimeLineID ThisTimeLineID
Definition: pg_control.h:38
int errmsg(const char *fmt,...)
Definition: elog.c:797
XLogRecPtr RedoRecPtr
Definition: xlog.c:550
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:674
XLogRecPtr checkPoint
Definition: pg_control.h:129
XLogRecPtr redo
Definition: pg_control.h:36
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:8422
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:176
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
static XLogRecPtr minRecoveryPoint
Definition: xlog.c:824
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1710
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ DataChecksumsEnabled()

bool DataChecksumsEnabled ( void  )

Definition at line 4761 of file xlog.c.

References Assert, and ControlFileData::data_checksum_version.

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

4762 {
4763  Assert(ControlFile != NULL);
4764  return (ControlFile->data_checksum_version > 0);
4765 }
uint32 data_checksum_version
Definition: pg_control.h:221
static ControlFileData * ControlFile
Definition: xlog.c:715
#define Assert(condition)
Definition: c.h:699

◆ do_pg_abort_backup()

void do_pg_abort_backup ( void  )

Definition at line 11166 of file xlog.c.

References Assert, EXCLUSIVE_BACKUP_NONE, XLogCtlInsert::exclusiveBackupState, XLogCtlInsert::forcePageWrites, XLogCtlData::Insert, XLogCtlInsert::nonExclusiveBackups, SESSION_BACKUP_NON_EXCLUSIVE, SESSION_BACKUP_NONE, sessionBackupState, WALInsertLockAcquireExclusive(), and WALInsertLockRelease().

Referenced by base_backup_cleanup(), and nonexclusive_base_backup_cleanup().

11167 {
11168  /*
11169  * Quick exit if session is not keeping around a non-exclusive backup
11170  * already started.
11171  */
11173  return;
11174 
11179 
11182  {
11183  XLogCtl->Insert.forcePageWrites = false;
11184  }
11186 }
static void WALInsertLockRelease(void)
Definition: xlog.c:1671
static SessionBackupState sessionBackupState
Definition: xlog.c:512
XLogCtlInsert Insert
Definition: xlog.c:577
bool forcePageWrites
Definition: xlog.c:551
int nonExclusiveBackups
Definition: xlog.c:563
ExclusiveBackupState exclusiveBackupState
Definition: xlog.c:562
#define Assert(condition)
Definition: c.h:699
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1642
static XLogCtlData * XLogCtl
Definition: xlog.c:707

◆ 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 10244 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().

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

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

References DEBUG1, LOG, readSource, and XLOG_FROM_PG_WAL.

Referenced by ReadRecord(), and XLogPageRead().

12178 {
12179  static XLogRecPtr lastComplaint = 0;
12180 
12181  if (readSource == XLOG_FROM_PG_WAL && emode == LOG)
12182  {
12183  if (RecPtr == lastComplaint)
12184  emode = DEBUG1;
12185  else
12186  lastComplaint = RecPtr;
12187  }
12188  return emode;
12189 }
#define DEBUG1
Definition: elog.h:25
static XLogSource readSource
Definition: xlog.c:790
#define LOG
Definition: elog.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21

◆ exitArchiveRecovery()

static void exitArchiveRecovery ( TimeLineID  endTLI,
XLogRecPtr  endOfLog 
)
static

Definition at line 5563 of file xlog.c.

References Assert, close, durable_rename(), ereport, errcode_for_file_access(), errmsg(), ERROR, FATAL, fd(), InArchiveRecovery, InvalidXLogRecPtr, LOG, MAXFNAMELEN, MAXPGPATH, readFile, RECOVERY_COMMAND_DONE, RECOVERY_COMMAND_FILE, snprintf(), ThisTimeLineID, UpdateMinRecoveryPoint(), wal_segment_size, XLByteToPrevSeg, XLByteToSeg, XLogArchiveCleanup(), XLOGDIR, XLogFileCopy(), XLogFileInit(), XLogFileName, XLogFileNameP(), and XLogSegmentOffset.

Referenced by StartupXLOG().

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