diff options
-rw-r--r-- | doc/src/sgml/ref/pg_receivexlog.sgml | 19 | ||||
-rw-r--r-- | src/bin/pg_basebackup/pg_basebackup.c | 6 | ||||
-rw-r--r-- | src/bin/pg_basebackup/pg_receivexlog.c | 39 | ||||
-rw-r--r-- | src/bin/pg_basebackup/streamutil.c | 7 |
4 files changed, 67 insertions, 4 deletions
diff --git a/doc/src/sgml/ref/pg_receivexlog.sgml b/doc/src/sgml/ref/pg_receivexlog.sgml index 8e5fca40228..f0a7763bdfc 100644 --- a/doc/src/sgml/ref/pg_receivexlog.sgml +++ b/doc/src/sgml/ref/pg_receivexlog.sgml @@ -58,6 +58,14 @@ PostgreSQL documentation configured with <xref linkend="guc-max-wal-senders"> set high enough to leave at least one session available for the stream. </para> + + <para> + If the connection is lost, or if it cannot be initially established, + with a non-fatal error, <application>pg_receivexlog</application> will + retry the connection indefinitely, and reestablish streaming as soon + as possible. To avoid this behavior, use the <literal>-n</literal> + parameter. + </para> </refsect1> <refsect1> @@ -87,6 +95,17 @@ PostgreSQL documentation <variablelist> <varlistentry> + <term><option>-n</option></term> + <term><option>--noloop</option></term> + <listitem> + <para> + Don't loop on connection errors. Instead, exit right away with + an error. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>-v</option></term> <term><option>--verbose</option></term> <listitem> diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index 6a2e557809a..d7466168d78 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -279,6 +279,9 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier) /* Get a second connection */ param->bgconn = GetConnection(); + if (!param->bgconn) + /* Error message already written in GetConnection() */ + exit(1); /* * Always in plain format, so we can write to basedir/pg_xlog. But the @@ -915,6 +918,9 @@ BaseBackup(void) * Connect in replication mode to the server */ conn = GetConnection(); + if (!conn) + /* Error message already written in GetConnection() */ + exit(1); /* * Run IDENTIFY_SYSTEM so we can get the timeline diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c index 01f20f372a4..084ddc4a8cb 100644 --- a/src/bin/pg_basebackup/pg_receivexlog.c +++ b/src/bin/pg_basebackup/pg_receivexlog.c @@ -33,9 +33,13 @@ #include "getopt_long.h" +/* Time to sleep between reconnection attempts */ +#define RECONNECT_SLEEP_TIME 5 + /* Global options */ char *basedir = NULL; int verbose = 0; +int noloop = 0; int standby_message_timeout = 10; /* 10 sec = default */ volatile bool time_to_abort = false; @@ -55,6 +59,7 @@ usage(void) printf(_("\nOptions controlling the output:\n")); printf(_(" -D, --dir=directory receive xlog files into this directory\n")); printf(_("\nGeneral options:\n")); + printf(_(" -n, --noloop do not loop on connection lost\n")); printf(_(" -v, --verbose output verbose messages\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_(" -V, --version output version information, then exit\n")); @@ -214,6 +219,9 @@ StreamLog(void) * Connect in replication mode to the server */ conn = GetConnection(); + if (!conn) + /* Error message already written in GetConnection() */ + return; /* * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog @@ -289,6 +297,7 @@ main(int argc, char **argv) {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, + {"noloop", no_argument, NULL, 'n'}, {"no-password", no_argument, NULL, 'w'}, {"password", no_argument, NULL, 'W'}, {"statusint", required_argument, NULL, 's'}, @@ -317,7 +326,7 @@ main(int argc, char **argv) } } - while ((c = getopt_long(argc, argv, "D:h:p:U:s:wWv", + while ((c = getopt_long(argc, argv, "D:h:p:U:s:nwWv", long_options, &option_index)) != -1) { switch (c) @@ -355,6 +364,9 @@ main(int argc, char **argv) exit(1); } break; + case 'n': + noloop = 1; + break; case 'v': verbose++; break; @@ -397,7 +409,28 @@ main(int argc, char **argv) pqsignal(SIGINT, sigint_handler); #endif - StreamLog(); + while (true) + { + StreamLog(); + if (time_to_abort) + /* + * We've been Ctrl-C'ed. That's not an error, so exit without + * an errorcode. + */ + exit(0); + else if (noloop) + { + fprintf(stderr, _("%s: disconnected.\n"), progname); + exit(1); + } + else + { + fprintf(stderr, _("%s: disconnected. Waiting %d seconds to try again\n"), + progname, RECONNECT_SLEEP_TIME); + pg_usleep(RECONNECT_SLEEP_TIME * 1000000); + } + } - exit(0); + /* Never get here */ + exit(2); } diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c index cc015370ff6..1416faa2e3c 100644 --- a/src/bin/pg_basebackup/streamutil.c +++ b/src/bin/pg_basebackup/streamutil.c @@ -65,6 +65,11 @@ xmalloc0(int size) } +/* + * Connect to the server. Returns a valid PGconn pointer if connected, + * or NULL on non-permanent error. On permanent error, the function will + * call exit(1) directly. + */ PGconn * GetConnection(void) { @@ -151,7 +156,7 @@ GetConnection(void) { fprintf(stderr, _("%s: could not connect to server: %s\n"), progname, PQerrorMessage(tmpconn)); - exit(1); + return NULL; } /* Connection ok! */ |