1236 lines
40 KiB
C++
1236 lines
40 KiB
C++
/*-------------------------------------------------------------------------
|
|
*
|
|
* config.c
|
|
*
|
|
* Configuration module of Postgres-XC configuration and operation tool.
|
|
*
|
|
* Copyright (c) 2013 Postgres-XC Development Group
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
/*
|
|
* This module handles pgxc_ctl configuration. This file includes
|
|
* parser of incoming variable inforation which is installed to
|
|
* pgxc_ctl variable system.
|
|
*
|
|
* This module also checks if there's any conficts in the resources
|
|
* among different nodes.
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <readline/readline.h>
|
|
#include <readline/history.h>
|
|
#include "variables.h"
|
|
#include "varnames.h"
|
|
#include "config.h"
|
|
#include "pgxc_ctl_log.h"
|
|
#include "pgxc_ctl.h"
|
|
#include "utils.h"
|
|
#include "do_shell.h"
|
|
|
|
extern char* pgxc_ctl_conf_prototype[];
|
|
|
|
static void addServer(char** name);
|
|
static void verifyResource(void);
|
|
|
|
enum Quote { UNQUOTED, SINGLEQUOTED, DOUBLEQUOTED };
|
|
|
|
/*====================================================================
|
|
*
|
|
* Configuration parser
|
|
*
|
|
* The following functions read, parse and constract variables.
|
|
*
|
|
* As you see pgxc_ctl_bash_script[] in pgxc_ctl_bash.c, each variable
|
|
* will be read in the form of
|
|
* varname value value ....
|
|
*
|
|
* Each variable is basically an array. Sometimes, only the first
|
|
* element is needed.
|
|
*
|
|
* Please note that pgxc_ctl_bash.c is build by make_signature script
|
|
* using pgxc_ctl_bash_2 and pgxc_cont_conf_part dynamically.
|
|
*
|
|
* You can change detailed behaviors of the script by editing these
|
|
* files. Be careful! Please maintain the interface to this module.
|
|
*
|
|
*===================================================================
|
|
*/
|
|
/*
|
|
* Get a token from the line
|
|
*/
|
|
char* get_word(char* line, char** token)
|
|
{
|
|
enum Quote quoted = UNQUOTED;
|
|
|
|
*token = NULL;
|
|
|
|
if (!line)
|
|
return NULL;
|
|
for (; *line == ' ' || *line == '\t'; line++)
|
|
;
|
|
if (!*line) {
|
|
*token = NULL;
|
|
return NULL;
|
|
}
|
|
if (*line == '"') {
|
|
quoted = DOUBLEQUOTED;
|
|
line++;
|
|
} else if (*line == '\'') {
|
|
quoted = SINGLEQUOTED;
|
|
line++;
|
|
} else if (*line == '#') {
|
|
*line = 0;
|
|
*token = NULL;
|
|
return NULL;
|
|
}
|
|
*token = line;
|
|
if (quoted == DOUBLEQUOTED) {
|
|
for (; *line && *line != '\n' && *line != '"'; line++)
|
|
;
|
|
if (*line == '"') {
|
|
*line = 0;
|
|
line++;
|
|
}
|
|
} else if (quoted == SINGLEQUOTED) {
|
|
for (; *line && *line != '\n' && *line != '\''; line++)
|
|
;
|
|
if (*line == '\'') {
|
|
*line = 0;
|
|
line++;
|
|
}
|
|
} else
|
|
for (; *line && *line != ' ' && *line != '\t' && *line != '\n' && *line != '#'; line++)
|
|
;
|
|
if (*line == '#') {
|
|
*line = 0;
|
|
return (line);
|
|
} else if (*line) {
|
|
*line = 0;
|
|
return (line + 1);
|
|
} else
|
|
return (line);
|
|
}
|
|
|
|
/*
|
|
* Parse line and create/update a variable.
|
|
*/
|
|
static void parse_line(char* line)
|
|
{
|
|
char* varname = NULL;
|
|
char* val = NULL;
|
|
pgxc_ctl_var* newv = NULL;
|
|
|
|
line = get_word(line, &varname);
|
|
if (!varname)
|
|
return;
|
|
if (!(newv = confirm_var(varname)))
|
|
return;
|
|
reset_value(newv);
|
|
while ((line = get_word(line, &val))) {
|
|
if (val) {
|
|
add_val(newv, val);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Parse line and filter only pre-defined variables.
|
|
*
|
|
* This blocks any unknow variables to be build within pgxc_ctl structure.
|
|
*/
|
|
static void parse_line_select(char* line, char* selectThis[])
|
|
{
|
|
char* varname = NULL;
|
|
char* val = NULL;
|
|
pgxc_ctl_var* newv = NULL;
|
|
int ii;
|
|
|
|
line = get_word(line, &varname);
|
|
if (!varname || varname[0] == '#')
|
|
return;
|
|
for (ii = 0; selectThis[ii]; ii++) {
|
|
if (strcmp(varname, selectThis[ii]) == 0) {
|
|
if (!(newv = confirm_var(varname)))
|
|
return;
|
|
while ((line = get_word(line, &val))) {
|
|
if (val)
|
|
add_val(newv, val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Configuration file I/F
|
|
*/
|
|
void read_vars(FILE* conf)
|
|
{
|
|
char line[MAXLINE + 1];
|
|
|
|
while (fgets(line, MAXLINE, conf))
|
|
parse_line(line);
|
|
}
|
|
|
|
/*
|
|
* Configuration file I/F
|
|
*/
|
|
void read_selected_vars(FILE* conf, char* selectThis[])
|
|
{
|
|
char line[MAXLINE + 1];
|
|
|
|
while (fgets(line, MAXLINE, conf))
|
|
parse_line_select(line, selectThis);
|
|
}
|
|
|
|
/*
|
|
* Build the configuraiton file prototype.
|
|
*/
|
|
void install_conf_prototype(char* path)
|
|
{
|
|
char cmd[MAXPATH + 1];
|
|
FILE* pgxc_config_proto = fopen(path, "w");
|
|
int i;
|
|
|
|
if (!pgxc_config_proto) {
|
|
elog(ERROR, "ERROR Could not open configuration prototype to %s. %s\n", path, strerror(errno));
|
|
return;
|
|
}
|
|
for (i = 0; pgxc_ctl_conf_prototype[i]; i++)
|
|
fprintf(pgxc_config_proto, "%s\n", pgxc_ctl_conf_prototype[i]);
|
|
fclose(pgxc_config_proto);
|
|
snprintf(cmd, MAXPATH, "chmod +x %s", path);
|
|
system(cmd);
|
|
}
|
|
|
|
/*
|
|
* Get all the servers --> VAR_allServers
|
|
*/
|
|
static void addServer(char** name)
|
|
{
|
|
int ii, jj;
|
|
int flag;
|
|
|
|
confirm_var(VAR_allServers);
|
|
|
|
for (ii = 0; name[ii]; ii++) {
|
|
flag = TRUE;
|
|
for (jj = 0; aval(VAR_allServers)[jj]; jj++) {
|
|
if (strcmp(name[ii], aval(VAR_allServers)[jj]) != 0)
|
|
continue;
|
|
else {
|
|
flag = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (flag)
|
|
add_val(find_var(VAR_allServers), name[ii]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Test each node and build target server list
|
|
*/
|
|
void makeServerList(void)
|
|
{
|
|
/* Initialize */
|
|
reset_var(VAR_allServers);
|
|
/* GTM Master */
|
|
addServer(aval(VAR_gtmMasterServer));
|
|
/* GTM Slave */
|
|
if (isVarYes(VAR_gtmSlave))
|
|
addServer(aval(VAR_gtmSlaveServer));
|
|
/* GTM_Proxy */
|
|
if (isVarYes(VAR_gtmProxy))
|
|
addServer(aval(VAR_gtmProxyServers));
|
|
/* Coordinator Master */
|
|
if (find_var(VAR_coordMasterServers))
|
|
addServer(aval(VAR_coordMasterServers));
|
|
/* Coordinator Slave */
|
|
if (isVarYes(VAR_coordSlave))
|
|
addServer(aval(VAR_coordSlaveServers));
|
|
/* Datanode Master */
|
|
addServer(aval(VAR_datanodeMasterServers));
|
|
/* Datanode Slave */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
addServer(aval(VAR_datanodeSlaveServers));
|
|
/* Should add secondary slaves */
|
|
}
|
|
|
|
/*
|
|
* Take care of "no" slaves and build server list. At present, we don't support
|
|
* Cascaded or multi slaves. This will be supported in the future.
|
|
*
|
|
* Please note that log archive backup site is not counted as this server list
|
|
* because such servers are not likely to provide XC node operation.
|
|
*
|
|
* Log archive backup will be implemented in the future.
|
|
*/
|
|
int is_none(char* s)
|
|
{
|
|
if (strcmp(s, "none") == 0)
|
|
return TRUE;
|
|
if (strcmp(s, "N/A") == 0)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Remove gtm slave. Used at failover.
|
|
*/
|
|
static void emptyGtmSlave()
|
|
{
|
|
reset_var_val(VAR_gtmSlaveServer, "none");
|
|
reset_var_val(VAR_gtmSlavePort, "0");
|
|
reset_var_val(VAR_gtmSlaveDir, "none");
|
|
}
|
|
|
|
/*
|
|
* Remove gtm proxies. Used when a node crashes.
|
|
* Because gtm_proxy is expected to be running at any target
|
|
* server, we don't have gtm_proxy slaves.
|
|
* We can just initialize gtm_proy using gtminit, configure and
|
|
* run it.
|
|
*/
|
|
static void emptyGtmProxies()
|
|
{
|
|
int ii;
|
|
|
|
reset_var_val(VAR_gtmProxy, "n");
|
|
reset_var(VAR_gtmProxyServers);
|
|
reset_var(VAR_gtmProxyNames);
|
|
reset_var(VAR_gtmProxyPorts);
|
|
reset_var(VAR_gtmProxyDirs);
|
|
reset_var_val(VAR_gtmPxyExtraConfig, "none");
|
|
reset_var(VAR_gtmPxySpecificExtraConfig);
|
|
for (ii = 0; ii < arraySizeName(VAR_allServers); ii++) {
|
|
add_val(find_var(VAR_gtmProxyServers), "none");
|
|
add_val(find_var(VAR_gtmProxyNames), "none");
|
|
add_val(find_var(VAR_gtmProxyPorts), "-1");
|
|
add_val(find_var(VAR_gtmProxyDirs), "none");
|
|
add_val(find_var(VAR_gtmPxyExtraConfig), "none");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Removes coordinator slaves from pgxc_ctl configuration.
|
|
* This is needed when a slave promotes and becomes a new
|
|
* master.
|
|
*/
|
|
static void emptyCoordSlaves()
|
|
{
|
|
int ii;
|
|
|
|
reset_var_val(VAR_coordSlave, "n");
|
|
reset_var(VAR_coordSlaveServers);
|
|
reset_var(VAR_coordSlaveDirs);
|
|
reset_var(VAR_coordArchLogDirs);
|
|
for (ii = 0; ii < arraySizeName(VAR_coordNames); ii++) {
|
|
add_val(find_var(VAR_coordSlaveServers), "none");
|
|
add_val(find_var(VAR_coordSlaveDirs), "none");
|
|
add_val(find_var(VAR_coordArchLogDirs), "none");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Removes datanode slave from pgxc_ctl configuration.
|
|
*/
|
|
static void emptyDatanodeSlaves()
|
|
{
|
|
int ii;
|
|
|
|
reset_var_val(VAR_datanodeSlave, "n");
|
|
reset_var(VAR_datanodeSlaveServers);
|
|
reset_var(VAR_datanodeSlaveDirs);
|
|
reset_var(VAR_datanodeArchLogDirs);
|
|
for (ii = 0; ii < arraySizeName(VAR_datanodeSlaveServers); ii++) {
|
|
add_val(find_var(VAR_datanodeSlaveServers), "none");
|
|
add_val(find_var(VAR_coordSlaveDirs), "none");
|
|
add_val(find_var(VAR_coordArchLogDirs), "none");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Scans initial configuration and set up "not configured" things.
|
|
*
|
|
* If, for example, gtm proxy is not configured,
|
|
* we set gtmProxy variable to "n".
|
|
*
|
|
* When gtmProxy varieble is already set to "n", remove gtm_proxy
|
|
* configuration information.
|
|
*
|
|
* Similar handling will be done for gtm slave, coordinator slaves
|
|
* and datanode slaves.
|
|
*/
|
|
void handle_no_slaves()
|
|
{
|
|
int is_empty;
|
|
int ii;
|
|
|
|
/* GTM Slave */
|
|
if (!find_var(VAR_gtmSlave))
|
|
reset_var_val(VAR_gtmSlave, "n");
|
|
if (!isVarYes(VAR_gtmSlave))
|
|
emptyGtmSlave();
|
|
else {
|
|
confirm_var(VAR_gtmSlaveServer);
|
|
if (!sval(VAR_gtmSlaveServer) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
emptyGtmSlave();
|
|
reset_var_val(VAR_gtmSlaveServer, "n");
|
|
}
|
|
}
|
|
|
|
/* GTM Proxy */
|
|
if (!find_var(VAR_gtmProxy))
|
|
reset_var_val(VAR_gtmProxy, "n");
|
|
if (!isVarYes(VAR_gtmProxy))
|
|
emptyGtmProxies();
|
|
else {
|
|
is_empty = TRUE;
|
|
for (ii = 0; aval(VAR_gtmProxyServers)[ii]; ii++) {
|
|
if (is_none(aval(VAR_gtmProxyServers)[ii]))
|
|
continue;
|
|
else {
|
|
is_empty = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (is_empty) {
|
|
reset_var_val(VAR_gtmProxy, "n");
|
|
emptyGtmProxies();
|
|
}
|
|
}
|
|
/* Coordinator Slaves */
|
|
if (!find_var(VAR_coordSlave))
|
|
reset_var_val(VAR_coordSlave, "n");
|
|
if (!isVarYes(VAR_coordSlave))
|
|
emptyCoordSlaves();
|
|
else {
|
|
is_empty = TRUE;
|
|
if (find_var(VAR_coordSlaveServers)) {
|
|
for (ii = 0; aval(VAR_coordSlaveServers)[ii]; ii++) {
|
|
if (is_none(aval(VAR_coordSlaveServers)[ii]))
|
|
continue;
|
|
else {
|
|
is_empty = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (is_empty) {
|
|
reset_var_val(VAR_coordSlave, "n");
|
|
emptyCoordSlaves();
|
|
}
|
|
} else {
|
|
elog(WARNING, "WARNING: coordSlaveServers variable not found where coordSlave is set to \"y\"\n");
|
|
reset_var_val(VAR_coordSlave, "n");
|
|
emptyCoordSlaves();
|
|
}
|
|
}
|
|
/* Datanode Slaves */
|
|
if (!find_var(VAR_datanodeSlave))
|
|
reset_var_val(VAR_datanodeSlave, "n");
|
|
if (!isVarYes(VAR_datanodeSlave))
|
|
emptyDatanodeSlaves();
|
|
else {
|
|
is_empty = TRUE;
|
|
if (find_var(VAR_datanodeSlaveServers)) {
|
|
for (ii = 0; aval(VAR_datanodeSlaveServers)[ii]; ii++) {
|
|
if (is_none(aval(VAR_datanodeSlaveServers)[ii]))
|
|
continue;
|
|
else {
|
|
is_empty = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (is_empty) {
|
|
reset_var_val(VAR_datanodeSlave, "n");
|
|
emptyDatanodeSlaves();
|
|
}
|
|
} else {
|
|
elog(WARNING, "WARNING: datanodeSlaveServers variable not found where datanodeSlave is set to \"y\"\n");
|
|
reset_var_val(VAR_datanodeSlave, "n");
|
|
emptyDatanodeSlaves();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check if there's no overlap in the resource --> Port, host and directory.
|
|
*/
|
|
static void reportMissingVar(char* name)
|
|
{
|
|
elog(ERROR, "ERROR: %s is not configured.\n", name);
|
|
}
|
|
|
|
static int anyConfigErrors = FALSE;
|
|
|
|
static void checkIfVarIsConfigured(char* name)
|
|
{
|
|
if (!find_var(name) || !sval(name)) {
|
|
anyConfigErrors = TRUE;
|
|
reportMissingVar(name);
|
|
}
|
|
}
|
|
|
|
static void checkIfConfigured(char* names[])
|
|
{
|
|
int ii;
|
|
for (ii = 0; names[ii]; ii++)
|
|
checkIfVarIsConfigured(names[ii]);
|
|
}
|
|
|
|
static void checkConfiguredAndSize(char* names[], char* msg)
|
|
{
|
|
int ii;
|
|
int sz0;
|
|
|
|
for (ii = 0; names[ii]; ii++) {
|
|
checkIfVarIsConfigured(names[ii]);
|
|
confirm_var(names[ii]);
|
|
}
|
|
sz0 = arraySizeName(names[0]);
|
|
for (ii = 1; names[ii]; ii++) {
|
|
if (arraySizeName(names[ii]) != sz0) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR,
|
|
"ERROR: Number of elements in %s definitions are different %s and %s. Check your configuration\n",
|
|
msg,
|
|
names[0],
|
|
names[ii]);
|
|
}
|
|
}
|
|
}
|
|
|
|
int checkSpecificResourceConflict(char* name, char* host, int port, char* dir, int is_gtm)
|
|
{
|
|
if (checkNameConflict(name, is_gtm))
|
|
return 1;
|
|
if (checkPortConflict(host, port))
|
|
return 1;
|
|
if (checkDirConflict(host, dir))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
/*
|
|
* Note that 1 will be returned when a conflict is found
|
|
*/
|
|
int checkNameConflict(char* name, int is_gtm)
|
|
{
|
|
int ii;
|
|
|
|
/*
|
|
* GTM Master
|
|
*/
|
|
if (!is_gtm && strcasecmp(name, sval(VAR_gtmName)) == 0)
|
|
return 1;
|
|
/*
|
|
* GTM Proxy
|
|
*/
|
|
if (isVarYes(VAR_gtmProxy))
|
|
for (ii = 0; aval(VAR_gtmProxyNames)[ii]; ii++)
|
|
if (strcasecmp(name, aval(VAR_gtmProxyNames)[ii]) == 0)
|
|
return 1;
|
|
/*
|
|
* Coordinator
|
|
*/
|
|
for (ii = 0; aval(VAR_coordNames)[ii]; ii++)
|
|
if (strcasecmp(name, aval(VAR_coordNames)[ii]) == 0)
|
|
return 1;
|
|
/*
|
|
* Datanode
|
|
*/
|
|
for (ii = 0; aval(VAR_datanodeNames)[ii]; ii++)
|
|
if (strcasecmp(name, aval(VAR_datanodeNames)[ii]) == 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Note that 1 will be returned when a conflict is found.
|
|
*/
|
|
int checkPortConflict(char* host, int port)
|
|
{
|
|
int ii;
|
|
|
|
/* GTM Master */
|
|
if ((strcasecmp(host, sval(VAR_gtmMasterServer)) == 0) && (atoi(sval(VAR_gtmMasterPort)) == port))
|
|
return 1;
|
|
/* GTM Slave */
|
|
if (isVarYes(VAR_gtmSlave) && (strcasecmp(host, sval(VAR_gtmSlaveServer)) == 0) &&
|
|
(atoi(sval(VAR_gtmSlavePort)) == port))
|
|
return 1;
|
|
/* GTM Proxy */
|
|
if (isVarYes(VAR_gtmProxy))
|
|
for (ii = 0; aval(VAR_gtmProxyNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_gtmProxyServers)[ii]) == 0) && (atoi(aval(VAR_gtmProxyPorts)[ii]) == port))
|
|
return 1;
|
|
/* Coordinator Master */
|
|
for (ii = 0; aval(VAR_coordNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_coordMasterServers)[ii]) == 0) &&
|
|
((atoi(aval(VAR_coordPorts)[ii]) == port) || (atoi(aval(VAR_poolerPorts)[ii])) == port))
|
|
return 1;
|
|
/* Coordinator Slave */
|
|
if (isVarYes(VAR_coordSlave))
|
|
for (ii = 0; aval(VAR_coordNames)[ii]; ii++)
|
|
if (doesExist(VAR_coordSlaveServers, ii) && !is_none(aval(VAR_coordSlaveServers)[ii]) &&
|
|
(strcasecmp(host, aval(VAR_coordSlaveServers)[ii]) == 0) && (atoi(aval(VAR_coordPorts)[ii]) == port))
|
|
return 1;
|
|
/* Datanode Master */
|
|
for (ii = 0; aval(VAR_datanodeNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_datanodeMasterServers)[ii]) == 0) && (atoi(aval(VAR_datanodePorts)[ii]) == port))
|
|
return 1;
|
|
/* Datanode Slave */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
for (ii = 0; aval(VAR_datanodeNames)[ii]; ii++)
|
|
if (doesExist(VAR_datanodeSlaveServers, ii) && !is_none(aval(VAR_datanodeSlaveServers)[ii]) &&
|
|
(strcasecmp(host, aval(VAR_datanodeSlaveServers)[ii]) == 0) &&
|
|
(atoi(aval(VAR_datanodePorts)[ii]) == port))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int checkDirConflict(char* host, char* dir)
|
|
{
|
|
int ii;
|
|
|
|
/* GTM Master */
|
|
if ((strcasecmp(host, sval(VAR_gtmMasterServer)) == 0) && (strcmp(dir, sval(VAR_gtmMasterDir)) == 0))
|
|
return 1;
|
|
/* GTM Slave */
|
|
if (isVarYes(VAR_gtmSlave) && (strcasecmp(host, sval(VAR_gtmSlaveServer)) == 0) &&
|
|
(strcmp(dir, sval(VAR_gtmSlaveDir)) == 0))
|
|
return 1;
|
|
/* GTM Proxy */
|
|
if (isVarYes(VAR_gtmProxy))
|
|
for (ii = 0; aval(VAR_gtmProxyNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_gtmProxyServers)[ii]) == 0) &&
|
|
(strcmp(dir, aval(VAR_gtmProxyDirs)[ii]) == 0))
|
|
return 1;
|
|
/* Coordinator Master */
|
|
for (ii = 0; aval(VAR_coordNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_coordMasterServers)[ii]) == 0) &&
|
|
(strcmp(dir, aval(VAR_coordMasterDirs)[ii]) == 0))
|
|
return 1;
|
|
/* Coordinator Slave */
|
|
if (isVarYes(VAR_coordSlave))
|
|
for (ii = 0; aval(VAR_coordNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_coordSlaveServers)[ii]) == 0) &&
|
|
(strcmp(dir, aval(VAR_coordSlaveDirs)[ii]) == 0))
|
|
return 1;
|
|
/* Datanode Master */
|
|
for (ii = 0; aval(VAR_datanodeNames)[ii]; ii++)
|
|
if ((strcasecmp(host, aval(VAR_datanodeMasterServers)[ii]) == 0) &&
|
|
(strcmp(dir, aval(VAR_datanodeMasterDirs)[ii]) == 0))
|
|
return 1;
|
|
/* Datanode Slave */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
if (doesExist(VAR_datanodeSlaveServers, ii) && doesExist(VAR_datanodeSlaveDirs, ii) &&
|
|
(strcasecmp(host, aval(VAR_datanodeSlaveServers)[ii]) == 0) &&
|
|
(strcmp(dir, aval(VAR_datanodeSlaveDirs)[ii]) == 0))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Check if there's any conflict among src and dest, checks duplicate in names, servers, ports and directories.
|
|
*
|
|
* The rules are:
|
|
*
|
|
* 1) Each node (gtm, gtm_proxy, coordinator, datanode) must have unique name.
|
|
*
|
|
* 2) A port, in a given host, must be owned (listed to) only by single node.
|
|
*
|
|
* 3) A directory, in a given host, must be owned (used) only by single node.
|
|
*/
|
|
static void checkResourceConflict(char* srcNames, char* srcServers, char* srcPorts, char* srcPoolers, char* srcDirs,
|
|
char* destNames, char* destServers, char* destPorts, char* destPoolers, char* destDirs, int destOnly, int checkName)
|
|
{
|
|
int ii, jj;
|
|
|
|
if (!srcNames || !find_var(srcNames)) {
|
|
/* No source specified */
|
|
return;
|
|
}
|
|
if (!destOnly) {
|
|
/* Check conflict among the source first */
|
|
for (ii = 0; aval(srcNames)[ii]; ii++) {
|
|
if (is_none(aval(srcNames)[ii]))
|
|
continue;
|
|
/* Pooler and the port in the same name */
|
|
if (srcPoolers && (atoi(aval(srcPorts)[ii]) == atoi(aval(srcPoolers)[ii]))) {
|
|
if (atoi(aval(srcPorts)[ii]) > 0) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in between port and pooler within %s variable.\n", srcNames);
|
|
}
|
|
}
|
|
if (checkName && srcNames && !doesExist(srcNames, ii))
|
|
assign_arrayEl(srcNames, ii, "none", NULL);
|
|
if (srcServers && !doesExist(srcServers, ii))
|
|
assign_arrayEl(srcServers, ii, "none", NULL);
|
|
if (srcPoolers && !doesExist(srcPoolers, ii))
|
|
assign_arrayEl(srcPoolers, ii, "-1", "-1");
|
|
if (srcPorts && !doesExist(srcPorts, ii))
|
|
assign_arrayEl(srcPorts, ii, "-1", "-1");
|
|
if (srcDirs && !doesExist(srcDirs, ii))
|
|
assign_arrayEl(srcDirs, ii, "none", NULL);
|
|
for (jj = ii + 1; aval(srcNames)[jj]; jj++) {
|
|
/* Name conflict */
|
|
if (checkName && srcNames && !doesExist(srcNames, jj))
|
|
assign_arrayEl(srcNames, jj, "none", NULL);
|
|
if (checkName && srcNames && (strcmp(aval(srcNames)[ii], aval(srcNames)[jj]) == 0)) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in resource name within %s variable.\n", srcNames);
|
|
}
|
|
if (srcServers && is_none(aval(srcServers)[ii]))
|
|
continue;
|
|
if (srcServers && !doesExist(srcServers, jj))
|
|
assign_arrayEl(srcServers, jj, "none", NULL);
|
|
if (srcServers && strcmp(aval(srcServers)[ii], aval(srcServers)[jj]) == 0) {
|
|
/* Ports and Poolers */
|
|
if (srcPorts && !doesExist(srcPorts, jj))
|
|
assign_arrayEl(srcPorts, jj, "-1", "-1");
|
|
if (srcPoolers && !doesExist(srcPoolers, jj))
|
|
assign_arrayEl(srcPoolers, jj, "-1", "-1");
|
|
if ((srcPorts && (atoi(aval(srcPorts)[ii]) > 0) &&
|
|
(atoi(aval(srcPorts)[ii]) == atoi(aval(srcPorts)[jj]))) ||
|
|
(srcPorts && srcPoolers && (atoi(aval(srcPorts)[ii]) > 0) &&
|
|
(atoi(aval(srcPorts)[ii]) == atoi(aval(srcPoolers)[jj]))) ||
|
|
(srcPoolers && (atoi(aval(srcPoolers)[ii]) > 0) &&
|
|
(atoi(aval(srcPoolers)[ii]) == atoi(aval(srcPoolers)[jj])))) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in port and pooler numbers within %s variable.\n", srcNames);
|
|
}
|
|
/* Directories */
|
|
if (srcDirs && !doesExist(srcDirs, jj))
|
|
assign_arrayEl(srcDirs, jj, "none", NULL);
|
|
if (srcDirs && strcmp(aval(srcDirs)[ii], aval(srcDirs)[jj]) == 0) {
|
|
if (!is_none(aval(srcDirs)[ii])) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in directories within %s variable.\n", srcNames);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Check between src and destination */
|
|
if (destNames) {
|
|
for (ii = 0; aval(srcNames)[ii]; ii++) {
|
|
if (is_none(aval(srcNames)[ii]))
|
|
continue;
|
|
for (jj = 0; aval(destNames)[jj]; jj++) {
|
|
/* Resource names */
|
|
if (checkName && (strcmp(aval(srcNames)[ii], aval(destNames)[jj]) == 0)) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in names between %s and %s variable.\n", srcNames, destNames);
|
|
}
|
|
if (destServers && !doesExist(destServers, jj))
|
|
assign_arrayEl(destServers, jj, "none", NULL);
|
|
if (srcServers && destServers && (strcmp(aval(srcServers)[ii], aval(destServers)[jj]) == 0) &&
|
|
!is_none(aval(srcServers)[ii])) {
|
|
/* Ports and poolers */
|
|
if (destPorts && !doesExist(destPorts, jj))
|
|
assign_arrayEl(destPorts, jj, "-1", "-1");
|
|
if (destPoolers && !doesExist(destPoolers, jj))
|
|
assign_arrayEl(destPoolers, jj, "-1", "-1");
|
|
if ((srcPorts && destPorts && (atoi(aval(srcPorts)[ii]) == atoi(aval(destPorts)[jj])) &&
|
|
(atoi(aval(srcPorts)[ii]) > 0)) ||
|
|
(destPoolers && srcPorts &&
|
|
(destPoolers && (atoi(aval(srcPorts)[ii]) == atoi(aval(destPoolers)[jj]))) &&
|
|
(atoi(aval(srcPorts)[ii]) > 0)) ||
|
|
(srcPoolers && destPorts && (atoi(aval(srcPoolers)[ii]) == atoi(aval(destPorts)[jj])) &&
|
|
(atoi(aval(srcPoolers)[ii]) > 0)) ||
|
|
(srcPoolers && destPoolers && (atoi(aval(srcPoolers)[ii]) == atoi(aval(destPoolers)[jj])) &&
|
|
(atoi(aval(srcPoolers)[ii]) > 0))) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in port/pooler in %s and %s variable.\n", srcNames, destNames);
|
|
}
|
|
/* Dir Names */
|
|
if (srcDirs && destDirs && !is_none(aval(srcDirs)[ii]) &&
|
|
(strcmp(aval(srcDirs)[ii], aval(destDirs)[jj]) == 0)) {
|
|
anyConfigErrors = TRUE;
|
|
elog(ERROR, "ERROR: Conflict in directory names in %s and %s variable.\n", srcNames, destNames);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check if each node resource is configured properly
|
|
* Again, finding an error will not make the program stop.
|
|
*/
|
|
static void verifyResource(void)
|
|
{
|
|
char* GtmVars[] = {VAR_gtmName, VAR_gtmMasterServer, VAR_gtmMasterPort, VAR_gtmMasterDir, NULL};
|
|
char* GtmSlaveVars[] = {VAR_gtmSlaveServer, VAR_gtmSlavePort, VAR_gtmSlaveDir, NULL};
|
|
char* gtmProxyVars[] = {VAR_gtmProxyNames, VAR_gtmProxyServers, VAR_gtmProxyPorts, VAR_gtmProxyDirs, NULL};
|
|
char* coordMasterVars[] = {VAR_coordNames,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterServers,
|
|
VAR_coordMasterDirs,
|
|
VAR_coordMaxWALSenders,
|
|
NULL};
|
|
char* coordSlaveVars[] = {VAR_coordNames, VAR_coordSlaveServers, VAR_coordSlaveDirs, VAR_coordArchLogDirs, NULL};
|
|
char* datanodeMasterVars[] = {VAR_datanodeNames,
|
|
VAR_datanodePorts,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodeMasterDirs,
|
|
VAR_datanodeMaxWALSenders,
|
|
NULL};
|
|
char* datanodeSlaveVars[] = {
|
|
VAR_datanodeNames, VAR_datanodeSlaveServers, VAR_datanodeSlaveDirs, VAR_datanodeArchLogDirs, NULL};
|
|
|
|
/*
|
|
* -------------- Fundamental check -------------------
|
|
*/
|
|
anyConfigErrors = FALSE;
|
|
/* GTM */
|
|
checkIfConfigured(GtmVars);
|
|
/* GTM slave */
|
|
if (isVarYes(VAR_gtmSlave))
|
|
checkIfConfigured(GtmSlaveVars);
|
|
/* GTM proxy */
|
|
if (isVarYes(VAR_gtmProxy))
|
|
checkConfiguredAndSize(gtmProxyVars, "GTM Proxy");
|
|
/* Coordinator Master */
|
|
checkIfConfigured(coordMasterVars);
|
|
checkConfiguredAndSize(coordMasterVars, "coordinator master");
|
|
/* Coordinator Slave */
|
|
if (isVarYes(VAR_coordSlave)) {
|
|
checkConfiguredAndSize(coordSlaveVars, "coordinator slave");
|
|
}
|
|
/* Datanode Master */
|
|
checkConfiguredAndSize(datanodeMasterVars, "datanode master");
|
|
/* Datanode Slave */
|
|
if (sval(VAR_datanodeSlave) && strcmp(sval(VAR_datanodeSlave), "y") == 0) {
|
|
checkConfiguredAndSize(datanodeSlaveVars, "datanode slave");
|
|
}
|
|
if (anyConfigErrors)
|
|
elog(ERROR, "ERROR: Found fundamental configuration error.\n");
|
|
/*
|
|
* --------------- Resource Conflict Check ---------------------
|
|
*/
|
|
/*
|
|
* GTM Master and others ----------------
|
|
*/
|
|
anyConfigErrors = FALSE;
|
|
/* GTM and GTM slave */
|
|
if (isVarYes(VAR_gtmSlave))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmMasterServer,
|
|
VAR_gtmMasterPort,
|
|
NULL,
|
|
VAR_gtmMasterDir,
|
|
VAR_gtmName,
|
|
VAR_gtmSlaveServer,
|
|
VAR_gtmSlavePort,
|
|
NULL,
|
|
VAR_gtmSlaveDir,
|
|
TRUE,
|
|
FALSE);
|
|
/* GTM and GTM Proxy, if any */
|
|
if (isVarYes(VAR_gtmProxy))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmMasterServer,
|
|
VAR_gtmMasterPort,
|
|
NULL,
|
|
VAR_gtmMasterDir,
|
|
VAR_gtmProxyNames,
|
|
VAR_gtmProxyServers,
|
|
VAR_gtmProxyPorts,
|
|
NULL,
|
|
VAR_gtmProxyDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM and coordinator masters */
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmMasterServer,
|
|
VAR_gtmMasterPort,
|
|
NULL,
|
|
VAR_gtmMasterDir,
|
|
VAR_coordNames,
|
|
VAR_coordMasterServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM and coordinator slaves, if any */
|
|
if (isVarYes(VAR_coordSlave))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmMasterServer,
|
|
VAR_gtmMasterPort,
|
|
NULL,
|
|
VAR_gtmMasterDir,
|
|
VAR_coordNames,
|
|
VAR_coordSlaveServers,
|
|
VAR_coordPorts,
|
|
NULL,
|
|
VAR_coordSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM and datanode masters */
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmMasterServer,
|
|
VAR_gtmMasterPort,
|
|
NULL,
|
|
VAR_gtmMasterDir,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeMasterDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM and datanode slaves, if any */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmMasterServer,
|
|
VAR_gtmMasterPort,
|
|
NULL,
|
|
VAR_gtmMasterDir,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/*
|
|
* GTM slave and others ------------
|
|
*/
|
|
if (isVarYes(VAR_gtmSlave)) {
|
|
/* GTM slave and GTM Proxy, if any */
|
|
if (isVarYes(VAR_gtmProxy))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmSlaveServer,
|
|
VAR_gtmSlavePort,
|
|
NULL,
|
|
VAR_gtmSlaveDir,
|
|
VAR_gtmProxyNames,
|
|
VAR_gtmProxyServers,
|
|
VAR_gtmProxyPorts,
|
|
NULL,
|
|
VAR_gtmProxyDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM slave and coordinator masters */
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmSlaveServer,
|
|
VAR_gtmSlavePort,
|
|
NULL,
|
|
VAR_gtmSlaveDir,
|
|
VAR_coordNames,
|
|
VAR_coordMasterServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM slave and coordinator slaves, if any */
|
|
if (isVarYes(VAR_coordSlave))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmSlaveServer,
|
|
VAR_gtmSlavePort,
|
|
NULL,
|
|
VAR_gtmSlaveDir,
|
|
VAR_coordNames,
|
|
VAR_coordSlaveServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM slave and datanode masters */
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmSlaveServer,
|
|
VAR_gtmSlavePort,
|
|
NULL,
|
|
VAR_gtmSlaveDir,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeMasterDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM slave and datanode slave, if any */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
checkResourceConflict(VAR_gtmName,
|
|
VAR_gtmSlaveServer,
|
|
VAR_gtmSlavePort,
|
|
NULL,
|
|
VAR_gtmSlaveDir,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeSlaveServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
}
|
|
/*
|
|
* GTM proxy and others ---------
|
|
*/
|
|
if (isVarYes(VAR_gtmProxy)) {
|
|
/* GTM proxy and coordinator masters */
|
|
checkResourceConflict(VAR_gtmProxyNames,
|
|
VAR_gtmProxyServers,
|
|
VAR_gtmProxyPorts,
|
|
NULL,
|
|
VAR_gtmProxyDirs,
|
|
VAR_coordNames,
|
|
VAR_coordMasterServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterDirs,
|
|
FALSE,
|
|
TRUE);
|
|
/* GTM proxy and coordinator slaves, if any */
|
|
if (sval(VAR_coordSlave) && (strcmp(sval(VAR_coordSlave), "y") == 0))
|
|
checkResourceConflict(VAR_gtmProxyNames,
|
|
VAR_gtmProxyServers,
|
|
VAR_gtmProxyPorts,
|
|
NULL,
|
|
VAR_gtmProxyDirs,
|
|
VAR_coordNames,
|
|
VAR_coordSlaveServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM proxy and datanode masters */
|
|
checkResourceConflict(VAR_gtmProxyNames,
|
|
VAR_gtmProxyServers,
|
|
VAR_gtmProxyPorts,
|
|
NULL,
|
|
VAR_gtmProxyDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeMasterDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/* GTM proxy and datanode slave, if any */
|
|
if (sval(VAR_datanodeSlave) && (strcmp(sval(VAR_datanodeSlave), "y") == 0))
|
|
checkResourceConflict(VAR_gtmProxyNames,
|
|
VAR_gtmProxyServers,
|
|
VAR_gtmProxyPorts,
|
|
NULL,
|
|
VAR_gtmProxyDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeSlaveServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
}
|
|
/*
|
|
* Coordinator Masters and others
|
|
*/
|
|
/* Coordinator master and coordinator slaves, if any */
|
|
if (isVarYes(VAR_coordSlave))
|
|
checkResourceConflict(VAR_coordNames,
|
|
VAR_coordMasterServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterDirs,
|
|
VAR_coordNames,
|
|
VAR_coordSlaveServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordSlaveDirs,
|
|
TRUE,
|
|
FALSE);
|
|
/* Coordinator masters and datanode masters */
|
|
checkResourceConflict(VAR_coordNames,
|
|
VAR_coordMasterServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeMasterDirs,
|
|
FALSE,
|
|
TRUE);
|
|
/* Coordinator masters and datanode slave, if any */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
checkResourceConflict(VAR_coordNames,
|
|
VAR_coordMasterServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordMasterDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeSlaveServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
/*
|
|
* Coordinator slaves and others
|
|
*/
|
|
if (isVarYes(VAR_coordSlave)) {
|
|
/* Coordinator slave and datanode masters */
|
|
checkResourceConflict(VAR_coordNames,
|
|
VAR_coordSlaveServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordSlaveDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeSlaveServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
FALSE,
|
|
TRUE);
|
|
/* Coordinator slave and datanode slave, if any */
|
|
if (isVarYes(VAR_datanodeSlave))
|
|
checkResourceConflict(VAR_coordNames,
|
|
VAR_coordSlaveServers,
|
|
VAR_coordPorts,
|
|
VAR_poolerPorts,
|
|
VAR_coordSlaveDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeSlaveServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
TRUE,
|
|
TRUE);
|
|
}
|
|
/*
|
|
* Datanode masters and others ---
|
|
*/
|
|
/* Datanode master self */
|
|
checkResourceConflict(VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeMasterDirs,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
TRUE);
|
|
/* Datanode master and datanode slave, if any */
|
|
if (sval(VAR_datanodeSlave) && (strcmp(sval(VAR_datanodeSlave), "y") == 0))
|
|
checkResourceConflict(VAR_datanodeNames,
|
|
VAR_datanodeMasterServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeMasterDirs,
|
|
VAR_datanodeNames,
|
|
VAR_datanodeSlaveServers,
|
|
VAR_datanodePorts,
|
|
NULL,
|
|
VAR_datanodeSlaveDirs,
|
|
TRUE,
|
|
FALSE);
|
|
if (anyConfigErrors) {
|
|
elog(ERROR, "ERROR: Found conflicts among resources. Exiting.\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check if the minimum components are configured --- gtm master, coordinator master and datanode master.
|
|
*/
|
|
void check_configuration(void)
|
|
{
|
|
/*
|
|
* See if mandatory configuration is defined. Will continue if error is detected
|
|
* to check all the errors at a time.
|
|
*/
|
|
/* GTM Master */
|
|
if (!find_var(VAR_gtmName) || !find_var(VAR_gtmMasterServer) || !find_var(VAR_gtmMasterPort) ||
|
|
!find_var(VAR_gtmMasterDir))
|
|
elog(ERROR,
|
|
"ERROR: GTM master configuration is missing. gtmName, gtmMasterServer, gtmMasterPort or gtmMasterDir\n");
|
|
/* Coordinator Master */
|
|
if (!find_var(VAR_coordNames) || !find_var(VAR_coordPorts) || !find_var(VAR_poolerPorts) ||
|
|
!find_var(VAR_coordMasterServers) || !find_var(VAR_coordMasterDirs))
|
|
elog(ERROR,
|
|
"ERROR: Coordinator master configuration is missing. coordNames, coodPorts, poolerPorts, coordMasterPorts "
|
|
"or coordMasterDirs\n");
|
|
/* Datanode Master */
|
|
if (!find_var(VAR_datanodeNames) || !find_var(VAR_datanodePorts) || !find_var(VAR_datanodeMasterServers) ||
|
|
!find_var(VAR_datanodeMasterDirs))
|
|
elog(ERROR,
|
|
"ERROR: Datanode master configuration is missing. datanodeNames, datanodePorts, datanodeMasterPorts or "
|
|
"datanodeMasterDirs\n");
|
|
handle_no_slaves();
|
|
verifyResource();
|
|
makeServerList();
|
|
}
|
|
|
|
/*
|
|
* Backup configuration files to a remote site as specified.
|
|
*/
|
|
int backup_configuration(void)
|
|
{
|
|
if ((strcasecmp(sval(VAR_configBackup), "y") != 0) || is_none(sval(VAR_configBackupHost)) ||
|
|
is_none(sval(VAR_configBackupDir)) || is_none(sval(VAR_configBackupFile)))
|
|
return (2);
|
|
return (doImmediate(NULL,
|
|
NULL,
|
|
"scp %s %s@%s:%s/%s",
|
|
pgxc_ctl_config_path,
|
|
sval(VAR_pgxcUser),
|
|
sval(VAR_configBackupHost),
|
|
sval(VAR_configBackupDir),
|
|
sval(VAR_configBackupFile)));
|
|
}
|
|
|
|
NodeType getNodeType(char* nodeName)
|
|
{
|
|
int ii;
|
|
|
|
/* Check GTM */
|
|
if (strcmp(nodeName, sval(VAR_gtmName)) == 0)
|
|
return NodeType_GTM;
|
|
/* GTM_Proxy */
|
|
for (ii = 0; aval(VAR_gtmProxyNames)[ii]; ii++)
|
|
if (strcmp(nodeName, aval(VAR_gtmProxyNames)[ii]) == 0)
|
|
return NodeType_GTM_PROXY;
|
|
/* Coordinator */
|
|
for (ii = 0; aval(VAR_coordNames)[ii]; ii++)
|
|
if (strcmp(nodeName, aval(VAR_coordNames)[ii]) == 0)
|
|
return NodeType_COORDINATOR;
|
|
/* Datanode */
|
|
for (ii = 0; aval(VAR_datanodeNames)[ii]; ii++)
|
|
if (strcmp(nodeName, aval(VAR_datanodeNames)[ii]) == 0)
|
|
return NodeType_DATANODE;
|
|
/* Nodename */
|
|
for (ii = 0; aval(VAR_allServers)[ii]; ii++)
|
|
if (strcmp(nodeName, aval(VAR_allServers)[ii]) == 0)
|
|
return NodeType_SERVER;
|
|
return NodeType_UNDEF;
|
|
}
|
|
|
|
int getDefaultWalSender(int isCoord)
|
|
{
|
|
int ii;
|
|
|
|
char* names = (char*)(isCoord ? VAR_coordNames : VAR_datanodeNames);
|
|
char* walSender = (char*)(isCoord ? VAR_coordMaxWALSenders : VAR_datanodeMaxWALSenders);
|
|
|
|
for (ii = 0; aval(names)[ii]; ii++) {
|
|
if (doesExist(names, ii) && !is_none(aval(names)[ii]) && (atoi(aval(walSender)[ii]) >= 0))
|
|
return atoi(aval(walSender)[ii]);
|
|
}
|
|
return 0;
|
|
}
|