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

Go to the source code of this file.

Data Structures

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

Macros

#define BootstrapTimeLineID   1
 
#define NUM_XLOGINSERT_LOCKS   8
 
#define INSERT_FREESPACE(endptr)    (((endptr) % XLOG_BLCKSZ == 0) ? 0 : (XLOG_BLCKSZ - (endptr) % XLOG_BLCKSZ))
 
#define NextBufIdx(idx)    (((idx) == XLogCtl->XLogCacheBlck) ? 0 : ((idx) + 1))
 
#define XLogRecPtrToBufIdx(recptr)    (((recptr) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))
 
#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)
 
#define ConvertToXSegs(x, segsize)   XLogMBVarToSegs((x), (segsize))
 
#define RefreshXLogWriteResult(_target)
 

Typedefs

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

Enumerations

enum  WalInsertClass { WALINSERT_NORMAL , WALINSERT_SPECIAL_SWITCH , WALINSERT_SPECIAL_CHECKPOINT }
 

Functions

static void CleanupAfterArchiveRecovery (TimeLineID EndOfLogTLI, XLogRecPtr EndOfLog, TimeLineID newTLI)
 
static void CheckRequiredParameterValues (void)
 
static void XLogReportParameters (void)
 
static int LocalSetXLogInsertAllowed (void)
 
static void CreateEndOfRecoveryRecord (void)
 
static XLogRecPtr CreateOverwriteContrecordRecord (XLogRecPtr aborted_lsn, XLogRecPtr pagePtr, TimeLineID newTLI)
 
static void CheckPointGuts (XLogRecPtr checkPointRedo, int flags)
 
static void KeepLogSeg (XLogRecPtr recptr, XLogSegNo *logSegNo)
 
static XLogRecPtr XLogGetReplicationSlotMinimumLSN (void)
 
static void AdvanceXLInsertBuffer (XLogRecPtr upto, TimeLineID tli, bool opportunistic)
 
static void XLogWrite (XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
 
static bool InstallXLogFileSegment (XLogSegNo *segno, char *tmppath, bool find_free, XLogSegNo max_segno, TimeLineID tli)
 
static void XLogFileClose (void)
 
static void PreallocXlogFiles (XLogRecPtr endptr, TimeLineID tli)
 
static void RemoveTempXlogFiles (void)
 
static void RemoveOldXlogFiles (XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr, TimeLineID insertTLI)
 
static void RemoveXlogFile (const struct dirent *segment_de, XLogSegNo recycleSegNo, XLogSegNo *endlogSegNo, TimeLineID insertTLI)
 
static void UpdateLastRemovedPtr (char *filename)
 
static void ValidateXLOGDirectoryStructure (void)
 
static void CleanupBackupHistory (void)
 
static void UpdateMinRecoveryPoint (XLogRecPtr lsn, bool force)
 
static bool PerformRecoveryXLogAction (void)
 
static void InitControlFile (uint64 sysidentifier, uint32 data_checksum_version)
 
static void WriteControlFile (void)
 
static void ReadControlFile (void)
 
static void UpdateControlFile (void)
 
static char * str_time (pg_time_t tnow)
 
static int get_sync_bit (int method)
 
static void CopyXLogRecordToWAL (int write_len, bool isLogSwitch, XLogRecData *rdata, XLogRecPtr StartPos, XLogRecPtr EndPos, TimeLineID tli)
 
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, TimeLineID tli)
 
static XLogRecPtr XLogBytePosToRecPtr (uint64 bytepos)
 
static XLogRecPtr XLogBytePosToEndRecPtr (uint64 bytepos)
 
static uint64 XLogRecPtrToBytePos (XLogRecPtr ptr)
 
static void WALInsertLockAcquire (void)
 
static void WALInsertLockAcquireExclusive (void)
 
static void WALInsertLockRelease (void)
 
static void WALInsertLockUpdateInsertingAt (XLogRecPtr insertingAt)
 
XLogRecPtr XLogInsertRecord (XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, bool topxid_included)
 
Size WALReadFromBuffers (char *dstbuf, XLogRecPtr startptr, Size count, TimeLineID tli)
 
static void CalculateCheckpointSegments (void)
 
void assign_max_wal_size (int newval, void *extra)
 
void assign_checkpoint_completion_target (double newval, void *extra)
 
bool check_wal_segment_size (int *newval, void **extra, GucSource source)
 
bool check_max_slot_wal_keep_size (int *newval, void **extra, GucSource source)
 
static XLogSegNo XLOGfileslop (XLogRecPtr lastredoptr)
 
bool XLogCheckpointNeeded (XLogSegNo new_segno)
 
void XLogSetAsyncXactLSN (XLogRecPtr asyncXactLSN)
 
void XLogSetReplicationSlotMinimumLSN (XLogRecPtr lsn)
 
void XLogFlush (XLogRecPtr record)
 
bool XLogBackgroundFlush (void)
 
bool XLogNeedsFlush (XLogRecPtr record)
 
static int XLogFileInitInternal (XLogSegNo logsegno, TimeLineID logtli, bool *added, char *path)
 
int XLogFileInit (XLogSegNo logsegno, TimeLineID logtli)
 
static void XLogFileCopy (TimeLineID destTLI, XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno, int upto)
 
int XLogFileOpen (XLogSegNo segno, TimeLineID tli)
 
void CheckXLogRemoved (XLogSegNo segno, TimeLineID tli)
 
XLogSegNo XLogGetLastRemovedSegno (void)
 
XLogSegNo XLogGetOldestSegno (TimeLineID tli)
 
void RemoveNonParentXlogFiles (XLogRecPtr switchpoint, TimeLineID newTLI)
 
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)
 
bool check_wal_consistency_checking (char **newval, void **extra, GucSource source)
 
void assign_wal_consistency_checking (const char *newval, void *extra)
 
void InitializeWalConsistencyChecking (void)
 
const char * show_archive_command (void)
 
const char * show_in_hot_standby (void)
 
void LocalProcessControlFile (bool reset)
 
WalLevel GetActiveWalLevelOnStandby (void)
 
Size XLOGShmemSize (void)
 
void XLOGShmemInit (void)
 
void BootStrapXLOG (uint32 data_checksum_version)
 
static void XLogInitNewTimeline (TimeLineID endTLI, XLogRecPtr endOfLog, TimeLineID newTLI)
 
void StartupXLOG (void)
 
void SwitchIntoArchiveRecovery (XLogRecPtr EndRecPtr, TimeLineID replayTLI)
 
void ReachedEndOfBackup (XLogRecPtr EndRecPtr, TimeLineID tli)
 
bool RecoveryInProgress (void)
 
RecoveryState GetRecoveryState (void)
 
bool XLogInsertAllowed (void)
 
XLogRecPtr GetRedoRecPtr (void)
 
void GetFullPageWriteInfo (XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
 
XLogRecPtr GetInsertRecPtr (void)
 
XLogRecPtr GetFlushRecPtr (TimeLineID *insertTLI)
 
TimeLineID GetWALInsertionTimeLine (void)
 
TimeLineID GetWALInsertionTimeLineIfSet (void)
 
XLogRecPtr GetLastImportantRecPtr (void)
 
pg_time_t GetLastSegSwitchData (XLogRecPtr *lastSwitchLSN)
 
void ShutdownXLOG (int code, Datum arg)
 
static void LogCheckpointStart (int flags, bool restartpoint)
 
static void LogCheckpointEnd (bool restartpoint)
 
static void UpdateCheckPointDistanceEstimate (uint64 nbytes)
 
static void update_checkpoint_display (int flags, bool restartpoint, bool reset)
 
void CreateCheckPoint (int flags)
 
static void RecoveryRestartPoint (const CheckPoint *checkPoint, XLogReaderState *record)
 
bool CreateRestartPoint (int flags)
 
WALAvailability GetWALAvailability (XLogRecPtr targetLSN)
 
void XLogPutNextOid (Oid nextOid)
 
XLogRecPtr RequestXLogSwitch (bool mark_unimportant)
 
XLogRecPtr XLogRestorePoint (const char *rpName)
 
void UpdateFullPageWrites (void)
 
void xlog_redo (XLogReaderState *record)
 
void assign_wal_sync_method (int new_wal_sync_method, void *extra)
 
void issue_xlog_fsync (int fd, XLogSegNo segno, TimeLineID tli)
 
void do_pg_backup_start (const char *backupidstr, bool fast, List **tablespaces, BackupState *state, StringInfo tblspcmapfile)
 
SessionBackupState get_backup_status (void)
 
void do_pg_backup_stop (BackupState *state, bool waitforarchive)
 
void do_pg_abort_backup (int code, Datum arg)
 
void register_persistent_abort_backup_handler (void)
 
XLogRecPtr GetXLogInsertRecPtr (void)
 
XLogRecPtr GetXLogWriteRecPtr (void)
 
void GetOldestRestartPoint (XLogRecPtr *oldrecptr, TimeLineID *oldtli)
 
void XLogShutdownWalRcv (void)
 
void SetInstallXLogFileSegmentActive (void)
 
bool IsInstallXLogFileSegmentActive (void)
 
void SetWalWriterSleeping (bool sleeping)
 

Variables

int max_wal_size_mb = 1024
 
int min_wal_size_mb = 80
 
int wal_keep_size_mb = 0
 
int XLOGbuffers = -1
 
int XLogArchiveTimeout = 0
 
int XLogArchiveMode = ARCHIVE_MODE_OFF
 
char * XLogArchiveCommand = NULL
 
bool EnableHotStandby = false
 
bool fullPageWrites = true
 
bool wal_log_hints = false
 
int wal_compression = WAL_COMPRESSION_NONE
 
char * wal_consistency_checking_string = NULL
 
boolwal_consistency_checking = NULL
 
bool wal_init_zero = true
 
bool wal_recycle = true
 
bool log_checkpoints = true
 
int wal_sync_method = DEFAULT_WAL_SYNC_METHOD
 
int wal_level = WAL_LEVEL_REPLICA
 
int CommitDelay = 0
 
int CommitSiblings = 5
 
int wal_retrieve_retry_interval = 5000
 
int max_slot_wal_keep_size_mb = -1
 
int wal_decode_buffer_size = 512 * 1024
 
bool track_wal_io_timing = false
 
int wal_segment_size = DEFAULT_XLOG_SEG_SIZE
 
int CheckPointSegments
 
static double CheckPointDistanceEstimate = 0
 
static double PrevCheckPointDistance = 0
 
static bool check_wal_consistency_checking_deferred = false
 
const struct config_enum_entry wal_sync_method_options []
 
const struct config_enum_entry archive_mode_options []
 
CheckpointStatsData CheckpointStats
 
static bool lastFullPageWrites
 
static bool LocalRecoveryInProgress = true
 
static int LocalXLogInsertAllowed = -1
 
XLogRecPtr ProcLastRecPtr = InvalidXLogRecPtr
 
XLogRecPtr XactLastRecEnd = InvalidXLogRecPtr
 
XLogRecPtr XactLastCommitEnd = InvalidXLogRecPtr
 
static XLogRecPtr RedoRecPtr
 
static bool doPageWrites
 
static SessionBackupState sessionBackupState = SESSION_BACKUP_NONE
 
static XLogCtlDataXLogCtl = NULL
 
static WALInsertLockPaddedWALInsertLocks = NULL
 
static ControlFileDataControlFile = NULL
 
static int UsableBytesInSegment
 
static XLogwrtResult LogwrtResult = {0, 0}
 
static int openLogFile = -1
 
static XLogSegNo openLogSegNo = 0
 
static TimeLineID openLogTLI = 0
 
static XLogRecPtr LocalMinRecoveryPoint
 
static TimeLineID LocalMinRecoveryPointTLI
 
static bool updateMinRecoveryPoint = true
 
static int MyLockNo = 0
 
static bool holdingAllLocks = false
 

Macro Definition Documentation

◆ BootstrapTimeLineID

#define BootstrapTimeLineID   1

Definition at line 110 of file xlog.c.

◆ ConvertToXSegs

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

Definition at line 602 of file xlog.c.

◆ INSERT_FREESPACE

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

Definition at line 579 of file xlog.c.

◆ NextBufIdx

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

Definition at line 583 of file xlog.c.

◆ NUM_XLOGINSERT_LOCKS

#define NUM_XLOGINSERT_LOCKS   8

Definition at line 149 of file xlog.c.

◆ RefreshXLogWriteResult

#define RefreshXLogWriteResult (   _target)
Value:
do { \
pg_read_barrier(); \
} while (0)
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:467
pg_atomic_uint64 logWriteResult
Definition: xlog.c:471
pg_atomic_uint64 logFlushResult
Definition: xlog.c:472
static XLogCtlData * XLogCtl
Definition: xlog.c:565

Definition at line 619 of file xlog.c.

◆ UsableBytesInPage

#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)

Definition at line 596 of file xlog.c.

◆ XLogRecPtrToBufIdx

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

Definition at line 590 of file xlog.c.

Typedef Documentation

◆ WALInsertLockPadded

◆ XLogCtlData

typedef struct XLogCtlData XLogCtlData

◆ XLogCtlInsert

typedef struct XLogCtlInsert XLogCtlInsert

◆ XLogwrtResult

typedef struct XLogwrtResult XLogwrtResult

◆ XLogwrtRqst

typedef struct XLogwrtRqst XLogwrtRqst

Enumeration Type Documentation

◆ WalInsertClass

Enumerator
WALINSERT_NORMAL 
WALINSERT_SPECIAL_SWITCH 
WALINSERT_SPECIAL_CHECKPOINT 

Definition at line 558 of file xlog.c.

559 {
WalInsertClass
Definition: xlog.c:559
@ WALINSERT_SPECIAL_SWITCH
Definition: xlog.c:561
@ WALINSERT_NORMAL
Definition: xlog.c:560
@ WALINSERT_SPECIAL_CHECKPOINT
Definition: xlog.c:562

Function Documentation

◆ AdvanceXLInsertBuffer()

static void AdvanceXLInsertBuffer ( XLogRecPtr  upto,
TimeLineID  tli,
bool  opportunistic 
)
static

Definition at line 1984 of file xlog.c.

1985 {
1987  int nextidx;
1988  XLogRecPtr OldPageRqstPtr;
1989  XLogwrtRqst WriteRqst;
1990  XLogRecPtr NewPageEndPtr = InvalidXLogRecPtr;
1991  XLogRecPtr NewPageBeginPtr;
1992  XLogPageHeader NewPage;
1993  int npages pg_attribute_unused() = 0;
1994 
1995  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
1996 
1997  /*
1998  * Now that we have the lock, check if someone initialized the page
1999  * already.
2000  */
2001  while (upto >= XLogCtl->InitializedUpTo || opportunistic)
2002  {
2004 
2005  /*
2006  * Get ending-offset of the buffer page we need to replace (this may
2007  * be zero if the buffer hasn't been used yet). Fall through if it's
2008  * already written out.
2009  */
2010  OldPageRqstPtr = pg_atomic_read_u64(&XLogCtl->xlblocks[nextidx]);
2011  if (LogwrtResult.Write < OldPageRqstPtr)
2012  {
2013  /*
2014  * Nope, got work to do. If we just want to pre-initialize as much
2015  * as we can without flushing, give up now.
2016  */
2017  if (opportunistic)
2018  break;
2019 
2020  /* Advance shared memory write request position */
2022  if (XLogCtl->LogwrtRqst.Write < OldPageRqstPtr)
2023  XLogCtl->LogwrtRqst.Write = OldPageRqstPtr;
2025 
2026  /*
2027  * Acquire an up-to-date LogwrtResult value and see if we still
2028  * need to write it or if someone else already did.
2029  */
2031  if (LogwrtResult.Write < OldPageRqstPtr)
2032  {
2033  /*
2034  * Must acquire write lock. Release WALBufMappingLock first,
2035  * to make sure that all insertions that we need to wait for
2036  * can finish (up to this same position). Otherwise we risk
2037  * deadlock.
2038  */
2039  LWLockRelease(WALBufMappingLock);
2040 
2041  WaitXLogInsertionsToFinish(OldPageRqstPtr);
2042 
2043  LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
2044 
2046  if (LogwrtResult.Write >= OldPageRqstPtr)
2047  {
2048  /* OK, someone wrote it already */
2049  LWLockRelease(WALWriteLock);
2050  }
2051  else
2052  {
2053  /* Have to write it ourselves */
2054  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
2055  WriteRqst.Write = OldPageRqstPtr;
2056  WriteRqst.Flush = 0;
2057  XLogWrite(WriteRqst, tli, false);
2058  LWLockRelease(WALWriteLock);
2060  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
2061  }
2062  /* Re-acquire WALBufMappingLock and retry */
2063  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
2064  continue;
2065  }
2066  }
2067 
2068  /*
2069  * Now the next buffer slot is free and we can set it up to be the
2070  * next output page.
2071  */
2072  NewPageBeginPtr = XLogCtl->InitializedUpTo;
2073  NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
2074 
2075  Assert(XLogRecPtrToBufIdx(NewPageBeginPtr) == nextidx);
2076 
2077  NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
2078 
2079  /*
2080  * Mark the xlblock with InvalidXLogRecPtr and issue a write barrier
2081  * before initializing. Otherwise, the old page may be partially
2082  * zeroed but look valid.
2083  */
2085  pg_write_barrier();
2086 
2087  /*
2088  * Be sure to re-zero the buffer so that bytes beyond what we've
2089  * written will look like zeroes and not valid XLOG records...
2090  */
2091  MemSet((char *) NewPage, 0, XLOG_BLCKSZ);
2092 
2093  /*
2094  * Fill the new page's header
2095  */
2096  NewPage->xlp_magic = XLOG_PAGE_MAGIC;
2097 
2098  /* NewPage->xlp_info = 0; */ /* done by memset */
2099  NewPage->xlp_tli = tli;
2100  NewPage->xlp_pageaddr = NewPageBeginPtr;
2101 
2102  /* NewPage->xlp_rem_len = 0; */ /* done by memset */
2103 
2104  /*
2105  * If online backup is not in progress, mark the header to indicate
2106  * that WAL records beginning in this page have removable backup
2107  * blocks. This allows the WAL archiver to know whether it is safe to
2108  * compress archived WAL data by transforming full-block records into
2109  * the non-full-block format. It is sufficient to record this at the
2110  * page level because we force a page switch (in fact a segment
2111  * switch) when starting a backup, so the flag will be off before any
2112  * records can be written during the backup. At the end of a backup,
2113  * the last page will be marked as all unsafe when perhaps only part
2114  * is unsafe, but at worst the archiver would miss the opportunity to
2115  * compress a few records.
2116  */
2117  if (Insert->runningBackups == 0)
2118  NewPage->xlp_info |= XLP_BKP_REMOVABLE;
2119 
2120  /*
2121  * If first page of an XLOG segment file, make it a long header.
2122  */
2123  if ((XLogSegmentOffset(NewPage->xlp_pageaddr, wal_segment_size)) == 0)
2124  {
2125  XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
2126 
2127  NewLongPage->xlp_sysid = ControlFile->system_identifier;
2128  NewLongPage->xlp_seg_size = wal_segment_size;
2129  NewLongPage->xlp_xlog_blcksz = XLOG_BLCKSZ;
2130  NewPage->xlp_info |= XLP_LONG_HEADER;
2131  }
2132 
2133  /*
2134  * Make sure the initialization of the page becomes visible to others
2135  * before the xlblocks update. GetXLogBuffer() reads xlblocks without
2136  * holding a lock.
2137  */
2138  pg_write_barrier();
2139 
2140  pg_atomic_write_u64(&XLogCtl->xlblocks[nextidx], NewPageEndPtr);
2141  XLogCtl->InitializedUpTo = NewPageEndPtr;
2142 
2143  npages++;
2144  }
2145  LWLockRelease(WALBufMappingLock);
2146 
2147 #ifdef WAL_DEBUG
2148  if (XLOG_DEBUG && npages > 0)
2149  {
2150  elog(DEBUG1, "initialized %d pages, up to %X/%X",
2151  npages, LSN_FORMAT_ARGS(NewPageEndPtr));
2152  }
2153 #endif
2154 }
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:485
#define pg_write_barrier()
Definition: atomics.h:157
#define pg_attribute_unused()
Definition: c.h:123
#define Assert(condition)
Definition: c.h:858
#define MemSet(start, val, len)
Definition: c.h:1020
size_t Size
Definition: c.h:605
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:225
static void Insert(File file)
Definition: fd.c:1313
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:114
PgStat_PendingWalStats PendingWalStats
Definition: pgstat_wal.c:24
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
uint64 system_identifier
Definition: pg_control.h:110
PgStat_Counter wal_buffers_full
Definition: pgstat.h:485
XLogwrtRqst LogwrtRqst
Definition: xlog.c:454
slock_t info_lck
Definition: xlog.c:552
XLogRecPtr InitializedUpTo
Definition: xlog.c:484
char * pages
Definition: xlog.c:491
pg_atomic_uint64 * xlblocks
Definition: xlog.c:492
XLogCtlInsert Insert
Definition: xlog.c:451
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
XLogRecPtr Write
Definition: xlog.c:326
XLogRecPtr Flush
Definition: xlog.c:321
XLogRecPtr Write
Definition: xlog.c:320
static XLogRecPtr WaitXLogInsertionsToFinish(XLogRecPtr upto)
Definition: xlog.c:1503
#define RefreshXLogWriteResult(_target)
Definition: xlog.c:619
int wal_segment_size
Definition: xlog.c:142
static XLogwrtResult LogwrtResult
Definition: xlog.c:611
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:590
static void XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
Definition: xlog.c:2313
static ControlFileData * ControlFile
Definition: xlog.c:573
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
#define XLP_BKP_REMOVABLE
Definition: xlog_internal.h:78
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

References Assert, ControlFile, DEBUG1, elog, XLogwrtRqst::Flush, XLogCtlData::info_lck, XLogCtlData::InitializedUpTo, XLogCtlData::Insert, Insert(), InvalidXLogRecPtr, LogwrtResult, XLogCtlData::LogwrtRqst, LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, XLogCtlData::pages, PendingWalStats, pg_atomic_read_u64(), pg_atomic_write_u64(), pg_attribute_unused, pg_write_barrier, RefreshXLogWriteResult, SpinLockAcquire, SpinLockRelease, ControlFileData::system_identifier, WaitXLogInsertionsToFinish(), PgStat_PendingWalStats::wal_buffers_full, wal_segment_size, XLogwrtRqst::Write, XLogwrtResult::Write, XLogCtlData::xlblocks, XLOG_PAGE_MAGIC, XLogCtl, 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().

◆ assign_checkpoint_completion_target()

void assign_checkpoint_completion_target ( double  newval,
void *  extra 
)

Definition at line 2197 of file xlog.c.

2198 {
2201 }
double CheckPointCompletionTarget
Definition: checkpointer.c:138
#define newval
static void CalculateCheckpointSegments(void)
Definition: xlog.c:2161

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 2190 of file xlog.c.

2191 {
2194 }
int max_wal_size_mb
Definition: xlog.c:113

References CalculateCheckpointSegments(), max_wal_size_mb, and newval.

◆ assign_wal_consistency_checking()

void assign_wal_consistency_checking ( const char *  newval,
void *  extra 
)

Definition at line 4750 of file xlog.c.

4751 {
4752  /*
4753  * If some checks were deferred, it's possible that the checks will fail
4754  * later during InitializeWalConsistencyChecking(). But in that case, the
4755  * postmaster will exit anyway, so it's safe to proceed with the
4756  * assignment.
4757  *
4758  * Any built-in resource managers specified are assigned immediately,
4759  * which affects WAL created before shared_preload_libraries are
4760  * processed. Any custom resource managers specified won't be assigned
4761  * until after shared_preload_libraries are processed, but that's OK
4762  * because WAL for a custom resource manager can't be written before the
4763  * module is loaded anyway.
4764  */
4765  wal_consistency_checking = extra;
4766 }
bool * wal_consistency_checking
Definition: xlog.c:125

References wal_consistency_checking.

◆ assign_wal_sync_method()

void assign_wal_sync_method ( int  new_wal_sync_method,
void *  extra 
)

Definition at line 8633 of file xlog.c.

8634 {
8635  if (wal_sync_method != new_wal_sync_method)
8636  {
8637  /*
8638  * To ensure that no blocks escape unsynced, force an fsync on the
8639  * currently open log segment (if any). Also, if the open flag is
8640  * changing, close the log file so it will be reopened (with new flag
8641  * bit) at next use.
8642  */
8643  if (openLogFile >= 0)
8644  {
8645  pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN);
8646  if (pg_fsync(openLogFile) != 0)
8647  {
8648  char xlogfname[MAXFNAMELEN];
8649  int save_errno;
8650 
8651  save_errno = errno;
8652  XLogFileName(xlogfname, openLogTLI, openLogSegNo,
8654  errno = save_errno;
8655  ereport(PANIC,
8657  errmsg("could not fsync file \"%s\": %m", xlogfname)));
8658  }
8659 
8661  if (get_sync_bit(wal_sync_method) != get_sync_bit(new_wal_sync_method))
8662  XLogFileClose();
8663  }
8664  }
8665 }
int errcode_for_file_access(void)
Definition: elog.c:876
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define PANIC
Definition: elog.h:42
#define ereport(elevel,...)
Definition: elog.h:149
int pg_fsync(int fd)
Definition: fd.c:386
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101
static int openLogFile
Definition: xlog.c:634
static int get_sync_bit(int method)
Definition: xlog.c:8585
int wal_sync_method
Definition: xlog.c:129
static TimeLineID openLogTLI
Definition: xlog.c:636
static void XLogFileClose(void)
Definition: xlog.c:3632
static XLogSegNo openLogSegNo
Definition: xlog.c:635
#define MAXFNAMELEN
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)

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

