On Fri, Oct 3, 2014 at 8:57 PM, Andres Freund <and...@2ndquadrant.com> 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 <mich...@otacoo.com> 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 <pgsql-b...@postgresql.org>.\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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers