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/xlogprefetcher.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 "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/walwriter.h"
#include "replication/logical.h"
#include "replication/origin.h"
#include "replication/slot.h"
#include "replication/snapbuild.h"
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/large_object.h"
#include "storage/latch.h"
#include "storage/pmsignal.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/reinit.h"
#include "storage/smgr.h"
#include "storage/spin.h"
#include "storage/sync.h"
#include "utils/guc_hooks.h"
#include "utils/guc_tables.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
#include "utils/pg_rusage.h"
#include "utils/snapmgr.h"
#include "utils/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))
 

Typedefs

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

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)
 
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)
 
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)
 
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)
 
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 (void)
 
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)
 
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_xlog_sync_method (int new_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

uint32 bootstrap_data_checksum_version
 
int max_wal_size_mb = 1024
 
int min_wal_size_mb = 80
 
int wal_keep_size_mb = 0
 
int XLOGbuffers = -1
 
int XLogArchiveTimeout = 0
 
int XLogArchiveMode = ARCHIVE_MODE_OFF
 
char * XLogArchiveCommand = NULL
 
bool EnableHotStandby = false
 
bool fullPageWrites = true
 
bool wal_log_hints = false
 
int wal_compression = WAL_COMPRESSION_NONE
 
char * wal_consistency_checking_string = NULL
 
boolwal_consistency_checking = NULL
 
bool wal_init_zero = true
 
bool wal_recycle = true
 
bool log_checkpoints = true
 
int sync_method = DEFAULT_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 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 114 of file xlog.c.

◆ ConvertToXSegs

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

Definition at line 599 of file xlog.c.

◆ INSERT_FREESPACE

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

Definition at line 576 of file xlog.c.

◆ NextBufIdx

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

Definition at line 580 of file xlog.c.

◆ NUM_XLOGINSERT_LOCKS

#define NUM_XLOGINSERT_LOCKS   8

Definition at line 153 of file xlog.c.

◆ UsableBytesInPage

#define UsableBytesInPage   (XLOG_BLCKSZ - SizeOfXLogShortPHD)

Definition at line 593 of file xlog.c.

◆ XLogRecPtrToBufIdx

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

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

Function Documentation

◆ AdvanceXLInsertBuffer()

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

Definition at line 1786 of file xlog.c.

1787 {
1789  int nextidx;
1790  XLogRecPtr OldPageRqstPtr;
1791  XLogwrtRqst WriteRqst;
1792  XLogRecPtr NewPageEndPtr = InvalidXLogRecPtr;
1793  XLogRecPtr NewPageBeginPtr;
1794  XLogPageHeader NewPage;
1795  int npages pg_attribute_unused() = 0;
1796 
1797  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
1798 
1799  /*
1800  * Now that we have the lock, check if someone initialized the page
1801  * already.
1802  */
1803  while (upto >= XLogCtl->InitializedUpTo || opportunistic)
1804  {
1806 
1807  /*
1808  * Get ending-offset of the buffer page we need to replace (this may
1809  * be zero if the buffer hasn't been used yet). Fall through if it's
1810  * already written out.
1811  */
1812  OldPageRqstPtr = XLogCtl->xlblocks[nextidx];
1813  if (LogwrtResult.Write < OldPageRqstPtr)
1814  {
1815  /*
1816  * Nope, got work to do. If we just want to pre-initialize as much
1817  * as we can without flushing, give up now.
1818  */
1819  if (opportunistic)
1820  break;
1821 
1822  /* Before waiting, get info_lck and update LogwrtResult */
1824  if (XLogCtl->LogwrtRqst.Write < OldPageRqstPtr)
1825  XLogCtl->LogwrtRqst.Write = OldPageRqstPtr;
1828 
1829  /*
1830  * Now that we have an up-to-date LogwrtResult value, see if we
1831  * still need to write it or if someone else already did.
1832  */
1833  if (LogwrtResult.Write < OldPageRqstPtr)
1834  {
1835  /*
1836  * Must acquire write lock. Release WALBufMappingLock first,
1837  * to make sure that all insertions that we need to wait for
1838  * can finish (up to this same position). Otherwise we risk
1839  * deadlock.
1840  */
1841  LWLockRelease(WALBufMappingLock);
1842 
1843  WaitXLogInsertionsToFinish(OldPageRqstPtr);
1844 
1845  LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
1846 
1848  if (LogwrtResult.Write >= OldPageRqstPtr)
1849  {
1850  /* OK, someone wrote it already */
1851  LWLockRelease(WALWriteLock);
1852  }
1853  else
1854  {
1855  /* Have to write it ourselves */
1856  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
1857  WriteRqst.Write = OldPageRqstPtr;
1858  WriteRqst.Flush = 0;
1859  XLogWrite(WriteRqst, tli, false);
1860  LWLockRelease(WALWriteLock);
1862  TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
1863  }
1864  /* Re-acquire WALBufMappingLock and retry */
1865  LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE);
1866  continue;
1867  }
1868  }
1869 
1870  /*
1871  * Now the next buffer slot is free and we can set it up to be the
1872  * next output page.
1873  */
1874  NewPageBeginPtr = XLogCtl->InitializedUpTo;
1875  NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
1876 
1877  Assert(XLogRecPtrToBufIdx(NewPageBeginPtr) == nextidx);
1878 
1879  NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ);
1880 
1881  /*
1882  * Be sure to re-zero the buffer so that bytes beyond what we've
1883  * written will look like zeroes and not valid XLOG records...
1884  */
1885  MemSet((char *) NewPage, 0, XLOG_BLCKSZ);
1886 
1887  /*
1888  * Fill the new page's header
1889  */
1890  NewPage->xlp_magic = XLOG_PAGE_MAGIC;
1891 
1892  /* NewPage->xlp_info = 0; */ /* done by memset */
1893  NewPage->xlp_tli = tli;
1894  NewPage->xlp_pageaddr = NewPageBeginPtr;
1895 
1896  /* NewPage->xlp_rem_len = 0; */ /* done by memset */
1897 
1898  /*
1899  * If online backup is not in progress, mark the header to indicate
1900  * that WAL records beginning in this page have removable backup
1901  * blocks. This allows the WAL archiver to know whether it is safe to
1902  * compress archived WAL data by transforming full-block records into
1903  * the non-full-block format. It is sufficient to record this at the
1904  * page level because we force a page switch (in fact a segment
1905  * switch) when starting a backup, so the flag will be off before any
1906  * records can be written during the backup. At the end of a backup,
1907  * the last page will be marked as all unsafe when perhaps only part
1908  * is unsafe, but at worst the archiver would miss the opportunity to
1909  * compress a few records.
1910  */
1911  if (Insert->runningBackups == 0)
1912  NewPage->xlp_info |= XLP_BKP_REMOVABLE;
1913 
1914  /*
1915  * If first page of an XLOG segment file, make it a long header.
1916  */
1917  if ((XLogSegmentOffset(NewPage->xlp_pageaddr, wal_segment_size)) == 0)
1918  {
1919  XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
1920 
1921  NewLongPage->xlp_sysid = ControlFile->system_identifier;
1922  NewLongPage->xlp_seg_size = wal_segment_size;
1923  NewLongPage->xlp_xlog_blcksz = XLOG_BLCKSZ;
1924  NewPage->xlp_info |= XLP_LONG_HEADER;
1925  }
1926 
1927  /*
1928  * Make sure the initialization of the page becomes visible to others
1929  * before the xlblocks update. GetXLogBuffer() reads xlblocks without
1930  * holding a lock.
1931  */
1932  pg_write_barrier();
1933 
1934  *((volatile XLogRecPtr *) &XLogCtl->xlblocks[nextidx]) = NewPageEndPtr;
1935 
1936  XLogCtl->InitializedUpTo = NewPageEndPtr;
1937 
1938  npages++;
1939  }
1940  LWLockRelease(WALBufMappingLock);
1941 
1942 #ifdef WAL_DEBUG
1943  if (XLOG_DEBUG && npages > 0)
1944  {
1945  elog(DEBUG1, "initialized %d pages, up to %X/%X",
1946  npages, LSN_FORMAT_ARGS(NewPageEndPtr));
1947  }
1948 #endif
1949 }
#define pg_write_barrier()
Definition: atomics.h:154
#define pg_attribute_unused()
Definition: c.h:125
#define MemSet(start, val, len)
Definition: c.h:1009
size_t Size
Definition: c.h:594
#define DEBUG1
Definition: elog.h:30
static void Insert(File file)
Definition: fd.c:1265
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_EXCLUSIVE
Definition: lwlock.h:116
PgStat_PendingWalStats PendingWalStats
Definition: pgstat_wal.c:24
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
uint64 system_identifier
Definition: pg_control.h:108
PgStat_Counter wal_buffers_full
Definition: pgstat.h:450
XLogwrtRqst LogwrtRqst
Definition: xlog.c:464
slock_t info_lck
Definition: xlog.c:559
XLogRecPtr InitializedUpTo
Definition: xlog.c:496
char * pages
Definition: xlog.c:503
XLogwrtResult LogwrtResult
Definition: xlog.c:484
XLogCtlInsert Insert
Definition: xlog.c:461
XLogRecPtr * xlblocks
Definition: xlog.c:504
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
XLogRecPtr Write
Definition: xlog.c:336
XLogRecPtr Flush
Definition: xlog.c:331
XLogRecPtr Write
Definition: xlog.c:330
static XLogCtlData * XLogCtl
Definition: xlog.c:562
static XLogRecPtr WaitXLogInsertionsToFinish(XLogRecPtr upto)
Definition: xlog.c:1438
int wal_segment_size
Definition: xlog.c:146
static XLogwrtResult LogwrtResult
Definition: xlog.c:608
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:587
static void XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
Definition: xlog.c:2089
static ControlFileData * ControlFile
Definition: xlog.c:570
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, XLogCtlData::LogwrtResult, LogwrtResult, XLogCtlData::LogwrtRqst, LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, XLogCtlData::pages, PendingWalStats, pg_attribute_unused, pg_write_barrier, 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 1992 of file xlog.c.

1993 {
1996 }
double CheckPointCompletionTarget
Definition: checkpointer.c:146
#define newval
static void CalculateCheckpointSegments(void)
Definition: xlog.c:1956

References CalculateCheckpointSegments(), CheckPointCompletionTarget, and newval.

◆ assign_max_wal_size()

void assign_max_wal_size ( int  newval,
void *  extra 
)

Definition at line 1985 of file xlog.c.

1986 {
1989 }
int max_wal_size_mb
Definition: xlog.c:117

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

4400 {
4401  /*
4402  * If some checks were deferred, it's possible that the checks will fail
4403  * later during InitializeWalConsistencyChecking(). But in that case, the
4404  * postmaster will exit anyway, so it's safe to proceed with the
4405  * assignment.
4406  *
4407  * Any built-in resource managers specified are assigned immediately,
4408  * which affects WAL created before shared_preload_libraries are
4409  * processed. Any custom resource managers specified won't be assigned
4410  * until after shared_preload_libraries are processed, but that's OK
4411  * because WAL for a custom resource manager can't be written before the
4412  * module is loaded anyway.
4413  */
4414  wal_consistency_checking = extra;
4415 }
bool * wal_consistency_checking
Definition: xlog.c:129

References wal_consistency_checking.

◆ assign_xlog_sync_method()

void assign_xlog_sync_method ( int  new_sync_method,
void *  extra 
)

Definition at line 8144 of file xlog.c.

8145 {
8146  if (sync_method != new_sync_method)
8147  {
8148  /*
8149  * To ensure that no blocks escape unsynced, force an fsync on the
8150  * currently open log segment (if any). Also, if the open flag is
8151  * changing, close the log file so it will be reopened (with new flag
8152  * bit) at next use.
8153  */
8154  if (openLogFile >= 0)
8155  {
8156  pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN);
8157  if (pg_fsync(openLogFile) != 0)
8158  {
8159  char xlogfname[MAXFNAMELEN];
8160  int save_errno;
8161 
8162  save_errno = errno;
8163  XLogFileName(xlogfname, openLogTLI, openLogSegNo,
8165  errno = save_errno;
8166  ereport(PANIC,
8168  errmsg("could not fsync file \"%s\": %m", xlogfname)));
8169  }
8170 
8172  if (get_sync_bit(sync_method) != get_sync_bit(new_sync_method))
8173  XLogFileClose();
8174  }
8175  }
8176 }
int errcode_for_file_access(void)
Definition: elog.c:881
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define PANIC
Definition: elog.h:42
#define ereport(elevel,...)
Definition: elog.h:149
int pg_fsync(int fd)
Definition: fd.c:361
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:88
static void pgstat_report_wait_end(void)
Definition: wait_event.h:104
static int openLogFile
Definition: xlog.c:618
static int get_sync_bit(int method)
Definition: xlog.c:8096
static TimeLineID openLogTLI
Definition: xlog.c:620
static void XLogFileClose(void)
Definition: xlog.c:3372
static XLogSegNo openLogSegNo
Definition: xlog.c:619
int sync_method
Definition: xlog.c:133
#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(), sync_method, wal_segment_size, XLogFileClose(), and XLogFileName().

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 4669 of file xlog.c.

4670 {
4671  CheckPoint checkPoint;
4672  char *buffer;
4673  XLogPageHeader page;
4674  XLogLongPageHeader longpage;
4675  XLogRecord *record;
4676  char *recptr;
4677  uint64 sysidentifier;
4678  struct timeval tv;
4679  pg_crc32c crc;
4680 
4681  /* allow ordinary WAL segment creation, like StartupXLOG() would */
4683 
4684  /*
4685  * Select a hopefully-unique system identifier code for this installation.
4686  * We use the result of gettimeofday(), including the fractional seconds
4687  * field, as being about as unique as we can easily get. (Think not to
4688  * use random(), since it hasn't been seeded and there's no portable way
4689  * to seed it other than the system clock value...) The upper half of the
4690  * uint64 value is just the tv_sec part, while the lower half contains the
4691  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
4692  * PID for a little extra uniqueness. A person knowing this encoding can
4693  * determine the initialization time of the installation, which could
4694  * perhaps be useful sometimes.
4695  */
4696  gettimeofday(&tv, NULL);
4697  sysidentifier = ((uint64) tv.tv_sec) << 32;
4698  sysidentifier |= ((uint64) tv.tv_usec) << 12;
4699  sysidentifier |= getpid() & 0xFFF;
4700 
4701  /* page buffer must be aligned suitably for O_DIRECT */
4702  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
4703  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
4704  memset(page, 0, XLOG_BLCKSZ);
4705 
4706  /*
4707  * Set up information for the initial checkpoint record
4708  *
4709  * The initial checkpoint record is written to the beginning of the WAL
4710  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
4711  * used, so that we can use 0/0 to mean "before any valid WAL segment".
4712  */
4713  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
4714  checkPoint.ThisTimeLineID = BootstrapTimeLineID;
4715  checkPoint.PrevTimeLineID = BootstrapTimeLineID;
4716  checkPoint.fullPageWrites = fullPageWrites;
4717  checkPoint.nextXid =
4719  checkPoint.nextOid = FirstGenbkiObjectId;
4720  checkPoint.nextMulti = FirstMultiXactId;
4721  checkPoint.nextMultiOffset = 0;
4722  checkPoint.oldestXid = FirstNormalTransactionId;
4723  checkPoint.oldestXidDB = Template1DbOid;
4724  checkPoint.oldestMulti = FirstMultiXactId;
4725  checkPoint.oldestMultiDB = Template1DbOid;
4728  checkPoint.time = (pg_time_t) time(NULL);
4730 
4731  ShmemVariableCache->nextXid = checkPoint.nextXid;
4732  ShmemVariableCache->nextOid = checkPoint.nextOid;
4734  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
4735  AdvanceOldestClogXid(checkPoint.oldestXid);
4736  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
4737  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
4739 
4740  /* Set up the XLOG page header */
4741  page->xlp_magic = XLOG_PAGE_MAGIC;
4742  page->xlp_info = XLP_LONG_HEADER;
4743  page->xlp_tli = BootstrapTimeLineID;
4745  longpage = (XLogLongPageHeader) page;
4746  longpage->xlp_sysid = sysidentifier;
4747  longpage->xlp_seg_size = wal_segment_size;
4748  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
4749 
4750  /* Insert the initial checkpoint record */
4751  recptr = ((char *) page + SizeOfXLogLongPHD);
4752  record = (XLogRecord *) recptr;
4753  record->xl_prev = 0;
4754  record->xl_xid = InvalidTransactionId;
4755  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
4757  record->xl_rmid = RM_XLOG_ID;
4758  recptr += SizeOfXLogRecord;
4759  /* fill the XLogRecordDataHeaderShort struct */
4760  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
4761  *(recptr++) = sizeof(checkPoint);
4762  memcpy(recptr, &checkPoint, sizeof(checkPoint));
4763  recptr += sizeof(checkPoint);
4764  Assert(recptr - (char *) record == record->xl_tot_len);
4765 
4766  INIT_CRC32C(crc);
4767  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
4768  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
4769  FIN_CRC32C(crc);
4770  record->xl_crc = crc;
4771 
4772  /* Create first XLOG segment file */
4775 
4776  /*
4777  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
4778  * close the file again in a moment.
4779  */
4780 
4781  /* Write the first page with the initial record */
4782  errno = 0;
4783  pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
4784  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
4785  {
4786  /* if write didn't set errno, assume problem is no disk space */
4787  if (errno == 0)
4788  errno = ENOSPC;
4789  ereport(PANIC,
4791  errmsg("could not write bootstrap write-ahead log file: %m")));
4792  }
4794 
4795  pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC);
4796  if (pg_fsync(openLogFile) != 0)
4797  ereport(PANIC,
4799  errmsg("could not fsync bootstrap write-ahead log file: %m")));
4801 
4802  if (close(openLogFile) != 0)
4803  ereport(PANIC,
4805  errmsg("could not close bootstrap write-ahead log file: %m")));
4806 
4807  openLogFile = -1;
4808 
4809  /* Now create pg_control */
4810  InitControlFile(sysidentifier);
4811  ControlFile->time = checkPoint.time;
4812  ControlFile->checkPoint = checkPoint.redo;
4813  ControlFile->checkPointCopy = checkPoint;
4814 
4815  /* some additional ControlFile fields are set in WriteControlFile() */
4816  WriteControlFile();
4817 
4818  /* Bootstrap the commit log, too */
4819  BootStrapCLOG();
4823 
4824  pfree(buffer);
4825 
4826  /*
4827  * Force control file to be read - in contrast to normal processing we'd
4828  * otherwise never run the checks and GUC related initializations therein.
4829  */
4830  ReadControlFile();
4831 }
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:793
void BootStrapCLOG(void)
Definition: clog.c:711
void BootStrapCommitTs(void)
Definition: commit_ts.c:553
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:860
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2179
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2213
void BootStrapMultiXact(void)
Definition: multixact.c:1894
#define FirstMultiXactId
Definition: multixact.h:25
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
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:50
MultiXactId oldestMulti
Definition: pg_control.h:49
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId newestCommitTsXid
Definition: pg_control.h:54
TransactionId oldestXid
Definition: pg_control.h:47
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
Oid nextOid
Definition: pg_control.h:44
TransactionId oldestActiveXid
Definition: pg_control.h:63
bool fullPageWrites
Definition: pg_control.h:42
MultiXactId nextMulti
Definition: pg_control.h:45
FullTransactionId nextXid
Definition: pg_control.h:43
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
pg_time_t time
Definition: pg_control.h:51
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:48
CheckPoint checkPointCopy
Definition: pg_control.h:133
pg_time_t time
Definition: pg_control.h:130
XLogRecPtr checkPoint
Definition: pg_control.h:131
FullTransactionId nextXid
Definition: transam.h:220
uint32 oidCount
Definition: transam.h:215
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:211
#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:345
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
VariableCache ShmemVariableCache
Definition: varsup.c:34
int gettimeofday(struct timeval *tp, void *tzp)
int XLogFileInit(XLogSegNo logsegno, TimeLineID logtli)
Definition: xlog.c:3113
bool fullPageWrites
Definition: xlog.c:125
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:3876
void SetInstallXLogFileSegmentActive(void)
Definition: xlog.c:8974
static void WriteControlFile(void)
Definition: xlog.c:3911
#define BootstrapTimeLineID
Definition: xlog.c:114
static void ReadControlFile(void)
Definition: xlog.c:3993
#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, VariableCacheData::nextOid, CheckPoint::nextOid, VariableCacheData::nextXid, CheckPoint::nextXid, VariableCacheData::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(), ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, TYPEALIGN, 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 1956 of file xlog.c.