◆ BootStrapXLOG()

void BootStrapXLOG ( uint32  data_checksum_version)

Definition at line 5026 of file xlog.c.

5027 {
5028  CheckPoint checkPoint;
5029  char *buffer;
5030  XLogPageHeader page;
5031  XLogLongPageHeader longpage;
5032  XLogRecord *record;
5033  char *recptr;
5034  uint64 sysidentifier;
5035  struct timeval tv;
5036  pg_crc32c crc;
5037 
5038  /* allow ordinary WAL segment creation, like StartupXLOG() would */
5040 
5041  /*
5042  * Select a hopefully-unique system identifier code for this installation.
5043  * We use the result of gettimeofday(), including the fractional seconds
5044  * field, as being about as unique as we can easily get. (Think not to
5045  * use random(), since it hasn't been seeded and there's no portable way
5046  * to seed it other than the system clock value...) The upper half of the
5047  * uint64 value is just the tv_sec part, while the lower half contains the
5048  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
5049  * PID for a little extra uniqueness. A person knowing this encoding can
5050  * determine the initialization time of the installation, which could
5051  * perhaps be useful sometimes.
5052  */
5053  gettimeofday(&tv, NULL);
5054  sysidentifier = ((uint64) tv.tv_sec) << 32;
5055  sysidentifier |= ((uint64) tv.tv_usec) << 12;
5056  sysidentifier |= getpid() & 0xFFF;
5057 
5058  /* page buffer must be aligned suitably for O_DIRECT */
5059  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
5060  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
5061  memset(page, 0, XLOG_BLCKSZ);
5062 
5063  /*
5064  * Set up information for the initial checkpoint record
5065  *
5066  * The initial checkpoint record is written to the beginning of the WAL
5067  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
5068  * used, so that we can use 0/0 to mean "before any valid WAL segment".
5069  */
5070  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
5071  checkPoint.ThisTimeLineID = BootstrapTimeLineID;
5072  checkPoint.PrevTimeLineID = BootstrapTimeLineID;
5073  checkPoint.fullPageWrites = fullPageWrites;
5074  checkPoint.wal_level = wal_level;
5075  checkPoint.nextXid =
5077  checkPoint.nextOid = FirstGenbkiObjectId;
5078  checkPoint.nextMulti = FirstMultiXactId;
5079  checkPoint.nextMultiOffset = 0;
5080  checkPoint.oldestXid = FirstNormalTransactionId;
5081  checkPoint.oldestXidDB = Template1DbOid;
5082  checkPoint.oldestMulti = FirstMultiXactId;
5083  checkPoint.oldestMultiDB = Template1DbOid;
5086  checkPoint.time = (pg_time_t) time(NULL);
5088 
5089  TransamVariables->nextXid = checkPoint.nextXid;
5090  TransamVariables->nextOid = checkPoint.nextOid;
5092  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5093  AdvanceOldestClogXid(checkPoint.oldestXid);
5094  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5095  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5097 
5098  /* Set up the XLOG page header */
5099  page->xlp_magic = XLOG_PAGE_MAGIC;
5100  page->xlp_info = XLP_LONG_HEADER;
5101  page->xlp_tli = BootstrapTimeLineID;
5103  longpage = (XLogLongPageHeader) page;
5104  longpage->xlp_sysid = sysidentifier;
5105  longpage->xlp_seg_size = wal_segment_size;
5106  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
5107 
5108  /* Insert the initial checkpoint record */
5109  recptr = ((char *) page + SizeOfXLogLongPHD);
5110  record = (XLogRecord *) recptr;
5111  record->xl_prev = 0;
5112  record->xl_xid = InvalidTransactionId;
5113  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
5115  record->xl_rmid = RM_XLOG_ID;
5116  recptr += SizeOfXLogRecord;
5117  /* fill the XLogRecordDataHeaderShort struct */
5118  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
5119  *(recptr++) = sizeof(checkPoint);
5120  memcpy(recptr, &checkPoint, sizeof(checkPoint));
5121  recptr += sizeof(checkPoint);
5122  Assert(recptr - (char *) record == record->xl_tot_len);
5123 
5124  INIT_CRC32C(crc);
5125  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
5126  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
5127  FIN_CRC32C(crc);
5128  record->xl_crc = crc;
5129 
5130  /* Create first XLOG segment file */
5133 
5134  /*
5135  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
5136  * close the file again in a moment.
5137  */
5138 
5139  /* Write the first page with the initial record */
5140  errno = 0;
5141  pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
5142  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
5143  {
5144  /* if write didn't set errno, assume problem is no disk space */
5145  if (errno == 0)
5146  errno = ENOSPC;
5147  ereport(PANIC,
5149  errmsg("could not write bootstrap write-ahead log file: %m")));
5150  }
5152 
5153  pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC);
5154  if (pg_fsync(openLogFile) != 0)
5155  ereport(PANIC,
5157  errmsg("could not fsync bootstrap write-ahead log file: %m")));
5159 
5160  if (close(openLogFile) != 0)
5161  ereport(PANIC,
5163  errmsg("could not close bootstrap write-ahead log file: %m")));
5164 
5165  openLogFile = -1;
5166 
5167  /* Now create pg_control */
5168  InitControlFile(sysidentifier, data_checksum_version);
5169  ControlFile->time = checkPoint.time;
5170  ControlFile->checkPoint = checkPoint.redo;
5171  ControlFile->checkPointCopy = checkPoint;
5172 
5173  /* some additional ControlFile fields are set in WriteControlFile() */
5174  WriteControlFile();
5175 
5176  /* Bootstrap the commit log, too */
5177  BootStrapCLOG();
5181 
5182  pfree(buffer);
5183 
5184  /*
5185  * Force control file to be read - in contrast to normal processing we'd
5186  * otherwise never run the checks and GUC related initializations therein.
5187  */
5188  ReadControlFile();
5189 }
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:804
void BootStrapCLOG(void)
Definition: clog.c:833
void BootStrapCommitTs(void)
Definition: commit_ts.c:596
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:909
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2328
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2362
void BootStrapMultiXact(void)
Definition: multixact.c:2034
#define FirstMultiXactId
Definition: multixact.h:25
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:68
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:98
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:103
return crc
int64 pg_time_t
Definition: pgtime.h:23
Oid oldestMultiDB
Definition: pg_control.h:51
MultiXactId oldestMulti
Definition: pg_control.h:50
MultiXactOffset nextMultiOffset
Definition: pg_control.h:47
TransactionId newestCommitTsXid
Definition: pg_control.h:55
TransactionId oldestXid
Definition: pg_control.h:48
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
Oid nextOid
Definition: pg_control.h:45
TransactionId oldestActiveXid
Definition: pg_control.h:64
bool fullPageWrites
Definition: pg_control.h:42
MultiXactId nextMulti
Definition: pg_control.h:46
FullTransactionId nextXid
Definition: pg_control.h:44
TransactionId oldestCommitTsXid
Definition: pg_control.h:53
pg_time_t time
Definition: pg_control.h:52
int wal_level
Definition: pg_control.h:43
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:49
CheckPoint checkPointCopy
Definition: pg_control.h:135
pg_time_t time
Definition: pg_control.h:132
XLogRecPtr checkPoint
Definition: pg_control.h:133
FullTransactionId nextXid
Definition: transam.h:220
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
uint8 xl_info
Definition: xlogrecord.h:46
uint32 xl_tot_len
Definition: xlogrecord.h:43
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
void BootStrapSUBTRANS(void)
Definition: subtrans.c:270
#define InvalidTransactionId
Definition: transam.h:31
#define FirstGenbkiObjectId
Definition: transam.h:195
#define FirstNormalTransactionId
Definition: transam.h:34
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:372
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:355
TransamVariablesData * TransamVariables
Definition: varsup.c:34
int gettimeofday(struct timeval *tp, void *tzp)
int XLogFileInit(XLogSegNo logsegno, TimeLineID logtli)
Definition: xlog.c:3373
bool fullPageWrites
Definition: xlog.c:121
static void InitControlFile(uint64 sysidentifier, uint32 data_checksum_version)
Definition: xlog.c:4197
void SetInstallXLogFileSegmentActive(void)
Definition: xlog.c:9476
int wal_level
Definition: xlog.c:130
static void WriteControlFile(void)
Definition: xlog.c:4232
#define BootstrapTimeLineID
Definition: xlog.c:110
static void ReadControlFile(void)
Definition: xlog.c:4314
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:217
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:241
#define SizeOfXLogRecord
Definition: xlogrecord.h:55

References AdvanceOldestClogXid(), Assert, BootStrapCLOG(), BootStrapCommitTs(), BootStrapMultiXact(), BootStrapSUBTRANS(), BootstrapTimeLineID, ControlFileData::checkPoint, ControlFileData::checkPointCopy, close, COMP_CRC32C, ControlFile, crc, ereport, errcode_for_file_access(), errmsg(), FIN_CRC32C, FirstGenbkiObjectId, FirstMultiXactId, FirstNormalTransactionId, fullPageWrites, CheckPoint::fullPageWrites, FullTransactionIdFromEpochAndXid(), gettimeofday(), INIT_CRC32C, InitControlFile(), InvalidTransactionId, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, TransamVariablesData::nextOid, CheckPoint::nextOid, TransamVariablesData::nextXid, CheckPoint::nextXid, TransamVariablesData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, openLogTLI, palloc(), PANIC, pfree(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), CheckPoint::PrevTimeLineID, ReadControlFile(), CheckPoint::redo, SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetTransactionIdLimit(), SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, TransamVariables, TYPEALIGN, wal_level, CheckPoint::wal_level, wal_segment_size, write, WriteControlFile(), XLogRecord::xl_crc, 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 BootstrapModeMain().

◆ CalculateCheckpointSegments()

static void CalculateCheckpointSegments ( void  )
static

Definition at line 2161 of file xlog.c.

2162 {
2163  double target;
2164 
2165  /*-------
2166  * Calculate the distance at which to trigger a checkpoint, to avoid
2167  * exceeding max_wal_size_mb. This is based on two assumptions:
2168  *
2169  * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
2170  * WAL for two checkpoint cycles to allow us to recover from the
2171  * secondary checkpoint if the first checkpoint failed, though we
2172  * only did this on the primary anyway, not on standby. Keeping just
2173  * one checkpoint simplifies processing and reduces disk space in
2174  * many smaller databases.)
2175  * b) during checkpoint, we consume checkpoint_completion_target *
2176  * number of segments consumed between checkpoints.
2177  *-------
2178  */
2179  target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
2181 
2182  /* round down */
2183  CheckPointSegments = (int) target;
2184 
2185  if (CheckPointSegments < 1)
2186  CheckPointSegments = 1;
2187 }
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:602
int CheckPointSegments
Definition: xlog.c:155

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

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

◆ check_max_slot_wal_keep_size()

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

Definition at line 2222 of file xlog.c.

2223 {
2224  if (IsBinaryUpgrade && *newval != -1)
2225  {
2226  GUC_check_errdetail("\"%s\" must be set to -1 during binary upgrade mode.",
2227  "max_slot_wal_keep_size");
2228  return false;
2229  }
2230 
2231  return true;
2232 }
bool IsBinaryUpgrade
Definition: globals.c:120
#define GUC_check_errdetail
Definition: guc.h:476

References GUC_check_errdetail, IsBinaryUpgrade, and newval.

◆ check_wal_buffers()

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

Definition at line 4630 of file xlog.c.

4631 {
4632  /*
4633  * -1 indicates a request for auto-tune.
4634  */
4635  if (*newval == -1)
4636  {
4637  /*
4638  * If we haven't yet changed the boot_val default of -1, just let it
4639  * be. We'll fix it when XLOGShmemSize is called.
4640  */
4641  if (XLOGbuffers == -1)
4642  return true;
4643 
4644  /* Otherwise, substitute the auto-tune value */
4646  }
4647 
4648  /*
4649  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
4650  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
4651  * the case, we just silently treat such values as a request for the
4652  * minimum. (We could throw an error instead, but that doesn't seem very
4653  * helpful.)
4654  */
4655  if (*newval < 4)
4656  *newval = 4;
4657 
4658  return true;
4659 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:4614
int XLOGbuffers
Definition: xlog.c:116

References newval, XLOGbuffers, and XLOGChooseNumBuffers().

◆ check_wal_consistency_checking()

bool check_wal_consistency_checking ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 4665 of file xlog.c.

4666 {
4667  char *rawstring;
4668  List *elemlist;
4669  ListCell *l;
4670  bool newwalconsistency[RM_MAX_ID + 1];
4671 
4672  /* Initialize the array */
4673  MemSet(newwalconsistency, 0, (RM_MAX_ID + 1) * sizeof(bool));
4674 
4675  /* Need a modifiable copy of string */
4676  rawstring = pstrdup(*newval);
4677 
4678  /* Parse string into list of identifiers */
4679  if (!SplitIdentifierString(rawstring, ',', &elemlist))
4680  {
4681  /* syntax error in list */
4682  GUC_check_errdetail("List syntax is invalid.");
4683  pfree(rawstring);
4684  list_free(elemlist);
4685  return false;
4686  }
4687 
4688  foreach(l, elemlist)
4689  {
4690  char *tok = (char *) lfirst(l);
4691  int rmid;
4692 
4693  /* Check for 'all'. */
4694  if (pg_strcasecmp(tok, "all") == 0)
4695  {
4696  for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
4697  if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL)
4698  newwalconsistency[rmid] = true;
4699  }
4700  else
4701  {
4702  /* Check if the token matches any known resource manager. */
4703  bool found = false;
4704 
4705  for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
4706  {
4707  if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL &&
4708  pg_strcasecmp(tok, GetRmgr(rmid).rm_name) == 0)
4709  {
4710  newwalconsistency[rmid] = true;
4711  found = true;
4712  break;
4713  }
4714  }
4715  if (!found)
4716  {
4717  /*
4718  * During startup, it might be a not-yet-loaded custom
4719  * resource manager. Defer checking until
4720  * InitializeWalConsistencyChecking().
4721  */
4723  {
4725  }
4726  else
4727  {
4728  GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
4729  pfree(rawstring);
4730  list_free(elemlist);
4731  return false;
4732  }
4733  }
4734  }
4735  }
4736 
4737  pfree(rawstring);
4738  list_free(elemlist);
4739 
4740  /* assign new value */
4741  *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool));
4742  memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool));
4743  return true;
4744 }
#define ERROR
Definition: elog.h:39
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:637
void list_free(List *list)
Definition: list.c:1546
char * pstrdup(const char *in)
Definition: mcxt.c:1696
bool process_shared_preload_libraries_done
Definition: miscinit.c:1779
#define lfirst(lc)
Definition: pg_list.h:172
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define RM_MAX_ID
Definition: rmgr.h:33
Definition: pg_list.h:54
void(* rm_mask)(char *pagedata, BlockNumber blkno)
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3432
static bool check_wal_consistency_checking_deferred
Definition: xlog.c:165
static RmgrData GetRmgr(RmgrId rmid)
static bool RmgrIdExists(RmgrId rmid)

References check_wal_consistency_checking_deferred, ERROR, GetRmgr(), GUC_check_errdetail, guc_malloc(), lfirst, list_free(), MemSet, newval, pfree(), pg_strcasecmp(), process_shared_preload_libraries_done, pstrdup(), RmgrData::rm_mask, RM_MAX_ID, RmgrIdExists(), and SplitIdentifierString().

◆ check_wal_segment_size()

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

Definition at line 2204 of file xlog.c.

