diff --git a/HISTORY b/HISTORY
index c8f670a8..82055fc7 100644
--- a/HISTORY
+++ b/HISTORY
@@ -18,6 +18,8 @@
GitHub #451 (Ian)
repmgr: fix "primary_slot_name" when using "standby clone" with --recovery-conf-only;
GitHub #474 (Ian)
+ repmgr: don't perform a switchover if an exclusive backup is running;
+ GitHub #476 (MartÃn)
repmgr: enable "witness unregister" to be run on any node; GitHub #472 (Ian)
repmgrd: create a PID file by default; GitHub #457 (Ian)
repmgrd: daemonize process by default; GitHub #458 (Ian)
diff --git a/dbutils.c b/dbutils.c
index 607821df..0a52c377 100644
--- a/dbutils.c
+++ b/dbutils.c
@@ -1601,6 +1601,39 @@ repmgrd_get_local_node_id(PGconn *conn)
}
+/*
+ * Function that checks if the primary is in exclusive backup mode.
+ * We'll use this when executing an action can conflict with an exclusive
+ * backup.
+ */
+BackupState
+server_in_exclusive_backup_mode(PGconn *conn)
+{
+ BackupState backup_state = BACKUP_STATE_UNKNOWN;
+ PGresult *res = PQexec(conn, "SELECT pg_catalog.pg_is_in_backup()");
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ log_error(_("unable to retrieve information regarding backup mode of node"));
+ log_detail("%s", PQerrorMessage(conn));
+ PQclear(res);
+ return BACKUP_STATE_UNKNOWN;
+ }
+
+ if (atobool(PQgetvalue(res, 0, 0)) == true)
+ {
+ backup_state = BACKUP_STATE_IN_BACKUP;
+ }
+ else
+ {
+ backup_state = BACKUP_STATE_NO_BACKUP;
+ }
+
+ PQclear(res);
+
+ return backup_state;
+}
+
/* ================ */
/* result functions */
@@ -3953,31 +3986,7 @@ connection_ping(PGconn *conn)
return;
}
-/*
- * Function that checks if the primary is in exclusive backup mode.
- * We'll use this when executing an action can conflict with an exclusive
- * backup.
- */
-bool
-server_not_in_exclusive_backup_mode(PGconn *conn)
-{
- PGresult *res = PQexec(conn, "SELECT pg_is_in_backup()");
- if (PQresultStatus(res) != PGRES_TUPLES_OK)
- {
- log_error(_("unable to retrieve information regarding backup mode of node"));
- log_detail("%s", PQerrorMessage(conn));
- PQclear(res);
- return false;
- }
-
- if (strcmp(PQgetvalue(res, 0, 0), "t") == 0)
- {
- log_warning(_("node is in exclusive backup mode"));
- return false;
- }
- return true;
-}
/* ==================== */
/* monitoring functions */
diff --git a/dbutils.h b/dbutils.h
index 3b765acb..1978a577 100644
--- a/dbutils.h
+++ b/dbutils.h
@@ -96,6 +96,14 @@ typedef enum
SLOT_ACTIVE
} ReplSlotStatus;
+typedef enum
+{
+ BACKUP_STATE_UNKNOWN = -1,
+ BACKUP_STATE_IN_BACKUP,
+ BACKUP_STATE_NO_BACKUP
+} BackupState;
+
+
/*
* Struct to store node information
*/
@@ -390,6 +398,7 @@ int get_ready_archive_files(PGconn *conn, const char *data_directory);
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
int repmgrd_get_local_node_id(PGconn *conn);
+BackupState server_in_exclusive_backup_mode(PGconn *conn);
/* extension functions */
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
@@ -467,7 +476,6 @@ int wait_connection_availability(PGconn *conn, long long timeout);
bool is_server_available(const char *conninfo);
bool is_server_available_params(t_conninfo_param_list *param_list);
void connection_ping(PGconn *conn);
-bool server_not_in_exclusive_backup_mode(PGconn *conn);
/* monitoring functions */
void
diff --git a/doc/appendix-release-notes.sgml b/doc/appendix-release-notes.sgml
index f3e5e22a..d5b63789 100644
--- a/doc/appendix-release-notes.sgml
+++ b/doc/appendix-release-notes.sgml
@@ -106,6 +106,14 @@
+
+
+ repmgr standby switchover
+ will refuse to run if an exclusive backup is taking place on the current primary.
+ (GitHub #476).
+
+
+
diff --git a/doc/repmgr-standby-switchover.sgml b/doc/repmgr-standby-switchover.sgml
index 81b06450..ebaa2d87 100644
--- a/doc/repmgr-standby-switchover.sgml
+++ b/doc/repmgr-standby-switchover.sgml
@@ -46,6 +46,9 @@
repmgrd should not be active on any nodes while a switchover is being
executed. This restriction may be lifted in a later version.
+
+ &repmgr; will not perform the switchover if an exclusive backup is running on the current primary.
+
diff --git a/doc/switchover.sgml b/doc/switchover.sgml
index 000d3e8c..69119ca3 100644
--- a/doc/switchover.sgml
+++ b/doc/switchover.sgml
@@ -57,7 +57,7 @@
As mentioned in the previous section, success of the switchover operation depends on
- &repmgr; being able to shut down the current primary server quickly and cleanly.
+ &repmgr; being able to shut down the current primary server quickly and cleanly.
@@ -121,15 +121,21 @@
-
- Check that access from applications is minimalized or preferably blocked
- completely, so applications are not unexpectedly interrupted.
+ Check that access from applications is minimalized or preferably blocked
+ completely, so applications are not unexpectedly interrupted.
+
+
+
+
+ If an exclusive backup is running on the current primary, &repmgr; will not perform the
+ switchover.
+
- Check there is no significant replication lag on standbys attached to the
- current primary.
+ Check there is no significant replication lag on standbys attached to the
+ current primary.
@@ -147,6 +153,7 @@
+
Finally, consider executing repmgr standby switchover with the
--dry-run option; this will perform any necessary checks and inform you about
diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c
index d778a075..16465521 100644
--- a/repmgr-action-standby.c
+++ b/repmgr-action-standby.c
@@ -2919,11 +2919,12 @@ do_standby_switchover(void)
* If the DBA wants to do the switchover anyway, he should first stop the
* backup that's running.
*/
- if (!server_not_in_exclusive_backup_mode(remote_conn))
+ if (server_in_exclusive_backup_mode(remote_conn) != BACKUP_STATE_NO_BACKUP)
{
- log_error(_("can't perform a switchover while primary server is in exclusive backup mode"));
+ log_error(_("unable to perform a switchover while primary server is in exclusive backup mode"));
log_hint(_("stop backup before attempting the switchover"));
+ PQfinish(local_conn);
PQfinish(remote_conn);
exit(ERR_SWITCHOVER_FAIL);