Hi,
I prepared a patch which adds a timestamp into a XLOG_BACKUP_END WAL-record. This functionality is needed in practice when we have to determine a recovery time of specific backup. This code developed in compatibility with WAL segments, which do not have a timestamp in a XLOG_BACKUP_END record.

--
Andrey Lepikhov
Postgres Professional:
https://postgrespro.com
The Russian Postgres Company
>From 8852a64156e7726bae11c1904b142c9b157cf654 Mon Sep 17 00:00:00 2001
From: "Andrey V. Lepikhov" <a.lepik...@postgrespro.ru>
Date: Mon, 9 Jul 2018 10:57:10 +0500
Subject: [PATCH] BACKUP_END timestamp addition

---
 src/backend/access/rmgrdesc/xlogdesc.c | 14 +++++++++++++-
 src/backend/access/transam/xlog.c      |  7 +++++--
 src/include/access/xlog_internal.h     |  7 +++++++
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 00741c7..5a0d61a 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -87,7 +87,19 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 		XLogRecPtr	startpoint;
 
 		memcpy(&startpoint, rec, sizeof(XLogRecPtr));
-		appendStringInfo(buf, "%X/%X",
+		/* Check for the format of WAL-record with timestamp */
+		if (XLogRecGetDataLen(record) >= sizeof(xl_backup_end))
+		{
+			TimestampTz	timestamp;
+
+			memcpy(&timestamp, &((xl_backup_end *)rec)->timestamp, sizeof(TimestampTz));
+			appendStringInfo(buf, "%X/%X; timestamp: %s",
+						 (uint32) (startpoint >> 32), (uint32) startpoint,
+						 timestamptz_to_str(timestamp));
+		}
+		else
+			/* WAL-record not have a timestamp */
+			appendStringInfo(buf, "%X/%X; <no timestamp>",
 						 (uint32) (startpoint >> 32), (uint32) startpoint);
 	}
 	else if (info == XLOG_PARAMETER_CHANGE)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 44017d3..12a5eb6 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -9950,7 +9950,7 @@ xlog_redo(XLogReaderState *record)
 	{
 		XLogRecPtr	startpoint;
 
-		memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint));
+		memcpy(&startpoint, &((xl_backup_end *)XLogRecGetData(record))->startpoint, sizeof(startpoint));
 
 		if (ControlFile->backupStartPoint == startpoint)
 		{
@@ -11069,11 +11069,14 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
 	}
 	else
 	{
+		xl_backup_end	xlrec;
 		/*
 		 * Write the backup-end xlog record
 		 */
 		XLogBeginInsert();
-		XLogRegisterData((char *) (&startpoint), sizeof(startpoint));
+		xlrec.startpoint = startpoint;
+		xlrec.timestamp = GetCurrentTimestamp();
+		XLogRegisterData((char *) (&xlrec), sizeof(xl_backup_end));
 		stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
 		stoptli = ThisTimeLineID;
 
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 7c76683..8c5d851 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -233,6 +233,13 @@ typedef struct xl_parameter_change
 	bool		track_commit_timestamp;
 } xl_parameter_change;
 
+/* BACKUP_END WAL record main data structure */
+typedef struct xl_backup_end
+{
+	XLogRecPtr	startpoint;
+	TimestampTz	timestamp;
+} xl_backup_end;
+
 /* logs restore point */
 typedef struct xl_restore_point
 {
-- 
2.7.4

Reply via email to