@@ -38,11 +38,15 @@ static intnoloop = 0;
3838static int standby_message_timeout = 10 * 1000 ;/* 10 sec = default */
3939static int fsync_interval = 0 ;/* 0 = default */
4040static volatile bool time_to_abort = false;
41+ static bool do_create_slot = false;
42+ static bool do_drop_slot = false;
4143
4244
4345static void usage (void );
46+ static DIR * get_destination_dir (char * dest_folder );
47+ static void close_destination_dir (DIR * dest_dir ,char * dest_folder );
4448static XLogRecPtr FindStreamingStart (uint32 * tli );
45- static void StreamLog ();
49+ static void StreamLog (void );
4650static bool stop_streaming (XLogRecPtr segendpos ,uint32 timeline ,
4751bool segment_finished );
4852
@@ -78,6 +82,9 @@ usage(void)
7882printf (_ (" -w, --no-password never prompt for password\n" ));
7983printf (_ (" -W, --password force password prompt (should happen automatically)\n" ));
8084printf (_ (" -S, --slot=SLOTNAME replication slot to use\n" ));
85+ printf (_ ("\nOptional actions:\n" ));
86+ printf (_ (" --create-slot create a new replication slot (for the slot's name see --slot)\n" ));
87+ printf (_ (" --drop-slot drop the replication slot (for the slot's name see --slot)\n" ));
8188printf (_ ("\nReport bugs to <pgsql-bugs@postgresql.org>.\n" ));
8289}
8390
@@ -118,6 +125,44 @@ stop_streaming(XLogRecPtr xlogpos, uint32 timeline, bool segment_finished)
118125return false;
119126}
120127
128+
129+ /*
130+ * Get destination directory.
131+ */
132+ static DIR *
133+ get_destination_dir (char * dest_folder )
134+ {
135+ DIR * dir ;
136+
137+ Assert (dest_folder != NULL );
138+ dir = opendir (dest_folder );
139+ if (dir == NULL )
140+ {
141+ fprintf (stderr ,_ ("%s: could not open directory \"%s\": %s\n" ),
142+ progname ,basedir ,strerror (errno ));
143+ disconnect_and_exit (1 );
144+ }
145+
146+ return dir ;
147+ }
148+
149+
150+ /*
151+ * Close existing directory.
152+ */
153+ static void
154+ close_destination_dir (DIR * dest_dir ,char * dest_folder )
155+ {
156+ Assert (dest_dir != NULL && dest_folder != NULL );
157+ if (closedir (dest_dir ))
158+ {
159+ fprintf (stderr ,_ ("%s: could not close directory \"%s\": %s\n" ),
160+ progname ,dest_folder ,strerror (errno ));
161+ disconnect_and_exit (1 );
162+ }
163+ }
164+
165+
121166/*
122167 * Determine starting location for streaming, based on any existing xlog
123168 * segments in the directory. We start at the end of the last one that is
@@ -134,13 +179,7 @@ FindStreamingStart(uint32 *tli)
134179uint32 high_tli = 0 ;
135180bool high_ispartial = false;
136181
137- dir = opendir (basedir );
138- if (dir == NULL )
139- {
140- fprintf (stderr ,_ ("%s: could not open directory \"%s\": %s\n" ),
141- progname ,basedir ,strerror (errno ));
142- disconnect_and_exit (1 );
143- }
182+ dir = get_destination_dir (basedir );
144183
145184while (errno = 0 , (dirent = readdir (dir ))!= NULL )
146185{
@@ -219,12 +258,7 @@ FindStreamingStart(uint32 *tli)
219258disconnect_and_exit (1 );
220259}
221260
222- if (closedir (dir ))
223- {
224- fprintf (stderr ,_ ("%s: could not close directory \"%s\": %s\n" ),
225- progname ,basedir ,strerror (errno ));
226- disconnect_and_exit (1 );
227- }
261+ close_destination_dir (dir ,basedir );
228262
229263if (high_segno > 0 )
230264{
@@ -344,11 +378,15 @@ main(int argc, char **argv)
344378{"status-interval" ,required_argument ,NULL ,'s' },
345379{"slot" ,required_argument ,NULL ,'S' },
346380{"verbose" ,no_argument ,NULL ,'v' },
381+ /* action */
382+ {"create-slot" ,no_argument ,NULL ,1 },
383+ {"drop-slot" ,no_argument ,NULL ,2 },
347384{NULL ,0 ,NULL ,0 }
348385};
349386
350387int c ;
351388int option_index ;
389+ char * db_name ;
352390
353391progname = get_progname (argv [0 ]);
354392set_pglocale_pgservice (argv [0 ],PG_TEXTDOMAIN ("pg_receivexlog" ));
@@ -427,6 +465,13 @@ main(int argc, char **argv)
427465case 'v' :
428466verbose ++ ;
429467break ;
468+ /* action */
469+ case 1 :
470+ do_create_slot = true;
471+ break ;
472+ case 2 :
473+ do_drop_slot = true;
474+ break ;
430475default :
431476
432477/*
@@ -451,21 +496,101 @@ main(int argc, char **argv)
451496exit (1 );
452497}
453498
499+ if (replication_slot == NULL && (do_drop_slot || do_create_slot ))
500+ {
501+ fprintf (stderr ,_ ("%s: --create-slot and --drop-slot need a slot to be specified using --slot\n" ),progname );
502+ fprintf (stderr ,_ ("Try \"%s --help\" for more information.\n" ),
503+ progname );
504+ exit (1 );
505+ }
506+
507+ if (do_drop_slot && do_create_slot )
508+ {
509+ fprintf (stderr ,_ ("%s: cannot use --create-slot together with --drop-slot\n" ),progname );
510+ fprintf (stderr ,_ ("Try \"%s --help\" for more information.\n" ),
511+ progname );
512+ exit (1 );
513+ }
514+
454515/*
455516 * Required arguments
456517 */
457- if (basedir == NULL )
518+ if (basedir == NULL && ! do_drop_slot )
458519{
459520fprintf (stderr ,_ ("%s: no target directory specified\n" ),progname );
460521fprintf (stderr ,_ ("Try \"%s --help\" for more information.\n" ),
461522progname );
462523exit (1 );
463524}
464525
526+ /*
527+ * Check existence of destination folder.
528+ */
529+ if (!do_drop_slot )
530+ {
531+ DIR * dir = get_destination_dir (basedir );
532+ close_destination_dir (dir ,basedir );
533+ }
534+
465535#ifndef WIN32
466536pqsignal (SIGINT ,sigint_handler );
467537#endif
468538
539+ /*
540+ * Obtain a connection before doing anything.
541+ */
542+ conn = GetConnection ();
543+ if (!conn )
544+ /* error message already written in GetConnection() */
545+ exit (1 );
546+
547+ /*
548+ * Run IDENTIFY_SYSTEM to make sure we've successfully have established a
549+ * replication connection and haven't connected using a database specific
550+ * connection.
551+ */
552+ if (!RunIdentifySystem (conn ,NULL ,NULL ,NULL ,& db_name ))
553+ disconnect_and_exit (1 );
554+
555+ /*
556+ * Check that there is a database associated with connection, none
557+ * should be defined in this context.
558+ */
559+ if (db_name )
560+ {
561+ fprintf (stderr ,
562+ _ ("%s: replication connection using slot \"%s\" is unexpectedly database specific\n" ),
563+ progname ,replication_slot );
564+ disconnect_and_exit (1 );
565+ }
566+
567+ /*
568+ * Drop a replication slot.
569+ */
570+ if (do_drop_slot )
571+ {
572+ if (verbose )
573+ fprintf (stderr ,
574+ _ ("%s: dropping replication slot \"%s\"\n" ),
575+ progname ,replication_slot );
576+
577+ if (!DropReplicationSlot (conn ,replication_slot ))
578+ disconnect_and_exit (1 );
579+ disconnect_and_exit (0 );
580+ }
581+
582+ /* Create a replication slot */
583+ if (do_create_slot )
584+ {
585+ if (verbose )
586+ fprintf (stderr ,
587+ _ ("%s: creating replication slot \"%s\"\n" ),
588+ progname ,replication_slot );
589+
590+ if (!CreateReplicationSlot (conn ,replication_slot ,NULL ,NULL , true))
591+ disconnect_and_exit (1 );
592+ }
593+
469594while (true)
470595{
471596StreamLog ();