@@ -38,11 +38,15 @@ static int noloop = 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 ,
4751 bool segment_finished );
4852
@@ -78,6 +82,9 @@ usage(void)
7882 printf (_ (" -w, --no-password never prompt for password\n" ));
7983 printf (_ (" -W, --password force password prompt (should happen automatically)\n" ));
8084 printf (_ (" -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" ));
8188 printf (_ ("\nReport bugs to <pgsql-bugs@postgresql.org>.\n" ));
8289}
8390
@@ -118,6 +125,44 @@ stop_streaming(XLogRecPtr xlogpos, uint32 timeline, bool segment_finished)
118125 return 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)
134179 uint32 high_tli = 0 ;
135180 bool 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
145184 while (errno = 0 , (dirent = readdir (dir )) != NULL )
146185 {
@@ -219,12 +258,7 @@ FindStreamingStart(uint32 *tli)
219258 disconnect_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
229263 if (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
350387 int c ;
351388 int option_index ;
389+ char * db_name ;
352390
353391 progname = get_progname (argv [0 ]);
354392 set_pglocale_pgservice (argv [0 ], PG_TEXTDOMAIN ("pg_receivexlog" ));
@@ -427,6 +465,13 @@ main(int argc, char **argv)
427465 case 'v' :
428466 verbose ++ ;
429467 break ;
468+ /* action */
469+ case 1 :
470+ do_create_slot = true;
471+ break ;
472+ case 2 :
473+ do_drop_slot = true;
474+ break ;
430475 default :
431476
432477 /*
@@ -451,21 +496,101 @@ main(int argc, char **argv)
451496 exit (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 {
459520 fprintf (stderr , _ ("%s: no target directory specified\n" ), progname );
460521 fprintf (stderr , _ ("Try \"%s --help\" for more information.\n" ),
461522 progname );
462523 exit (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
466536 pqsignal (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+
469594 while (true)
470595 {
471596 StreamLog ();
0 commit comments