2205 {
2206  if (!IsValidWalSegSize(*newval))
2207  {
2208  GUC_check_errdetail("The WAL segment size must be a power of two between 1 MB and 1 GB.");
2209  return false;
2210  }
2211 
2212  return true;
2213 }
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:96

References GUC_check_errdetail, IsValidWalSegSize, and newval.

◆ CheckPointGuts()

static void CheckPointGuts ( XLogRecPtr  checkPointRedo,
int  flags 
)
static

Definition at line 7502 of file xlog.c.

7503 {
7509 
7510  /* Write out all dirty data in SLRUs and the main buffer pool */
7511  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
7513  CheckPointCLOG();
7518  CheckPointBuffers(flags);
7519 
7520  /* Perform all queued up fsyncs */
7521  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
7525  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
7526 
7527  /* We deliberately delay 2PC checkpointing as long as possible */
7528  CheckPointTwoPhase(checkPointRedo);
7529 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
void CheckPointBuffers(int flags)
Definition: bufmgr.c:3692
void CheckPointCLOG(void)
Definition: clog.c:937
void CheckPointCommitTs(void)
Definition: commit_ts.c:820
void CheckPointMultiXact(void)
Definition: multixact.c:2304
void CheckPointReplicationOrigin(void)
Definition: origin.c:577
void CheckPointPredicate(void)
Definition: predicate.c:1036
void CheckPointRelationMap(void)
Definition: relmapper.c:611
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1155
void CheckPointReplicationSlots(bool is_shutdown)
Definition: slot.c:1867
void CheckPointSnapBuild(void)
Definition: snapbuild.c:2074
TimestampTz ckpt_write_t
Definition: xlog.h:162
TimestampTz ckpt_sync_end_t
Definition: xlog.h:164
TimestampTz ckpt_sync_t
Definition: xlog.h:163
void CheckPointSUBTRANS(void)
Definition: subtrans.c:355
void ProcessSyncRequests(void)
Definition: sync.c:286
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1816
CheckpointStatsData CheckpointStats
Definition: xlog.c:208
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:139

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

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ CheckRequiredParameterValues()

static void CheckRequiredParameterValues ( void  )
static

Definition at line 5378 of file xlog.c.

5379 {
5380  /*
5381  * For archive recovery, the WAL must be generated with at least 'replica'
5382  * wal_level.
5383  */
5385  {
5386  ereport(FATAL,
5387  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
5388  errmsg("WAL was generated with \"wal_level=minimal\", cannot continue recovering"),
5389  errdetail("This happens if you temporarily set \"wal_level=minimal\" on the server."),
5390  errhint("Use a backup taken after setting \"wal_level\" to higher than \"minimal\".")));
5391  }
5392 
5393  /*
5394  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
5395  * must have at least as many backend slots as the primary.
5396  */
5398  {
5399  /* We ignore autovacuum_max_workers when we make this test. */
5400  RecoveryRequiresIntParameter("max_connections",
5403  RecoveryRequiresIntParameter("max_worker_processes",
5406  RecoveryRequiresIntParameter("max_wal_senders",
5409  RecoveryRequiresIntParameter("max_prepared_transactions",
5412  RecoveryRequiresIntParameter("max_locks_per_transaction",
5415  }
5416 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
#define FATAL
Definition: elog.h:41
int MaxConnections
Definition: globals.c:142
int max_worker_processes
Definition: globals.c:143
int max_locks_per_xact
Definition: lock.c:53
int max_worker_processes
Definition: pg_control.h:181
int max_locks_per_xact
Definition: pg_control.h:184
int max_prepared_xacts
Definition: pg_control.h:183
int max_prepared_xacts
Definition: twophase.c:115
int max_wal_senders
Definition: walsender.c:121
bool EnableHotStandby
Definition: xlog.c:120
@ WAL_LEVEL_MINIMAL
Definition: xlog.h:74
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:138
void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue)

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

Referenced by StartupXLOG(), and xlog_redo().

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3720 of file xlog.c.

3721 {
3722  int save_errno = errno;
3723  XLogSegNo lastRemovedSegNo;
3724 
3726  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3728 
3729  if (segno <= lastRemovedSegNo)
3730  {
3731  char filename[MAXFNAMELEN];
3732 
3733  XLogFileName(filename, tli, segno, wal_segment_size);
3734  errno = save_errno;
3735  ereport(ERROR,
3737  errmsg("requested WAL segment %s has already been removed",
3738  filename)));
3739  }
3740  errno = save_errno;
3741 }
static char * filename
Definition: pg_dumpall.c:119
XLogSegNo lastRemovedSegNo
Definition: xlog.c:460
uint64 XLogSegNo
Definition: xlogdefs.h:48

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

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

◆ CleanupAfterArchiveRecovery()

static void CleanupAfterArchiveRecovery ( TimeLineID  EndOfLogTLI,
XLogRecPtr  EndOfLog,
TimeLineID  newTLI 
)
static

Definition at line 5282 of file xlog.c.

5284 {
5285  /*
5286  * Execute the recovery_end_command, if any.
5287  */
5288  if (recoveryEndCommand && strcmp(recoveryEndCommand, "") != 0)
5290  "recovery_end_command",
5291  true,
5292  WAIT_EVENT_RECOVERY_END_COMMAND);
5293 
5294  /*
5295  * We switched to a new timeline. Clean up segments on the old timeline.
5296  *
5297  * If there are any higher-numbered segments on the old timeline, remove
5298  * them. They might contain valid WAL, but they might also be
5299  * pre-allocated files containing garbage. In any case, they are not part
5300  * of the new timeline's history so we don't need them.
5301  */
5302  RemoveNonParentXlogFiles(EndOfLog, newTLI);
5303 
5304  /*
5305  * If the switch happened in the middle of a segment, what to do with the
5306  * last, partial segment on the old timeline? If we don't archive it, and
5307  * the server that created the WAL never archives it either (e.g. because
5308  * it was hit by a meteor), it will never make it to the archive. That's
5309  * OK from our point of view, because the new segment that we created with
5310  * the new TLI contains all the WAL from the old timeline up to the switch
5311  * point. But if you later try to do PITR to the "missing" WAL on the old
5312  * timeline, recovery won't find it in the archive. It's physically
5313  * present in the new file with new TLI, but recovery won't look there
5314  * when it's recovering to the older timeline. On the other hand, if we
5315  * archive the partial segment, and the original server on that timeline
5316  * is still running and archives the completed version of the same segment
5317  * later, it will fail. (We used to do that in 9.4 and below, and it
5318  * caused such problems).
5319  *
5320  * As a compromise, we rename the last segment with the .partial suffix,
5321  * and archive it. Archive recovery will never try to read .partial
5322  * segments, so they will normally go unused. But in the odd PITR case,
5323  * the administrator can copy them manually to the pg_wal directory
5324  * (removing the suffix). They can be useful in debugging, too.
5325  *
5326  * If a .done or .ready file already exists for the old timeline, however,
5327  * we had already determined that the segment is complete, so we can let
5328  * it be archived normally. (In particular, if it was restored from the
5329  * archive to begin with, it's expected to have a .done file).
5330  */
5331  if (XLogSegmentOffset(EndOfLog, wal_segment_size) != 0 &&
5333  {
5334  char origfname[MAXFNAMELEN];
5335  XLogSegNo endLogSegNo;
5336 
5337  XLByteToPrevSeg(EndOfLog, endLogSegNo, wal_segment_size);
5338  XLogFileName(origfname, EndOfLogTLI, endLogSegNo, wal_segment_size);
5339 
5340  if (!XLogArchiveIsReadyOrDone(origfname))
5341  {
5342  char origpath[MAXPGPATH];
5343  char partialfname[MAXFNAMELEN];
5344  char partialpath[MAXPGPATH];
5345 
5346  /*
5347  * If we're summarizing WAL, we can't rename the partial file
5348  * until the summarizer finishes with it, else it will fail.
5349  */
5350  if (summarize_wal)
5351  WaitForWalSummarization(EndOfLog);
5352 
5353  XLogFilePath(origpath, EndOfLogTLI, endLogSegNo, wal_segment_size);
5354  snprintf(partialfname, MAXFNAMELEN, "%s.partial", origfname);
5355  snprintf(partialpath, MAXPGPATH, "%s.partial", origpath);
5356 
5357  /*
5358  * Make sure there's no .done or .ready file for the .partial
5359  * file.
5360  */
5361  XLogArchiveCleanup(partialfname);
5362 
5363  durable_rename(origpath, partialpath, ERROR);
5364  XLogArchiveNotify(partialfname);
5365  }
5366  }
5367 }
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:782
#define MAXPGPATH
#define snprintf
Definition: port.h:238
bool summarize_wal
void WaitForWalSummarization(XLogRecPtr lsn)
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition: xlog.c:3933
#define XLogArchivingActive()
Definition: xlog.h:99
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
static void XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
bool XLogArchiveIsReadyOrDone(const char *xlog)
Definition: xlogarchive.c:664
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal, uint32 wait_event_info)
Definition: xlogarchive.c:295
void XLogArchiveNotify(const char *xlog)
Definition: xlogarchive.c:444
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:712
char * recoveryEndCommand
Definition: xlogrecovery.c:84

References durable_rename(), ERROR, ExecuteRecoveryCommand(), MAXFNAMELEN, MAXPGPATH, recoveryEndCommand, RemoveNonParentXlogFiles(), snprintf, summarize_wal, WaitForWalSummarization(), wal_segment_size, XLByteToPrevSeg, XLogArchiveCleanup(), XLogArchiveIsReadyOrDone(), XLogArchiveNotify(), XLogArchivingActive, XLogFileName(), XLogFilePath(), and XLogSegmentOffset.

Referenced by StartupXLOG().

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

Definition at line 4154 of file xlog.c.

4155 {
4156  DIR *xldir;
4157  struct dirent *xlde;
4158  char path[MAXPGPATH + sizeof(XLOGDIR)];
4159 
4160  xldir = AllocateDir(XLOGDIR);
4161 
4162  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
4163  {
4164  if (IsBackupHistoryFileName(xlde->d_name))
4165  {
4166  if (XLogArchiveCheckDone(xlde->d_name))
4167  {
4168  elog(DEBUG2, "removing WAL backup history file \"%s\"",
4169  xlde->d_name);
4170  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
4171  unlink(path);
4172  XLogArchiveCleanup(xlde->d_name);
4173  }
4174  }
4175  }
4176 
4177  FreeDir(xldir);
4178 }
#define DEBUG2
Definition: elog.h:29
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2932
int FreeDir(DIR *dir)
Definition: fd.c:2984
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2866
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
#define XLOGDIR
static bool IsBackupHistoryFileName(const char *fname)
bool XLogArchiveCheckDone(const char *xlog)
Definition: xlogarchive.c:565

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

Referenced by do_pg_backup_stop().

◆ CopyXLogRecordToWAL()

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

Definition at line 1224 of file xlog.c.

1226 {
1227  char *currpos;
1228  int freespace;
1229  int written;
1230  XLogRecPtr CurrPos;
1231  XLogPageHeader pagehdr;
1232 
1233  /*
1234  * Get a pointer to the right place in the right WAL buffer to start
1235  * inserting to.
1236  */
1237  CurrPos = StartPos;
1238  currpos = GetXLogBuffer(CurrPos, tli);
1239  freespace = INSERT_FREESPACE(CurrPos);
1240 
1241  /*
1242  * there should be enough space for at least the first field (xl_tot_len)
1243  * on this page.
1244  */
1245  Assert(freespace >= sizeof(uint32));
1246 
1247  /* Copy record data */
1248  written = 0;
1249  while (rdata != NULL)
1250  {
1251  const char *rdata_data = rdata->data;
1252  int rdata_len = rdata->len;
1253 
1254  while (rdata_len > freespace)
1255  {
1256  /*
1257  * Write what fits on this page, and continue on the next page.
1258  */
1259  Assert(CurrPos % XLOG_BLCKSZ >= SizeOfXLogShortPHD || freespace == 0);
1260  memcpy(currpos, rdata_data, freespace);
1261  rdata_data += freespace;
1262  rdata_len -= freespace;
1263  written += freespace;
1264  CurrPos += freespace;
1265 
1266  /*
1267  * Get pointer to beginning of next page, and set the xlp_rem_len
1268  * in the page header. Set XLP_FIRST_IS_CONTRECORD.
1269  *
1270  * It's safe to set the contrecord flag and xlp_rem_len without a
1271  * lock on the page. All the other flags were already set when the
1272  * page was initialized, in AdvanceXLInsertBuffer, and we're the
1273  * only backend that needs to set the contrecord flag.
1274  */
1275  currpos = GetXLogBuffer(CurrPos, tli);
1276  pagehdr = (XLogPageHeader) currpos;
1277  pagehdr->xlp_rem_len = write_len - written;
1278  pagehdr->xlp_info |= XLP_FIRST_IS_CONTRECORD;
1279 
1280  /* skip over the page header */
1281  if (XLogSegmentOffset(CurrPos, wal_segment_size) == 0)
1282  {
1283  CurrPos += SizeOfXLogLongPHD;
1284  currpos += SizeOfXLogLongPHD;
1285  }
1286  else
1287  {
1288  CurrPos += SizeOfXLogShortPHD;
1289  currpos += SizeOfXLogShortPHD;
1290  }
1291  freespace = INSERT_FREESPACE(CurrPos);
1292  }
1293 
1294  Assert(CurrPos % XLOG_BLCKSZ >= SizeOfXLogShortPHD || rdata_len == 0);
1295  memcpy(currpos, rdata_data, rdata_len);
1296  currpos += rdata_len;
1297  CurrPos += rdata_len;
1298  freespace -= rdata_len;
1299  written += rdata_len;
1300 
1301  rdata = rdata->next;
1302  }
1303  Assert(written == write_len);
1304 
1305  /*
1306  * If this was an xlog-switch, it's not enough to write the switch record,
1307  * we also have to consume all the remaining space in the WAL segment. We
1308  * have already reserved that space, but we need to actually fill it.
1309  */
1310  if (isLogSwitch && XLogSegmentOffset(CurrPos, wal_segment_size) != 0)
1311  {
1312  /* An xlog-switch record doesn't contain any data besides the header */
1313  Assert(write_len == SizeOfXLogRecord);
1314 
1315  /* Assert that we did reserve the right amount of space */
1316  Assert(XLogSegmentOffset(EndPos, wal_segment_size) == 0);
1317 
1318  /* Use up all the remaining space on the current page */
1319  CurrPos += freespace;
1320 
1321  /*
1322  * Cause all remaining pages in the segment to be flushed, leaving the
1323  * XLog position where it should be, at the start of the next segment.
1324  * We do this one page at a time, to make sure we don't deadlock
1325  * against ourselves if wal_buffers < wal_segment_size.
1326  */
1327  while (CurrPos < EndPos)
1328  {
1329  /*
1330  * The minimal action to flush the page would be to call
1331  * WALInsertLockUpdateInsertingAt(CurrPos) followed by
1332  * AdvanceXLInsertBuffer(...). The page would be left initialized
1333  * mostly to zeros, except for the page header (always the short
1334  * variant, as this is never a segment's first page).
1335  *
1336  * The large vistas of zeros are good for compressibility, but the
1337  * headers interrupting them every XLOG_BLCKSZ (with values that
1338  * differ from page to page) are not. The effect varies with
1339  * compression tool, but bzip2 for instance compresses about an
1340  * order of magnitude worse if those headers are left in place.
1341  *
1342  * Rather than complicating AdvanceXLInsertBuffer itself (which is
1343  * called in heavily-loaded circumstances as well as this lightly-
1344  * loaded one) with variant behavior, we just use GetXLogBuffer
1345  * (which itself calls the two methods we need) to get the pointer
1346  * and zero most of the page. Then we just zero the page header.
1347  */
1348  currpos = GetXLogBuffer(CurrPos, tli);
1349  MemSet(currpos, 0, SizeOfXLogShortPHD);
1350 
1351  CurrPos += XLOG_BLCKSZ;
1352  }
1353  }
1354  else
1355  {
1356  /* Align the end position, so that the next record starts aligned */
1357  CurrPos = MAXALIGN64(CurrPos);
1358  }
1359 
1360  if (CurrPos != EndPos)
1361  ereport(PANIC,
1363  errmsg_internal("space reserved for WAL record does not match what was written"));
1364 }
unsigned int uint32
Definition: c.h:506
#define MAXALIGN64(LEN)
Definition: c.h:836
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
const char * data
struct XLogRecData * next
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:579
static char * GetXLogBuffer(XLogRecPtr ptr, TimeLineID tli)
Definition: xlog.c:1631
#define XLP_FIRST_IS_CONTRECORD
Definition: xlog_internal.h:74
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52

References Assert, XLogRecData::data, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg_internal(), 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().

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 6883 of file xlog.c.

6884 {
6885  bool shutdown;
6886  CheckPoint checkPoint;
6887  XLogRecPtr recptr;
6888  XLogSegNo _logSegNo;
6890  uint32 freespace;
6891  XLogRecPtr PriorRedoPtr;
6892  XLogRecPtr last_important_lsn;
6893  VirtualTransactionId *vxids;
6894  int nvxids;
6895  int oldXLogAllowed = 0;
6896 
6897  /*
6898  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
6899  * issued at a different time.
6900  */
6902  shutdown = true;
6903  else
6904  shutdown = false;
6905 
6906  /* sanity check */
6907  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
6908  elog(ERROR, "can't create a checkpoint during recovery");
6909 
6910  /*
6911  * Prepare to accumulate statistics.
6912  *
6913  * Note: because it is possible for log_checkpoints to change while a
6914  * checkpoint proceeds, we always accumulate stats, even if
6915  * log_checkpoints is currently off.
6916  */
6917  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
6919 
6920  /*
6921  * Let smgr prepare for checkpoint; this has to happen outside the
6922  * critical section and before we determine the REDO pointer. Note that
6923  * smgr must not do anything that'd have to be undone if we decide no
6924  * checkpoint is needed.
6925  */
6927 
6928  /*
6929  * Use a critical section to force system panic if we have trouble.
6930  */
6932 
6933  if (shutdown)
6934  {
6935  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6938  LWLockRelease(ControlFileLock);
6939  }
6940 
6941  /* Begin filling in the checkpoint WAL record */
6942  MemSet(&checkPoint, 0, sizeof(checkPoint));
6943  checkPoint.time = (pg_time_t) time(NULL);
6944 
6945  /*
6946  * For Hot Standby, derive the oldestActiveXid before we fix the redo
6947  * pointer. This allows us to begin accumulating changes to assemble our
6948  * starting snapshot of locks and transactions.
6949  */
6950  if (!shutdown && XLogStandbyInfoActive())
6952  else
6954 
6955  /*
6956  * Get location of last important record before acquiring insert locks (as
6957  * GetLastImportantRecPtr() also locks WAL locks).
6958  */
6959  last_important_lsn = GetLastImportantRecPtr();
6960 
6961  /*
6962  * If this isn't a shutdown or forced checkpoint, and if there has been no
6963  * WAL activity requiring a checkpoint, skip it. The idea here is to
6964  * avoid inserting duplicate checkpoints when the system is idle.
6965  */
6967  CHECKPOINT_FORCE)) == 0)
6968  {
6969  if (last_important_lsn == ControlFile->checkPoint)
6970  {
6971  END_CRIT_SECTION();
6972  ereport(DEBUG1,
6973  (errmsg_internal("checkpoint skipped because system is idle")));
6974  return;
6975  }
6976  }
6977 
6978  /*
6979  * An end-of-recovery checkpoint is created before anyone is allowed to
6980  * write WAL. To allow us to write the checkpoint record, temporarily
6981  * enable XLogInsertAllowed.
6982  */
6983  if (flags & CHECKPOINT_END_OF_RECOVERY)
6984  oldXLogAllowed = LocalSetXLogInsertAllowed();
6985 
6986  checkPoint.ThisTimeLineID = XLogCtl->InsertTimeLineID;
6987  if (flags & CHECKPOINT_END_OF_RECOVERY)
6988  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
6989  else
6990  checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
6991 
6992  /*
6993  * We must block concurrent insertions while examining insert state.
6994  */
6996 
6997  checkPoint.fullPageWrites = Insert->fullPageWrites;
6998  checkPoint.wal_level = wal_level;
6999 
7000  if (shutdown)
7001  {
7002  XLogRecPtr curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
7003 
7004  /*
7005  * Compute new REDO record ptr = location of next XLOG record.
7006  *
7007  * Since this is a shutdown checkpoint, there can't be any concurrent
7008  * WAL insertion.
7009  */
7010  freespace = INSERT_FREESPACE(curInsert);
7011  if (freespace == 0)
7012  {
7013  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
7014  curInsert += SizeOfXLogLongPHD;
7015  else
7016  curInsert += SizeOfXLogShortPHD;
7017  }
7018  checkPoint.redo = curInsert;
7019 
7020  /*
7021  * Here we update the shared RedoRecPtr for future XLogInsert calls;
7022  * this must be done while holding all the insertion locks.
7023  *
7024  * Note: if we fail to complete the checkpoint, RedoRecPtr will be
7025  * left pointing past where it really needs to point. This is okay;
7026  * the only consequence is that XLogInsert might back up whole buffers
7027  * that it didn't really need to. We can't postpone advancing
7028  * RedoRecPtr because XLogInserts that happen while we are dumping
7029  * buffers must assume that their buffer changes are not included in
7030  * the checkpoint.
7031  */
7032  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
7033  }
7034 
7035  /*
7036  * Now we can release the WAL insertion locks, allowing other xacts to
7037  * proceed while we are flushing disk buffers.
7038  */
7040 
7041  /*
7042  * If this is an online checkpoint, we have not yet determined the redo
7043  * point. We do so now by inserting the special XLOG_CHECKPOINT_REDO
7044  * record; the LSN at which it starts becomes the new redo pointer. We
7045  * don't do this for a shutdown checkpoint, because in that case no WAL
7046  * can be written between the redo point and the insertion of the
7047  * checkpoint record itself, so the checkpoint record itself serves to
7048  * mark the redo point.
7049  */
7050  if (!shutdown)
7051  {
7052  /* Include WAL level in record for WAL summarizer's benefit. */
7053  XLogBeginInsert();
7054  XLogRegisterData((char *) &wal_level, sizeof(wal_level));
7055  (void) XLogInsert(RM_XLOG_ID, XLOG_CHECKPOINT_REDO);
7056 
7057  /*
7058  * XLogInsertRecord will have updated XLogCtl->Insert.RedoRecPtr in
7059  * shared memory and RedoRecPtr in backend-local memory, but we need
7060  * to copy that into the record that will be inserted when the
7061  * checkpoint is complete.
7062  */
7063  checkPoint.redo = RedoRecPtr;
7064  }
7065 
7066  /* Update the info_lck-protected copy of RedoRecPtr as well */
7068  XLogCtl->RedoRecPtr = checkPoint.redo;
7070 
7071  /*
7072  * If enabled, log checkpoint start. We postpone this until now so as not
7073  * to log anything if we decided to skip the checkpoint.
7074  */
7075  if (log_checkpoints)
7076  LogCheckpointStart(flags, false);
7077 
7078  /* Update the process title */
7079  update_checkpoint_display(flags, false, false);
7080 
7081  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
7082 
7083  /*
7084  * Get the other info we need for the checkpoint record.
7085  *
7086  * We don't need to save oldestClogXid in the checkpoint, it only matters
7087  * for the short period in which clog is being truncated, and if we crash
7088  * during that we'll redo the clog truncation and fix up oldestClogXid
7089  * there.
7090  */
7091  LWLockAcquire(XidGenLock, LW_SHARED);
7092  checkPoint.nextXid = TransamVariables->nextXid;
7093  checkPoint.oldestXid = TransamVariables->oldestXid;
7095  LWLockRelease(XidGenLock);
7096 
7097  LWLockAcquire(CommitTsLock, LW_SHARED);
7100  LWLockRelease(CommitTsLock);
7101 
7102  LWLockAcquire(OidGenLock, LW_SHARED);
7103  checkPoint.nextOid = TransamVariables->nextOid;
7104  if (!shutdown)
7105  checkPoint.nextOid += TransamVariables->oidCount;
7106  LWLockRelease(OidGenLock);
7107 
7108  MultiXactGetCheckptMulti(shutdown,
7109  &checkPoint.nextMulti,
7110  &checkPoint.nextMultiOffset,
7111  &checkPoint.oldestMulti,
7112  &checkPoint.oldestMultiDB);
7113 
7114  /*
7115  * Having constructed the checkpoint record, ensure all shmem disk buffers
7116  * and commit-log buffers are flushed to disk.
7117  *
7118  * This I/O could fail for various reasons. If so, we will fail to
7119  * complete the checkpoint, but there is no reason to force a system
7120  * panic. Accordingly, exit critical section while doing it.
7121  */
7122  END_CRIT_SECTION();
7123 
7124  /*
7125  * In some cases there are groups of actions that must all occur on one
7126  * side or the other of a checkpoint record. Before flushing the
7127  * checkpoint record we must explicitly wait for any backend currently
7128  * performing those groups of actions.
7129  *
7130  * One example is end of transaction, so we must wait for any transactions
7131  * that are currently in commit critical sections. If an xact inserted
7132  * its commit record into XLOG just before the REDO point, then a crash
7133  * restart from the REDO point would not replay that record, which means
7134  * that our flushing had better include the xact's update of pg_xact. So
7135  * we wait till he's out of his commit critical section before proceeding.
7136  * See notes in RecordTransactionCommit().
7137  *
7138  * Because we've already released the insertion locks, this test is a bit
7139  * fuzzy: it is possible that we will wait for xacts we didn't really need
7140  * to wait for. But the delay should be short and it seems better to make
7141  * checkpoint take a bit longer than to hold off insertions longer than
7142  * necessary. (In fact, the whole reason we have this issue is that xact.c
7143  * does commit record XLOG insertion and clog update as two separate steps
7144  * protected by different locks, but again that seems best on grounds of
7145  * minimizing lock contention.)
7146  *
7147  * A transaction that has not yet set delayChkptFlags when we look cannot
7148  * be at risk, since it has not inserted its commit record yet; and one
7149  * that's already cleared it is not at risk either, since it's done fixing
7150  * clog and we will correctly flush the update below. So we cannot miss
7151  * any xacts we need to wait for.
7152  */
7154  if (nvxids > 0)
7155  {
7156  do
7157  {
7158  /*
7159  * Keep absorbing fsync requests while we wait. There could even
7160  * be a deadlock if we don't, if the process that prevents the
7161  * checkpoint is trying to add a request to the queue.
7162  */
7164 
7165  pgstat_report_wait_start(WAIT_EVENT_CHECKPOINT_DELAY_START);
7166  pg_usleep(10000L); /* wait for 10 msec */
7168  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
7170  }
7171  pfree(vxids);
7172 
7173  CheckPointGuts(checkPoint.redo, flags);
7174 
7176  if (nvxids > 0)
7177  {
7178  do
7179  {
7181 
7182  pgstat_report_wait_start(WAIT_EVENT_CHECKPOINT_DELAY_COMPLETE);
7183  pg_usleep(10000L); /* wait for 10 msec */
7185  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
7187  }
7188  pfree(vxids);
7189 
7190  /*
7191  * Take a snapshot of running transactions and write this to WAL. This
7192  * allows us to reconstruct the state of running transactions during
7193  * archive recovery, if required. Skip, if this info disabled.
7194  *
7195  * If we are shutting down, or Startup process is completing crash
7196  * recovery we don't need to write running xact data.
7197  */
7198  if (!shutdown && XLogStandbyInfoActive())
7200 
7202 
7203  /*
7204  * Now insert the checkpoint record into XLOG.
7205  */
7206  XLogBeginInsert();
7207  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
7208  recptr = XLogInsert(RM_XLOG_ID,
7209  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
7211 
7212  XLogFlush(recptr);
7213 
7214  /*
7215  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
7216  * overwritten at next startup. No-one should even try, this just allows
7217  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
7218  * to just temporarily disable writing until the system has exited
7219  * recovery.
7220  */
7221  if (shutdown)
7222  {
7223  if (flags & CHECKPOINT_END_OF_RECOVERY)
7224  LocalXLogInsertAllowed = oldXLogAllowed;
7225  else
7226  LocalXLogInsertAllowed = 0; /* never again write WAL */
7227  }
7228 
7229  /*
7230  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
7231  * = end of actual checkpoint record.
7232  */
7233  if (shutdown && checkPoint.redo != ProcLastRecPtr)
7234  ereport(PANIC,
7235  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
7236 
7237  /*
7238  * Remember the prior checkpoint's redo ptr for
7239  * UpdateCheckPointDistanceEstimate()
7240  */
7241  PriorRedoPtr = ControlFile->checkPointCopy.redo;
7242 
7243  /*
7244  * Update the control file.
7245  */
7246  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7247  if (shutdown)
7250  ControlFile->checkPointCopy = checkPoint;
7251  /* crash recovery should always recover to the end of WAL */
7254 
7255  /*
7256  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
7257  * unused on non-shutdown checkpoints, but seems useful to store it always
7258  * for debugging purposes.
7259  */
7261 
7263  LWLockRelease(ControlFileLock);
7264 
7265  /* Update shared-memory copy of checkpoint XID/epoch */
7267  XLogCtl->ckptFullXid = checkPoint.nextXid;
7269 
7270  /*
7271  * We are now done with critical updates; no need for system panic if we
7272  * have trouble while fooling with old log segments.
7273  */
7274  END_CRIT_SECTION();
7275 
7276  /*
7277  * WAL summaries end when the next XLOG_CHECKPOINT_REDO or
7278  * XLOG_CHECKPOINT_SHUTDOWN record is reached. This is the first point
7279  * where (a) we're not inside of a critical section and (b) we can be
7280  * certain that the relevant record has been flushed to disk, which must
7281  * happen before it can be summarized.
7282  *
7283  * If this is a shutdown checkpoint, then this happens reasonably
7284  * promptly: we've only just inserted and flushed the
7285  * XLOG_CHECKPOINT_SHUTDOWN record. If this is not a shutdown checkpoint,
7286  * then this might not be very prompt at all: the XLOG_CHECKPOINT_REDO
7287  * record was written before we began flushing data to disk, and that
7288  * could be many minutes ago at this point. However, we don't XLogFlush()
7289  * after inserting that record, so we're not guaranteed that it's on disk
7290  * until after the above call that flushes the XLOG_CHECKPOINT_ONLINE
7291  * record.
7292  */
7294 
7295  /*
7296  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
7297  */
7299 
7300  /*
7301  * Update the average distance between checkpoints if the prior checkpoint
7302  * exists.
7303  */
7304  if (PriorRedoPtr != InvalidXLogRecPtr)
7306 
7307  /*
7308  * Delete old log files, those no longer needed for last checkpoint to
7309  * prevent the disk holding the xlog from growing full.
7310  */
7312  KeepLogSeg(recptr, &_logSegNo);
7314  _logSegNo, InvalidOid,
7316  {
7317  /*
7318  * Some slots have been invalidated; recalculate the old-segment
7319  * horizon, starting again from RedoRecPtr.
7320  */
7322  KeepLogSeg(recptr, &_logSegNo);
7323  }
7324  _logSegNo--;
7325  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
7326  checkPoint.ThisTimeLineID);
7327 
7328  /*
7329  * Make more log segments if needed. (Do this after recycling old log
7330  * segments, since that may supply some of the needed files.)
7331  */
7332  if (!shutdown)
7333  PreallocXlogFiles(recptr, checkPoint.ThisTimeLineID);
7334 
7335  /*
7336  * Truncate pg_subtrans if possible. We can throw away all data before
7337  * the oldest XMIN of any running transaction. No future transaction will
7338  * attempt to reference any pg_subtrans entry older than that (see Asserts
7339  * in subtrans.c). During recovery, though, we mustn't do this because
7340  * StartupSUBTRANS hasn't been called yet.
7341  */
7342  if (!RecoveryInProgress())
7344 
7345  /* Real work is done; log and update stats. */
7346  LogCheckpointEnd(false);
7347 
7348  /* Reset the process title */
7349  update_checkpoint_display(flags, false, true);
7350 
7351  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
7352  NBuffers,
7356 }
static uint64 pg_atomic_read_membarrier_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:476
void AbsorbSyncRequests(void)
int NBuffers
Definition: globals.c:141
@ LW_SHARED
Definition: lwlock.h:115
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2282
#define XLOG_CHECKPOINT_REDO
Definition: pg_control.h:82
@ DB_SHUTDOWNING
Definition: pg_control.h:94
@ DB_SHUTDOWNED
Definition: pg_control.h:92
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:69
#define InvalidOid
Definition: postgres_ext.h:36
#define DELAY_CHKPT_START
Definition: proc.h:114
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:115
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
Definition: procarray.c:3047
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2884
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:2034
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
Definition: procarray.c:3093
void pg_usleep(long microsec)
Definition: signal.c:53
bool InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, XLogSegNo oldestSegno, Oid dboid, TransactionId snapshotConflictHorizon)
Definition: slot.c:1811
@ RS_INVAL_WAL_REMOVED
Definition: slot.h:54
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:1285
TimestampTz ckpt_start_t
Definition: xlog.h:161
int ckpt_segs_removed
Definition: xlog.h:170
int ckpt_segs_added
Definition: xlog.h:169
int ckpt_bufs_written
Definition: xlog.h:167
int ckpt_segs_recycled
Definition: xlog.h:171
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:168
XLogRecPtr unloggedLSN
Definition: pg_control.h:137
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:169
TransactionId oldestCommitTsXid
Definition: transam.h:232
TransactionId newestCommitTsXid
Definition: transam.h:233
TransactionId oldestXid
Definition: transam.h:222
FullTransactionId ckptFullXid
Definition: xlog.c:456
TimeLineID InsertTimeLineID
Definition: xlog.c:508
XLogRecPtr RedoRecPtr
Definition: xlog.c:455
TimeLineID PrevTimeLineID
Definition: xlog.c:509
pg_atomic_uint64 unloggedLSN
Definition: xlog.c:463
XLogRecPtr RedoRecPtr
Definition: xlog.c:429
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:411
void SyncPreCheckpoint(void)
Definition: sync.c:177
void SyncPostCheckpoint(void)
Definition: sync.c:202
void SetWalSummarizerLatch(void)
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:252
bool RecoveryInProgress(void)
Definition: xlog.c:6333
static void WALInsertLockRelease(void)
Definition: xlog.c:1444
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1857
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1415
static void UpdateControlFile(void)
Definition: xlog.c:4552
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr, TimeLineID insertTLI)
Definition: xlog.c:3858
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:6648
static XLogRecPtr RedoRecPtr
Definition: xlog.c:272
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:6680
static void PreallocXlogFiles(XLogRecPtr endptr, TimeLineID tli)
Definition: xlog.c:3683
bool log_checkpoints
Definition: xlog.c:128
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:7945
static int LocalSetXLogInsertAllowed(void)
Definition: xlog.c:6421
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:6555
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:6783
static int LocalXLogInsertAllowed
Definition: xlog.c:235
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2795
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:7502
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:6821
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:140
#define CHECKPOINT_FORCE
Definition: xlog.h:142
#define XLogStandbyInfoActive()
Definition: xlog.h:123
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const char *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149

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

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

◆ CreateEndOfRecoveryRecord()

static void CreateEndOfRecoveryRecord ( void  )
static

Definition at line 7367 of file xlog.c.

7368 {
7369  xl_end_of_recovery xlrec;
7370  XLogRecPtr recptr;
7371 
7372  /* sanity check */
7373  if (!RecoveryInProgress())
7374  elog(ERROR, "can only be used to end recovery");
7375 
7376  xlrec.end_time = GetCurrentTimestamp();
7377  xlrec.wal_level = wal_level;
7378 
7383 
7385 
7386  XLogBeginInsert();
7387  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
7388  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
7389 
7390  XLogFlush(recptr);
7391 
7392  /*
7393  * Update the control file so that crash recovery can follow the timeline
7394  * changes to this point.
7395  */
7396  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7397  ControlFile->minRecoveryPoint = recptr;
7398  ControlFile->minRecoveryPointTLI = xlrec.ThisTimeLineID;
7400  LWLockRelease(ControlFileLock);
7401 
7402  END_CRIT_SECTION();
7403 }
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:77
TimeLineID PrevTimeLineID
TimestampTz end_time
TimeLineID ThisTimeLineID

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

Referenced by PerformRecoveryXLogAction().

◆ CreateOverwriteContrecordRecord()

static XLogRecPtr CreateOverwriteContrecordRecord ( XLogRecPtr  aborted_lsn,
XLogRecPtr  pagePtr,
TimeLineID  newTLI 
)
static

Definition at line 7432 of file xlog.c.

7434 {
7436  XLogRecPtr recptr;
7437  XLogPageHeader pagehdr;
7438  XLogRecPtr startPos;
7439 
7440  /* sanity checks */
7441  if (!RecoveryInProgress())
7442  elog(ERROR, "can only be used at end of recovery");
7443  if (pagePtr % XLOG_BLCKSZ != 0)
7444  elog(ERROR, "invalid position for missing continuation record %X/%X",
7445  LSN_FORMAT_ARGS(pagePtr));
7446 
7447  /* The current WAL insert position should be right after the page header */
7448  startPos = pagePtr;
7449  if (XLogSegmentOffset(startPos, wal_segment_size) == 0)
7450  startPos += SizeOfXLogLongPHD;
7451  else
7452  startPos += SizeOfXLogShortPHD;
7453  recptr = GetXLogInsertRecPtr();
7454  if (recptr != startPos)
7455  elog(ERROR, "invalid WAL insert position %X/%X for OVERWRITE_CONTRECORD",
7456  LSN_FORMAT_ARGS(recptr));
7457 
7459 
7460  /*
7461  * Initialize the XLOG page header (by GetXLogBuffer), and set the
7462  * XLP_FIRST_IS_OVERWRITE_CONTRECORD flag.
7463  *
7464  * No other backend is allowed to write WAL yet, so acquiring the WAL
7465  * insertion lock is just pro forma.
7466  */
7468  pagehdr = (XLogPageHeader) GetXLogBuffer(pagePtr, newTLI);
7471 
7472  /*
7473  * Insert the XLOG_OVERWRITE_CONTRECORD record as the first record on the
7474  * page. We know it becomes the first record, because no other backend is
7475  * allowed to write WAL yet.
7476  */
7477  XLogBeginInsert();
7478  xlrec.overwritten_lsn = aborted_lsn;
7480  XLogRegisterData((char *) &xlrec, sizeof(xl_overwrite_contrecord));
7481  recptr = XLogInsert(RM_XLOG_ID, XLOG_OVERWRITE_CONTRECORD);
7482 
7483  /* check that the record was inserted to the right place */
7484  if (ProcLastRecPtr != startPos)
7485  elog(ERROR, "OVERWRITE_CONTRECORD was inserted to unexpected position %X/%X",
7487 
7488  XLogFlush(recptr);
7489 
7490  END_CRIT_SECTION();
7491 
7492  return recptr;
7493 }
#define XLOG_OVERWRITE_CONTRECORD
Definition: pg_control.h:81
static void WALInsertLockAcquire(void)
Definition: xlog.c:1370
XLogRecPtr GetXLogInsertRecPtr(void)
Definition: xlog.c:9427
#define XLP_FIRST_IS_OVERWRITE_CONTRECORD
Definition: xlog_internal.h:80

References elog, END_CRIT_SECTION, ERROR, GetCurrentTimestamp(), GetXLogBuffer(), GetXLogInsertRecPtr(), LSN_FORMAT_ARGS, xl_overwrite_contrecord::overwrite_time, xl_overwrite_contrecord::overwritten_lsn, ProcLastRecPtr, RecoveryInProgress(), SizeOfXLogLongPHD, SizeOfXLogShortPHD, START_CRIT_SECTION, wal_segment_size, WALInsertLockAcquire(), WALInsertLockRelease(), XLOG_OVERWRITE_CONTRECORD, XLogBeginInsert(), XLogFlush(), XLogInsert(), XLogRegisterData(), XLogSegmentOffset, XLP_FIRST_IS_OVERWRITE_CONTRECORD, and XLogPageHeaderData::xlp_info.

Referenced by StartupXLOG().

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 7583 of file xlog.c.

7584 {
7585  XLogRecPtr lastCheckPointRecPtr;
7586  XLogRecPtr lastCheckPointEndPtr;
7587  CheckPoint lastCheckPoint;
7588  XLogRecPtr PriorRedoPtr;
7589  XLogRecPtr receivePtr;
7590  XLogRecPtr replayPtr;
7591  TimeLineID replayTLI;
7592  XLogRecPtr endptr;
7593  XLogSegNo _logSegNo;
7594  TimestampTz xtime;
7595 
7596  /* Concurrent checkpoint/restartpoint cannot happen */
7598 
7599  /* Get a local copy of the last safe checkpoint record. */
7601  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
7602  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
7603  lastCheckPoint = XLogCtl->lastCheckPoint;
7605 
7606  /*
7607  * Check that we're still in recovery mode. It's ok if we exit recovery
7608  * mode after this check, the restart point is valid anyway.
7609  */
7610  if (!RecoveryInProgress())
7611  {
7612  ereport(DEBUG2,
7613  (errmsg_internal("skipping restartpoint, recovery has already ended")));
7614  return false;
7615  }
7616 
7617  /*
7618  * If the last checkpoint record we've replayed is already our last
7619  * restartpoint, we can't perform a new restart point. We still update
7620  * minRecoveryPoint in that case, so that if this is a shutdown restart
7621  * point, we won't start up earlier than before. That's not strictly
7622  * necessary, but when hot standby is enabled, it would be rather weird if
7623  * the database opened up for read-only connections at a point-in-time
7624  * before the last shutdown. Such time travel is still possible in case of
7625  * immediate shutdown, though.
7626  *
7627  * We don't explicitly advance minRecoveryPoint when we do create a
7628  * restartpoint. It's assumed that flushing the buffers will do that as a
7629  * side-effect.
7630  */
7631  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
7632  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
7633  {
7634  ereport(DEBUG2,
7635  (errmsg_internal("skipping restartpoint, already performed at %X/%X",
7636  LSN_FORMAT_ARGS(lastCheckPoint.redo))));
7637 
7639  if (flags & CHECKPOINT_IS_SHUTDOWN)
7640  {
7641  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7644  LWLockRelease(ControlFileLock);
7645  }
7646  return false;
7647  }
7648 
7649  /*
7650  * Update the shared RedoRecPtr so that the startup process can calculate
7651  * the number of segments replayed since last restartpoint, and request a
7652  * restartpoint if it exceeds CheckPointSegments.
7653  *
7654  * Like in CreateCheckPoint(), hold off insertions to update it, although
7655  * during recovery this is just pro forma, because no WAL insertions are
7656  * happening.
7657  */
7659  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
7661 
7662  /* Also update the info_lck-protected copy */
7664  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
7666 
7667  /*
7668  * Prepare to accumulate statistics.
7669  *
7670  * Note: because it is possible for log_checkpoints to change while a
7671  * checkpoint proceeds, we always accumulate stats, even if
7672  * log_checkpoints is currently off.
7673  */
7674  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
7676 
7677  if (log_checkpoints)
7678  LogCheckpointStart(flags, true);
7679 
7680  /* Update the process title */
7681  update_checkpoint_display(flags, true, false);
7682 
7683  CheckPointGuts(lastCheckPoint.redo, flags);
7684 
7685  /*
7686  * This location needs to be after CheckPointGuts() to ensure that some
7687  * work has already happened during this checkpoint.
7688  */
7689  INJECTION_POINT("create-restart-point");
7690 
7691  /*
7692  * Remember the prior checkpoint's redo ptr for
7693  * UpdateCheckPointDistanceEstimate()
7694  */
7695  PriorRedoPtr = ControlFile->checkPointCopy.redo;
7696 
7697  /*
7698  * Update pg_control, using current time. Check that it still shows an
7699  * older checkpoint, else do nothing; this is a quick hack to make sure
7700  * nothing really bad happens if somehow we get here after the
7701  * end-of-recovery checkpoint.
7702  */
7703  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7704  if (ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
7705  {
7706  /*
7707  * Update the checkpoint information. We do this even if the cluster
7708  * does not show DB_IN_ARCHIVE_RECOVERY to match with the set of WAL
7709  * segments recycled below.
7710  */
7711  ControlFile->checkPoint = lastCheckPointRecPtr;
7712  ControlFile->checkPointCopy = lastCheckPoint;
7713 
7714  /*
7715  * Ensure minRecoveryPoint is past the checkpoint record and update it
7716  * if the control file still shows DB_IN_ARCHIVE_RECOVERY. Normally,
7717  * this will have happened already while writing out dirty buffers,
7718  * but not necessarily - e.g. because no buffers were dirtied. We do
7719  * this because a backup performed in recovery uses minRecoveryPoint
7720  * to determine which WAL files must be included in the backup, and
7721  * the file (or files) containing the checkpoint record must be
7722  * included, at a minimum. Note that for an ordinary restart of
7723  * recovery there's no value in having the minimum recovery point any
7724  * earlier than this anyway, because redo will begin just after the
7725  * checkpoint record.
7726  */
7728  {
7729  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
7730  {
7731  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
7733 
7734  /* update local copy */
7737  }
7738  if (flags & CHECKPOINT_IS_SHUTDOWN)
7740  }
7742  }
7743  LWLockRelease(ControlFileLock);
7744 
7745  /*
7746  * Update the average distance between checkpoints/restartpoints if the
7747  * prior checkpoint exists.
7748  */
7749  if (PriorRedoPtr != InvalidXLogRecPtr)
7751 
7752  /*
7753  * Delete old log files, those no longer needed for last restartpoint to
7754  * prevent the disk holding the xlog from growing full.
7755  */
7757 
7758  /*
7759  * Retreat _logSegNo using the current end of xlog replayed or received,
7760  * whichever is later.
7761  */
7762  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
7763  replayPtr = GetXLogReplayRecPtr(&replayTLI);
7764  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
7765  KeepLogSeg(endptr, &_logSegNo);
7767  _logSegNo, InvalidOid,
7769  {
7770  /*
7771  * Some slots have been invalidated; recalculate the old-segment
7772  * horizon, starting again from RedoRecPtr.
7773  */
7775  KeepLogSeg(endptr, &_logSegNo);
7776  }
7777  _logSegNo--;
7778 
7779  /*
7780  * Try to recycle segments on a useful timeline. If we've been promoted
7781  * since the beginning of this restartpoint, use the new timeline chosen
7782  * at end of recovery. If we're still in recovery, use the timeline we're
7783  * currently replaying.
7784  *
7785  * There is no guarantee that the WAL segments will be useful on the
7786  * current timeline; if recovery proceeds to a new timeline right after
7787  * this, the pre-allocated WAL segments on this timeline will not be used,
7788  * and will go wasted until recycled on the next restartpoint. We'll live
7789  * with that.
7790  */
7791  if (!RecoveryInProgress())
7792  replayTLI = XLogCtl->InsertTimeLineID;
7793 
7794  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, replayTLI);
7795 
7796  /*
7797  * Make more log segments if needed. (Do this after recycling old log
7798  * segments, since that may supply some of the needed files.)
7799  */
7800  PreallocXlogFiles(endptr, replayTLI);
7801 
7802  /*
7803  * Truncate pg_subtrans if possible. We can throw away all data before
7804  * the oldest XMIN of any running transaction. No future transaction will
7805  * attempt to reference any pg_subtrans entry older than that (see Asserts
7806  * in subtrans.c). When hot standby is disabled, though, we mustn't do
7807  * this because StartupSUBTRANS hasn't been called yet.
7808  */
7809  if (EnableHotStandby)
7811 
7812  /* Real work is done; log and update stats. */
7813  LogCheckpointEnd(true);
7814 
7815  /* Reset the process title */
7816  update_checkpoint_display(flags, true, true);
7817 
7818  xtime = GetLatestXTime();
7820  (errmsg("recovery restart point at %X/%X",
7821  LSN_FORMAT_ARGS(lastCheckPoint.redo)),
7822  xtime ? errdetail("Last completed transaction was at log time %s.",
7823  timestamptz_to_str(xtime)) : 0));
7824 
7825  /*
7826  * Finally, execute archive_cleanup_command, if any.
7827  */
7828  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
7830  "archive_cleanup_command",
7831  false,
7832  WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND);
7833 
7834  return true;
7835 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1843
int64 TimestampTz
Definition: timestamp.h:39
#define LOG
Definition: elog.h:31
bool IsUnderPostmaster
Definition: globals.c:119
#define INJECTION_POINT(name)
@ B_CHECKPOINTER
Definition: miscadmin.h:354
BackendType MyBackendType
Definition: miscinit.c:63
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:96
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:93
CheckPoint lastCheckPoint
Definition: xlog.c:544
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:542
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:543
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2715
static XLogRecPtr LocalMinRecoveryPoint
Definition: xlog.c:645
static TimeLineID LocalMinRecoveryPointTLI
Definition: xlog.c:646
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint32 TimeLineID
Definition: xlogdefs.h:59
char * archiveCleanupCommand
Definition: xlogrecovery.c:85
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
TimestampTz GetLatestXTime(void)

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

Referenced by CheckpointerMain(), and ShutdownXLOG().

◆ DataChecksumsEnabled()

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

Definition at line 9386 of file xlog.c.

9387 {
9388  bool during_backup_start = DatumGetBool(arg);
9389 
9390  /* If called during backup start, there shouldn't be one already running */
9391  Assert(!during_backup_start || sessionBackupState == SESSION_BACKUP_NONE);
9392 
9393  if (during_backup_start || sessionBackupState != SESSION_BACKUP_NONE)
9394  {
9398 
9401 
9402  if (!during_backup_start)
9403  ereport(WARNING,
9404  errmsg("aborting backup due to backend exiting before pg_backup_stop was called"));
9405  }
9406 }
#define WARNING
Definition: elog.h:36
void * arg
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
int runningBackups
Definition: xlog.c:437
static SessionBackupState sessionBackupState
Definition: xlog.c:390
@ SESSION_BACKUP_NONE
Definition: xlog.h:286

References arg, Assert, DatumGetBool(), ereport, errmsg(), XLogCtlData::Insert, XLogCtlInsert::runningBackups, SESSION_BACKUP_NONE, sessionBackupState, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, and XLogCtl.

Referenced by do_pg_backup_start(), perform_base_backup(), and register_persistent_abort_backup_handler().

◆ do_pg_backup_start()

void do_pg_backup_start ( const char *  backupidstr,
bool  fast,
List **  tablespaces,
BackupState state,
StringInfo  tblspcmapfile 
)

Definition at line 8784 of file xlog.c.

8786 {
8788 
8789  Assert(state != NULL);
8791 
8792  /*
8793  * During recovery, we don't need to check WAL level. Because, if WAL
8794  * level is not sufficient, it's impossible to get here during recovery.
8795  */
8797  ereport(ERROR,
8798  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8799  errmsg("WAL level not sufficient for making an online backup"),
8800  errhint("\"wal_level\" must be set to \"replica\" or \"logical\" at server start.")));
8801 
8802  if (strlen(backupidstr) > MAXPGPATH)
8803  ereport(ERROR,
8804  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8805  errmsg("backup label too long (max %d bytes)",
8806  MAXPGPATH)));
8807 
8808  strlcpy(state->name, backupidstr, sizeof(state->name));
8809 
8810  /*
8811  * Mark backup active in shared memory. We must do full-page WAL writes
8812  * during an on-line backup even if not doing so at other times, because
8813  * it's quite possible for the backup dump to obtain a "torn" (partially
8814  * written) copy of a database page if it reads the page concurrently with
8815  * our write to the same page. This can be fixed as long as the first
8816  * write to the page in the WAL sequence is a full-page write. Hence, we
8817  * increment runningBackups then force a CHECKPOINT, to ensure there are
8818  * no dirty pages in shared memory that might get dumped while the backup
8819  * is in progress without having a corresponding WAL record. (Once the
8820  * backup is complete, we need not force full-page writes anymore, since
8821  * we expect that any pages not modified during the backup interval must
8822  * have been correctly captured by the backup.)
8823  *
8824  * Note that forcing full-page writes has no effect during an online
8825  * backup from the standby.
8826  *
8827  * We must hold all the insertion locks to change the value of
8828  * runningBackups, to ensure adequate interlocking against
8829  * XLogInsertRecord().
8830  */
8834 
8835  /*
8836  * Ensure we decrement runningBackups if we fail below. NB -- for this to
8837  * work correctly, it is critical that sessionBackupState is only updated
8838  * after this block is over.
8839  */
8841  {
8842  bool gotUniqueStartpoint = false;
8843  DIR *tblspcdir;
8844  struct dirent *de;
8845  tablespaceinfo *ti;
8846  int datadirpathlen;
8847 
8848  /*
8849  * Force an XLOG file switch before the checkpoint, to ensure that the
8850  * WAL segment the checkpoint is written to doesn't contain pages with
8851  * old timeline IDs. That would otherwise happen if you called
8852  * pg_backup_start() right after restoring from a PITR archive: the
8853  * first WAL segment containing the startup checkpoint has pages in
8854  * the beginning with the old timeline ID. That can cause trouble at
8855  * recovery: we won't have a history file covering the old timeline if
8856  * pg_wal directory was not included in the base backup and the WAL
8857  * archive was cleared too before starting the backup.
8858  *
8859  * This also ensures that we have emitted a WAL page header that has
8860  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
8861  * Therefore, if a WAL archiver (such as pglesslog) is trying to
8862  * compress out removable backup blocks, it won't remove any that
8863  * occur after this point.
8864  *
8865  * During recovery, we skip forcing XLOG file switch, which means that
8866  * the backup taken during recovery is not available for the special
8867  * recovery case described above.
8868  */
8870  RequestXLogSwitch(false);
8871 
8872  do
8873  {
8874  bool checkpointfpw;
8875 
8876  /*
8877  * Force a CHECKPOINT. Aside from being necessary to prevent torn
8878  * page problems, this guarantees that two successive backup runs
8879  * will have different checkpoint positions and hence different
8880  * history file names, even if nothing happened in between.
8881  *
8882  * During recovery, establish a restartpoint if possible. We use
8883  * the last restartpoint as the backup starting checkpoint. This
8884  * means that two successive backup runs can have same checkpoint
8885  * positions.
8886  *
8887  * Since the fact that we are executing do_pg_backup_start()
8888  * during recovery means that checkpointer is running, we can use
8889  * RequestCheckpoint() to establish a restartpoint.
8890  *
8891  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
8892  * passing fast = true). Otherwise this can take awhile.
8893  */
8895  (fast ? CHECKPOINT_IMMEDIATE : 0));
8896 
8897  /*
8898  * Now we need to fetch the checkpoint record location, and also
8899  * its REDO pointer. The oldest point in WAL that would be needed
8900  * to restore starting from the checkpoint is precisely the REDO
8901  * pointer.
8902  */
8903  LWLockAcquire(ControlFileLock, LW_SHARED);
8904  state->checkpointloc = ControlFile->checkPoint;
8905  state->startpoint = ControlFile->checkPointCopy.redo;
8907  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
8908  LWLockRelease(ControlFileLock);
8909 
8911  {
8912  XLogRecPtr recptr;
8913 
8914  /*
8915  * Check to see if all WAL replayed during online backup
8916  * (i.e., since last restartpoint used as backup starting
8917  * checkpoint) contain full-page writes.
8918  */
8920  recptr = XLogCtl->lastFpwDisableRecPtr;
8922 
8923  if (!checkpointfpw || state->startpoint <= recptr)
8924  ereport(ERROR,
8925  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8926  errmsg("WAL generated with \"full_page_writes=off\" was replayed "
8927  "since last restartpoint"),
8928  errhint("This means that the backup being taken on the standby "
8929  "is corrupt and should not be used. "
8930  "Enable \"full_page_writes\" and run CHECKPOINT on the primary, "
8931  "and then try an online backup again.")));
8932 
8933  /*
8934  * During recovery, since we don't use the end-of-backup WAL
8935  * record and don't write the backup history file, the
8936  * starting WAL location doesn't need to be unique. This means
8937  * that two base backups started at the same time might use
8938  * the same checkpoint as starting locations.
8939  */
8940  gotUniqueStartpoint = true;
8941  }
8942 
8943  /*
8944  * If two base backups are started at the same time (in WAL sender
8945  * processes), we need to make sure that they use different
8946  * checkpoints as starting locations, because we use the starting
8947  * WAL location as a unique identifier for the base backup in the
8948  * end-of-backup WAL record and when we write the backup history
8949  * file. Perhaps it would be better generate a separate unique ID
8950  * for each backup instead of forcing another checkpoint, but
8951  * taking a checkpoint right after another is not that expensive
8952  * either because only few buffers have been dirtied yet.
8953  */
8955  if (XLogCtl->Insert.lastBackupStart < state->startpoint)
8956  {
8957  XLogCtl->Insert.lastBackupStart = state->startpoint;
8958  gotUniqueStartpoint = true;
8959  }
8961  } while (!gotUniqueStartpoint);
8962 
8963  /*
8964  * Construct tablespace_map file.
8965  */
8966  datadirpathlen = strlen(DataDir);
8967 
8968  /* Collect information about all tablespaces */
8969  tblspcdir = AllocateDir(PG_TBLSPC_DIR);
8970  while ((de = ReadDir(tblspcdir, PG_TBLSPC_DIR)) != NULL)
8971  {
8972  char fullpath[MAXPGPATH + sizeof(PG_TBLSPC_DIR)];
8973  char linkpath[MAXPGPATH];
8974  char *relpath = NULL;
8975  char *s;
8976  PGFileType de_type;
8977  char *badp;
8978  Oid tsoid;
8979 
8980  /*
8981  * Try to parse the directory name as an unsigned integer.
8982  *
8983  * Tablespace directories should be positive integers that can be
8984  * represented in 32 bits, with no leading zeroes or trailing
8985  * garbage. If we come across a name that doesn't meet those
8986  * criteria, skip it.
8987  */
8988  if (de->d_name[0] < '1' || de->d_name[1] > '9')
8989  continue;
8990  errno = 0;
8991  tsoid = strtoul(de->d_name, &badp, 10);
8992  if (*badp != '\0' || errno == EINVAL || errno == ERANGE)
8993  continue;
8994 
8995  snprintf(fullpath, sizeof(fullpath), "%s/%s", PG_TBLSPC_DIR, de->d_name);
8996 
8997  de_type = get_dirent_type(fullpath, de, false, ERROR);
8998 
8999  if (de_type == PGFILETYPE_LNK)
9000  {
9001  StringInfoData escapedpath;
9002  int rllen;
9003 
9004  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
9005  if (rllen < 0)
9006  {
9007  ereport(WARNING,
9008  (errmsg("could not read symbolic link \"%s\": %m",
9009  fullpath)));
9010  continue;
9011  }
9012  else if (rllen >= sizeof(linkpath))
9013  {
9014  ereport(WARNING,
9015  (errmsg("symbolic link \"%s\" target is too long",
9016  fullpath)));
9017  continue;
9018  }
9019  linkpath[rllen] = '\0';
9020 
9021  /*
9022  * Relpath holds the relative path of the tablespace directory
9023  * when it's located within PGDATA, or NULL if it's located
9024  * elsewhere.
9025  */
9026  if (rllen > datadirpathlen &&
9027  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
9028  IS_DIR_SEP(linkpath[datadirpathlen]))
9029  relpath = pstrdup(linkpath + datadirpathlen + 1);
9030 
9031  /*
9032  * Add a backslash-escaped version of the link path to the
9033  * tablespace map file.
9034  */
9035  initStringInfo(&escapedpath);
9036  for (s = linkpath; *s; s++)
9037  {
9038  if (*s == '\n' || *s == '\r' || *s == '\\')
9039  appendStringInfoChar(&escapedpath, '\\');
9040  appendStringInfoChar(&escapedpath, *s);
9041  }
9042  appendStringInfo(tblspcmapfile, "%s %s\n",
9043  de->d_name, escapedpath.data);
9044  pfree(escapedpath.data);
9045  }
9046  else if (de_type == PGFILETYPE_DIR)
9047  {
9048  /*
9049  * It's possible to use allow_in_place_tablespaces to create
9050  * directories directly under pg_tblspc, for testing purposes
9051  * only.
9052  *
9053  * In this case, we store a relative path rather than an
9054  * absolute path into the tablespaceinfo.
9055  */
9056  snprintf(linkpath, sizeof(linkpath), "%s/%s",
9057  PG_TBLSPC_DIR, de->d_name);
9058  relpath = pstrdup(linkpath);
9059  }
9060  else
9061  {
9062  /* Skip any other file type that appears here. */
9063  continue;
9064  }
9065 
9066  ti = palloc(sizeof(tablespaceinfo));
9067  ti->oid = tsoid;
9068  ti->path = pstrdup(linkpath);
9069  ti->rpath = relpath;
9070  ti->size = -1;
9071 
9072  if (tablespaces)
9073  *tablespaces = lappend(*tablespaces, ti);
9074  }
9075  FreeDir(tblspcdir);
9076 
9077  state->starttime = (pg_time_t) time(NULL);
9078  }
9080 
9081  state->started_in_recovery = backup_started_in_recovery;
9082 
9083  /*
9084  * Mark that the start phase has correctly finished for the backup.
9085  */
9087 }
static bool backup_started_in_recovery
Definition: basebackup.c:124
void RequestCheckpoint(int flags)
Definition: checkpointer.c:941
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:526
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_LNK
Definition: file_utils.h:24
@ PGFILETYPE_DIR
Definition: file_utils.h:23
char * DataDir
Definition: globals.c:70
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
List * lappend(List *list, void *datum)
Definition: list.c:339
#define IS_DIR_SEP(ch)
Definition: port.h:102
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
unsigned int Oid
Definition: postgres_ext.h:31
#define relpath(rlocator, forknum)
Definition: relpath.h:102
#define PG_TBLSPC_DIR
Definition: relpath.h:41
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:550
XLogRecPtr lastBackupStart
Definition: xlog.c:438
Definition: regguts.h:323
char * rpath
Definition: basebackup.h:32
#define readlink(path, buf, size)
Definition: win32_port.h:236
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:8052
void do_pg_abort_backup(int code, Datum arg)
Definition: xlog.c:9386
@ SESSION_BACKUP_RUNNING
Definition: xlog.h:287
#define CHECKPOINT_WAIT
Definition: xlog.h:145
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:141
#define XLogIsNeeded()
Definition: xlog.h:109

