1384 lines
41 KiB
C++
1384 lines
41 KiB
C++
/*-------------------------------------------------------------------------
|
|
*
|
|
* gtm_cmd.c
|
|
*
|
|
* GTM command module of Postgres-XC configuration and operation tool.
|
|
*
|
|
* Copyright (c) 2013 Postgres-XC Development Group
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
/*
|
|
* This module provides various gtm-related pgxc_operation.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <setjmp.h>
|
|
#include <string.h>
|
|
#include <readline/readline.h>
|
|
#include <readline/history.h>
|
|
|
|
#include "pgxc_ctl.h"
|
|
#include "do_command.h"
|
|
#include "variables.h"
|
|
#include "varnames.h"
|
|
#include "pgxc_ctl_log.h"
|
|
#include "config.h"
|
|
#include "do_shell.h"
|
|
#include "utils.h"
|
|
#include "gtm_cmd.h"
|
|
#include "monitor.h"
|
|
|
|
static char date[MAXTOKEN + 1];
|
|
|
|
/* ======================================================================================
|
|
*
|
|
* GTM Staff
|
|
*
|
|
* =======================================================================================
|
|
*/
|
|
/*
|
|
* Init gtm master -----------------------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_initGtmMaster(void)
|
|
{
|
|
cmd_t *cmdInitGtmMaster, *cmdGtmConf, *cmdGxid;
|
|
char date[MAXTOKEN + 1];
|
|
FILE* f = NULL;
|
|
char** fileList = NULL;
|
|
|
|
/* Kill current gtm, bild work directory and run initgtm */
|
|
cmdInitGtmMaster = initCmd(sval(VAR_gtmMasterServer));
|
|
snprintf(newCommand(cmdInitGtmMaster),
|
|
MAXLINE,
|
|
"killall -u %s -9 gs_gtm; rm -rf %s; mkdir -p %s;gs_initgtm -Z gtm -D %s",
|
|
sval(VAR_pgxcUser),
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir));
|
|
|
|
/* Then prepare gtm.conf file */
|
|
|
|
/* Prepare local Stdin */
|
|
appendCmdEl(cmdInitGtmMaster, (cmdGtmConf = initCmd(sval(VAR_gtmMasterServer))));
|
|
if ((f = prepareLocalStdin(newFilename(cmdGtmConf->localStdin), MAXPATH, NULL)) == NULL) {
|
|
cleanCmd(cmdInitGtmMaster);
|
|
return (NULL);
|
|
}
|
|
fprintf(f,
|
|
"#===============================================\n"
|
|
"# Added at initialization, %s\n"
|
|
"listen_addresses = '*'\n",
|
|
timeStampString(date, MAXTOKEN));
|
|
if (!is_none(sval(VAR_gtmExtraConfig)))
|
|
AddMember(fileList, sval(VAR_gtmExtraConfig));
|
|
if (!is_none(sval(VAR_gtmMasterSpecificExtraConfig)))
|
|
AddMember(fileList, sval(VAR_gtmMasterSpecificExtraConfig));
|
|
appendFiles(f, fileList);
|
|
CleanArray(fileList);
|
|
fprintf(f,
|
|
"port = %s\n"
|
|
"nodename = '%s'\n"
|
|
"startup = ACT\n"
|
|
"# End of addition\n",
|
|
sval(VAR_gtmMasterPort),
|
|
sval(VAR_gtmName));
|
|
fclose(f);
|
|
/* other options */
|
|
snprintf(newCommand(cmdGtmConf), MAXLINE, "cat >> %s/gtm.conf", sval(VAR_gtmMasterDir));
|
|
|
|
/* Setup GTM with appropriate GXID value */
|
|
|
|
appendCmdEl(cmdGtmConf, (cmdGxid = initCmd(sval(VAR_gtmMasterServer))));
|
|
snprintf(newCommand(cmdGxid),
|
|
MAXLINE,
|
|
"(gs_gtm -x 2000 -D %s &); sleep 1; gtm_ctl stop -Z gtm -D %s",
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir));
|
|
|
|
return cmdInitGtmMaster;
|
|
}
|
|
int init_gtm_master(void)
|
|
{
|
|
int rc;
|
|
cmdList_t* cmdList = NULL;
|
|
|
|
elog(INFO, "Initialize GTM master\n");
|
|
cmdList = initCmdList();
|
|
|
|
/* Kill current gtm, build work directory and run initgtm */
|
|
|
|
addCmd(cmdList, prepare_initGtmMaster());
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
elog(INFO, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
/*
|
|
* Add gtm slave: to be used after all the configuration is done.
|
|
*
|
|
* This function only maintains internal configuration, updte configuration file,
|
|
* and make backup if configured. You should run init_gtm_slave and stat_gtm_slave
|
|
* separately.
|
|
*/
|
|
int add_gtmSlave(char* name, char* host, int port, char* dir)
|
|
{
|
|
char port_s[MAXTOKEN + 1];
|
|
char date[MAXTOKEN + 1];
|
|
FILE* f = NULL;
|
|
int rc;
|
|
|
|
if (isVarYes(VAR_gtmSlave)) {
|
|
elog(ERROR, "ERROR: GTM slave is already configured.\n");
|
|
return 1;
|
|
}
|
|
if (is_none(host)) {
|
|
elog(ERROR, "ERROR: Cannot add gtm slave with the name \"none\".\n");
|
|
return 1;
|
|
}
|
|
if (is_none(dir)) {
|
|
elog(ERROR, "ERROR: Cannot add gtm slave with the directory \"none\".\n");
|
|
return 1;
|
|
}
|
|
if (checkSpecificResourceConflict(name, host, port, dir, TRUE)) {
|
|
elog(ERROR,
|
|
"ERROR: New specified name:%s, host:%s, port:%d and dir:\"%s\" conflicts with existing node.\n",
|
|
name,
|
|
host,
|
|
port,
|
|
dir);
|
|
return 1;
|
|
}
|
|
assign_sval(VAR_gtmSlave, Strdup("y"));
|
|
assign_sval(VAR_gtmSlaveServer, Strdup(host));
|
|
snprintf(port_s, MAXTOKEN, "%d", port);
|
|
assign_sval(VAR_gtmSlavePort, Strdup(port_s));
|
|
assign_sval(VAR_gtmSlaveDir, Strdup(dir));
|
|
makeServerList();
|
|
if ((f = fopen(pgxc_ctl_config_path, "a")) == NULL) {
|
|
/* Should it be panic? */
|
|
elog(ERROR, "ERROR: cannot open configuration file \"%s\", %s\n", pgxc_ctl_config_path, strerror(errno));
|
|
return 1;
|
|
}
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# pgxc configuration file updated due to GTM slave addition\n"
|
|
"# %s\n",
|
|
timeStampString(date, MAXTOKEN + 1));
|
|
fprintSval(f, VAR_gtmSlave);
|
|
fprintSval(f, VAR_gtmSlaveServer);
|
|
fprintSval(f, VAR_gtmSlavePort);
|
|
fprintSval(f, VAR_gtmSlaveDir);
|
|
fprintf(f, "%s", "#----End of reconfiguration -------------------------\n");
|
|
fclose(f);
|
|
backup_configuration();
|
|
if ((rc = init_gtm_slave()) != 0)
|
|
return rc;
|
|
return (start_gtm_slave());
|
|
}
|
|
|
|
int remove_gtmSlave(bool clean_opt)
|
|
{
|
|
FILE* f = NULL;
|
|
|
|
/* Check if gtm_slave is configured */
|
|
if (!isVarYes(VAR_gtmSlave) || !sval(VAR_gtmSlaveServer) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
elog(ERROR, "ERROR: GTM slave is not configured.\n");
|
|
return 1;
|
|
}
|
|
/* Check if gtm_slave is not running */
|
|
if (!do_gtm_ping(sval(VAR_gtmSlaveServer), atoi(sval(VAR_gtmSlavePort)))) {
|
|
elog(ERROR, "ERROR: GTM slave is now running. Cannot remove it.\n");
|
|
return 1;
|
|
}
|
|
elog(NOTICE, "Removing gtm slave.\n");
|
|
/* Clean */
|
|
if (clean_opt)
|
|
clean_gtm_slave();
|
|
/* Reconfigure */
|
|
reset_var(VAR_gtmSlave);
|
|
assign_sval(VAR_gtmSlave, Strdup("n"));
|
|
reset_var(VAR_gtmSlaveServer);
|
|
assign_sval(VAR_gtmSlaveServer, Strdup("none"));
|
|
reset_var(VAR_gtmSlavePort);
|
|
assign_sval(VAR_gtmSlavePort, Strdup("-1"));
|
|
reset_var(VAR_gtmSlaveDir);
|
|
assign_sval(VAR_gtmSlaveDir, Strdup("none"));
|
|
/* Write the configuration file and bakup it */
|
|
if ((f = fopen(pgxc_ctl_config_path, "a")) == NULL) {
|
|
/* Should it be panic? */
|
|
elog(ERROR, "ERROR: cannot open configuration file \"%s\", %s\n", pgxc_ctl_config_path, strerror(errno));
|
|
return 1;
|
|
}
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# pgxc configuration file updated due to GTM slave removal\n"
|
|
"# %s\n",
|
|
timeStampString(date, MAXTOKEN + 1));
|
|
fprintSval(f, VAR_gtmSlave);
|
|
fprintSval(f, VAR_gtmSlaveServer);
|
|
fprintSval(f, VAR_gtmSlavePort);
|
|
fprintSval(f, VAR_gtmSlaveDir);
|
|
fprintf(f, "%s", "#----End of reconfiguration -------------------------\n");
|
|
fclose(f);
|
|
backup_configuration();
|
|
elog(NOTICE, "Done.\n");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Init gtm slave -------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
* Assumes Gtm Slave is configured.
|
|
* Caller should check this.
|
|
*/
|
|
cmd_t* prepare_initGtmSlave(void)
|
|
{
|
|
char date[MAXTOKEN + 1];
|
|
cmd_t *cmdInitGtm, *cmdGtmConf;
|
|
FILE* f = NULL;
|
|
char** fileList = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmSlave) || (sval(VAR_gtmSlaveServer) == NULL) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
elog(ERROR, "ERROR: GTM slave is not configured.\n");
|
|
return (NULL);
|
|
}
|
|
/* Kill current gtm, build work directory and run initgtm */
|
|
cmdInitGtm = initCmd(sval(VAR_gtmSlaveServer));
|
|
snprintf(newCommand(cmdInitGtm),
|
|
MAXLINE,
|
|
"killall -u %s -9 gs_gtm; rm -rf %s; mkdir -p %s; gs_initgtm -Z gtm -D %s",
|
|
sval(VAR_pgxcUser),
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmSlaveDir));
|
|
|
|
/* Prepare gtm.conf file */
|
|
|
|
/* Prepare local Stdin */
|
|
appendCmdEl(cmdInitGtm, (cmdGtmConf = initCmd(sval(VAR_gtmSlaveServer))));
|
|
snprintf(newCommand(cmdGtmConf), MAXLINE, "cat >> %s/gtm.conf", sval(VAR_gtmSlaveDir));
|
|
if ((f = prepareLocalStdin(newFilename(cmdGtmConf->localStdin), MAXPATH, NULL)) == NULL) {
|
|
cleanCmd(cmdInitGtm);
|
|
return (NULL);
|
|
}
|
|
fprintf(f,
|
|
"#===============================================\n"
|
|
"# Added at initialization, %s\n"
|
|
"listen_addresses = '*'\n",
|
|
timeStampString(date, MAXPATH + 1));
|
|
if (!is_none(sval(VAR_gtmExtraConfig)))
|
|
AddMember(fileList, sval(VAR_gtmExtraConfig));
|
|
if (!is_none(sval(VAR_gtmMasterSpecificExtraConfig)))
|
|
AddMember(fileList, sval(VAR_gtmMasterSpecificExtraConfig));
|
|
appendFiles(f, fileList);
|
|
CleanArray(fileList);
|
|
fprintf(f,
|
|
"port = %s\n"
|
|
"nodename = '%s'\n"
|
|
"startup = STANDBY\n"
|
|
"active_host = '%s'\n"
|
|
"active_port = %d\n"
|
|
"# End of addition\n",
|
|
sval(VAR_gtmSlavePort),
|
|
sval(VAR_gtmName),
|
|
sval(VAR_gtmMasterServer),
|
|
atoi(sval(VAR_gtmMasterPort)));
|
|
fclose(f);
|
|
return (cmdInitGtm);
|
|
}
|
|
|
|
int init_gtm_slave(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmdInitGtm = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Initialize GTM slave\n");
|
|
cmdList = initCmdList();
|
|
if ((cmdInitGtm = prepare_initGtmSlave())) {
|
|
addCmd(cmdList, cmdInitGtm);
|
|
/* Do all the commands and clean */
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
elog(INFO, "Done.\n");
|
|
return (rc);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Start gtm master -----------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_startGtmMaster(void)
|
|
{
|
|
cmd_t* cmdGtmCtl = NULL;
|
|
|
|
cmdGtmCtl = initCmd(sval(VAR_gtmMasterServer));
|
|
snprintf(newCommand(cmdGtmCtl),
|
|
MAXLINE,
|
|
"gtm_ctl stop -Z gtm -D %s;"
|
|
"rm -f %s/register.node;"
|
|
"gtm_ctl start -Z gtm -D %s",
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir));
|
|
return cmdGtmCtl;
|
|
}
|
|
|
|
int start_gtm_master(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Start GTM master\n");
|
|
cmdList = initCmdList();
|
|
addCmd(cmdList, prepare_startGtmMaster());
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
return (rc);
|
|
}
|
|
|
|
/*
|
|
* Start gtm slave ----------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_startGtmSlave(void)
|
|
{
|
|
cmd_t* cmdGtmCtl = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmSlave) || (sval(VAR_gtmSlaveServer) == NULL) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
elog(ERROR, "ERROR: GTM slave is not configured.\n");
|
|
return (NULL);
|
|
}
|
|
cmdGtmCtl = initCmd(sval(VAR_gtmSlaveServer));
|
|
snprintf(newCommand(cmdGtmCtl),
|
|
MAXLINE,
|
|
"gtm_ctl stop -Z gtm -D %s;"
|
|
"rm -rf %s/register.node;"
|
|
"gtm_ctl start -Z gtm -D %s",
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmSlaveDir));
|
|
return (cmdGtmCtl);
|
|
}
|
|
|
|
int start_gtm_slave(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmd = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Start GTM slave");
|
|
cmdList = initCmdList();
|
|
if ((cmd = prepare_startGtmSlave())) {
|
|
addCmd(cmdList, cmd);
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
elog(INFO, "Done.\n");
|
|
return (rc);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Stop gtm master ---------------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_stopGtmMaster(void)
|
|
{
|
|
cmd_t* cmdGtmCtl = NULL;
|
|
|
|
cmdGtmCtl = initCmd(sval(VAR_gtmMasterServer));
|
|
snprintf(newCommand(cmdGtmCtl), MAXLINE, "gtm_ctl stop -Z gtm -D %s", sval(VAR_gtmMasterDir));
|
|
return (cmdGtmCtl);
|
|
}
|
|
|
|
int stop_gtm_master(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Stop GTM master\n");
|
|
cmdList = initCmdList();
|
|
addCmd(cmdList, prepare_stopGtmMaster());
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
return (rc);
|
|
}
|
|
|
|
/*
|
|
* Stop gtm slave ---------------------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_stopGtmSlave(void)
|
|
{
|
|
cmd_t* cmdGtmCtl = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmSlave) || (sval(VAR_gtmSlaveServer) == NULL) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
elog(ERROR, "ERROR: GTM slave is not configured.\n");
|
|
return (NULL);
|
|
}
|
|
cmdGtmCtl = initCmd(sval(VAR_gtmSlaveServer));
|
|
snprintf(newCommand(cmdGtmCtl), MAXLINE, "gtm_ctl stop -Z gtm -D %s", sval(VAR_gtmSlaveDir));
|
|
return (cmdGtmCtl);
|
|
}
|
|
|
|
int stop_gtm_slave(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmd = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Stop GTM slave\n");
|
|
cmdList = initCmdList();
|
|
if ((cmd = prepare_stopGtmSlave())) {
|
|
addCmd(cmdList, cmd);
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
return (rc);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Kill gtm master -----------------------------------------------------
|
|
*
|
|
* You should not kill gtm master in this way. This may discard the latest
|
|
* gtm status. This is just in case. You must try to stop gtm master
|
|
* gracefully.
|
|
*/
|
|
cmd_t* prepare_killGtmMaster(void)
|
|
{
|
|
cmd_t* cmdKill = NULL;
|
|
pid_t gtmPid;
|
|
|
|
cmdKill = initCmd(sval(VAR_gtmMasterServer));
|
|
gtmPid = get_gtm_pid(sval(VAR_gtmMasterServer), sval(VAR_gtmMasterDir));
|
|
if (gtmPid > 0)
|
|
snprintf(newCommand(cmdKill),
|
|
MAXLINE,
|
|
"kill -9 %d; rm -rf /tmp/.s.'*'%d'*' %s/gtm.pid",
|
|
gtmPid,
|
|
atoi(sval(VAR_gtmMasterPort)),
|
|
sval(VAR_gtmMasterDir));
|
|
else
|
|
snprintf(newCommand(cmdKill),
|
|
MAXLINE,
|
|
"killall -u %s -9 gs_gtm; rm -rf /tmp/.s.'*'%d'*' %s/gtm.pid",
|
|
sval(VAR_pgxcUser),
|
|
atoi(sval(VAR_gtmMasterPort)),
|
|
sval(VAR_gtmMasterDir));
|
|
return (cmdKill);
|
|
}
|
|
|
|
int kill_gtm_master(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmd_killGtmMaster = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Kill GTM master\n");
|
|
cmdList = initCmdList();
|
|
if ((cmd_killGtmMaster = prepare_killGtmMaster())) {
|
|
addCmd(cmdList, cmd_killGtmMaster);
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
return (rc);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Kill gtm slave --------------------------------------------------------
|
|
*
|
|
* GTM slave has no significant informaion to carry over. But it is a good
|
|
* habit to stop gtm slave gracefully with stop command.
|
|
*/
|
|
cmd_t* prepare_killGtmSlave(void)
|
|
{
|
|
cmd_t* cmdKill = NULL;
|
|
pid_t gtmPid;
|
|
|
|
if (!isVarYes(VAR_gtmSlave) || (sval(VAR_gtmSlaveServer) == NULL) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
elog(ERROR, "ERROR: GTM slave is not configured.\n");
|
|
return (NULL);
|
|
}
|
|
cmdKill = initCmd(sval(VAR_gtmSlaveServer));
|
|
gtmPid = get_gtm_pid(sval(VAR_gtmSlaveServer), sval(VAR_gtmSlaveDir));
|
|
if (gtmPid > 0)
|
|
snprintf(newCommand(cmdKill),
|
|
MAXLINE,
|
|
"kill -9 %d; rm -rf /tmp/.s.'*'%d'*' %s/gtm.pid",
|
|
gtmPid,
|
|
atoi(sval(VAR_gtmSlavePort)),
|
|
sval(VAR_gtmSlaveDir));
|
|
else
|
|
snprintf(newCommand(cmdKill),
|
|
MAXLINE,
|
|
"killall -u %s -9 gs_gtm; rm -rf /tmp/.s.'*'%d'*' %s/gtm.pid",
|
|
sval(VAR_pgxcUser),
|
|
atoi(sval(VAR_gtmSlavePort)),
|
|
sval(VAR_gtmSlaveDir));
|
|
return (cmdKill);
|
|
}
|
|
|
|
int kill_gtm_slave(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmdKill = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Kill GTM slave\n");
|
|
cmdList = initCmdList();
|
|
if ((cmdKill = prepare_killGtmSlave())) {
|
|
addCmd(cmdList, cmdKill);
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
return (rc);
|
|
} else
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Failover the gtm ------------------------------------------------------
|
|
*/
|
|
int failover_gtm(void)
|
|
{
|
|
char date[MAXTOKEN + 1];
|
|
char* stdIn = NULL;
|
|
int rc;
|
|
FILE* f = NULL;
|
|
|
|
elog(INFO, "Failover gtm\n");
|
|
if (!isVarYes(VAR_gtmSlave) || (sval(VAR_gtmSlaveServer) == NULL) || is_none(sval(VAR_gtmSlaveServer))) {
|
|
elog(ERROR, "ERROR: GTM slave is not configured. Cannot failover.\n");
|
|
return (1);
|
|
}
|
|
|
|
if (do_gtm_ping(sval(VAR_gtmSlaveServer), atoi(sval(VAR_gtmSlavePort))) != 0) {
|
|
elog(ERROR, "ERROR: GTM slave is not running\n");
|
|
return (1);
|
|
}
|
|
|
|
/* Promote the slave */
|
|
elog(NOTICE, "Running \"gtm_ctl promote -Z gtm -D %s\"\n", sval(VAR_gtmSlaveDir));
|
|
rc = doImmediate(sval(VAR_gtmSlaveServer), NULL, "gtm_ctl promote -Z gtm -D %s", sval(VAR_gtmSlaveDir));
|
|
if (WEXITSTATUS(rc) != 0) {
|
|
elog(
|
|
ERROR, "ERROR: could not promote gtm (host:%s, dir:%s)\n", sval(VAR_gtmSlaveServer), sval(VAR_gtmSlaveDir));
|
|
return 1;
|
|
}
|
|
|
|
/* Configure promoted gtm */
|
|
if ((f = prepareLocalStdin(newFilename(stdIn), MAXPATH, NULL)) == NULL)
|
|
return (1);
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# Updated due to GTM failover\n"
|
|
"# %s\n"
|
|
"startup = ACT\n"
|
|
"#----End of reconfiguration -------------------------\n",
|
|
timeStampString(date, MAXTOKEN + 1));
|
|
fclose(f);
|
|
elog(NOTICE, "Updating gtm.conf at %s:%s\n", sval(VAR_gtmSlaveServer), sval(VAR_gtmSlaveDir));
|
|
rc = doImmediate(sval(VAR_gtmSlaveServer), stdIn, "cat >> %s/gtm.conf", sval(VAR_gtmSlaveDir));
|
|
if (WEXITSTATUS(rc) != 0) {
|
|
elog(ERROR,
|
|
"ERROR: could not update gtm.conf (host: %s, dir:%s)\n",
|
|
sval(VAR_gtmSlaveServer),
|
|
sval(VAR_gtmSlaveDir));
|
|
return 1;
|
|
}
|
|
|
|
/* Update and backup configuration file */
|
|
if ((f = prepareLocalStdin(stdIn, MAXPATH, NULL)) == NULL)
|
|
return (1);
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# pgxc configuration file updated due to GTM failover\n"
|
|
"# %s\n"
|
|
"gtmMasterServer=%s\n"
|
|
"gtmMasterPort=%s\n"
|
|
"gtmMasterDir=%s\n"
|
|
"gtmSlave=n\n"
|
|
"gtmSlaveServer=none\n"
|
|
"gtmSlavePort=0\n"
|
|
"gtmSlaveDir=none\n"
|
|
"#----End of reconfiguration -------------------------\n",
|
|
timeStampString(date, MAXTOKEN + 1),
|
|
sval(VAR_gtmSlaveServer),
|
|
sval(VAR_gtmSlavePort),
|
|
sval(VAR_gtmSlaveDir));
|
|
fclose(f);
|
|
rc = doImmediate(NULL, stdIn, "cat >> %s", pgxc_ctl_config_path);
|
|
if (WEXITSTATUS(rc) != 0) {
|
|
elog(ERROR,
|
|
"ERROR: could not update gtm.conf (host: %s, dir:%s)\n",
|
|
sval(VAR_gtmSlaveServer),
|
|
sval(VAR_gtmSlaveDir));
|
|
return 1;
|
|
}
|
|
freeAndReset(stdIn);
|
|
backup_configuration();
|
|
|
|
/* Reconfigure myself */
|
|
assign_val(VAR_gtmMasterServer, VAR_gtmSlaveServer);
|
|
reset_var(VAR_gtmSlaveServer);
|
|
assign_val(VAR_gtmMasterPort, VAR_gtmSlavePort);
|
|
reset_var(VAR_gtmSlavePort);
|
|
assign_val(VAR_gtmMasterDir, VAR_gtmSlaveDir);
|
|
reset_var(VAR_gtmSlaveDir);
|
|
assign_sval(VAR_gtmSlaveServer, "none");
|
|
assign_sval(VAR_gtmSlavePort, "0");
|
|
assign_sval(VAR_gtmSlaveDir, "none");
|
|
assign_sval(VAR_gtmSlave, "n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Clean gtm master resources -- directory and socket --------------------------
|
|
*/
|
|
cmd_t* prepare_cleanGtmMaster(void)
|
|
{
|
|
cmd_t* cmd = NULL;
|
|
|
|
/* Remote work dir and clean the socket */
|
|
cmd = initCmd(sval(VAR_gtmMasterServer));
|
|
snprintf(newCommand(cmd),
|
|
MAXLINE,
|
|
"rm -rf %s; mkdir -p %s; chmod 0700 %s;rm -f /tmp/.s.*%d*",
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmMasterDir),
|
|
atoi(VAR_gtmMasterPort));
|
|
return cmd;
|
|
}
|
|
|
|
int clean_gtm_master(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
int rc;
|
|
|
|
elog(INFO, "Clearing gtm master directory and socket.\n");
|
|
cmdList = initCmdList();
|
|
addCmd(cmdList, prepare_cleanGtmMaster());
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
return (rc);
|
|
}
|
|
|
|
/*
|
|
* Clean gtm master resources -- direcotry and socket --------------------------
|
|
*/
|
|
/*
|
|
* Null will be retruend if gtm slave is not configured.
|
|
* Be careful. If you configure gtm slave and gtm master on a same server,
|
|
* bott slave amd master process will be killed.
|
|
*/
|
|
cmd_t* prepare_cleanGtmSlave(void)
|
|
{
|
|
cmd_t* cmd = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmSlave) || is_none(VAR_gtmSlaveServer))
|
|
return (NULL);
|
|
cmd = initCmd(sval(VAR_gtmSlaveServer));
|
|
snprintf(newCommand(cmd),
|
|
MAXLINE,
|
|
"rm -rf %s; mkdir -p %s; chmod 0700 %s;rm -f /tmp/.s.*%d*",
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmMasterDir),
|
|
atoi(VAR_gtmSlavePort));
|
|
return cmd;
|
|
}
|
|
|
|
int clean_gtm_slave(void)
|
|
{
|
|
cmdList_t* cmdList = NULL;
|
|
int rc;
|
|
|
|
elog(NOTICE, "Clearing gtm slave resources.\n");
|
|
if (!isVarYes(VAR_gtmSlave) || is_none(VAR_gtmSlaveServer)) {
|
|
elog(ERROR, "ERROR: gtm slave is not configured.\n");
|
|
return 1;
|
|
}
|
|
cmdList = initCmdList();
|
|
addCmd(cmdList, prepare_cleanGtmSlave());
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
elog(NOTICE, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
/*
|
|
* ==================================================================================
|
|
*
|
|
* Gtm Proxy Staff
|
|
*
|
|
* ==================================================================================
|
|
*/
|
|
|
|
/*
|
|
* Add gtm proxy: to be used after all the configuration is done.
|
|
*
|
|
* This function only maintains internal configuration, updte configuration file,
|
|
* and make backup if configured. You should run init and start it separately.
|
|
*/
|
|
int add_gtmProxy(char* name, char* host, int port, char* dir)
|
|
{
|
|
char port_s[MAXTOKEN + 1];
|
|
char date[MAXTOKEN + 1];
|
|
FILE* f = NULL;
|
|
char** nodelist = NULL;
|
|
int rc;
|
|
|
|
if (is_none(host)) {
|
|
elog(ERROR, "ERROR: Cannot add gtm proxy with the name \"none\".\n");
|
|
return 1;
|
|
}
|
|
if (is_none(dir)) {
|
|
elog(ERROR, "ERROR: Cannot add gtm proxy with the directory \"none\".\n");
|
|
return 1;
|
|
}
|
|
if (checkSpecificResourceConflict(name, host, port, dir, TRUE)) {
|
|
elog(ERROR,
|
|
"ERROR: New specified name:%s, host:%s, port:%d and dir:\"%s\" conflicts with existing node.\n",
|
|
name,
|
|
host,
|
|
port,
|
|
dir);
|
|
return 1;
|
|
}
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
assign_sval(VAR_gtmProxy, Strdup("y"));
|
|
reset_var(VAR_gtmProxyNames);
|
|
}
|
|
add_val(find_var(VAR_gtmProxyNames), Strdup(name));
|
|
add_val(find_var(VAR_gtmProxyServers), Strdup(host));
|
|
snprintf(port_s, MAXTOKEN, "%d", port);
|
|
add_val(find_var(VAR_gtmProxyPorts), Strdup(port_s));
|
|
add_val(find_var(VAR_gtmProxyDirs), Strdup(dir));
|
|
add_val(find_var(VAR_gtmPxySpecificExtraConfig), Strdup("none"));
|
|
makeServerList();
|
|
if ((f = fopen(pgxc_ctl_config_path, "a")) == NULL) {
|
|
/* Should it be panic? */
|
|
elog(ERROR, "ERROR: cannot open configuration file \"%s\", %s\n", pgxc_ctl_config_path, strerror(errno));
|
|
return 1;
|
|
}
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# pgxc configuration file updated due to GTM proxy (%s) addition\n"
|
|
"# %s\n",
|
|
name,
|
|
timeStampString(date, MAXTOKEN + 1));
|
|
fprintSval(f, VAR_gtmProxy);
|
|
fprintAval(f, VAR_gtmProxyNames);
|
|
fprintAval(f, VAR_gtmProxyServers);
|
|
fprintAval(f, VAR_gtmProxyPorts);
|
|
fprintAval(f, VAR_gtmProxyDirs);
|
|
fprintAval(f, VAR_gtmPxySpecificExtraConfig);
|
|
fprintf(f, "%s", "#----End of reconfiguration -------------------------\n");
|
|
fclose(f);
|
|
AddMember(nodelist, name);
|
|
init_gtm_proxy(nodelist);
|
|
rc = start_gtm_proxy(nodelist);
|
|
CleanArray(nodelist);
|
|
return rc;
|
|
}
|
|
|
|
int remove_gtmProxy(char* name, bool clean_opt)
|
|
{
|
|
FILE* f = NULL;
|
|
int idx;
|
|
|
|
/* Check if gtm proxy exists */
|
|
if ((idx = gtmProxyIdx(name)) < 0) {
|
|
elog(ERROR, "ERROR: %s is not a gtm proxy.\n", name);
|
|
return 1;
|
|
}
|
|
/* Check if it is in use */
|
|
if (ifExists(VAR_coordMasterServers, aval(VAR_gtmProxyServers)[idx]) ||
|
|
ifExists(VAR_coordSlaveServers, aval(VAR_gtmProxyServers)[idx]) ||
|
|
ifExists(VAR_datanodeMasterServers, aval(VAR_gtmProxyServers)[idx]) ||
|
|
ifExists(VAR_datanodeSlaveServers, aval(VAR_gtmProxyServers)[idx])) {
|
|
elog(ERROR, "ERROR: GTM Proxy %s is in use\n", name);
|
|
return 1;
|
|
}
|
|
elog(NOTICE, "NOTICE: removing gtm_proxy %s\n", name);
|
|
/* Clean */
|
|
if (clean_opt) {
|
|
char** nodelist = NULL;
|
|
|
|
elog(NOTICE, "NOTICE: cleaning target resources.\n");
|
|
AddMember(nodelist, name);
|
|
clean_gtm_proxy(nodelist);
|
|
CleanArray(nodelist);
|
|
}
|
|
/* Reconfigure */
|
|
var_assign(&aval(VAR_gtmProxyNames)[idx], Strdup("none"));
|
|
var_assign(&aval(VAR_gtmProxyServers)[idx], Strdup("none"));
|
|
var_assign(&aval(VAR_gtmProxyPorts)[idx], Strdup("-1"));
|
|
var_assign(&aval(VAR_gtmProxyDirs)[idx], Strdup("none"));
|
|
handle_no_slaves();
|
|
makeServerList();
|
|
/* Update configuration file and backup it */
|
|
if ((f = fopen(pgxc_ctl_config_path, "a")) == NULL) {
|
|
/* Should it be panic? */
|
|
elog(ERROR, "ERROR: cannot open configuration file \"%s\", %s\n", pgxc_ctl_config_path, strerror(errno));
|
|
return 1;
|
|
}
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# pgxc configuration file updated due to GTM proxy addition\n"
|
|
"# %s\n"
|
|
"%s=%s\n" /* gtmProxy */
|
|
"%s=( %s )\n" /* gtmProxyNames */
|
|
"%s=( %s )\n" /* gtmProxyServers */
|
|
"%s=( %s )\n" /* gtmProxyPorts */
|
|
"%s=( %s )\n" /* gtmProxyDirs */
|
|
"#----End of reconfiguration -------------------------\n",
|
|
timeStampString(date, MAXTOKEN + 1),
|
|
VAR_gtmProxy,
|
|
sval(VAR_gtmProxy),
|
|
VAR_gtmProxyNames,
|
|
listValue(VAR_gtmProxyNames),
|
|
VAR_gtmProxyServers,
|
|
listValue(VAR_gtmProxyServers),
|
|
VAR_gtmProxyPorts,
|
|
listValue(VAR_gtmProxyPorts),
|
|
VAR_gtmProxyDirs,
|
|
listValue(VAR_gtmProxyDirs));
|
|
fclose(f);
|
|
backup_configuration();
|
|
elog(NOTICE, "Done.\n");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Does not check if node name is valid.
|
|
*/
|
|
|
|
cmd_t* prepare_initGtmProxy(char* nodeName)
|
|
{
|
|
cmd_t *cmdInitGtm, *cmdGtmProxyConf;
|
|
int idx;
|
|
FILE* f = NULL;
|
|
char timestamp[MAXTOKEN + 1];
|
|
char** fileList = NULL;
|
|
|
|
if ((idx = gtmProxyIdx(nodeName)) < 0) {
|
|
elog(ERROR, "ERROR: Specified name %s is not GTM Proxy configuration.\n", nodeName);
|
|
return NULL;
|
|
}
|
|
|
|
/* Build directory and run initgtm */
|
|
cmdInitGtm = initCmd(aval(VAR_gtmProxyServers)[idx]);
|
|
snprintf(newCommand(cmdInitGtm),
|
|
MAXLINE,
|
|
"killall -u %s -9 gtm_proxy;"
|
|
"rm -rf %s;"
|
|
"mkdir -p %s;"
|
|
"gs_initgtm -Z gtm_proxy -D %s",
|
|
sval(VAR_pgxcUser),
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
aval(VAR_gtmProxyDirs)[idx]);
|
|
|
|
/* Configure gtm_proxy.conf */
|
|
appendCmdEl(cmdInitGtm, (cmdGtmProxyConf = initCmd(aval(VAR_gtmProxyServers)[idx])));
|
|
if ((f = prepareLocalStdin(newFilename(cmdGtmProxyConf->localStdin), MAXPATH, NULL)) == NULL) {
|
|
cleanCmd(cmdInitGtm);
|
|
return NULL;
|
|
}
|
|
fprintf(f,
|
|
"#===========================\n"
|
|
"# Added at initialization, %s\n"
|
|
"listen_addresses = '*'\n"
|
|
"worker_threads = 1\n"
|
|
"gtm_connect_retry_interval = 1\n",
|
|
timeStampString(timestamp, MAXTOKEN));
|
|
;
|
|
if (!is_none(sval(VAR_gtmPxyExtraConfig)))
|
|
AddMember(fileList, sval(VAR_gtmPxyExtraConfig));
|
|
if (!is_none(aval(VAR_gtmPxySpecificExtraConfig)[idx]))
|
|
AddMember(fileList, aval(VAR_gtmPxySpecificExtraConfig)[idx]);
|
|
appendFiles(f, fileList);
|
|
CleanArray(fileList);
|
|
fprintf(f,
|
|
"nodename = '%s'\n"
|
|
"port = %s\n"
|
|
"gtm_host = '%s'\n"
|
|
"gtm_port = %s\n"
|
|
"# End of addition\n",
|
|
aval(VAR_gtmProxyNames)[idx],
|
|
aval(VAR_gtmProxyPorts)[idx],
|
|
sval(VAR_gtmMasterServer),
|
|
sval(VAR_gtmMasterPort));
|
|
fclose(f);
|
|
snprintf(newCommand(cmdGtmProxyConf), MAXLINE, "cat >> %s/gtm_proxy.conf", aval(VAR_gtmProxyDirs)[idx]);
|
|
return (cmdInitGtm);
|
|
}
|
|
|
|
/*
|
|
* Initialize gtm proxy -------------------------------------------------------
|
|
*/
|
|
int init_gtm_proxy(char** nodeList)
|
|
{
|
|
char** actualNodeList;
|
|
int ii;
|
|
int rc;
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmdInitGtmPxy = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
elog(ERROR, "ERROR: GTM Proxy is not configured.\n");
|
|
return 1;
|
|
}
|
|
actualNodeList = makeActualNodeList(nodeList);
|
|
/* Init and run initgtm */
|
|
cmdList = initCmdList();
|
|
for (ii = 0; actualNodeList[ii]; ii++) {
|
|
elog(NOTICE, "Initializing gtm proxy %s.\n", actualNodeList[ii]);
|
|
if ((cmdInitGtmPxy = prepare_initGtmProxy(actualNodeList[ii])))
|
|
addCmd(cmdList, cmdInitGtmPxy);
|
|
else
|
|
elog(WARNING, "WARNING: %s is not a gtm proxy.\n", actualNodeList[ii]);
|
|
}
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
CleanArray(actualNodeList);
|
|
elog(NOTICE, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
int init_gtm_proxy_all(void)
|
|
{
|
|
elog(NOTICE, "Initialize all the gtm proxies.\n");
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
elog(ERROR, "ERROR: GTM Proxy is not configured.\n");
|
|
return (1);
|
|
}
|
|
return (init_gtm_proxy(aval(VAR_gtmProxyNames)));
|
|
}
|
|
|
|
/*
|
|
* Start gtm proxy -----------------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_startGtmProxy(char* nodeName)
|
|
{
|
|
cmd_t* cmd = NULL;
|
|
int idx;
|
|
|
|
if ((idx = gtmProxyIdx(nodeName)) < 0) {
|
|
elog(ERROR, "ERROR: Specified name %s is not GTM Proxy\n", nodeName);
|
|
return (NULL);
|
|
}
|
|
cmd = initCmd(aval(VAR_gtmProxyServers)[idx]);
|
|
snprintf(newCommand(cmd),
|
|
MAXLINE,
|
|
"killall -u %s -9 gtm_proxy;"
|
|
"gtm_ctl start -Z gtm_proxy -D %s",
|
|
sval(VAR_pgxcUser),
|
|
aval(VAR_gtmProxyDirs)[idx]);
|
|
return (cmd);
|
|
}
|
|
|
|
int start_gtm_proxy(char** nodeList)
|
|
{
|
|
char** actualNodeList;
|
|
int ii;
|
|
int rc;
|
|
cmdList_t* cmdList = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
elog(ERROR, "ERROR: GTM Proxy is not configured.\n");
|
|
return (1);
|
|
}
|
|
actualNodeList = makeActualNodeList(nodeList);
|
|
/* Init and run initgtm */
|
|
cmdList = initCmdList();
|
|
for (ii = 0; actualNodeList[ii]; ii++) {
|
|
cmd_t* cmd = NULL;
|
|
elog(NOTICE, "Starting gtm proxy %s.\n", actualNodeList[ii]);
|
|
if ((cmd = prepare_startGtmProxy(actualNodeList[ii])))
|
|
addCmd(cmdList, cmd);
|
|
else
|
|
elog(WARNING, "WARNING: %s is not a gtm proxy.\n", actualNodeList[ii]);
|
|
}
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
CleanArray(actualNodeList);
|
|
elog(NOTICE, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
int start_gtm_proxy_all(void)
|
|
{
|
|
elog(NOTICE, "Starting all the gtm proxies.\n");
|
|
return (start_gtm_proxy(aval(VAR_gtmProxyNames)));
|
|
}
|
|
|
|
/*
|
|
* Stop gtm proxy -------------------------------------------------------------
|
|
*/
|
|
cmd_t* prepare_stopGtmProxy(char* nodeName)
|
|
{
|
|
cmd_t* cmd = NULL;
|
|
int idx;
|
|
|
|
if ((idx = gtmProxyIdx(nodeName)) < 0) {
|
|
elog(ERROR, "ERROR: Specified name %s is not GTM Proxy\n", nodeName);
|
|
return NULL;
|
|
}
|
|
cmd = initCmd(aval(VAR_gtmProxyServers)[idx]);
|
|
snprintf(newCommand(cmd), MAXLINE, "gtm_ctl stop -Z gtm_proxy -D %s", aval(VAR_gtmProxyDirs)[idx]);
|
|
return (cmd);
|
|
}
|
|
|
|
int stop_gtm_proxy(char** nodeList)
|
|
{
|
|
char** actualNodeList;
|
|
int ii;
|
|
int rc;
|
|
cmdList_t* cmdList = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
elog(ERROR, "ERROR: GTM Proxy is not configured.\n");
|
|
return (1);
|
|
}
|
|
actualNodeList = makeActualNodeList(nodeList);
|
|
/* Init and run initgtm */
|
|
cmdList = initCmdList();
|
|
for (ii = 0; actualNodeList[ii]; ii++) {
|
|
cmd_t* cmd = NULL;
|
|
|
|
elog(NOTICE, "Stopping gtm proxy %s.\n", actualNodeList[ii]);
|
|
if ((cmd = prepare_stopGtmProxy(actualNodeList[ii])))
|
|
addCmd(cmdList, cmd);
|
|
else
|
|
elog(WARNING, "WARNING: %s is not a gtm proxy.\n", actualNodeList[ii]);
|
|
}
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
CleanArray(actualNodeList);
|
|
elog(NOTICE, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
int stop_gtm_proxy_all(void)
|
|
{
|
|
elog(NOTICE, "Stopping all the gtm proxies.\n");
|
|
return (stop_gtm_proxy(aval(VAR_gtmProxyNames)));
|
|
}
|
|
|
|
/*
|
|
* Kill gtm proxy -------------------------------------------------------------------
|
|
*
|
|
* Although gtm proxy does not have significant resources to carry over to the next
|
|
* run, it is a good habit to stop gtm proxy with stop command gracefully.
|
|
*/
|
|
cmd_t* prepare_killGtmProxy(char* nodeName)
|
|
{
|
|
cmd_t* cmd = NULL;
|
|
int idx;
|
|
pid_t gtmPxyPid;
|
|
|
|
if ((idx = gtmProxyIdx(nodeName)) < 0) {
|
|
elog(ERROR, "ERROR: Specified name %s is not GTM Proxy\n", nodeName);
|
|
return NULL;
|
|
}
|
|
cmd = initCmd(aval(VAR_gtmProxyServers)[idx]);
|
|
gtmPxyPid = get_gtmProxy_pid(aval(VAR_gtmProxyServers)[idx], aval(VAR_gtmProxyDirs)[idx]);
|
|
if (gtmPxyPid > 0)
|
|
snprintf(newCommand(cmd),
|
|
MAXLINE,
|
|
"kill -9 %d; rm -rf /tmp/.s.'*'%d'*' %s/gtm_proxy.pid",
|
|
gtmPxyPid,
|
|
atoi(aval(VAR_gtmProxyPorts)[idx]),
|
|
aval(VAR_gtmProxyDirs)[idx]);
|
|
else
|
|
snprintf(newCommand(cmd),
|
|
MAXLINE,
|
|
"killall -u %s -9 gs_gtm; rm -rf /tmp/.s.'*'%d'*' %s/gtm_proxy.pid",
|
|
sval(VAR_pgxcUser),
|
|
atoi(aval(VAR_gtmProxyPorts)[idx]),
|
|
aval(VAR_gtmProxyDirs)[idx]);
|
|
return (cmd);
|
|
}
|
|
|
|
int kill_gtm_proxy(char** nodeList)
|
|
{
|
|
char** actualNodeList;
|
|
int ii;
|
|
int rc;
|
|
cmdList_t* cmdList = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
elog(ERROR, "ERROR: GTM Proxy is not configured.\n");
|
|
return (1);
|
|
}
|
|
actualNodeList = makeActualNodeList(nodeList);
|
|
/* Init and run initgtm */
|
|
cmdList = initCmdList();
|
|
for (ii = 0; actualNodeList[ii]; ii++) {
|
|
cmd_t* cmd = NULL;
|
|
|
|
elog(NOTICE, "Killing process of gtm proxy %s.\n", actualNodeList[ii]);
|
|
if ((cmd = prepare_killGtmProxy(actualNodeList[ii])))
|
|
addCmd(cmdList, cmd);
|
|
else
|
|
elog(WARNING, "WARNING: %s is not a gtm proxy.\n", actualNodeList[ii]);
|
|
}
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
CleanArray(actualNodeList);
|
|
return (rc);
|
|
}
|
|
|
|
int kill_gtm_proxy_all(void)
|
|
{
|
|
elog(NOTICE, "Killing all the gtm proxy processes.\n");
|
|
return (kill_gtm_proxy(aval(VAR_gtmProxyNames)));
|
|
}
|
|
|
|
/*
|
|
* Reconnect to the current GTM master --------------------------------------------------
|
|
*
|
|
* When failed over, the current Master must have been updated.
|
|
* Remember to update gtm_proxy configuration file so that it
|
|
* connects to the new master at the next start.
|
|
* Please note that we assume GTM has already been failed over.
|
|
* First argument is gtm_proxy nodename
|
|
*/
|
|
cmd_t* prepare_reconnectGtmProxy(char* nodeName)
|
|
{
|
|
cmd_t *cmdGtmCtl, *cmdGtmProxyConf;
|
|
int idx;
|
|
FILE* f = NULL;
|
|
char date[MAXTOKEN + 1];
|
|
|
|
if ((idx = gtmProxyIdx(nodeName)) < 0) {
|
|
elog(ERROR, "ERROR: Specified name %s is not GTM Proxy\n", nodeName);
|
|
return (NULL);
|
|
}
|
|
|
|
/* gtm_ctl reconnect */
|
|
cmdGtmCtl = initCmd(aval(VAR_gtmProxyServers)[idx]);
|
|
snprintf(newCommand(cmdGtmCtl),
|
|
MAXLINE,
|
|
"gtm_ctl reconnect -Z gtm_proxy -D %s -o \\\"-s %s -t %s\\\"",
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
sval(VAR_gtmMasterServer),
|
|
sval(VAR_gtmMasterPort));
|
|
|
|
/* gtm_proxy.conf */
|
|
appendCmdEl(cmdGtmCtl, (cmdGtmProxyConf = initCmd(aval(VAR_gtmProxyServers)[idx])));
|
|
if ((f = prepareLocalStdin(newFilename(cmdGtmProxyConf->localStdin), MAXPATH, NULL)) == NULL) {
|
|
cleanCmd(cmdGtmCtl);
|
|
return (NULL);
|
|
}
|
|
fprintf(f,
|
|
"#===================================================\n"
|
|
"# Updated due to GTM Proxy reconnect\n"
|
|
"# %s\n"
|
|
"gtm_host = '%s'\n"
|
|
"gtm_port = %s\n"
|
|
"#----End of reconfiguration -------------------------\n",
|
|
timeStampString(date, MAXTOKEN),
|
|
sval(VAR_gtmMasterServer),
|
|
sval(VAR_gtmMasterPort));
|
|
fclose(f);
|
|
snprintf(newCommand(cmdGtmProxyConf), MAXLINE, "cat >> %s/gtm_proxy.conf", aval(VAR_gtmProxyDirs)[idx]);
|
|
return (cmdGtmCtl);
|
|
}
|
|
|
|
int reconnect_gtm_proxy(char** nodeList)
|
|
{
|
|
char** actualNodeList;
|
|
int ii;
|
|
int rc;
|
|
cmdList_t* cmdList = NULL;
|
|
|
|
if (!isVarYes(VAR_gtmProxy)) {
|
|
elog(ERROR, "GTM Proxy is not configured.\n");
|
|
return (1);
|
|
}
|
|
actualNodeList = makeActualNodeList(nodeList);
|
|
/* Init and run initgtm */
|
|
cmdList = initCmdList();
|
|
for (ii = 0; actualNodeList[ii]; ii++) {
|
|
cmd_t* cmd = NULL;
|
|
|
|
elog(NOTICE, "Reconnecting gtm proxy %s.\n", actualNodeList[ii]);
|
|
if ((cmd = prepare_reconnectGtmProxy(actualNodeList[ii])))
|
|
addCmd(cmdList, cmd);
|
|
else
|
|
elog(WARNING, "WARNING: %s is not a gtm proxy.\n", actualNodeList[ii]);
|
|
}
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
CleanArray(actualNodeList);
|
|
elog(NOTICE, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
int reconnect_gtm_proxy_all(void)
|
|
{
|
|
elog(NOTICE, "Reconnecting all the gtm proxies to the new one.\n");
|
|
return (reconnect_gtm_proxy(aval(VAR_gtmProxyNames)));
|
|
}
|
|
|
|
/*
|
|
* Cleanup -- nodeName must be valid. Instead, NULL will bereturned.
|
|
*/
|
|
cmd_t* prepare_cleanGtmProxy(char* nodeName)
|
|
{
|
|
cmd_t* cmd = NULL;
|
|
int idx;
|
|
|
|
if ((idx = gtmProxyIdx(nodeName)) < 0)
|
|
return NULL;
|
|
cmd = initCmd(aval(VAR_gtmProxyServers)[idx]);
|
|
snprintf(newCommand(cmd),
|
|
MAXLINE,
|
|
"rm -rf %s; mkdir -p %s; chmod 0700 %s;rm -f /tmp/.s.*%d*",
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
atoi(aval(VAR_gtmProxyPorts)[idx]));
|
|
return cmd;
|
|
}
|
|
|
|
int clean_gtm_proxy(char** nodeList)
|
|
{
|
|
char** actualNodeList;
|
|
cmdList_t* cmdList = NULL;
|
|
cmd_t* cmd = NULL;
|
|
int ii;
|
|
int rc;
|
|
|
|
actualNodeList = makeActualNodeList(nodeList);
|
|
cmdList = initCmdList();
|
|
for (ii = 0; actualNodeList[ii]; ii++) {
|
|
elog(NOTICE, "Clearing resources for gtm_proxy %s.\n", actualNodeList[ii]);
|
|
if ((cmd = prepare_cleanGtmProxy(actualNodeList[ii])))
|
|
addCmd(cmdList, cmd);
|
|
else
|
|
elog(WARNING, "%s is not a gtm proxy.\n", actualNodeList[ii]);
|
|
}
|
|
rc = doCmdList(cmdList);
|
|
cleanCmdList(cmdList);
|
|
CleanArray(actualNodeList);
|
|
elog(NOTICE, "Done.\n");
|
|
return (rc);
|
|
}
|
|
|
|
int clean_gtm_proxy_all(void)
|
|
{
|
|
elog(NOTICE, "Clearing all the gtm_proxy resources.\n");
|
|
return (clean_gtm_proxy(aval(VAR_gtmProxyNames)));
|
|
}
|
|
|
|
/*
|
|
* configuration --------------------------------------------------------------------
|
|
*/
|
|
int show_config_gtmMaster(int flag, char* hostname)
|
|
{
|
|
char lineBuf[MAXLINE + 1];
|
|
char editBuf[MAXPATH + 1];
|
|
|
|
lineBuf[0] = 0;
|
|
if (flag)
|
|
strncat(lineBuf, "GTM Master: ", MAXLINE);
|
|
if (hostname) {
|
|
snprintf(editBuf, MAXPATH, "host: %s", hostname);
|
|
strncat(lineBuf, editBuf, MAXLINE);
|
|
}
|
|
if (flag || hostname)
|
|
strncat(lineBuf, "\n", MAXLINE);
|
|
lockLogFile();
|
|
if (lineBuf[0])
|
|
elog(NOTICE, "%s", lineBuf);
|
|
print_simple_node_info(sval(VAR_gtmName),
|
|
sval(VAR_gtmMasterPort),
|
|
sval(VAR_gtmMasterDir),
|
|
sval(VAR_gtmExtraConfig),
|
|
sval(VAR_gtmMasterSpecificExtraConfig));
|
|
unlockLogFile();
|
|
return 0;
|
|
}
|
|
|
|
int show_config_gtmSlave(int flag, char* hostname)
|
|
{
|
|
char lineBuf[MAXLINE + 1];
|
|
char editBuf[MAXPATH + 1];
|
|
|
|
if (!isVarYes(VAR_gtmSlave) || is_none(VAR_gtmSlaveServer)) {
|
|
elog(ERROR, "ERROR: gtm slave is not configured.\n");
|
|
return 0;
|
|
}
|
|
lineBuf[0] = 0;
|
|
if (flag)
|
|
strncat(lineBuf, "GTM Slave: ", MAXLINE);
|
|
if (hostname) {
|
|
snprintf(editBuf, MAXPATH, "host: %s", hostname);
|
|
strncat(lineBuf, editBuf, MAXLINE);
|
|
}
|
|
if (flag || hostname)
|
|
strncat(lineBuf, "\n", MAXLINE);
|
|
lockLogFile();
|
|
elog(NOTICE, "%s", lineBuf);
|
|
print_simple_node_info(sval(VAR_gtmName),
|
|
sval(VAR_gtmSlavePort),
|
|
sval(VAR_gtmSlaveDir),
|
|
sval(VAR_gtmExtraConfig),
|
|
sval(VAR_gtmSlaveSpecificExtraConfig));
|
|
unlockLogFile();
|
|
return 0;
|
|
}
|
|
|
|
int show_config_gtmProxies(char** nameList)
|
|
{
|
|
int ii;
|
|
|
|
lockLogFile();
|
|
for (ii = 0; nameList[ii]; ii++)
|
|
show_config_gtmProxy(TRUE, ii, aval(VAR_gtmProxyServers)[ii]);
|
|
unlockLogFile();
|
|
return 0;
|
|
}
|
|
|
|
int show_config_gtmProxy(int flag, int idx, char* hostname)
|
|
{
|
|
char lineBuf[MAXLINE + 1];
|
|
char editBuf[MAXPATH + 1];
|
|
|
|
lineBuf[0] = 0;
|
|
if (flag)
|
|
strncat(lineBuf, "GTM Proxy: ", MAXLINE);
|
|
if (hostname) {
|
|
snprintf(editBuf, MAXPATH, "host: %s", hostname);
|
|
strncat(lineBuf, editBuf, MAXLINE);
|
|
}
|
|
if (flag || hostname)
|
|
strncat(lineBuf, "\n", MAXLINE);
|
|
lockLogFile();
|
|
if (lineBuf[0])
|
|
elog(NOTICE, "%s", lineBuf);
|
|
print_simple_node_info(aval(VAR_gtmProxyNames)[idx],
|
|
aval(VAR_gtmProxyPorts)[idx],
|
|
aval(VAR_gtmProxyDirs)[idx],
|
|
sval(VAR_gtmPxyExtraConfig),
|
|
aval(VAR_gtmPxySpecificExtraConfig)[idx]);
|
|
unlockLogFile();
|
|
return 0;
|
|
}
|