diff options
author | Pavan Deolasee | 2015-01-07 13:00:38 +0000 |
---|---|---|
committer | Pavan Deolasee | 2015-04-15 05:49:14 +0000 |
commit | 1759a58ac03262b870904af45a826373f3594225 (patch) | |
tree | 3fc23a85fe10c97cbdac3da8ffd734731131bf21 | |
parent | 873b408f762fae090c5721d3f4e3eedb4e26adc1 (diff) |
Do not force remove data directories if they are not empty.
pgxc_ctl would try to cleanup specified directories (using rm -rf) even if they
are not empty. It does so for GTM, datanodes, coordinators and all other
components. This could lead to serious issues if user accidently specifies a
wrong directory since it will wipe out everything under that directory.
We now check if the directory is empty and then only proceed. Otherwise the
initialization step will be skipped and existing data directory will be used to
start the corresponding server. Also, we do this only for critical components
such as datanodes, coordinators and GTM master. Other components such as
datanode/coordinator/GTM slaves and GTM proxies can be recreated without any
data loss.
-rw-r--r-- | contrib/pgxc_ctl/coord_cmd.c | 8 | ||||
-rw-r--r-- | contrib/pgxc_ctl/datanode_cmd.c | 8 | ||||
-rw-r--r-- | contrib/pgxc_ctl/gtm_cmd.c | 15 | ||||
-rw-r--r-- | contrib/pgxc_ctl/utils.c | 61 | ||||
-rw-r--r-- | contrib/pgxc_ctl/utils.h | 1 |
5 files changed, 91 insertions, 2 deletions
diff --git a/contrib/pgxc_ctl/coord_cmd.c b/contrib/pgxc_ctl/coord_cmd.c index 891ab34703..1d4a1e5a23 100644 --- a/contrib/pgxc_ctl/coord_cmd.c +++ b/contrib/pgxc_ctl/coord_cmd.c @@ -77,6 +77,14 @@ cmd_t *prepare_initCoordinatorMaster(char *nodeName) nodeName); return(NULL); } + + if (pgxc_check_dir(aval(VAR_coordMasterDirs)[jj]) == 2) + { + elog(ERROR, "ERROR: target coordinator directory %s exists and is not empty. Skip initilialization.\n", + aval(VAR_coordMasterDirs)[jj]); + return NULL; + } + cmd = cmdInitdb = initCmd(aval(VAR_coordMasterServers)[jj]); snprintf(newCommand(cmdInitdb), MAXLINE, "rm -rf %s;" diff --git a/contrib/pgxc_ctl/datanode_cmd.c b/contrib/pgxc_ctl/datanode_cmd.c index c5a9f61f5b..b86ca4ded6 100644 --- a/contrib/pgxc_ctl/datanode_cmd.c +++ b/contrib/pgxc_ctl/datanode_cmd.c @@ -67,6 +67,14 @@ cmd_t *prepare_initDatanodeMaster(char *nodeName) if ((idx = datanodeIdx(nodeName)) < 0) return(NULL); + + if (pgxc_check_dir(aval(VAR_datanodeMasterDirs)[idx]) == 2) + { + elog(ERROR, "ERROR: target datanode directory %s exists and is not empty. Skip initilialization.\n", + aval(VAR_datanodeMasterDirs)[idx]); + return NULL; + } + /* Build each datanode's initialize command */ cmd = cmdInitdb = initCmd(aval(VAR_datanodeMasterServers)[idx]); snprintf(newCommand(cmdInitdb), MAXLINE, diff --git a/contrib/pgxc_ctl/gtm_cmd.c b/contrib/pgxc_ctl/gtm_cmd.c index c7be7ab09c..c7879bb3a2 100644 --- a/contrib/pgxc_ctl/gtm_cmd.c +++ b/contrib/pgxc_ctl/gtm_cmd.c @@ -53,6 +53,16 @@ cmd_t *prepare_initGtmMaster(void) char date[MAXTOKEN+1]; FILE *f; char **fileList = NULL; + int result; + + result = pgxc_check_dir(sval(VAR_gtmMasterDir)); + + if (result == 2) + { + elog(ERROR, "ERROR: target GTM directory %s exists and is not empty. Skip initilialization.\n", + sval(VAR_gtmMasterDir)); + return NULL; + } /* Kill current gtm, bild work directory and run initgtm */ cmdInitGtmMaster = initCmd(sval(VAR_gtmMasterServer)); @@ -106,13 +116,16 @@ int init_gtm_master(void) { int rc; cmdList_t *cmdList; + cmd_t *cmd; elog(INFO, "Initialize GTM master\n"); cmdList = initCmdList(); /* Kill current gtm, build work directory and run initgtm */ - addCmd(cmdList, prepare_initGtmMaster()); + if ((cmd = prepare_initGtmMaster())) + addCmd(cmdList, cmd); + rc = doCmdList(cmdList); cleanCmdList(cmdList); elog(INFO, "Done.\n"); diff --git a/contrib/pgxc_ctl/utils.c b/contrib/pgxc_ctl/utils.c index 279ecca5c6..dd79fa10dc 100644 --- a/contrib/pgxc_ctl/utils.c +++ b/contrib/pgxc_ctl/utils.c @@ -14,6 +14,7 @@ #include <stdlib.h> #include <string.h> #include <sys/types.h> +#include <dirent.h> #include <unistd.h> #include <errno.h> #include <stdio.h> @@ -28,6 +29,8 @@ #include "config.h" #include "variables.h" #include "varnames.h" +#include "c.h" + static int Malloc_ed = 0; static int Strdup_ed = 0; @@ -368,4 +371,60 @@ char *getIpAddress(char *hostName) trimNl(ipAddr); return ipAddr; } - + + +/* + * Test to see if a directory exists and is empty or not. + * + * Returns: + * 0 if nonexistent + * 1 if exists and empty + * 2 if exists and not empty + * -1 if trouble accessing directory (errno reflects the error) + */ +int +pgxc_check_dir(const char *dir) +{ + int result = 1; + DIR *chkdir; + struct dirent *file; + + errno = 0; + + chkdir = opendir(dir); + + if (chkdir == NULL) + return (errno == ENOENT) ? 0 : -1; + + while ((file = readdir(chkdir)) != NULL) + { + if (strcmp(".", file->d_name) == 0 || + strcmp("..", file->d_name) == 0) + { + /* skip this and parent directory */ + continue; + } + else + { + result = 2; /* not empty */ + break; + } + } + +#ifdef WIN32 + + /* + * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in + * released version + */ + if (GetLastError() == ERROR_NO_MORE_FILES) + errno = 0; +#endif + + closedir(chkdir); + + if (errno != 0) + result = -1; /* some kind of I/O error? */ + + return result; +} diff --git a/contrib/pgxc_ctl/utils.h b/contrib/pgxc_ctl/utils.h index d2a7eb4500..6d0fb9d691 100644 --- a/contrib/pgxc_ctl/utils.h +++ b/contrib/pgxc_ctl/utils.h @@ -33,6 +33,7 @@ extern int pingNode(char *host, char *port); extern void trimNl(char *s); extern char *getChPidList(char *host, pid_t ppid); extern char *getIpAddress(char *hostName); +extern int pgxc_check_dir(const char *dir); #define get_postmaster_pid(host, dir) get_prog_pid(host, "postmaster", dir) #define get_gtm_pid(host, dir) get_prog_pid(host, "gtm", dir) |