1957 {
1958  double target;
1959 
1960  /*-------
1961  * Calculate the distance at which to trigger a checkpoint, to avoid
1962  * exceeding max_wal_size_mb. This is based on two assumptions:
1963  *
1964  * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
1965  * WAL for two checkpoint cycles to allow us to recover from the
1966  * secondary checkpoint if the first checkpoint failed, though we
1967  * only did this on the primary anyway, not on standby. Keeping just
1968  * one checkpoint simplifies processing and reduces disk space in
1969  * many smaller databases.)
1970  * b) during checkpoint, we consume checkpoint_completion_target *
1971  * number of segments consumed between checkpoints.
1972  *-------
1973  */
1974  target = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /
1976 
1977  /* round down */
1978  CheckPointSegments = (int) target;
1979 
1980  if (CheckPointSegments < 1)
1981  CheckPointSegments = 1;
1982 }
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:599
int CheckPointSegments
Definition: xlog.c:159

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_wal_buffers()

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

Definition at line 4279 of file xlog.c.

4280 {
4281  /*
4282  * -1 indicates a request for auto-tune.
4283  */
4284  if (*newval == -1)
4285  {
4286  /*
4287  * If we haven't yet changed the boot_val default of -1, just let it
4288  * be. We'll fix it when XLOGShmemSize is called.
4289  */
4290  if (XLOGbuffers == -1)
4291  return true;
4292 
4293  /* Otherwise, substitute the auto-tune value */
4295  }
4296 
4297  /*
4298  * We clamp manually-set values to at least 4 blocks. Prior to PostgreSQL
4299  * 9.1, a minimum of 4 was enforced by guc.c, but since that is no longer
4300  * the case, we just silently treat such values as a request for the
4301  * minimum. (We could throw an error instead, but that doesn't seem very
4302  * helpful.)
4303  */
4304  if (*newval < 4)
4305  *newval = 4;
4306 
4307  return true;
4308 }
static int XLOGChooseNumBuffers(void)
Definition: xlog.c:4263
int XLOGbuffers
Definition: xlog.c:120

References newval, XLOGbuffers, and XLOGChooseNumBuffers().

◆ check_wal_consistency_checking()

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

Definition at line 4314 of file xlog.c.

4315 {
4316  char *rawstring;
4317  List *elemlist;
4318  ListCell *l;
4319  bool newwalconsistency[RM_MAX_ID + 1];
4320 
4321  /* Initialize the array */
4322  MemSet(newwalconsistency, 0, (RM_MAX_ID + 1) * sizeof(bool));
4323 
4324  /* Need a modifiable copy of string */
4325  rawstring = pstrdup(*newval);
4326 
4327  /* Parse string into list of identifiers */
4328  if (!SplitIdentifierString(rawstring, ',', &elemlist))
4329  {
4330  /* syntax error in list */
4331  GUC_check_errdetail("List syntax is invalid.");
4332  pfree(rawstring);
4333  list_free(elemlist);
4334  return false;
4335  }
4336 
4337  foreach(l, elemlist)
4338  {
4339  char *tok = (char *) lfirst(l);
4340  int rmid;
4341 
4342  /* Check for 'all'. */
4343  if (pg_strcasecmp(tok, "all") == 0)
4344  {
4345  for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
4346  if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL)
4347  newwalconsistency[rmid] = true;
4348  }
4349  else
4350  {
4351  /* Check if the token matches any known resource manager. */
4352  bool found = false;
4353 
4354  for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
4355  {
4356  if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL &&
4357  pg_strcasecmp(tok, GetRmgr(rmid).rm_name) == 0)
4358  {
4359  newwalconsistency[rmid] = true;
4360  found = true;
4361  break;
4362  }
4363  }
4364  if (!found)
4365  {
4366  /*
4367  * During startup, it might be a not-yet-loaded custom
4368  * resource manager. Defer checking until
4369  * InitializeWalConsistencyChecking().
4370  */
4372  {
4374  }
4375  else
4376  {
4377  GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
4378  pfree(rawstring);
4379  list_free(elemlist);
4380  return false;
4381  }
4382  }
4383  }
4384  }
4385 
4386  pfree(rawstring);
4387  list_free(elemlist);
4388 
4389  /* assign new value */
4390  *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool));
4391  memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool));
4392  return true;
4393 }
#define ERROR
Definition: elog.h:39
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:631
#define GUC_check_errdetail
Definition: guc.h:436
void list_free(List *list)
Definition: list.c:1545
char * pstrdup(const char *in)
Definition: mcxt.c:1644
bool process_shared_preload_libraries_done
Definition: miscinit.c:1765
#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:3454
static bool check_wal_consistency_checking_deferred
Definition: xlog.c:169
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 1999 of file xlog.c.

2000 {
2001  if (!IsValidWalSegSize(*newval))
2002  {
2003  GUC_check_errdetail("The WAL segment size must be a power of two between 1 MB and 1 GB.");
2004  return false;
2005  }
2006 
2007  return true;
2008 }
#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 7038 of file xlog.c.

