From 30e9d061728abfdcdc6ea6b94c0fab641f786a59 Mon Sep 17 00:00:00 2001 From: Jaime Casanova Date: Sun, 11 Nov 2012 10:07:34 -0500 Subject: [PATCH] Add an option for STANDBY FOLLOW to wait for a master to appear. This is important for autofailover to do the right thing when standbys detected master death at different times. While this is a new option, seems important for the autofailover to work properly so i will consider the lack of it a bug and will backpatch to 2.0 where autofailover was introduced. For gripe from Alex Railean, about a standby not finding the new master because the new master hasn't finish promoting. --- repmgr.c | 25 +++++++++++++++++++------ repmgr.conf.sample | 2 +- repmgr.h | 1 + 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/repmgr.c b/repmgr.c index eb9d254c..2d4772c6 100644 --- a/repmgr.c +++ b/repmgr.c @@ -85,7 +85,7 @@ bool need_a_node = true; bool require_password = false; /* Initialization of runtime options */ -t_runtime_options runtime_options = { "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, "", "", 0 }; +t_runtime_options runtime_options = { "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, "", "", 0 }; t_configuration_options options = { "", -1, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", -1 }; static char *server_mode = NULL; @@ -107,6 +107,7 @@ main(int argc, char **argv) {"wal-keep-segments", required_argument, NULL, 'w'}, {"keep-history", required_argument, NULL, 'k'}, {"force", no_argument, NULL, 'F'}, + {"wait", no_argument, NULL, 'W'}, {"ignore-rsync-warning", no_argument, NULL, 'I'}, {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} @@ -133,7 +134,7 @@ main(int argc, char **argv) } - while ((c = getopt_long(argc, argv, "d:h:p:U:D:l:f:R:w:k:F:I:v", long_options, + while ((c = getopt_long(argc, argv, "d:h:p:U:D:l:f:R:w:k:F:W:I:v", long_options, &optindex)) != -1) { switch (c) @@ -177,6 +178,9 @@ main(int argc, char **argv) case 'F': runtime_options.force = true; break; + case 'W': + runtime_options.wait_for_master = true; + break; case 'I': runtime_options.ignore_rsync_warn = true; break; @@ -1378,10 +1382,18 @@ do_standby_follow(void) exit(ERR_BAD_CONFIG); } - /* we also need to check if there is any master in the cluster */ - log_info(_("%s connecting to master database\n"), progname); - master_conn = getMasterConnection(conn, repmgr_schema, - options.cluster_name, &master_id,(char *) &master_conninfo); + /* + * we also need to check if there is any master in the cluster + * or wait for one to appear if we have set the wait option + */ + log_info(_("%s discovering new master...\n"), progname); + + do + { + master_conn = getMasterConnection(conn, repmgr_schema, + options.cluster_name, &master_id,(char *) &master_conninfo); + } while (master_conn == NULL && runtime_options.wait_for_master); + if (master_conn == NULL) { log_err(_("There isn't a master to follow in this cluster\n")); @@ -1700,6 +1712,7 @@ help(const char *progname) printf(_(" -I, --ignore-rsync-warning ignore rsync partial transfer warning\n")); printf(_(" -k, --keep-history=VALUE keeps indicated number of days of history\n")); printf(_(" -F, --force force potentially dangerous operations to happen\n")); + printf(_(" -W, --wait wait for a master to appear")); printf(_("\n%s performs some tasks like clone a node, promote it "), progname); printf(_("or making follow another node and then exits.\n")); diff --git a/repmgr.conf.sample b/repmgr.conf.sample index 6e81aa3f..9daaf3f4 100644 --- a/repmgr.conf.sample +++ b/repmgr.conf.sample @@ -24,7 +24,7 @@ reconnect_interval=10 failover=automatic priority=-1 promote_command='repmgr standby promote -f /path/to/repmgr.conf' -follow_command='repmgr standby follow -f /path/to/repmgr.conf' +follow_command='repmgr standby follow -f /path/to/repmgr.conf -W' # Log level: possible values are DEBUG, INFO, NOTICE, WARNING, ERR, ALERT, CRIT or EMERG # Default: NOTICE diff --git a/repmgr.h b/repmgr.h index dcab7d46..295a4645 100644 --- a/repmgr.h +++ b/repmgr.h @@ -59,6 +59,7 @@ typedef struct char wal_keep_segments[MAXLEN]; bool verbose; bool force; + bool wait_for_master; bool ignore_rsync_warn; char masterport[MAXLEN];