pg_rewind: Allow writing recovery configuration
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 30 Sep 2019 15:57:35 +0000 (12:57 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 30 Sep 2019 15:57:35 +0000 (12:57 -0300)
This is provided with a new switch --write-recovery-conf and reuses the
pg_basebackup code.

Author: Paul Guo, Jimmy Yih, Ashwin Agrawal
Reviewed-by: Alexey Kondratov, Michaël Paquier, Álvaro Herrera
Discussion: https://postgr.es/m/CAEET0ZEffUkXc48pg2iqARQgGRYDiiVxDu+yYek_bTwJF+q=Uw@mail.gmail.com

doc/src/sgml/ref/pg_rewind.sgml
src/bin/pg_rewind/Makefile
src/bin/pg_rewind/libpq_fetch.c
src/bin/pg_rewind/pg_rewind.c
src/bin/pg_rewind/pg_rewind.h

index a06e5ac5e11b8b0ff716370c5077acaa7f74aac5..fbf454803b5502394498b2dc3a7c3ed20569e0e6 100644 (file)
@@ -180,6 +180,19 @@ 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.  <literal>--source-server</literal> is mandatory with
+        this option.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-n</option></term>
       <term><option>--dry-run</option></term>
index 859d3abc41bcd633e85d0991e415957768dbca55..98fb381c629c748d48b134d13945e132de2810bf 100644 (file)
@@ -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 \
index 002776f6962ed47ee3c2a7cd65df406b9c41ab70..f4ebf7d8420b7e90304f74422a9d5fc3c771d22f 100644 (file)
 #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.
index 8cb0d726cfeef5a552c1385ae508735ebd1c7192..a7fd9e0cabe749827b2a74caedb620d56cd26515 100644 (file)
@@ -27,6 +27,7 @@
 #include "common/file_perm.h"
 #include "common/file_utils.h"
 #include "common/restricted_token.h"
+#include "fe_utils/recovery_gen.h"
 #include "getopt_long.h"
 #include "storage/bufpage.h"
 
@@ -41,6 +42,7 @@ static void syncTargetDirectory(void);
 static void sanityChecks(void);
 static void findCommonAncestorTimeline(XLogRecPtr *recptr, int *tliIndex);
 static void ensureCleanShutdown(const char *argv0);
+static void disconnect_atexit(void);
 
 static ControlFileData ControlFile_target;
 static ControlFileData ControlFile_source;
@@ -76,6 +78,8 @@ 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"
+            "                                 (requires --source-server)\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"));
@@ -94,6 +98,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},
        {"no-ensure-shutdown", no_argument, NULL, 44},
@@ -118,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"));
@@ -138,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)
        {
@@ -158,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);
@@ -200,6 +210,13 @@ main(int argc, char **argv)
        exit(1);
    }
 
+   if (writerecoveryconf && connstr_source == NULL)
+   {
+       pg_log_error("no source server information (--source--server) specified for --write-recovery-conf");
+       fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+       exit(1);
+   }
+
    if (optind < argc)
    {
        pg_log_error("too many command-line arguments (first is \"%s\")",
@@ -236,6 +253,8 @@ main(int argc, char **argv)
 
    umask(pg_mode_mask);
 
+   atexit(disconnect_atexit);
+
    /* Connect to remote server */
    if (connstr_source)
        libpqConnect(connstr_source);
@@ -322,6 +341,9 @@ main(int argc, char **argv)
    if (!rewind_needed)
    {
        pg_log_info("no rewind required");
+       if (writerecoveryconf)
+           WriteRecoveryConfig(conn, datadir_target,
+                               GenerateRecoveryConfig(conn, NULL));
        exit(0);
    }
 
@@ -419,6 +441,10 @@ main(int argc, char **argv)
        pg_log_info("syncing target data directory");
    syncTargetDirectory();
 
+   if (writerecoveryconf)
+       WriteRecoveryConfig(conn, datadir_target,
+                           GenerateRecoveryConfig(conn, NULL));
+
    pg_log_info("Done!");
 
    return 0;
@@ -828,3 +854,10 @@ ensureCleanShutdown(const char *argv0)
        pg_fatal("Command was: %s", cmd);
    }
 }
+
+static void
+disconnect_atexit(void)
+{
+   if (conn != NULL)
+       PQfinish(conn);
+}
index 1125c7e60f68dc6f5feab34c43a04b1f5648b9b1..aa3a0ce8fc5e34389d25cc533f0369340d285290 100644 (file)
 #include "datapagemap.h"
 
 #include "access/timeline.h"
+#include "common/logging.h"
+#include "libpq-fe.h"
 #include "storage/block.h"
 #include "storage/relfilenode.h"
 
-#include "common/logging.h"
 
 /* Configuration options */
 extern char *datadir_target;
@@ -31,6 +32,9 @@ extern int    WalSegSz;
 extern TimeLineHistoryEntry *targetHistory;
 extern int targetNentries;
 
+/* general state */
+extern PGconn *conn;
+
 /* Progress counters */
 extern uint64 fetch_size;
 extern uint64 fetch_done;
@@ -53,6 +57,7 @@ extern void progress_report(bool force);
 
 /* in timeline.c */
 extern TimeLineHistoryEntry *rewind_parseTimeLineHistory(char *buffer,
-                                                        TimeLineID targetTLI, int *nentries);
+                                                        TimeLineID targetTLI,
+                                                        int *nentries);
 
 #endif                         /* PG_REWIND_H */