From 75aad9a85effb0da11ce8a4e317e2132395354a2 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Wed, 30 Sep 2015 17:01:23 +0900 Subject: [PATCH] repmgr witness create --force: overwrite existing data directory Per Github #82 (dimitri). --- check_dir.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- check_dir.h | 1 + repmgr.c | 4 ++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/check_dir.c b/check_dir.c index 8038e752..6289079b 100644 --- a/check_dir.c +++ b/check_dir.c @@ -23,15 +23,19 @@ #include #include #include +#include /* NB: postgres_fe must be included BEFORE check_dir */ #include #include -#include "check_dir.h" +#include "check_dir.h" #include "strutil.h" #include "log.h" +static bool _create_pg_dir(char *dir, bool force, bool for_witness); +static int unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); + /* * make sure the directory either doesn't exist or is empty * we use this function to check the new data directory and @@ -244,6 +248,19 @@ is_pg_dir(char *dir) bool create_pg_dir(char *dir, bool force) +{ + return _create_pg_dir(dir, force, false); +} + +bool +create_witness_pg_dir(char *dir, bool force) +{ + return _create_pg_dir(dir, force, true); +} + + +static bool +_create_pg_dir(char *dir, bool force, bool for_witness) { bool pg_dir = false; @@ -280,12 +297,24 @@ create_pg_dir(char *dir, bool force) pg_dir = is_pg_dir(dir); - /* - * we use force to reduce the time needed to restore a node which - * turn async after a failover or anything else - */ + if (pg_dir && force) { + + /* + * The witness server does not store any data other than a copy of the + * repmgr metadata, so in --force mode we can simply overwrite the + * directory. + * + * For non-witness servers, we'll leave the data in place, both to reduce + * the risk of unintentional data loss and to make it possible for the + * data directory to be brought up-to-date with rsync. + */ + if (for_witness) + { + log_notice(_("deleting existing data directory \"%s\"\n"), dir); + nftw(dir, unlink_dir_callback, 64, FTW_DEPTH | FTW_PHYS); + } /* Let it continue */ break; } @@ -307,3 +336,14 @@ create_pg_dir(char *dir, bool force) } return true; } + +static int +unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) +{ + int rv = remove(fpath); + + if (rv) + perror(fpath); + + return rv; +} diff --git a/check_dir.h b/check_dir.h index d11ec589..b3d44134 100644 --- a/check_dir.h +++ b/check_dir.h @@ -26,5 +26,6 @@ bool create_dir(char *dir); bool set_dir_permissions(char *dir); bool is_pg_dir(char *dir); bool create_pg_dir(char *dir, bool force); +bool create_witness_pg_dir(char *dir, bool force); #endif diff --git a/repmgr.c b/repmgr.c index 1e9f46cb..5b775335 100644 --- a/repmgr.c +++ b/repmgr.c @@ -2010,7 +2010,7 @@ do_witness_create(void) masterconn = establish_db_connection_by_params(keywords, values, true); if (!masterconn) { - /* No event logging possible as we can't connect to the master */ + /* No event logging possible here as we can't connect to the master */ log_err(_("unable to connect to master\n")); exit(ERR_DB_CON); } @@ -2065,7 +2065,7 @@ do_witness_create(void) } /* Check this directory could be used as a PGDATA dir */ - if (!create_pg_dir(runtime_options.dest_dir, runtime_options.force)) + if (!create_witness_pg_dir(runtime_options.dest_dir, runtime_options.force)) { PQExpBufferData errmsg; initPQExpBuffer(&errmsg);