* Copyright (c) 2021 Huawei Technologies Co.,Ltd.
*
* CM is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* ctl_misc.cpp
* cm_ctl check -B BINNAME -T DATAPATH
* cm_ctl build -n NODEID -D DATADIR [-t SECS] [-f] [-b full]
* cm_ctl disable -n NODEID -D DATADIR [-t SECS]
* cm_ctl hotpatch -E PATCH_COMMAND -P PATCH_NAME
* cm_ctl set [--log_level=LOG_LEVEL] [--cm_arbitration_mode=ARBITRATION_MODE]
* [--cm_switchover_az_mode=SWITCHOVER_AZ_MODE]
* cm_ctl get [--log_level] [--cm_arbitration_mode] [--cm_switchover_az_mode]
*
* IDENTIFICATION
* src/cm_ctl/ctl_misc.cpp
*
* -------------------------------------------------------------------------
*/
#include <signal.h>
#include "common/config/cm_config.h"
#include "cm/libpq-fe.h"
#include "cm/cm_misc.h"
#include "ctl_common.h"
#include "ctl_process_message.h"
#include "cm_msg_version_convert.h"
#include "cm/libpq-int.h"
#include "cm/cm_agent/cma_main.h"
#define MAX_INSTANCE_ROLE_ABNORMAL_TIMES 40
extern char* g_bin_name;
extern char* g_bin_path;
extern int do_force;
extern ShutdownMode shutdown_mode_num;
extern bool wait_seconds_set;
extern int g_waitSeconds;
extern char mpp_env_separate_file[MAXPGPATH];
extern uint32 g_nodeIndexForCmServer[CM_PRIMARY_STANDBY_NUM];
extern char g_cmData[CM_PATH_LENGTH];
extern char result_path[MAXPGPATH];
extern uint32 g_commandOperationNodeId;
extern uint32 g_commandOperationInstanceId;
extern char g_appPath[MAXPGPATH];
extern uint32 g_nodeId;
extern char manual_start_file[MAXPGPATH];
extern char instance_manual_start_file[MAXPGPATH];
extern char etcd_manual_start_file[MAXPGPATH];
#ifndef ENABLE_MULTIPLE_NODES
extern char g_ltranManualStartFile[MAXPGPATH];
extern char g_libnetManualStartFile[MAXPGPATH];
#else
extern bool cn_resumes_restart;
#endif
extern char* cm_logic_cluster_restart_mode_set;
extern bool cm_switchover_az_mode_get;
extern char* cm_switchover_az_mode_set;
extern bool cm_arbitration_mode_get;
extern char* cm_arbitration_mode_set;
extern bool log_level_get;
extern char* log_level_set;
extern const char* g_progname;
extern CM_Conn* CmServer_conn;
extern CM_Conn* CmServer_conn1;
extern char *g_dcfXMode;
extern int g_dcfVoteNum;
extern char *g_cmsPromoteMode;
static pid_t get_instances_pid(const char* pid_path);
static bool is_etcd_stopping(void);
#ifndef ENABLE_MULTIPLE_NODES
static bool IsLtranStopping(void);
#endif
static bool is_instance_stopping(const char* dataPath);
static int do_hotpatch_cmserver(const char* command, const char* path, uint32 nodeid);
static bool checkManualStartFile(const char* binaryName, const char* dataPath);
static status_t DoSetCmsPromoteMode();
const int BUILD_CMS_TIMEOUT = 120;
const int BUILD_DN_TIMEOUT = 600;
static const uint32 PRIMARY_STANDBY_MODE = 2;
int do_set(void)
{
ctl_to_cm_set cm_ctl_cm_set_content;
int ret;
int time_pass = 0;
bool success = false;
char* receive_msg = NULL;
cm_msg_type* cm_msg_type_ptr = NULL;
if (g_cmsPromoteMode != NULL) {
if (DoSetCmsPromoteMode() != CM_SUCCESS) {
return 1;
}
return 0;
}
if (cm_arbitration_mode_set != NULL) {
for (uint32 kk = 0; kk < g_node_num; kk++) {
do_conn_cmserver(true, kk);
if (CmServer_conn1 != NULL) {
break;
}
}
CMPQfinish(CmServer_conn);
CmServer_conn = CmServer_conn1;
} else {
do_conn_cmserver(false, 0);
}
if (CmServer_conn == NULL) {
write_runlog(ERROR, "send set msg to cm_server connect fail.\n");
return -1;
}
write_runlog(LOG, "send set msg to cm_server.\n");
cm_ctl_cm_set_content.msg_type = (int)MSG_CTL_CM_SET;
cm_ctl_cm_set_content.log_level = UNKNOWN_LEVEL;
cm_ctl_cm_set_content.cm_arbitration_mode = UNKNOWN_ARBITRATION;
cm_ctl_cm_set_content.cm_switchover_az_mode = UNKNOWN_SWITCHOVER_AZ;
cm_ctl_cm_set_content.cm_logic_cluster_restart_mode = UNKNOWN_LOGIC_CLUSTER_RESTART;
if (log_level_set != NULL) {
cm_ctl_cm_set_content.log_level = log_level_string_to_int(log_level_set);
if (cm_ctl_cm_set_content.log_level == UNKNOWN_LEVEL) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
write_runlog(FATAL, "invalid log level.\n");
DoAdvice();
exit(1);
}
}
if (cm_arbitration_mode_set != NULL) {
if (isMajority(cm_arbitration_mode_set)) {
cm_ctl_cm_set_content.cm_arbitration_mode = MAJORITY_ARBITRATION;
} else if (isMinority(cm_arbitration_mode_set)) {
write_runlog(LOG, "Minority cluster! The cluster data may be lost: RPO !=0.\n");
cm_ctl_cm_set_content.cm_arbitration_mode = MINORITY_ARBITRATION;
} else {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
write_runlog(FATAL, "invalid cm server arbitration mode.\n");
DoAdvice();
exit(1);
}
}
if (cm_switchover_az_mode_set != NULL) {
if (strcasecmp("NON_AUTO", cm_switchover_az_mode_set) == 0) {
cm_ctl_cm_set_content.cm_switchover_az_mode = NON_AUTOSWITCHOVER_AZ;
} else if (strcasecmp("AUTO", cm_switchover_az_mode_set) == 0) {
cm_ctl_cm_set_content.cm_switchover_az_mode = AUTOSWITCHOVER_AZ;
} else {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
write_runlog(FATAL, "invalid cm server switchover az mode.\n");
DoAdvice();
exit(1);
}
}
if (cm_logic_cluster_restart_mode_set != NULL) {
cm_ctl_cm_set_content.logic_cluster_delay = (uint32)CmAtoi(cm_logic_cluster_restart_mode_set, 0);
if (cm_ctl_cm_set_content.logic_cluster_delay == 0) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
write_runlog(FATAL, "invalid cm server failover delay time.\n");
DoAdvice();
exit(1);
} else {
cm_ctl_cm_set_content.cm_logic_cluster_restart_mode = MODIFY_LOGIC_CLUSTER_RESTART;
}
}
ret = cm_client_send_msg(CmServer_conn, 'C', (char*)&cm_ctl_cm_set_content, sizeof(ctl_to_cm_set));
if (ret != 0) {
FINISH_CONNECTION((CmServer_conn), -1);
}
for (;;) {
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION((CmServer_conn), -1);
}
receive_msg = recv_cm_server_cmd(CmServer_conn);
if (receive_msg != NULL) {
cm_msg_type_ptr = (cm_msg_type *)receive_msg;
if (cm_msg_type_ptr->msg_type == (int)MSG_CM_CTL_SET_ACK) {
write_runlog(LOG, "cm server has been set.\n");
success = true;
} else {
write_runlog(ERROR, "unknown the msg type is %d.\n", cm_msg_type_ptr->msg_type);
}
}
if (success) {
break;
}
(void)sleep(1);
write_runlog(LOG, ".");
time_pass++;
if (time_pass >= g_waitSeconds) {
break;
}
}
if (time_pass >= g_waitSeconds) {
write_runlog(ERROR,
"set command timeout!\n\n"
"HINT: Maybe the set action is continually running in the background.\n"
"You can wait for a while and check the value of item has been set using "
"\"cm_ctl get <item>\".\n");
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return -3;
} else {
write_runlog(LOG, "new value set successfully.\n");
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return 0;
}
}
int do_get(void)
{
cm_msg_type cm_msg;
int ret;
int time_pass = 0;
char* receive_msg = NULL;
bool success = false;
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(ERROR, "send get msg to cm_server connect fail.\n");
return -1;
}
write_runlog(LOG, "send get msg to cm_server.\n");
cm_msg.msg_type = (int)MSG_CTL_CM_GET;
ret = cm_client_send_msg(CmServer_conn, 'C', (char*)&cm_msg, sizeof(cm_msg));
if (ret != 0) {
FINISH_CONNECTION((CmServer_conn), -1);
}
for (;;) {
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION((CmServer_conn), -1);
}
receive_msg = recv_cm_server_cmd(CmServer_conn);
if (receive_msg != NULL) {
cm_to_ctl_get *cm_to_ctl_get_ptr = (cm_to_ctl_get*)receive_msg;
switch (cm_to_ctl_get_ptr->msg_type) {
case MSG_CM_CTL_GET_ACK:
write_runlog(WARNING, "cm server has been get.\n");
success = true;
if (log_level_get) {
write_runlog(LOG, "log_level=%s\n", log_level_int_to_string(cm_to_ctl_get_ptr->log_level));
}
if (cm_arbitration_mode_get) {
if (cm_to_ctl_get_ptr->cm_arbitration_mode == MAJORITY_ARBITRATION) {
write_runlog(LOG, "cm_arbitration_mode=MAJORITY\n");
} else if (cm_to_ctl_get_ptr->cm_arbitration_mode == MINORITY_ARBITRATION) {
write_runlog(LOG, "cm_arbitration_mode=MINORITY\n");
} else {
write_runlog(LOG, "cm_arbitration_mode=UNKNOWN\n");
}
}
if (cm_switchover_az_mode_get) {
if (cm_to_ctl_get_ptr->cm_switchover_az_mode == AUTOSWITCHOVER_AZ) {
write_runlog(LOG, "cm_switchover_az_mode=AUTO\n");
} else if (cm_to_ctl_get_ptr->cm_switchover_az_mode == NON_AUTOSWITCHOVER_AZ) {
write_runlog(LOG, "cm_switchover_az_mode=NON_AUTO\n");
} else {
write_runlog(LOG, "cm_switchover_az_mode=UNKNOWN\n");
}
}
break;
default:
write_runlog(ERROR, "unknown the msg type is %d.\n", cm_to_ctl_get_ptr->msg_type);
break;
}
}
if (success) {
break;
}
(void)sleep(1);
write_runlog(LOG, ".");
time_pass++;
if (time_pass >= g_waitSeconds) {
break;
}
}
if (time_pass >= g_waitSeconds) {
write_runlog(ERROR, "get command timeout.\n");
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return -3;
} else {
write_runlog(LOG, "gets it successfully.\n");
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return 0;
}
}
int do_check(void)
{
* 0 : nothingness
* 2 : running
*/
int status = CheckInstanceStatus(g_bin_name, g_bin_path);
if (status == PROCESS_RUNNING) {
CmSleep(10);
status = CheckInstanceStatus(g_bin_name, g_bin_path);
}
return status;
}
int CheckInstanceStatus(const char* processName, const char* cmdLine)
{
char pid_path[MAX_PATH_LEN];
char cmd_path[MAX_PATH_LEN];
FILE* fp = NULL;
char getBuff[MAX_PATH_LEN];
char* get_result = NULL;
char paraName[MAX_PATH_LEN];
char paraValue[MAX_PATH_LEN];
int pid = 0;
int ppid = 0;
char state = '0';
uid_t uid = 0;
uid_t uid1 = 0;
uid_t uid2 = 0;
uid_t uid3 = 0;
bool nameFound = false;
bool nameGet = false;
bool ppidGet = false;
bool stateGet = false;
bool haveFound = false;
bool uidGet = false;
char* p = NULL;
int i = 0;
int paralen;
int ret;
errno_t tnRet = 0;
int rcs;
int pid_post = 0;
char pid_post_path[MAX_PATH_LEN];
const char* procPath = "/proc";
rcs = snprintf_s(pid_post_path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s", cmdLine, "postmaster.pid");
securec_check_intval(rcs, (void)rcs);
canonicalize_path(pid_post_path);
if (strcmp(processName, "gaussdb") == 0) {
pid_post = get_instances_pid(pid_post_path);
}
DIR *dir = opendir(procPath);
if (dir == NULL) {
char errBuffer[ERROR_LIMIT_LEN];
write_runlog(ERROR,
"failed to open the directory: dir=\"%s\", errno=%d, errMessage=\"%s\".\n",
procPath,
errno,
strerror_r(errno, errBuffer, ERROR_LIMIT_LEN));
return -1;
}
struct dirent *de;
while ((de = readdir(dir)) != NULL) {
check whether there are files under the directory ,these files includes
all detailed information about the process */
if (CM_is_str_all_digit(de->d_name) != 0) {
continue;
}
tnRet = memset_s(pid_path, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
pid = atoi(de->d_name);
{
ret = snprintf_s(pid_path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "/proc/%d/status", pid);
securec_check_intval(ret, (void)ret);
}
fp = fopen(pid_path, "r");
if (fp == NULL) {
continue;
}
nameGet = false;
ppidGet = false;
stateGet = false;
uidGet = false;
tnRet = memset_s(paraValue, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
ppid = 0;
state = '0';
uid = 0;
tnRet = memset_s(getBuff, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
nameFound = false;
while ((get_result = fgets(getBuff, MAX_PATH_LEN - 1, fp)) != NULL) {
tnRet = memset_s(paraName, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
if (!nameGet && ((get_result = strstr(getBuff, "Name:")) != NULL)) {
nameGet = true;
ret = sscanf_s(getBuff, "%s %s", paraName, MAX_PATH_LEN, paraValue, MAX_PATH_LEN);
check_sscanf_s_result(ret, 2);
securec_check_intval(ret, (void)ret);
if (strcmp(processName, paraValue) == 0) {
nameFound = true;
} else {
break;
}
}
if (!ppidGet && ((get_result = strstr(getBuff, "PPid:")) != NULL)) {
ppidGet = true;
ret = sscanf_s(getBuff, "%s %d", paraName, MAX_PATH_LEN, &ppid);
check_sscanf_s_result(ret, 2);
securec_check_intval(ret, (void)ret);
}
if (!stateGet && ((get_result = strstr(getBuff, "State:")) != NULL)) {
stateGet = true;
ret = sscanf_s(getBuff, "%s %c", paraName, MAX_PATH_LEN, &state, 1);
check_sscanf_s_result(ret, 2);
securec_check_intval(ret, (void)ret);
}
if (!uidGet && ((get_result = strstr(getBuff, "Uid:")) != NULL)) {
uidGet = true;
ret = sscanf_s(
getBuff, "%s %u %u %u %u", paraName, MAX_PATH_LEN, &uid, &uid1, &uid2, &uid3);
check_sscanf_s_result(ret, 5);
securec_check_intval(ret, (void)ret);
}
if (nameGet && ppidGet && stateGet && uidGet) {
break;
}
}
(void)fclose(fp);
if (!nameFound) {
continue;
}
if (getuid() != uid) {
continue;
}
tnRet = memset_s(cmd_path, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
ret = snprintf_s(cmd_path, MAX_PATH_LEN, MAX_PATH_LEN - 1, "/proc/%d/cmdline", pid);
securec_check_intval(ret, (void)ret);
fp = fopen(cmd_path, "r");
if (fp == NULL) {
continue;
}
tnRet = memset_s(getBuff, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
if ((get_result = fgets(getBuff, MAX_PATH_LEN - 1, fp)) != NULL) {
p = getBuff;
i = 0;
while (i < MAX_PATH_LEN - 1) {
if (*p == '/') {
if (strcmp(p, cmdLine) == 0) {
haveFound = true;
break;
} else {
char* cmd_line_tmp = xstrdup(cmdLine);
canonicalize_path(cmd_line_tmp);
if (strcmp(p, cmd_line_tmp) == 0) {
haveFound = true;
FREE_AND_RESET(cmd_line_tmp);
break;
}
FREE_AND_RESET(cmd_line_tmp);
paralen = (int)strlen(p);
p = p + paralen;
i = i + paralen;
}
} else if (*p == 'l') {
if (strstr(p, cmdLine) != NULL) {
haveFound = true;
break;
} else {
p++;
i++;
}
} else {
p++;
i++;
}
}
tnRet = memset_s(getBuff, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(tnRet, (void)tnRet);
}
(void)fclose(fp);
if (haveFound) {
break;
}
}
(void)closedir(dir);
bool foundStartFile = checkManualStartFile(processName, cmdLine);
write_runlog(DEBUG1,
"check the manual start file and the instance process: foundStartFile=%d, haveFound=%d,"
" binaryName=\"%s\", dataPath=\"%s\".\n",
foundStartFile,
haveFound,
processName,
cmdLine);
if (haveFound && !foundStartFile) {
if (strcmp(processName, "gaussdb") == 0) {
if ((pid_post == pid) && (pid > 0)) {
return PROCESS_RUNNING;
} else {
return PROCESS_WAIT_START;
}
} else {
return PROCESS_RUNNING;
}
} else if (!haveFound && foundStartFile) {
return PROCESS_NOT_EXIST;
} else if (haveFound && foundStartFile) {
return PROCESS_WAIT_STOP;
} else {
return PROCESS_WAIT_START;
}
}
static pid_t get_instances_pid(const char* pid_path)
{
pid_t pid;
FILE *pidf = fopen(pid_path, "r");
if (pidf == NULL) {
char errBuffer[ERROR_LIMIT_LEN];
if (errno == ENOENT) {
write_runlog(DEBUG1,
"PID file :\"%s\" does not exist: %s\n.",
pid_path,
strerror_r(errno, errBuffer, ERROR_LIMIT_LEN));
} else {
write_runlog(DEBUG1,
"could not open PID file \"%s\": %s\n.",
pid_path,
strerror_r(errno, errBuffer, ERROR_LIMIT_LEN));
}
return 0;
}
if (fscanf_s(pidf, "%d", &pid) != 1) {
write_runlog(DEBUG1, "invalid data in PID file \"%s\"\n", pid_path);
(void)fclose(pidf);
return 0;
}
(void)fclose(pidf);
return pid;
}
* @brief Check whether the manual start file exist in the target node.
*
* @param [in] binaryName: The binary name string.
* @param [in] dataPath: The data path string.
*
* @return true: if the instance is manual stopped.
* @return false: if the instance is not manual stopped.
*/
static bool checkManualStartFile(const char* binaryName, const char* dataPath)
{
if (binaryName == NULL) {
write_runlog(DEBUG1, "Binary name is null.\n");
return false;
}
if (strncmp(binaryName, ETCD_BIN_NAME, sizeof(ETCD_BIN_NAME)) == 0) {
return is_etcd_stopping();
}
#ifndef ENABLE_MULTIPLE_NODES
if (strncmp(binaryName, ITRAN_BIN_NAME, sizeof(ITRAN_BIN_NAME)) == 0) {
return IsLtranStopping();
}
#endif
if (is_node_stopping(g_nodeId, g_nodeId, manual_start_file, result_path, mpp_env_separate_file)) {
write_runlog(DEBUG1,
"manual_start_file(%s) successfully write at node(%u, %s).\n",
manual_start_file,
g_nodeId,
g_node[g_nodeId].nodeName);
return true;
}
if (strncmp(binaryName, CM_AGENT_BIN_NAME, sizeof(CM_AGENT_BIN_NAME)) == 0 ||
strncmp(binaryName, CM_SERVER_BIN_NAME, sizeof(CM_SERVER_BIN_NAME)) == 0) {
return false;
}
return is_instance_stopping(dataPath);
}
static bool is_etcd_stopping(void)
{
int result = -1;
char command[MAXPGPATH] = {0};
int ret;
ret = snprintf_s(command, MAXPGPATH, MAXPGPATH - 1, "ls %s > /dev/null 2>&1 \n echo -e $? > %s",
etcd_manual_start_file, result_path);
securec_check_intval(ret, (void)ret);
exec_system(command, &result, result_path);
return (result == 0);
}
#ifndef ENABLE_MULTIPLE_NODES
static bool IsLtranStopping(void)
{
int result = -1;
char command[MAXPGPATH * 3] = {0};
int ret;
ret = snprintf_s(command,
MAXPGPATH * 3,
MAXPGPATH * 3 - 1,
"ls %s > /dev/null 2>&1 \n echo -e $? > %s",
g_ltranManualStartFile,
result_path);
securec_check_ss_c(ret, "", "");
exec_system(command, &result, result_path);
return (result == 0) ? true : false;
}
#endif
static bool is_instance_stopping(const char* dataPath)
{
int result = -1;
char command[MAX_PATH_LEN] = {0};
int ret;
uint32 instanceId = 0;
int instanceType = 0;
ret = FindInstanceIdAndType(g_currentNode->node, dataPath, &instanceId, &instanceType);
if (ret != 0) {
write_runlog(FATAL, "can't find the node_id:%u, data_path:%s.\n", g_currentNode->node, dataPath);
exit(-1);
}
ret = snprintf_s(command, MAX_PATH_LEN, MAX_PATH_LEN - 1, "ls %s_%u > /dev/null 2>&1 \n echo -e $? > %s",
instance_manual_start_file, instanceId, result_path);
securec_check_intval(ret, (void)ret);
exec_system(command, &result, result_path);
return (result == 0);
}
int do_disable_cn()
{
int ret;
int instance_type = 0;
uint32 instanceId = 0;
char* receive_msg = NULL;
cm_msg_type* cm_msg_type_ptr = NULL;
ctl_to_cm_disable_cn ctl_to_cm_disable_cn_content = {0};
ctl_to_cm_disable_cn_ack* ctl_to_cm_disable_cn_ack_ptr = NULL;
cm_to_ctl_instance_status* cm_to_ctl_instance_status_ptr = NULL;
cm_to_ctl_instance_status_ipv4* cm_to_ctl_instance_status_ptr_ipv4 = NULL;
ctl_to_cm_query cm_ctl_cm_query_content = {0};
int wait_time = DEFAULT_WAIT;
int sendQueryCount = 0;
int getQueryCount = 0;
bool success = false;
int checkSendDisableTime = 3;
bool tryFlag = false;
int checkCNStateCnt = 10;
bool tryCheckStateFlag = false;
ret = FindInstanceIdAndType(g_commandOperationNodeId, g_cmData, &instanceId, &instance_type);
if (ret != 0) {
write_stderr(
_("%s: can't find the node_id:%u, data_path:%s.\n"), g_progname, g_commandOperationNodeId, g_cmData);
return -1;
}
if (instance_type != INSTANCE_TYPE_COORDINATE) {
write_stderr(_("%s: the instance is not coordinator, only coordinator can be disabled.\n"), g_progname);
return -1;
}
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_stderr(_("%s: send disable cn msg to cm_server, connect fail node_id:%u, data_path:%s.\n"),
g_progname,
g_commandOperationNodeId,
g_cmData);
return -1;
}
ctl_to_cm_disable_cn_content.msg_type = (int)MSG_CTL_CM_DISABLE_CN;
ctl_to_cm_disable_cn_content.instanceId = instanceId;
if (wait_seconds_set) {
ctl_to_cm_disable_cn_content.wait_seconds = g_waitSeconds;
wait_time = g_waitSeconds;
} else {
ctl_to_cm_disable_cn_content.wait_seconds = DEFAULT_WAIT * 2;
wait_time = DEFAULT_WAIT * 2;
}
ret = cm_client_send_msg(CmServer_conn, 'C', (char*)&ctl_to_cm_disable_cn_content, sizeof(ctl_to_cm_disable_cn));
if (ret != 0) {
FINISH_CONNECTION((CmServer_conn), -1);
}
for (;;) {
tryCheckStateFlag = false;
if (CmServer_conn != NULL) {
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
}
receive_msg = recv_cm_server_cmd(CmServer_conn);
}
if (receive_msg != NULL) {
cm_msg_type_ptr = (cm_msg_type*)receive_msg;
switch (cm_msg_type_ptr->msg_type) {
case MSG_CTL_CM_DISABLE_CN_ACK:
ctl_to_cm_disable_cn_ack_ptr = (ctl_to_cm_disable_cn_ack*)receive_msg;
if (ctl_to_cm_disable_cn_ack_ptr != NULL && !ctl_to_cm_disable_cn_ack_ptr->disable_ok && !tryFlag) {
if ((strstr(ctl_to_cm_disable_cn_ack_ptr->errMsg, "state is not down") != NULL) &&
checkCNStateCnt > 0) {
tryCheckStateFlag = true;
break;
}
write_stderr(_("\n%s:%s"), g_progname, ctl_to_cm_disable_cn_ack_ptr->errMsg);
return -1;
}
break;
case MSG_CM_CTL_DATA:
getQueryCount++;
if (undocumentedVersion !=0 && undocumentedVersion < SUPPORT_IPV6_VERSION) {
cm_to_ctl_instance_status_ptr_ipv4 = (cm_to_ctl_instance_status_ipv4*)receive_msg;
if (cm_to_ctl_instance_status_ptr_ipv4->coordinatemember.status == INSTANCE_ROLE_DELETED) {
success = true;
}
} else {
cm_to_ctl_instance_status_ptr = (cm_to_ctl_instance_status*)receive_msg;
if (cm_to_ctl_instance_status_ptr->coordinatemember.status == INSTANCE_ROLE_DELETED) {
success = true;
}
}
break;
default:
write_stderr(_("\n%s: unknown the msg type is %d.\n"), g_progname, cm_msg_type_ptr->msg_type);
break;
}
}
if (tryCheckStateFlag) {
(void)cm_client_send_msg(
CmServer_conn, 'C', (char*)&ctl_to_cm_disable_cn_content, sizeof(ctl_to_cm_disable_cn));
checkCNStateCnt--;
(void)sleep(1);
write_stderr(_("."));
wait_time--;
continue;
}
if ((sendQueryCount - getQueryCount) > 3) {
if (checkSendDisableTime > 0) {
checkSendDisableTime--;
(void)sleep(1);
write_stderr(_("."));
wait_time--;
continue;
} else {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
do_conn_cmserver(false, 0);
if (CmServer_conn != NULL) {
write_stderr(_("\n%s: will send disable msg again.\n"), g_progname);
(void)cm_client_send_msg(
CmServer_conn, 'C', (char*)&ctl_to_cm_disable_cn_content, sizeof(ctl_to_cm_disable_cn));
}
checkSendDisableTime = 3;
sendQueryCount = 0;
getQueryCount = 0;
tryFlag = true;
(void)sleep(1);
write_stderr(_("."));
wait_time--;
continue;
}
}
if (success) {
break;
}
cm_ctl_cm_query_content.msg_type = (int)MSG_CTL_CM_QUERY;
cm_ctl_cm_query_content.node = g_commandOperationNodeId;
cm_ctl_cm_query_content.instanceId = instanceId;
cm_ctl_cm_query_content.instance_type = instance_type;
cm_ctl_cm_query_content.wait_seconds = DEFAULT_WAIT;
if (CmServer_conn != NULL) {
(void)cm_client_send_msg(
CmServer_conn, 'C', (char*)&cm_ctl_cm_query_content, sizeof(cm_ctl_cm_query_content));
}
sendQueryCount++;
wait_time--;
if (wait_time <= 0) {
break;
}
write_stderr(_("."));
(void)sleep(1);
}
if (wait_time <= 0) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
write_stderr(_("\n%s: disable coordinator %u command timeout.\n"), g_progname, instanceId);
return -3;
}
write_stderr(_("\n%s: disable coordinator %u successfully.\n"), g_progname, instanceId);
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return 0;
}
static status_t GetCmsBuildStepResult()
{
int waitTime = BUILD_CMS_TIMEOUT;
char *receiveMsg = NULL;
cm_to_ctl_command_ack *cmsAckPtr;
for (;;) {
if (CmServer_conn != NULL) {
if (cm_client_flush_msg(CmServer_conn) == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION_WITHOUT_EXITCODE((CmServer_conn));
}
receiveMsg = recv_cm_server_cmd(CmServer_conn);
}
if (receiveMsg != NULL) {
const cm_msg_type *type = reinterpret_cast<cm_msg_type *>(reinterpret_cast<void *>(receiveMsg));
switch (type->msg_type) {
case MSG_CM_CTL_BACKUP_OPEN:
write_runlog(ERROR, "disable build cms in recovery mode.\n");
return CM_ERROR;
case MSG_CM_CTL_COMMAND_ACK:
cmsAckPtr = reinterpret_cast<cm_to_ctl_command_ack *>(reinterpret_cast<void *>(receiveMsg));
if (cmsAckPtr->isCmsBuildStepSuccess) {
return CM_SUCCESS;
}
return CM_ERROR;
default:
break;
}
}
cm_sleep(1);
waitTime--;
write_runlog(LOG, ".");
if (waitTime <= 0) {
break;
}
}
write_runlog(DEBUG1, "the step of cms build timeout.\n");
return CM_ERROR;
}
static bool IsCmsStatusNormal(uint32 nodeIndex)
{
CM_Conn *conn = NULL;
do_conn_cmserver(true, nodeIndex, false, &conn);
if (conn != NULL) {
CMPQfinish(conn);
return true;
}
return false;
}
static status_t NotifyCmsBuild(ctl_to_cm_build &buildMsg, const CmsBuildStep &step)
{
buildMsg.cmsBuildStep = step;
if (cm_client_send_msg(CmServer_conn, 'C', (char*)&buildMsg, sizeof(buildMsg)) != 0) {
write_runlog(DEBUG1, "send step(%d) of cms build node(%u) msg to cms failed.\n", (int)step, buildMsg.node);
return CM_ERROR;
}
if (GetCmsBuildStepResult() != CM_SUCCESS) {
write_runlog(DEBUG1, "the step(%d) of cms build node(%u) failed.\n", (int)step, buildMsg.node);
return CM_ERROR;
}
write_runlog(DEBUG1, "the step(%d) of cms build node(%u) success.\n", (int)step, buildMsg.node);
return CM_SUCCESS;
}
static status_t SendBuildCmsMsgAndGetAck(uint32 nodeIndex, ctl_to_cm_build &buildMsg)
{
if (IsCmsPrimary(&g_node[nodeIndex])) {
write_runlog(LOG, "The node(%u) is primary, can't do build cms.\n", g_node[nodeIndex].node);
return CM_ERROR;
}
if (IsCmsStatusNormal(nodeIndex)) {
write_runlog(LOG, "The node(%u) cms is normal, can't do build cms.\n", g_node[nodeIndex].node);
return CM_ERROR;
}
buildMsg.msg_type = (int)MSG_CTL_CM_BUILD;
buildMsg.node = g_node[nodeIndex].node;
if (NotifyCmsBuild(buildMsg, CMS_BUILD_LOCK) == CM_ERROR) {
return CM_ERROR;
}
if (NotifyCmsBuild(buildMsg, CMS_BUILD_DOING) == CM_ERROR) {
return CM_ERROR;
}
if (NotifyCmsBuild(buildMsg, CMS_BUILD_UNLOCK) == CM_ERROR) {
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t DoCmsBuild(ctl_to_cm_build &buildMsg)
{
uint32 buildNode = (g_commandOperationNodeId != 0) ? g_commandOperationNodeId : g_currentNode->node;
if (g_dn_replication_num != PRIMARY_STANDBY_MODE) {
write_runlog(LOG, "build -c only used in primary-standby mode, can't do build cms.\n");
return CM_ERROR;
}
for (uint32 i = 0; i < g_cm_server_num; ++i) {
if (g_node[g_nodeIndexForCmServer[i]].node == buildNode) {
return SendBuildCmsMsgAndGetAck(g_nodeIndexForCmServer[i], buildMsg);
}
}
write_runlog(LOG, "node(%u) have no cms, can't do build cms.\n", buildNode);
return CM_ERROR;
}
void SendQuery(uint32 instanceId, int instanceType)
{
ctl_to_cm_query queryMsg = {0};
queryMsg.msg_type = (int)MSG_CTL_CM_QUERY;
queryMsg.node = g_commandOperationNodeId;
queryMsg.instanceId = instanceId;
queryMsg.instance_type = instanceType;
queryMsg.wait_seconds = g_waitSeconds;
queryMsg.relation = 0;
if (CmServer_conn != NULL) {
(void)cm_client_send_msg(CmServer_conn, 'C', (char*)&queryMsg, sizeof(queryMsg));
}
return;
}
static bool CheckBuildCond(int32 localRole)
{
return (localRole == INSTANCE_ROLE_STANDBY || localRole == INSTANCE_ROLE_CASCADE_STANDBY);
}
int DoBuild(const CtlOption *ctx)
{
CtlGetCmJsonConf();
if (g_enableSharedStorage) {
write_runlog(LOG, "in shared storage mode, can't do cm_ctl build.\n");
return 0;
}
int waitTime = BUILD_DN_TIMEOUT;
int instanceType = 0;
int getQueryCount = 0;
int dnRoleAbnormal = 0;
int sendQueryCount = 0;
int checkSendBuildTime = 3;
bool tryFlag = false;
bool success;
bool sendBuildFlag = false;
char *receiveMsg = NULL;
uint32 instanceId = 0;
cm_msg_type *msgType = NULL;
ctl_to_cm_build buildMsg = {0};
cm_to_ctl_command_ack *commandAckPtr = NULL;
cm_to_ctl_instance_status instStatusPtr = {0};
cm_to_ctl_instance_status_ipv4 *instStatusPtrIpv4 = NULL;
errno_t rc;
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(ERROR, "send build msg to cm_server, connect fail, node_id:%u, data_path:%s.\n",
ctx->comm.nodeId,
g_cmData);
return -1;
}
if (ctx->build.isNeedCmsBuild) {
if (DoCmsBuild(buildMsg) != CM_SUCCESS) {
write_runlog(LOG, "cm_ctl build cms failed.\n");
FINISH_CONNECTION((CmServer_conn), -1);
}
write_runlog(LOG, "cm_ctl build cms success.\n");
FINISH_CONNECTION((CmServer_conn), 0);
}
write_runlog(DEBUG1, "send build msg to cm_server, node_id:%u, data_path:%s.\n", ctx->comm.nodeId, g_cmData);
if (FindInstanceIdAndType(ctx->comm.nodeId, g_cmData, &instanceId, &instanceType) != 0) {
write_runlog(ERROR, "can't find the node_id:%u, data_path:%s.\n", ctx->comm.nodeId, g_cmData);
return -1;
}
buildMsg.msg_type = (int)MSG_CTL_CM_BUILD;
buildMsg.node = ctx->comm.nodeId;
buildMsg.instanceId = instanceId;
buildMsg.full_build = ctx->build.doFullBuild;
buildMsg.parallel = ctx->build.parallel;
if (wait_seconds_set) {
buildMsg.wait_seconds = g_waitSeconds;
waitTime = g_waitSeconds;
} else {
buildMsg.wait_seconds = DEFAULT_WAIT * 60 * 2;
waitTime = DEFAULT_WAIT * 60 * 2;
}
if (do_force == 1) {
buildMsg.force_build = CM_CTL_FORCE_BUILD;
} else {
buildMsg.force_build = CM_CTL_UNFORCE_BUILD;
}
if (cm_client_send_msg(CmServer_conn, 'C', (char*)&buildMsg, sizeof(ctl_to_cm_build)) != 0) {
FINISH_CONNECTION((CmServer_conn), -1);
}
success = false;
for (;;) {
if (CmServer_conn != NULL) {
if (cm_client_flush_msg(CmServer_conn) == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION_WITHOUT_EXITCODE((CmServer_conn));
}
receiveMsg = recv_cm_server_cmd(CmServer_conn);
}
if (receiveMsg != NULL) {
msgType = (cm_msg_type*)receiveMsg;
switch (msgType->msg_type) {
case MSG_CM_CTL_COMMAND_ACK:
commandAckPtr = (cm_to_ctl_command_ack*)receiveMsg;
if ((commandAckPtr->command_result == CM_ANOTHER_COMMAND_RUNNING) && !tryFlag) {
write_runlog(ERROR, "another command(%d) is running.\n", commandAckPtr->pengding_command);
FINISH_CONNECTION((CmServer_conn), -1);
} else if (commandAckPtr->command_result == CM_INVALID_COMMAND) {
write_runlog(ERROR, "can not build at current role.\n");
FINISH_CONNECTION((CmServer_conn), -1);
} else if (commandAckPtr->command_result == CM_INVALID_PRIMARY_TERM) {
write_runlog(ERROR, "can not build, primary term is invalid.\n");
FINISH_CONNECTION((CmServer_conn), -1);
} else if (commandAckPtr->command_result == CM_DN_NORMAL_STATE) {
write_runlog(LOG, "build successfully.\n");
FINISH_CONNECTION((CmServer_conn), 0);
}
sendBuildFlag = true;
break;
case MSG_CM_CTL_DATA:
getQueryCount++;
if (undocumentedVersion !=0 && undocumentedVersion < SUPPORT_IPV6_VERSION) {
instStatusPtrIpv4 = (cm_to_ctl_instance_status_ipv4*)receiveMsg;
CmToCtlInstanceStatusV1ToV2(instStatusPtrIpv4, &instStatusPtr);
} else {
rc = memcpy_s(&instStatusPtr,
sizeof(cm_to_ctl_instance_status),
receiveMsg,
sizeof(cm_to_ctl_instance_status));
securec_check_errno(rc, (void)rc);
}
if (instStatusPtr.instance_type == INSTANCE_TYPE_GTM) {
if (instStatusPtr.gtm_member.local_status.local_role == INSTANCE_ROLE_STANDBY) {
success = true;
}
} else if (instStatusPtr.instance_type == INSTANCE_TYPE_DATANODE) {
if ((CheckBuildCond(instStatusPtr.data_node_member.local_status.local_role)) &&
(instStatusPtr.data_node_member.local_status.db_state == INSTANCE_HA_STATE_NORMAL)) {
success = true;
}
if ((instStatusPtr.data_node_member.local_status.local_role == INSTANCE_ROLE_UNKNOWN) &&
(instStatusPtr.data_node_member.local_status.db_state == INSTANCE_HA_STATE_BUILD_FAILED)) {
write_runlog(ERROR,
"build failed, please refer to the log of cm_agent(nodeid:%u) for detailed reasons.\n",
ctx->comm.nodeId);
FINISH_CONNECTION((CmServer_conn), -1);
}
if (!CheckBuildCond(instStatusPtr.data_node_member.local_status.local_role) &&
instStatusPtr.data_node_member.local_status.db_state != INSTANCE_HA_STATE_BUILDING) {
dnRoleAbnormal++;
} else {
dnRoleAbnormal = 0;
}
if (dnRoleAbnormal > MAX_INSTANCE_ROLE_ABNORMAL_TIMES) {
if (instStatusPtr.data_node_member.local_status.db_state ==
INSTANCE_HA_STATE_MANUAL_STOPPED) {
write_runlog(ERROR, "build failed, instance is stopped.\n");
} else {
write_runlog(ERROR, "build failed, instance role is not standby or cascade standby.\n");
}
FINISH_CONNECTION((CmServer_conn), -1);
}
}
break;
case MSG_CM_BUILD_DOING:
getQueryCount++;
break;
case MSG_CM_BUILD_DOWN:
write_runlog(ERROR, "rm -f the cm instance manual start file failed and quit.\n");
return -1;
case MSG_CM_CTL_BACKUP_OPEN:
write_runlog(ERROR, "disable do build in recovery mode.\n");
FINISH_CONNECTION((CmServer_conn), -1);
default:
write_runlog(ERROR, "unknown the msg type is %d.\n", msgType->msg_type);
break;
}
}
if (!sendBuildFlag || (sendQueryCount - getQueryCount) > 3) {
if (checkSendBuildTime > 0) {
checkSendBuildTime--;
(void)sleep(1);
write_runlog(LOG, ".");
waitTime--;
continue;
} else {
FINISH_CONNECTION_WITHOUT_EXITCODE((CmServer_conn));
do_conn_cmserver(false, 0);
if ((CmServer_conn != NULL) && !sendBuildFlag) {
write_runlog(LOG, "will send build msg again.\n");
(void)cm_client_send_msg(CmServer_conn, 'C', (char*)&buildMsg, sizeof(ctl_to_cm_build));
}
checkSendBuildTime = 3;
sendQueryCount = 0;
getQueryCount = 0;
tryFlag = true;
(void)sleep(1);
write_runlog(LOG, ".");
waitTime--;
continue;
}
}
if (success) {
break;
}
SendQuery(instanceId, instanceType);
sendQueryCount++;
write_runlog(LOG, ".");
(void)sleep(1);
waitTime--;
if (waitTime <= 0) {
break;
}
}
if (waitTime <= 0) {
write_runlog(ERROR,
"build command timeout!\n\n"
"HINT: Maybe the build action is continually running in the background.\n"
"You can wait for a while and check the status of current cluster using "
"\"cm_ctl query -Cv\".\n");
FINISH_CONNECTION_WITHOUT_EXITCODE((CmServer_conn));
return -3;
}
FINISH_CONNECTION_WITHOUT_EXITCODE((CmServer_conn));
(void)sleep(6);
write_runlog(LOG, "build successfully.\n");
return 0;
}
int do_setmode()
{
cm_msg_type msgsetmode;
int ret;
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(ERROR, "send mode change msg to cm_server, connect fail node_id:%u, data_path:%s.\n",
g_commandOperationNodeId,
g_cmData);
return -1;
}
msgsetmode.msg_type = (int)MSG_CTL_CM_SETMODE;
ret = cm_client_send_msg(CmServer_conn, 'C', (char*)&msgsetmode, sizeof(msgsetmode));
if (ret != 0) {
FINISH_CONNECTION((CmServer_conn), -1);
}
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION((CmServer_conn), -1);
}
char *receive_msg = recv_cm_server_cmd(CmServer_conn);
if (receive_msg != NULL) {
cm_msg_type* cm_msg_type_ptr = (cm_msg_type *)receive_msg;
if (cm_msg_type_ptr->msg_type == (int)MSG_CM_CTL_SETMODE_ACK) {
write_runlog(WARNING, "Postupgrade mode has been set.\n");
} else {
write_runlog(ERROR, "unknown the msg type is %d.\n", cm_msg_type_ptr->msg_type);
FINISH_CONNECTION((CmServer_conn), -1);
}
}
write_runlog(LOG, "new mode set successfully.\n");
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return 0;
}
static int do_hotpatch_cmserver(const char* command, const char* path, uint32 nodeid)
{
int wait_time;
cm_hotpatch_msg msg_hotpatch;
int ret;
char* ret_msg = NULL;
do_conn_cmserver(true, nodeid);
if (CmServer_conn1 == NULL) {
write_runlog(LOG, "cm_server[%s]\n[PATCH-ERROR] Connection ERR.\n", g_node[nodeid].nodeName);
return -1;
}
msg_hotpatch.msg_type = (int)MSG_CTL_CM_HOTPATCH;
ret = snprintf_s(msg_hotpatch.command, MAX_LENGTH_HP_CMD, MAX_LENGTH_HP_CMD - 1, "%s", command);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(msg_hotpatch.path, MAX_LENGTH_HP_PATH, MAX_LENGTH_HP_PATH - 1, "%s", path);
securec_check_intval(ret, (void)ret);
ret = cm_client_send_msg(CmServer_conn1, 'C', (char*)&msg_hotpatch, sizeof(msg_hotpatch));
if (ret != 0) {
CMPQfinish(CmServer_conn1);
CmServer_conn1 = NULL;
return -1;
}
ret = cm_client_flush_msg(CmServer_conn1);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
CMPQfinish(CmServer_conn1);
CmServer_conn1 = NULL;
return -1;
}
for (wait_time = g_waitSeconds * 1000; wait_time > 0; wait_time--) {
CmSleep(1);
ret_msg = recv_cm_server_cmd(CmServer_conn1);
if (ret_msg != NULL) {
write_runlog(LOG, "cm_server[%s]\n%s\n", g_node[nodeid].nodeName, ret_msg);
break;
}
}
if (ret_msg == NULL) {
write_runlog(LOG, "cm_server[%s]\n[PATCH-ERROR] TIMEOUT ERR.\n", g_node[nodeid].nodeName);
}
CMPQfinish(CmServer_conn1);
CmServer_conn1 = NULL;
return 0;
}
int do_hotpatch(const char* command, const char* path)
{
for (uint32 kk = 0; kk < g_cm_server_num; kk++) {
uint32 cm_server_node_index = g_nodeIndexForCmServer[kk];
(void)do_hotpatch_cmserver(command, path, cm_server_node_index);
}
return 0;
}
void set_mode(const char* modeopt)
{
if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0) {
shutdown_mode_num = FAST_MODE;
} else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0) {
shutdown_mode_num = IMMEDIATE_MODE;
} else if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0) {
shutdown_mode_num = SMART_MODE;
#ifdef ENABLE_MULTIPLE_NODES
} else if (strcmp(modeopt, "r") == 0 || strcmp(modeopt, "resume") == 0) {
shutdown_mode_num = RESUME_MODE;
cn_resumes_restart = true;
#endif
} else {
write_runlog(FATAL, "unrecognized shutdown mode \"%s\"\n", modeopt);
DoAdvice();
exit(1);
}
}
int DoSetRunMode(void)
{
char cmd[MAXPGPATH] = {0};
int rc = 0;
if (g_dcfXMode == NULL) {
write_runlog(ERROR, "g_dcfXMode is NULL.\n");
return 1;
}
if (strcasecmp(g_dcfXMode, "minority") == 0) {
rc = snprintf_s(cmd, MAXPGPATH,
MAXPGPATH - 1,
SYSTEMQUOTE "%s setrunmode -D %s --xmode=%s --votenum=%d" SYSTEMQUOTE,
PG_CTL_NAME,
g_cmData, g_dcfXMode, g_dcfVoteNum);
} else if (strcasecmp(g_dcfXMode, "normal") == 0) {
rc = snprintf_s(cmd,
MAXPGPATH,
MAXPGPATH - 1,
SYSTEMQUOTE "%s setrunmode -D %s --xmode=%s" SYSTEMQUOTE,
PG_CTL_NAME,
g_cmData, g_dcfXMode);
} else {
write_runlog(LOG, "set datanode run mode, unexpected xmode:(%s).\n", g_dcfXMode);
return 1;
}
securec_check_intval(rc, (void)rc);
write_runlog(DEBUG1, "set datanode run mode, cmd:%s.\n", cmd);
if (g_commandOperationNodeId == g_currentNode->node) {
write_runlog(LOG, "set datanode run mode on current node(%u).\n", g_commandOperationNodeId);
rc = system(cmd);
} else {
uint32 i;
for (i = 0; i < g_node_num; i++) {
if (g_node[i].node == g_commandOperationNodeId) {
break;
}
}
if (i < g_node_num) {
write_runlog(
LOG, "set datanode run mode on remote node: %s(%u).\n", g_node[i].nodeName, g_commandOperationNodeId);
rc = SshExec(&g_node[i], cmd);
} else {
write_runlog(
ERROR, "Could not find the node in the cluster by the node id %u.\n", g_commandOperationNodeId);
return 1;
}
}
if (rc != 0) {
write_runlog(ERROR, "set datanode run mode failed, gs_ctl return code: %d, errno=%d.\n",
SHELL_RETURN_CODE(rc), errno);
return SHELL_RETURN_CODE(rc);
}
write_runlog(LOG, "set datanode run mode success.\n");
return 0;
}
int DoGsCtlCommand(const char *commond, const char *cmdName)
{
uint32 i = 0;
int rc;
char gausshomePath[CM_PATH_LENGTH] = {0};
int result = 1;
char cmd[CM_PATH_LENGTH] = {0};
rc = GetHomePath(gausshomePath, sizeof(gausshomePath));
if (rc != EOK) {
return 1;
}
if (g_commandOperationNodeId == g_currentNode->node && strstr(gausshomePath, "/var/chroot") == NULL) {
rc = snprintf_s(cmd, CM_PATH_LENGTH, CM_PATH_LENGTH - 1,
SYSTEMQUOTE "%s -D %s -t %d \n echo -e $? > %s" SYSTEMQUOTE,
commond, g_cmData, g_waitSeconds, result_path);
securec_check_intval(rc, (void)rc);
write_runlog(LOG, "execute %s on current node(%u).\n", cmdName, g_commandOperationNodeId);
exec_system(cmd, &result, result_path);
} else {
for (i = 0; i < g_node_num; i++) {
if (g_node[i].node == g_commandOperationNodeId) {
break;
}
}
if (i < g_node_num) {
rc = snprintf_s(cmd, CM_PATH_LENGTH, CM_PATH_LENGTH - 1,
SYSTEMQUOTE "%s -D %s -t %d\" > /dev/null 2>&1; echo -e $? > %s" SYSTEMQUOTE,
commond, g_cmData, g_waitSeconds, result_path);
securec_check_intval(rc, (void)rc);
write_runlog(LOG, "execute %s on remote node: %s(%u).\n",
cmdName, g_node[i].nodeName, g_commandOperationNodeId);
exec_system_ssh(g_commandOperationNodeId - 1, cmd, &result, result_path, mpp_env_separate_file);
} else {
write_runlog(
ERROR, "Could not find the node in the cluster by the node id %u.\n", g_commandOperationNodeId);
return 1;
}
}
write_runlog(DEBUG1, "execute %s, cmd:%s.\n", cmdName, cmd);
return result;
}
int CalcDcfVoterNum(const cm_to_ctl_instance_status* cmToCtlInstanceStatusPtr, int *voteNum)
{
uint32 i;
uint32 j;
uint32 nodeIndex = 0;
int role = 0;
for (i = 0; i < g_node_num; i++) {
if (g_node[i].node == cmToCtlInstanceStatusPtr->node) {
nodeIndex = i;
break;
}
}
if (i >= g_node_num) {
write_runlog(ERROR, "can't find the node(%u).", cmToCtlInstanceStatusPtr->node);
return -1;
}
if (g_cm_server_num > CM_PRIMARY_STANDBY_NUM) {
write_runlog(ERROR, "the number of cm_server is bigger than %d.\n", CM_PRIMARY_STANDBY_NUM);
return -1;
}
if (cmToCtlInstanceStatusPtr->instance_type == INSTANCE_TYPE_DATANODE) {
for (j = 0; j < g_node[nodeIndex].datanodeCount; j++) {
if (g_node[nodeIndex].datanode[j].datanodeId == cmToCtlInstanceStatusPtr->instanceId) {
break;
}
}
if (j >= g_node[nodeIndex].datanodeCount) {
write_runlog(ERROR, "can't find the instance(%u).", cmToCtlInstanceStatusPtr->instanceId);
return -1;
}
role = cmToCtlInstanceStatusPtr->data_node_member.receive_status.local_role;
if (role == DCF_ROLE_LEADER || role == DCF_ROLE_LOGGER || role == DCF_ROLE_FOLLOWER) {
(*voteNum)++;
}
}
return 0;
}
int ProcessRecvMsg(int *voterNum)
{
char *receiveMsg = NULL;
cm_msg_type *cmMsgTypePtr = NULL;
cm_to_ctl_instance_status cmToCtlInstanceStatusPtr = {0};
const int microSecond = 1000;
int voterDnNum = 0;
int ret;
int waitTime = g_waitSeconds * microSecond;
bool recDataEnd = false;
for (; waitTime > 0;) {
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
break;
}
receiveMsg = recv_cm_server_cmd(CmServer_conn);
while (receiveMsg != NULL) {
cmMsgTypePtr = (cm_msg_type *)receiveMsg;
switch (cmMsgTypePtr->msg_type) {
case MSG_CM_CTL_DATA_BEGIN:
case MSG_CM_CTL_NODE_END:
break;
case MSG_CM_CTL_DATA:
GetCtlInstanceStatusFromRecvMsg(receiveMsg, &cmToCtlInstanceStatusPtr);
if (CalcDcfVoterNum(&cmToCtlInstanceStatusPtr, &voterDnNum) != 0) {
return -1;
}
break;
case MSG_CM_CTL_DATA_END:
recDataEnd = true;
break;
default:
write_runlog(ERROR, "unknown the msg type is %d.\n", cmMsgTypePtr->msg_type);
break;
}
receiveMsg = recv_cm_server_cmd(CmServer_conn);
}
CmSleep(1);
waitTime--;
if (recDataEnd || waitTime <= 0) {
break;
}
}
*voterNum = voterDnNum;
if (ret != 0 || waitTime <= 0) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
write_runlog(ERROR, "send query msg to cm_server failed.\n");
return -1;
}
return 0;
}
int DoQueryInner(int *voterNum)
{
ctl_to_cm_query cmCtlCmQueryContent;
int voterNodeNum = 0;
int ret;
if (g_cm_server_num > CM_PRIMARY_STANDBY_NUM) {
write_runlog(ERROR, "the number of cm_server is bigger than %d.\n", CM_PRIMARY_STANDBY_NUM);
exit(1);
}
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(ERROR, "can't connect to cm_server.\n"
"Maybe cm_server is not running, or timeout expired. Please try again.\n");
return -1;
}
cmCtlCmQueryContent.msg_type = (int)MSG_CTL_CM_QUERY;
cmCtlCmQueryContent.node = INVALID_NODE_NUM;
cmCtlCmQueryContent.relation = 0;
cmCtlCmQueryContent.instanceId = INVALID_INSTACNE_NUM;
cmCtlCmQueryContent.wait_seconds = g_waitSeconds;
cmCtlCmQueryContent.detail = CLUSTER_DETAIL_STATUS_QUERY;
ret = cm_client_send_msg(CmServer_conn, 'C', (char*)&cmCtlCmQueryContent, sizeof(cmCtlCmQueryContent));
if (ret != 0) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return -1;
}
CmSleep(1);
if (ProcessRecvMsg(&voterNodeNum) != 0) {
return -1;
}
*voterNum = voterNodeNum;
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
return 0;
}
int PreCondCheck(void)
{
const int minVoterNum = 3;
int voterCount = 0;
if (DoQueryInner(&voterCount) != 0) {
write_runlog(ERROR, "Dcf role query error.\n");
return 1;
}
if (voterCount <= minVoterNum) {
write_runlog(ERROR, "Operation is invalid, voter role node should be more than 3.\n");
return 1;
}
return 0;
}
static status_t DoCheck(const CtlOption *ctx)
{
const int errcode = -2;
if (ctx->comm.nodeId == 0 || ctx->comm.dataPath[0] == '\0') {
write_runlog(ERROR, "unexpected arg (node_id:%u) (data:%s).\n", ctx->comm.nodeId, ctx->comm.dataPath);
return CM_ERROR;
}
if (ctx->dcfOption.group == errcode || ctx->dcfOption.priority == errcode) {
write_runlog(ERROR, "input is invalid\n");
return CM_ERROR;
}
return CM_SUCCESS;
}
static int DoCheckRole(const DcfOption *ctx)
{
if (ctx->role == NULL) {
return 1;
}
if (strcasecmp(ctx->role, "passive") != 0 && strcasecmp(ctx->role, "follower") != 0) {
write_runlog(ERROR, "error, unexpected role :(%s).\n", ctx->role);
return -1;
}
if (strcasecmp(ctx->role, "passive") == 0 && PreCondCheck() != 0) {
write_runlog(ERROR, "You can execute \"cm_ctl query -v\" and check dcf_role.\n");
return -1;
}
return 0;
}
char *DoConcatCmd(const CtlOption *ctx)
{
char tmp[CM_PATH_LENGTH] = {0};
char *cmd = (char *)malloc(CM_PATH_LENGTH);
if (cmd == NULL) {
write_runlog(ERROR, "error, cmd is NULL.\n");
return NULL;
}
int rc = memset_s(cmd, CM_PATH_LENGTH, 0, CM_PATH_LENGTH);
securec_check_errno(rc, (void)rc);
if (DoCheckRole(&ctx->dcfOption) == -1) {
free(cmd);
return NULL;
}
if (DoCheckRole(&ctx->dcfOption) == 0) {
rc = snprintf_s(tmp, CM_PATH_LENGTH, CM_PATH_LENGTH - 1, "-R %s ", ctx->dcfOption.role);
securec_check_intval(rc, (void)rc);
rc = strcat_s(cmd, CM_PATH_LENGTH, tmp);
securec_check_errno(rc, (void)rc);
}
if (ctx->dcfOption.group >= 0) {
rc = snprintf_s(tmp, CM_PATH_LENGTH, CM_PATH_LENGTH - 1, "-G %d ", ctx->dcfOption.group);
securec_check_intval(rc, (void)rc);
rc = strcat_s(cmd, CM_PATH_LENGTH, tmp);
securec_check_errno(rc, (void)rc);
}
if (ctx->dcfOption.priority >= 0) {
rc = snprintf_s(tmp, CM_PATH_LENGTH, CM_PATH_LENGTH - 1, "--priority %d ", ctx->dcfOption.priority);
securec_check_intval(rc, (void)rc);
rc = strcat_s(cmd, CM_PATH_LENGTH, tmp);
securec_check_errno(rc, (void)rc);
}
return cmd;
}
int DoChangeMember(const CtlOption *ctx)
{
int result;
int errTimeout = 2;
char command[CM_PATH_LENGTH] = {0};
char cmdName[CM_PATH_LENGTH] = "changemember";
if (DoCheck(ctx) == CM_ERROR) {
return 1;
}
char *tmp = DoConcatCmd(ctx);
if (tmp == NULL) {
write_runlog(ERROR, "error, command is NULL.\n");
return 1;
}
int rc = snprintf_s(command, CM_PATH_LENGTH, CM_PATH_LENGTH - 1, "%s member -O change %s", PG_CTL_NAME, tmp);
securec_check_intval(rc, (void)rc);
result = DoGsCtlCommand(command, cmdName);
FREE_AND_RESET(tmp);
if (result == 0) {
write_runlog(LOG, "execute changemember successfully.\n");
} else if (result == 1) {
write_runlog(ERROR, "execute changemember failed, you can check the gs_ctl log.\n");
} else if (result == errTimeout) {
write_runlog(ERROR, "execute changemember timeout.\n");
} else {
write_runlog(ERROR, "unexpect execute result code: %d.\n", result);
}
return result;
}
int DoChangeRole(const CtlOption *ctx)
{
int result;
int errTimeout = 2;
int rc;
char command[CM_PATH_LENGTH] = {0};
char cmdName[CM_PATH_LENGTH] = "changeRole";
if (g_commandOperationNodeId == 0 || g_cmData[0] == '\0' || strlen(ctx->dcfOption.role) == 0) {
write_runlog(ERROR, "unexpected arg (node_id:%u) (data:%s) (role:%s).\n",
g_commandOperationNodeId, g_cmData, ctx->dcfOption.role);
return 1;
}
if (strcasecmp(ctx->dcfOption.role, "passive") != 0 && strcasecmp(ctx->dcfOption.role, "follower") != 0) {
write_runlog(ERROR, "error, unexpected role :(%s).\n", ctx->dcfOption.role);
return 1;
}
if (strcasecmp(ctx->dcfOption.role, "passive") == 0 && PreCondCheck() != 0) {
write_runlog(ERROR, "You can execute \"cm_ctl query -v\" and check dcf_role.\n");
return 1;
}
rc = snprintf_s(
command, CM_PATH_LENGTH, CM_PATH_LENGTH - 1, "%s changerole -R %s ", PG_CTL_NAME, ctx->dcfOption.role);
securec_check_intval(rc, (void)rc);
result = DoGsCtlCommand(command, cmdName);
if (result == 0) {
write_runlog(LOG, "execute change dcf role successfully.\n");
} else if (result == 1) {
write_runlog(ERROR, "execute change dcf role failed, you can check the gs_ctl log.\n");
} else if (result == errTimeout) {
write_runlog(ERROR, "execute change dcf timeout.\n");
} else {
write_runlog(ERROR, "unexpect execute result code: %d.\n", result);
}
return result;
}
int DoReload()
{
int ret;
CtlToCMReload ctlToCMReloadContent = {0};
cm_msg_type* cm_msg_type_ptr = NULL;
CMToCtlReloadAck* reloadAckMsg = NULL;
int waitTime = RELOAD_WAIT_TIME;
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(ERROR, "send reload msg to cm_server, connect fail.\n");
return -1;
}
ctlToCMReloadContent.msgType = (int)MSG_CTL_CM_RELOAD;
ret = cm_client_send_msg(CmServer_conn, 'C', (char*)&ctlToCMReloadContent, sizeof(CtlToCMReload));
if (ret != 0) {
FINISH_CONNECTION((CmServer_conn), -1);
}
for (;;) {
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION((CmServer_conn), -1);
}
char *receive_msg = recv_cm_server_cmd(CmServer_conn);
if (receive_msg != NULL) {
cm_msg_type_ptr = (cm_msg_type*)receive_msg;
if (cm_msg_type_ptr->msg_type == (int)MSG_CM_CTL_RELOAD_ACK) {
reloadAckMsg = (CMToCtlReloadAck *)receive_msg;
if (reloadAckMsg->reloadOk && (KillAllCms(false) == CM_SUCCESS)) {
write_runlog(LOG, "cm_ctl reload success.\n");
FINISH_CONNECTION((CmServer_conn), 0);
} else {
write_runlog(LOG, "cm_ctl reload failed.\n");
FINISH_CONNECTION((CmServer_conn), -1);
}
} else {
write_runlog(ERROR, "unknown the msg type is %d.\n", cm_msg_type_ptr->msg_type);
}
}
waitTime--;
if (waitTime <= 0) {
break;
}
write_runlog(LOG, ".");
(void)sleep(1);
}
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
if (waitTime <= 0) {
write_runlog(LOG, "execute cm_ctl reload command timeout.\n");
return -1;
}
return 0;
}
static void SetNodeInstBaseInfo(NodeInstBaseInfo *info, uint32 nodeIdx, uint32 instIdx)
{
info->nodeIdx = nodeIdx;
info->instIdx = instIdx;
}
int FindInstanceByInstId(uint32 instId, Instance *inst)
{
for (uint32 nodeIdx = 0; nodeIdx < g_node_num; nodeIdx++) {
staticNodeConfig *curNode = &g_node[nodeIdx];
if (curNode->gtm == 1) {
if (curNode->gtmId == instId) {
inst->instType = INST_TYPE_GTM;
inst->node = curNode->node;
inst->InstNode = curNode;
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, 0);
return 0;
}
}
if (curNode->coordinate == 1) {
if (curNode->coordinateId == instId) {
inst->instType = INST_TYPE_CN;
inst->node = curNode->node;
inst->InstNode = curNode;
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, 0);
return 0;
}
}
if (curNode->cmServerLevel == 1) {
if (curNode->cmServerId == instId) {
inst->instType = INST_TYPE_CMSERVER;
inst->node = curNode->node;
inst->InstNode = curNode;
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, 0);
return 0;
}
}
for (uint32 i = 0; i < curNode->datanodeCount; i++) {
if (curNode->datanode[i].datanodeId == instId) {
inst->instType = INST_TYPE_DN;
inst->node = curNode->node;
inst->dnInst = &curNode->datanode[i];
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, i);
return 0;
}
}
}
write_runlog(FATAL, "can't find instance by instanceId: %u.\n", instId);
return -1;
}
const char *GetInstTypeStr(InstanceType type)
{
switch (type) {
case INST_TYPE_CMSERVER:
return "CM_SERVER";
case INST_TYPE_GTM:
return "GTM";
case INST_TYPE_CN:
return "COORDINATOR";
case INST_TYPE_DN:
return "DATANODE";
case INST_TYPE_FENCED_UDF:
return "UDF";
case INST_TYPE_INIT:
default:
return "UNKNOWN";
}
}
static status_t SetCmsPromoteModeCore(const Instance *inst, PromoteMode pMode)
{
if (inst->instType != INST_TYPE_CMSERVER) {
write_runlog(FATAL, "'we only support cm_server force promote but pointed instance's role is %s.\n",
GetInstTypeStr(inst->instType));
return CM_ERROR;
}
char cmsPModeFile[MAXPGPATH] = {0};
errno_t rcs =
snprintf_s(cmsPModeFile, sizeof(cmsPModeFile), sizeof(cmsPModeFile) - 1, "%s/bin/promote_mode_cms", g_appPath);
securec_check_intval(rcs, (void)rcs);
char command[MAXPGPATH];
int ret;
switch (pMode) {
case PMODE_AUTO:
ret = snprintf_s(command,
sizeof(command),
sizeof(command) - 1,
SYSTEMQUOTE "rm -f %s > \"%s\" 2>&1" SYSTEMQUOTE,
cmsPModeFile,
DEVNULL);
break;
case PMODE_FORCE_PRIMAYR:
default:
ret = snprintf_s(command,
sizeof(command),
sizeof(command) - 1,
SYSTEMQUOTE "echo %d > %s; chmod 600 %s" SYSTEMQUOTE,
(int32)pMode,
cmsPModeFile,
cmsPModeFile);
break;
}
securec_check_intval(ret, (void)ret);
write_runlog(LOG, "set CMS promote mode(%d), nodeid: %u, instanceid %u.\n",
(int32)pMode, inst->node, inst->InstNode->cmServerId);
ret = runCmdByNodeId(command, inst->node);
if (ret != 0) {
write_runlog(DEBUG1, "Failed to set CMS promote mode with executing the command: command=\"%s\","
" nodeId=%u, systemReturn=%d, shellReturn=%d, errno=%d.\n",
command, inst->node, ret, SHELL_RETURN_CODE(ret), errno);
return CM_ERROR;
}
write_runlog(LOG, "set CMS promote mode successfully.\n");
return CM_SUCCESS;
}
static status_t CheckSetCmsPromoteModeParam()
{
if (g_cmsPromoteMode == NULL) {
write_runlog(FATAL, "'--cmsPromoteMode=[AUTO|PRIMARY_F]' is needed.\n");
return CM_ERROR;
}
if (g_commandOperationNodeId != 0 && get_node_index(g_commandOperationNodeId) == INVALID_NODE_NUM) {
write_runlog(FATAL, "'-n $nodeId' value is illegal. \n");
return CM_ERROR;
}
if (g_commandOperationInstanceId == 0) {
write_runlog(FATAL, "'-I $instId' is needed.\n");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t DoSetCmsPromoteMode()
{
if (CheckSetCmsPromoteModeParam() != CM_SUCCESS) {
DoAdvice();
return CM_ERROR;
}
Instance curInst;
errno_t rc = memset_s(&curInst, sizeof(curInst), 0, sizeof(curInst));
securec_check_errno(rc, (void)rc);
if (FindInstanceByInstId(g_commandOperationInstanceId, &curInst) != 0) {
write_runlog(FATAL, "we can't find instance: %u.\n", g_commandOperationInstanceId);
return CM_ERROR;
}
if (g_commandOperationNodeId != 0 && curInst.node != g_commandOperationNodeId) {
write_runlog(FATAL, "'-n'(node:%u) is not same with '-I'(node:%u).\n", g_commandOperationNodeId, curInst.node);
return CM_ERROR;
}
PromoteMode pMode = PMODE_AUTO;
if (strcasecmp(g_cmsPromoteMode, "AUTO") == 0) {
pMode = PMODE_AUTO;
} else if (strcasecmp(g_cmsPromoteMode, "PRIMARY_F") == 0) {
pMode = PMODE_FORCE_PRIMAYR;
} else {
write_runlog(FATAL, "'--cmsPromoteMode' illegal(%s), must be 'AUTO' or 'PRIMARY_F'.\n", g_cmsPromoteMode);
return CM_ERROR;
}
return SetCmsPromoteModeCore(&curInst, pMode);
}
static status_t SendDdbCmdMsgToCms(const char *cmd)
{
errno_t rc;
ExecDdbCmdMsg sendMsg;
write_runlog(DEBUG1, "Sending msg to cm_server to do ddb cmd.\n");
rc = memset_s(sendMsg.cmdLine, DCC_CMD_MAX_LEN, 0, DCC_CMD_MAX_LEN);
securec_check_errno(rc, (void)rc);
sendMsg.msgType = static_cast<int>(MSG_EXEC_DDB_COMMAND);
rc = strcpy_s(sendMsg.cmdLine, DCC_CMD_MAX_LEN, cmd);
securec_check_errno(rc, (void)rc);
if (cm_client_send_msg(CmServer_conn, 'C', (char*)(&sendMsg), sizeof(ExecDdbCmdMsg)) != 0) {
FINISH_CONNECTION_WITHOUT_EXITCODE((CmServer_conn));
write_runlog(ERROR, "ctl send exec ddb cmd msg to cms failed.\n");
(void)printf(_("exec ddb cmd fail.\n"));
return CM_ERROR;
}
return CM_SUCCESS;
}
void DoDccCmd(int argc, char **argv)
{
int ret;
size_t curLen = 0;
char cmd[DCC_CMD_MAX_LEN];
if (argc <= OPTION_POS) {
write_runlog(ERROR, "exec ddb command without param.\n");
return;
}
InitDdbCmdMsgFunc();
for (int i = OPTION_POS; i < argc; ++i) {
size_t optionLen = strlen(argv[i]);
if (optionLen > CM_PATH_LENGTH) {
write_runlog(ERROR, "The option len(%zu) is more than 1k, can't exec the cmd.\n", optionLen);
return;
}
++optionLen;
if ((curLen + optionLen) >= sizeof(cmd)) {
write_runlog(ERROR, "The cmd len is longer than %d, can't exec the cmd.\n", DCC_CMD_MAX_LEN);
return;
}
ret = snprintf_s((cmd + curLen), (sizeof(cmd) - curLen), ((sizeof(cmd) - curLen) - 1),
" %s", argv[i]);
securec_check_intval(ret, (void)ret);
curLen += optionLen;
}
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(LOG, "exec ddb cmd fail, can't connect to cmserver.\n");
return;
}
if (SendDdbCmdMsgToCms(cmd) != CM_SUCCESS) {
return;
}
GetExecCmdResult(argv[OPTION_POS], (int)EXEC_DDB_COMMAND_ACK);
FINISH_CONNECTION_WITHOUT_EXITCODE(CmServer_conn);
return;
}