7039 {
7045 
7046  /* Write out all dirty data in SLRUs and the main buffer pool */
7047  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_START(flags);
7049  CheckPointCLOG();
7054  CheckPointBuffers(flags);
7055 
7056  /* Perform all queued up fsyncs */
7057  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
7061  TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
7062 
7063  /* We deliberately delay 2PC checkpointing as long as possible */
7064  CheckPointTwoPhase(checkPointRedo);
7065 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
void CheckPointBuffers(int flags)
Definition: bufmgr.c:3276
void CheckPointCLOG(void)
Definition: clog.c:817
void CheckPointCommitTs(void)
Definition: commit_ts.c:774
void CheckPointMultiXact(void)
Definition: multixact.c:2155
void CheckPointReplicationOrigin(void)
Definition: origin.c:573
void CheckPointPredicate(void)
Definition: predicate.c:1005
void CheckPointRelationMap(void)
Definition: relmapper.c:611
void CheckPointLogicalRewriteHeap(void)
Definition: rewriteheap.c:1189
void CheckPointReplicationSlots(bool is_shutdown)
Definition: slot.c:1582
void CheckPointSnapBuild(void)
Definition: snapbuild.c:2055
TimestampTz ckpt_write_t
Definition: xlog.h:157
TimestampTz ckpt_sync_end_t
Definition: xlog.h:159
TimestampTz ckpt_sync_t
Definition: xlog.h:158
void CheckPointSUBTRANS(void)
Definition: subtrans.c:284
void ProcessSyncRequests(void)
Definition: sync.c:291
void CheckPointTwoPhase(XLogRecPtr redo_horizon)
Definition: twophase.c:1794
CheckpointStatsData CheckpointStats
Definition: xlog.c:212
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:134

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

5014 {
5015  /*
5016  * For archive recovery, the WAL must be generated with at least 'replica'
5017  * wal_level.
5018  */
5020  {
5021  ereport(FATAL,
5022  (errmsg("WAL was generated with wal_level=minimal, cannot continue recovering"),
5023  errdetail("This happens if you temporarily set wal_level=minimal on the server."),
5024  errhint("Use a backup taken after setting wal_level to higher than minimal.")));
5025  }
5026 
5027  /*
5028  * For Hot Standby, the WAL must be generated with 'replica' mode, and we
5029  * must have at least as many backend slots as the primary.
5030  */
5032  {
5033  /* We ignore autovacuum_max_workers when we make this test. */
5034  RecoveryRequiresIntParameter("max_connections",
5037  RecoveryRequiresIntParameter("max_worker_processes",
5040  RecoveryRequiresIntParameter("max_wal_senders",
5043  RecoveryRequiresIntParameter("max_prepared_transactions",
5046  RecoveryRequiresIntParameter("max_locks_per_transaction",
5049  }
5050 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
#define FATAL
Definition: elog.h:41
int MaxConnections
Definition: globals.c:137
int max_worker_processes
Definition: globals.c:138
int max_locks_per_xact
Definition: lock.c:55
int max_worker_processes
Definition: pg_control.h:179
int max_locks_per_xact
Definition: pg_control.h:182
int max_prepared_xacts
Definition: pg_control.h:181
int max_prepared_xacts
Definition: twophase.c:118
int max_wal_senders
Definition: walsender.c:122
bool EnableHotStandby
Definition: xlog.c:124
@ WAL_LEVEL_MINIMAL
Definition: xlog.h:69
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:137
void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue)

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

Referenced by StartupXLOG(), and xlog_redo().

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3460 of file xlog.c.

3461 {
3462  int save_errno = errno;
3463  XLogSegNo lastRemovedSegNo;
3464 
3466  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3468 
3469  if (segno <= lastRemovedSegNo)
3470  {
3471  char filename[MAXFNAMELEN];
3472 
3473  XLogFileName(filename, tli, segno, wal_segment_size);
3474  errno = save_errno;
3475  ereport(ERROR,
3477  errmsg("requested WAL segment %s has already been removed",
3478  filename)));
3479  }
3480  errno = save_errno;
3481 }
static char * filename
Definition: pg_dumpall.c:119
XLogSegNo lastRemovedSegNo
Definition: xlog.c:470
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 4924 of file xlog.c.

4926 {
4927  /*
4928  * Execute the recovery_end_command, if any.
4929  */
4930  if (recoveryEndCommand && strcmp(recoveryEndCommand, "") != 0)
4932  "recovery_end_command",
4933  true,
4934  WAIT_EVENT_RECOVERY_END_COMMAND);
4935 
4936  /*
4937  * We switched to a new timeline. Clean up segments on the old timeline.
4938  *
4939  * If there are any higher-numbered segments on the old timeline, remove
4940  * them. They might contain valid WAL, but they might also be
4941  * pre-allocated files containing garbage. In any case, they are not part
4942  * of the new timeline's history so we don't need them.
4943  */
4944  RemoveNonParentXlogFiles(EndOfLog, newTLI);
4945 
4946  /*
4947  * If the switch happened in the middle of a segment, what to do with the
4948  * last, partial segment on the old timeline? If we don't archive it, and
4949  * the server that created the WAL never archives it either (e.g. because
4950  * it was hit by a meteor), it will never make it to the archive. That's
4951  * OK from our point of view, because the new segment that we created with
4952  * the new TLI contains all the WAL from the old timeline up to the switch
4953  * point. But if you later try to do PITR to the "missing" WAL on the old
4954  * timeline, recovery won't find it in the archive. It's physically
4955  * present in the new file with new TLI, but recovery won't look there
4956  * when it's recovering to the older timeline. On the other hand, if we
4957  * archive the partial segment, and the original server on that timeline
4958  * is still running and archives the completed version of the same segment
4959  * later, it will fail. (We used to do that in 9.4 and below, and it
4960  * caused such problems).
4961  *
4962  * As a compromise, we rename the last segment with the .partial suffix,
4963  * and archive it. Archive recovery will never try to read .partial
4964  * segments, so they will normally go unused. But in the odd PITR case,
4965  * the administrator can copy them manually to the pg_wal directory
4966  * (removing the suffix). They can be useful in debugging, too.
4967  *
4968  * If a .done or .ready file already exists for the old timeline, however,
4969  * we had already determined that the segment is complete, so we can let
4970  * it be archived normally. (In particular, if it was restored from the
4971  * archive to begin with, it's expected to have a .done file).
4972  */
4973  if (XLogSegmentOffset(EndOfLog, wal_segment_size) != 0 &&
4975  {
4976  char origfname[MAXFNAMELEN];
4977  XLogSegNo endLogSegNo;
4978 
4979  XLByteToPrevSeg(EndOfLog, endLogSegNo, wal_segment_size);
4980  XLogFileName(origfname, EndOfLogTLI, endLogSegNo, wal_segment_size);
4981 
4982  if (!XLogArchiveIsReadyOrDone(origfname))
4983  {
4984  char origpath[MAXPGPATH];
4985  char partialfname[MAXFNAMELEN];
4986  char partialpath[MAXPGPATH];
4987 
4988  XLogFilePath(origpath, EndOfLogTLI, endLogSegNo, wal_segment_size);
4989  snprintf(partialfname, MAXFNAMELEN, "%s.partial", origfname);
4990  snprintf(partialpath, MAXPGPATH, "%s.partial", origpath);
4991 
4992  /*
4993  * Make sure there's no .done or .ready file for the .partial
4994  * file.
4995  */
4996  XLogArchiveCleanup(partialfname);
4997 
4998  durable_rename(origpath, partialpath, ERROR);
4999  XLogArchiveNotify(partialfname);
5000  }
5001  }
5002 }
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:734
#define MAXPGPATH
#define snprintf
Definition: port.h:238
void RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
Definition: xlog.c:3635
#define XLogArchivingActive()
Definition: xlog.h:94
#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:658
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal, uint32 wait_event_info)
Definition: xlogarchive.c:289
void XLogArchiveNotify(const char *xlog)
Definition: xlogarchive.c:438
void XLogArchiveCleanup(const char *xlog)
Definition: xlogarchive.c:706
char * recoveryEndCommand
Definition: xlogrecovery.c:83

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

Referenced by StartupXLOG().

◆ CleanupBackupHistory()

static void CleanupBackupHistory ( void  )
static

Definition at line 3833 of file xlog.c.

3834 {
3835  DIR *xldir;
3836  struct dirent *xlde;
3837  char path[MAXPGPATH + sizeof(XLOGDIR)];
3838 
3839  xldir = AllocateDir(XLOGDIR);
3840 
3841  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
3842  {
3843  if (IsBackupHistoryFileName(xlde->d_name))
3844  {
3845  if (XLogArchiveCheckDone(xlde->d_name))
3846  {
3847  elog(DEBUG2, "removing WAL backup history file \"%s\"",
3848  xlde->d_name);
3849  snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name);
3850  unlink(path);
3851  XLogArchiveCleanup(xlde->d_name);
3852  }
3853  }
3854  }
3855 
3856  FreeDir(xldir);
3857 }
#define DEBUG2
Definition: elog.h:29
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2854
int FreeDir(DIR *dir)
Definition: fd.c:2906
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2788
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:559

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

1163 {
1164  char *currpos;
1165  int freespace;
1166  int written;
1167  XLogRecPtr CurrPos;
1168  XLogPageHeader pagehdr;
1169 
1170  /*
1171  * Get a pointer to the right place in the right WAL buffer to start
1172  * inserting to.
1173  */
1174  CurrPos = StartPos;
1175  currpos = GetXLogBuffer(CurrPos, tli);
1176  freespace = INSERT_FREESPACE(CurrPos);
1177 
1178  /*
1179  * there should be enough space for at least the first field (xl_tot_len)
1180  * on this page.
1181  */
1182  Assert(freespace >= sizeof(uint32));
1183 
1184  /* Copy record data */
1185  written = 0;
1186  while (rdata != NULL)
1187  {
1188  char *rdata_data = rdata->data;
1189  int rdata_len = rdata->len;
1190 
1191  while (rdata_len > freespace)
1192  {
1193  /*
1194  * Write what fits on this page, and continue on the next page.
1195  */
1196  Assert(CurrPos % XLOG_BLCKSZ >= SizeOfXLogShortPHD || freespace == 0);
1197  memcpy(currpos, rdata_data, freespace);
1198  rdata_data += freespace;
1199  rdata_len -= freespace;
1200  written += freespace;
1201  CurrPos += freespace;
1202 
1203  /*
1204  * Get pointer to beginning of next page, and set the xlp_rem_len
1205  * in the page header. Set XLP_FIRST_IS_CONTRECORD.
1206  *
1207  * It's safe to set the contrecord flag and xlp_rem_len without a
1208  * lock on the page. All the other flags were already set when the
1209  * page was initialized, in AdvanceXLInsertBuffer, and we're the
1210  * only backend that needs to set the contrecord flag.
1211  */
1212  currpos = GetXLogBuffer(CurrPos, tli);
1213  pagehdr = (XLogPageHeader) currpos;
1214  pagehdr->xlp_rem_len = write_len - written;
1215  pagehdr->xlp_info |= XLP_FIRST_IS_CONTRECORD;
1216 
1217  /* skip over the page header */
1218  if (XLogSegmentOffset(CurrPos, wal_segment_size) == 0)
1219  {
1220  CurrPos += SizeOfXLogLongPHD;
1221  currpos += SizeOfXLogLongPHD;
1222  }
1223  else
1224  {
1225  CurrPos += SizeOfXLogShortPHD;
1226  currpos += SizeOfXLogShortPHD;
1227  }
1228  freespace = INSERT_FREESPACE(CurrPos);
1229  }
1230 
1231  Assert(CurrPos % XLOG_BLCKSZ >= SizeOfXLogShortPHD || rdata_len == 0);
1232  memcpy(currpos, rdata_data, rdata_len);
1233  currpos += rdata_len;
1234  CurrPos += rdata_len;
1235  freespace -= rdata_len;
1236  written += rdata_len;
1237 
1238  rdata = rdata->next;
1239  }
1240  Assert(written == write_len);
1241 
1242  /*
1243  * If this was an xlog-switch, it's not enough to write the switch record,
1244  * we also have to consume all the remaining space in the WAL segment. We
1245  * have already reserved that space, but we need to actually fill it.
1246  */
1247  if (isLogSwitch && XLogSegmentOffset(CurrPos, wal_segment_size) != 0)
1248  {
1249  /* An xlog-switch record doesn't contain any data besides the header */
1250  Assert(write_len == SizeOfXLogRecord);
1251 
1252  /* Assert that we did reserve the right amount of space */
1253  Assert(XLogSegmentOffset(EndPos, wal_segment_size) == 0);
1254 
1255  /* Use up all the remaining space on the current page */
1256  CurrPos += freespace;
1257 
1258  /*
1259  * Cause all remaining pages in the segment to be flushed, leaving the
1260  * XLog position where it should be, at the start of the next segment.
1261  * We do this one page at a time, to make sure we don't deadlock
1262  * against ourselves if wal_buffers < wal_segment_size.
1263  */
1264  while (CurrPos < EndPos)
1265  {
1266  /*
1267  * The minimal action to flush the page would be to call
1268  * WALInsertLockUpdateInsertingAt(CurrPos) followed by
1269  * AdvanceXLInsertBuffer(...). The page would be left initialized
1270  * mostly to zeros, except for the page header (always the short
1271  * variant, as this is never a segment's first page).
1272  *
1273  * The large vistas of zeros are good for compressibility, but the
1274  * headers interrupting them every XLOG_BLCKSZ (with values that
1275  * differ from page to page) are not. The effect varies with
1276  * compression tool, but bzip2 for instance compresses about an
1277  * order of magnitude worse if those headers are left in place.
1278  *
1279  * Rather than complicating AdvanceXLInsertBuffer itself (which is
1280  * called in heavily-loaded circumstances as well as this lightly-
1281  * loaded one) with variant behavior, we just use GetXLogBuffer
1282  * (which itself calls the two methods we need) to get the pointer
1283  * and zero most of the page. Then we just zero the page header.
1284  */
1285  currpos = GetXLogBuffer(CurrPos, tli);
1286  MemSet(currpos, 0, SizeOfXLogShortPHD);
1287 
1288  CurrPos += XLOG_BLCKSZ;
1289  }
1290  }
1291  else
1292  {
1293  /* Align the end position, so that the next record starts aligned */
1294  CurrPos = MAXALIGN64(CurrPos);
1295  }
1296 
1297  if (CurrPos != EndPos)
1298  elog(PANIC, "space reserved for WAL record does not match what was written");
1299 }
unsigned int uint32
Definition: c.h:495
#define MAXALIGN64(LEN)
Definition: c.h:825
struct XLogRecData * next
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:576
static char * GetXLogBuffer(XLogRecPtr ptr, TimeLineID tli)
Definition: xlog.c:1548
#define XLP_FIRST_IS_CONTRECORD
Definition: xlog_internal.h:74
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52

References Assert(), XLogRecData::data, elog(), GetXLogBuffer(), INSERT_FREESPACE, XLogRecData::len, MAXALIGN64, MemSet, XLogRecData::next, PANIC, SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogShortPHD, wal_segment_size, XLogSegmentOffset, XLP_FIRST_IS_CONTRECORD, XLogPageHeaderData::xlp_info, and XLogPageHeaderData::xlp_rem_len.

Referenced by XLogInsertRecord().

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 6476 of file xlog.c.

6477 {
6478  bool shutdown;
6479  CheckPoint checkPoint;
6480  XLogRecPtr recptr;
6481  XLogSegNo _logSegNo;
6483  uint32 freespace;
6484  XLogRecPtr PriorRedoPtr;
6485  XLogRecPtr curInsert;
6486  XLogRecPtr last_important_lsn;
6487  VirtualTransactionId *vxids;
6488  int nvxids;
6489  int oldXLogAllowed = 0;
6490 
6491  /*
6492  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
6493  * issued at a different time.
6494  */
6496  shutdown = true;
6497  else
6498  shutdown = false;
6499 
6500  /* sanity check */
6501  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
6502  elog(ERROR, "can't create a checkpoint during recovery");
6503 
6504  /*
6505  * Prepare to accumulate statistics.
6506  *
6507  * Note: because it is possible for log_checkpoints to change while a
6508  * checkpoint proceeds, we always accumulate stats, even if
6509  * log_checkpoints is currently off.
6510  */
6511  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
6513 
6514  /*
6515  * Let smgr prepare for checkpoint; this has to happen outside the
6516  * critical section and before we determine the REDO pointer. Note that
6517  * smgr must not do anything that'd have to be undone if we decide no
6518  * checkpoint is needed.
6519  */
6521 
6522  /*
6523  * Use a critical section to force system panic if we have trouble.
6524  */
6526 
6527  if (shutdown)
6528  {
6529  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6532  LWLockRelease(ControlFileLock);
6533  }
6534 
6535  /* Begin filling in the checkpoint WAL record */
6536  MemSet(&checkPoint, 0, sizeof(checkPoint));
6537  checkPoint.time = (pg_time_t) time(NULL);
6538 
6539  /*
6540  * For Hot Standby, derive the oldestActiveXid before we fix the redo
6541  * pointer. This allows us to begin accumulating changes to assemble our
6542  * starting snapshot of locks and transactions.
6543  */
6544  if (!shutdown && XLogStandbyInfoActive())
6546  else
6548 
6549  /*
6550  * Get location of last important record before acquiring insert locks (as
6551  * GetLastImportantRecPtr() also locks WAL locks).
6552  */
6553  last_important_lsn = GetLastImportantRecPtr();
6554 
6555  /*
6556  * We must block concurrent insertions while examining insert state to
6557  * determine the checkpoint REDO pointer.
6558  */
6560  curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
6561 
6562  /*
6563  * If this isn't a shutdown or forced checkpoint, and if there has been no
6564  * WAL activity requiring a checkpoint, skip it. The idea here is to
6565  * avoid inserting duplicate checkpoints when the system is idle.
6566  */
6568  CHECKPOINT_FORCE)) == 0)
6569  {
6570  if (last_important_lsn == ControlFile->checkPoint)
6571  {
6573  END_CRIT_SECTION();
6574  ereport(DEBUG1,
6575  (errmsg_internal("checkpoint skipped because system is idle")));
6576  return;
6577  }
6578  }
6579 
6580  /*
6581  * An end-of-recovery checkpoint is created before anyone is allowed to
6582  * write WAL. To allow us to write the checkpoint record, temporarily
6583  * enable XLogInsertAllowed.
6584  */
6585  if (flags & CHECKPOINT_END_OF_RECOVERY)
6586  oldXLogAllowed = LocalSetXLogInsertAllowed();
6587 
6588  checkPoint.ThisTimeLineID = XLogCtl->InsertTimeLineID;
6589  if (flags & CHECKPOINT_END_OF_RECOVERY)
6590  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
6591  else
6592  checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
6593 
6594  checkPoint.fullPageWrites = Insert->fullPageWrites;
6595 
6596  /*
6597  * Compute new REDO record ptr = location of next XLOG record.
6598  *
6599  * NB: this is NOT necessarily where the checkpoint record itself will be,
6600  * since other backends may insert more XLOG records while we're off doing
6601  * the buffer flush work. Those XLOG records are logically after the
6602  * checkpoint, even though physically before it. Got that?
6603  */
6604  freespace = INSERT_FREESPACE(curInsert);
6605  if (freespace == 0)
6606  {
6607  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
6608  curInsert += SizeOfXLogLongPHD;
6609  else
6610  curInsert += SizeOfXLogShortPHD;
6611  }
6612  checkPoint.redo = curInsert;
6613 
6614  /*
6615  * Here we update the shared RedoRecPtr for future XLogInsert calls; this
6616  * must be done while holding all the insertion locks.
6617  *
6618  * Note: if we fail to complete the checkpoint, RedoRecPtr will be left
6619  * pointing past where it really needs to point. This is okay; the only
6620  * consequence is that XLogInsert might back up whole buffers that it
6621  * didn't really need to. We can't postpone advancing RedoRecPtr because
6622  * XLogInserts that happen while we are dumping buffers must assume that
6623  * their buffer changes are not included in the checkpoint.
6624  */
6625  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
6626 
6627  /*
6628  * Now we can release the WAL insertion locks, allowing other xacts to
6629  * proceed while we are flushing disk buffers.
6630  */
6632 
6633  /* Update the info_lck-protected copy of RedoRecPtr as well */
6635  XLogCtl->RedoRecPtr = checkPoint.redo;
6637 
6638  /*
6639  * If enabled, log checkpoint start. We postpone this until now so as not
6640  * to log anything if we decided to skip the checkpoint.
6641  */
6642  if (log_checkpoints)
6643  LogCheckpointStart(flags, false);
6644 
6645  /* Update the process title */
6646  update_checkpoint_display(flags, false, false);
6647 
6648  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
6649 
6650  /*
6651  * Get the other info we need for the checkpoint record.
6652  *
6653  * We don't need to save oldestClogXid in the checkpoint, it only matters
6654  * for the short period in which clog is being truncated, and if we crash
6655  * during that we'll redo the clog truncation and fix up oldestClogXid
6656  * there.
6657  */
6658  LWLockAcquire(XidGenLock, LW_SHARED);
6659  checkPoint.nextXid = ShmemVariableCache->nextXid;
6660  checkPoint.oldestXid = ShmemVariableCache->oldestXid;
6662  LWLockRelease(XidGenLock);
6663 
6664  LWLockAcquire(CommitTsLock, LW_SHARED);
6667  LWLockRelease(CommitTsLock);
6668 
6669  LWLockAcquire(OidGenLock, LW_SHARED);
6670  checkPoint.nextOid = ShmemVariableCache->nextOid;
6671  if (!shutdown)
6672  checkPoint.nextOid += ShmemVariableCache->oidCount;
6673  LWLockRelease(OidGenLock);
6674 
6675  MultiXactGetCheckptMulti(shutdown,
6676  &checkPoint.nextMulti,
6677  &checkPoint.nextMultiOffset,
6678  &checkPoint.oldestMulti,
6679  &checkPoint.oldestMultiDB);
6680 
6681  /*
6682  * Having constructed the checkpoint record, ensure all shmem disk buffers
6683  * and commit-log buffers are flushed to disk.
6684  *
6685  * This I/O could fail for various reasons. If so, we will fail to
6686  * complete the checkpoint, but there is no reason to force a system
6687  * panic. Accordingly, exit critical section while doing it.
6688  */
6689  END_CRIT_SECTION();
6690 
6691  /*
6692  * In some cases there are groups of actions that must all occur on one
6693  * side or the other of a checkpoint record. Before flushing the
6694  * checkpoint record we must explicitly wait for any backend currently
6695  * performing those groups of actions.
6696  *
6697  * One example is end of transaction, so we must wait for any transactions
6698  * that are currently in commit critical sections. If an xact inserted
6699  * its commit record into XLOG just before the REDO point, then a crash
6700  * restart from the REDO point would not replay that record, which means
6701  * that our flushing had better include the xact's update of pg_xact. So
6702  * we wait till he's out of his commit critical section before proceeding.
6703  * See notes in RecordTransactionCommit().
6704  *
6705  * Because we've already released the insertion locks, this test is a bit
6706  * fuzzy: it is possible that we will wait for xacts we didn't really need
6707  * to wait for. But the delay should be short and it seems better to make
6708  * checkpoint take a bit longer than to hold off insertions longer than
6709  * necessary. (In fact, the whole reason we have this issue is that xact.c
6710  * does commit record XLOG insertion and clog update as two separate steps
6711  * protected by different locks, but again that seems best on grounds of
6712  * minimizing lock contention.)
6713  *
6714  * A transaction that has not yet set delayChkptFlags when we look cannot
6715  * be at risk, since it has not inserted its commit record yet; and one
6716  * that's already cleared it is not at risk either, since it's done fixing
6717  * clog and we will correctly flush the update below. So we cannot miss
6718  * any xacts we need to wait for.
6719  */
6721  if (nvxids > 0)
6722  {
6723  do
6724  {
6725  pg_usleep(10000L); /* wait for 10 msec */
6726  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6728  }
6729  pfree(vxids);
6730 
6731  CheckPointGuts(checkPoint.redo, flags);
6732 
6734  if (nvxids > 0)
6735  {
6736  do
6737  {
6738  pg_usleep(10000L); /* wait for 10 msec */
6739  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6741  }
6742  pfree(vxids);
6743 
6744  /*
6745  * Take a snapshot of running transactions and write this to WAL. This
6746  * allows us to reconstruct the state of running transactions during
6747  * archive recovery, if required. Skip, if this info disabled.
6748  *
6749  * If we are shutting down, or Startup process is completing crash
6750  * recovery we don't need to write running xact data.
6751  */
6752  if (!shutdown && XLogStandbyInfoActive())
6754 
6756 
6757  /*
6758  * Now insert the checkpoint record into XLOG.
6759  */
6760  XLogBeginInsert();
6761  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
6762  recptr = XLogInsert(RM_XLOG_ID,
6763  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
6765 
6766  XLogFlush(recptr);
6767 
6768  /*
6769  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
6770  * overwritten at next startup. No-one should even try, this just allows
6771  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
6772  * to just temporarily disable writing until the system has exited
6773  * recovery.
6774  */
6775  if (shutdown)
6776  {
6777  if (flags & CHECKPOINT_END_OF_RECOVERY)
6778  LocalXLogInsertAllowed = oldXLogAllowed;
6779  else
6780  LocalXLogInsertAllowed = 0; /* never again write WAL */
6781  }
6782 
6783  /*
6784  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
6785  * = end of actual checkpoint record.
6786  */
6787  if (shutdown && checkPoint.redo != ProcLastRecPtr)
6788  ereport(PANIC,
6789  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
6790 
6791  /*
6792  * Remember the prior checkpoint's redo ptr for
6793  * UpdateCheckPointDistanceEstimate()
6794  */
6795  PriorRedoPtr = ControlFile->checkPointCopy.redo;
6796 
6797  /*
6798  * Update the control file.
6799  */
6800  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6801  if (shutdown)
6804  ControlFile->checkPointCopy = checkPoint;
6805  /* crash recovery should always recover to the end of WAL */
6808 
6809  /*
6810  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
6811  * unused on non-shutdown checkpoints, but seems useful to store it always
6812  * for debugging purposes.
6813  */
6817 
6819  LWLockRelease(ControlFileLock);
6820 
6821  /* Update shared-memory copy of checkpoint XID/epoch */
6823  XLogCtl->ckptFullXid = checkPoint.nextXid;
6825 
6826  /*
6827  * We are now done with critical updates; no need for system panic if we
6828  * have trouble while fooling with old log segments.
6829  */
6830  END_CRIT_SECTION();
6831 
6832  /*
6833  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
6834  */
6836 
6837  /*
6838  * Update the average distance between checkpoints if the prior checkpoint
6839  * exists.
6840  */
6841  if (PriorRedoPtr != InvalidXLogRecPtr)
6843 
6844  /*
6845  * Delete old log files, those no longer needed for last checkpoint to
6846  * prevent the disk holding the xlog from growing full.
6847  */
6849  KeepLogSeg(recptr, &_logSegNo);
6851  _logSegNo, InvalidOid,
6853  {
6854  /*
6855  * Some slots have been invalidated; recalculate the old-segment
6856  * horizon, starting again from RedoRecPtr.
6857  */
6859  KeepLogSeg(recptr, &_logSegNo);
6860  }
6861  _logSegNo--;
6862  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
6863  checkPoint.ThisTimeLineID);
6864 
6865  /*
6866  * Make more log segments if needed. (Do this after recycling old log
6867  * segments, since that may supply some of the needed files.)
6868  */
6869  if (!shutdown)
6870  PreallocXlogFiles(recptr, checkPoint.ThisTimeLineID);
6871 
6872  /*
6873  * Truncate pg_subtrans if possible. We can throw away all data before
6874  * the oldest XMIN of any running transaction. No future transaction will
6875  * attempt to reference any pg_subtrans entry older than that (see Asserts
6876  * in subtrans.c). During recovery, though, we mustn't do this because
6877  * StartupSUBTRANS hasn't been called yet.
6878  */
6879  if (!RecoveryInProgress())
6881 
6882  /* Real work is done; log and update stats. */
6883  LogCheckpointEnd(false);
6884 
6885  /* Reset the process title */
6886  update_checkpoint_display(flags, false, true);
6887 
6888  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
6889  NBuffers,
6893 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
int NBuffers
Definition: globals.c:136
@ LW_SHARED
Definition: lwlock.h:117
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2133
@ DB_SHUTDOWNING
Definition: pg_control.h:92
@ DB_SHUTDOWNED
Definition: pg_control.h:90
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:68
#define InvalidOid
Definition: postgres_ext.h:36
#define DELAY_CHKPT_START
Definition: proc.h:119
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:120
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
Definition: procarray.c:3008
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2845
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:2015
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
Definition: procarray.c:3054
void pg_usleep(long microsec)
Definition: signal.c:53
bool InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, XLogSegNo oldestSegno, Oid dboid, TransactionId snapshotConflictHorizon)
Definition: slot.c:1526
@ RS_INVAL_WAL_REMOVED
Definition: slot.h:48
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:1287
TimestampTz ckpt_start_t
Definition: xlog.h:156
int ckpt_segs_removed
Definition: xlog.h:165
int ckpt_segs_added
Definition: xlog.h:164
int ckpt_bufs_written
Definition: xlog.h:162
int ckpt_segs_recycled
Definition: xlog.h:166
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:166
XLogRecPtr unloggedLSN
Definition: pg_control.h:135
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:167
TransactionId newestCommitTsXid
Definition: transam.h:233
TransactionId oldestXid
Definition: transam.h:222
TransactionId oldestCommitTsXid
Definition: transam.h:232
FullTransactionId ckptFullXid
Definition: xlog.c:466
TimeLineID InsertTimeLineID
Definition: xlog.c:515
slock_t ulsn_lck
Definition: xlog.c:474
XLogRecPtr RedoRecPtr
Definition: xlog.c:465
XLogRecPtr unloggedLSN
Definition: xlog.c:473
TimeLineID PrevTimeLineID
Definition: xlog.c:516
XLogRecPtr RedoRecPtr
Definition: xlog.c:439
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:338
void SyncPreCheckpoint(void)
Definition: sync.c:182
void SyncPostCheckpoint(void)
Definition: sync.c:207
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:256
bool RecoveryInProgress(void)
Definition: xlog.c:5948
static void WALInsertLockRelease(void)
Definition: xlog.c:1379
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1659
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1350
static void UpdateControlFile(void)
Definition: xlog.c:4194
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr, TimeLineID insertTLI)
Definition: xlog.c:3561
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:6246
static XLogRecPtr RedoRecPtr
Definition: xlog.c:276
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:6278
static void PreallocXlogFiles(XLogRecPtr endptr, TimeLineID tli)
Definition: xlog.c:3423
bool log_checkpoints
Definition: xlog.c:132
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:7475
static int LocalSetXLogInsertAllowed(void)
Definition: xlog.c:6036
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:6153
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:6381
static int LocalXLogInsertAllowed
Definition: xlog.c:239
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2535
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:7038
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:6419
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:135
#define CHECKPOINT_FORCE
Definition: xlog.h:137
#define XLogStandbyInfoActive()
Definition: xlog.h:118
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
void XLogRegisterData(char *data, uint32 len)
Definition: xloginsert.c:351
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:461
void XLogBeginInsert(void)
Definition: xloginsert.c:150

References 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, VariableCacheData::newestCommitTsXid, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, VariableCacheData::nextOid, CheckPoint::nextOid, VariableCacheData::nextXid, CheckPoint::nextXid, VariableCacheData::oidCount, CheckPoint::oldestActiveXid, VariableCacheData::oldestCommitTsXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, VariableCacheData::oldestXid, CheckPoint::oldestXid, VariableCacheData::oldestXidDB, CheckPoint::oldestXidDB, PANIC, pfree(), pg_usleep(), PreallocXlogFiles(), XLogCtlData::PrevTimeLineID, CheckPoint::PrevTimeLineID, ProcLastRecPtr, RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), RS_INVAL_WAL_REMOVED, ShmemVariableCache, SizeOfXLogLongPHD, SizeOfXLogShortPHD, SpinLockAcquire, SpinLockRelease, START_CRIT_SECTION, ControlFileData::state, SyncPostCheckpoint(), SyncPreCheckpoint(), CheckPoint::ThisTimeLineID, CheckPoint::time, TruncateSUBTRANS(), XLogCtlData::ulsn_lck, XLogCtlData::unloggedLSN, ControlFileData::unloggedLSN, update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, XLOG_CHECKPOINT_ONLINE, 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 6904 of file xlog.c.

6905 {
6906  xl_end_of_recovery xlrec;
6907  XLogRecPtr recptr;
6908 
6909  /* sanity check */
6910  if (!RecoveryInProgress())
6911  elog(ERROR, "can only be used to end recovery");
6912 
6913  xlrec.end_time = GetCurrentTimestamp();
6914 
6919 
6921 
6922  XLogBeginInsert();
6923  XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery));
6924  recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY);
6925 
6926  XLogFlush(recptr);
6927 
6928  /*
6929  * Update the control file so that crash recovery can follow the timeline
6930  * changes to this point.
6931  */
6932  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6933  ControlFile->minRecoveryPoint = recptr;
6934  ControlFile->minRecoveryPointTLI = xlrec.ThisTimeLineID;
6936  LWLockRelease(ControlFileLock);
6937 
6938  END_CRIT_SECTION();
6939 }
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
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(), 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 6968 of file xlog.c.

6970 {
6972  XLogRecPtr recptr;
6973  XLogPageHeader pagehdr;
6974  XLogRecPtr startPos;
6975 
6976  /* sanity checks */
6977  if (!RecoveryInProgress())
6978  elog(ERROR, "can only be used at end of recovery");
6979  if (pagePtr % XLOG_BLCKSZ != 0)
6980  elog(ERROR, "invalid position for missing continuation record %X/%X",
6981  LSN_FORMAT_ARGS(pagePtr));
6982 
6983  /* The current WAL insert position should be right after the page header */
6984  startPos = pagePtr;
6985  if (XLogSegmentOffset(startPos, wal_segment_size) == 0)
6986  startPos += SizeOfXLogLongPHD;
6987  else
6988  startPos += SizeOfXLogShortPHD;
6989  recptr = GetXLogInsertRecPtr();
6990  if (recptr != startPos)
6991  elog(ERROR, "invalid WAL insert position %X/%X for OVERWRITE_CONTRECORD",
6992  LSN_FORMAT_ARGS(recptr));
6993 
6995 
6996  /*
6997  * Initialize the XLOG page header (by GetXLogBuffer), and set the
6998  * XLP_FIRST_IS_OVERWRITE_CONTRECORD flag.
6999  *
7000  * No other backend is allowed to write WAL yet, so acquiring the WAL
7001  * insertion lock is just pro forma.
7002  */
7004  pagehdr = (XLogPageHeader) GetXLogBuffer(pagePtr, newTLI);
7007 
7008  /*
7009  * Insert the XLOG_OVERWRITE_CONTRECORD record as the first record on the
7010  * page. We know it becomes the first record, because no other backend is
7011  * allowed to write WAL yet.
7012  */
7013  XLogBeginInsert();
7014  xlrec.overwritten_lsn = aborted_lsn;
7016  XLogRegisterData((char *) &xlrec, sizeof(xl_overwrite_contrecord));
7017  recptr = XLogInsert(RM_XLOG_ID, XLOG_OVERWRITE_CONTRECORD);
7018 
7019  /* check that the record was inserted to the right place */
7020  if (ProcLastRecPtr != startPos)
7021  elog(ERROR, "OVERWRITE_CONTRECORD was inserted to unexpected position %X/%X",
7023 
7024  XLogFlush(recptr);
7025 
7026  END_CRIT_SECTION();
7027 
7028  return recptr;
7029 }
#define XLOG_OVERWRITE_CONTRECORD
Definition: pg_control.h:80
static void WALInsertLockAcquire(void)
Definition: xlog.c:1305
XLogRecPtr GetXLogInsertRecPtr(void)
Definition: xlog.c:8923
#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 7119 of file xlog.c.

7120 {
7121  XLogRecPtr lastCheckPointRecPtr;
7122  XLogRecPtr lastCheckPointEndPtr;
7123  CheckPoint lastCheckPoint;
7124  XLogRecPtr PriorRedoPtr;
7125  XLogRecPtr receivePtr;
7126  XLogRecPtr replayPtr;
7127  TimeLineID replayTLI;
7128  XLogRecPtr endptr;
7129  XLogSegNo _logSegNo;
7130  TimestampTz xtime;
7131 
7132  /* Concurrent checkpoint/restartpoint cannot happen */
7134 
7135  /* Get a local copy of the last safe checkpoint record. */
7137  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
7138  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
7139  lastCheckPoint = XLogCtl->lastCheckPoint;
7141 
7142  /*
7143  * Check that we're still in recovery mode. It's ok if we exit recovery
7144  * mode after this check, the restart point is valid anyway.
7145  */
7146  if (!RecoveryInProgress())
7147  {
7148  ereport(DEBUG2,
7149  (errmsg_internal("skipping restartpoint, recovery has already ended")));
7150  return false;
7151  }
7152 
7153  /*
7154  * If the last checkpoint record we've replayed is already our last
7155  * restartpoint, we can't perform a new restart point. We still update
7156  * minRecoveryPoint in that case, so that if this is a shutdown restart
7157  * point, we won't start up earlier than before. That's not strictly
7158  * necessary, but when hot standby is enabled, it would be rather weird if
7159  * the database opened up for read-only connections at a point-in-time
7160  * before the last shutdown. Such time travel is still possible in case of
7161  * immediate shutdown, though.
7162  *
7163  * We don't explicitly advance minRecoveryPoint when we do create a
7164  * restartpoint. It's assumed that flushing the buffers will do that as a
7165  * side-effect.
7166  */
7167  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
7168  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
7169  {
7170  ereport(DEBUG2,
7171  (errmsg_internal("skipping restartpoint, already performed at %X/%X",
7172  LSN_FORMAT_ARGS(lastCheckPoint.redo))));
7173 
7175  if (flags & CHECKPOINT_IS_SHUTDOWN)
7176  {
7177  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7180  LWLockRelease(ControlFileLock);
7181  }
7182  return false;
7183  }
7184 
7185  /*
7186  * Update the shared RedoRecPtr so that the startup process can calculate
7187  * the number of segments replayed since last restartpoint, and request a
7188  * restartpoint if it exceeds CheckPointSegments.
7189  *
7190  * Like in CreateCheckPoint(), hold off insertions to update it, although
7191  * during recovery this is just pro forma, because no WAL insertions are
7192  * happening.
7193  */
7195  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
7197 
7198  /* Also update the info_lck-protected copy */
7200  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
7202 
7203  /*
7204  * Prepare to accumulate statistics.
7205  *
7206  * Note: because it is possible for log_checkpoints to change while a
7207  * checkpoint proceeds, we always accumulate stats, even if
7208  * log_checkpoints is currently off.
7209  */
7210  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
7212 
7213  if (log_checkpoints)
7214  LogCheckpointStart(flags, true);
7215 
7216  /* Update the process title */
7217  update_checkpoint_display(flags, true, false);
7218 
7219  CheckPointGuts(lastCheckPoint.redo, flags);
7220 
7221  /*
7222  * Remember the prior checkpoint's redo ptr for
7223  * UpdateCheckPointDistanceEstimate()
7224  */
7225  PriorRedoPtr = ControlFile->checkPointCopy.redo;
7226 
7227  /*
7228  * Update pg_control, using current time. Check that it still shows an
7229  * older checkpoint, else do nothing; this is a quick hack to make sure
7230  * nothing really bad happens if somehow we get here after the
7231  * end-of-recovery checkpoint.
7232  */
7233  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7234  if (ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
7235  {
7236  /*
7237  * Update the checkpoint information. We do this even if the cluster
7238  * does not show DB_IN_ARCHIVE_RECOVERY to match with the set of WAL
7239  * segments recycled below.
7240  */
7241  ControlFile->checkPoint = lastCheckPointRecPtr;
7242  ControlFile->checkPointCopy = lastCheckPoint;
7243 
7244  /*
7245  * Ensure minRecoveryPoint is past the checkpoint record and update it
7246  * if the control file still shows DB_IN_ARCHIVE_RECOVERY. Normally,
7247  * this will have happened already while writing out dirty buffers,
7248  * but not necessarily - e.g. because no buffers were dirtied. We do
7249  * this because a backup performed in recovery uses minRecoveryPoint
7250  * to determine which WAL files must be included in the backup, and
7251  * the file (or files) containing the checkpoint record must be
7252  * included, at a minimum. Note that for an ordinary restart of
7253  * recovery there's no value in having the minimum recovery point any
7254  * earlier than this anyway, because redo will begin just after the
7255  * checkpoint record.
7256  */
7258  {
7259  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
7260  {
7261  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
7263 
7264  /* update local copy */
7267  }
7268  if (flags & CHECKPOINT_IS_SHUTDOWN)
7270  }
7272  }
7273  LWLockRelease(ControlFileLock);
7274 
7275  /*
7276  * Update the average distance between checkpoints/restartpoints if the
7277  * prior checkpoint exists.
7278  */
7279  if (PriorRedoPtr != InvalidXLogRecPtr)
7281 
7282  /*
7283  * Delete old log files, those no longer needed for last restartpoint to
7284  * prevent the disk holding the xlog from growing full.
7285  */
7287 
7288  /*
7289  * Retreat _logSegNo using the current end of xlog replayed or received,
7290  * whichever is later.
7291  */
7292  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
7293  replayPtr = GetXLogReplayRecPtr(&replayTLI);
7294  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
7295  KeepLogSeg(endptr, &_logSegNo);
7297  _logSegNo, InvalidOid,
7299  {
7300  /*
7301  * Some slots have been invalidated; recalculate the old-segment
7302  * horizon, starting again from RedoRecPtr.
7303  */
7305  KeepLogSeg(endptr, &_logSegNo);
7306  }
7307  _logSegNo--;
7308 
7309  /*
7310  * Try to recycle segments on a useful timeline. If we've been promoted
7311  * since the beginning of this restartpoint, use the new timeline chosen
7312  * at end of recovery. If we're still in recovery, use the timeline we're
7313  * currently replaying.
7314  *
7315  * There is no guarantee that the WAL segments will be useful on the
7316  * current timeline; if recovery proceeds to a new timeline right after
7317  * this, the pre-allocated WAL segments on this timeline will not be used,
7318  * and will go wasted until recycled on the next restartpoint. We'll live
7319  * with that.
7320  */
7321  if (!RecoveryInProgress())
7322  replayTLI = XLogCtl->InsertTimeLineID;
7323 
7324  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, replayTLI);
7325 
7326  /*
7327  * Make more log segments if needed. (Do this after recycling old log
7328  * segments, since that may supply some of the needed files.)
7329  */
7330  PreallocXlogFiles(endptr, replayTLI);
7331 
7332  /*
7333  * Truncate pg_subtrans if possible. We can throw away all data before
7334  * the oldest XMIN of any running transaction. No future transaction will
7335  * attempt to reference any pg_subtrans entry older than that (see Asserts
7336  * in subtrans.c). When hot standby is disabled, though, we mustn't do
7337  * this because StartupSUBTRANS hasn't been called yet.
7338  */
7339  if (EnableHotStandby)
7341 
7342  /* Real work is done; log and update stats. */
7343  LogCheckpointEnd(true);
7344 
7345  /* Reset the process title */
7346  update_checkpoint_display(flags, true, true);
7347 
7348  xtime = GetLatestXTime();
7350  (errmsg("recovery restart point at %X/%X",
7351  LSN_FORMAT_ARGS(lastCheckPoint.redo)),
7352  xtime ? errdetail("Last completed transaction was at log time %s.",
7353  timestamptz_to_str(xtime)) : 0));
7354 
7355  /*
7356  * Finally, execute archive_cleanup_command, if any.
7357  */
7358  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
7360  "archive_cleanup_command",
7361  false,
7362  WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND);
7363 
7364  return true;
7365 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1782
int64 TimestampTz
Definition: timestamp.h:39
#define LOG
Definition: elog.h:31
bool IsUnderPostmaster
Definition: globals.c:113
@ B_CHECKPOINTER
Definition: miscadmin.h:335
BackendType MyBackendType
Definition: miscinit.c:63
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:94
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:91
CheckPoint lastCheckPoint
Definition: xlog.c:551
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:549
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:550
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2455
static XLogRecPtr LocalMinRecoveryPoint
Definition: xlog.c:629
static TimeLineID LocalMinRecoveryPointTLI
Definition: xlog.c:630
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint32 TimeLineID
Definition: xlogdefs.h:59
char * archiveCleanupCommand
Definition: xlogrecovery.c:84
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, 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 8882 of file xlog.c.

8883 {
8884  bool during_backup_start = DatumGetBool(arg);
8885 
8886  /* If called during backup start, there shouldn't be one already running */
8887  Assert(!during_backup_start || sessionBackupState == SESSION_BACKUP_NONE);
8888 
8889  if (during_backup_start || sessionBackupState != SESSION_BACKUP_NONE)
8890  {
8894 
8897 
8898  if (!during_backup_start)
8899  ereport(WARNING,
8900  errmsg("aborting backup due to backend exiting before pg_backup_stop was called"));
8901  }
8902 }
#define WARNING
Definition: elog.h:36
void * arg
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
int runningBackups
Definition: xlog.c:447
static SessionBackupState sessionBackupState
Definition: xlog.c:400
@ SESSION_BACKUP_NONE
Definition: xlog.h:276

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

8295 {
8297 
8298  Assert(state != NULL);
8300 
8301  /*
8302  * During recovery, we don't need to check WAL level. Because, if WAL
8303  * level is not sufficient, it's impossible to get here during recovery.
8304  */
8306  ereport(ERROR,
8307  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8308  errmsg("WAL level not sufficient for making an online backup"),
8309  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8310 
8311  if (strlen(backupidstr) > MAXPGPATH)
8312  ereport(ERROR,
8313  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8314  errmsg("backup label too long (max %d bytes)",
8315  MAXPGPATH)));
8316 
8317  memcpy(state->name, backupidstr, strlen(backupidstr));
8318 
8319  /*
8320  * Mark backup active in shared memory. We must do full-page WAL writes
8321  * during an on-line backup even if not doing so at other times, because
8322  * it's quite possible for the backup dump to obtain a "torn" (partially
8323  * written) copy of a database page if it reads the page concurrently with
8324  * our write to the same page. This can be fixed as long as the first
8325  * write to the page in the WAL sequence is a full-page write. Hence, we
8326  * increment runningBackups then force a CHECKPOINT, to ensure there are
8327  * no dirty pages in shared memory that might get dumped while the backup
8328  * is in progress without having a corresponding WAL record. (Once the
8329  * backup is complete, we need not force full-page writes anymore, since
8330  * we expect that any pages not modified during the backup interval must
8331  * have been correctly captured by the backup.)
8332  *
8333  * Note that forcing full-page writes has no effect during an online
8334  * backup from the standby.
8335  *
8336  * We must hold all the insertion locks to change the value of
8337  * runningBackups, to ensure adequate interlocking against
8338  * XLogInsertRecord().
8339  */
8343 
8344  /*
8345  * Ensure we decrement runningBackups if we fail below. NB -- for this to
8346  * work correctly, it is critical that sessionBackupState is only updated
8347  * after this block is over.
8348  */
8350  {
8351  bool gotUniqueStartpoint = false;
8352  DIR *tblspcdir;
8353  struct dirent *de;
8354  tablespaceinfo *ti;
8355  int datadirpathlen;
8356 
8357  /*
8358  * Force an XLOG file switch before the checkpoint, to ensure that the
8359  * WAL segment the checkpoint is written to doesn't contain pages with
8360  * old timeline IDs. That would otherwise happen if you called
8361  * pg_backup_start() right after restoring from a PITR archive: the
8362  * first WAL segment containing the startup checkpoint has pages in
8363  * the beginning with the old timeline ID. That can cause trouble at
8364  * recovery: we won't have a history file covering the old timeline if
8365  * pg_wal directory was not included in the base backup and the WAL
8366  * archive was cleared too before starting the backup.
8367  *
8368  * This also ensures that we have emitted a WAL page header that has
8369  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
8370  * Therefore, if a WAL archiver (such as pglesslog) is trying to
8371  * compress out removable backup blocks, it won't remove any that
8372  * occur after this point.
8373  *
8374  * During recovery, we skip forcing XLOG file switch, which means that
8375  * the backup taken during recovery is not available for the special
8376  * recovery case described above.
8377  */
8379  RequestXLogSwitch(false);
8380 
8381  do
8382  {
8383  bool checkpointfpw;
8384 
8385  /*
8386  * Force a CHECKPOINT. Aside from being necessary to prevent torn
8387  * page problems, this guarantees that two successive backup runs
8388  * will have different checkpoint positions and hence different
8389  * history file names, even if nothing happened in between.
8390  *
8391  * During recovery, establish a restartpoint if possible. We use
8392  * the last restartpoint as the backup starting checkpoint. This
8393  * means that two successive backup runs can have same checkpoint
8394  * positions.
8395  *
8396  * Since the fact that we are executing do_pg_backup_start()
8397  * during recovery means that checkpointer is running, we can use
8398  * RequestCheckpoint() to establish a restartpoint.
8399  *
8400  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
8401  * passing fast = true). Otherwise this can take awhile.
8402  */
8404  (fast ? CHECKPOINT_IMMEDIATE : 0));
8405 
8406  /*
8407  * Now we need to fetch the checkpoint record location, and also
8408  * its REDO pointer. The oldest point in WAL that would be needed
8409  * to restore starting from the checkpoint is precisely the REDO
8410  * pointer.
8411  */
8412  LWLockAcquire(ControlFileLock, LW_SHARED);
8413  state->checkpointloc = ControlFile->checkPoint;
8414  state->startpoint = ControlFile->checkPointCopy.redo;
8416  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
8417  LWLockRelease(ControlFileLock);
8418 
8420  {
8421  XLogRecPtr recptr;
8422 
8423  /*
8424  * Check to see if all WAL replayed during online backup
8425  * (i.e., since last restartpoint used as backup starting
8426  * checkpoint) contain full-page writes.
8427  */
8429  recptr = XLogCtl->lastFpwDisableRecPtr;
8431 
8432  if (!checkpointfpw || state->startpoint <= recptr)
8433  ereport(ERROR,
8434  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8435  errmsg("WAL generated with full_page_writes=off was replayed "
8436  "since last restartpoint"),
8437  errhint("This means that the backup being taken on the standby "
8438  "is corrupt and should not be used. "
8439  "Enable full_page_writes and run CHECKPOINT on the primary, "
8440  "and then try an online backup again.")));
8441 
8442  /*
8443  * During recovery, since we don't use the end-of-backup WAL
8444  * record and don't write the backup history file, the
8445  * starting WAL location doesn't need to be unique. This means
8446  * that two base backups started at the same time might use
8447  * the same checkpoint as starting locations.
8448  */
8449  gotUniqueStartpoint = true;
8450  }
8451 
8452  /*
8453  * If two base backups are started at the same time (in WAL sender
8454  * processes), we need to make sure that they use different
8455  * checkpoints as starting locations, because we use the starting
8456  * WAL location as a unique identifier for the base backup in the
8457  * end-of-backup WAL record and when we write the backup history
8458  * file. Perhaps it would be better generate a separate unique ID
8459  * for each backup instead of forcing another checkpoint, but
8460  * taking a checkpoint right after another is not that expensive
8461  * either because only few buffers have been dirtied yet.
8462  */
8464  if (XLogCtl->Insert.lastBackupStart < state->startpoint)
8465  {
8466  XLogCtl->Insert.lastBackupStart = state->startpoint;
8467  gotUniqueStartpoint = true;
8468  }
8470  } while (!gotUniqueStartpoint);
8471 
8472  /*
8473  * Construct tablespace_map file.
8474  */
8475  datadirpathlen = strlen(DataDir);
8476 
8477  /* Collect information about all tablespaces */
8478  tblspcdir = AllocateDir("pg_tblspc");
8479  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
8480  {
8481  char fullpath[MAXPGPATH + 10];
8482  char linkpath[MAXPGPATH];
8483  char *relpath = NULL;
8484  char *s;
8485  PGFileType de_type;
8486 
8487  /* Skip anything that doesn't look like a tablespace */
8488  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
8489  continue;
8490 
8491  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
8492 
8493  de_type = get_dirent_type(fullpath, de, false, ERROR);
8494 
8495  if (de_type == PGFILETYPE_LNK)
8496  {
8497  StringInfoData escapedpath;
8498  int rllen;
8499 
8500  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
8501  if (rllen < 0)
8502  {
8503  ereport(WARNING,
8504  (errmsg("could not read symbolic link \"%s\": %m",
8505  fullpath)));
8506  continue;
8507  }
8508  else if (rllen >= sizeof(linkpath))
8509  {
8510  ereport(WARNING,
8511  (errmsg("symbolic link \"%s\" target is too long",
8512  fullpath)));
8513  continue;
8514  }
8515  linkpath[rllen] = '\0';
8516 
8517  /*
8518  * Relpath holds the relative path of the tablespace directory
8519  * when it's located within PGDATA, or NULL if it's located
8520  * elsewhere.
8521  */
8522  if (rllen > datadirpathlen &&
8523  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
8524  IS_DIR_SEP(linkpath[datadirpathlen]))
8525  relpath = pstrdup(linkpath + datadirpathlen + 1);
8526 
8527  /*
8528  * Add a backslash-escaped version of the link path to the
8529  * tablespace map file.
8530  */
8531  initStringInfo(&escapedpath);
8532  for (s = linkpath; *s; s++)
8533  {
8534  if (*s == '\n' || *s == '\r' || *s == '\\')
8535  appendStringInfoChar(&escapedpath, '\\');
8536  appendStringInfoChar(&escapedpath, *s);
8537  }
8538  appendStringInfo(tblspcmapfile, "%s %s\n",
8539  de->d_name, escapedpath.data);
8540  pfree(escapedpath.data);
8541  }
8542  else if (de_type == PGFILETYPE_DIR)
8543  {
8544  /*
8545  * It's possible to use allow_in_place_tablespaces to create
8546  * directories directly under pg_tblspc, for testing purposes
8547  * only.
8548  *
8549  * In this case, we store a relative path rather than an
8550  * absolute path into the tablespaceinfo.
8551  */
8552  snprintf(linkpath, sizeof(linkpath), "pg_tblspc/%s",
8553  de->d_name);
8554  relpath = pstrdup(linkpath);
8555  }
8556  else
8557  {
8558  /* Skip any other file type that appears here. */
8559  continue;
8560  }
8561 
8562  ti = palloc(sizeof(tablespaceinfo));
8563  ti->oid = pstrdup(de->d_name);
8564  ti->path = pstrdup(linkpath);
8565  ti->rpath = relpath;
8566  ti->size = -1;
8567 
8568  if (tablespaces)
8569  *tablespaces = lappend(*tablespaces, ti);
8570  }
8571  FreeDir(tblspcdir);
8572 
8573  state->starttime = (pg_time_t) time(NULL);
8574  }
8576 
8577  state->started_in_recovery = backup_started_in_recovery;
8578 
8579  /*
8580  * Mark that the start phase has correctly finished for the backup.
8581  */
8583 }
static bool backup_started_in_recovery
Definition: basebackup.c:102
void RequestCheckpoint(int flags)
Definition: checkpointer.c:930
int errcode(int sqlerrcode)
Definition: elog.c:858
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:525
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:66
#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:338
#define IS_DIR_SEP(ch)
Definition: port.h:102
#define relpath(rlocator, forknum)
Definition: relpath.h:94
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:557
XLogRecPtr lastBackupStart
Definition: xlog.c:448
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:7568
void do_pg_abort_backup(int code, Datum arg)
Definition: xlog.c:8882
@ SESSION_BACKUP_RUNNING
Definition: xlog.h:277
#define CHECKPOINT_WAIT
Definition: xlog.h:140
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:136
#define XLogIsNeeded()
Definition: xlog.h:104

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, 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, 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 8608 of file xlog.c.

