summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2025-10-23 15:57:46 +0900
committerMichael Paquier <michael@paquier.xyz>2025-10-23 15:57:46 +0900
commit6ae08d9583e9a5e951286948bdd9fcd58e67718a (patch)
treec0ae8f924e923da5d5cb4bb67109201006d0d957
parentabc2b71383b4c49c2fbda74c281d50f3936551b8 (diff)
pg_rewind: Extend code detecting relation files to work with WAL files
isRelDataFile() is renamed to getFileContentType(), extended so as it becomes able to detect more file patterns than only relation files. The new file name pattern that can be detected is WAL files. This refactoring has been suggested by Robert Haas. This will be used in a follow-up patch where we are looking at improving how WAL files are processed by pg_rewind. As of this change, WAL files are still handled the same way as previously, always copied from the source to the target server. Extracted from a larger patch by the same authors. Author: John Hsu <johnhyvr@gmail.com> Author: Justin Kwan <justinpkwan@outlook.com> Reviewed-by: Japin Li <japinli@hotmail.com> Reviewed-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com> Discussion: https://postgr.es/m/181b4c6fa9c.b8b725681941212.7547232617810891479@viggy28.dev
-rw-r--r--src/bin/pg_rewind/filemap.c60
-rw-r--r--src/bin/pg_rewind/filemap.h9
-rw-r--r--src/tools/pgindent/typedefs.list1
3 files changed, 48 insertions, 22 deletions
diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c
index c933871ca9f..00f5d60d620 100644
--- a/src/bin/pg_rewind/filemap.c
+++ b/src/bin/pg_rewind/filemap.c
@@ -55,7 +55,7 @@
static filehash_hash *filehash;
-static bool isRelDataFile(const char *path);
+static file_content_type_t getFileContentType(const char *path);
static char *datasegpath(RelFileLocator rlocator, ForkNumber forknum,
BlockNumber segno);
@@ -210,7 +210,7 @@ insert_filehash_entry(const char *path)
if (!found)
{
entry->path = pg_strdup(path);
- entry->isrelfile = isRelDataFile(path);
+ entry->content_type = getFileContentType(path);
entry->target_exists = false;
entry->target_type = FILE_TYPE_UNDEFINED;
@@ -294,7 +294,7 @@ process_source_file(const char *path, file_type_t type, size_t size,
* sanity check: a filename that looks like a data file better be a
* regular file
*/
- if (type != FILE_TYPE_REGULAR && isRelDataFile(path))
+ if (type != FILE_TYPE_REGULAR && getFileContentType(path) == FILE_CONTENT_TYPE_RELATION)
pg_fatal("data file \"%s\" in source is not a regular file", path);
/* Remember this source file */
@@ -383,7 +383,7 @@ process_target_wal_block_change(ForkNumber forknum, RelFileLocator rlocator,
*/
if (entry)
{
- Assert(entry->isrelfile);
+ Assert(entry->content_type == FILE_CONTENT_TYPE_RELATION);
if (entry->target_exists)
{
@@ -560,22 +560,35 @@ print_filemap(filemap_t *filemap)
}
/*
- * Does it look like a relation data file?
- *
- * For our purposes, only files belonging to the main fork are considered
- * relation files. Other forks are always copied in toto, because we cannot
- * reliably track changes to them, because WAL only contains block references
- * for the main fork.
+ * Determine what kind of file this one looks like.
*/
-static bool
-isRelDataFile(const char *path)
+static file_content_type_t
+getFileContentType(const char *path)
{
RelFileLocator rlocator;
unsigned int segNo;
int nmatch;
- bool matched;
+ file_content_type_t result = FILE_CONTENT_TYPE_OTHER;
+
+ /* Check if it is a WAL file. */
+ if (strncmp("pg_wal/", path, 7) == 0)
+ {
+ const char *filename = path + 7; /* Skip "pg_wal/" */
+
+ if (IsXLogFileName(filename))
+ return FILE_CONTENT_TYPE_WAL;
+ else
+ return FILE_CONTENT_TYPE_OTHER;
+ }
/*----
+ * Does it look like a relation data file?
+ *
+ * For our purposes, only files belonging to the main fork are considered
+ * relation files. Other forks are always copied in toto, because we
+ * cannot reliably track changes to them, because WAL only contains block
+ * references for the main fork.
+ *
* Relation data files can be in one of the following directories:
*
* global/
@@ -598,14 +611,14 @@ isRelDataFile(const char *path)
rlocator.dbOid = InvalidOid;
rlocator.relNumber = InvalidRelFileNumber;
segNo = 0;
- matched = false;
+ result = FILE_CONTENT_TYPE_OTHER;
nmatch = sscanf(path, "global/%u.%u", &rlocator.relNumber, &segNo);
if (nmatch == 1 || nmatch == 2)
{
rlocator.spcOid = GLOBALTABLESPACE_OID;
rlocator.dbOid = 0;
- matched = true;
+ result = FILE_CONTENT_TYPE_RELATION;
}
else
{
@@ -614,7 +627,7 @@ isRelDataFile(const char *path)
if (nmatch == 2 || nmatch == 3)
{
rlocator.spcOid = DEFAULTTABLESPACE_OID;
- matched = true;
+ result = FILE_CONTENT_TYPE_RELATION;
}
else
{
@@ -622,7 +635,7 @@ isRelDataFile(const char *path)
&rlocator.spcOid, &rlocator.dbOid, &rlocator.relNumber,
&segNo);
if (nmatch == 3 || nmatch == 4)
- matched = true;
+ result = FILE_CONTENT_TYPE_RELATION;
}
}
@@ -632,17 +645,17 @@ isRelDataFile(const char *path)
* creates the exact same filename, when passed the RelFileLocator
* information we extracted from the filename.
*/
- if (matched)
+ if (result == FILE_CONTENT_TYPE_RELATION)
{
char *check_path = datasegpath(rlocator, MAIN_FORKNUM, segNo);
if (strcmp(check_path, path) != 0)
- matched = false;
+ result = FILE_CONTENT_TYPE_OTHER;
pfree(check_path);
}
- return matched;
+ return result;
}
/*
@@ -799,7 +812,12 @@ decide_file_action(file_entry_t *entry)
return FILE_ACTION_NONE;
case FILE_TYPE_REGULAR:
- if (!entry->isrelfile)
+ if (entry->content_type == FILE_CONTENT_TYPE_WAL)
+ {
+ /* It's a WAL file, copy it. */
+ return FILE_ACTION_COPY;
+ }
+ else if (entry->content_type != FILE_CONTENT_TYPE_RELATION)
{
/*
* It's a non-data file that we have no special processing
diff --git a/src/bin/pg_rewind/filemap.h b/src/bin/pg_rewind/filemap.h
index df78a02e3da..fada420fc23 100644
--- a/src/bin/pg_rewind/filemap.h
+++ b/src/bin/pg_rewind/filemap.h
@@ -36,6 +36,13 @@ typedef enum
FILE_TYPE_SYMLINK,
} file_type_t;
+typedef enum
+{
+ FILE_CONTENT_TYPE_OTHER = 0,
+ FILE_CONTENT_TYPE_RELATION,
+ FILE_CONTENT_TYPE_WAL
+} file_content_type_t;
+
/*
* For every file found in the local or remote system, we have a file entry
* that contains information about the file on both systems. For relation
@@ -51,7 +58,7 @@ typedef struct file_entry_t
uint32 status; /* hash status */
const char *path;
- bool isrelfile; /* is it a relation data file? */
+ file_content_type_t content_type;
/*
* Status of the file in the target.
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 377a7946585..c13f92988ee 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3622,6 +3622,7 @@ fe_scram_state
fe_scram_state_enum
fetch_range_request
file_action_t
+file_content_type_t
file_entry_t
file_type_t
filehash_hash