From 0ea6b6322e8eb6e105936e18f433b0454dab37bd Mon Sep 17 00:00:00 2001
From: Paul Guo <paulguo@gmail.com>
Date: Thu, 18 Apr 2019 19:37:36 +0800
Subject: [PATCH v8 1/2] Add option to write recovery configuration information
 in pg_rewind.

---
 doc/src/sgml/ref/pg_rewind.sgml | 11 +++++++++++
 src/bin/pg_rewind/Makefile      |  2 +-
 src/bin/pg_rewind/libpq_fetch.c |  3 +--
 src/bin/pg_rewind/pg_rewind.c   | 26 +++++++++++++++++++++++++-
 src/bin/pg_rewind/pg_rewind.h   |  2 ++
 5 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/doc/src/sgml/ref/pg_rewind.sgml b/doc/src/sgml/ref/pg_rewind.sgml
index ac142d22fc..b8b43e8220 100644
--- a/doc/src/sgml/ref/pg_rewind.sgml
+++ b/doc/src/sgml/ref/pg_rewind.sgml
@@ -165,6 +165,17 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-R</option></term>
+      <term><option>--write-recovery-conf</option></term>
+      <listitem>
+       <para>
+        Create <filename>standby.signal</filename> and append connection settings
+        to <filename>postgresql.auto.conf</filename> in the output directory.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-n</option></term>
       <term><option>--dry-run</option></term>
diff --git a/src/bin/pg_rewind/Makefile b/src/bin/pg_rewind/Makefile
index 859d3abc41..98fb381c62 100644
--- a/src/bin/pg_rewind/Makefile
+++ b/src/bin/pg_rewind/Makefile
@@ -16,7 +16,7 @@ top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
 override CPPFLAGS := -I$(libpq_srcdir) -DFRONTEND $(CPPFLAGS)
-LDFLAGS_INTERNAL += $(libpq_pgport)
+LDFLAGS_INTERNAL += $(libpq_pgport) -L$(top_builddir)/src/fe_utils -lpgfeutils
 
 OBJS	= pg_rewind.o parsexlog.o xlogreader.o datapagemap.o timeline.o \
 	fetch.o file_ops.o copy_fetch.o libpq_fetch.o filemap.o \
diff --git a/src/bin/pg_rewind/libpq_fetch.c b/src/bin/pg_rewind/libpq_fetch.c
index 002776f696..f4ebf7d842 100644
--- a/src/bin/pg_rewind/libpq_fetch.c
+++ b/src/bin/pg_rewind/libpq_fetch.c
@@ -20,12 +20,11 @@
 #include "file_ops.h"
 #include "filemap.h"
 
-#include "libpq-fe.h"
 #include "catalog/pg_type_d.h"
 #include "fe_utils/connect.h"
 #include "port/pg_bswap.h"
 
-static PGconn *conn = NULL;
+PGconn *conn = NULL;
 
 /*
  * Files are fetched max CHUNKSIZE bytes at a time.
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index 15e3eab550..2312e564f6 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -29,6 +29,7 @@
 #include "common/restricted_token.h"
 #include "getopt_long.h"
 #include "storage/bufpage.h"
+#include "fe_utils/recovery_gen.h"
 
 static void usage(const char *progname);
 
@@ -65,6 +66,12 @@ int			targetNentries;
 uint64		fetch_size;
 uint64		fetch_done;
 
+static void
+disconnect_atexit(void)
+{
+	if (conn != NULL)
+		PQfinish(conn);
+}
 
 static void
 usage(const char *progname)
@@ -75,6 +82,7 @@ usage(const char *progname)
 	printf(_("  -D, --target-pgdata=DIRECTORY  existing data directory to modify\n"));
 	printf(_("      --source-pgdata=DIRECTORY  source data directory to synchronize with\n"));
 	printf(_("      --source-server=CONNSTR    source server to synchronize with\n"));
+	printf(_("  -R, --write-recovery-conf      write configuration for replication\n"));
 	printf(_("  -n, --dry-run                  stop before modifying anything\n"));
 	printf(_("  -N, --no-sync                  do not wait for changes to be written\n"
 			 "                                 safely to disk\n"));
@@ -92,6 +100,7 @@ main(int argc, char **argv)
 	static struct option long_options[] = {
 		{"help", no_argument, NULL, '?'},
 		{"target-pgdata", required_argument, NULL, 'D'},
+		{"write-recovery-conf", no_argument, NULL, 'R'},
 		{"source-pgdata", required_argument, NULL, 1},
 		{"source-server", required_argument, NULL, 2},
 		{"version", no_argument, NULL, 'V'},
@@ -114,6 +123,7 @@ main(int argc, char **argv)
 	XLogRecPtr	endrec;
 	TimeLineID	endtli;
 	ControlFileData ControlFile_new;
+	bool		writerecoveryconf = false;
 
 	pg_logging_init(argv[0]);
 	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_rewind"));
@@ -134,7 +144,7 @@ main(int argc, char **argv)
 		}
 	}
 
-	while ((c = getopt_long(argc, argv, "D:nNP", long_options, &option_index)) != -1)
+	while ((c = getopt_long(argc, argv, "D:nNPR", long_options, &option_index)) != -1)
 	{
 		switch (c)
 		{
@@ -154,6 +164,10 @@ main(int argc, char **argv)
 				do_sync = false;
 				break;
 
+			case 'R':
+				writerecoveryconf = true;
+				break;
+
 			case 3:
 				debug = true;
 				pg_logging_set_level(PG_LOG_DEBUG);
@@ -231,7 +245,10 @@ main(int argc, char **argv)
 
 	/* Connect to remote server */
 	if (connstr_source)
+	{
 		libpqConnect(connstr_source);
+		atexit(disconnect_atexit);
+	}
 
 	/*
 	 * Ok, we have all the options and we're ready to start. Read in all the
@@ -297,6 +314,9 @@ main(int argc, char **argv)
 	if (!rewind_needed)
 	{
 		pg_log_info("no rewind required");
+		if (writerecoveryconf && connstr_source)
+			WriteRecoveryConfig(conn, datadir_target,
+								GenerateRecoveryConfig(conn, NULL));
 		exit(0);
 	}
 
@@ -394,6 +414,10 @@ main(int argc, char **argv)
 		pg_log_info("syncing target data directory");
 	syncTargetDirectory();
 
+	if (writerecoveryconf && connstr_source)
+		WriteRecoveryConfig(conn, datadir_target,
+							GenerateRecoveryConfig(conn, NULL));
+
 	pg_log_info("Done!");
 
 	return 0;
diff --git a/src/bin/pg_rewind/pg_rewind.h b/src/bin/pg_rewind/pg_rewind.h
index 1125c7e60f..3cee48556c 100644
--- a/src/bin/pg_rewind/pg_rewind.h
+++ b/src/bin/pg_rewind/pg_rewind.h
@@ -18,6 +18,7 @@
 #include "storage/relfilenode.h"
 
 #include "common/logging.h"
+#include "libpq-fe.h"
 
 /* Configuration options */
 extern char *datadir_target;
@@ -26,6 +27,7 @@ extern char *connstr_source;
 extern bool showprogress;
 extern bool dry_run;
 extern int	WalSegSz;
+extern PGconn *conn;
 
 /* Target history */
 extern TimeLineHistoryEntry *targetHistory;
-- 
2.17.2