8609 {
8610  bool backup_stopped_in_recovery = false;
8611  char histfilepath[MAXPGPATH];
8612  char lastxlogfilename[MAXFNAMELEN];
8613  char histfilename[MAXFNAMELEN];
8614  XLogSegNo _logSegNo;
8615  FILE *fp;
8616  int seconds_before_warning;
8617  int waits = 0;
8618  bool reported_waiting = false;
8619 
8620  Assert(state != NULL);
8621 
8622  backup_stopped_in_recovery = RecoveryInProgress();
8623 
8624  /*
8625  * During recovery, we don't need to check WAL level. Because, if WAL
8626  * level is not sufficient, it's impossible to get here during recovery.
8627  */
8628  if (!backup_stopped_in_recovery && !XLogIsNeeded())
8629  ereport(ERROR,
8630  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8631  errmsg("WAL level not sufficient for making an online backup"),
8632  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8633 
8634  /*
8635  * OK to update backup counter and session-level lock.
8636  *
8637  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them,
8638  * otherwise they can be updated inconsistently, which might cause
8639  * do_pg_abort_backup() to fail.
8640  */
8642 
8643  /*
8644  * It is expected that each do_pg_backup_start() call is matched by
8645  * exactly one do_pg_backup_stop() call.
8646  */
8649 
8650  /*
8651  * Clean up session-level lock.
8652  *
8653  * You might think that WALInsertLockRelease() can be called before
8654  * cleaning up session-level lock because session-level lock doesn't need
8655  * to be protected with WAL insertion lock. But since
8656  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
8657  * cleaned up before it.
8658  */
8660 
8662 
8663  /*
8664  * If we are taking an online backup from the standby, we confirm that the
8665  * standby has not been promoted during the backup.
8666  */
8667  if (state->started_in_recovery && !backup_stopped_in_recovery)
8668  ereport(ERROR,
8669  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8670  errmsg("the standby was promoted during online backup"),
8671  errhint("This means that the backup being taken is corrupt "
8672  "and should not be used. "
8673  "Try taking another online backup.")));
8674 
8675  /*
8676  * During recovery, we don't write an end-of-backup record. We assume that
8677  * pg_control was backed up last and its minimum recovery point can be
8678  * available as the backup end location. Since we don't have an
8679  * end-of-backup record, we use the pg_control value to check whether
8680  * we've reached the end of backup when starting recovery from this
8681  * backup. We have no way of checking if pg_control wasn't backed up last
8682  * however.
8683  *
8684  * We don't force a switch to new WAL file but it is still possible to
8685  * wait for all the required files to be archived if waitforarchive is
8686  * true. This is okay if we use the backup to start a standby and fetch
8687  * the missing WAL using streaming replication. But in the case of an
8688  * archive recovery, a user should set waitforarchive to true and wait for
8689  * them to be archived to ensure that all the required files are
8690  * available.
8691  *
8692  * We return the current minimum recovery point as the backup end
8693  * location. Note that it can be greater than the exact backup end
8694  * location if the minimum recovery point is updated after the backup of
8695  * pg_control. This is harmless for current uses.
8696  *
8697  * XXX currently a backup history file is for informational and debug
8698  * purposes only. It's not essential for an online backup. Furthermore,
8699  * even if it's created, it will not be archived during recovery because
8700  * an archiver is not invoked. So it doesn't seem worthwhile to write a
8701  * backup history file during recovery.
8702  */
8703  if (backup_stopped_in_recovery)
8704  {
8705  XLogRecPtr recptr;
8706 
8707  /*
8708  * Check to see if all WAL replayed during online backup contain
8709  * full-page writes.
8710  */
8712  recptr = XLogCtl->lastFpwDisableRecPtr;
8714 
8715  if (state->startpoint <= recptr)
8716  ereport(ERROR,
8717  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8718  errmsg("WAL generated with full_page_writes=off was replayed "
8719  "during online backup"),
8720  errhint("This means that the backup being taken on the standby "
8721  "is corrupt and should not be used. "
8722  "Enable full_page_writes and run CHECKPOINT on the primary, "
8723  "and then try an online backup again.")));
8724 
8725 
8726  LWLockAcquire(ControlFileLock, LW_SHARED);
8727  state->stoppoint = ControlFile->minRecoveryPoint;
8729  LWLockRelease(ControlFileLock);
8730  }
8731  else
8732  {
8733  char *history_file;
8734 
8735  /*
8736  * Write the backup-end xlog record
8737  */
8738  XLogBeginInsert();
8739  XLogRegisterData((char *) (&state->startpoint),
8740  sizeof(state->startpoint));
8741  state->stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
8742 
8743  /*
8744  * Given that we're not in recovery, InsertTimeLineID is set and can't
8745  * change, so we can read it without a lock.
8746  */
8747  state->stoptli = XLogCtl->InsertTimeLineID;
8748 
8749  /*
8750  * Force a switch to a new xlog segment file, so that the backup is
8751  * valid as soon as archiver moves out the current segment file.
8752  */
8753  RequestXLogSwitch(false);
8754 
8755  state->stoptime = (pg_time_t) time(NULL);
8756 
8757  /*
8758  * Write the backup history file
8759  */
8760  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
8761  BackupHistoryFilePath(histfilepath, state->stoptli, _logSegNo,
8762  state->startpoint, wal_segment_size);
8763  fp = AllocateFile(histfilepath, "w");
8764  if (!fp)
8765  ereport(ERROR,
8767  errmsg("could not create file \"%s\": %m",
8768  histfilepath)));
8769 
8770  /* Build and save the contents of the backup history file */
8771  history_file = build_backup_content(state, true);
8772  fprintf(fp, "%s", history_file);
8773  pfree(history_file);
8774 
8775  if (fflush(fp) || ferror(fp) || FreeFile(fp))
8776  ereport(ERROR,
8778  errmsg("could not write file \"%s\": %m",
8779  histfilepath)));
8780 
8781  /*
8782  * Clean out any no-longer-needed history files. As a side effect,
8783  * this will post a .ready file for the newly created history file,
8784  * notifying the archiver that history file may be archived
8785  * immediately.
8786  */
8788  }
8789 
8790  /*
8791  * If archiving is enabled, wait for all the required WAL files to be
8792  * archived before returning. If archiving isn't enabled, the required WAL
8793  * needs to be transported via streaming replication (hopefully with
8794  * wal_keep_size set high enough), or some more exotic mechanism like
8795  * polling and copying files from pg_wal with script. We have no knowledge
8796  * of those mechanisms, so it's up to the user to ensure that he gets all
8797  * the required WAL.
8798  *
8799  * We wait until both the last WAL file filled during backup and the
8800  * history file have been archived, and assume that the alphabetic sorting
8801  * property of the WAL files ensures any earlier WAL files are safely
8802  * archived as well.
8803  *
8804  * We wait forever, since archive_command is supposed to work and we
8805  * assume the admin wanted his backup to work completely. If you don't
8806  * wish to wait, then either waitforarchive should be passed in as false,
8807  * or you can set statement_timeout. Also, some notices are issued to
8808  * clue in anyone who might be doing this interactively.
8809  */
8810 
8811  if (waitforarchive &&
8812  ((!backup_stopped_in_recovery && XLogArchivingActive()) ||
8813  (backup_stopped_in_recovery && XLogArchivingAlways())))
8814  {
8815  XLByteToPrevSeg(state->stoppoint, _logSegNo, wal_segment_size);
8816  XLogFileName(lastxlogfilename, state->stoptli, _logSegNo,
8818 
8819  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
8820  BackupHistoryFileName(histfilename, state->stoptli, _logSegNo,
8821  state->startpoint, wal_segment_size);
8822 
8823  seconds_before_warning = 60;
8824  waits = 0;
8825 
8826  while (XLogArchiveIsBusy(lastxlogfilename) ||
8827  XLogArchiveIsBusy(histfilename))
8828  {
8830 
8831  if (!reported_waiting && waits > 5)
8832  {
8833  ereport(NOTICE,
8834  (errmsg("base backup done, waiting for required WAL segments to be archived")));
8835  reported_waiting = true;
8836  }
8837 
8838  (void) WaitLatch(MyLatch,
8840  1000L,
8841  WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE);
8843 
8844  if (++waits >= seconds_before_warning)
8845  {
8846  seconds_before_warning *= 2; /* This wraps in >10 years... */
8847  ereport(WARNING,
8848  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
8849  waits),
8850  errhint("Check that your archive_command is executing properly. "
8851  "You can safely cancel this backup, "
8852  "but the database backup will not be usable without all the WAL segments.")));
8853  }
8854  }
8855 
8856  ereport(NOTICE,
8857  (errmsg("all required WAL segments have been archived")));
8858  }
8859  else if (waitforarchive)
8860  ereport(NOTICE,
8861  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
8862 }
#define NOTICE
Definition: elog.h:35
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2528
int FreeFile(FILE *file)
Definition: fd.c:2726
struct Latch * MyLatch
Definition: globals.c:58
void ResetLatch(Latch *latch)
Definition: latch.c:697
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:490
#define WL_TIMEOUT
Definition: latch.h:128
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
#define WL_LATCH_SET
Definition: latch.h:125
static void const char fflush(stdout)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define XLOG_BACKUP_END
Definition: pg_control.h:72
#define fprintf
Definition: port.h:242
static void CleanupBackupHistory(void)
Definition: xlog.c:3833
#define XLogArchivingAlways()
Definition: xlog.h:97
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:613
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 8589 of file xlog.c.

8590 {
8591  return sessionBackupState;
8592 }

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

8097 {
8098  int o_direct_flag = 0;
8099 
8100  /*
8101  * Use O_DIRECT if requested, except in walreceiver process. The WAL
8102  * written by walreceiver is normally read by the startup process soon
8103  * after it's written. Also, walreceiver performs unaligned writes, which
8104  * don't work with O_DIRECT, so it is required for correctness too.
8105  */
8107  o_direct_flag = PG_O_DIRECT;
8108 
8109  /* If fsync is disabled, never open in sync mode */
8110  if (!enableFsync)
8111  return o_direct_flag;
8112 
8113  switch (method)
8114  {
8115  /*
8116  * enum values for all sync options are defined even if they are
8117  * not supported on the current platform. But if not, they are
8118  * not included in the enum option array, and therefore will never
8119  * be seen here.
8120  */
8121  case SYNC_METHOD_FSYNC:
8123  case SYNC_METHOD_FDATASYNC:
8124  return o_direct_flag;
8125 #ifdef O_SYNC
8126  case SYNC_METHOD_OPEN:
8127  return O_SYNC | o_direct_flag;
8128 #endif
8129 #ifdef O_DSYNC
8131  return O_DSYNC | o_direct_flag;
8132 #endif
8133  default:
8134  /* can't happen (unless we are out of sync with option array) */
8135  elog(ERROR, "unrecognized wal_sync_method: %d", method);
8136  return 0; /* silence warning */
8137  }
8138 }
int io_direct_flags
Definition: fd.c:168
#define IO_DIRECT_WAL
Definition: fd.h:53
#define PG_O_DIRECT
Definition: fd.h:95
bool enableFsync
Definition: globals.c:123
#define AmWalReceiverProcess()
Definition: miscadmin.h:457
#define O_DSYNC
Definition: win32_port.h:352
#define SYNC_METHOD_FSYNC
Definition: xlog.h:22
#define SYNC_METHOD_OPEN
Definition: xlog.h:24
#define SYNC_METHOD_FDATASYNC
Definition: xlog.h:23
#define SYNC_METHOD_OPEN_DSYNC
Definition: xlog.h:26
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:25

References AmWalReceiverProcess, elog(), enableFsync, ERROR, io_direct_flags, IO_DIRECT_WAL, O_DSYNC, PG_O_DIRECT, SYNC_METHOD_FDATASYNC, SYNC_METHOD_FSYNC, SYNC_METHOD_FSYNC_WRITETHROUGH, SYNC_METHOD_OPEN, and SYNC_METHOD_OPEN_DSYNC.

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

◆ GetActiveWalLevelOnStandby()

WalLevel GetActiveWalLevelOnStandby ( void  )

Definition at line 4501 of file xlog.c.

4502 {
4503  return ControlFile->wal_level;
4504 }

References ControlFile, and ControlFileData::wal_level.

Referenced by CheckLogicalDecodingRequirements().

◆ GetFakeLSNForUnloggedRel()

XLogRecPtr GetFakeLSNForUnloggedRel ( void  )

Definition at line 4239 of file xlog.c.

4240 {
4241  XLogRecPtr nextUnloggedLSN;
4242 
4243  /* increment the unloggedLSN counter, need SpinLock */
4245  nextUnloggedLSN = XLogCtl->unloggedLSN++;
4247 
4248  return nextUnloggedLSN;
4249 }

References SpinLockAcquire, SpinLockRelease, XLogCtlData::ulsn_lck, XLogCtlData::unloggedLSN, and XLogCtl.

Referenced by gistGetFakeLSN().

◆ GetFlushRecPtr()

XLogRecPtr GetFlushRecPtr ( TimeLineID insertTLI)

Definition at line 6113 of file xlog.c.

6114 {
6116 
6120 
6121  /*
6122  * If we're writing and flushing WAL, the time line can't be changing, so
6123  * no lock is required.
6124  */
6125  if (insertTLI)
6126  *insertTLI = XLogCtl->InsertTimeLineID;
6127 
6128  return LogwrtResult.Flush;
6129 }
RecoveryState SharedRecoveryState
Definition: xlog.c:522
XLogRecPtr Flush
Definition: xlog.c:337
@ RECOVERY_STATE_DONE
Definition: xlog.h:88

References Assert(), XLogwrtResult::Flush, XLogCtlData::info_lck, XLogCtlData::InsertTimeLineID, XLogCtlData::LogwrtResult, LogwrtResult, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by get_flush_position(), GetCurrentLSN(), 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 6081 of file xlog.c.

6082 {
6083  *RedoRecPtr_p = RedoRecPtr;
6084  *doPageWrites_p = doPageWrites;
6085 }
static bool doPageWrites
Definition: xlog.c:289

References doPageWrites, and RedoRecPtr.

Referenced by XLogCheckBufferNeedsBackup(), and XLogInsert().

◆ GetInsertRecPtr()

XLogRecPtr GetInsertRecPtr ( void  )

Definition at line 6096 of file xlog.c.

6097 {
6098  XLogRecPtr recptr;
6099 
6101  recptr = XLogCtl->LogwrtRqst.Write;
6103 
6104  return recptr;
6105 }

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

6154 {
6156  int i;
6157 
6158  for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
6159  {
6160  XLogRecPtr last_important;
6161 
6162  /*
6163  * Need to take a lock to prevent torn reads of the LSN, which are
6164  * possible on some of the supported platforms. WAL insert locks only
6165  * support exclusive mode, so we have to use that.
6166  */
6168  last_important = WALInsertLocks[i].l.lastImportantAt;
6169  LWLockRelease(&WALInsertLocks[i].l.lock);
6170 
6171  if (res < last_important)
6172  res = last_important;
6173  }
6174 
6175  return res;
6176 }
int i
Definition: isn.c:73
XLogRecPtr lastImportantAt
Definition: xlog.c:380
WALInsertLock l
Definition: xlog.c:392
static WALInsertLockPadded * WALInsertLocks
Definition: xlog.c:565
#define NUM_XLOGINSERT_LOCKS
Definition: xlog.c:153

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

6183 {
6184  pg_time_t result;
6185 
6186  /* Need WALWriteLock, but shared lock is sufficient */
6187  LWLockAcquire(WALWriteLock, LW_SHARED);
6188  result = XLogCtl->lastSegSwitchTime;
6189  *lastSwitchLSN = XLogCtl->lastSegSwitchLSN;
6190  LWLockRelease(WALWriteLock);
6191 
6192  return result;
6193 }
pg_time_t lastSegSwitchTime
Definition: xlog.c:477
XLogRecPtr lastSegSwitchLSN
Definition: xlog.c:478

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

Referenced by CheckArchiveTimeout().

◆ GetMockAuthenticationNonce()

char* GetMockAuthenticationNonce ( void  )

Definition at line 4213 of file xlog.c.

4214 {
4215  Assert(ControlFile != NULL);
4217 }
char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]
Definition: pg_control.h:227

References Assert(), ControlFile, and ControlFileData::mock_authentication_nonce.

Referenced by scram_mock_salt().

◆ GetOldestRestartPoint()

void GetOldestRestartPoint ( XLogRecPtr oldrecptr,
TimeLineID oldtli 
)

Definition at line 8953 of file xlog.c.

8954 {
8955  LWLockAcquire(ControlFileLock, LW_SHARED);
8956  *oldrecptr = ControlFile->checkPointCopy.redo;
8958  LWLockRelease(ControlFileLock);
8959 }

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

5985 {
5986  RecoveryState retval;
5987 
5989  retval = XLogCtl->SharedRecoveryState;
5991 
5992  return retval;
5993 }
RecoveryState
Definition: xlog.h:85

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

Referenced by XLogArchiveCheckDone().

◆ GetRedoRecPtr()

XLogRecPtr GetRedoRecPtr ( void  )

Definition at line 6051 of file xlog.c.

6052 {
6053  XLogRecPtr ptr;
6054 
6055  /*
6056  * The possibly not up-to-date copy in XlogCtl is enough. Even if we
6057  * grabbed a WAL insertion lock to read the authoritative value in
6058  * Insert->RedoRecPtr, someone might update it just after we've released
6059  * the lock.
6060  */
6062  ptr = XLogCtl->RedoRecPtr;
6064 
6065  if (RedoRecPtr < ptr)
6066  RedoRecPtr = ptr;
6067 
6068  return RedoRecPtr;
6069 }

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

Referenced by CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), nextval_internal(), ReplicationSlotReserveWal(), XLogPageRead(), XLogSaveBufferForHint(), and XLogWrite().

◆ GetSystemIdentifier()

uint64 GetSystemIdentifier ( void  )

Definition at line 4203 of file xlog.c.

4204 {
4205  Assert(ControlFile != NULL);
4207 }

References Assert(), ControlFile, and ControlFileData::system_identifier.

Referenced by IdentifySystem(), ReplicationSlotNameForTablesync(), and WalReceiverMain().

◆ GetWALAvailability()

WALAvailability GetWALAvailability ( XLogRecPtr  targetLSN)

Definition at line 7391 of file xlog.c.

