]> granicus.if.org Git - postgresql/commitdiff
pg_ctl: Add wait option to promote action
authorPeter Eisentraut <peter_e@gmx.net>
Sat, 6 Aug 2016 01:35:19 +0000 (21:35 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Wed, 21 Sep 2016 16:00:00 +0000 (12:00 -0400)
When waiting is selected for the promote action, look into pg_control
until the state changes, then use the PQping-based waiting until the
server is reachable.

Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
doc/src/sgml/ref/pg_ctl-ref.sgml
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_ctl/t/003_promote.pl

index 6ceb7816dc87b06a43e84a81ae0e08b69cbe9b03..a00c355f4aac5591f9d3d38ede7d265ce65b95b9 100644 (file)
@@ -91,6 +91,8 @@ PostgreSQL documentation
   <cmdsynopsis>
    <command>pg_ctl</command>
    <arg choice="plain"><option>promote</option></arg>
+   <arg choice="opt"><option>-w</option></arg>
+   <arg choice="opt"><option>-t</option> <replaceable>seconds</replaceable></arg>
    <arg choice="opt"><option>-s</option></arg>
    <arg choice="opt"><option>-D</option> <replaceable>datadir</replaceable></arg>
   </cmdsynopsis>
@@ -361,8 +363,8 @@ PostgreSQL documentation
       <term><option>--timeout</option></term>
       <listitem>
        <para>
-        The maximum number of seconds to wait when waiting for startup or
-        shutdown to complete.  Defaults to the value of the
+        The maximum number of seconds to wait when waiting for an operation
+        to complete (see option <option>-w</option>). Defaults to the value of the
         <envar>PGCTLTIMEOUT</> environment variable or, if not set, to 60
         seconds.
        </para>
@@ -383,8 +385,23 @@ PostgreSQL documentation
       <term><option>-w</option></term>
       <listitem>
        <para>
-        Wait for the startup or shutdown to complete.
-        Waiting is the default option for shutdowns, but not startups.
+        Wait for an operation to complete.  This is supported for the
+        modes <literal>start</literal>, <literal>stop</literal>,
+        <literal>restart</literal>, <literal>promote</literal>,
+        and <literal>register</literal>.
+       </para>
+
+       <para>
+        Waiting is the default option for shutdowns, but not startups,
+        restarts, or promotions.  This is mainly for historical reasons; the
+        waiting option is almost always preferable.  If waiting is not
+        selected, the requested action is triggered, but there is no feedback
+        about its success.  In that case, the server log file or an external
+        monitoring system would have to be used to check the progress and
+        success of the operation.
+       </para>
+
+       <para>
         When waiting for startup, <command>pg_ctl</command> repeatedly
         attempts to connect to the server.
         When waiting for shutdown, <command>pg_ctl</command> waits for
@@ -400,8 +417,8 @@ PostgreSQL documentation
       <term><option>-W</option></term>
       <listitem>
        <para>
-        Do not wait for startup or shutdown to complete.  This is the
-        default for start and restart modes.
+        Do not wait for an operation to complete.  This is the opposite of the
+        option <option>-w</option>.
        </para>
       </listitem>
      </varlistentry>
index eb8a67a9033e9d2fc65b186ab6be8a5ad402f195..2f0976a9cc155d21e28c32706ecc1669ed35506c 100644 (file)
@@ -1228,7 +1228,34 @@ do_promote(void)
                exit(1);
        }
 
-       print_msg(_("server promoting\n"));
+       if (do_wait)
+       {
+               DBState state = DB_STARTUP;
+
+               print_msg(_("waiting for server to promote..."));
+               while (wait_seconds > 0)
+               {
+                       state = get_control_dbstate();
+                       if (state == DB_IN_PRODUCTION)
+                               break;
+
+                       print_msg(".");
+                       pg_usleep(1000000);     /* 1 sec */
+                       wait_seconds--;
+               }
+               if (state == DB_IN_PRODUCTION)
+               {
+                       print_msg(_(" done\n"));
+                       print_msg(_("server promoted\n"));
+               }
+               else
+               {
+                       print_msg(_(" stopped waiting\n"));
+                       print_msg(_("server is still promoting\n"));
+               }
+       }
+       else
+               print_msg(_("server promoting\n"));
 }
 
 
@@ -2405,18 +2432,10 @@ main(int argc, char **argv)
 
        if (!wait_set)
        {
-               switch (ctl_command)
-               {
-                       case RESTART_COMMAND:
-                       case START_COMMAND:
-                               do_wait = false;
-                               break;
-                       case STOP_COMMAND:
-                               do_wait = true;
-                               break;
-                       default:
-                               break;
-               }
+               if (ctl_command == STOP_COMMAND)
+                       do_wait = true;
+               else
+                       do_wait = false;
        }
 
        if (ctl_command == RELOAD_COMMAND)
index 1461234f2af8824bed1c33a090da97241848fba2..0b6090b6eb515e17ce434eefb7f63241995e9681 100644 (file)
@@ -3,7 +3,7 @@ use warnings;
 
 use PostgresNode;
 use TestLib;
-use Test::More tests => 9;
+use Test::More tests => 12;
 
 my $tempdir = TestLib::tempdir;
 
@@ -37,3 +37,19 @@ command_ok([ 'pg_ctl', '-D', $node_standby->data_dir, 'promote' ],
 
 ok($node_standby->poll_query_until('postgres', 'SELECT NOT pg_is_in_recovery()'),
    'promoted standby is not in recovery');
+
+# same again with wait option
+$node_standby = get_new_node('standby2');
+$node_standby->init_from_backup($node_primary, 'my_backup', has_streaming => 1);
+$node_standby->start;
+
+is($node_standby->safe_psql('postgres', 'SELECT pg_is_in_recovery()'),
+   't', 'standby is in recovery');
+
+command_ok([ 'pg_ctl', '-D', $node_standby->data_dir, '-w', 'promote' ],
+                  'pg_ctl -w promote of standby runs');
+
+# no wait here
+
+is($node_standby->safe_psql('postgres', 'SELECT pg_is_in_recovery()'),
+   'f', 'promoted standby is not in recovery');