References AllocateDir(), appendStringInfo(), appendStringInfoChar(), Assert, backup_started_in_recovery, ControlFileData::checkPoint, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, ControlFileData::checkPointCopy, ControlFile, dirent::d_name, StringInfoData::data, DataDir, DatumGetBool(), do_pg_abort_backup(), ereport, errcode(), errhint(), errmsg(), ERROR, FreeDir(), CheckPoint::fullPageWrites, get_dirent_type(), XLogCtlData::info_lck, initStringInfo(), XLogCtlData::Insert, IS_DIR_SEP, lappend(), XLogCtlInsert::lastBackupStart, XLogCtlData::lastFpwDisableRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXPGPATH, tablespaceinfo::oid, palloc(), tablespaceinfo::path, pfree(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, PG_TBLSPC_DIR, PGFILETYPE_DIR, PGFILETYPE_LNK, pstrdup(), ReadDir(), readlink, RecoveryInProgress(), CheckPoint::redo, relpath, RequestCheckpoint(), RequestXLogSwitch(), tablespaceinfo::rpath, XLogCtlInsert::runningBackups, SESSION_BACKUP_RUNNING, sessionBackupState, tablespaceinfo::size, snprintf, SpinLockAcquire, SpinLockRelease, strlcpy(), CheckPoint::ThisTimeLineID, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, XLogCtl, and XLogIsNeeded.

Referenced by perform_base_backup(), and pg_backup_start().

◆ do_pg_backup_stop()

void do_pg_backup_stop ( BackupState state,
bool  waitforarchive 
)

Definition at line 9112 of file xlog.c.

9113 {
9114  bool backup_stopped_in_recovery = false;
9115  char histfilepath[MAXPGPATH];
9116  char lastxlogfilename[MAXFNAMELEN];
9117  char histfilename[MAXFNAMELEN];
9118  XLogSegNo _logSegNo;
9119  FILE *fp;
9120  int seconds_before_warning;
9121  int waits = 0;
9122  bool reported_waiting = false;
9123 
9124  Assert(state != NULL);
9125 
9126  backup_stopped_in_recovery = RecoveryInProgress();
9127 
9128  /*
9129  * During recovery, we don't need to check WAL level. Because, if WAL
9130  * level is not sufficient, it's impossible to get here during recovery.
9131  */
9132  if (!backup_stopped_in_recovery && !XLogIsNeeded())
9133  ereport(ERROR,
9134  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
9135  errmsg("WAL level not sufficient for making an online backup"),
9136  errhint("\"wal_level\" must be set to \"replica\" or \"logical\" at server start.")));
9137 
9138  /*
9139  * OK to update backup counter and session-level lock.
9140  *
9141  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them,
9142  * otherwise they can be updated inconsistently, which might cause
9143  * do_pg_abort_backup() to fail.
9144  */
9146 
9147  /*
9148  * It is expected that each do_pg_backup_start() call is matched by
9149  * exactly one do_pg_backup_stop() call.
9150  */
9153 
9154  /*
9155  * Clean up session-level lock.
9156  *
9157  * You might think that WALInsertLockRelease() can be called before
9158  * cleaning up session-level lock because session-level lock doesn't need
9159  * to be protected with WAL insertion lock. But since
9160  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
9161  * cleaned up before it.
9162  */
9164 
9166 
9167  /*
9168  * If we are taking an online backup from the standby, we confirm that the
9169  * standby has not been promoted during the backup.
9170  */
9171  if (state->started_in_recovery && !backup_stopped_in_recovery)
9172  ereport(ERROR,
9173  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
9174  errmsg("the standby was promoted during online backup"),
9175  errhint("This means that the backup being taken is corrupt "
9176  "and should not be used. "
9177  "Try taking another online backup.")));
9178 
9179  /*
9180  * During recovery, we don't write an end-of-backup record. We assume that
9181  * pg_control was backed up last and its minimum recovery point can be
9182  * available as the backup end location. Since we don't have an
9183  * end-of-backup record, we use the pg_control value to check whether
9184  * we've reached the end of backup when starting recovery from this
9185  * backup. We have no way of checking if pg_control wasn't backed up last
9186  * however.
9187  *
9188  * We don't force a switch to new WAL file but it is still possible to
9189  * wait for all the required files to be archived if waitforarchive is
9190  * true. This is okay if we use the backup to start a standby and fetch
9191  * the missing WAL using streaming replication. But in the case of an
9192  * archive recovery, a user should set waitforarchive to true and wait for
9193  * them to be archived to ensure that all the required files are
9194  * available.
9195  *
9196  * We return the current minimum recovery point as the backup end
9197  * location. Note that it can be greater than the exact backup end
9198  * location if the minimum recovery point is updated after the backup of
9199  * pg_control. This is harmless for current uses.
9200  *
9201  * XXX currently a backup history file is for informational and debug
9202  * purposes only. It's not essential for an online backup. Furthermore,
9203  * even if it's created, it will not be archived during recovery because
9204  * an archiver is not invoked. So it doesn't seem worthwhile to write a
9205  * backup history file during recovery.
9206  */
9207  if (backup_stopped_in_recovery)
9208  {
9209  XLogRecPtr recptr;
9210 
9211  /*
9212  * Check to see if all WAL replayed during online backup contain
9213  * full-page writes.
9214  */
9216  recptr = XLogCtl->lastFpwDisableRecPtr;
9218 
9219  if (state->startpoint <= recptr)
9220  ereport(ERROR,
9221  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
9222  errmsg("WAL generated with \"full_page_writes=off\" was replayed "
9223  "during online backup"),
9224  errhint("This means that the backup being taken on the standby "
9225  "is corrupt and should not be used. "
9226  "Enable \"full_page_writes\" and run CHECKPOINT on the primary, "
9227  "and then try an online backup again.")));
9228 
9229 
9230  LWLockAcquire(ControlFileLock, LW_SHARED);
9231  state->stoppoint = ControlFile->minRecoveryPoint;
9233  LWLockRelease(ControlFileLock);
9234  }
9235  else
9236  {
9237  char *history_file;
9238 
9239  /*
9240  * Write the backup-end xlog record
9241  */
9242  XLogBeginInsert();
9243  XLogRegisterData((char *) (&state->startpoint),
9244  sizeof(state->startpoint));
9245  state->stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
9246 
9247  /*
9248  * Given that we're not in recovery, InsertTimeLineID is set and can't
9249  * change, so we can read it without a lock.
9250  */
9251  state->stoptli = XLogCtl->InsertTimeLineID;
9252 
9253  /*
9254  * Force a switch to a new xlog segment file, so that the backup is
9255  * valid as soon as archiver moves out the current segment file.
9256  */
9257  RequestXLogSwitch(false);
9258 
9259  state->stoptime = (pg_time_t) time(NULL);
9260 
9261  /*
9262  * Write the backup history file
9263  */
9264  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
9265  BackupHistoryFilePath(histfilepath, state->stoptli, _logSegNo,
9266  state->startpoint, wal_segment_size);
9267  fp = AllocateFile(histfilepath, "w");
9268  if (!fp)
9269  ereport(ERROR,
9271  errmsg("could not create file \"%s\": %m",
9272  histfilepath)));
9273 
9274  /* Build and save the contents of the backup history file */
9275  history_file = build_backup_content(state, true);
9276  fprintf(fp, "%s", history_file);
9277  pfree(history_file);
9278 
9279  if (fflush(fp) || ferror(fp) || FreeFile(fp))
9280  ereport(ERROR,
9282  errmsg("could not write file \"%s\": %m",
9283  histfilepath)));
9284 
9285  /*
9286  * Clean out any no-longer-needed history files. As a side effect,
9287  * this will post a .ready file for the newly created history file,
9288  * notifying the archiver that history file may be archived
9289  * immediately.
9290  */
9292  }
9293 
9294  /*
9295  * If archiving is enabled, wait for all the required WAL files to be
9296  * archived before returning. If archiving isn't enabled, the required WAL
9297  * needs to be transported via streaming replication (hopefully with
9298  * wal_keep_size set high enough), or some more exotic mechanism like
9299  * polling and copying files from pg_wal with script. We have no knowledge
9300  * of those mechanisms, so it's up to the user to ensure that he gets all
9301  * the required WAL.
9302  *
9303  * We wait until both the last WAL file filled during backup and the
9304  * history file have been archived, and assume that the alphabetic sorting
9305  * property of the WAL files ensures any earlier WAL files are safely
9306  * archived as well.
9307  *
9308  * We wait forever, since archive_command is supposed to work and we
9309  * assume the admin wanted his backup to work completely. If you don't
9310  * wish to wait, then either waitforarchive should be passed in as false,
9311  * or you can set statement_timeout. Also, some notices are issued to
9312  * clue in anyone who might be doing this interactively.
9313  */
9314 
9315  if (waitforarchive &&
9316  ((!backup_stopped_in_recovery && XLogArchivingActive()) ||
9317  (backup_stopped_in_recovery && XLogArchivingAlways())))
9318  {
9319  XLByteToPrevSeg(state->stoppoint, _logSegNo, wal_segment_size);
9320  XLogFileName(lastxlogfilename, state->stoptli, _logSegNo,
9322 
9323  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
9324  BackupHistoryFileName(histfilename, state->stoptli, _logSegNo,
9325  state->startpoint, wal_segment_size);
9326 
9327  seconds_before_warning = 60;
9328  waits = 0;
9329 
9330  while (XLogArchiveIsBusy(lastxlogfilename) ||
9331  XLogArchiveIsBusy(histfilename))
9332  {
9334 
9335  if (!reported_waiting && waits > 5)
9336  {
9337  ereport(NOTICE,
9338  (errmsg("base backup done, waiting for required WAL segments to be archived")));
9339  reported_waiting = true;
9340  }
9341 
9342  (void) WaitLatch(MyLatch,
9344  1000L,
9345  WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE);
9347 
9348  if (++waits >= seconds_before_warning)
9349  {
9350  seconds_before_warning *= 2; /* This wraps in >10 years... */
9351  ereport(WARNING,
9352  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
9353  waits),
9354  errhint("Check that your \"archive_command\" is executing properly. "
9355  "You can safely cancel this backup, "
9356  "but the database backup will not be usable without all the WAL segments.")));
9357  }
9358  }
9359 
9360  ereport(NOTICE,
9361  (errmsg("all required WAL segments have been archived")));
9362  }
9363  else if (waitforarchive)
9364  ereport(NOTICE,
9365  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
9366 }
#define NOTICE
Definition: elog.h:35
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2606
int FreeFile(FILE *file)
Definition: fd.c:2804
struct Latch * MyLatch
Definition: globals.c:62
void ResetLatch(Latch *latch)
Definition: latch.c:724
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:517
#define WL_TIMEOUT
Definition: latch.h:130
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
#define WL_LATCH_SET
Definition: latch.h:127
static void const char fflush(stdout)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define XLOG_BACKUP_END
Definition: pg_control.h:73
#define fprintf
Definition: port.h:242
static void CleanupBackupHistory(void)
Definition: xlog.c:4154
#define XLogArchivingAlways()
Definition: xlog.h:102
static void BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
static void BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:619
char * build_backup_content(BackupState *state, bool ishistoryfile)
Definition: xlogbackup.c:29

