Hi!
* Patch needs rebase by CFbot
Rebased the patches onto the current master and marked them as v4.
Best wishes,
--
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
From 689539285dd813a682507ce310b45c978d67b065 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyota....@gmail.com>
Date: Wed, 4 Sep 2024 16:15:16 +0900
Subject: [PATCH 1/3] Split file-related parts from xlog_internal.h
Some modules that require XLOG file manipulation had to include
xlog_internal.h, which contains excessively detailed internal
information. This commit separates the file and file path-related
components into xlogfilepaths.h, thereby avoiding the exposure of
unrelated details of the XLOG module.
---
src/backend/access/transam/timeline.c | 1 -
src/backend/postmaster/pgarch.c | 1 -
src/backend/utils/adt/genfile.c | 1 -
src/bin/initdb/initdb.c | 1 +
src/bin/pg_archivecleanup/pg_archivecleanup.c | 2 +-
src/bin/pg_basebackup/pg_basebackup.c | 4 +-
src/bin/pg_basebackup/pg_receivewal.c | 1 +
src/bin/pg_basebackup/receivelog.c | 2 +-
src/bin/pg_basebackup/streamutil.c | 2 +-
src/bin/pg_controldata/pg_controldata.c | 1 -
src/bin/pg_rewind/pg_rewind.c | 2 +-
src/include/access/xlog.h | 13 +-
src/include/access/xlog_internal.h | 178 +-------------
src/include/access/xlogfilepaths.h | 219 ++++++++++++++++++
14 files changed, 230 insertions(+), 198 deletions(-)
create mode 100644 src/include/access/xlogfilepaths.h
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index a27f27cc037..710e92297e3 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -38,7 +38,6 @@
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogarchive.h"
-#include "access/xlogdefs.h"
#include "pgstat.h"
#include "storage/fd.h"
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 7e622ae4bd2..4db8a00b849 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -30,7 +30,6 @@
#include <unistd.h>
#include "access/xlog.h"
-#include "access/xlog_internal.h"
#include "archive/archive_module.h"
#include "archive/shell_archive.h"
#include "lib/binaryheap.h"
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index 80bb807fbe9..af4c148c809 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -21,7 +21,6 @@
#include <dirent.h>
#include "access/htup_details.h"
-#include "access/xlog_internal.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_tablespace_d.h"
#include "catalog/pg_type.h"
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 22b7d31b165..6768ef84c7c 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -65,6 +65,7 @@
#endif
#include "access/xlog_internal.h"
+#include "lib/stringinfo.h"
#include "catalog/pg_authid_d.h"
#include "catalog/pg_class_d.h"
#include "catalog/pg_collation_d.h"
diff --git a/src/bin/pg_archivecleanup/pg_archivecleanup.c b/src/bin/pg_archivecleanup/pg_archivecleanup.c
index c25348bcb85..edf1828bc73 100644
--- a/src/bin/pg_archivecleanup/pg_archivecleanup.c
+++ b/src/bin/pg_archivecleanup/pg_archivecleanup.c
@@ -15,7 +15,7 @@
#include <signal.h>
#include <sys/time.h>
-#include "access/xlog_internal.h"
+#include "access/xlogfilepaths.h"
#include "common/logging.h"
#include "getopt_long.h"
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 1da4bfc2351..01f36e1c38e 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -25,7 +25,7 @@
#include <zlib.h>
#endif
-#include "access/xlog_internal.h"
+#include "access/xlogfilepaths.h"
#include "astreamer_inject.h"
#include "backup/basebackup.h"
#include "common/compression.h"
@@ -35,6 +35,8 @@
#include "fe_utils/option_utils.h"
#include "fe_utils/recovery_gen.h"
#include "getopt_long.h"
+#include "pgtime.h"
+#include "port/pg_bswap.h"
#include "receivelog.h"
#include "streamutil.h"
diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c
index de3584018b0..4facc35f845 100644
--- a/src/bin/pg_basebackup/pg_receivewal.c
+++ b/src/bin/pg_basebackup/pg_receivewal.c
@@ -27,6 +27,7 @@
#include <zlib.h>
#endif
+//#include "access/xlogfilepaths.h"
#include "access/xlog_internal.h"
#include "common/file_perm.h"
#include "common/logging.h"
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 6b6e32dfbdf..4f72ed42e11 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -18,7 +18,7 @@
#include <sys/stat.h>
#include <unistd.h>
-#include "access/xlog_internal.h"
+#include "access/xlogfilepaths.h"
#include "common/logging.h"
#include "libpq-fe.h"
#include "receivelog.h"
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 8e605f43ffe..62eb0586dc4 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -17,7 +17,7 @@
#include <sys/time.h>
#include <unistd.h>
-#include "access/xlog_internal.h"
+#include "access/xlogfilepaths.h"
#include "common/connect.h"
#include "common/file_perm.h"
#include "common/logging.h"
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index bea779eef94..162f087626d 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -22,7 +22,6 @@
#include "access/transam.h"
#include "access/xlog.h"
-#include "access/xlog_internal.h"
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
#include "common/logging.h"
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index 2c8b1a07007..a625105fbcc 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -15,7 +15,7 @@
#include <unistd.h>
#include "access/timeline.h"
-#include "access/xlog_internal.h"
+#include "access/xlogfilepaths.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index d313099c027..7ef9264fabc 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -16,6 +16,7 @@
#include "datatype/timestamp.h"
#include "lib/stringinfo.h"
#include "nodes/pg_list.h"
+#include "access/xlogfilepaths.h"
/* Sync methods */
@@ -299,16 +300,4 @@ extern void do_pg_abort_backup(int code, Datum arg);
extern void register_persistent_abort_backup_handler(void);
extern SessionBackupState get_backup_status(void);
-/* File path names (all relative to $PGDATA) */
-#define RECOVERY_SIGNAL_FILE "recovery.signal"
-#define STANDBY_SIGNAL_FILE "standby.signal"
-#define BACKUP_LABEL_FILE "backup_label"
-#define BACKUP_LABEL_OLD "backup_label.old"
-
-#define TABLESPACE_MAP "tablespace_map"
-#define TABLESPACE_MAP_OLD "tablespace_map.old"
-
-/* files to signal promotion to primary */
-#define PROMOTE_SIGNAL_FILE "promote"
-
#endif /* XLOG_H */
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 2cf8d55d706..5e846e48073 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -21,6 +21,7 @@
#include "access/xlogdefs.h"
#include "access/xlogreader.h"
+#include "access/xlogfilepaths.h"
#include "datatype/timestamp.h"
#include "lib/stringinfo.h"
#include "pgtime.h"
@@ -84,187 +85,10 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
#define XLogPageHeaderSize(hdr) \
(((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
-/* wal_segment_size can range from 1MB to 1GB */
-#define WalSegMinSize 1024 * 1024
-#define WalSegMaxSize 1024 * 1024 * 1024
-/* default number of min and max wal segments */
-#define DEFAULT_MIN_WAL_SEGS 5
-#define DEFAULT_MAX_WAL_SEGS 64
-
-/* check that the given size is a valid wal_segment_size */
-#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
-#define IsValidWalSegSize(size) \
- (IsPowerOf2(size) && \
- ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
-
-#define XLogSegmentsPerXLogId(wal_segsz_bytes) \
- (UINT64CONST(0x100000000) / (wal_segsz_bytes))
-
-#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
- (dest) = (segno) * (wal_segsz_bytes) + (offset)
-
-#define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
- ((xlogptr) & ((wal_segsz_bytes) - 1))
-
-/*
- * Compute a segment number from an XLogRecPtr.
- *
- * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
- * a boundary byte is taken to be in the previous segment. This is suitable
- * for deciding which segment to write given a pointer to a record end,
- * for example.
- */
-#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
- logSegNo = (xlrp) / (wal_segsz_bytes)
-
-#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
- logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
-
-/*
- * Convert values of GUCs measured in megabytes to equiv. segment count.
- * Rounds down.
- */
-#define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
- ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
-
-/*
- * Is an XLogRecPtr within a particular XLOG segment?
- *
- * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
- * a boundary byte is taken to be in the previous segment.
- */
-#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
- (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
-
-#define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
- ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
-
/* Check if an XLogRecPtr value is in a plausible range */
#define XRecOffIsValid(xlrp) \
((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD)
-/*
- * The XLog directory and control file (relative to $PGDATA)
- */
-#define XLOGDIR "pg_wal"
-#define XLOG_CONTROL_FILE "global/pg_control"
-
-/*
- * These macros encapsulate knowledge about the exact layout of XLog file
- * names, timeline history file names, and archive-status file names.
- */
-#define MAXFNAMELEN 64
-
-/* Length of XLog file name */
-#define XLOG_FNAME_LEN 24
-
-/*
- * Generate a WAL segment file name. Do not use this function in a helper
- * function allocating the result generated.
- */
-static inline void
-XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
-{
- snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
- (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
- (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
-}
-
-static inline void
-XLogFileNameById(char *fname, TimeLineID tli, uint32 log, uint32 seg)
-{
- snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg);
-}
-
-static inline bool
-IsXLogFileName(const char *fname)
-{
- return (strlen(fname) == XLOG_FNAME_LEN && \
- strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN);
-}
-
-/*
- * XLOG segment with .partial suffix. Used by pg_receivewal and at end of
- * archive recovery, when we want to archive a WAL segment but it might not
- * be complete yet.
- */
-static inline bool
-IsPartialXLogFileName(const char *fname)
-{
- return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
- strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
- strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
-}
-
-static inline void
-XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
-{
- uint32 log;
- uint32 seg;
-
- sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
- *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
-}
-
-static inline void
-XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
-{
- snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
- (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
- (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
-}
-
-static inline void
-TLHistoryFileName(char *fname, TimeLineID tli)
-{
- snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
-}
-
-static inline bool
-IsTLHistoryFileName(const char *fname)
-{
- return (strlen(fname) == 8 + strlen(".history") &&
- strspn(fname, "0123456789ABCDEF") == 8 &&
- strcmp(fname + 8, ".history") == 0);
-}
-
-static inline void
-TLHistoryFilePath(char *path, TimeLineID tli)
-{
- snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
-}
-
-static inline void
-StatusFilePath(char *path, const char *xlog, const char *suffix)
-{
- snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
-}
-
-static inline void
-BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
-{
- snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
- (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
- (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
- (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
-}
-
-static inline bool
-IsBackupHistoryFileName(const char *fname)
-{
- return (strlen(fname) > XLOG_FNAME_LEN &&
- strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
- strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
-}
-
-static inline void
-BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
-{
- snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
- (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
- (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
- (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
-}
/*
* Information logged when we detect a change in one of the parameters
diff --git a/src/include/access/xlogfilepaths.h b/src/include/access/xlogfilepaths.h
new file mode 100644
index 00000000000..cdde2ccae4f
--- /dev/null
+++ b/src/include/access/xlogfilepaths.h
@@ -0,0 +1,219 @@
+/*
+ * xlogfilepaths.h
+ *
+ * File name definitions and handling macros for PostgreSQL write-ahead logs.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogfilepaths.h
+ */
+#ifndef XLOG_FILEPATHS_H
+#define XLOG_FILEPATHS_H
+
+#include "access/xlogdefs.h"
+
+/*
+ * The XLog directory and files (relative to $PGDATA)
+ */
+#define XLOGDIR "pg_wal"
+
+/* control files */
+#define XLOG_CONTROL_FILE "global/pg_control"
+#define BACKUP_LABEL_FILE "backup_label"
+#define BACKUP_LABEL_OLD "backup_label.old"
+
+/* tablespace map */
+#define TABLESPACE_MAP "tablespace_map"
+#define TABLESPACE_MAP_OLD "tablespace_map.old"
+
+/* files to signal run mode to standby */
+#define RECOVERY_SIGNAL_FILE "recovery.signal"
+#define STANDBY_SIGNAL_FILE "standby.signal"
+
+/* files to signal promotion to primary */
+#define PROMOTE_SIGNAL_FILE "promote"
+
+/* wal_segment_size can range from 1MB to 1GB */
+#define WalSegMinSize 1024 * 1024
+#define WalSegMaxSize 1024 * 1024 * 1024
+
+/* default number of min and max wal segments */
+#define DEFAULT_MIN_WAL_SEGS 5
+#define DEFAULT_MAX_WAL_SEGS 64
+
+
+/*
+ * These macros encapsulate knowledge about the exact layout of XLog file
+ * names, timeline history file names, and archive-status file names.
+ */
+#define MAXFNAMELEN 64
+
+/* Length of XLog file name */
+#define XLOG_FNAME_LEN 24
+
+/* check that the given size is a valid wal_segment_size */
+#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
+#define IsValidWalSegSize(size) \
+ (IsPowerOf2(size) && \
+ ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
+
+/* Number of segments in a logical XLOG file */
+#define XLogSegmentsPerXLogId(wal_segsz_bytes) \
+ (UINT64CONST(0x100000000) / (wal_segsz_bytes))
+
+/*
+ * Compute an XLogRecPtr from a segment number and offset.
+ */
+#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
+ (dest) = (segno) * (wal_segsz_bytes) + (offset)
+/*
+ * Compute a segment number from an XLogRecPtr.
+ *
+ * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
+ * a boundary byte is taken to be in the previous segment. This is suitable
+ * for deciding which segment to write given a pointer to a record end,
+ * for example.
+ */
+#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = (xlrp) / (wal_segsz_bytes)
+
+#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
+
+/* Compute the in-segment offset from an XLogRecPtr. */
+#define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
+ ((xlogptr) & ((wal_segsz_bytes) - 1))
+
+/*
+ * Convert values of GUCs measured in megabytes to equiv. segment count.
+ * Rounds down.
+ */
+#define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
+ ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
+
+/*
+ * Is an XLogRecPtr within a particular XLOG segment?
+ *
+ * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
+ * a boundary byte is taken to be in the previous segment.
+ */
+#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
+
+#define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
+
+/*
+ * XLOG file name handling functions
+ */
+static inline void
+StatusFilePath(char *path, const char *xlog, const char *suffix)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
+}
+
+static inline bool
+IsTLHistoryFileName(const char *fname)
+{
+ return (strlen(fname) == 8 + strlen(".history") &&
+ strspn(fname, "0123456789ABCDEF") == 8 &&
+ strcmp(fname + 8, ".history") == 0);
+}
+
+static inline void
+XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
+{
+ uint32 log;
+ uint32 seg;
+
+ sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
+ *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
+}
+
+static inline void
+XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
+}
+
+/*
+ * Generate a WAL segment file name. Do not use this function in a helper
+ * function allocating the result generated.
+ */
+static inline void
+XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
+}
+
+static inline void
+XLogFileNameById(char *fname, TimeLineID tli, uint32 log, uint32 seg)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg);
+}
+
+static inline bool
+IsXLogFileName(const char *fname)
+{
+ return (strlen(fname) == XLOG_FNAME_LEN && \
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN);
+}
+
+/*
+ * XLOG segment with .partial suffix. Used by pg_receivewal and at end of
+ * archive recovery, when we want to archive a WAL segment but it might not
+ * be complete yet.
+ */
+static inline bool
+IsPartialXLogFileName(const char *fname)
+{
+ return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
+ strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
+}
+
+static inline void
+TLHistoryFileName(char *fname, TimeLineID tli)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
+}
+
+static inline void
+TLHistoryFilePath(char *path, TimeLineID tli)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
+}
+
+static inline void
+BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
+}
+
+static inline bool
+IsBackupHistoryFileName(const char *fname)
+{
+ return (strlen(fname) > XLOG_FNAME_LEN &&
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
+ strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
+}
+
+static inline void
+BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
+}
+
+
+#endif /* XLOG_FILEPATHS_H */
--
2.48.1
From 8c9254604e4fd28658a218070e0f7d30e05d563d Mon Sep 17 00:00:00 2001
From: "Anton A. Melnikov" <a.melni...@postgrespro.ru>
Date: Sat, 7 Sep 2024 10:18:51 +0300
Subject: [PATCH 2/3] Extract size-related macros from xlogfilepaths.h to
xlogfilesize.h
---
src/include/access/xlogfilepaths.h | 65 +----------------------
src/include/access/xlogfilesize.h | 83 ++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+), 63 deletions(-)
create mode 100644 src/include/access/xlogfilesize.h
diff --git a/src/include/access/xlogfilepaths.h b/src/include/access/xlogfilepaths.h
index cdde2ccae4f..ed28cf975e6 100644
--- a/src/include/access/xlogfilepaths.h
+++ b/src/include/access/xlogfilepaths.h
@@ -12,6 +12,7 @@
#define XLOG_FILEPATHS_H
#include "access/xlogdefs.h"
+#include "access/xlogfilesize.h"
/*
* The XLog directory and files (relative to $PGDATA)
@@ -34,75 +35,13 @@
/* files to signal promotion to primary */
#define PROMOTE_SIGNAL_FILE "promote"
-/* wal_segment_size can range from 1MB to 1GB */
-#define WalSegMinSize 1024 * 1024
-#define WalSegMaxSize 1024 * 1024 * 1024
-/* default number of min and max wal segments */
-#define DEFAULT_MIN_WAL_SEGS 5
-#define DEFAULT_MAX_WAL_SEGS 64
-
-
-/*
- * These macros encapsulate knowledge about the exact layout of XLog file
- * names, timeline history file names, and archive-status file names.
- */
+/* Maximum length of XLog file name including possible suffix */
#define MAXFNAMELEN 64
/* Length of XLog file name */
#define XLOG_FNAME_LEN 24
-/* check that the given size is a valid wal_segment_size */
-#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
-#define IsValidWalSegSize(size) \
- (IsPowerOf2(size) && \
- ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
-
-/* Number of segments in a logical XLOG file */
-#define XLogSegmentsPerXLogId(wal_segsz_bytes) \
- (UINT64CONST(0x100000000) / (wal_segsz_bytes))
-
-/*
- * Compute an XLogRecPtr from a segment number and offset.
- */
-#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
- (dest) = (segno) * (wal_segsz_bytes) + (offset)
-/*
- * Compute a segment number from an XLogRecPtr.
- *
- * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
- * a boundary byte is taken to be in the previous segment. This is suitable
- * for deciding which segment to write given a pointer to a record end,
- * for example.
- */
-#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
- logSegNo = (xlrp) / (wal_segsz_bytes)
-
-#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
- logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
-
-/* Compute the in-segment offset from an XLogRecPtr. */
-#define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
- ((xlogptr) & ((wal_segsz_bytes) - 1))
-
-/*
- * Convert values of GUCs measured in megabytes to equiv. segment count.
- * Rounds down.
- */
-#define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
- ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
-
-/*
- * Is an XLogRecPtr within a particular XLOG segment?
- *
- * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
- * a boundary byte is taken to be in the previous segment.
- */
-#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
- (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
-
-#define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
- ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
/*
* XLOG file name handling functions
diff --git a/src/include/access/xlogfilesize.h b/src/include/access/xlogfilesize.h
new file mode 100644
index 00000000000..fef30e02a62
--- /dev/null
+++ b/src/include/access/xlogfilesize.h
@@ -0,0 +1,83 @@
+/*
+ * xlogfilesize.h
+ *
+ * Size definitions and handling macros for PostgreSQL write-ahead logs.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogfilesize.h
+ */
+
+#ifndef XLOG_FILESIZE_H
+#define XLOG_FILESIZE_H
+
+#include "access/xlogdefs.h"
+
+/* wal_segment_size can range from 1MB to 1GB */
+#define WalSegMinSize 1024 * 1024
+#define WalSegMaxSize 1024 * 1024 * 1024
+
+/* default number of min and max wal segments */
+#define DEFAULT_MIN_WAL_SEGS 5
+#define DEFAULT_MAX_WAL_SEGS 64
+
+/*
+ * These macros encapsulate knowledge about the exact layout of XLog
+ * files, timeline history fils and archive-status fils.
+ */
+
+/* check that the given size is a valid wal_segment_size */
+#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
+#define IsValidWalSegSize(size) \
+ (IsPowerOf2(size) && \
+ ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
+
+/* Number of segments in a logical XLOG file */
+#define XLogSegmentsPerXLogId(wal_segsz_bytes) \
+ (UINT64CONST(0x100000000) / (wal_segsz_bytes))
+
+/*
+ * Compute an XLogRecPtr from a segment number and offset.
+ */
+#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
+ (dest) = (segno) * (wal_segsz_bytes) + (offset)
+/*
+ * Compute a segment number from an XLogRecPtr.
+ *
+ * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
+ * a boundary byte is taken to be in the previous segment. This is suitable
+ * for deciding which segment to write given a pointer to a record end,
+ * for example.
+ */
+#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = (xlrp) / (wal_segsz_bytes)
+
+#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
+
+/* Compute the in-segment offset from an XLogRecPtr. */
+#define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
+ ((xlogptr) & ((wal_segsz_bytes) - 1))
+
+/*
+ * Convert values of GUCs measured in megabytes to equiv. segment count.
+ * Rounds down.
+ */
+#define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
+ ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
+
+/*
+ * Is an XLogRecPtr within a particular XLOG segment?
+ *
+ * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
+ * a boundary byte is taken to be in the previous segment.
+ */
+#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
+
+#define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
+
+
+#endif /* XLOG_FILESIZE_H */
--
2.48.1
From 2df6b6cb767c9bddcb27da838cbce5ea40053a4e Mon Sep 17 00:00:00 2001
From: "Anton A. Melnikov" <a.melni...@postgrespro.ru>
Date: Wed, 4 Sep 2024 16:23:23 +0900
Subject: [PATCH 3/3] Use XLOG_CONTROL_FILE macro everywhere in C code
---
src/backend/backup/basebackup.c | 2 +-
src/backend/postmaster/postmaster.c | 2 +-
src/bin/pg_combinebackup/pg_combinebackup.c | 5 +++--
src/bin/pg_controldata/pg_controldata.c | 3 ++-
src/bin/pg_rewind/filemap.c | 3 ++-
src/bin/pg_rewind/pg_rewind.c | 8 ++++----
src/bin/pg_upgrade/controldata.c | 7 ++++---
src/bin/pg_verifybackup/pg_verifybackup.c | 3 ++-
src/common/controldata_utils.c | 2 +-
9 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c
index 3f8a3c55725..f0813eda8d7 100644
--- a/src/backend/backup/basebackup.c
+++ b/src/backend/backup/basebackup.c
@@ -1349,7 +1349,7 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
/* Skip pg_control here to back up it last */
- if (strcmp(pathbuf, "./global/pg_control") == 0)
+ if (strcmp(pathbuf, "./" XLOG_CONTROL_FILE) == 0)
continue;
if (lstat(pathbuf, &statbuf) != 0)
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a0c37532d2f..7b5f6c37a95 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1516,7 +1516,7 @@ checkControlFile(void)
char path[MAXPGPATH];
FILE *fp;
- snprintf(path, sizeof(path), "%s/global/pg_control", DataDir);
+ snprintf(path, sizeof(path), "%s/%s", DataDir, XLOG_CONTROL_FILE);
fp = AllocateFile(path, PG_BINARY_R);
if (fp == NULL)
diff --git a/src/bin/pg_combinebackup/pg_combinebackup.c b/src/bin/pg_combinebackup/pg_combinebackup.c
index 050260ee832..01241a8fb60 100644
--- a/src/bin/pg_combinebackup/pg_combinebackup.c
+++ b/src/bin/pg_combinebackup/pg_combinebackup.c
@@ -24,6 +24,7 @@
#include <linux/fs.h>
#endif
+#include "access/xlogfilepaths.h"
#include "backup_label.h"
#include "common/checksum_helper.h"
#include "common/controldata_utils.h"
@@ -300,7 +301,7 @@ main(int argc, char *argv[])
{
char *controlpath;
- controlpath = psprintf("%s/%s", prior_backup_dirs[i], "global/pg_control");
+ controlpath = psprintf("%s/%s", prior_backup_dirs[i], XLOG_CONTROL_FILE);
pg_fatal("%s: manifest system identifier is %llu, but control file has %llu",
controlpath,
@@ -614,7 +615,7 @@ check_control_files(int n_backups, char **backup_dirs)
bool crc_ok;
char *controlpath;
- controlpath = psprintf("%s/%s", backup_dirs[i], "global/pg_control");
+ controlpath = psprintf("%s/%s", backup_dirs[i], XLOG_CONTROL_FILE);
pg_log_debug("reading \"%s\"", controlpath);
control_file = get_controlfile_by_exact_path(controlpath, &crc_ok);
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 162f087626d..d3714c629b3 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -1,7 +1,8 @@
/*
* pg_controldata
*
- * reads the data from $PGDATA/global/pg_control
+ * reads the data from reads the data from the control file
+ * which is located at $PGDATA/XLOG_CONTROL_FILE
*
* copyright (c) Oliver Elphick <o...@lfix.co.uk>, 2001;
* license: BSD
diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c
index a28d1667d4c..3ef38f329cb 100644
--- a/src/bin/pg_rewind/filemap.c
+++ b/src/bin/pg_rewind/filemap.c
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "access/xlogfilepaths.h"
#include "catalog/pg_tablespace_d.h"
#include "common/file_utils.h"
#include "common/hashfn_unstable.h"
@@ -704,7 +705,7 @@ decide_file_action(file_entry_t *entry)
* Don't touch the control file. It is handled specially, after copying
* all the other files.
*/
- if (strcmp(path, "global/pg_control") == 0)
+ if (strcmp(path, XLOG_CONTROL_FILE) == 0)
return FILE_ACTION_NONE;
/* Skip macOS system files */
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index a625105fbcc..d32439fbfaf 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -328,7 +328,7 @@ main(int argc, char **argv)
* need to make sure by themselves that the target cluster is in a clean
* state.
*/
- buffer = slurpFile(datadir_target, "global/pg_control", &size);
+ buffer = slurpFile(datadir_target, XLOG_CONTROL_FILE, &size);
digestControlFile(&ControlFile_target, buffer, size);
pg_free(buffer);
@@ -338,12 +338,12 @@ main(int argc, char **argv)
{
ensureCleanShutdown(argv[0]);
- buffer = slurpFile(datadir_target, "global/pg_control", &size);
+ buffer = slurpFile(datadir_target, XLOG_CONTROL_FILE, &size);
digestControlFile(&ControlFile_target, buffer, size);
pg_free(buffer);
}
- buffer = source->fetch_file(source, "global/pg_control", &size);
+ buffer = source->fetch_file(source, XLOG_CONTROL_FILE, &size);
digestControlFile(&ControlFile_source, buffer, size);
pg_free(buffer);
@@ -636,7 +636,7 @@ perform_rewind(filemap_t *filemap, rewind_source *source,
* Fetch the control file from the source last. This ensures that the
* minRecoveryPoint is up-to-date.
*/
- buffer = source->fetch_file(source, "global/pg_control", &size);
+ buffer = source->fetch_file(source, XLOG_CONTROL_FILE, &size);
digestControlFile(&ControlFile_source_after, buffer, size);
pg_free(buffer);
diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c
index 47ee27ec835..4af699d7d1e 100644
--- a/src/bin/pg_upgrade/controldata.c
+++ b/src/bin/pg_upgrade/controldata.c
@@ -12,6 +12,7 @@
#include <ctype.h>
#include <limits.h> /* for CHAR_MIN */
+#include "access/xlogfilepaths.h"
#include "common/string.h"
#include "pg_upgrade.h"
@@ -757,10 +758,10 @@ disable_old_cluster(transferMode transfer_mode)
new_path[MAXPGPATH];
/* rename pg_control so old server cannot be accidentally started */
- prep_status("Adding \".old\" suffix to old global/pg_control");
+ prep_status("Adding \".old\" suffix to old " XLOG_CONTROL_FILE);
- snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata);
- snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata);
+ snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, XLOG_CONTROL_FILE);
+ snprintf(new_path, sizeof(new_path), "%s/%s.old", old_cluster.pgdata, XLOG_CONTROL_FILE);
if (pg_mv_file(old_path, new_path) != 0)
pg_fatal("could not rename file \"%s\" to \"%s\": %m",
old_path, new_path);
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index 84edd2cdca5..df5466553fa 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <time.h>
+#include "access/xlogfilepaths.h"
#include "common/logging.h"
#include "common/parse_manifest.h"
#include "fe_utils/simple_list.h"
@@ -730,7 +731,7 @@ verify_plain_backup_file(verifier_context *context, char *relpath,
* version 1.
*/
if (context->manifest->version != 1 &&
- strcmp(relpath, "global/pg_control") == 0)
+ strcmp(relpath, XLOG_CONTROL_FILE) == 0)
verify_control_file(fullpath, context->manifest->system_identifier);
/* Update statistics for progress report, if necessary */
diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c
index 34d8a3a4e31..fa375dc9129 100644
--- a/src/common/controldata_utils.c
+++ b/src/common/controldata_utils.c
@@ -53,7 +53,7 @@ get_controlfile(const char *DataDir, bool *crc_ok_p)
{
char ControlFilePath[MAXPGPATH];
- snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
+ snprintf(ControlFilePath, MAXPGPATH, "%s/%s", DataDir, XLOG_CONTROL_FILE);
return get_controlfile_by_exact_path(ControlFilePath, crc_ok_p);
}
--
2.48.1