include-all-tli-files-in-backup-1.patch
text/x-diff
Filename: include-all-tli-files-in-backup-1.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/replication/basebackup.c | 76 | 1 |
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 65200c1..5c0deaa 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -12,12 +12,13 @@
*/
#include "postgres.h"
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
-#include "access/xlog_internal.h" /* for pg_start/stop_backup */
+#include "access/xlog_internal.h"
#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "libpq/libpq.h"
@@ -44,6 +45,7 @@ typedef struct
static int64 sendDir(char *path, int basepathlen, bool sizeonly);
+static void sendTimeLineHistoryFiles(void);
static void sendFile(char *readfilename, char *tarfilename,
struct stat * statbuf);
static void sendFileWithContent(const char *filename, const char *content);
@@ -286,6 +288,27 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
break;
}
+ /*
+ * Include all timeline history files.
+ *
+ * The timeline history files are usually not strictly required to
+ * restore the backup, but if you take a backup from a standby server,
+ * and the WAL segment containing the checkpoint record contains WAL
+ * from an older timeline, recovery will complain on the older
+ * timeline's ID if there is no timeline history file listing it. This
+ * can happen if you take a backup right after promoting a standby to
+ * become new master, and take the backup from a different, cascading
+ * standby server.
+ *
+ * However, even when not strictly required, the timeline history
+ * files are tiny, and provide a lot of forensic information about the
+ * recovery history of the database, so it's best to always include
+ * them all. (If asked to include WAL, that is. Otherwise you need a
+ * WAL archive to restore anyway, and the timeline history files
+ * should be present in the archive)
+ */
+ sendTimeLineHistoryFiles();
+
/* Send CopyDone message for the last tar file */
pq_putemptymessage('c');
}
@@ -726,6 +749,58 @@ sendDir(char *path, int basepathlen, bool sizeonly)
return size;
}
+/*
+ * Include all timeline history files from pg_xlog in the output tar stream.
+ */
+static void
+sendTimeLineHistoryFiles(void)
+{
+ DIR *dir;
+ struct dirent *de;
+ char pathbuf[MAXPGPATH];
+ struct stat statbuf;
+
+ dir = AllocateDir("./pg_xlog");
+ while ((de = ReadDir(dir, "./pg_xlog")) != NULL)
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ if (strlen(de->d_name) == 8 + strlen(".history") &&
+ strspn(de->d_name, "0123456789ABCDEF") == 8 &&
+ strcmp(de->d_name + 8, ".history") == 0)
+ {
+ /* It looks like a timeline history file. Include it. */
+ snprintf(pathbuf, MAXPGPATH, "./pg_xlog/%s", de->d_name);
+
+ if (lstat(pathbuf, &statbuf) != 0)
+ {
+ if (errno != ENOENT)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not stat file or directory \"%s\": %m",
+ pathbuf)));
+
+ /* If the file went away while scanning, it's no error. */
+ continue;
+ }
+
+ if (!S_ISREG(statbuf.st_mode))
+ {
+ /*
+ * Huh? It's named like a timeline history file, but isn't a
+ * regular file.
+ */
+ ereport(WARNING,
+ (errmsg("skipping special file \"%s\"", pathbuf)));
+ continue;
+ }
+
+ sendFile(pathbuf, pathbuf + 1, &statbuf);
+ }
+ }
+ FreeDir(dir);
+}
+
/*****
* Functions for handling tar file format
*