References AllocateFile(), Assert, BackupHistoryFileName(), BackupHistoryFilePath(), build_backup_content(), CHECK_FOR_INTERRUPTS, CleanupBackupHistory(), ControlFile, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, fflush(), fprintf, FreeFile(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::InsertTimeLineID, XLogCtlData::lastFpwDisableRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXFNAMELEN, MAXPGPATH, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyLatch, NOTICE, pfree(), RecoveryInProgress(), RequestXLogSwitch(), ResetLatch(), XLogCtlInsert::runningBackups, SESSION_BACKUP_NONE, sessionBackupState, SpinLockAcquire, SpinLockRelease, WaitLatch(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, WL_TIMEOUT, XLByteToPrevSeg, XLByteToSeg, XLOG_BACKUP_END, XLogArchiveIsBusy(), XLogArchivingActive, XLogArchivingAlways, XLogBeginInsert(), XLogCtl, XLogFileName(), XLogInsert(), XLogIsNeeded, and XLogRegisterData().

Referenced by perform_base_backup(), and pg_backup_stop().

◆ get_backup_status()

SessionBackupState get_backup_status ( void  )

Definition at line 9093 of file xlog.c.

9094 {
9095  return sessionBackupState;
9096 }

References sessionBackupState.

Referenced by pg_backup_start(), pg_backup_stop(), and SendBaseBackup().

◆ get_sync_bit()

static int get_sync_bit ( int  method)
static

Definition at line 8585 of file xlog.c.

8586 {
8587  int o_direct_flag = 0;
8588 
8589  /*
8590  * Use O_DIRECT if requested, except in walreceiver process. The WAL
8591  * written by walreceiver is normally read by the startup process soon
8592  * after it's written. Also, walreceiver performs unaligned writes, which
8593  * don't work with O_DIRECT, so it is required for correctness too.
8594  */
8596  o_direct_flag = PG_O_DIRECT;
8597 
8598  /* If fsync is disabled, never open in sync mode */
8599  if (!enableFsync)
8600  return o_direct_flag;
8601 
8602  switch (method)
8603  {
8604  /*
8605  * enum values for all sync options are defined even if they are
8606  * not supported on the current platform. But if not, they are
8607  * not included in the enum option array, and therefore will never
8608  * be seen here.
8609  */
8610  case WAL_SYNC_METHOD_FSYNC:
8613  return o_direct_flag;
8614 #ifdef O_SYNC
8615  case WAL_SYNC_METHOD_OPEN:
8616  return O_SYNC | o_direct_flag;
8617 #endif
8618 #ifdef O_DSYNC
8620  return O_DSYNC | o_direct_flag;
8621 #endif
8622  default:
8623  /* can't happen (unless we are out of sync with option array) */
8624  elog(ERROR, "unrecognized \"wal_sync_method\": %d", method);
8625  return 0; /* silence warning */
8626  }
8627 }
int io_direct_flags
Definition: fd.c:168
#define IO_DIRECT_WAL
Definition: fd.h:55
#define PG_O_DIRECT
Definition: fd.h:97
bool enableFsync
Definition: globals.c:128
#define AmWalReceiverProcess()
Definition: miscadmin.h:380
#define O_DSYNC
Definition: win32_port.h:352
@ WAL_SYNC_METHOD_OPEN
Definition: xlog.h:26
@ WAL_SYNC_METHOD_FDATASYNC
Definition: xlog.h:25
@ WAL_SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:27
@ WAL_SYNC_METHOD_OPEN_DSYNC
Definition: xlog.h:28
@ WAL_SYNC_METHOD_FSYNC
Definition: xlog.h:24

References AmWalReceiverProcess, elog, enableFsync, ERROR, io_direct_flags, IO_DIRECT_WAL, O_DSYNC, PG_O_DIRECT, WAL_SYNC_METHOD_FDATASYNC, WAL_SYNC_METHOD_FSYNC, WAL_SYNC_METHOD_FSYNC_WRITETHROUGH, WAL_SYNC_METHOD_OPEN, and WAL_SYNC_METHOD_OPEN_DSYNC.

Referenced by assign_wal_sync_method(), XLogFileInit(), XLogFileInitInternal(), and XLogFileOpen().

◆ GetActiveWalLevelOnStandby()

WalLevel GetActiveWalLevelOnStandby ( void  )

Definition at line 4852 of file xlog.c.

4853 {
4854  return ControlFile->wal_level;
4855 }

References ControlFile, and ControlFileData::wal_level.

Referenced by CheckLogicalDecodingRequirements().

◆ GetFakeLSNForUnloggedRel()

XLogRecPtr GetFakeLSNForUnloggedRel ( void  )

Definition at line 4597 of file xlog.c.

4598 {
4600 }
static uint64 pg_atomic_fetch_add_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
Definition: atomics.h:522

References pg_atomic_fetch_add_u64(), XLogCtlData::unloggedLSN, and XLogCtl.

Referenced by gistGetFakeLSN().

◆ GetFlushRecPtr()

XLogRecPtr GetFlushRecPtr ( TimeLineID insertTLI)

Definition at line 6498 of file xlog.c.

6499 {
6501 
6503 
6504  /*
6505  * If we're writing and flushing WAL, the time line can't be changing, so
6506  * no lock is required.
6507  */
6508  if (insertTLI)
6509  *insertTLI = XLogCtl->InsertTimeLineID;
6510 
6511  return LogwrtResult.Flush;
6512 }
RecoveryState SharedRecoveryState
Definition: xlog.c:515
XLogRecPtr Flush
Definition: xlog.c:327
@ RECOVERY_STATE_DONE
Definition: xlog.h:93

References Assert, XLogwrtResult::Flush, XLogCtlData::InsertTimeLineID, LogwrtResult, RECOVERY_STATE_DONE, RefreshXLogWriteResult, XLogCtlData::SharedRecoveryState, and XLogCtl.

Referenced by binary_upgrade_logical_slot_has_caught_up(), get_flush_position(), GetCurrentLSN(), GetLatestLSN(), IdentifySystem(), pg_current_wal_flush_lsn(), pg_logical_slot_get_changes_guts(), pg_replication_slot_advance(), read_local_xlog_page_guts(), StartReplication(), WalSndWaitForWal(), XLogSendLogical(), and XLogSendPhysical().

◆ GetFullPageWriteInfo()

void GetFullPageWriteInfo ( XLogRecPtr RedoRecPtr_p,
bool doPageWrites_p 
)

Definition at line 6466 of file xlog.c.

6467 {
6468  *RedoRecPtr_p = RedoRecPtr;
6469  *doPageWrites_p = doPageWrites;
6470 }
static bool doPageWrites
Definition: xlog.c:285

References doPageWrites, and RedoRecPtr.

Referenced by XLogCheckBufferNeedsBackup(), and XLogInsert().

◆ GetInsertRecPtr()

XLogRecPtr GetInsertRecPtr ( void  )

Definition at line 6481 of file xlog.c.

6482 {
6483  XLogRecPtr recptr;
6484 
6486  recptr = XLogCtl->LogwrtRqst.Write;
6488 
6489  return recptr;
6490 }

References XLogCtlData::info_lck, XLogCtlData::LogwrtRqst, SpinLockAcquire, SpinLockRelease, XLogwrtRqst::Write, and XLogCtl.

Referenced by CheckpointerMain(), gistvacuumscan(), and IsCheckpointOnSchedule().

◆ GetLastImportantRecPtr()

XLogRecPtr GetLastImportantRecPtr ( void  )

Definition at line 6555 of file xlog.c.

6556 {
6558  int i;
6559 
6560  for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
6561  {
6562  XLogRecPtr last_important;
6563 
6564  /*
6565  * Need to take a lock to prevent torn reads of the LSN, which are
6566  * possible on some of the supported platforms. WAL insert locks only
6567  * support exclusive mode, so we have to use that.
6568  */
6570  last_important = WALInsertLocks[i].l.lastImportantAt;
6571  LWLockRelease(&WALInsertLocks[i].l.lock);
6572 
6573  if (res < last_important)
6574  res = last_important;
6575  }
6576 
6577  return res;
6578 }
int i
Definition: isn.c:73
XLogRecPtr lastImportantAt
Definition: xlog.c:370
WALInsertLock l
Definition: xlog.c:382
static WALInsertLockPadded * WALInsertLocks
Definition: xlog.c:568
#define NUM_XLOGINSERT_LOCKS
Definition: xlog.c:149

References i, InvalidXLogRecPtr, WALInsertLockPadded::l, WALInsertLock::lastImportantAt, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NUM_XLOGINSERT_LOCKS, res, and WALInsertLocks.

Referenced by BackgroundWriterMain(), CheckArchiveTimeout(), and CreateCheckPoint().

◆ GetLastSegSwitchData()

pg_time_t GetLastSegSwitchData ( XLogRecPtr lastSwitchLSN)

Definition at line 6584 of file xlog.c.

6585 {
6586  pg_time_t result;
6587 
6588  /* Need WALWriteLock, but shared lock is sufficient */
6589  LWLockAcquire(WALWriteLock, LW_SHARED);
6590  result = XLogCtl->lastSegSwitchTime;
6591  *lastSwitchLSN = XLogCtl->lastSegSwitchLSN;
6592  LWLockRelease(WALWriteLock);
6593 
6594  return result;
6595 }
pg_time_t lastSegSwitchTime
Definition: xlog.c:466
XLogRecPtr lastSegSwitchLSN
Definition: xlog.c:467

References XLogCtlData::lastSegSwitchLSN, XLogCtlData::lastSegSwitchTime, LW_SHARED, LWLockAcquire(), LWLockRelease(), and XLogCtl.

Referenced by CheckArchiveTimeout().

◆ GetMockAuthenticationNonce()

char* GetMockAuthenticationNonce ( void  )

Definition at line 4571 of file xlog.c.

4572 {
4573  Assert(ControlFile != NULL);
4575 }
char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]
Definition: pg_control.h:229

References Assert, ControlFile, and ControlFileData::mock_authentication_nonce.

Referenced by scram_mock_salt().

◆ GetOldestRestartPoint()

void GetOldestRestartPoint ( XLogRecPtr oldrecptr,
TimeLineID oldtli 
)

Definition at line 9455 of file xlog.c.

9456 {
9457  LWLockAcquire(ControlFileLock, LW_SHARED);
9458  *oldrecptr = ControlFile->checkPointCopy.redo;
9460  LWLockRelease(ControlFileLock);
9461 }

References ControlFileData::checkPointCopy, ControlFile, LW_SHARED, LWLockAcquire(), LWLockRelease(), CheckPoint::redo, and CheckPoint::ThisTimeLineID.

Referenced by ExecuteRecoveryCommand(), and RestoreArchivedFile().

◆ GetRecoveryState()

RecoveryState GetRecoveryState ( void  )

Definition at line 6369 of file xlog.c.

6370 {
6371  RecoveryState retval;
6372 
6374  retval = XLogCtl->SharedRecoveryState;
6376 
6377  return retval;
6378 }
RecoveryState
Definition: xlog.h:90

References XLogCtlData::info_lck, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by XLogArchiveCheckDone().

◆ GetRedoRecPtr()

XLogRecPtr GetRedoRecPtr ( void  )

Definition at line 6436 of file xlog.c.

6437 {
6438  XLogRecPtr ptr;
6439 
6440  /*
6441  * The possibly not up-to-date copy in XlogCtl is enough. Even if we
6442  * grabbed a WAL insertion lock to read the authoritative value in
6443  * Insert->RedoRecPtr, someone might update it just after we've released
6444  * the lock.
6445  */
6447  ptr = XLogCtl->RedoRecPtr;
6449 
6450  if (RedoRecPtr < ptr)
6451  RedoRecPtr = ptr;
6452 
6453  return RedoRecPtr;
6454 }

References XLogCtlData::info_lck, RedoRecPtr, XLogCtlData::RedoRecPtr, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), MaybeRemoveOldWalSummaries(), nextval_internal(), pgstat_before_server_shutdown(), ReplicationSlotReserveWal(), smgr_bulk_finish(), smgr_bulk_start_smgr(), XLogPageRead(), XLogSaveBufferForHint(), and XLogWrite().

