recovery-in-pgcontrol-v7-0001-add-info-to-manifest.patch
text/x-diff
Filename: recovery-in-pgcontrol-v7-0001-add-info-to-manifest.patch
Type: text/x-diff
Part: 0
Patch
Format: format-patch
Series: patch v7-0001
Subject: Add label and start/stop time to backup manifest.
| File | + | − |
|---|---|---|
| doc/src/sgml/backup-manifest.sgml | 51 | 0 |
| src/backend/backup/backup_manifest.c | 54 | 2 |
| src/backend/backup/basebackup.c | 8 | 1 |
| src/bin/pg_verifybackup/parse_manifest.c | 40 | 0 |
| src/include/backup/backup_manifest.h | 4 | 1 |
From 97bb113b5bf5427449b748c3ee25b647a2c5fef5 Mon Sep 17 00:00:00 2001
From: David Steele <david@pgmasters.net>
Date: Sun, 19 Nov 2023 16:54:36 +0000
Subject: Add label and start/stop time to backup manifest.
Add label passed by the user to pg_basebackup and backup start/stop time to
the backup_manifest file. Currently these fields are purely for informational
purposes.
---
doc/src/sgml/backup-manifest.sgml | 51 +++++++++++++++++++++
src/backend/backup/backup_manifest.c | 56 +++++++++++++++++++++++-
src/backend/backup/basebackup.c | 9 +++-
src/bin/pg_verifybackup/parse_manifest.c | 40 +++++++++++++++++
src/include/backup/backup_manifest.h | 5 ++-
5 files changed, 157 insertions(+), 4 deletions(-)
diff --git a/doc/src/sgml/backup-manifest.sgml b/doc/src/sgml/backup-manifest.sgml
index 771be1310a..a80b79e587 100644
--- a/doc/src/sgml/backup-manifest.sgml
+++ b/doc/src/sgml/backup-manifest.sgml
@@ -42,6 +42,16 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>Backup-Label</literal></term>
+ <listitem>
+ <para>
+ Backup label specified by the user. This will be set to a default value
+ if no backup label was specified.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>Files</literal></term>
<listitem>
@@ -67,6 +77,17 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>Time-Range</literal></term>
+ <listitem>
+ <para>
+ The associated value is always an object describing the start/stop time
+ of the backup. The structure of this object is further described in
+ <xref linkend="backup-manifest-time-range" />.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>Manifest-Checksum</literal></term>
<listitem>
@@ -213,4 +234,34 @@
for the same timeline.
</para>
</sect1>
+
+ <sect1 id="backup-manifest-time-range">
+ <title>Backup Manifest Time Range Object</title>
+
+ <para>
+ The object which describes the time range always has three keys:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>Start-Time</literal></term>
+ <listitem>
+ <para>
+ The start time for the backup.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>End-Time</literal></term>
+ <listitem>
+ <para>
+ The end time for the backup. This is when the backup was stopped in
+ <productname>PostgreSQL</productname> and represents the earliest time
+ that can be used for time-based Point-In-Time Recovery.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect1>
</chapter>
diff --git a/src/backend/backup/backup_manifest.c b/src/backend/backup/backup_manifest.c
index aeed362a9a..9540f05964 100644
--- a/src/backend/backup/backup_manifest.c
+++ b/src/backend/backup/backup_manifest.c
@@ -56,7 +56,8 @@ IsManifestEnabled(backup_manifest_info *manifest)
void
InitializeBackupManifest(backup_manifest_info *manifest,
backup_manifest_option want_manifest,
- pg_checksum_type manifest_checksum_type)
+ pg_checksum_type manifest_checksum_type,
+ const char *label)
{
memset(manifest, 0, sizeof(backup_manifest_info));
manifest->checksum_type = manifest_checksum_type;
@@ -78,9 +79,21 @@ InitializeBackupManifest(backup_manifest_info *manifest,
manifest->still_checksumming = true;
if (want_manifest != MANIFEST_OPTION_NO)
+ {
+ StringInfoData buf;
+
AppendToManifest(manifest,
"{ \"PostgreSQL-Backup-Manifest-Version\": 1,\n"
- "\"Files\": [");
+ "\"Backup-Label\": ");
+
+ /* JSON encode label and add it to manifest */
+ initStringInfo(&buf);
+ escape_json(&buf, label);
+ AppendStringToManifest(manifest, buf.data);
+ pfree(buf.data);
+
+ AppendToManifest(manifest, ",\n\"Files\": [");
+ }
}
/*
@@ -308,6 +321,45 @@ AddWALInfoToBackupManifest(backup_manifest_info *manifest, XLogRecPtr startptr,
AppendStringToManifest(manifest, "\n],\n");
}
+/*
+ * Add backup start/end time information to the manifest.
+ */
+void
+AddTimeInfoToBackupManifest(backup_manifest_info *manifest, pg_time_t starttime,
+ pg_time_t endtime)
+{
+ StringInfoData buf;
+
+ if (!IsManifestEnabled(manifest))
+ return;
+
+ /* Start the time range. */
+ AppendStringToManifest(manifest, "\"Time-Range\": { ");
+
+ /*
+ * Convert start/end time to strings and append them to the manifest. Since
+ * it's not clear what time zone to use and since time zone definitions can
+ * change, possibly causing confusion, use GMT always.
+ */
+ initStringInfo(&buf);
+
+ appendStringInfoString(&buf, "\"Start-Time\": \"");
+ enlargeStringInfo(&buf, 128);
+ buf.len += pg_strftime(&buf.data[buf.len], 128, "%Y-%m-%d %H:%M:%S %Z",
+ pg_gmtime(&starttime));
+ appendStringInfoString(&buf, "\", \"End-Time\": \"");
+ enlargeStringInfo(&buf, 128);
+ buf.len += pg_strftime(&buf.data[buf.len], 128, "%Y-%m-%d %H:%M:%S %Z",
+ pg_gmtime(&endtime));
+ appendStringInfoString(&buf, "\" },\n");
+
+ /* Add to the manifest. */
+ AppendStringToManifest(manifest, buf.data);
+
+ /* Avoid leaking memory. */
+ pfree(buf.data);
+}
+
/*
* Finalize the backup manifest, and send it to the client.
*/
diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c
index 35dd79babc..c7b3ba3e6e 100644
--- a/src/backend/backup/basebackup.c
+++ b/src/backend/backup/basebackup.c
@@ -225,6 +225,8 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
bbsink_state state;
XLogRecPtr endptr;
TimeLineID endtli;
+ pg_time_t starttime;
+ pg_time_t stoptime;
backup_manifest_info manifest;
BackupState *backup_state;
StringInfo tablespace_map;
@@ -243,7 +245,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
backup_started_in_recovery = RecoveryInProgress();
InitializeBackupManifest(&manifest, opt->manifest,
- opt->manifest_checksum_type);
+ opt->manifest_checksum_type, opt->label);
total_checksum_failures = 0;
@@ -380,6 +382,10 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
endptr = backup_state->stoppoint;
endtli = backup_state->stoptli;
+ /* Record start/stop time for manifest */
+ starttime = backup_state->starttime;
+ stoptime = backup_state->stoptime;
+
/* Deallocate backup-related variables. */
pfree(tablespace_map->data);
pfree(tablespace_map);
@@ -629,6 +635,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
AddWALInfoToBackupManifest(&manifest, state.startptr, state.starttli,
endptr, endtli);
+ AddTimeInfoToBackupManifest(&manifest, starttime, stoptime);
SendBackupManifest(&manifest, sink);
diff --git a/src/bin/pg_verifybackup/parse_manifest.c b/src/bin/pg_verifybackup/parse_manifest.c
index bf0227c668..408af88e58 100644
--- a/src/bin/pg_verifybackup/parse_manifest.c
+++ b/src/bin/pg_verifybackup/parse_manifest.c
@@ -25,6 +25,7 @@ typedef enum
JM_EXPECT_TOPLEVEL_END,
JM_EXPECT_TOPLEVEL_FIELD,
JM_EXPECT_VERSION_VALUE,
+ JM_EXPECT_BACKUP_LABEL_VALUE,
JM_EXPECT_FILES_START,
JM_EXPECT_FILES_NEXT,
JM_EXPECT_THIS_FILE_FIELD,
@@ -33,6 +34,9 @@ typedef enum
JM_EXPECT_WAL_RANGES_NEXT,
JM_EXPECT_THIS_WAL_RANGE_FIELD,
JM_EXPECT_THIS_WAL_RANGE_VALUE,
+ JM_EXPECT_TIME_RANGE_START,
+ JM_EXPECT_THIS_TIME_RANGE_FIELD,
+ JM_EXPECT_THIS_TIME_RANGE_VALUE,
JM_EXPECT_MANIFEST_CHECKSUM_VALUE,
JM_EXPECT_EOF,
} JsonManifestSemanticState;
@@ -188,6 +192,9 @@ json_manifest_object_start(void *state)
parse->start_lsn = NULL;
parse->end_lsn = NULL;
break;
+ case JM_EXPECT_TIME_RANGE_START:
+ parse->state = JM_EXPECT_THIS_TIME_RANGE_FIELD;
+ break;
default:
json_manifest_parse_failure(parse->context,
"unexpected object start");
@@ -223,6 +230,9 @@ json_manifest_object_end(void *state)
json_manifest_finalize_wal_range(parse);
parse->state = JM_EXPECT_WAL_RANGES_NEXT;
break;
+ case JM_EXPECT_THIS_TIME_RANGE_FIELD:
+ parse->state = JM_EXPECT_TOPLEVEL_FIELD;
+ break;
default:
json_manifest_parse_failure(parse->context,
"unexpected object end");
@@ -312,6 +322,13 @@ json_manifest_object_field_start(void *state, char *fname, bool isnull)
break;
}
+ /* Is this the backup label? */
+ if (strcmp(fname, "Backup-Label") == 0)
+ {
+ parse->state = JM_EXPECT_BACKUP_LABEL_VALUE;
+ break;
+ }
+
/* Is this the list of files? */
if (strcmp(fname, "Files") == 0)
{
@@ -326,6 +343,13 @@ json_manifest_object_field_start(void *state, char *fname, bool isnull)
break;
}
+ /* Is this the time range? */
+ if (strcmp(fname, "Time-Range") == 0)
+ {
+ parse->state = JM_EXPECT_TIME_RANGE_START;
+ break;
+ }
+
/* Is this the manifest checksum? */
if (strcmp(fname, "Manifest-Checksum") == 0)
{
@@ -372,6 +396,14 @@ json_manifest_object_field_start(void *state, char *fname, bool isnull)
parse->state = JM_EXPECT_THIS_WAL_RANGE_VALUE;
break;
+ case JM_EXPECT_THIS_TIME_RANGE_FIELD:
+ if (strcmp(fname, "Start-Time") != 0 &&
+ strcmp(fname, "End-Time") != 0)
+ json_manifest_parse_failure(parse->context,
+ "unexpected time range field");
+ parse->state = JM_EXPECT_THIS_TIME_RANGE_VALUE;
+ break;
+
default:
json_manifest_parse_failure(parse->context,
"unexpected object field");
@@ -410,6 +442,10 @@ json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
parse->state = JM_EXPECT_TOPLEVEL_FIELD;
break;
+ case JM_EXPECT_BACKUP_LABEL_VALUE:
+ parse->state = JM_EXPECT_TOPLEVEL_FIELD;
+ break;
+
case JM_EXPECT_THIS_FILE_VALUE:
switch (parse->file_field)
{
@@ -451,6 +487,10 @@ json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
parse->state = JM_EXPECT_THIS_WAL_RANGE_FIELD;
break;
+ case JM_EXPECT_THIS_TIME_RANGE_VALUE:
+ parse->state = JM_EXPECT_THIS_TIME_RANGE_FIELD;
+ break;
+
case JM_EXPECT_MANIFEST_CHECKSUM_VALUE:
parse->state = JM_EXPECT_TOPLEVEL_END;
parse->manifest_checksum = token;
diff --git a/src/include/backup/backup_manifest.h b/src/include/backup/backup_manifest.h
index bd7067ae42..4ab1291bba 100644
--- a/src/include/backup/backup_manifest.h
+++ b/src/include/backup/backup_manifest.h
@@ -37,7 +37,8 @@ typedef struct backup_manifest_info
extern void InitializeBackupManifest(backup_manifest_info *manifest,
backup_manifest_option want_manifest,
- pg_checksum_type manifest_checksum_type);
+ pg_checksum_type manifest_checksum_type,
+ const char *label);
extern void AddFileToBackupManifest(backup_manifest_info *manifest,
Oid spcoid,
const char *pathname, size_t size,
@@ -47,6 +48,8 @@ extern void AddWALInfoToBackupManifest(backup_manifest_info *manifest,
XLogRecPtr startptr,
TimeLineID starttli, XLogRecPtr endptr,
TimeLineID endtli);
+extern void AddTimeInfoToBackupManifest(backup_manifest_info *manifest,
+ pg_time_t starttime, pg_time_t endtime);
extern void SendBackupManifest(backup_manifest_info *manifest, bbsink *sink);
extern void FreeBackupManifest(backup_manifest_info *manifest);
--
2.34.1