7392 {
7393  XLogRecPtr currpos; /* current write LSN */
7394  XLogSegNo currSeg; /* segid of currpos */
7395  XLogSegNo targetSeg; /* segid of targetLSN */
7396  XLogSegNo oldestSeg; /* actual oldest segid */
7397  XLogSegNo oldestSegMaxWalSize; /* oldest segid kept by max_wal_size */
7398  XLogSegNo oldestSlotSeg; /* oldest segid kept by slot */
7399  uint64 keepSegs;
7400 
7401  /*
7402  * slot does not reserve WAL. Either deactivated, or has never been active
7403  */
7404  if (XLogRecPtrIsInvalid(targetLSN))
7405  return WALAVAIL_INVALID_LSN;
7406 
7407  /*
7408  * Calculate the oldest segment currently reserved by all slots,
7409  * considering wal_keep_size and max_slot_wal_keep_size. Initialize
7410  * oldestSlotSeg to the current segment.
7411  */
7412  currpos = GetXLogWriteRecPtr();
7413  XLByteToSeg(currpos, oldestSlotSeg, wal_segment_size);
7414  KeepLogSeg(currpos, &oldestSlotSeg);
7415 
7416  /*
7417  * Find the oldest extant segment file. We get 1 until checkpoint removes
7418  * the first WAL segment file since startup, which causes the status being
7419  * wrong under certain abnormal conditions but that doesn't actually harm.
7420  */
7421  oldestSeg = XLogGetLastRemovedSegno() + 1;
7422 
7423  /* calculate oldest segment by max_wal_size */
7424  XLByteToSeg(currpos, currSeg, wal_segment_size);
7426 
7427  if (currSeg > keepSegs)
7428  oldestSegMaxWalSize = currSeg - keepSegs;
7429  else
7430  oldestSegMaxWalSize = 1;
7431 
7432  /* the segment we care about */
7433  XLByteToSeg(targetLSN, targetSeg, wal_segment_size);
7434 
7435  /*
7436  * No point in returning reserved or extended status values if the
7437  * targetSeg is known to be lost.
7438  */
7439  if (targetSeg >= oldestSlotSeg)
7440  {
7441  /* show "reserved" when targetSeg is within max_wal_size */
7442  if (targetSeg >= oldestSegMaxWalSize)
7443  return WALAVAIL_RESERVED;
7444 
7445  /* being retained by slots exceeding max_wal_size */
7446  return WALAVAIL_EXTENDED;
7447  }
7448 
7449  /* WAL segments are no longer retained but haven't been removed yet */
7450  if (targetSeg >= oldestSeg)
7451  return WALAVAIL_UNRESERVED;
7452 
7453  /* Definitely lost */
7454  return WALAVAIL_REMOVED;
7455 }
XLogSegNo XLogGetLastRemovedSegno(void)
Definition: xlog.c:3491
XLogRecPtr GetXLogWriteRecPtr(void)
Definition: xlog.c:8939
@ WALAVAIL_REMOVED
Definition: xlog.h:188
@ WALAVAIL_RESERVED
Definition: xlog.h:184
@ WALAVAIL_UNRESERVED
Definition: xlog.h:187
@ WALAVAIL_EXTENDED
Definition: xlog.h:185
@ WALAVAIL_INVALID_LSN
Definition: xlog.h:183

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

6137 {
6139 
6140  /* Since the value can't be changing, no lock is required. */
6141  return XLogCtl->InsertTimeLineID;
6142 }

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(), and XLogSendPhysical().

◆ GetXLogBuffer()

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

Definition at line 1548 of file xlog.c.

1549 {
1550  int idx;
1551  XLogRecPtr endptr;
1552  static uint64 cachedPage = 0;
1553  static char *cachedPos = NULL;
1554  XLogRecPtr expectedEndPtr;
1555 
1556  /*
1557  * Fast path for the common case that we need to access again the same
1558  * page as last time.
1559  */
1560  if (ptr / XLOG_BLCKSZ == cachedPage)
1561  {
1562  Assert(((XLogPageHeader) cachedPos)->xlp_magic == XLOG_PAGE_MAGIC);
1563  Assert(((XLogPageHeader) cachedPos)->xlp_pageaddr == ptr - (ptr % XLOG_BLCKSZ));
1564  return cachedPos + ptr % XLOG_BLCKSZ;
1565  }
1566 
1567  /*
1568  * The XLog buffer cache is organized so that a page is always loaded to a
1569  * particular buffer. That way we can easily calculate the buffer a given
1570  * page must be loaded into, from the XLogRecPtr alone.
1571  */
1572  idx = XLogRecPtrToBufIdx(ptr);
1573 
1574  /*
1575  * See what page is loaded in the buffer at the moment. It could be the
1576  * page we're looking for, or something older. It can't be anything newer
1577  * - that would imply the page we're looking for has already been written
1578  * out to disk and evicted, and the caller is responsible for making sure
1579  * that doesn't happen.
1580  *
1581  * However, we don't hold a lock while we read the value. If someone has
1582  * just initialized the page, it's possible that we get a "torn read" of
1583  * the XLogRecPtr if 64-bit fetches are not atomic on this platform. In
1584  * that case we will see a bogus value. That's ok, we'll grab the mapping
1585  * lock (in AdvanceXLInsertBuffer) and retry if we see anything else than
1586  * the page we're looking for. But it means that when we do this unlocked
1587  * read, we might see a value that appears to be ahead of the page we're
1588  * looking for. Don't PANIC on that, until we've verified the value while
1589  * holding the lock.
1590  */
1591  expectedEndPtr = ptr;
1592  expectedEndPtr += XLOG_BLCKSZ - ptr % XLOG_BLCKSZ;
1593 
1594  endptr = XLogCtl->xlblocks[idx];
1595  if (expectedEndPtr != endptr)
1596  {
1597  XLogRecPtr initializedUpto;
1598 
1599  /*
1600  * Before calling AdvanceXLInsertBuffer(), which can block, let others
1601  * know how far we're finished with inserting the record.
1602  *
1603  * NB: If 'ptr' points to just after the page header, advertise a
1604  * position at the beginning of the page rather than 'ptr' itself. If
1605  * there are no other insertions running, someone might try to flush
1606  * up to our advertised location. If we advertised a position after
1607  * the page header, someone might try to flush the page header, even
1608  * though page might actually not be initialized yet. As the first
1609  * inserter on the page, we are effectively responsible for making
1610  * sure that it's initialized, before we let insertingAt to move past
1611  * the page header.
1612  */
1613  if (ptr % XLOG_BLCKSZ == SizeOfXLogShortPHD &&
1614  XLogSegmentOffset(ptr, wal_segment_size) > XLOG_BLCKSZ)
1615  initializedUpto = ptr - SizeOfXLogShortPHD;
1616  else if (ptr % XLOG_BLCKSZ == SizeOfXLogLongPHD &&
1617  XLogSegmentOffset(ptr, wal_segment_size) < XLOG_BLCKSZ)
1618  initializedUpto = ptr - SizeOfXLogLongPHD;
1619  else
1620  initializedUpto = ptr;
1621 
1622  WALInsertLockUpdateInsertingAt(initializedUpto);
1623 
1624  AdvanceXLInsertBuffer(ptr, tli, false);
1625  endptr = XLogCtl->xlblocks[idx];
1626 
1627  if (expectedEndPtr != endptr)
1628  elog(PANIC, "could not find WAL buffer for %X/%X",
1629  LSN_FORMAT_ARGS(ptr));
1630  }
1631  else
1632  {
1633  /*
1634  * Make sure the initialization of the page is visible to us, and
1635  * won't arrive later to overwrite the WAL data we write on the page.
1636  */
1638  }
1639 
1640  /*
1641  * Found the buffer holding this page. Return a pointer to the right
1642  * offset within the page.
1643  */
1644  cachedPage = ptr / XLOG_BLCKSZ;
1645  cachedPos = XLogCtl->pages + idx * (Size) XLOG_BLCKSZ;
1646 
1647  Assert(((XLogPageHeader) cachedPos)->xlp_magic == XLOG_PAGE_MAGIC);
1648  Assert(((XLogPageHeader) cachedPos)->xlp_pageaddr == ptr - (ptr % XLOG_BLCKSZ));
1649 
1650  return cachedPos + ptr % XLOG_BLCKSZ;
1651 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
#define pg_memory_barrier()
Definition: atomics.h:140
static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt)
Definition: xlog.c:1405
static void AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic)
Definition: xlog.c:1786

References AdvanceXLInsertBuffer(), Assert(), elog(), idx(), LSN_FORMAT_ARGS, XLogCtlData::pages, PANIC, 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 8923 of file xlog.c.

8924 {
8926  uint64 current_bytepos;
8927 
8928  SpinLockAcquire(&Insert->insertpos_lck);
8929  current_bytepos = Insert->CurrBytePos;
8930  SpinLockRelease(&Insert->insertpos_lck);
8931 
8932  return XLogBytePosToRecPtr(current_bytepos);
8933 }

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()

◆ InitControlFile()

static void InitControlFile ( uint64  sysidentifier)
static

Definition at line 3876 of file xlog.c.

3877 {
3878  char mock_auth_nonce[MOCK_AUTH_NONCE_LEN];
3879 
3880  /*
3881  * Generate a random nonce. This is used for authentication requests that
3882  * will fail because the user does not exist. The nonce is used to create
3883  * a genuine-looking password challenge for the non-existent user, in lieu
3884  * of an actual stored password.
3885  */
3886  if (!pg_strong_random(mock_auth_nonce, MOCK_AUTH_NONCE_LEN))
3887  ereport(PANIC,
3888  (errcode(ERRCODE_INTERNAL_ERROR),
3889  errmsg("could not generate secret authorization token")));
3890 
3891  memset(ControlFile, 0, sizeof(ControlFileData));
3892  /* Initialize pg_control status fields */
3893  ControlFile->system_identifier = sysidentifier;
3894  memcpy(ControlFile->mock_authentication_nonce, mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
3897 
3898  /* Set important parameter values for use when replaying WAL */
3908 }
bool track_commit_timestamp
Definition: commit_ts.c:102
#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:183
int wal_level
Definition: xlog.c:134
bool wal_log_hints
Definition: xlog.c:126
uint32 bootstrap_data_checksum_version
Definition: bootstrap.c:48
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36

References bootstrap_data_checksum_version, 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 4426 of file xlog.c.

4427 {
4429 
4431  {
4432  struct config_generic *guc;
4433 
4434  guc = find_option("wal_consistency_checking", false, false, ERROR);
4435 
4437 
4438  set_config_option_ext("wal_consistency_checking",
4440  guc->scontext, guc->source, guc->srole,
4441  GUC_ACTION_SET, true, ERROR, false);
4442 
4443  /* checking should not be deferred again */
4445  }
4446 }
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
Definition: guc.c:1163
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:3324
@ GUC_ACTION_SET
Definition: guc.h:197
GucContext scontext
Definition: guc_tables.h:166
GucSource source
Definition: guc_tables.h:164
char * wal_consistency_checking_string
Definition: xlog.c:128

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

3298 {
3299  char path[MAXPGPATH];
3300  struct stat stat_buf;
3301 
3302  Assert(tli != 0);
3303 
3304  XLogFilePath(path, tli, *segno, wal_segment_size);
3305 
3306  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
3308  {
3309  LWLockRelease(ControlFileLock);
3310  return false;
3311  }
3312 
3313  if (!find_free)
3314  {
3315  /* Force installation: get rid of any pre-existing segment file */
3316  durable_unlink(path, DEBUG1);
3317  }
3318  else
3319  {
3320  /* Find a free slot to put it in */
3321  while (stat(path, &stat_buf) == 0)
3322  {
3323  if ((*segno) >= max_segno)
3324  {
3325  /* Failed to find a free slot within specified range */
3326  LWLockRelease(ControlFileLock);
3327  return false;
3328  }
3329  (*segno)++;
3330  XLogFilePath(path, tli, *segno, wal_segment_size);
3331  }
3332  }
3333 
3334  Assert(access(path, F_OK) != 0 && errno == ENOENT);
3335  if (durable_rename(tmppath, path, LOG) != 0)
3336  {
3337  LWLockRelease(ControlFileLock);
3338  /* durable_rename already emitted log message */
3339  return false;
3340  }
3341 
3342  LWLockRelease(ControlFileLock);
3343 
3344  return true;
3345 }
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:824
short access
Definition: preproc-type.c:36
bool InstallXLogFileSegmentActive
Definition: xlog.c:532
#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 8982 of file xlog.c.

8983 {
8984  bool result;
8985 
8986  LWLockAcquire(ControlFileLock, LW_SHARED);
8988  LWLockRelease(ControlFileLock);
8989 
8990  return result;
8991 }

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

8187 {
8188  char *msg = NULL;
8189  instr_time start;
8190 
8191  Assert(tli != 0);
8192 
8193  /*
8194  * Quick exit if fsync is disabled or write() has already synced the WAL
8195  * file.
8196  */
8197  if (!enableFsync ||
8200  return;
8201 
8202  /* Measure I/O timing to sync the WAL file */
8203  if (track_wal_io_timing)
8204  INSTR_TIME_SET_CURRENT(start);
8205  else
8206  INSTR_TIME_SET_ZERO(start);
8207 
8208  pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC);
8209  switch (sync_method)
8210  {
8211  case SYNC_METHOD_FSYNC:
8212  if (pg_fsync_no_writethrough(fd) != 0)
8213  msg = _("could not fsync file \"%s\": %m");
8214  break;
8215 #ifdef HAVE_FSYNC_WRITETHROUGH
8217  if (pg_fsync_writethrough(fd) != 0)
8218  msg = _("could not fsync write-through file \"%s\": %m");
8219  break;
8220 #endif
8221  case SYNC_METHOD_FDATASYNC:
8222  if (pg_fdatasync(fd) != 0)
8223  msg = _("could not fdatasync file \"%s\": %m");
8224  break;
8225  case SYNC_METHOD_OPEN:
8227  /* not reachable */
8228  Assert(false);
8229  break;
8230  default:
8231  elog(PANIC, "unrecognized wal_sync_method: %d", sync_method);
8232  break;
8233  }
8234 
8235  /* PANIC if failed to fsync */
8236  if (msg)
8237  {
8238  char xlogfname[MAXFNAMELEN];
8239  int save_errno = errno;
8240 
8241  XLogFileName(xlogfname, tli, segno, wal_segment_size);
8242  errno = save_errno;
8243  ereport(PANIC,
8245  errmsg(msg, xlogfname)));
8246  }
8247 
8249 
8250  /*
8251  * Increment the I/O timing and the number of times WAL files were synced.
8252  */
8253  if (track_wal_io_timing)
8254  {
8255  instr_time end;
8256 
8259  }
8260 
8262 }
#define _(x)
Definition: elog.c:91
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:416
int pg_fdatasync(int fd)
Definition: fd.c:455
int pg_fsync_writethrough(int fd)
Definition: fd.c:436
#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:454
PgStat_Counter wal_sync
Definition: pgstat.h:452
bool track_wal_io_timing
Definition: xlog.c:140

References _, Assert(), elog(), enableFsync, ereport, errcode_for_file_access(), errmsg(), 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(), sync_method, SYNC_METHOD_FDATASYNC, SYNC_METHOD_FSYNC, SYNC_METHOD_FSYNC_WRITETHROUGH, SYNC_METHOD_OPEN, SYNC_METHOD_OPEN_DSYNC, track_wal_io_timing, wal_segment_size, PgStat_PendingWalStats::wal_sync, PgStat_PendingWalStats::wal_sync_time, and XLogFileName().

Referenced by XLogWalRcvFlush(), and XLogWrite().

◆ KeepLogSeg()

static void KeepLogSeg ( XLogRecPtr  recptr,
XLogSegNo logSegNo 
)
static

Definition at line 7475 of file xlog.c.

7476 {
7477  XLogSegNo currSegNo;
7478  XLogSegNo segno;
7479  XLogRecPtr keep;
7480 
7481  XLByteToSeg(recptr, currSegNo, wal_segment_size);
7482  segno = currSegNo;
7483 
7484  /*
7485  * Calculate how many segments are kept by slots first, adjusting for
7486  * max_slot_wal_keep_size.
7487  */
7489  if (keep != InvalidXLogRecPtr && keep < recptr)
7490  {
7491  XLByteToSeg(keep, segno, wal_segment_size);
7492 
7493  /* Cap by max_slot_wal_keep_size ... */
7494  if (max_slot_wal_keep_size_mb >= 0)
7495  {
7496  uint64 slot_keep_segs;
7497 
7498  slot_keep_segs =
7500 
7501  if (currSegNo - segno > slot_keep_segs)
7502  segno = currSegNo - slot_keep_segs;
7503  }
7504  }
7505 
7506  /* but, keep at least wal_keep_size if that's set */
7507  if (wal_keep_size_mb > 0)
7508  {
7509  uint64 keep_segs;
7510 
7512  if (currSegNo - segno < keep_segs)
7513  {
7514  /* avoid underflow, don't go below 1 */
7515  if (currSegNo <= keep_segs)
7516  segno = 1;
7517  else
7518  segno = currSegNo - keep_segs;
7519  }
7520  }
7521 
7522  /* don't delete WAL segments newer than the calculated segment */
7523  if (segno < *logSegNo)
7524  *logSegNo = segno;
7525 }
int wal_keep_size_mb
Definition: xlog.c:119
static XLogRecPtr XLogGetReplicationSlotMinimumLSN(void)
Definition: xlog.c:2434
int max_slot_wal_keep_size_mb
Definition: xlog.c:138

References ConvertToXSegs, 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 4488 of file xlog.c.

4489 {
4490  Assert(reset || ControlFile == NULL);
4491  ControlFile = palloc(sizeof(ControlFileData));
4492  ReadControlFile();
4493 }
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 6036 of file xlog.c.