◆ GetSystemIdentifier()

uint64 GetSystemIdentifier ( void  )

◆ GetWALAvailability()

WALAvailability GetWALAvailability ( XLogRecPtr  targetLSN)

Definition at line 7861 of file xlog.c.

7862 {
7863  XLogRecPtr currpos; /* current write LSN */
7864  XLogSegNo currSeg; /* segid of currpos */
7865  XLogSegNo targetSeg; /* segid of targetLSN */
7866  XLogSegNo oldestSeg; /* actual oldest segid */
7867  XLogSegNo oldestSegMaxWalSize; /* oldest segid kept by max_wal_size */
7868  XLogSegNo oldestSlotSeg; /* oldest segid kept by slot */
7869  uint64 keepSegs;
7870 
7871  /*
7872  * slot does not reserve WAL. Either deactivated, or has never been active
7873  */
7874  if (XLogRecPtrIsInvalid(targetLSN))
7875  return WALAVAIL_INVALID_LSN;
7876 
7877  /*
7878  * Calculate the oldest segment currently reserved by all slots,
7879  * considering wal_keep_size and max_slot_wal_keep_size. Initialize
7880  * oldestSlotSeg to the current segment.
7881  */
7882  currpos = GetXLogWriteRecPtr();
7883  XLByteToSeg(currpos, oldestSlotSeg, wal_segment_size);
7884  KeepLogSeg(currpos, &oldestSlotSeg);
7885 
7886  /*
7887  * Find the oldest extant segment file. We get 1 until checkpoint removes
7888  * the first WAL segment file since startup, which causes the status being
7889  * wrong under certain abnormal conditions but that doesn't actually harm.
7890  */
7891  oldestSeg = XLogGetLastRemovedSegno() + 1;
7892 
7893  /* calculate oldest segment by max_wal_size */
7894  XLByteToSeg(currpos, currSeg, wal_segment_size);
7896 
7897  if (currSeg > keepSegs)
7898  oldestSegMaxWalSize = currSeg - keepSegs;
7899  else
7900  oldestSegMaxWalSize = 1;
7901 
7902  /* the segment we care about */
7903  XLByteToSeg(targetLSN, targetSeg, wal_segment_size);
7904 
7905  /*
7906  * No point in returning reserved or extended status values if the
7907  * targetSeg is known to be lost.
7908  */
7909  if (targetSeg >= oldestSlotSeg)
7910  {
7911  /* show "reserved" when targetSeg is within max_wal_size */
7912  if (targetSeg >= oldestSegMaxWalSize)
7913  return WALAVAIL_RESERVED;
7914 
7915  /* being retained by slots exceeding max_wal_size */
7916  return WALAVAIL_EXTENDED;
7917  }
7918 
7919  /* WAL segments are no longer retained but haven't been removed yet */
7920  if (targetSeg >= oldestSeg)
7921  return WALAVAIL_UNRESERVED;
7922 
7923  /* Definitely lost */
7924  return WALAVAIL_REMOVED;
7925 }
XLogSegNo XLogGetLastRemovedSegno(void)
Definition: xlog.c:3751
XLogRecPtr GetXLogWriteRecPtr(void)
Definition: xlog.c:9443
@ WALAVAIL_REMOVED
Definition: xlog.h:193
@ WALAVAIL_RESERVED
Definition: xlog.h:189
@ WALAVAIL_UNRESERVED
Definition: xlog.h:192
@ WALAVAIL_EXTENDED
Definition: xlog.h:190
@ WALAVAIL_INVALID_LSN
Definition: xlog.h:188

References ConvertToXSegs, GetXLogWriteRecPtr(), KeepLogSeg(), max_wal_size_mb, wal_segment_size, WALAVAIL_EXTENDED, WALAVAIL_INVALID_LSN, WALAVAIL_REMOVED, WALAVAIL_RESERVED, WALAVAIL_UNRESERVED, XLByteToSeg, XLogGetLastRemovedSegno(), and XLogRecPtrIsInvalid.

Referenced by pg_get_replication_slots().

◆ GetWALInsertionTimeLine()

TimeLineID GetWALInsertionTimeLine ( void  )

Definition at line 6519 of file xlog.c.

6520 {
6522 
6523  /* Since the value can't be changing, no lock is required. */
6524  return XLogCtl->InsertTimeLineID;
6525 }

References Assert, XLogCtlData::InsertTimeLineID, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, and XLogCtl.

Referenced by logical_read_xlog_page(), pg_walfile_name(), pg_walfile_name_offset(), ReadReplicationSlot(), WALReadFromBuffers(), and XLogSendPhysical().

◆ GetWALInsertionTimeLineIfSet()

TimeLineID GetWALInsertionTimeLineIfSet ( void  )

Definition at line 6535 of file xlog.c.

6536 {
6537  TimeLineID insertTLI;
6538 
6540  insertTLI = XLogCtl->InsertTimeLineID;
6542 
6543  return insertTLI;
6544 }

References XLogCtlData::info_lck, XLogCtlData::InsertTimeLineID, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by GetLatestLSN().

◆ GetXLogBuffer()

static char * GetXLogBuffer ( XLogRecPtr  ptr,
TimeLineID  tli 
)
static

Definition at line 1631 of file xlog.c.

1632 {
1633  int idx;
1634  XLogRecPtr endptr;
1635  static uint64 cachedPage = 0;
1636  static char *cachedPos = NULL;
1637  XLogRecPtr expectedEndPtr;
1638 
1639  /*
1640  * Fast path for the common case that we need to access again the same
1641  * page as last time.
1642  */
1643  if (ptr / XLOG_BLCKSZ == cachedPage)
1644  {
1645  Assert(((XLogPageHeader) cachedPos)->xlp_magic == XLOG_PAGE_MAGIC);
1646  Assert(((XLogPageHeader) cachedPos)->xlp_pageaddr == ptr - (ptr % XLOG_BLCKSZ));
1647  return cachedPos + ptr % XLOG_BLCKSZ;
1648  }
1649 
1650  /*
1651  * The XLog buffer cache is organized so that a page is always loaded to a
1652  * particular buffer. That way we can easily calculate the buffer a given
1653  * page must be loaded into, from the XLogRecPtr alone.
1654  */
1655  idx = XLogRecPtrToBufIdx(ptr);
1656 
1657  /*
1658  * See what page is loaded in the buffer at the moment. It could be the
1659  * page we're looking for, or something older. It can't be anything newer
1660  * - that would imply the page we're looking for has already been written
1661  * out to disk and evicted, and the caller is responsible for making sure
1662  * that doesn't happen.
1663  *
1664  * We don't hold a lock while we read the value. If someone is just about
1665  * to initialize or has just initialized the page, it's possible that we
1666  * get InvalidXLogRecPtr. That's ok, we'll grab the mapping lock (in
1667  * AdvanceXLInsertBuffer) and retry if we see anything other than the page
1668  * we're looking for.
1669  */
1670  expectedEndPtr = ptr;
1671  expectedEndPtr += XLOG_BLCKSZ - ptr % XLOG_BLCKSZ;
1672 
1673  endptr = pg_atomic_read_u64(&XLogCtl->xlblocks[idx]);
1674  if (expectedEndPtr != endptr)
1675  {
1676  XLogRecPtr initializedUpto;
1677 
1678  /*
1679  * Before calling AdvanceXLInsertBuffer(), which can block, let others
1680  * know how far we're finished with inserting the record.
1681  *
1682  * NB: If 'ptr' points to just after the page header, advertise a
1683  * position at the beginning of the page rather than 'ptr' itself. If
1684  * there are no other insertions running, someone might try to flush
1685  * up to our advertised location. If we advertised a position after
1686  * the page header, someone might try to flush the page header, even
1687  * though page might actually not be initialized yet. As the first
1688  * inserter on the page, we are effectively responsible for making
1689  * sure that it's initialized, before we let insertingAt to move past
1690  * the page header.
1691  */
1692  if (ptr % XLOG_BLCKSZ == SizeOfXLogShortPHD &&
1693  XLogSegmentOffset(ptr, wal_segment_size) > XLOG_BLCKSZ)
1694  initializedUpto = ptr - SizeOfXLogShortPHD;
1695  else if (ptr % XLOG_BLCKSZ == SizeOfXLogLongPHD &&
1696  XLogSegmentOffset(ptr, wal_segment_size) < XLOG_BLCKSZ)
1697  initializedUpto = ptr - SizeOfXLogLongPHD;
1698  else
1699  initializedUpto = ptr;
1700 
1701  WALInsertLockUpdateInsertingAt(initializedUpto);
1702 
1703  AdvanceXLInsertBuffer(ptr, tli, false);
1704  endptr = pg_atomic_read_u64(&XLogCtl->xlblocks[idx]);
1705 
1706  if (expectedEndPtr != endptr)
1707  elog(PANIC, "could not find WAL buffer for %X/%X",
1708  LSN_FORMAT_ARGS(ptr));
1709  }
1710  else
1711  {
1712  /*
1713  * Make sure the initialization of the page is visible to us, and
1714  * won't arrive later to overwrite the WAL data we write on the page.
1715  */
1717  }
1718 
1719  /*
1720  * Found the buffer holding this page. Return a pointer to the right
1721  * offset within the page.
1722  */
1723  cachedPage = ptr / XLOG_BLCKSZ;
1724  cachedPos = XLogCtl->pages + idx * (Size) XLOG_BLCKSZ;
1725 
1726  Assert(((XLogPageHeader) cachedPos)->xlp_magic == XLOG_PAGE_MAGIC);
1727  Assert(((XLogPageHeader) cachedPos)->xlp_pageaddr == ptr - (ptr % XLOG_BLCKSZ));
1728 
1729  return cachedPos + ptr % XLOG_BLCKSZ;
1730 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
#define pg_memory_barrier()
Definition: atomics.h:143
static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt)
Definition: xlog.c:1470
static void AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic)
Definition: xlog.c:1984

References AdvanceXLInsertBuffer(), Assert, elog, idx(), LSN_FORMAT_ARGS, XLogCtlData::pages, PANIC, pg_atomic_read_u64(), pg_memory_barrier, SizeOfXLogLongPHD, SizeOfXLogShortPHD, wal_segment_size, WALInsertLockUpdateInsertingAt(), XLogCtlData::xlblocks, XLOG_PAGE_MAGIC, XLogCtl, XLogRecPtrToBufIdx, and XLogSegmentOffset.

Referenced by CopyXLogRecordToWAL(), and CreateOverwriteContrecordRecord().

◆ GetXLogInsertRecPtr()

XLogRecPtr GetXLogInsertRecPtr ( void  )

Definition at line 9427 of file xlog.c.

9428 {
9430  uint64 current_bytepos;
9431 
9432  SpinLockAcquire(&Insert->insertpos_lck);
9433  current_bytepos = Insert->CurrBytePos;
9434  SpinLockRelease(&Insert->insertpos_lck);
9435 
9436  return XLogBytePosToRecPtr(current_bytepos);
9437 }

References XLogCtlData::Insert, Insert(), SpinLockAcquire, SpinLockRelease, XLogBytePosToRecPtr(), and XLogCtl.

Referenced by CreateOverwriteContrecordRecord(), gistGetFakeLSN(), logical_begin_heap_rewrite(), pg_current_wal_insert_lsn(), and ReplicationSlotReserveWal().

◆ GetXLogWriteRecPtr()

XLogRecPtr GetXLogWriteRecPtr ( void  )

◆ InitControlFile()

static void InitControlFile ( uint64  sysidentifier,
uint32  data_checksum_version 
)
static

Definition at line 4197 of file xlog.c.

