From a74a4aa23bb95b590ff01ee564219d2eacea3706 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Fri, 5 Sep 2014 19:19:41 -0400
Subject: [PATCH] pg_upgrade:  preserve the timestamp epoch

This is useful for replication tools like Slony and Skytools.

Report by Sergey Konoplev
---
 contrib/pg_upgrade/controldata.c   | 16 ++++++++++------
 contrib/pg_upgrade/pg_upgrade.c    |  8 ++++++--
 contrib/pg_upgrade/pg_upgrade.h    |  1 +
 doc/src/sgml/ref/pg_resetxlog.sgml |  3 ++-
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
index cce44ba7837..9282b8e88e6 100644
--- a/contrib/pg_upgrade/controldata.c
+++ b/contrib/pg_upgrade/controldata.c
@@ -209,16 +209,20 @@ get_control_data(ClusterInfo *cluster, bool live_check)
 		}
 		else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL)
 		{
-			char	   *op = strchr(p, '/');
+			p = strchr(p, ':');
+
+			if (p == NULL || strlen(p) <= 1)
+				pg_fatal("%d: controldata retrieval problem\n", __LINE__);
 
-			if (op == NULL)
-				op = strchr(p, ':');
+			p++;				/* removing ':' char */
+			cluster->controldata.chkpnt_nxtepoch = str2uint(p);
 
-			if (op == NULL || strlen(op) <= 1)
+			p = strchr(p, '/');
+			if (p == NULL || strlen(p) <= 1)
 				pg_fatal("%d: controldata retrieval problem\n", __LINE__);
 
-			op++;				/* removing ':' char */
-			cluster->controldata.chkpnt_nxtxid = str2uint(op);
+			p++;				/* removing '/' char */
+			cluster->controldata.chkpnt_nxtxid = str2uint(p);
 			got_xid = true;
 		}
 		else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL)
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index b6f370f1d2c..3b8241b37e2 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -420,12 +420,16 @@ copy_clog_xlog_xid(void)
 	/* copy old commit logs to new data dir */
 	copy_subdir_files("pg_clog");
 
-	/* set the next transaction id of the new cluster */
-	prep_status("Setting next transaction ID for new cluster");
+	/* set the next transaction id and epoch of the new cluster */
+	prep_status("Setting next transaction ID and epoch for new cluster");
 	exec_prog(UTILITY_LOG_FILE, NULL, true,
 			  "\"%s/pg_resetxlog\" -f -x %u \"%s\"",
 			  new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid,
 			  new_cluster.pgdata);
+	exec_prog(UTILITY_LOG_FILE, NULL, true,
+			  "\"%s/pg_resetxlog\" -f -e %u \"%s\"",
+			  new_cluster.bindir, old_cluster.controldata.chkpnt_nxtepoch,
+			  new_cluster.pgdata);
 	check_ok();
 
 	/*
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index 4b8facf5ce7..1ac33949569 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -190,6 +190,7 @@ typedef struct
 	char		nextxlogfile[25];
 	uint32		chkpnt_tli;
 	uint32		chkpnt_nxtxid;
+	uint32		chkpnt_nxtepoch;
 	uint32		chkpnt_nxtoid;
 	uint32		chkpnt_nxtmulti;
 	uint32		chkpnt_nxtmxoff;
diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml
index 34b06069556..0b53bd68595 100644
--- a/doc/src/sgml/ref/pg_resetxlog.sgml
+++ b/doc/src/sgml/ref/pg_resetxlog.sgml
@@ -166,7 +166,8 @@ PostgreSQL documentation
       except in the field that is set by <command>pg_resetxlog</command>,
       so any value will work so far as the database itself is concerned.
       You might need to adjust this value to ensure that replication
-      systems such as <application>Slony-I</> work correctly &mdash;
+      systems such as <application>Slony-I</> and
+      <application>Skytools</> work correctly &mdash;
       if so, an appropriate value should be obtainable from the state of
       the downstream replicated database.
      </para>
-- 
GitLab