6037 {
6038  int oldXLogAllowed = LocalXLogInsertAllowed;
6039 
6041 
6042  return oldXLogAllowed;
6043 }

References LocalXLogInsertAllowed.

Referenced by CreateCheckPoint(), and StartupXLOG().

◆ LogCheckpointEnd()

static void LogCheckpointEnd ( bool  restartpoint)
static

Definition at line 6278 of file xlog.c.

6279 {
6280  long write_msecs,
6281  sync_msecs,
6282  total_msecs,
6283  longest_msecs,
6284  average_msecs;
6285  uint64 average_sync_time;
6286 
6288 
6291 
6294 
6295  /* Accumulate checkpoint timing summary data, in milliseconds. */
6298 
6299  /*
6300  * All of the published timing statistics are accounted for. Only
6301  * continue if a log message is to be written.
6302  */
6303  if (!log_checkpoints)
6304  return;
6305 
6308 
6309  /*
6310  * Timing values returned from CheckpointStats are in microseconds.
6311  * Convert to milliseconds for consistent printing.
6312  */
6313  longest_msecs = (long) ((CheckpointStats.ckpt_longest_sync + 999) / 1000);
6314 
6315  average_sync_time = 0;
6317  average_sync_time = CheckpointStats.ckpt_agg_sync_time /
6319  average_msecs = (long) ((average_sync_time + 999) / 1000);
6320 
6321  /*
6322  * ControlFileLock is not required to see ControlFile->checkPoint and
6323  * ->checkPointCopy here as we are the only updator of those variables at
6324  * this moment.
6325  */
6326  if (restartpoint)
6327  ereport(LOG,
6328  (errmsg("restartpoint complete: wrote %d buffers (%.1f%%); "
6329  "%d WAL file(s) added, %d removed, %d recycled; "
6330  "write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
6331  "sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; "
6332  "distance=%d kB, estimate=%d kB; "
6333  "lsn=%X/%X, redo lsn=%X/%X",
6335  (double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers,
6339  write_msecs / 1000, (int) (write_msecs % 1000),
6340  sync_msecs / 1000, (int) (sync_msecs % 1000),
6341  total_msecs / 1000, (int) (total_msecs % 1000),
6343  longest_msecs / 1000, (int) (longest_msecs % 1000),
6344  average_msecs / 1000, (int) (average_msecs % 1000),
6345  (int) (PrevCheckPointDistance / 1024.0),
6346  (int) (CheckPointDistanceEstimate / 1024.0),
6349  else
6350  ereport(LOG,
6351  (errmsg("checkpoint complete: wrote %d buffers (%.1f%%); "
6352  "%d WAL file(s) added, %d removed, %d recycled; "
6353  "write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; "
6354  "sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; "
6355  "distance=%d kB, estimate=%d kB; "
6356  "lsn=%X/%X, redo lsn=%X/%X",
6358  (double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers,
6362  write_msecs / 1000, (int) (write_msecs % 1000),
6363  sync_msecs / 1000, (int) (sync_msecs % 1000),
6364  total_msecs / 1000, (int) (total_msecs % 1000),
6366  longest_msecs / 1000, (int) (longest_msecs % 1000),
6367  average_msecs / 1000, (int) (average_msecs % 1000),
6368  (int) (PrevCheckPointDistance / 1024.0),
6369  (int) (CheckPointDistanceEstimate / 1024.0),
6372 }
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition: timestamp.c:1695
PgStat_CheckpointerStats PendingCheckpointerStats
uint64 ckpt_agg_sync_time
Definition: xlog.h:170
uint64 ckpt_longest_sync
Definition: xlog.h:169
TimestampTz ckpt_end_t
Definition: xlog.h:160
int ckpt_sync_rels
Definition: xlog.h:168
PgStat_Counter checkpoint_sync_time
Definition: pgstat.h:266
PgStat_Counter checkpoint_write_time
Definition: pgstat.h:265
static double CheckPointDistanceEstimate
Definition: xlog.c:162
static double PrevCheckPointDistance
Definition: xlog.c:163

References ControlFileData::checkPoint, PgStat_CheckpointerStats::checkpoint_sync_time, PgStat_CheckpointerStats::checkpoint_write_time, 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, and TimestampDifferenceMilliseconds().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ LogCheckpointStart()

static void LogCheckpointStart ( int  flags,
bool  restartpoint 
)
static

Definition at line 6246 of file xlog.c.

6247 {
6248  if (restartpoint)
6249  ereport(LOG,
6250  /* translator: the placeholders show checkpoint options */
6251  (errmsg("restartpoint starting:%s%s%s%s%s%s%s%s",
6252  (flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
6253  (flags & CHECKPOINT_END_OF_RECOVERY) ? " end-of-recovery" : "",
6254  (flags & CHECKPOINT_IMMEDIATE) ? " immediate" : "",
6255  (flags & CHECKPOINT_FORCE) ? " force" : "",
6256  (flags & CHECKPOINT_WAIT) ? " wait" : "",
6257  (flags & CHECKPOINT_CAUSE_XLOG) ? " wal" : "",
6258  (flags & CHECKPOINT_CAUSE_TIME) ? " time" : "",
6259  (flags & CHECKPOINT_FLUSH_ALL) ? " flush-all" : "")));
6260  else
6261  ereport(LOG,
6262  /* translator: the placeholders show checkpoint options */
6263  (errmsg("checkpoint starting:%s%s%s%s%s%s%s%s",
6264  (flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
6265  (flags & CHECKPOINT_END_OF_RECOVERY) ? " end-of-recovery" : "",
6266  (flags & CHECKPOINT_IMMEDIATE) ? " immediate" : "",
6267  (flags & CHECKPOINT_FORCE) ? " force" : "",
6268  (flags & CHECKPOINT_WAIT) ? " wait" : "",
6269  (flags & CHECKPOINT_CAUSE_XLOG) ? " wal" : "",
6270  (flags & CHECKPOINT_CAUSE_TIME) ? " time" : "",
6271  (flags & CHECKPOINT_FLUSH_ALL) ? " flush-all" : "")));
6272 }
#define CHECKPOINT_CAUSE_XLOG
Definition: xlog.h:143
#define CHECKPOINT_FLUSH_ALL
Definition: xlog.h:138
#define CHECKPOINT_CAUSE_TIME
Definition: xlog.h:144

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

5899 {
5900  bool promoted = false;
5901 
5902  /*
5903  * Perform a checkpoint to update all our recovery activity to disk.
5904  *
5905  * Note that we write a shutdown checkpoint rather than an on-line one.
5906  * This is not particularly critical, but since we may be assigning a new
5907  * TLI, using a shutdown checkpoint allows us to have the rule that TLI
5908  * only changes in shutdown checkpoints, which allows some extra error
5909  * checking in xlog_redo.
5910  *
5911  * In promotion, only create a lightweight end-of-recovery record instead
5912  * of a full checkpoint. A checkpoint is requested later, after we're
5913  * fully out of recovery mode and already accepting queries.
5914  */
5917  {
5918  promoted = true;
5919 
5920  /*
5921  * Insert a special WAL record to mark the end of recovery, since we
5922  * aren't doing a checkpoint. That means that the checkpointer process
5923  * may likely be in the middle of a time-smoothed restartpoint and
5924  * could continue to be for minutes after this. That sounds strange,
5925  * but the effect is roughly the same and it would be stranger to try
5926  * to come out of the restartpoint and then checkpoint. We request a
5927  * checkpoint later anyway, just for safety.
5928  */
5930  }
5931  else
5932  {
5935  CHECKPOINT_WAIT);
5936  }
5937 
5938  return promoted;
5939 }
static void CreateEndOfRecoveryRecord(void)
Definition: xlog.c:6904
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 3423 of file xlog.c.

3424 {
3425  XLogSegNo _logSegNo;
3426  int lf;
3427  bool added;
3428  char path[MAXPGPATH];
3429  uint64 offset;
3430 
3432  return; /* unlocked check says no */
3433 
3434  XLByteToPrevSeg(endptr, _logSegNo, wal_segment_size);
3435  offset = XLogSegmentOffset(endptr - 1, wal_segment_size);
3436  if (offset >= (uint32) (0.75 * wal_segment_size))
3437  {
3438  _logSegNo++;
3439  lf = XLogFileInitInternal(_logSegNo, tli, &added, path);
3440  if (lf >= 0)
3441  close(lf);
3442  if (added)
3444  }
3445 }
static int XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, bool *added, char *path)
Definition: xlog.c:2943

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

5862 {
5863  /*
5864  * We have reached the end of base backup, as indicated by pg_control. The
5865  * data on disk is now consistent (unless minRecoveryPoint is further
5866  * ahead, which can happen if we crashed during previous recovery). Reset
5867  * backupStartPoint and backupEndPoint, and update minRecoveryPoint to
5868  * make sure we don't allow starting up at an earlier point even if
5869  * recovery is stopped and restarted soon after this.
5870  */
5871  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5872 
5873  if (ControlFile->minRecoveryPoint < EndRecPtr)
5874  {
5875  ControlFile->minRecoveryPoint = EndRecPtr;
5877  }
5878 
5881  ControlFile->backupEndRequired = false;
5883 
5884  LWLockRelease(ControlFileLock);
5885 }
XLogRecPtr backupStartPoint
Definition: pg_control.h:168
bool backupEndRequired
Definition: pg_control.h:170
XLogRecPtr backupEndPoint
Definition: pg_control.h:169

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

3994 {
3995  pg_crc32c crc;
3996  int fd;
3997  static char wal_segsz_str[20];
3998  int r;
3999 
4000  /*
4001  * Read data...
4002  */
4004  O_RDWR | PG_BINARY);
4005  if (fd < 0)
4006  ereport(PANIC,
4008  errmsg("could not open file \"%s\": %m",
4009  XLOG_CONTROL_FILE)));
4010 
4011  pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_READ);
4012  r = read(fd, ControlFile, sizeof(ControlFileData));
4013  if (r != sizeof(ControlFileData))
4014  {
4015  if (r < 0)
4016  ereport(PANIC,
4018  errmsg("could not read file \"%s\": %m",
4019  XLOG_CONTROL_FILE)));
4020  else
4021  ereport(PANIC,
4023  errmsg("could not read file \"%s\": read %d of %zu",
4024  XLOG_CONTROL_FILE, r, sizeof(ControlFileData))));
4025  }
4027 
4028  close(fd);
4029 
4030  /*
4031  * Check for expected pg_control format version. If this is wrong, the
4032  * CRC check will likely fail because we'll be checking the wrong number
4033  * of bytes. Complaining about wrong version will probably be more
4034  * enlightening than complaining about wrong CRC.
4035  */
4036 
4038  ereport(FATAL,
4039  (errmsg("database files are incompatible with server"),
4040  errdetail("The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x),"
4041  " but the server was compiled with PG_CONTROL_VERSION %d (0x%08x).",
4044  errhint("This could be a problem of mismatched byte ordering. It looks like you need to initdb.")));
4045 
4047  ereport(FATAL,
4048  (errmsg("database files are incompatible with server"),
4049  errdetail("The database cluster was initialized with PG_CONTROL_VERSION %d,"
4050  " but the server was compiled with PG_CONTROL_VERSION %d.",
4052  errhint("It looks like you need to initdb.")));
4053 
4054  /* Now check the CRC. */
4055  INIT_CRC32C(crc);
4056  COMP_CRC32C(crc,
4057  (char *) ControlFile,
4058  offsetof(ControlFileData, crc));
4059  FIN_CRC32C(crc);
4060 
4061  if (!EQ_CRC32C(crc, ControlFile->crc))
4062  ereport(FATAL,
4063  (errmsg("incorrect checksum in control file")));
4064 
4065  /*
4066  * Do compatibility checking immediately. If the database isn't
4067  * compatible with the backend executable, we want to abort before we can
4068  * possibly do any damage.
4069  */
4071  ereport(FATAL,
4072  (errmsg("database files are incompatible with server"),
4073  errdetail("The database cluster was initialized with CATALOG_VERSION_NO %d,"
4074  " but the server was compiled with CATALOG_VERSION_NO %d.",
4076  errhint("It looks like you need to initdb.")));
4077  if (ControlFile->maxAlign != MAXIMUM_ALIGNOF)
4078  ereport(FATAL,
4079  (errmsg("database files are incompatible with server"),
4080  errdetail("The database cluster was initialized with MAXALIGN %d,"
4081  " but the server was compiled with MAXALIGN %d.",
4082  ControlFile->maxAlign, MAXIMUM_ALIGNOF),
4083  errhint("It looks like you need to initdb.")));
4085  ereport(FATAL,
4086  (errmsg("database files are incompatible with server"),
4087  errdetail("The database cluster appears to use a different floating-point number format than the server executable."),
4088  errhint("It looks like you need to initdb.")));
4089  if (ControlFile->blcksz != BLCKSZ)
4090  ereport(FATAL,
4091  (errmsg("database files are incompatible with server"),
4092  errdetail("The database cluster was initialized with BLCKSZ %d,"
4093  " but the server was compiled with BLCKSZ %d.",
4094  ControlFile->blcksz, BLCKSZ),
4095  errhint("It looks like you need to recompile or initdb.")));
4096  if (ControlFile->relseg_size != RELSEG_SIZE)
4097  ereport(FATAL,
4098  (errmsg("database files are incompatible with server"),
4099  errdetail("The database cluster was initialized with RELSEG_SIZE %d,"
4100  " but the server was compiled with RELSEG_SIZE %d.",
4101  ControlFile->relseg_size, RELSEG_SIZE),
4102  errhint("It looks like you need to recompile or initdb.")));
4103  if (ControlFile->xlog_blcksz != XLOG_BLCKSZ)
4104  ereport(FATAL,
4105  (errmsg("database files are incompatible with server"),
4106  errdetail("The database cluster was initialized with XLOG_BLCKSZ %d,"
4107  " but the server was compiled with XLOG_BLCKSZ %d.",
4108  ControlFile->xlog_blcksz, XLOG_BLCKSZ),
4109  errhint("It looks like you need to recompile or initdb.")));
4111  ereport(FATAL,
4112  (errmsg("database files are incompatible with server"),
4113  errdetail("The database cluster was initialized with NAMEDATALEN %d,"
4114  " but the server was compiled with NAMEDATALEN %d.",
4116  errhint("It looks like you need to recompile or initdb.")));
4118  ereport(FATAL,
4119  (errmsg("database files are incompatible with server"),
4120  errdetail("The database cluster was initialized with INDEX_MAX_KEYS %d,"
4121  " but the server was compiled with INDEX_MAX_KEYS %d.",
4123  errhint("It looks like you need to recompile or initdb.")));
4125  ereport(FATAL,
4126  (errmsg("database files are incompatible with server"),
4127  errdetail("The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d,"
4128  " but the server was compiled with TOAST_MAX_CHUNK_SIZE %d.",
4130  errhint("It looks like you need to recompile or initdb.")));
4132  ereport(FATAL,
4133  (errmsg("database files are incompatible with server"),
4134  errdetail("The database cluster was initialized with LOBLKSIZE %d,"
4135  " but the server was compiled with LOBLKSIZE %d.",
4136  ControlFile->loblksize, (int) LOBLKSIZE),
4137  errhint("It looks like you need to recompile or initdb.")));
4138 
4139 #ifdef USE_FLOAT8_BYVAL
4140  if (ControlFile->float8ByVal != true)
4141  ereport(FATAL,
4142  (errmsg("database files are incompatible with server"),
4143  errdetail("The database cluster was initialized without USE_FLOAT8_BYVAL"
4144  " but the server was compiled with USE_FLOAT8_BYVAL."),
4145  errhint("It looks like you need to recompile or initdb.")));
4146 #else
4147  if (ControlFile->float8ByVal != false)
4148  ereport(FATAL,
4149  (errmsg("database files are incompatible with server"),
4150  errdetail("The database cluster was initialized with USE_FLOAT8_BYVAL"
4151  " but the server was compiled without USE_FLOAT8_BYVAL."),
4152  errhint("It looks like you need to recompile or initdb.")));
4153 #endif
4154 
4156 
4158  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4159  errmsg_plural("invalid WAL segment size in control file (%d byte)",
4160  "invalid WAL segment size in control file (%d bytes)",
4163  errdetail("The WAL segment size must be a power of two between 1 MB and 1 GB.")));
4164 
4165  snprintf(wal_segsz_str, sizeof(wal_segsz_str), "%d", wal_segment_size);
4166  SetConfigOption("wal_segment_size", wal_segsz_str, PGC_INTERNAL,
4168 
4169  /* check and update variables dependent on wal_segment_size */
4171  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4172  errmsg("\"min_wal_size\" must be at least twice \"wal_segment_size\"")));
4173 
4175  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4176  errmsg("\"max_wal_size\" must be at least twice \"wal_segment_size\"")));
4177 
4179  (wal_segment_size / XLOG_BLCKSZ * UsableBytesInPage) -
4181 
4182