4198 {
4199  char mock_auth_nonce[MOCK_AUTH_NONCE_LEN];
4200 
4201  /*
4202  * Generate a random nonce. This is used for authentication requests that
4203  * will fail because the user does not exist. The nonce is used to create
4204  * a genuine-looking password challenge for the non-existent user, in lieu
4205  * of an actual stored password.
4206  */
4207  if (!pg_strong_random(mock_auth_nonce, MOCK_AUTH_NONCE_LEN))
4208  ereport(PANIC,
4209  (errcode(ERRCODE_INTERNAL_ERROR),
4210  errmsg("could not generate secret authorization token")));
4211 
4212  memset(ControlFile, 0, sizeof(ControlFileData));
4213  /* Initialize pg_control status fields */
4214  ControlFile->system_identifier = sysidentifier;
4215  memcpy(ControlFile->mock_authentication_nonce, mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
4218 
4219  /* Set important parameter values for use when replaying WAL */
4228  ControlFile->data_checksum_version = data_checksum_version;
4229 }
bool track_commit_timestamp
Definition: commit_ts.c:109
#define MOCK_AUTH_NONCE_LEN
Definition: pg_control.h:28
bool pg_strong_random(void *buf, size_t len)
bool track_commit_timestamp
Definition: pg_control.h:185
bool wal_log_hints
Definition: xlog.c:122
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36

References ControlFile, ControlFileData::data_checksum_version, DB_SHUTDOWNED, ereport, errcode(), errmsg(), FirstNormalUnloggedLSN, max_locks_per_xact, ControlFileData::max_locks_per_xact, max_prepared_xacts, ControlFileData::max_prepared_xacts, max_wal_senders, ControlFileData::max_wal_senders, max_worker_processes, ControlFileData::max_worker_processes, MaxConnections, ControlFileData::MaxConnections, MOCK_AUTH_NONCE_LEN, ControlFileData::mock_authentication_nonce, PANIC, pg_strong_random(), ControlFileData::state, ControlFileData::system_identifier, track_commit_timestamp, ControlFileData::track_commit_timestamp, ControlFileData::unloggedLSN, wal_level, ControlFileData::wal_level, wal_log_hints, and ControlFileData::wal_log_hints.

Referenced by BootStrapXLOG().

◆ InitializeWalConsistencyChecking()

void InitializeWalConsistencyChecking ( void  )

Definition at line 4777 of file xlog.c.

4778 {
4780 
4782  {
4783  struct config_generic *guc;
4784 
4785  guc = find_option("wal_consistency_checking", false, false, ERROR);
4786 
4788 
4789  set_config_option_ext("wal_consistency_checking",
4791  guc->scontext, guc->source, guc->srole,
4792  GUC_ACTION_SET, true, ERROR, false);
4793 
4794  /* checking should not be deferred again */
4796  }
4797 }
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
Definition: guc.c:1234
int set_config_option_ext(const char *name, const char *value, GucContext context, GucSource source, Oid srole, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3382
@ GUC_ACTION_SET
Definition: guc.h:199
GucContext scontext
Definition: guc_tables.h:167
GucSource source
Definition: guc_tables.h:165
char * wal_consistency_checking_string
Definition: xlog.c:124

References Assert, check_wal_consistency_checking_deferred, ERROR, find_option(), GUC_ACTION_SET, process_shared_preload_libraries_done, config_generic::scontext, set_config_option_ext(), config_generic::source, config_generic::srole, and wal_consistency_checking_string.

Referenced by PostgresSingleUserMain(), and PostmasterMain().

◆ InstallXLogFileSegment()

static bool InstallXLogFileSegment ( XLogSegNo segno,
char *  tmppath,
bool  find_free,
XLogSegNo  max_segno,
TimeLineID  tli 
)
static

Definition at line 3556 of file xlog.c.

3558 {
3559  char path[MAXPGPATH];
3560  struct stat stat_buf;
3561 
3562  Assert(tli != 0);
3563 
3564  XLogFilePath(path, tli, *segno, wal_segment_size);
3565 
3566  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
3568  {
3569  LWLockRelease(ControlFileLock);
3570  return false;
3571  }
3572 
3573  if (!find_free)
3574  {
3575  /* Force installation: get rid of any pre-existing segment file */
3576  durable_unlink(path, DEBUG1);
3577  }
3578  else
3579  {
3580  /* Find a free slot to put it in */
3581  while (stat(path, &stat_buf) == 0)
3582  {
3583  if ((*segno) >= max_segno)
3584  {
3585  /* Failed to find a free slot within specified range */
3586  LWLockRelease(ControlFileLock);
3587  return false;
3588  }
3589  (*segno)++;
3590  XLogFilePath(path, tli, *segno, wal_segment_size);
3591  }
3592  }
3593 
3594  Assert(access(path, F_OK) != 0 && errno == ENOENT);
3595  if (durable_rename(tmppath, path, LOG) != 0)
3596  {
3597  LWLockRelease(ControlFileLock);
3598  /* durable_rename already emitted log message */
3599  return false;
3600  }
3601 
3602  LWLockRelease(ControlFileLock);
3603 
3604  return true;
3605 }
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:872
short access
Definition: preproc-type.c:36
bool InstallXLogFileSegmentActive
Definition: xlog.c:525
#define stat
Definition: win32_port.h:284

References Assert, DEBUG1, durable_rename(), durable_unlink(), XLogCtlData::InstallXLogFileSegmentActive, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MAXPGPATH, stat, wal_segment_size, XLogCtl, and XLogFilePath().

Referenced by RemoveXlogFile(), XLogFileCopy(), and XLogFileInitInternal().

◆ IsInstallXLogFileSegmentActive()

bool IsInstallXLogFileSegmentActive ( void  )

Definition at line 9484 of file xlog.c.

9485 {
9486  bool result;
9487 
9488  LWLockAcquire(ControlFileLock, LW_SHARED);
9490  LWLockRelease(ControlFileLock);
9491 
9492  return result;
9493 }

References XLogCtlData::InstallXLogFileSegmentActive, LW_SHARED, LWLockAcquire(), LWLockRelease(), and XLogCtl.

Referenced by XLogFileRead().

◆ issue_xlog_fsync()

void issue_xlog_fsync ( int  fd,
XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 8675 of file xlog.c.

8676 {
8677  char *msg = NULL;
8678  instr_time start;
8679 
8680  Assert(tli != 0);
8681 
8682  /*
8683  * Quick exit if fsync is disabled or write() has already synced the WAL
8684  * file.
8685  */
8686  if (!enableFsync ||
8689  return;
8690 
8691  /* Measure I/O timing to sync the WAL file */
8692  if (track_wal_io_timing)
8694  else
8696 
8697  pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC);
8698  switch (wal_sync_method)
8699  {
8700  case WAL_SYNC_METHOD_FSYNC:
8701  if (pg_fsync_no_writethrough(fd) != 0)
8702  msg = _("could not fsync file \"%s\": %m");
8703  break;
8704 #ifdef HAVE_FSYNC_WRITETHROUGH
8706  if (pg_fsync_writethrough(fd) != 0)
8707  msg = _("could not fsync write-through file \"%s\": %m");
8708  break;
8709 #endif
8711  if (pg_fdatasync(fd) != 0)
8712  msg = _("could not fdatasync file \"%s\": %m");
8713  break;
8714  case WAL_SYNC_METHOD_OPEN:
8716  /* not reachable */
8717  Assert(false);
8718  break;
8719  default:
8720  ereport(PANIC,
8721  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8722  errmsg_internal("unrecognized \"wal_sync_method\": %d", wal_sync_method));
8723  break;
8724  }
8725 
8726  /* PANIC if failed to fsync */
8727  if (msg)
8728  {
8729  char xlogfname[MAXFNAMELEN];
8730  int save_errno = errno;
8731 
8732  XLogFileName(xlogfname, tli, segno, wal_segment_size);
8733  errno = save_errno;
8734  ereport(PANIC,
8736  errmsg(msg, xlogfname)));
8737  }
8738 
8740 
8741  /*
8742  * Increment the I/O timing and the number of times WAL files were synced.
8743  */
8744  if (track_wal_io_timing)
8745  {
8746  instr_time end;
8747 
8750  }
8751 
8753 }
#define _(x)
Definition: elog.c:90
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:441
int pg_fdatasync(int fd)
Definition: fd.c:480
int pg_fsync_writethrough(int fd)
Definition: fd.c:461
return str start
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:172
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:184
static int fd(const char *x, int i)
Definition: preproc-init.c:105
instr_time wal_sync_time
Definition: pgstat.h:489
PgStat_Counter wal_sync
Definition: pgstat.h:487
bool track_wal_io_timing
Definition: xlog.c:136

References _, Assert, enableFsync, ereport, errcode(), errcode_for_file_access(), errmsg(), errmsg_internal(), fd(), INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, INSTR_TIME_SET_ZERO, MAXFNAMELEN, PANIC, PendingWalStats, pg_fdatasync(), pg_fsync_no_writethrough(), pg_fsync_writethrough(), pgstat_report_wait_end(), pgstat_report_wait_start(), start, track_wal_io_timing, wal_segment_size, PgStat_PendingWalStats::wal_sync, wal_sync_method, WAL_SYNC_METHOD_FDATASYNC, WAL_SYNC_METHOD_FSYNC, WAL_SYNC_METHOD_FSYNC_WRITETHROUGH, WAL_SYNC_METHOD_OPEN, WAL_SYNC_METHOD_OPEN_DSYNC, PgStat_PendingWalStats::wal_sync_time, and XLogFileName().

Referenced by XLogWalRcvFlush(), and XLogWrite().

◆ KeepLogSeg()

static void KeepLogSeg ( XLogRecPtr  recptr,
XLogSegNo logSegNo 
)
static

Definition at line 7945 of file xlog.c.

7946 {
7947  XLogSegNo currSegNo;
7948  XLogSegNo segno;
7949  XLogRecPtr keep;
7950 
7951  XLByteToSeg(recptr, currSegNo, wal_segment_size);
7952  segno = currSegNo;
7953 
7954  /*
7955  * Calculate how many segments are kept by slots first, adjusting for
7956  * max_slot_wal_keep_size.
7957  */
7959  if (keep != InvalidXLogRecPtr && keep < recptr)
7960  {
7961  XLByteToSeg(keep, segno, wal_segment_size);
7962 
7963  /* Cap by max_slot_wal_keep_size ... */
7964  if (max_slot_wal_keep_size_mb >= 0)
7965  {
7966  uint64 slot_keep_segs;
7967 
7968  slot_keep_segs =
7970 
7971  if (currSegNo - segno > slot_keep_segs)
7972  segno = currSegNo - slot_keep_segs;
7973  }
7974  }
7975 
7976  /*
7977  * If WAL summarization is in use, don't remove WAL that has yet to be
7978  * summarized.
7979  */
7980  keep = GetOldestUnsummarizedLSN(NULL, NULL);
7981  if (keep != InvalidXLogRecPtr)
7982  {
7983  XLogSegNo unsummarized_segno;
7984 
7985  XLByteToSeg(keep, unsummarized_segno, wal_segment_size);
7986  if (unsummarized_segno < segno)
7987  segno = unsummarized_segno;
7988  }
7989 
7990  /* but, keep at least wal_keep_size if that's set */
7991  if (wal_keep_size_mb > 0)
7992  {
7993  uint64 keep_segs;
7994 
7996  if (currSegNo - segno < keep_segs)
7997  {
7998  /* avoid underflow, don't go below 1 */
7999  if (currSegNo <= keep_segs)
8000  segno = 1;
8001  else
8002  segno = currSegNo - keep_segs;
8003  }
8004  }
8005 
8006  /* don't delete WAL segments newer than the calculated segment */
8007  if (segno < *logSegNo)
8008  *logSegNo = segno;
8009 }
XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact)
int wal_keep_size_mb
Definition: xlog.c:115
static XLogRecPtr XLogGetReplicationSlotMinimumLSN(void)
Definition: xlog.c:2694
int max_slot_wal_keep_size_mb
Definition: xlog.c:134

References ConvertToXSegs, GetOldestUnsummarizedLSN(), InvalidXLogRecPtr, max_slot_wal_keep_size_mb, wal_keep_size_mb, wal_segment_size, XLByteToSeg, and XLogGetReplicationSlotMinimumLSN().

Referenced by CreateCheckPoint(), CreateRestartPoint(), and GetWALAvailability().

◆ LocalProcessControlFile()

void LocalProcessControlFile ( bool  reset)

Definition at line 4839 of file xlog.c.

4840 {
4841  Assert(reset || ControlFile == NULL);
4842  ControlFile = palloc(sizeof(ControlFileData));
4843  ReadControlFile();
4844 }
void reset(void)
Definition: sql-declare.c:600

References Assert, ControlFile, palloc(), ReadControlFile(), and reset().

Referenced by PostgresSingleUserMain(), PostmasterMain(), and PostmasterStateMachine().

◆ LocalSetXLogInsertAllowed()

static int LocalSetXLogInsertAllowed ( void  )
static

Definition at line 6421 of file xlog.c.

6422 {
6423  int oldXLogAllowed = LocalXLogInsertAllowed;
6424 
6426 
6427  return oldXLogAllowed;
6428 }

References LocalXLogInsertAllowed.

Referenced by CreateCheckPoint(), and StartupXLOG().

◆ LogCheckpointEnd()

static void LogCheckpointEnd ( bool  restartpoint)
static

Definition at line 6680 of file xlog.c.

6681 {
6682  long write_msecs,
6683  sync_msecs,
6684  total_msecs,
6685  longest_msecs,
6686  average_msecs;
6687  uint64 average_sync_time;
6688 
6690 
6693 
6696 
6697  /* Accumulate checkpoint timing summary data, in milliseconds. */
6698  PendingCheckpointerStats.write_time += write_msecs;
6699  PendingCheckpointerStats.sync_time += sync_msecs;
6700 
6701  /*
6702  * All of the published timing statistics are accounted for. Only
6703  * continue if a log message is to be written.
6704  */
6705  if (!log_checkpoints)
6706  return;
6707 
6710 
6711  /*
6712  * Timing values returned from CheckpointStats are in microseconds.
6713  * Convert to milliseconds for consistent printing.
6714  */
6715  longest_msecs = (long) ((CheckpointStats.ckpt_longest_sync + 999) / 1000);
6716 
6717  average_sync_time = 0;
6719  average_sync_time = CheckpointStats.ckpt_agg_sync_time /
6721  average_msecs = (long) ((average_sync_time + 999) / 1000);
6722 
6723  /*
6724  * ControlFileLock is not required to see ControlFile->checkPoint and
6725  * ->checkPointCopy here as we are the only updator of those variables at
6726  * this moment.
6727  */
6728  if (restartpoint)
6729  ereport(LOG,
6730  (errmsg("restartpoint complete: wrote %d buffers (%.1f%%); "
6731  "%d WAL file(s) added, %d removed, %d recycled; "
6732  "write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
6733  "sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; "
6734  "distance=%d kB, estimate=%d kB; "
6735  "lsn=%X/%X, redo lsn=%X/%X",
6737  (double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers,
6741  write_msecs / 1000, (int) (write_msecs % 1000),
6742  sync_msecs / 1000, (int) (sync_msecs % 1000),
6743  total_msecs / 1000, (int) (total_msecs % 1000),
6745  longest_msecs / 1000, (int) (longest_msecs % 1000),
6746  average_msecs / 1000, (int) (average_msecs % 1000),
6747  (int) (PrevCheckPointDistance / 1024.0),
6748  (int) (CheckPointDistanceEstimate / 1024.0),
6751  else
6752  ereport(LOG,
6753  (errmsg("checkpoint complete: wrote %d buffers (%.1f%%); "
6754  "%d WAL file(s) added, %d removed, %d recycled; "
6755  "write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
6756  "sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; "
6757  "distance=%d kB, estimate=%d kB; "
6758  "lsn=%X/%X, redo lsn=%X/%X",
6760  (double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers,
6764  write_msecs / 1000, (int) (write_msecs % 1000),
6765  sync_msecs / 1000, (int) (sync_msecs % 1000),
6766  total_msecs / 1000, (int) (total_msecs % 1000),
6768  longest_msecs / 1000, (int) (longest_msecs % 1000),
6769  average_msecs / 1000, (int) (average_msecs % 1000),
6770  (int) (PrevCheckPointDistance / 1024.0),
6771  (int) (CheckPointDistanceEstimate / 1024.0),
6774 }
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition: timestamp.c:1756
PgStat_CheckpointerStats PendingCheckpointerStats
uint64 ckpt_agg_sync_time
Definition: xlog.h:175
uint64 ckpt_longest_sync
Definition: xlog.h:174
TimestampTz ckpt_end_t
Definition: xlog.h:165
int ckpt_sync_rels
Definition: xlog.h:173
PgStat_Counter sync_time
Definition: pgstat.h:301
PgStat_Counter write_time
Definition: pgstat.h:300
static double CheckPointDistanceEstimate
Definition: xlog.c:158
static double PrevCheckPointDistance
Definition: xlog.c:159

References ControlFileData::checkPoint, ControlFileData::checkPointCopy, CheckPointDistanceEstimate, CheckpointStats, CheckpointStatsData::ckpt_agg_sync_time, CheckpointStatsData::ckpt_bufs_written, CheckpointStatsData::ckpt_end_t, CheckpointStatsData::ckpt_longest_sync, CheckpointStatsData::ckpt_segs_added, CheckpointStatsData::ckpt_segs_recycled, CheckpointStatsData::ckpt_segs_removed, CheckpointStatsData::ckpt_start_t, CheckpointStatsData::ckpt_sync_end_t, CheckpointStatsData::ckpt_sync_rels, CheckpointStatsData::ckpt_sync_t, CheckpointStatsData::ckpt_write_t, ControlFile, ereport, errmsg(), GetCurrentTimestamp(), LOG, log_checkpoints, LSN_FORMAT_ARGS, NBuffers, PendingCheckpointerStats, PrevCheckPointDistance, CheckPoint::redo, PgStat_CheckpointerStats::sync_time, TimestampDifferenceMilliseconds(), and PgStat_CheckpointerStats::write_time.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ LogCheckpointStart()

static void LogCheckpointStart ( int  flags,
bool  restartpoint 
)
static

Definition at line 6648 of file xlog.c.

6649 {
6650  if (restartpoint)
6651  ereport(LOG,
6652  /* translator: the placeholders show checkpoint options */
6653  (errmsg("restartpoint starting:%s%s%s%s%s%s%s%s",
6654  (flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
6655  (flags & CHECKPOINT_END_OF_RECOVERY) ? " end-of-recovery" : "",
6656  (flags & CHECKPOINT_IMMEDIATE) ? " immediate" : "",
6657  (flags & CHECKPOINT_FORCE) ? " force" : "",
6658  (flags & CHECKPOINT_WAIT) ? " wait" : "",
6659  (flags & CHECKPOINT_CAUSE_XLOG) ? " wal" : "",
6660  (flags & CHECKPOINT_CAUSE_TIME) ? " time" : "",
6661  (flags & CHECKPOINT_FLUSH_ALL) ? " flush-all" : "")));
6662  else
6663  ereport(LOG,
6664  /* translator: the placeholders show checkpoint options */
6665  (errmsg("checkpoint starting:%s%s%s%s%s%s%s%s",
6666  (flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
6667  (flags & CHECKPOINT_END_OF_RECOVERY) ? " end-of-recovery" : "",
6668  (flags & CHECKPOINT_IMMEDIATE) ? " immediate" : "",
6669  (flags & CHECKPOINT_FORCE) ? " force" : "",
6670  (flags & CHECKPOINT_WAIT) ? " wait" : "",
6671  (flags & CHECKPOINT_CAUSE_XLOG) ? " wal" : "",
6672  (flags & CHECKPOINT_CAUSE_TIME) ? " time" : "",
6673  (flags & CHECKPOINT_FLUSH_ALL) ? " flush-all" : "")));
6674 }
#define CHECKPOINT_CAUSE_XLOG
Definition: xlog.h:148
#define CHECKPOINT_FLUSH_ALL
Definition: xlog.h:143
#define CHECKPOINT_CAUSE_TIME
Definition: xlog.h:149

References CHECKPOINT_CAUSE_TIME, CHECKPOINT_CAUSE_XLOG, CHECKPOINT_END_OF_RECOVERY, CHECKPOINT_FLUSH_ALL, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_IS_SHUTDOWN, CHECKPOINT_WAIT, ereport, errmsg(), and LOG.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ PerformRecoveryXLogAction()

static bool PerformRecoveryXLogAction ( void  )
static

Definition at line 6283 of file xlog.c.

6284 {
6285  bool promoted = false;
6286 
6287  /*
6288  * Perform a checkpoint to update all our recovery activity to disk.
6289  *
6290  * Note that we write a shutdown checkpoint rather than an on-line one.
6291  * This is not particularly critical, but since we may be assigning a new
6292  * TLI, using a shutdown checkpoint allows us to have the rule that TLI
6293  * only changes in shutdown checkpoints, which allows some extra error
6294  * checking in xlog_redo.
6295  *
6296  * In promotion, only create a lightweight end-of-recovery record instead
6297  * of a full checkpoint. A checkpoint is requested later, after we're
6298  * fully out of recovery mode and already accepting queries.
6299  */
6302  {
6303  promoted = true;
6304 
6305  /*
6306  * Insert a special WAL record to mark the end of recovery, since we
6307  * aren't doing a checkpoint. That means that the checkpointer process
6308  * may likely be in the middle of a time-smoothed restartpoint and
6309  * could continue to be for minutes after this. That sounds strange,
6310  * but the effect is roughly the same and it would be stranger to try
6311  * to come out of the restartpoint and then checkpoint. We request a
6312  * checkpoint later anyway, just for safety.
6313  */
6315  }
6316  else
6317  {
6320  CHECKPOINT_WAIT);
6321  }
6322 
6323  return promoted;
6324 }
static void CreateEndOfRecoveryRecord(void)
Definition: xlog.c:7367
bool PromoteIsTriggered(void)

References ArchiveRecoveryRequested, CHECKPOINT_END_OF_RECOVERY, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, CreateEndOfRecoveryRecord(), IsUnderPostmaster, PromoteIsTriggered(), and RequestCheckpoint().

Referenced by StartupXLOG().

◆ PreallocXlogFiles()

static void PreallocXlogFiles ( XLogRecPtr  endptr,
TimeLineID  tli 
)
static

Definition at line 3683 of file xlog.c.

3684 {
3685  XLogSegNo _logSegNo;
3686  int lf;
3687  bool added;
3688  char path[MAXPGPATH];
3689  uint64 offset;
3690 
3692  return; /* unlocked check says no */
3693 
3694  XLByteToPrevSeg(endptr, _logSegNo, wal_segment_size);
3695  offset = XLogSegmentOffset(endptr - 1, wal_segment_size);
3696  if (offset >= (uint32) (0.75 * wal_segment_size))
3697  {
3698  _logSegNo++;
3699  lf = XLogFileInitInternal(_logSegNo, tli, &added, path);
3700  if (lf >= 0)
3701  close(lf);
3702  if (added)
3704  }
3705 }
static int XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, bool *added, char *path)
Definition: xlog.c:3203

References CheckpointStats, CheckpointStatsData::ckpt_segs_added, close, XLogCtlData::InstallXLogFileSegmentActive, MAXPGPATH, wal_segment_size, XLByteToPrevSeg, XLogCtl, XLogFileInitInternal(), and XLogSegmentOffset.

Referenced by CreateCheckPoint(), CreateRestartPoint(), and StartupXLOG().

◆ ReachedEndOfBackup()

void ReachedEndOfBackup ( XLogRecPtr  EndRecPtr,
TimeLineID  tli 
)

Definition at line 6246 of file xlog.c.

6247 {
6248  /*
6249  * We have reached the end of base backup, as indicated by pg_control. The
6250  * data on disk is now consistent (unless minRecoveryPoint is further
6251  * ahead, which can happen if we crashed during previous recovery). Reset
6252  * backupStartPoint and backupEndPoint, and update minRecoveryPoint to
6253  * make sure we don't allow starting up at an earlier point even if
6254  * recovery is stopped and restarted soon after this.
6255  */
6256  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6257 
6258  if (ControlFile->minRecoveryPoint < EndRecPtr)
6259  {
6260  ControlFile->minRecoveryPoint = EndRecPtr;
6262  }
6263 
6266  ControlFile->backupEndRequired = false;
6268 
6269  LWLockRelease(ControlFileLock);
6270 }
XLogRecPtr backupStartPoint
Definition: pg_control.h:170
bool backupEndRequired
Definition: pg_control.h:172
XLogRecPtr backupEndPoint
Definition: pg_control.h:171

References ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, ControlFile, InvalidXLogRecPtr, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, and UpdateControlFile().

Referenced by CheckRecoveryConsistency().

◆ ReadControlFile()

static void ReadControlFile ( void  )
static

Definition at line 4314 of file xlog.c.

4315 {
4316  pg_crc32c crc;
4317  int fd;
4318  char wal_segsz_str[20];
4319  int r;
4320 
4321  /*
4322  * Read data...
4323  */
4325  O_RDWR | PG_BINARY);
4326  if (fd < 0)
4327  ereport(PANIC,
4329  errmsg("could not open file \"%s\": %m",
4330  XLOG_CONTROL_FILE)));
4331 
4332  pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_READ);
4333  r = read(fd, ControlFile, sizeof(ControlFileData));
4334  if (r != sizeof(ControlFileData))
4335  {
4336  if (r < 0)
4337  ereport(PANIC,
4339  errmsg("could not read file \"%s\": %m",
4340  XLOG_CONTROL_FILE)));
4341  else
4342  ereport(PANIC,
4344  errmsg("could not read file \"%s\": read %d of %zu",
4345  XLOG_CONTROL_FILE, r, sizeof(ControlFileData))));
4346  }
4348 
4349  close(fd);
4350 
4351  /*
4352