On Fri, Oct 3, 2014 at 8:57 PM, Andres Freund <[email protected]> wrote:
> > <para>
> > + <application>pg_receivexlog</application> can run in one of two
> > following
> > + modes, which control physical replication slot:
>
> I don't think that's good enough. There's also the important mode where
> it's not doing --create/--drop at all.
Well, yes, however the third mode is not explicitly present, and I
don't see much point in adding a --start mode thinking
backward-compatibility. Now, I refactored a bit the documentation to
mention that pg_receivexlog can perform additional actions to control
replication slots. I added as well in the portion of option --slot how
it interacts with --create-slot and --drop-slot.
> > + if (db_name)
> > + {
> > + fprintf(stderr,
> > + _("%s: database defined for replication
> > connection \"%s\"\n"),
> > + progname, replication_slot);
> > + disconnect_and_exit(1);
> > + }
>
> I don't like 'defined' here. 'replication connection unexpectedly is
> database specific' or something would be better.
Sure, IMO the error message should as well mention the replication
slot being used, so I reformulated as such:
"replication connection using slot foo is unexpectedly database specific"
>
> I do wonder whether --create/--drop aren't somewhat weird for
> pg_receivexlog. It's not that clear what it means. It'd be ugly, but we
> could rename them --create-slot/drop-slot.
In line with the other patch sent earlier, options are renamed to
--create-slot and --drop-slot.
Regards,
--
Michael
From aba831b62795303ec666b8c18810f404458d8acd Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email protected]>
Date: Mon, 1 Sep 2014 20:53:45 +0900
Subject: [PATCH] Support for replslot creation and drop in pg_receivexlog
Using the new actions --create-slot and --drop-slot that are similarly
present in pg_recvlogical, a user can respectively create and drop a
replication slot that can be used afterwards when fetching WALs.
---
doc/src/sgml/ref/pg_receivexlog.sgml | 31 ++++++-
src/bin/pg_basebackup/pg_receivexlog.c | 154 +++++++++++++++++++++++++++++----
2 files changed, 169 insertions(+), 16 deletions(-)
diff --git a/doc/src/sgml/ref/pg_receivexlog.sgml b/doc/src/sgml/ref/pg_receivexlog.sgml
index 5916b8f..72290e5 100644
--- a/doc/src/sgml/ref/pg_receivexlog.sgml
+++ b/doc/src/sgml/ref/pg_receivexlog.sgml
@@ -255,7 +255,9 @@ PostgreSQL documentation
to make sure that <application>pg_receivexlog</> cannot become the
synchronous standby through an incautious setting of
<xref linkend="guc-synchronous-standby-names">; it does not flush
- data frequently enough for this to work correctly.
+ data frequently enough for this to work correctly. In
+ <option>--create-slot</option> mode, create the slot with this name.
+ In <option>--drop-slot</option> mode, delete the slot with this name.
</para>
</listitem>
</varlistentry>
@@ -263,6 +265,33 @@ PostgreSQL documentation
</para>
<para>
+ <application>pg_receivexlog</application> can perform one of the two
+ following actions in order to control physical replication slots:
+
+ <variablelist>
+ <varlistentry>
+ <term><option>--create-slot</option></term>
+ <listitem>
+ <para>
+ Create a new physical replication slot with the name specified in
+ <option>--slot</option>, then start stream.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--drop-slot</option></term>
+ <listitem>
+ <para>
+ Drop the replication slot with the name specified in
+ <option>--slot</option>, then exit.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
Other options are also available:
<variablelist>
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c
index 171cf43..5b71f85 100644
--- a/src/bin/pg_basebackup/pg_receivexlog.c
+++ b/src/bin/pg_basebackup/pg_receivexlog.c
@@ -38,11 +38,15 @@ static int noloop = 0;
static int standby_message_timeout = 10 * 1000; /* 10 sec = default */
static int fsync_interval = 0; /* 0 = default */
static volatile bool time_to_abort = false;
+static bool do_create_slot = false;
+static bool do_drop_slot = false;
static void usage(void);
+static DIR* get_destination_dir(char *dest_folder);
+static void close_destination_dir(DIR *dest_dir, char *dest_folder);
static XLogRecPtr FindStreamingStart(uint32 *tli);
-static void StreamLog();
+static void StreamLog(void);
static bool stop_streaming(XLogRecPtr segendpos, uint32 timeline,
bool segment_finished);
@@ -78,6 +82,9 @@ usage(void)
printf(_(" -w, --no-password never prompt for password\n"));
printf(_(" -W, --password force password prompt (should happen automatically)\n"));
printf(_(" -S, --slot=SLOTNAME replication slot to use\n"));
+ printf(_("\nOptional actions:\n"));
+ printf(_(" --create-slot create a new replication slot (for the slot's name see --slot)\n"));
+ printf(_(" --drop-slot drop the replication slot (for the slot's name see --slot)\n"));
printf(_("\nReport bugs to <[email protected]>.\n"));
}
@@ -118,6 +125,44 @@ stop_streaming(XLogRecPtr xlogpos, uint32 timeline, bool segment_finished)
return false;
}
+
+/*
+ * Get destination directory.
+ */
+static DIR*
+get_destination_dir(char *dest_folder)
+{
+ DIR *dir;
+
+ Assert(dest_folder != NULL);
+ dir = opendir(dest_folder);
+ if (dir == NULL)
+ {
+ fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
+ progname, basedir, strerror(errno));
+ disconnect_and_exit(1);
+ }
+
+ return dir;
+}
+
+
+/*
+ * Close existing directory.
+ */
+static void
+close_destination_dir(DIR *dest_dir, char *dest_folder)
+{
+ Assert(dest_dir != NULL && dest_folder != NULL);
+ if (closedir(dest_dir))
+ {
+ fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
+ progname, dest_folder, strerror(errno));
+ disconnect_and_exit(1);
+ }
+}
+
+
/*
* Determine starting location for streaming, based on any existing xlog
* segments in the directory. We start at the end of the last one that is
@@ -134,13 +179,7 @@ FindStreamingStart(uint32 *tli)
uint32 high_tli = 0;
bool high_ispartial = false;
- dir = opendir(basedir);
- if (dir == NULL)
- {
- fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
- progname, basedir, strerror(errno));
- disconnect_and_exit(1);
- }
+ dir = get_destination_dir(basedir);
while (errno = 0, (dirent = readdir(dir)) != NULL)
{
@@ -219,12 +258,7 @@ FindStreamingStart(uint32 *tli)
disconnect_and_exit(1);
}
- if (closedir(dir))
- {
- fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
- progname, basedir, strerror(errno));
- disconnect_and_exit(1);
- }
+ close_destination_dir(dir, basedir);
if (high_segno > 0)
{
@@ -344,11 +378,15 @@ main(int argc, char **argv)
{"status-interval", required_argument, NULL, 's'},
{"slot", required_argument, NULL, 'S'},
{"verbose", no_argument, NULL, 'v'},
+/* action */
+ {"create-slot", no_argument, NULL, 1},
+ {"drop-slot", no_argument, NULL, 2},
{NULL, 0, NULL, 0}
};
int c;
int option_index;
+ char *db_name;
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_receivexlog"));
@@ -427,6 +465,13 @@ main(int argc, char **argv)
case 'v':
verbose++;
break;
+/* action */
+ case 1:
+ do_create_slot = true;
+ break;
+ case 2:
+ do_drop_slot = true;
+ break;
default:
/*
@@ -451,10 +496,26 @@ main(int argc, char **argv)
exit(1);
}
+ if (replication_slot == NULL && (do_drop_slot || do_create_slot))
+ {
+ fprintf(stderr, _("%s: replication slot needed with action --create-slot or --drop-slot\n"), progname);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+ progname);
+ exit(1);
+ }
+
+ if (do_drop_slot && do_create_slot)
+ {
+ fprintf(stderr, _("%s: cannot use --create-slot together with --drop-slot\n"), progname);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+ progname);
+ exit(1);
+ }
+
/*
* Required arguments
*/
- if (basedir == NULL)
+ if (basedir == NULL && !do_drop_slot)
{
fprintf(stderr, _("%s: no target directory specified\n"), progname);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
@@ -462,10 +523,73 @@ main(int argc, char **argv)
exit(1);
}
+ /*
+ * Check existence of destination folder.
+ */
+ if (!do_drop_slot)
+ {
+ DIR *dir = get_destination_dir(basedir);
+ close_destination_dir(dir, basedir);
+ }
+
#ifndef WIN32
pqsignal(SIGINT, sigint_handler);
#endif
+ /*
+ * Obtain a connection before doing anything.
+ */
+ conn = GetConnection();
+ if (!conn)
+ /* error message already written in GetConnection() */
+ exit(1);
+
+ /*
+ * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog
+ * position.
+ */
+ if (!RunIdentifySystem(conn, NULL, NULL, NULL, &db_name))
+ disconnect_and_exit(1);
+
+ /*
+ * Check that there is a database associated with connection, none
+ * should be defined in this context.
+ */
+ if (db_name)
+ {
+ fprintf(stderr,
+ _("%s: replication connection using slot \"%s\" is unexpectedly database specific\n"),
+ progname, replication_slot);
+ disconnect_and_exit(1);
+ }
+
+ /*
+ * Drop a replication slot.
+ */
+ if (do_drop_slot)
+ {
+ if (verbose)
+ fprintf(stderr,
+ _("%s: dropping replication slot \"%s\"\n"),
+ progname, replication_slot);
+
+ if (!DropReplicationSlot(conn, replication_slot))
+ disconnect_and_exit(1);
+ disconnect_and_exit(0);
+ }
+
+ /* Create a replication slot */
+ if (do_create_slot)
+ {
+ if (verbose)
+ fprintf(stderr,
+ _("%s: creating replication slot \"%s\"\n"),
+ progname, replication_slot);
+
+ if (!CreateReplicationSlot(conn, replication_slot, NULL, NULL, true))
+ disconnect_and_exit(1);
+ }
+
while (true)
{
StreamLog();
--
2.1.2
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers