add feature for vip and readonly check

This commit is contained in:
yanghao 2023-02-28 09:47:49 +08:00
parent 9adc6a3580
commit 6c2b3f625c
77 changed files with 6594 additions and 1252 deletions

View File

@ -21,7 +21,7 @@
* -------------------------------------------------------------------------
*/
#include "cm/cm_elog.h"
#include "cm_ssl_base.h"
#include "cm_text.h"
#include "cm_disk_rw.h"
#include "cm_ddb_adapter.h"
#include "cm_ddb_sharedisk_cmd.h"

View File

@ -213,8 +213,7 @@ void ShowPgThreadWaitStatus(cltPqConn_t* Conn, uint32 index, int instanceType)
return;
}
int DatanodeStatusCheck(
DnStatus *dnStatus, uint32 dataNodeIndex)
int DatanodeStatusCheck(DnStatus *dnStatus, uint32 dataNodeIndex, int32 dnProcess)
{
static uint32 checkDnSql5Timer = g_check_dn_sql5_interval;
checkDnSql5Timer++;
@ -231,7 +230,6 @@ int DatanodeStatusCheck(
/* in case we return 0 without set the db_state. */
reportMsg->local_status.db_state = INSTANCE_HA_STATE_UNKONWN;
int dnProcess = check_one_instance_status(GetDnProcessName(), dataPath, NULL);
if (g_dnConn[dataNodeIndex] == NULL) {
rcs = snprintf_s(gaussdbStatePath, MAXPGPATH, MAXPGPATH - 1, "%s/gaussdb.state", dataPath);
securec_check_intval(rcs, (void)rcs);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2023 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.
* -------------------------------------------------------------------------
*
* cma_libpq_com.cpp
*
* IDENTIFICATION
* src/cm_agent/client_adpts/libpq/cma_libpq_com.cpp
*
* -------------------------------------------------------------------------
*/
#include "cma_libpq_com.h"
#include "cm_elog.h"
int ExecDmlSqlCmd(ResultSetHandle handle, CltResultSet set, cltPqConn_t **conn, const char *sqlCommand,
const SqlCond *sqlCond)
{
uint32 instId = 0;
const char *str = "unknown";
if (sqlCond != NULL) {
instId = sqlCond->instId;
str = sqlCond->str;
}
if (conn == NULL || (*conn) == NULL) {
write_runlog(ERROR, "[%s: %u] cannot execute sqlCommand[%s], bacause conn is NULL.\n", str, instId, sqlCommand);
return -1;
}
cltPqResult_t *nodeResult = Exec((*conn), sqlCommand);
if (nodeResult == NULL) {
write_runlog(ERROR, "[%s: %u] sqlCommands[%s] fail return NULL, errmsg is %s.\n",
str, instId, sqlCommand, ErrorMessage(*conn));
CLOSE_CONNECTION(*conn);
}
if ((ResultStatus(nodeResult) != CLTPQRES_CMD_OK) && (ResultStatus(nodeResult) != CLTPQRES_TUPLES_OK)) {
write_runlog(ERROR, "[%s: %u] sqlCommand[%s] fail ResultStatus=%d, errmsg is %s.\n",
str, instId, sqlCommand, (int32)ResultStatus(nodeResult), ErrorMessage(*conn));
CLEAR_AND_CLOSE_CONNECTION(nodeResult, (*conn));
}
if (handle != NULL) {
if (handle(set, nodeResult, sqlCommand, sqlCond) != 0) {
CLEAR_AND_CLOSE_CONNECTION(nodeResult, (*conn));
}
}
Clear(nodeResult);
return 0;
}

View File

@ -923,22 +923,28 @@ uint32 CheckDiskForLogPath(void)
return percent;
}
int ExecuteSystemCmd(const char *cmd)
int ExecuteSystemCmd(const char *cmd, int32 logLevel, int32 *errCode)
{
int ret = system(cmd);
if (ret == -1) {
write_runlog(ERROR, "Fail to execute command %s, and errno=%d.\n", cmd, errno);
return -1;
// shield error codes 10 (no child processes), it may be much
const int32 noChildProcessesErrCode = 10;
int32 tmpLevel = (errno == noChildProcessesErrCode) ? logLevel : ERROR;
write_runlog(tmpLevel, "Fail to execute command %s, and errno=%d.\n", cmd, errno);
return ERROR_EXECUTE_CMD;
}
if (WIFEXITED(ret)) {
if (WEXITSTATUS(ret) == 0) {
return 0;
return SUCCESS_EXECUTE_CMD;
}
}
write_runlog(ERROR, "Fail to execute command %s, script exit code %d.\n", cmd, WEXITSTATUS(ret));
return -1;
write_runlog(logLevel, "Fail to execute command %s, script exit code %d.\n", cmd, WEXITSTATUS(ret));
if (errCode != NULL) {
*errCode = WEXITSTATUS(ret);
}
return FAILED_EXECUTE_CMD;
}
void CheckDnNicDown(uint32 index)

View File

@ -27,6 +27,8 @@
#include "cm/cs_ssl.h"
#include "cma_common.h"
#include "cma_instance_check.h"
#include "cma_instance_management_res.h"
#include "cma_process_messages_client.h"
#include "cma_connect.h"
#ifdef ENABLE_MULTIPLE_NODES
#include "cma_coordinator.h"
@ -368,6 +370,9 @@ static void CloseConnToCmserver(void)
write_runlog(LOG, "close agent to cmserver connection.\n");
}
CleanCmsMsgQueue();
if (IsCusResExistLocal()) {
NotifyClientConnectClose();
}
}
static status_t SendCmsMsgMain()

View File

@ -317,6 +317,9 @@ static void RecvClientMsgMain(int epollfd, int eventNums, const ListenPort *list
void* RecvClientEventsMain(void * const arg)
{
thread_name = "RecvClientMsg";
write_runlog(LOG, "recv msg from client thread begin, threadId:%lu.\n", (unsigned long)pthread_self());
int epollfd;
ListenPort listenfd;
struct epoll_event events[MAX_EVENTS];

View File

@ -50,6 +50,7 @@
static bool IsCmsReplaceFlagFileExists();
static void StopCmInstance();
static void StopOneZengine(uint32 index);
static bool StopCurDnFloatIp(uint32 index);
#ifdef ENABLE_GCOV
static const int SIG_TYPE = 2;
@ -680,6 +681,7 @@ void stop_datanode_check(uint32 i)
g_isDnFirstStart = true;
}
(void)StopCurDnFloatIp(i);
}
}
@ -732,6 +734,39 @@ static int cmserver_stopped_check(void)
return PROCESS_NOT_EXIST;
}
static NetworkState CheckCurDnFloatIpStatus(uint32 index)
{
DnFloatIp *dnFloatIp = GetDnFloatIpByDnIdx(index);
if (dnFloatIp == NULL || dnFloatIp->dnFloatIpCount == 0) {
return NETWORK_STATE_UNKNOWN;
}
NetworkState state[MAX_FLOAT_IP_COUNT];
GetFloatIpNicStatus(dnFloatIp->instId, CM_INSTANCE_TYPE_DN, state, dnFloatIp->dnFloatIpCount);
for (uint32 i = 0; i < dnFloatIp->dnFloatIpCount; ++i) {
if (state[i] == NETWORK_STATE_UP) {
return NETWORK_STATE_UP;
}
}
return NETWORK_STATE_DOWN;
}
static int32 CheckFloatIpStateInDn(uint32 index)
{
uint32 count = DelFloatIpInDatanode(index);
if (count != 0) {
write_runlog(
LOG, "line: %d: datanode(%u) floatIp is running.\n", __LINE__, g_currentNode->datanode[index].datanodeId);
return PROCESS_RUNNING;
}
NetworkState state = CheckCurDnFloatIpStatus(index);
if (state == NETWORK_STATE_UP) {
write_runlog(
LOG, "line: %d: datanode(%u) floatIp is running.\n", __LINE__, g_currentNode->datanode[index].datanodeId);
return PROCESS_RUNNING;
}
return PROCESS_NOT_EXIST;
}
static int datanode_stopped_check(void)
{
int ret;
@ -756,6 +791,9 @@ static int datanode_stopped_check(void)
write_runlog(LOG, "data node is running path is %s\n", g_currentNode->datanode[ii].datanodeLocalDataPath);
return PROCESS_RUNNING;
}
if (CheckFloatIpStateInDn(ii) == PROCESS_RUNNING) {
return PROCESS_RUNNING;
}
}
return PROCESS_NOT_EXIST;
@ -1335,6 +1373,7 @@ static void NormalShutdownAllDatanode()
} else {
NormalShutdownOneDatanode(dnInfo, g_dnReportMsg[i].dnStatus.reportMsg.local_status.local_role);
}
DelAndDownFloatIpInDn(i);
}
}
@ -1402,6 +1441,12 @@ static void ShutdownOneDatanode(const dataNodeInfo *dnInfo)
immediate_stop_one_instance(dnInfo->datanodeLocalDataPath, INSTANCE_DN);
}
void DelAndDownFloatIpInDn(uint32 index)
{
(void)DelFloatIpInDatanode(index);
SetNicOper(g_currentNode->datanode[index].datanodeId, CM_INSTANCE_TYPE_DN, NETWORK_TYPE_FLOATIP, NETWORK_OPER_DOWN);
}
static void ImmediateShutdownAllDatanode()
{
for (uint32 ii = 0; ii < g_currentNode->datanodeCount; ii++) {
@ -1410,6 +1455,7 @@ static void ImmediateShutdownAllDatanode()
} else {
ShutdownOneDatanode(&g_currentNode->datanode[ii]);
}
DelAndDownFloatIpInDn(ii);
}
}
@ -1455,6 +1501,7 @@ static void FastShutdownAllDatanode()
} else {
fast_stop_one_instance(g_currentNode->datanode[ii].datanodeLocalDataPath, INSTANCE_DN);
}
DelAndDownFloatIpInDn(ii);
}
}
@ -1553,6 +1600,22 @@ void StopZengineByCmd(uint32 index)
immediate_stop_one_instance(g_currentNode->datanode[index].datanodeLocalDataPath, INSTANCE_DN);
}
static bool StopCurDnFloatIp(uint32 index)
{
uint32 count = DelFloatIpInDatanode(index);
if (count != 0) {
return false;
}
NetworkState state = CheckCurDnFloatIpStatus(index);
if (state != NETWORK_STATE_UP) {
return true;
}
write_runlog(
LOG, "instId(%u) FloatIp is running, it need to be stopped.\n", g_currentNode->datanode[index].datanodeId);
SetNicOper(g_currentNode->datanode[index].datanodeId, CM_INSTANCE_TYPE_DN, NETWORK_TYPE_FLOATIP, NETWORK_OPER_DOWN);
return false;
}
static void StopOneZengine(uint32 index)
{
bool dnManualStop = DnManualStop(index);
@ -1574,6 +1637,11 @@ static void StopOneZengine(uint32 index)
StopZengineByCmd(index);
return;
}
if (!StopCurDnFloatIp(index)) {
return;
}
write_runlog(LOG,
"datanode is not running, no need to shutdown: %s.\n",
g_currentNode->datanode[index].datanodeLocalDataPath);

View File

@ -30,17 +30,29 @@
uint32 g_localResConfCount = 0;
int SystemExecute(const char *scriptPath, const char *oper, uint32 timeout)
static int CusResCmdExecute(const char *scriptPath, const char *oper, uint32 timeout, bool8 needNohup)
{
char command[MAX_PATH_LEN + MAX_OPTION_LEN] = {0};
int ret = snprintf_s(command,
MAX_PATH_LEN + MAX_OPTION_LEN,
MAX_PATH_LEN + MAX_OPTION_LEN - 1,
SYSTEMQUOTE "timeout -s SIGKILL %us %s %s > %s" SYSTEMQUOTE,
timeout,
scriptPath,
oper,
CM_DEVNULL);
int ret;
if (needNohup) {
ret = snprintf_s(command,
MAX_PATH_LEN + MAX_OPTION_LEN,
MAX_PATH_LEN + MAX_OPTION_LEN - 1,
SYSTEMQUOTE "nohup timeout -s SIGKILL %us %s %s > %s &" SYSTEMQUOTE,
timeout,
scriptPath,
oper,
CM_DEVNULL);
} else {
ret = snprintf_s(command,
MAX_PATH_LEN + MAX_OPTION_LEN,
MAX_PATH_LEN + MAX_OPTION_LEN - 1,
SYSTEMQUOTE "timeout -s SIGKILL %us %s %s > %s" SYSTEMQUOTE,
timeout,
scriptPath,
oper,
CM_DEVNULL);
}
securec_check_intval(ret, (void)ret);
int status = system(command);
if (status == -1) {
@ -63,7 +75,7 @@ status_t StartOneResInst(const CmResConfList *conf)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-start %u %s", conf->resInstanceId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_FALSE);
if (ret == 0) {
write_runlog(LOG, "StartOneResInst: run start script (%s %s) successfully.\n", conf->script, oper);
} else if (ret == CUS_RES_START_FAIL_DEPEND_NOT_ALIVE) {
@ -83,7 +95,7 @@ void StopOneResInst(const CmResConfList *conf)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-stop %u %s", conf->resInstanceId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_FALSE);
if (ret == 0) {
write_runlog(LOG, "StopOneResInst: run stop command (%s %s) successfully.\n", conf->script, oper);
} else {
@ -112,12 +124,13 @@ status_t RegOneResInst(const CmResConfList *conf, uint32 destInstId)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-reg %u %s", destInstId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_TRUE);
if (ret != 0) {
write_runlog(ERROR, "RegOneResInst: reg inst cmd(%s %s) failed, ret=%d\n", conf->script, oper, ret);
write_runlog(ERROR, "[%s]: cmd:(%s %s) execute failed, ret=%d.\n", __FUNCTION__, conf->script, oper, ret);
return CM_ERROR;
}
write_runlog(LOG, "RegOneResInst: reg inst cmd(%s %s) success\n", conf->script, oper);
write_runlog(LOG, "[%s]: cmd:(%s %s) is executing.\n", __FUNCTION__, conf->script, oper);
return CM_SUCCESS;
}
@ -127,12 +140,13 @@ status_t UnregOneResInst(const CmResConfList *conf, uint32 destInstId)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-unreg %u %s", destInstId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_TRUE);
if (ret != 0) {
write_runlog(ERROR, "UnregOneResInst: unreg inst cmd:(%s %s) failed, ret=%d\n", conf->script, oper, ret);
write_runlog(ERROR, "[%s]: cmd:(%s %s) execute failed, ret=%d.\n", __FUNCTION__, conf->script, oper, ret);
return CM_ERROR;
}
write_runlog(LOG, "UnregOneResInst: unreg inst cmd:(%s %s) success\n", conf->script, oper);
write_runlog(LOG, "[%s]: cmd:(%s %s) is executing.\n", __FUNCTION__, conf->script, oper);
return CM_SUCCESS;
}
@ -143,7 +157,7 @@ ResIsregStatus IsregOneResInst(const CmResConfList *conf, uint32 destInstId)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-isreg %u %s", destInstId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_FALSE);
switch (ret) {
case RES_INST_ISREG_UNKNOWN:
write_runlog(DEBUG5, "IsregOneResInst: res(%s) inst(%u) get isreg error.\n", conf->resName, destInstId);
@ -175,7 +189,7 @@ status_t CleanOneResInst(const CmResConfList *conf)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-clean %u %s", conf->resInstanceId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_FALSE);
if (ret != 0) {
write_runlog(ERROR, "CleanOneResInst: clean inst cmd(%s %s) failed, ret=%d\n", conf->script, oper, ret);
return CM_ERROR;
@ -184,21 +198,43 @@ status_t CleanOneResInst(const CmResConfList *conf)
return CM_SUCCESS;
}
static void StopCurNodeFloatIp()
{
for (uint32 i = 0; i < g_currentNode->datanodeCount; ++i) {
DelAndDownFloatIpInDn(i);
}
}
static inline void CleanOneInstCheckCount(CmResConfList *resConf)
{
if (resConf->checkInfo.startCount != 0) {
write_runlog(LOG, "res(%s) inst(%u) restart times will clean.\n", resConf->resName, resConf->cmInstanceId);
write_runlog(LOG, "res(%s) inst(%u) restart times clean.\n", resConf->resName, resConf->cmInstanceId);
}
resConf->checkInfo.startCount = 0;
resConf->checkInfo.startTime = 0;
resConf->checkInfo.brokeTime = 0;
}
static inline void CleanOneInstAbnormalStat(CmResConfList *resConf, int curStat)
{
if (resConf->checkInfo.abnormalTime != 0) {
write_runlog(LOG, "res(%s) inst(%u) status from abnormal change to %d.\n",
resConf->resName, resConf->cmInstanceId, curStat);
resConf->checkInfo.abnormalTime = 0;
}
}
static inline void CleanOneInstOnlineTimes(CmResConfList *resConf)
{
resConf->checkInfo.onlineTimes = 0;
}
void StopAllResInst()
{
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
OneResInstClean(&g_resConf[i]);
}
StopCurNodeFloatIp();
}
int CheckOneResInst(const CmResConfList *conf)
@ -207,8 +243,9 @@ int CheckOneResInst(const CmResConfList *conf)
int ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-check %u %s", conf->resInstanceId, conf->arg);
securec_check_intval(ret, (void)ret);
ret = SystemExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut);
if ((ret != CUS_RES_CHECK_STAT_ONLINE) && (ret != CUS_RES_CHECK_STAT_OFFLINE)) {
ret = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_FALSE);
if ((ret != CUS_RES_CHECK_STAT_ONLINE) && (ret != CUS_RES_CHECK_STAT_OFFLINE) &&
(ret != CUS_RES_CHECK_STAT_ABNORMAL)) {
write_runlog(LOG, "CheckOneResInst, run system command(%s %s) special result=%d\n", conf->script, oper, ret);
}
return ret;
@ -272,6 +309,8 @@ static inline status_t RestartOneResInst(CmResConfList *conf)
static void ProcessOfflineInstance(CmResConfList *conf)
{
long curTime = GetCurMonotonicTimeSec();
if (conf->checkInfo.restartTimes == -1) {
if (CanCusInstDoRestart(conf)) {
(void)RestartOneResInst(conf);
@ -279,22 +318,22 @@ static void ProcessOfflineInstance(CmResConfList *conf)
return;
}
if (conf->checkInfo.brokeTime == 0) {
conf->checkInfo.brokeTime = time(NULL);
conf->checkInfo.brokeTime = curTime;
return;
}
if (conf->checkInfo.startCount >= conf->checkInfo.restartTimes) {
write_runlog(LOG, "res(%s) inst(%u) is offline, but restart times (%d) >= limit (%d), can't do restart again, "
"will do manually stop.\n", conf->resName, conf->resInstanceId, conf->checkInfo.startCount,
"will do manually stop.\n", conf->resName, conf->cmInstanceId, conf->checkInfo.startCount,
conf->checkInfo.restartTimes);
ManualStopLocalResInst(conf);
return;
}
if ((time(NULL) - conf->checkInfo.brokeTime) < conf->checkInfo.restartDelay) {
if ((curTime - conf->checkInfo.brokeTime) < conf->checkInfo.restartDelay) {
write_runlog(DEBUG5, "[CLIENT] res(%s) inst(%u) curTime=%ld, brokeTime=%ld, restartDelay=%d.\n",
conf->resName, conf->resInstanceId, time(NULL), conf->checkInfo.brokeTime, conf->checkInfo.restartDelay);
conf->resName, conf->resInstanceId, curTime, conf->checkInfo.brokeTime, conf->checkInfo.restartDelay);
return;
}
if ((time(NULL) - conf->checkInfo.startTime) < conf->checkInfo.restartPeriod) {
if ((curTime - conf->checkInfo.startTime) < conf->checkInfo.restartPeriod) {
write_runlog(DEBUG5, "[CLIENT] res(%s) inst(%u) startTime = %ld, restartPeriod = %d.\n",
conf->resName, conf->resInstanceId, conf->checkInfo.startTime, conf->checkInfo.restartPeriod);
return;
@ -304,11 +343,49 @@ static void ProcessOfflineInstance(CmResConfList *conf)
}
CM_RETVOID_IFERR(RestartOneResInst(conf));
conf->checkInfo.startCount++;
conf->checkInfo.startTime = time(NULL);
conf->checkInfo.startTime = curTime;
write_runlog(LOG, "res(%s) inst(%u) has been restart (%d) times, restart more than (%d) time will manually stop.\n",
conf->resName, conf->cmInstanceId, conf->checkInfo.startCount, conf->checkInfo.restartTimes);
}
static void ProcessAbnormalInstance(CmResConfList *conf)
{
long curTime = GetCurMonotonicTimeSec();
if (conf->checkInfo.abnormalTime == 0) {
conf->checkInfo.abnormalTime = curTime;
}
const int writeLogInterval = 10;
int duration = (int)(curTime - conf->checkInfo.abnormalTime);
if (duration < conf->checkInfo.abnormalTimeout) {
if ((duration > 0) && (duration % writeLogInterval == 0)) {
write_runlog(LOG, "res(%s) inst(%u) has been abnormal (%d)s, timeout is (%d)s.\n",
conf->resName, conf->cmInstanceId, duration, conf->checkInfo.abnormalTimeout);
}
return;
}
if ((conf->checkInfo.startCount >= conf->checkInfo.restartTimes) && (conf->checkInfo.restartTimes != -1)) {
write_runlog(LOG, "res(%s) inst(%u) is abnormal, but restart times (%d) >= limit (%d), can't do restart again, "
"will do manually stop.\n",
conf->resName, conf->cmInstanceId, conf->checkInfo.startCount, conf->checkInfo.restartTimes);
ManualStopLocalResInst(conf);
return;
}
write_runlog(LOG, "res(%s) inst(%u) has been abnormal (%d)s, >= timeout(%d)s, need restart.\n",
conf->resName, conf->cmInstanceId, duration, conf->checkInfo.abnormalTimeout);
CM_RETVOID_IFERR(RestartOneResInst(conf));
conf->checkInfo.startCount++;
conf->checkInfo.startTime = curTime;
if (conf->checkInfo.restartTimes != -1) {
write_runlog(LOG, "res(%s) inst(%u) has been restart (%d) times, restart more (%d) time will manually stop.\n",
conf->resName, conf->cmInstanceId, conf->checkInfo.startCount, conf->checkInfo.restartTimes);
}
}
static inline bool NeedStopResInst(const char *resName, uint32 cmInstId)
{
return (IsInstManualStopped(cmInstId) || CmFileExist(g_cmManualStartPath) || !IsOneResInstWork(resName, cmInstId) ||
@ -333,18 +410,34 @@ void StartResourceCheck()
switch (ret) {
case CUS_RES_CHECK_STAT_ONLINE:
ProcessOnlineInstance(&g_resConf[i]);
CleanOneInstAbnormalStat(&g_resConf[i], CUS_RES_CHECK_STAT_ONLINE);
break;
case CUS_RES_CHECK_STAT_OFFLINE:
g_resConf[i].checkInfo.onlineTimes = 0;
CleanOneInstOnlineTimes(&g_resConf[i]);
CleanOneInstAbnormalStat(&g_resConf[i], CUS_RES_CHECK_STAT_OFFLINE);
if (NeedStopResInst(g_resConf[i].resName, g_resConf[i].cmInstanceId)) {
CleanOneInstCheckCount(&g_resConf[i]);
break;
}
ProcessOfflineInstance(&g_resConf[i]);
break;
default :
case CUS_RES_CHECK_STAT_ABNORMAL:
CleanOneInstOnlineTimes(&g_resConf[i]);
if (!IsOneResInstWork(g_resConf[i].resName, g_resConf[i].cmInstanceId)) {
write_runlog(LOG, "res(%s) inst(%u) is abnormal, but has been kick out, need stop it.\n",
g_resConf[i].resName, g_resConf[i].cmInstanceId);
(void)CleanOneResInst(&g_resConf[i]);
break;
}
if (IsInstManualStopped(g_resConf[i].cmInstanceId) || CmFileExist(g_cmManualStartPath)) {
CleanOneInstCheckCount(&g_resConf[i]);
break;
}
ProcessAbnormalInstance(&g_resConf[i]);
break;
default:
write_runlog(ERROR, "StartResourceCheck, special status(%d).\n", ret);
break ;
break;
}
}
}
@ -381,7 +474,8 @@ void StopResourceCheck()
int ResourceStoppedCheck(void)
{
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
if (CheckOneResInst(&g_resConf[i]) == CUS_RES_CHECK_STAT_ONLINE) {
int ret = CheckOneResInst(&g_resConf[i]);
if (ret == CUS_RES_CHECK_STAT_ONLINE || ret == CUS_RES_CHECK_STAT_ABNORMAL) {
write_runlog(LOG, "resource is running, script is %s\n", g_resConf[i].script);
return PROCESS_RUNNING;
}
@ -418,12 +512,14 @@ static status_t InitResNameConf(const char *resNameJson, char *resNameConf)
return CM_SUCCESS;
}
static inline void InitOneConfOfRes(const char *paraName, int value, int *newValue, int defValue)
static inline void InitOneConfOfRes(const char *paraName, int value, int *newValue)
{
if (IsResConfValid(paraName, value)) {
*newValue = value;
} else {
*newValue = defValue;
*newValue = CmAtoi(ResConfDefValue(paraName), 0);
write_runlog(ERROR, "\"%s\":%d out of range, range [%d, %d], use default value(%d).\n",
paraName, value, ResConfMinValue(paraName), ResConfMaxValue(paraName), *newValue);
}
}
@ -437,16 +533,12 @@ static status_t InitLocalCommConfOfDefRes(const CusResConfJson *resJson, CmResCo
securec_check_errno(rc, (void)rc);
canonicalize_path(localConf->script);
const int defCheckInterval = 1;
InitOneConfOfRes("check_interval", resJson->checkInterval, &localConf->checkInfo.checkInterval, defCheckInterval);
const int defTimeOut = 10;
InitOneConfOfRes("time_out", resJson->timeOut, &localConf->checkInfo.timeOut, defTimeOut);
const int defRestartDelay = 1;
InitOneConfOfRes("restart_delay", resJson->restartDelay, &localConf->checkInfo.restartDelay, defRestartDelay);
const int defRestartPeriod = 1;
InitOneConfOfRes("restart_period", resJson->restartPeriod, &localConf->checkInfo.restartPeriod, defRestartPeriod);
const int defRestartTimes = -1;
InitOneConfOfRes("restart_times", resJson->restartTimes, &localConf->checkInfo.restartTimes, defRestartTimes);
InitOneConfOfRes("check_interval", resJson->checkInterval, &localConf->checkInfo.checkInterval);
InitOneConfOfRes("time_out", resJson->timeOut, &localConf->checkInfo.timeOut);
InitOneConfOfRes("restart_delay", resJson->restartDelay, &localConf->checkInfo.restartDelay);
InitOneConfOfRes("restart_period", resJson->restartPeriod, &localConf->checkInfo.restartPeriod);
InitOneConfOfRes("restart_times", resJson->restartTimes, &localConf->checkInfo.restartTimes);
InitOneConfOfRes("abnormal_timeout", resJson->abnormalTimeout, &localConf->checkInfo.abnormalTimeout);
return CM_SUCCESS;
}
@ -569,8 +661,5 @@ uint32 GetLocalResConfCount()
bool IsCusResExistLocal()
{
if (g_localResConfCount == 0) {
return false;
}
return true;
return (g_localResConfCount > 0);
}

View File

@ -100,6 +100,17 @@ static inline void PushToAgentMsgQue(const AgentMsgPkg *msgPkg, MsgQueue *msgQue
(void)pthread_cond_signal(&msgQue->cond);
}
void PushMsgToAllClientSendQue(const char *msgPtr, uint32 msgLen)
{
ClientConn *clientConn = GetClientConnect();
for (uint32 i = 0; i < CM_MAX_RES_COUNT; ++i) {
if (!clientConn[i].isClosed) {
write_runlog(LOG, "notify inst(%u), CMA disconnect with CMS.\n", clientConn[i].cmInstanceId);
PushMsgToClientSendQue(msgPtr, msgLen, i);
}
}
}
void PushMsgToClientSendQue(const char *msgPtr, uint32 msgLen, uint32 conId)
{
AgentMsgPkg msgPkg = {0};

View File

@ -22,13 +22,17 @@
* -------------------------------------------------------------------------
*/
#include <limits.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <linux/if.h>
#include "cjson/cJSON.h"
#include "cma_global_params.h"
#include "cm_util.h"
#include "cm_text.h"
#include "cm_json_config.h"
#include "cm_json_parse_floatIp.h"
#include "cma_global_params.h"
#include "cma_common.h"
#include "cma_network_check.h"
@ -58,6 +62,7 @@ typedef struct NetworkInfoT {
NetworkOper oper;
uint32 port;
uint32 cnt;
uint32 checkCnt;
const char (*ips)[CM_IP_LENGTH];
NetWorkAddr *netAddr;
NetworkState *stateCheck;
@ -90,6 +95,10 @@ typedef struct NetworkStateStringMapT {
const char *str;
} NetworkStateStringMap;
#ifdef ENABLE_UT
#define static
#endif
static bool GetNicstatusByAddrs(const struct ifaddrs *ifList, NetworkInfo *netInfo, int32 logLevel = WARNING,
NetworkQuest quest = NETWORK_QUEST_CHECK);
static void GetNicDownCmd(char *cmd, uint32 cmdLen, const NetworkInfo *netInfo, uint32 index);
@ -97,6 +106,7 @@ static void GetNicDownCmd(char *cmd, uint32 cmdLen, const NetworkInfo *netInfo,
static CmNetworkInfo *g_cmNetWorkInfo = NULL;
static uint32 g_instCnt = 0;
static CmNetworkByType g_cmNetworkByType[CM_INSTANCE_TYPE_CEIL] = {{0}};
static ParseFloatIpFunc g_cmaParseFuc = {0};
static NetworkStateOperMap g_stateOperMap[] = {{NETWORK_STATE_UNKNOWN, NETWORK_OPER_UNKNOWN},
{NETWORK_STATE_UP, NETWORK_OPER_UP},
@ -104,14 +114,20 @@ static NetworkStateOperMap g_stateOperMap[] = {{NETWORK_STATE_UNKNOWN, NETWORK_O
{NETWORK_STATE_CEIL, NETWORK_OPER_CEIL}};
static const char *g_ifconfigCmd = "ifconfig";
static const char *IFCONFIG_CMD_DEFAULT = "ifconfig";
static const char *IFCONFIG_CMD_SUSE = "/sbin/ifconfig";
static const char *IFCONFIG_CMD_EULER = "/usr/sbin/ifconfig";
static const char *ARPING_CMD = "arping -w 1 -A -I";
static const char *SHOW_IPV6_CMD = "ip addr show | grep";
static const char *IPV6_TENTATIVE_FLAG = "tentative";
static const char *IPV6_DADFAILED_FLAG = "dadfailed";
static const char *const IFCONFIG_CMD_DEFAULT = "ifconfig";
static const char *const IFCONFIG_CMD_SUSE = "/sbin/ifconfig";
static const char *const IFCONFIG_CMD_EULER = "/usr/sbin/ifconfig";
static const char *const ARPING_CMD = "arping -w 1 -A -I";
static const char *const SHOW_IPV6_CMD = "ip addr show | grep";
static const char *const IPV6_TENTATIVE_FLAG = "tentative";
static const char *const IPV6_DADFAILED_FLAG = "dadfailed";
static const char *const TIMEOUT_MECHA = "timeout -s SIGKILL";
static const uint32 DEFAULT_CMD_TIMEOUT = 2;
static const char *g_sudoPermCmd = "";
static const char *const SUDO_PERM_CMD = "sudo";
static DnFloatIpMapOper g_floatIpMap = {0};
static NetworkOperStringMap g_operStringMap[NETWORK_OPER_CEIL] = {
{NETWORK_OPER_UNKNOWN, "NETWORK_OPER_UNKNOWN"},
{NETWORK_OPER_UP, "NETWORK_OPER_UP"},
@ -144,6 +160,67 @@ const char *GetOperMapString(NetworkOper oper)
return "unknown_oper";
}
void SetFloatIpOper(uint32 dnIdx, NetworkOper oper, const char *str)
{
if (!IsNeedCheckFloatIp() || (agent_backup_open != CLUSTER_PRIMARY)) {
write_runlog(DEBUG1, "%s agent_backup_open=%d, cannot set floatIp oper.\n", str, (int32)agent_backup_open);
return;
}
if (dnIdx >= CM_MAX_DATANODE_PER_NODE) {
return;
}
g_floatIpMap.oper[dnIdx] = oper;
write_runlog(LOG, "%s set floatIp oper=%d.\n", str, (int32)oper);
}
NetworkOper GetFloatIpOper(uint32 dnIdx)
{
if (dnIdx >= CM_MAX_DATANODE_PER_NODE) {
return NETWORK_OPER_UNKNOWN;
}
return g_floatIpMap.oper[dnIdx];
}
DnFloatIp *GetDnFloatIpByDnIdx(uint32 dnIdx)
{
if (dnIdx >= CM_MAX_DATANODE_PER_NODE) {
return NULL;
}
return &(g_floatIpMap.floatIp[dnIdx]);
}
static bool8 CmaFindNodeInfoByNodeIdx(uint32 instId, uint32 *nodeIdx, uint32 *dnIdx, const char *str)
{
return (bool8)FindDnIdxInCurNode(instId, dnIdx, str);
}
static DnFloatIp *CmaGetDnFloatIpByNodeInfo(uint32 nodeIdx, uint32 dnIdx)
{
return GetDnFloatIpByDnIdx(dnIdx);
}
static void IncreaseDnFloatIpCnt(uint32 nodeIdx)
{
++g_floatIpMap.count;
}
static void CmaInitParseFloatIpCnt()
{
g_cmaParseFuc.findNodeInfo = CmaFindNodeInfoByNodeIdx;
g_cmaParseFuc.getFloatIp = CmaGetDnFloatIpByNodeInfo;
g_cmaParseFuc.increaseCnt = IncreaseDnFloatIpCnt;
InitParseFloatIpFunc(&g_cmaParseFuc);
}
static inline void InitFloatIpMap()
{
errno_t rc = memset_s(&(g_floatIpMap), sizeof(DnFloatIpMapOper), 0, sizeof(DnFloatIpMapOper));
securec_check_errno(rc, (void)rc);
CmaInitParseFloatIpCnt();
ParseVipConf(LOG);
write_runlog(LOG, "success to get g_floatIpMap, and this count is %u.\n", g_floatIpMap.count);
}
NetworkOper ChangeInt2NetworkOper(int32 oper)
{
if (oper < 0 || oper >= (int32)NETWORK_OPER_CEIL) {
@ -195,7 +272,7 @@ static NetworkInfo *GetNetworkInfo(uint32 instId, CmaInstType instType, NetworkT
return NULL;
}
bool GetNicStatus(unsigned int instId, CmaInstType instType, NetworkType type)
bool GetNicStatus(uint32 instId, CmaInstType instType, NetworkType type)
{
NetworkInfo *netInfo = GetNetworkInfo(instId, instType, type);
if (netInfo == NULL) {
@ -272,6 +349,51 @@ static uint32 GetCurrentNodeInstNum()
return count;
}
static void SetNetWorkAddr(NetWorkAddr *netAddr, uint32 cnt, const char (*ips)[CM_IP_LENGTH])
{
if (cnt == 0 || ips == NULL || netAddr == NULL) {
return;
}
for (uint32 i = 0; i < cnt; ++i) {
netAddr[i].ip = ips[i];
}
}
static bool8 IsCurIpInIpPool(const char **ipPool, uint32 cnt, const char *ip)
{
if (cnt == 0 || ip == NULL) {
return CM_FALSE;
}
for (uint32 i = 0; i < cnt; ++i) {
if (ipPool[i] == NULL) {
continue;
}
if (cm_str_equal(ipPool[i], ip)) {
return CM_TRUE;
}
}
return CM_FALSE;
}
static uint32 GetIpCheckCnt(const char (*ips)[CM_IP_LENGTH], uint32 cnt)
{
const char *ipPool[MAX_FLOAT_IP_COUNT] = {0};
uint32 checkCnt = 0;
for (uint32 i = 0; i < cnt; ++i) {
if (i >= MAX_FLOAT_IP_COUNT) {
break;
}
if (IsCurIpInIpPool(ipPool, checkCnt, ips[i])) {
continue;
}
if (checkCnt < MAX_FLOAT_IP_COUNT) {
ipPool[checkCnt] = ips[i];
++checkCnt;
}
}
return checkCnt;
}
static status_t SetNetWorkInfo(
NetworkInfo *info, uint32 cnt, const char (*ips)[CM_IP_LENGTH], NetworkType type, uint32 port)
{
@ -285,6 +407,7 @@ static status_t SetNetWorkInfo(
cnt, MAX_FLOAT_IP_COUNT);
}
info->cnt = curCnt;
info->checkCnt = GetIpCheckCnt(ips, cnt);
info->oper = NETWORK_OPER_UNKNOWN;
info->port = port;
if (cnt == 0) {
@ -325,10 +448,17 @@ static status_t SetCmNetWorkInfoDn(CmaInstType type, uint32 *index, const dataNo
const dataNodeInfo *dnInfo = &(datanodeInfo[dnIdx]);
CmNetworkInfo *cmNetWorkInfo = &(g_cmNetWorkInfo[(*index)]);
cmNetWorkInfo->instId = dnInfo->datanodeId;
DnFloatIp *dnFloatIp = GetDnFloatIpByDnIdx(dnIdx);
CM_RETURN_IFERR(SetNetWorkInfo(&(cmNetWorkInfo->manaIp[NETWORK_TYPE_LISTEN]), dnInfo->datanodeListenCount,
dnInfo->datanodeListenIP, NETWORK_TYPE_LISTEN, dnInfo->datanodePort));
CM_RETURN_IFERR(SetNetWorkInfo(&(cmNetWorkInfo->manaIp[NETWORK_TYPE_HA]), dnInfo->datanodeLocalHAListenCount,
dnInfo->datanodeLocalHAIP, NETWORK_TYPE_HA, dnInfo->datanodeLocalHAPort));
if (dnFloatIp != NULL) {
NetworkInfo *netInfo = &(cmNetWorkInfo->manaIp[NETWORK_TYPE_FLOATIP]);
CM_RETURN_IFERR(SetNetWorkInfo(netInfo, dnFloatIp->dnFloatIpCount,
dnFloatIp->dnFloatIp, NETWORK_TYPE_FLOATIP, dnFloatIp->dnFloatIpPort));
SetNetWorkAddr(netInfo->netAddr, netInfo->cnt, dnFloatIp->baseIp);
}
++(*index);
if (type >= CM_INSTANCE_TYPE_CEIL) {
return CM_SUCCESS;
@ -445,9 +575,19 @@ static void InitIfconfigCmd()
}
}
static void InitSudoPermCmd()
{
g_sudoPermCmd = "";
if (g_clusterType != V3SingleInstCluster) {
g_sudoPermCmd = SUDO_PERM_CMD;
}
}
static status_t InitCmNetWorkInfo()
{
InitFloatIpMap();
InitIfconfigCmd();
InitSudoPermCmd();
g_instCnt = GetCurrentNodeInstNum();
write_runlog(LOG, "current node has %u instance.\n", g_instCnt);
size_t mallocLen = sizeof(CmNetworkInfo) * g_instCnt;
@ -612,7 +752,7 @@ static bool GetNicstatusByAddrs(
return false;
}
++validIpCount;
if (validIpCount == netInfo->cnt) {
if (validIpCount == netInfo->checkCnt) {
return true;
}
}
@ -621,7 +761,8 @@ static bool GetNicstatusByAddrs(
}
char allListenIp[CM_IP_ALL_NUM_LENGTH] = {0};
listen_ip_merge(netInfo->cnt, netInfo->ips, allListenIp, CM_IP_ALL_NUM_LENGTH);
write_runlog(WARNING, "can't find nic related with %s.\n", allListenIp);
write_runlog(WARNING, "can't find nic related with %s, cnt=[%u: %u].\n",
allListenIp, netInfo->cnt, netInfo->checkCnt);
return false;
}
@ -669,6 +810,25 @@ static bool CheckNetworkStatus()
return true;
}
bool8 CheckNetworkStatusByIps(const char (*ips)[CM_IP_LENGTH], uint32 cnt)
{
struct ifaddrs *ifList = NULL;
if (getifaddrs(&ifList) < 0) {
write_runlog(WARNING, "failed to get iflist.\n");
return CM_FALSE;
}
NetworkInfo netInfo;
errno_t rc = memset_s(&netInfo, sizeof(NetworkInfo), 0, sizeof(NetworkInfo));
securec_check_errno(rc, (void)rc);
netInfo.ips = ips;
netInfo.cnt = cnt;
netInfo.checkCnt = GetIpCheckCnt(ips, cnt);
netInfo.type = NETWORK_TYPE_HA;
CheckNicStatus(ifList, &netInfo);
freeifaddrs(ifList);
return (bool8)netInfo.networkRes;
}
static bool GetNetworkAddr(NetworkInfo *netInfo, const char *str)
{
struct ifaddrs *ifList = NULL;
@ -722,16 +882,19 @@ static void GetNicUpCmd(char *cmd, uint32 cmdLen, const NetworkInfo *netInfo, ui
if (netInfo->netAddr[index].netMask[0] == '\0' || netInfo->netAddr[index].netName[0] == '\0') {
return;
}
errno_t rc = 0;
if (netInfo->netAddr[index].family == AF_INET) {
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %s:%u %s netmask %s up", g_ifconfigCmd, netAddr->netName,
netInfo->port, netInfo->ips[index], netAddr->netMask);
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %us %s %s %s:%u %s netmask %s up",
TIMEOUT_MECHA, DEFAULT_CMD_TIMEOUT, g_sudoPermCmd, g_ifconfigCmd,
netAddr->netName, netInfo->port, netInfo->ips[index], netAddr->netMask);
} else if (netInfo->netAddr[index].family == AF_INET6) {
if (!CheckIpV6Valid(netInfo, index, "[GetNicUpCmd]", LOG)) {
return;
}
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %s inet6 add %s/%s", g_ifconfigCmd, netAddr->netName,
netInfo->ips[index], netAddr->netMask);
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %us %s %s %s inet6 add %s/%s",
TIMEOUT_MECHA, DEFAULT_CMD_TIMEOUT, g_sudoPermCmd, g_ifconfigCmd,
netAddr->netName, netInfo->ips[index], netAddr->netMask);
}
securec_check_intval(rc, (void)rc);
}
@ -744,11 +907,13 @@ static void GetNicDownCmd(char *cmd, uint32 cmdLen, const NetworkInfo *netInfo,
}
errno_t rc = 0;
if (netInfo->netAddr[index].family == AF_INET) {
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %s:%u down", g_ifconfigCmd, netAddr->netName,
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %us %s %s %s:%u down",
TIMEOUT_MECHA, DEFAULT_CMD_TIMEOUT, g_sudoPermCmd, g_ifconfigCmd, netAddr->netName,
netInfo->port);
} else {
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %s inet6 del %s/%s", g_ifconfigCmd, netAddr->netName,
netInfo->ips[index], netAddr->netMask);
rc = snprintf_s(cmd, cmdLen, cmdLen - 1, "%s %us %s %s %s inet6 del %s/%s",
TIMEOUT_MECHA, DEFAULT_CMD_TIMEOUT, g_sudoPermCmd, g_ifconfigCmd,
netAddr->netName, netInfo->ips[index], netAddr->netMask);
}
securec_check_intval(rc, (void)rc);
}
@ -772,15 +937,12 @@ static void ExecuteArpingCmd(ArpingCmdRes *arpingCmd, const char *str)
static void CheckArpingCmdRes(NetworkInfo *netInfo)
{
if (netInfo->oper != NETWORK_OPER_UP) {
return;
}
for (uint32 i = 0; i < netInfo->cnt; ++i) {
ExecuteArpingCmd(&(netInfo->arpingCmd[i]), "[CheckArpingCmdRes]");
}
}
static bool CheckNicStatusMeetsExpect(NetworkInfo *netInfo)
static bool CheckNicStatusMeetsExpect(NetworkInfo *netInfo, bool8 *isExeArping)
{
if (netInfo->cnt == 0) {
return true;
@ -791,7 +953,7 @@ static bool CheckNicStatusMeetsExpect(NetworkInfo *netInfo)
}
// only float ip is up, it will notify switch
if (netInfo->oper == NETWORK_OPER_UP) {
CheckArpingCmdRes(netInfo);
*isExeArping = CM_TRUE;
}
for (uint32 i = 0; i < netInfo->cnt; ++i) {
if (netInfo->stateRecord[i] != state) {
@ -801,7 +963,7 @@ static bool CheckNicStatusMeetsExpect(NetworkInfo *netInfo)
return true;
}
static void GenArpingCmdAndExecute(NetworkInfo *netInfo, uint32 index)
static void GenArpingCmd(NetworkInfo *netInfo, uint32 index, bool8 *isExeArping)
{
if (netInfo->oper != NETWORK_OPER_UP) {
return;
@ -813,12 +975,12 @@ static void GenArpingCmdAndExecute(NetworkInfo *netInfo, uint32 index)
"%s %s %s", ARPING_CMD, netInfo->netAddr[index].netName, netInfo->ips[index]);
securec_check_intval(rc, (void)rc);
}
ExecuteArpingCmd(&(netInfo->arpingCmd[index]), "[GenArpingCmdAndExecute]");
*isExeArping = CM_TRUE;
}
static void DoUpOrDownNetworkOper(NetworkInfo *netInfo)
static void DoUpOrDownNetworkOper(NetworkInfo *netInfo, bool8 *isExeArping)
{
if (CheckNicStatusMeetsExpect(netInfo)) {
if (CheckNicStatusMeetsExpect(netInfo, isExeArping)) {
return;
}
const char *str = (netInfo->oper == NETWORK_OPER_UP) ? "[DoUpNetworkOper]" : "[DoDownNetworkOper]";
@ -838,6 +1000,7 @@ static void DoUpOrDownNetworkOper(NetworkInfo *netInfo)
GetNicDownCmd(cmd, CM_MAX_COMMAND_LONG_LEN, netInfo, i);
}
if (cmd[0] == '\0') {
GenArpingCmd(netInfo, i, isExeArping);
continue;
}
write_runlog(LOG, "%s Ip: %s oper=[%d: %s], state=[%d: %s], GetNicCmd(%s).\n", str, netInfo->ips[i],
@ -854,20 +1017,38 @@ static void DoUpOrDownNetworkOper(NetworkInfo *netInfo)
} else {
netInfo->stateRecord[i] = GetNetworkStateByOper(netInfo->oper);
write_runlog(LOG, "%s successfully to execute the cmd(%s).\n", str, cmd);
GenArpingCmdAndExecute(netInfo, i);
GenArpingCmd(netInfo, i, isExeArping);
}
}
}
static void CheckAndExecuteArpingCmd()
{
NetworkInfo *manaIp;
for (uint32 i = 0; i < g_instCnt; ++i) {
manaIp = &(g_cmNetWorkInfo[i].manaIp[NETWORK_TYPE_FLOATIP]);
CheckArpingCmdRes(manaIp);
}
}
static void DoNetworkOper()
{
if (!IsNeedCheckFloatIp() || (agent_backup_open != CLUSTER_PRIMARY)) {
write_runlog(DEBUG1, "[DoNetworkOper] agent_backup_open=%d, cannot set floatIp oper.\n",
(int32)agent_backup_open);
return;
}
NetworkInfo *manaIp = NULL;
bool8 isExeArping = CM_FALSE;
for (uint32 i = 0; i < g_instCnt; ++i) {
manaIp = &(g_cmNetWorkInfo[i].manaIp[NETWORK_TYPE_FLOATIP]);
if (manaIp->oper == NETWORK_OPER_UNKNOWN) {
continue;
}
DoUpOrDownNetworkOper(manaIp);
DoUpOrDownNetworkOper(manaIp, &isExeArping);
}
if (isExeArping) {
CheckAndExecuteArpingCmd();
}
}
@ -894,6 +1075,31 @@ status_t CreateNetworkResource()
return CM_SUCCESS;
}
static uint8 CheckSingleFloatIpDown(const NetworkInfo *manaIp)
{
for (uint32 i = 0; i < manaIp->cnt; ++i) {
if (manaIp->stateRecord[i] == NETWORK_STATE_UP) {
return CM_FALSE;
}
}
return CM_TRUE;
}
static uint8 IsAllFloatIpDown()
{
NetworkInfo *manaIp = NULL;
for (uint32 i = 0; i < g_instCnt; ++i) {
manaIp = &(g_cmNetWorkInfo[i].manaIp[NETWORK_TYPE_FLOATIP]);
if (manaIp->cnt == 0) {
continue;
}
if (!CheckSingleFloatIpDown(manaIp)) {
return CM_FALSE;
}
}
return CM_TRUE;
}
void *CmaCheckNetWorkMain(void *arg)
{
thread_name = "CheckNetWork";
@ -902,7 +1108,7 @@ void *CmaCheckNetWorkMain(void *arg)
uint32 sleepInterval = 1;
bool networkRes = false;
for (;;) {
if ((g_exitFlag || g_shutdownRequest)) {
if ((g_exitFlag || g_shutdownRequest) && IsAllFloatIpDown()) {
cm_sleep(sleepInterval);
continue;
}

View File

@ -61,8 +61,10 @@ static bool IsDNCoredump(uint32 dnId)
static bool DnPhonyDeadProcessE2E(int dnId, int phonyDead)
{
if (phonyDead == PROCESS_PHONY_DEAD_D) {
/* Verify that the short link to dn is available */
if (CheckDnStausPhonyDead(dnId, (int)agent_phony_dead_check_interval) != 0) {
if (IsDatanodeSSMode()) {
write_runlog(LOG, "[%s] dn is D status, but in ss mode, can't process the D status.\n", __FUNCTION__);
} else if (CheckDnStausPhonyDead(dnId, (int)agent_phony_dead_check_interval) != 0) {
/* Verify that the short link to dn is available */
g_dnPhonyDeadD[dnId] = true;
write_runlog(WARNING, "dn_%u phony dead D\n", g_currentNode->datanode[dnId].datanodeId);
return true;
@ -105,7 +107,12 @@ static bool DnPhonyDeadStatusCheck(int dnId, uint32 *agentCheckTimeInterval)
return false;
}
if (phonyDead == PROCESS_PHONY_DEAD_D) {
return true;
if (IsDatanodeSSMode()) {
write_runlog(LOG, "[%s] dn is D status, but in ss mode, can't process the D status.\n", __FUNCTION__);
return false;
} else {
return true;
}
}
if (phonyDead == PROCESS_PHONY_DEAD_T) {
if (g_clusterType != V3SingleInstCluster && g_agentCheckTStatusInterval > agent_phony_dead_check_interval) {
@ -249,4 +256,4 @@ void *FaultDetectMain(void *arg)
}
return NULL;
}
}

View File

@ -24,6 +24,7 @@
#include "securec.h"
#include "cm/cm_elog.h"
#include "cm/cm_msg.h"
#include "cm/cm_util.h"
#include "cma_common.h"
#include "cma_global_params.h"
#include "cma_client.h"
@ -34,6 +35,7 @@
#include "cma_instance_management_res.h"
#include "cma_instance_check.h"
#include "cma_mes.h"
#include "cma_instance_management_res.h"
#include "cma_process_messages.h"
#ifdef ENABLE_MULTIPLE_NODES
#include "cma_coordinator.h"
@ -66,6 +68,23 @@ static void InstancesStatusCheckAndReport(void)
}
}
static void WillSetFloatIpOper(uint32 instId, NetworkOper oper, const char *str)
{
if (!IsNeedCheckFloatIp() || (agent_backup_open != CLUSTER_PRIMARY)) {
write_runlog(LOG, "%s agent_backup_open=%d, cannot set floatIp oper.\n", str, (int32)agent_backup_open);
return;
}
uint32 dnIdx = 0;
bool ret = FindDnIdxInCurNode(instId, &dnIdx, str);
if (!ret) {
write_runlog(ERROR, "%s cannot do the network oper in instId(%u), because it cannot be found in "
"current node.\n", str, instId);
return;
}
SetNicOper(instId, CM_INSTANCE_TYPE_DN, NETWORK_TYPE_FLOATIP, oper);
SetFloatIpOper(dnIdx, oper, str);
}
static void AgentSendHeartbeat()
{
agent_to_cm_heartbeat hbMsg = {0};
@ -473,6 +492,7 @@ static void process_failover_command(const char* dataDir, int instanceType, uint
instanceName);
/* report the alarm */
ReportCMAEventAlarm(AlarmFailOver, &tempAdditionalParam);
WillSetFloatIpOper(instance_id, NETWORK_OPER_UP, "[process_failover_command]");
break;
default:
write_runlog(LOG, "node_type is unknown !\n");
@ -1746,7 +1766,38 @@ static void MsgCmAgentResArbitrate(const AgentMsgPkg *msg, char *dataPath, const
if (recvMsg == NULL) {
return;
}
ProcessResRegFromCms(recvMsg);
static uint64 processTime = 0;
static const uint64 processInterval = 1000;
uint64 curTime = GetMonotonicTimeMs();
if ((curTime - processTime) > processInterval) {
ProcessResRegFromCms(recvMsg);
processTime = curTime;
}
}
static void ProcessFloatIpFromCms(const CmsDnFloatIpAck *recvMsg)
{
NetworkOper oper = ChangeInt2NetworkOper(recvMsg->oper);
if (oper == NETWORK_OPER_UNKNOWN) {
return;
}
write_runlog(LOG, "receive floatIp oper msg(%d=%s) from cms.\n", (int32)oper, GetOperMapString(oper));
WillSetFloatIpOper(recvMsg->baseInfo.instId, oper, "[ProcessFloatIpFromCms]");
}
static void MsgCmAgentFloatIpAck(const AgentMsgPkg *msg, char *dataPath, const cm_msg_type *msgTypePtr)
{
const CmsDnFloatIpAck *recvMsg = (const CmsDnFloatIpAck *)CmGetMsgBytesPtr(msg, sizeof(CmsDnFloatIpAck));
if (recvMsg == NULL) {
return;
}
if (!IsNeedCheckFloatIp() || (agent_backup_open != CLUSTER_PRIMARY)) {
write_runlog(DEBUG1, "[MsgCmAgentFloatIpAck] agent_backup_open=%d, cannot set floatIp oper.\n",
(int32)agent_backup_open);
return;
}
ProcessFloatIpFromCms(recvMsg);
}
static void MsgCmAgentIsregCheckListChanged(const AgentMsgPkg *msg, char *dataPath, const cm_msg_type *msgTypePtr)
@ -1906,7 +1957,7 @@ void CmServerCmdProcessorInit(void)
g_cmsCmdProcessor[MSG_GET_SHARED_STORAGE_INFO_ACK] = MsgCmAgentGetSharedStorageModeAck;
g_cmsCmdProcessor[MSG_CM_RES_LOCK_ACK] = MsgCmAgentResLockAck;
g_cmsCmdProcessor[MSG_CM_RES_REG] = MsgCmAgentResArbitrate;
g_cmsCmdProcessor[MSG_CM_AGENT_FLOAT_IP_ACK] = NULL;
g_cmsCmdProcessor[MSG_CM_AGENT_FLOAT_IP_ACK] = MsgCmAgentFloatIpAck;
g_cmsCmdProcessor[MSG_CM_AGENT_ISREG_CHECK_LIST_CHANGED] = MsgCmAgentIsregCheckListChanged;
#ifdef ENABLE_MULTIPLE_NODES
g_cmsCmdProcessor[MSG_CM_AGENT_NOTIFY_CN] = MsgCmAgentNotifyCn;
@ -2010,6 +2061,7 @@ void *ProcessSendCmsMsgMain(void *arg)
struct timespec lastReportTime = {0, 0};
struct timespec currentTime = {0, 0};
long expiredTime = 0;
const uint32 overLongTime = 1000;
(void)clock_gettime(CLOCK_MONOTONIC, &lastReportTime);
pthread_t threadId = pthread_self();
thread_name = "SendCmsMsg";
@ -2029,13 +2081,22 @@ void *ProcessSendCmsMsgMain(void *arg)
write_runlog(LOG, "connection to cm_server %u seconds timeout expired .\n", agent_heartbeat_timeout);
g_cmServerNeedReconnect = true;
}
uint64 t1 = GetMonotonicTimeMs();
ReportInstanceStatus();
uint64 t2 = GetMonotonicTimeMs();
if (etcdTimeReportInterval >= AGENT_REPORT_ETCD_CYCLE || etcdTimeReportInterval == 0) {
EtcdCurrentTimeReport();
etcdTimeReportInterval = 0;
}
etcdTimeReportInterval++;
(void)clock_gettime(CLOCK_MONOTONIC, &lastReportTime);
uint64 t3 = GetMonotonicTimeMs();
if ((t3 - t1) > overLongTime) {
write_runlog(LOG, "[%s] ReportInstanceStatus=%lu, EtcdCurrentTimeReport=%lu.\n",
__FUNCTION__, (t2 - t1), (t3 - t2));
}
}
CmUsleep(AGENT_RECV_CYCLE);
}
@ -2068,21 +2129,44 @@ void *ProcessRecvCmsMsgMain(void *arg)
thread_name = "ProcessCmsMsg";
write_runlog(LOG, "process cms msg thread begin, threadId:%lu.\n", (unsigned long)pthread_self());
int32 msgType;
const uint32 overLongTime = 3000;
for (;;) {
if (g_shutdownRequest) {
cm_sleep(5);
continue;
}
msgType = -1;
MsgQueue &recvQueue = GetCmsRecvQueue();
uint64 t1 = GetMonotonicTimeMs();
(void)pthread_mutex_lock(&recvQueue.lock);
uint64 t2 = GetMonotonicTimeMs();
while (recvQueue.msg.empty()) {
(void)pthread_cond_wait(&recvQueue.cond, &recvQueue.lock);
}
uint64 t3 = GetMonotonicTimeMs();
AgentMsgPkg msgPkg = recvQueue.msg.front();
recvQueue.msg.pop();
uint64 t4 = GetMonotonicTimeMs();
(void)pthread_mutex_unlock(&recvQueue.lock);
uint64 t5 = GetMonotonicTimeMs();
ProcessCmServerCmd(&msgPkg);
if (msgPkg.msgLen >= (sizeof(int32))) {
msgType = *(int *)(msgPkg.msgPtr);
}
uint64 t6 = GetMonotonicTimeMs();
FreeBufFromMsgPool(msgPkg.msgPtr);
uint64 t7 = GetMonotonicTimeMs();
if ((t7 - t1) > overLongTime) {
write_runlog(LOG, "[%s] lock=%lu, wait=%lu, pop=%lu, unlock=%lu, process=%lu, free=%lu, msgType=%d.\n",
__FUNCTION__, (t2 - t1), (t3 - t2), (t4 - t3), (t5 - t4), (t6 - t5), (t7 - t6), msgType);
}
}
return NULL;

View File

@ -31,6 +31,15 @@
#include "cma_instance_management_res.h"
#include "cma_process_messages_client.h"
void NotifyClientConnectClose()
{
AgentToClientNotify cmaMsg = {{0}};
cmaMsg.head.msgType = (uint32)MSG_AGENT_CLIENT_NOTIFY_CONN_CLOSE;
cmaMsg.notify.isCmaConnClose = CM_TRUE;
PushMsgToAllClientSendQue((char*)&cmaMsg, sizeof(cmaMsg));
}
static void SendHeartbeatAckToClient(uint32 conId)
{
MsgHead hbAck = {0};
@ -53,19 +62,10 @@ static void SendStatusListToClient(CmResStatList &statList, uint32 conId, bool i
(void)pthread_rwlock_rdlock(&(statList.rwlock));
rc = memcpy_s(&sendList.resStatusList, sizeof(OneResStatList), &statList.status, sizeof(OneResStatList));
(void)pthread_rwlock_unlock(&(statList.rwlock));
securec_check_errno(rc, (void)rc);
(void)pthread_rwlock_unlock(&(statList.rwlock));
write_runlog(LOG, "[CLIENT] send status list to res(%s), version=%llu.\n",
sendList.resStatusList.resName, sendList.resStatusList.version);
for (uint32 i = 0; i < sendList.resStatusList.instanceCount; ++i) {
write_runlog(LOG, "nodeId=%u,instanceId=%u,resInstanceId=%u,status=%d,isWork=%u\n",
sendList.resStatusList.resStat[i].nodeId,
sendList.resStatusList.resStat[i].cmInstanceId,
sendList.resStatusList.resStat[i].resInstanceId,
(int)sendList.resStatusList.resStat[i].status,
sendList.resStatusList.resStat[i].isWorkMember);
}
PrintCusInfoResList(&sendList.resStatusList, __FUNCTION__);
PushMsgToClientSendQue((char*)&sendList, sizeof(AgentToClientResList), conId);
}
@ -242,19 +242,6 @@ static void UpdateResStatusList(CmResStatList *resStat, const OneResStatList *ne
securec_check_errno(rc, (void)rc);
}
static void PrintLatestResStatusList(const OneResStatList *resStat)
{
write_runlog(LOG, "[CLIENT] res(%s) statList changed, version=%llu.\n", resStat->resName, resStat->version);
for (uint32 i = 0; i < resStat->instanceCount; ++i) {
write_runlog(LOG, "nodeId=%u,cmInstanceId=%u,resInstanceId=%u,status=%u,isWork=%u\n",
resStat->resStat[i].nodeId,
resStat->resStat[i].cmInstanceId,
resStat->resStat[i].resInstanceId,
resStat->resStat[i].status,
resStat->resStat[i].isWorkMember);
}
}
void ProcessResStatusList(const CmsReportResStatList *msg)
{
if (msg->resList.instanceCount > CM_MAX_RES_INST_COUNT) {
@ -270,7 +257,7 @@ void ProcessResStatusList(const CmsReportResStatList *msg)
}
UpdateResStatusList(&g_resStatus[index], &msg->resList);
PrintLatestResStatusList(&msg->resList);
PrintCusInfoResList(&msg->resList, __FUNCTION__);
}
void ProcessResStatusChanged(const CmsReportResStatList *msg)

View File

@ -811,9 +811,22 @@ static void SendDiskUsageMsg(const DnStatus *pkgDnStatus, uint32 datanodeId)
PushMsgToCmsSendQue((char *)&diskUsageMsg, (uint32)sizeof(AgentToCmDiskUsageStatusReport), "dnDiskUsage");
}
static void SendFloatIpMsg(const CmaDnFloatIpInfo *floatIpInfo, uint32 dnId)
{
if (!IsNeedCheckFloatIp() || (agent_backup_open != CLUSTER_PRIMARY)) {
return;
}
if (floatIpInfo->info.count == 0) {
return;
}
write_runlog(DEBUG5, "dn(%u) floatIpMsg will send to cms.\n", dnId);
PushMsgToCmsSendQue((const char *)floatIpInfo, (uint32)sizeof(CmaDnFloatIpInfo), "dn floatIpMsg");
}
static void SendDnReportMsgCore(const DnStatus *pkgDnStatus, uint32 datanodeId, AgentToCmserverDnSyncList *syncListMsg)
{
SendDnReportMsg(pkgDnStatus, datanodeId);
SendFloatIpMsg(&(pkgDnStatus->floatIpInfo), datanodeId);
if (g_clusterType == V3SingleInstCluster) {
return;
}
@ -961,10 +974,26 @@ void InitDnLocalPeerMsg(AgentCmDnLocalPeer *lpInfo, int32 index)
lpInfo->instanceType = INSTANCE_TYPE_DATANODE;
}
static void SetDnBaseMsg(BaseInstInfo *baseInfo, int32 index, int32 msgType)
{
baseInfo->msgType = msgType;
baseInfo->instId = g_currentNode->datanode[index].datanodeId;
baseInfo->node = g_currentNode->node;
baseInfo->instType = INSTANCE_TYPE_DATANODE;
}
static void InitDnFloatIpMsg(CmaDnFloatIpInfo *ipInfo, int32 index)
{
errno_t rc = memset_s(ipInfo, sizeof(CmaDnFloatIpInfo), 0, sizeof(CmaDnFloatIpInfo));
securec_check_errno(rc, (void)rc);
SetDnBaseMsg(&(ipInfo->baseInfo), index, (int32)MSG_AGENT_CM_FLOAT_IP);
}
void InitDNStatus(DnStatus *dnStatus, int i)
{
InitReportMsg(&dnStatus->reportMsg, i);
InitDnLocalPeerMsg(&(dnStatus->lpInfo), i);
InitDnFloatIpMsg(&(dnStatus->floatIpInfo), i);
}
static void ChangeLocalRoleInBackup(int dnIdx, int *localDnRole)
@ -1071,7 +1100,7 @@ void* DNStatusCheckMain(void *arg)
int ret = snprintf_s(instanceName, sizeof(instanceName), sizeof(instanceName) - 1,
"%s_%u", "dn", g_currentNode->datanode[i].datanodeId);
securec_check_intval(ret, (void)ret);
int runing = PROCESS_UNKNOWN;
int32 running = PROCESS_UNKNOWN;
for (;;) {
set_thread_state(threadId);
@ -1084,8 +1113,9 @@ void* DNStatusCheckMain(void *arg)
}
InitDNStatus(&dnStatus, i);
running = check_one_instance_status(GetDnProcessName(), g_currentNode->datanode[i].datanodeLocalDataPath, NULL);
if (g_currentNode->datanode[i].datanodeRole != DUMMY_STANDBY_DN) {
ret = DatanodeStatusCheck(&dnStatus, (uint32)i);
ret = DatanodeStatusCheck(&dnStatus, (uint32)i, running);
}
if (ret < 0 || g_currentNode->datanode[i].datanodeRole == DUMMY_STANDBY_DN) {
@ -1093,13 +1123,11 @@ void* DNStatusCheckMain(void *arg)
write_runlog(ERROR, "DatanodeStatusCheck failed, ret=%d\n", ret);
}
runing = check_one_instance_status(GetDnProcessName(), g_currentNode->datanode[i].datanodeLocalDataPath,
NULL);
if (g_currentNode->datanode[i].datanodeRole == DUMMY_STANDBY_DN &&
dnStatus.reportMsg.processStatus != INSTANCE_PROCESS_RUNNING && runing != PROCESS_RUNNING) {
dnStatus.reportMsg.processStatus != INSTANCE_PROCESS_RUNNING && running != PROCESS_RUNNING) {
checkDummyTimes = CHECK_DUMMY_STATE_TIMES;
}
if (runing == PROCESS_RUNNING) {
if (running == PROCESS_RUNNING) {
if (g_currentNode->datanode[i].datanodeRole == DUMMY_STANDBY_DN && checkDummyTimes > 0) {
checkDummyTimes--;
}
@ -1206,6 +1234,7 @@ void* DNStatusCheckMain(void *arg)
write_runlog(DEBUG5, "DatanodeStatusCheck: local role is %d, db state is %d, build reason is %d\n",
dnStatus.reportMsg.local_status.local_role, dnStatus.reportMsg.local_status.db_state,
dnStatus.reportMsg.local_status.buildReason);
DnCheckFloatIp(&dnStatus, (uint32)i, (bool8)(running == PROCESS_RUNNING));
(void)pthread_rwlock_wrlock(&(g_dnReportMsg[i].lk_lock));
rc = memcpy_s((void *)&(g_dnReportMsg[i].dnStatus.lpInfo), sizeof(AgentCmDnLocalPeer),
(void *)&dnStatus.lpInfo, sizeof(AgentCmDnLocalPeer));
@ -1213,6 +1242,9 @@ void* DNStatusCheckMain(void *arg)
rc = memcpy_s((void *)&(g_dnReportMsg[i].dnStatus.reportMsg), sizeof(agent_to_cm_datanode_status_report),
(void *)&dnStatus.reportMsg, sizeof(agent_to_cm_datanode_status_report));
securec_check_errno(rc, (void)rc);
rc = memcpy_s((void *)&(g_dnReportMsg[i].dnStatus.floatIpInfo), sizeof(CmaDnFloatIpInfo),
(void *)&dnStatus.floatIpInfo, sizeof(CmaDnFloatIpInfo));
securec_check_errno(rc, (void)rc);
(void)pthread_rwlock_unlock(&(g_dnReportMsg[i].lk_lock));
cm_sleep(agent_report_interval);

View File

@ -217,19 +217,20 @@ void SendResIsregReportMsg()
// check res status
static void DoCheckResourceStatus(CmResConfList *resConf, CmResourceStatus *resStat)
{
long curTime = GetCurMonotonicTimeSec();
static uint32 latestStat = (uint32)CUS_RES_CHECK_STAT_UNKNOWN;
if (resConf->checkInfo.checkTime == 0) {
resStat->status = (uint32)CheckOneResInst(resConf);
resConf->checkInfo.checkTime = time(NULL);
resConf->checkInfo.checkTime = curTime;
latestStat = resStat->status;
return;
}
if ((time(NULL) - resConf->checkInfo.checkTime) < resConf->checkInfo.checkInterval) {
if ((curTime - resConf->checkInfo.checkTime) < resConf->checkInfo.checkInterval) {
resStat->status = latestStat;
return;
}
resStat->status = (uint32)CheckOneResInst(resConf);
resConf->checkInfo.checkTime = time(NULL);
resConf->checkInfo.checkTime = curTime;
latestStat = resStat->status;
}

View File

@ -69,7 +69,7 @@ OneResStatList *GetClientStatusList()
static timespec GetMutexTimeout(time_t timeout)
{
struct timespec releaseTime = { 0, 0 };
(void)clock_gettime(CLOCK_REALTIME, &releaseTime);
(void)clock_gettime(CLOCK_MONOTONIC, &releaseTime);
releaseTime.tv_sec = releaseTime.tv_sec + timeout;
return releaseTime;
@ -445,6 +445,31 @@ static status_t RecvResLockAckProcess()
return CM_SUCCESS;
}
static void SetLockApiFailed()
{
(void)pthread_mutex_lock(&g_lockFlag->condLock);
g_lockFlag->error = (uint32)CM_RES_CLIENT_CONNECT_ERR;
(void)pthread_mutex_unlock(&g_lockFlag->condLock);
(void)pthread_cond_signal(&g_lockFlag->cond);
}
static status_t RecvCmaConnClose()
{
CmaNotifyClient cmaMsg = {0};
if (CmClientRecvMsg((char*)&cmaMsg, sizeof(CmaNotifyClient)) != CM_SUCCESS) {
write_runlog(ERROR, "[%s] client recv msg agent fail or timeout.\n", __FUNCTION__);
return CM_ERROR;
}
if (cmaMsg.isCmaConnClose) {
write_runlog(LOG, "the CMA and CMS are disconnected.\n");
SetLockApiFailed();
}
return CM_SUCCESS;
}
static status_t RecvMsgFromAgent()
{
MsgHead msgHead = {0};
@ -468,6 +493,9 @@ static status_t RecvMsgFromAgent()
case MSG_CM_RES_LOCK_ACK:
CM_RETURN_IFERR(RecvResLockAckProcess());
break;
case MSG_AGENT_CLIENT_NOTIFY_CONN_CLOSE:
CM_RETURN_IFERR(RecvCmaConnClose());
break;
default:
write_runlog(ERROR, "recv unknown msg, msgType(%u).\n", msgHead.msgType);
return CM_ERROR;
@ -567,17 +595,17 @@ static void InitGlobalVariable(const char *resName)
g_initFlag->initSuccess = false;
(void)pthread_mutex_init(&g_initFlag->lock, NULL);
(void)pthread_cond_init(&g_initFlag->cond, NULL);
InitPthreadCondMonotonic(&g_initFlag->cond);
while (!g_sendMsg->sendQueue.empty()) {
g_sendMsg->sendQueue.pop();
}
(void)pthread_mutex_init(&g_sendMsg->lock, NULL);
(void)pthread_cond_init(&g_sendMsg->cond, NULL);
InitPthreadCondMonotonic(&g_sendMsg->cond);
(void)pthread_mutex_init(&g_lockFlag->condLock, NULL);
(void)pthread_mutex_init(&g_lockFlag->optLock, NULL);
(void)pthread_cond_init(&g_lockFlag->cond, NULL);
InitPthreadCondMonotonic(&g_lockFlag->cond);
}
status_t PreInit(uint32 instanceId, const char *resName, CmNotifyFunc func, bool *isFirstInit)

View File

@ -21,7 +21,9 @@
*
* -------------------------------------------------------------------------
*/
#include "cm_defs.h"
#include "elog.h"
#include "cm_text.h"
#include "cm_json_config.h"
#define CM_SET_READ_JSON_ERR(errPtr, err) \
@ -35,6 +37,7 @@ typedef void (*ParseCusRes)(const cJSON *resJson, OneCusResConfJson *resConf);
static void ParseAppResConfJson(const cJSON *resJson, OneCusResConfJson *resConf);
static void ParseDnResConfJson(const cJSON *resJson, OneCusResConfJson *resConf);
static void ParseVipResConfJson(const cJSON *resJson, OneCusResConfJson *resConf);
static void EmptyCmJsonWriteLog(int logLevel, const char *format, ...)
{
@ -53,6 +56,7 @@ static CmJsonLogOutput CmJsonWriteLog = EmptyCmJsonWriteLog;
static ParseCusResMap g_cusResMap[] = {
{"APP", CUSTOM_RESOURCE_APP, ParseAppResConfJson},
{"DN", CUSTOM_RESOURCE_DN, ParseDnResConfJson},
{"VIP", CUSTOM_RESOURCE_VIP, ParseVipResConfJson},
};
static void *CmJsonMalloc(size_t size)
@ -188,6 +192,9 @@ static void ParseAppDnResConfJson(const cJSON *resJson, CusResConfJson *resConf)
if (GetValueIntFromJson(&resConf->restartTimes, resJson, "restart_times") != 0) {
resConf->restartTimes = defValue;
}
if (GetValueIntFromJson(&resConf->abnormalTimeout, resJson, "abnormal_timeout") != 0) {
resConf->abnormalTimeout = defValue;
}
}
static void ParseAppResConfJson(const cJSON *resJson, OneCusResConfJson *resConf)
@ -202,6 +209,106 @@ static void ParseDnResConfJson(const cJSON *resJson, OneCusResConfJson *resConf)
ParseAllCusResInstConfJson(resJson, &resConf->dnResConf);
}
int FetchStrFromText(const char *textStr, char *result, uint32 len, char beginPoint)
{
bool8 isFetch = CM_FALSE;
uint32 point = 0;
for (uint32 i = 0; textStr[i] != '\0'; ++i) {
if (!isFetch) {
if (textStr[i] == beginPoint) {
isFetch = CM_TRUE;
}
continue;
}
if (textStr[i] == SEPARATOR_CHAR) {
break;
}
if (point >= len) {
return -1;
}
result[point] = textStr[i];
++point;
}
CmTrimStr(result);
if (result[0] == '\0') {
return -1;
}
return 0;
}
int GetValueStrFromText(char *result, uint32 resultLen, const char *textStr, const char *expectValue)
{
const char *point = strstr(textStr, expectValue);
if (point == NULL) {
write_runlog(ERROR, "Failed to get value str from text, when textStr=[%s], expectValue=[%s].\n",
textStr, expectValue);
return -1;
}
if (FetchStrFromText(point, result, resultLen, '=') != 0) {
write_runlog(ERROR, "Failed to fetch text from string, when textStr=[%s], expectValue=[%s].\n",
textStr, expectValue);
return -1;
}
return 0;
}
static void ParseOneBaseIp(const cJSON *ipJson, BaseIpListConf *ipConf)
{
if (GetValueIntFromJson(&ipConf->instId, ipJson, "res_instance_id") != 0) {
ipConf->instId = 0;
}
char baseIp[CM_JSON_STR_LEN] = {0};
if (GetValueStrFromJson(baseIp, CM_JSON_STR_LEN, ipJson, "inst_attr") != 0) {
return;
}
if (GetValueStrFromText(ipConf->baseIp, CM_JSON_STR_LEN, baseIp, "base_ip") != 0) {
errno_t rc = memset_s(ipConf->baseIp, CM_JSON_STR_LEN, 0, CM_JSON_STR_LEN);
securec_check_errno(rc, (void)rc);
}
}
static void ParseAllBaseIp(const cJSON *resJson, VipCusResConfJson *resConf)
{
cJSON *baseIpArray = cJSON_GetObjectItem(resJson, "instances");
if (!cJSON_IsArray(baseIpArray)) {
if (baseIpArray != NULL) {
CmJsonWriteLog(WARNING, "[ReadConfJson] \"instances\" obj is not an array, can't parse continue.\n");
}
return;
}
int arrLen = cJSON_GetArraySize(baseIpArray);
if (arrLen <= 0) {
CmJsonWriteLog(WARNING, "[ReadConfJson] baseIp array len invalid, arrLen=%d, can't parse continue.\n", arrLen);
return;
}
resConf->baseIpList.count = (uint32)arrLen;
resConf->baseIpList.conf = (BaseIpListConf*)CmJsonMalloc((uint32)arrLen * sizeof(BaseIpListConf));
for (int i = 0; i < arrLen; ++i) {
cJSON *resItem = cJSON_GetArrayItem(baseIpArray, i);
if (resItem != NULL) {
ParseOneBaseIp(resItem, &resConf->baseIpList.conf[i]);
}
}
}
static void ParseVipResConfJson(const cJSON *resJson, OneCusResConfJson *resConf)
{
errno_t rc;
if (GetValueStrFromJson(resConf->vipResConf.resName, CM_JSON_STR_LEN, resJson, "name") != 0) {
rc = memset_s(resConf->vipResConf.resName, CM_JSON_STR_LEN, 0, CM_JSON_STR_LEN);
securec_check_errno(rc, (void)rc);
}
if (GetValueStrFromJson(resConf->vipResConf.floatIp, CM_JSON_STR_LEN, resJson, "float_ip") != 0) {
rc = memset_s(resConf->vipResConf.floatIp, CM_JSON_STR_LEN, 0, CM_JSON_STR_LEN);
securec_check_errno(rc, (void)rc);
}
ParseAllBaseIp(resJson, &resConf->vipResConf);
}
static void ParseOneCusResConfJson(const cJSON *resItem, OneCusResConfJson *resConf)
{
char resType[CM_JSON_STR_LEN] = {0};
@ -211,7 +318,7 @@ static void ParseOneCusResConfJson(const cJSON *resItem, OneCusResConfJson *resC
}
size_t arrLen = sizeof(g_cusResMap) / sizeof(g_cusResMap[0]);
for (size_t i = 0; i < arrLen; ++i) {
for (size_t i = 0; i < arrLen; ++i) {
if (strcmp(resType, g_cusResMap[i].resTypeName) == 0) {
resConf->resType = g_cusResMap[i].resType;
g_cusResMap[i].parseFunc(resItem, resConf);

View File

@ -0,0 +1,166 @@
/*
* Copyright (c) 2022 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.
* -------------------------------------------------------------------------
*
* cm_json_parse_floatIp.cpp
*
*
* IDENTIFICATION
* src/cm_common/cm_json_parse_floatIp.cpp
*
* -------------------------------------------------------------------------
*/
#include "cm_json_parse_floatIp.h"
#include "cm_elog.h"
#include "cm_misc.h"
#include "cm_json_config.h"
static const ParseFloatIpFunc *g_parseFuc = NULL;
static DnFloatIp *CmGetDnFloatIpByDnIdx(uint32 nodeIdx, uint32 dnIdx)
{
if (g_parseFuc == NULL || g_parseFuc->getFloatIp == NULL) {
return NULL;
}
return g_parseFuc->getFloatIp(nodeIdx, dnIdx);
}
static bool IsBaseIpInDnFloatIp(const char *baseIp, const char *floatIp, uint32 nodeIdx, uint32 dnIdx)
{
DnFloatIp *dnFloatIp = CmGetDnFloatIpByDnIdx(nodeIdx, dnIdx);
if (dnFloatIp == NULL) {
return true;
}
for (uint32 i = 0; i < dnFloatIp->dnFloatIpCount; ++i) {
if (strcmp(baseIp, dnFloatIp->baseIp[i]) == 0) {
write_runlog(LOG, "instId(%u) baseIp(%s) may be existed in floatIp.\n", dnFloatIp->instId, baseIp);
return true;
}
if (strcmp(floatIp, dnFloatIp->dnFloatIp[i]) == 0) {
write_runlog(LOG, "instId(%u) floatIp(%s) may be existed in floatIp.\n", dnFloatIp->instId, floatIp);
return true;
}
}
return false;
}
static void CmIncreaseFloatIpCnt(uint32 nodeIdx)
{
if (g_parseFuc == NULL || g_parseFuc->increaseCnt == NULL) {
return;
}
g_parseFuc->increaseCnt(nodeIdx);
}
static void GenDnFloat(uint32 nodeIdx, uint32 dnIdx, const char *baseIp, const char *floatIp, const char *floatIpName)
{
DnFloatIp *dnFloatIp = CmGetDnFloatIpByDnIdx(nodeIdx, dnIdx);
if (dnFloatIp == NULL) {
return;
}
if (IsBaseIpInDnFloatIp(baseIp, floatIp, nodeIdx, dnIdx)) {
return;
}
dnFloatIp->instId = g_currentNode->datanode[dnIdx].datanodeId;
dnFloatIp->dataPath = g_currentNode->datanode[dnIdx].datanodeLocalDataPath;
dnFloatIp->dnFloatIpPort = g_currentNode->datanode[dnIdx].datanodePort;
uint32 point = dnFloatIp->dnFloatIpCount;
if (point >= MAX_FLOAT_IP_COUNT) {
write_runlog(
LOG, "instId(%u) point(%u) more than maxCount(%u).\n", dnFloatIp->instId, point, MAX_FLOAT_IP_COUNT);
return;
}
if (point == 0) {
CmIncreaseFloatIpCnt(nodeIdx);
}
errno_t rc = strcpy_s(dnFloatIp->baseIp[point], CM_IP_LENGTH, baseIp);
securec_check_errno(rc, (void)rc);
rc = strcpy_s(dnFloatIp->dnFloatIp[point], CM_IP_LENGTH, floatIp);
securec_check_errno(rc, (void)rc);
rc = strncpy_s(dnFloatIp->floatIpName[point], CM_MAX_RES_NAME, floatIpName, CM_MAX_RES_NAME - 1);
securec_check_errno(rc, (void)rc);
++dnFloatIp->dnFloatIpCount;
}
static bool8 CmFindNodeInfoByInstId(uint32 instId, uint32 *nodeIdx, uint32 *dnIdx, const char *str)
{
if (g_parseFuc == NULL || g_parseFuc->findNodeInfo == NULL) {
return CM_FALSE;
}
return g_parseFuc->findNodeInfo(instId, nodeIdx, dnIdx, str);
}
static void CheckDnInstInItem(const VipCusResConfJson *vipConf, const char *floatIp, const char *floatIpName)
{
const char *str = "[CheckDnInstInItem]";
int32 instId;
uint32 nodeIdx;
uint32 dnIdx;
const char *baseIp;
for (uint32 i = 0; i < vipConf->baseIpList.count; ++i) {
instId = vipConf->baseIpList.conf[i].instId;
if (instId < 0) {
write_runlog(ERROR, "find the error insId(%d) in base_ip_list.\n", instId);
continue;
}
if (!CmFindNodeInfoByInstId((uint32)vipConf->baseIpList.conf[i].instId, &nodeIdx, &dnIdx, str)) {
continue;
}
if (CM_IS_EMPTY_STR(vipConf->baseIpList.conf[i].baseIp) ||
CheckIpValid(vipConf->baseIpList.conf[i].baseIp) == CM_FALSE) {
continue;
}
baseIp = vipConf->baseIpList.conf[i].baseIp;
check_input_for_security(baseIp);
if (strcmp(baseIp, floatIp) == 0) {
continue;
}
GenDnFloat(nodeIdx, dnIdx, baseIp, floatIp, floatIpName);
}
}
void ParseVipConf(int32 logLevel)
{
if (IsConfJsonEmpty()) {
write_runlog(logLevel, "ParseVipConf, no resource exist.\n");
return;
}
char floatIp[MAX_PATH_LEN];
const char *floatIpName;
errno_t rc;
for (uint32 i = 0; i < g_confJson->resource.count; ++i) {
if (g_confJson->resource.conf[i].resType != CUSTOM_RESOURCE_VIP) {
continue;
}
if (CM_IS_EMPTY_STR(g_confJson->resource.conf[i].vipResConf.floatIp) ||
CheckIpValid(g_confJson->resource.conf[i].vipResConf.floatIp) == CM_FALSE) {
continue;
}
rc = memset_s(floatIp, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(rc, (void)rc);
rc = strcpy_s(floatIp, MAX_PATH_LEN, g_confJson->resource.conf[i].vipResConf.floatIp);
securec_check_errno(rc, (void)rc);
floatIpName = g_confJson->resource.conf[i].vipResConf.resName;
check_input_for_security(floatIpName);
CheckDnInstInItem(&g_confJson->resource.conf[i].vipResConf, floatIp, floatIpName);
}
}
void InitParseFloatIpFunc(const ParseFloatIpFunc *parseFuc)
{
g_parseFuc = parseFuc;
}

View File

@ -782,7 +782,7 @@ cluster_msg_string cluster_msg_map_string[] = {
{"MSG_AGENT_CLIENT_HEARTBEAT_ACK", MSG_AGENT_CLIENT_HEARTBEAT_ACK},
{"MSG_AGENT_CLIENT_RES_STATUS_LIST", MSG_AGENT_CLIENT_RES_STATUS_LIST},
{"MSG_AGENT_CLIENT_RES_STATUS_CHANGE", MSG_AGENT_CLIENT_RES_STATUS_CHANGE},
{"MSG_AGENT_CLIENT_SET_RES_DATA_STATUS", MSG_AGENT_CLIENT_SET_RES_DATA_STATUS},
{"MSG_AGENT_CLIENT_NOTIFY_CONN_CLOSE", MSG_AGENT_CLIENT_NOTIFY_CONN_CLOSE},
{"MSG_AGENT_CLIENT_REPORT_RES_DATA", MSG_AGENT_CLIENT_REPORT_RES_DATA},
{"MSG_EXEC_DDB_COMMAND", MSG_EXEC_DDB_COMMAND},
{"EXEC_DDB_COMMAND_ACK", EXEC_DDB_COMMAND_ACK},
@ -810,6 +810,7 @@ cluster_msg_string cluster_msg_map_string[] = {
{"MSG_CTL_CM_NODE_DISK_STATUS_REQ", (int32)MSG_CTL_CM_NODE_DISK_STATUS_REQ},
{"MSG_CTL_CM_NODE_DISK_STATUS_ACK", (int32)MSG_CTL_CM_NODE_DISK_STATUS_ACK},
{"MSG_AGENT_CM_FLOAT_IP", (int32)MSG_AGENT_CM_FLOAT_IP},
{"MSG_CTL_CM_FLOAT_IP_REQ", (int32)MSG_CTL_CM_FLOAT_IP_REQ},
{"MSG_CM_AGENT_FLOAT_IP_ACK", (int32)MSG_CM_AGENT_FLOAT_IP_ACK},
{"MSG_AGENT_CM_ISREG_REPORT", (int32)MSG_AGENT_CM_ISREG_REPORT},
{"MSG_CM_AGENT_ISREG_CHECK_LIST_CHANGED", (int32)MSG_CM_AGENT_ISREG_CHECK_LIST_CHANGED},
@ -1310,3 +1311,11 @@ bool IsNodeIdValid(int nodeId)
}
return false;
}
bool IsNeedCheckFloatIp()
{
if (g_clusterType == SingleInstCluster) {
return true;
}
return false;
}

View File

@ -186,8 +186,18 @@ int GetHomePath(char *outputEnvValue, uint32 envValueLen, int32 logLevel)
bool IsBoolCmParamTrue(const char *param)
{
return (strcmp(param, "on") == 0) || (strcmp(param, "yes") == 0) ||
(strcmp(param, "true") == 0) || (strcmp(param, "1") == 0);
return (strcasecmp(param, "on") == 0) || (strcasecmp(param, "yes") == 0) || (strcasecmp(param, "true") == 0) ||
(strcasecmp(param, "1") == 0);
}
bool CheckBoolConfigParam(const char* value)
{
if (strcasecmp(value, "on") == 0 || strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0 ||
strcasecmp(value, "1") == 0 || strcasecmp(value, "off") == 0 || strcasecmp(value, "no") == 0 ||
strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
return true;
}
return false;
}
bool IsSharedStorageMode()
@ -283,3 +293,19 @@ status_t TcpRecvMsg(int socket, char *buf, size_t remainSize, uint32 timeout)
return CM_SUCCESS;
}
long GetCurMonotonicTimeSec()
{
struct timespec curTime = {0, 0};
(void)clock_gettime(CLOCK_MONOTONIC, &curTime);
return curTime.tv_sec;
}
void InitPthreadCondMonotonic(pthread_cond_t *cond)
{
pthread_condattr_t attr;
(void)pthread_condattr_init(&attr);
(void)pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
(void)pthread_cond_init(cond, &attr);
(void)pthread_condattr_destroy(&attr);
}

View File

@ -28,7 +28,18 @@
bool g_enableSharedStorage = false;
CmResStatList g_resStatus[CM_MAX_RES_COUNT] = {{0}};
uint32 g_resCount = 0;
static uint32 g_resCount = 0;
static bool8 g_isDnSSMode = CM_FALSE;
typedef enum IpTypeEn {
IP_TYPE_INIT = 0,
IP_TYPE_UNKNOWN = 1,
IP_TYPE_IPV4,
IP_TYPE_IPV6,
IP_TYPE_NEITHER,
IP_TYPE_CEIL,
} IpType;
typedef struct ResConfRangeSt {
const char *param;
@ -36,13 +47,34 @@ typedef struct ResConfRangeSt {
int max;
} ResConfRange;
typedef struct ResConfDefaultSt {
const char *param;
const char *defValue;
} ResConfDefault;
static ResConfRange g_resConfRange[] = {
{"check_interval", 1, 2147483647},
{"time_out", 1, 2147483647},
{"abnormal_timeout", 0, 2147483647},
{"restart_delay", 0, 1800},
{"restart_period", 0, 3600},
{"restart_times", -1, 9999},
{"instance_id", 1, 2147483647}
{"res_instance_id", 0, 2147483647}
};
static ResConfDefault g_resConfDef[] = {
{"resources_type", "APP"},
{"check_interval", "1"},
{"time_out", "10"},
{"abnormal_timeout", "30"},
{"restart_delay", "1"},
{"restart_period", "1"},
{"restart_times", "-1"},
{"res_instance_id", "0"},
{"one instance res_instance_id", "0"},
{"is_critical", "true"},
{"location_type", "local"},
{"location_attr", ""}
};
typedef status_t (*InitCusRes)(const OneCusResConfJson *oneResJson, OneResStatList *oneResStat);
@ -92,18 +124,44 @@ bool IsResConfValid(const char *param, int value)
if (strcmp(param, g_resConfRange[i].param) != 0) {
continue;
}
int minValue = g_resConfRange[i].min;
int maxValue = g_resConfRange[i].max;
if (value >= minValue && value <= maxValue) {
return true;
} else {
write_runlog(ERROR, "\"%s\":%d invalid, range [%d, %d].\n", param, value, minValue, maxValue);
return false;
}
return (value >= g_resConfRange[i].min && value <= g_resConfRange[i].max);
}
return false;
}
int ResConfMaxValue(const char *param)
{
uint32 arrLen = (sizeof(g_resConfRange) / sizeof(g_resConfRange[0]));
for (uint32 i = 0; i < arrLen; ++i) {
if (strcmp(param, g_resConfRange[i].param) == 0) {
return g_resConfRange[i].max;
}
}
return INT32_MAX;
}
int ResConfMinValue(const char *param)
{
uint32 arrLen = (sizeof(g_resConfRange) / sizeof(g_resConfRange[0]));
for (uint32 i = 0; i < arrLen; ++i) {
if (strcmp(param, g_resConfRange[i].param) == 0) {
return g_resConfRange[i].min;
}
}
return INT32_MIN;
}
const char* ResConfDefValue(const char *param)
{
uint32 arrLen = (sizeof(g_resConfDef) / sizeof(g_resConfDef[0]));
for (uint32 i = 0; i < arrLen; ++i) {
if (strcmp(param, g_resConfDef[i].param) == 0) {
return g_resConfDef[i].defValue;
}
}
return "";
}
static inline bool IsCustomResource(CusResType resType)
{
uint32 arrLen = (sizeof(g_customResourceType) / sizeof(g_customResourceType[0]));
@ -275,6 +333,9 @@ status_t InitAllResStat(int logLevel)
if (!IsCustomResource(g_confJson->resource.conf[i].resType)) {
continue;
}
if (g_confJson->resource.conf[i].resType == CUSTOM_RESOURCE_DN) {
g_isDnSSMode = CM_TRUE;
}
if (g_resCount >= CM_MAX_RES_COUNT) {
write_runlog(ERROR, "[InitResStat] custom resource count overflow, max:%d.\n", CM_MAX_RES_COUNT);
CleanResStat();
@ -398,6 +459,107 @@ status_t GetResNameByCmInstId(uint32 instId, char *resName, uint32 nameLen)
return CM_ERROR;
}
static IpType GetIpType(const char *ip)
{
if (CM_IS_EMPTY_STR(ip)) {
return IP_TYPE_NEITHER;
}
int32 ip4Cnt = 0;
int32 ip6Cnt = 0;
const int32 ip4CntTotal = 3;
const int32 ip6CntMax = 7;
const int32 ip6CntMin = 2;
uint32 ipLen = (uint32)strlen(ip);
for (uint32 i = 0; i < ipLen; ++i) {
if (ip[i] == '.') {
++ip4Cnt;
} else if (ip[i] == ':') {
++ip6Cnt;
}
}
if (ip6Cnt == 0 && ip4Cnt == ip4CntTotal) {
return IP_TYPE_IPV4;
}
if (ip4Cnt == 0 && (ip6Cnt >= ip6CntMin && ip6Cnt <= ip6CntMax)) {
return IP_TYPE_IPV6;
}
write_runlog(ERROR, "ip(%s) is invalid, and ip4Cnt=%d, ip6Cnd=%d.\n", ip, ip4Cnt, ip6Cnt);
return IP_TYPE_NEITHER;
}
static uint8 CheckIpV4PartlyValid(const char *ipPart)
{
if (CM_is_str_all_digit(ipPart) != 0) {
write_runlog(ERROR, "ip(%s) is not digital.\n", ipPart);
return CM_FALSE;
}
const uint32 maxLen = 3;
uint32 ipLen = (uint32)strlen(ipPart);
if (ipLen > maxLen) {
return CM_FALSE;
}
if (ipPart[0] == '0' && ipLen > 1) {
write_runlog(ERROR, "ip(%s) first is 0.\n", ipPart);
return CM_FALSE;
}
const int32 maxValue = 255;
int32 value = (int32)CmAtoi(ipPart, 0);
if (value < 0 || value > maxValue) {
write_runlog(ERROR, "ip(%s) value(%d) is not in [%d: %d].\n", ipPart, value, 0, maxValue);
return CM_FALSE;
}
return CM_TRUE;
}
static uint8 CheckIpV4Valid(char *ip, uint32 ipLen)
{
if (CM_IS_EMPTY_STR(ip)) {
return CM_FALSE;
}
char baseIp[CM_IP_LENGTH] = {0};
errno_t rc = strncpy_s(baseIp, CM_IP_LENGTH, ip, ipLen);
securec_check_errno(rc, (void)rc);
const char *ipPoint = ".";
char *savePtr = NULL;
// first
char *subStr = strtok_r(ip, ipPoint, &savePtr);
CM_RETFALSE_IFNOT(CheckIpV4PartlyValid(subStr));
int cnt = 1;
while (!CM_IS_EMPTY_STR(savePtr)) {
subStr = strtok_r(NULL, ipPoint, &savePtr);
CM_RETFALSE_IFNOT(CheckIpV4PartlyValid(subStr));
++cnt;
}
const int maxIpv4Part = 4;
if (cnt != maxIpv4Part) {
write_runlog(ERROR, "ip(%s) is invalid, cnt=%d.\n", baseIp, cnt);
return CM_FALSE;
}
return CM_TRUE;
}
uint8 CheckIpValid(const char *ip)
{
char tempIp[CM_IP_LENGTH] = {0};
errno_t rc = strcpy_s(tempIp, CM_IP_LENGTH, ip);
securec_check_errno(rc, (void)rc);
if (GetIpType(tempIp) != IP_TYPE_IPV4) {
write_runlog(ERROR, "ip(%s) is invalid, not ipV4.\n", ip);
return CM_FALSE;
}
if (CheckIpV4Valid(tempIp, CM_IP_LENGTH) == CM_FALSE) {
write_runlog(ERROR, "ipV4(%s) is invalid.\n", ip);
return CM_FALSE;
}
return CM_TRUE;
}
uint32 CusResCount()
{
return g_resCount;
@ -405,8 +567,23 @@ uint32 CusResCount()
bool IsCusResExist()
{
if (g_resCount == 0) {
return false;
}
return true;
return (g_resCount > 0);
}
void PrintCusInfoResList(const OneResStatList *status, const char *info)
{
write_runlog(LOG, "[CUS_RES] [%s] res(%s), version=%llu, status:\n", info, status->resName, status->version);
for (uint32 i = 0; i < status->instanceCount; ++i) {
write_runlog(LOG, "[CUS_RES] nodeId=%u, cmInstId=%u, resInstId=%u, status=%u, isWork=%u;\n",
status->resStat[i].nodeId,
status->resStat[i].cmInstanceId,
status->resStat[i].resInstanceId,
status->resStat[i].status,
status->resStat[i].isWorkMember);
}
}
bool8 IsDatanodeSSMode()
{
return g_isDnSSMode;
}

267
src/cm_common/cm_text.cpp Normal file
View File

@ -0,0 +1,267 @@
/*
* Copyright (c) 2022 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.
* -------------------------------------------------------------------------
*
* cm_text.cpp
*
* IDENTIFICATION
* src/cm_common/cm_text.cpp
*
* -------------------------------------------------------------------------
*/
#include <ctype.h>
#include "cm_text.h"
#include "securec.h"
#include "cm_debug.h"
#include "cm_elog.h"
bool8 IsCmBracketText(const text_t *text)
{
bool8 inString = CM_FALSE;
uint32 depth;
const int minLen = 2;
if (text->len < minLen) {
return CM_FALSE;
}
bool8 flag = (bool8)(CM_TEXT_BEGIN(text) != '(' || CM_TEXT_END(text) != ')');
if (flag) {
return CM_FALSE;
}
depth = 1;
for (uint32 i = 1; i < text->len; i++) {
if (text->str[i] == '\'') {
inString = (bool8)(!inString);
continue;
}
if (inString) {
continue;
} else if (text->str[i] == '(') {
depth++;
} else if (text->str[i] == ')') {
depth--;
if (depth == 0) {
return (bool8)(i == text->len - 1);
}
}
}
return CM_FALSE;
}
void CmRtrimText(text_t *text)
{
int32 index;
if (text->str == NULL) {
text->len = 0;
return;
} else if (text->len == 0) {
return;
}
index = (int32)text->len - 1;
while (index >= 0) {
if ((unsigned char)text->str[index] > (unsigned char)' ') {
text->len = (uint32)(index + 1);
return;
}
--index;
}
}
void CmLtrimText(text_t *text)
{
if (text->str == NULL) {
text->len = 0;
return;
} else if (text->len == 0) {
return;
}
while (text->len > 0) {
if ((unsigned char)*text->str > ' ') {
break;
}
text->str++;
text->len--;
}
}
void CmTrimText(text_t *text)
{
CmLtrimText(text);
CmRtrimText(text);
}
static void CmRTrimStr(char *str)
{
int32 strLen = (int32)strlen(str);
int32 i = strLen - 1;
for (; i >= 0; --i) {
if (!isspace(str[i])) {
if (i < strLen - 1) {
str[i + 1] = '\0';
}
break;
}
}
}
static void CmLTrimStr(char *str)
{
uint32 index = 0;
uint32 strLen = (uint32)strlen(str);
for (uint32 i = 0; i < strLen; ++i) {
if (isspace(str[i])) {
++index;
} else {
break;
}
}
if (index == 0) {
return;
}
char *tempStr = str + index;
uint32 curLen = (uint32)strlen(tempStr);
if (curLen == 0) {
str[0] = '\0';
return;
}
errno_t rc = memmove_s(str, strlen(str), tempStr, curLen);
securec_check_errno(rc, (void)rc);
str[curLen] = '\0';
}
void CmTrimStr(char *str)
{
if (CM_IS_EMPTY_STR(str)) {
return;
}
CmRTrimStr(str);
CmLTrimStr(str);
}
void CmRemoveBrackets(text_t *text)
{
const int lenReduce = 2;
while (IsCmBracketText(text)) {
text->str++;
text->len -= lenReduce;
CmTrimText(text);
}
}
void CmSplitText(const text_t *text, char splitChar, char encloseChar, text_t *left, text_t *right)
{
uint32 i;
bool8 isEnclosed = CM_FALSE;
left->str = text->str;
for (i = 0; i < text->len; i++) {
if (encloseChar != 0 && text->str[i] == encloseChar) {
isEnclosed = (bool8)(!isEnclosed);
continue;
}
if (isEnclosed) {
continue;
}
if (text->str[i] == splitChar) {
left->len = i;
right->str = text->str + i + 1;
right->len = text->len - (i + 1);
return;
}
}
/* if the split_char is not found */
left->len = text->len;
right->len = 0;
right->str = NULL;
}
bool8 CmFetchText(text_t *text, char splitChar, char encloseChar, text_t *sub)
{
text_t remain;
if (text->len == 0) {
CM_TEXT_CLEAR(sub);
return CM_FALSE;
}
CmSplitText(text, splitChar, encloseChar, sub, &remain);
text->len = remain.len;
text->str = remain.str;
return CM_TRUE;
}
bool8 CmTextStrEqualIns(const text_t *text, const char *str)
{
uint32 i;
for (i = 0; i < text->len; i++) {
if (UPPER(text->str[i]) != UPPER(str[i]) || str[i] == '\0') {
return CM_FALSE;
}
}
return (bool8)(str[text->len] == '\0');
}
void CmFetchFileName(text_t *files, text_t *name)
{
if (!CmFetchText(files, ',', '\0', name)) {
return;
}
CmTrimText(name);
const uint32 quotaionLen = 2;
if (name->str[0] == '\'') {
name->str++;
if (name->len >= quotaionLen) {
name->len -= quotaionLen;
} else {
name->len = 0;
}
CmTrimText(name);
}
}
status_t CmText2Str(const text_t *text, char *buf, uint32 bufSize)
{
if (buf == NULL) {
return CM_ERROR;
}
uint32 copy_size;
CM_ASSERT(bufSize > 1);
copy_size = (text->len >= bufSize) ? bufSize - 1 : text->len;
if (copy_size > 0) {
int res = memcpy_s(buf, bufSize, text->str, copy_size);
if (res != 0) {
return CM_ERROR;
}
}
buf[copy_size] = '\0';
return CM_SUCCESS;
}

View File

@ -23,6 +23,7 @@
*/
#include "cm_error.h"
#include "cm/cm_elog.h"
#include "cm_text.h"
#ifdef __cplusplus
extern "C" {

View File

@ -34,6 +34,8 @@
#include "cm_cipher.h"
#include "cm_elog.h"
#include "cm_misc_base.h"
#include "cm_text.h"
#include "cm_debug.h"
#ifdef __cplusplus
extern "C" {
@ -162,25 +164,6 @@ time_t CmCurrentTime()
return time(NULL);
}
status_t CmText2Str(const text_t *text, char *buf, uint32 buf_size)
{
if (buf == NULL) {
return CM_ERROR;
}
uint32 copy_size;
CM_ASSERT(buf_size > 1);
copy_size = (text->len >= buf_size) ? buf_size - 1 : text->len;
if (copy_size > 0) {
int res = memcpy_sp(buf, buf_size, text->str, copy_size);
if (res != 0) {
return CM_ERROR;
}
}
buf[copy_size] = '\0';
return CM_SUCCESS;
}
static const char *cm_cs_ssl_init_err_string(ssl_init_error_t err)
{
if (err > SSL_INITERR_NONE && err < SSL_INITERR_LASTERR) {
@ -189,19 +172,6 @@ static const char *cm_cs_ssl_init_err_string(ssl_init_error_t err)
return g_ssl_error_string[0];
}
static inline bool cm_text_str_equal_ins(const text_t *text, const char *str)
{
uint32 i;
for (i = 0; i < text->len; i++) {
if (UPPER(text->str[i]) != UPPER(str[i]) || str[i] == '\0') {
return false;
}
}
return (str[text->len] == '\0');
}
/*
Get the last SSL error code and reason
*/
@ -772,7 +742,7 @@ static status_t cm_cs_ssl_match_cipher(const text_t *left, char *cipher, uint32_
}
for (i = 0; i < count; i++) {
if (!cm_text_str_equal_ins(left, cipher_list[i])) {
if (!CmTextStrEqualIns(left, cipher_list[i])) {
continue;
}
*support = true;
@ -796,59 +766,14 @@ static status_t cm_cs_ssl_match_cipher(const text_t *left, char *cipher, uint32_
return CM_SUCCESS;
}
static void cm_split_text(const text_t *text, char split_char, char enclose_char, text_t *left, text_t *right)
{
uint32 i;
bool is_enclosed = false;
left->str = text->str;
for (i = 0; i < text->len; i++) {
if (enclose_char != 0 && text->str[i] == enclose_char) {
is_enclosed = !is_enclosed;
continue;
}
if (is_enclosed) {
continue;
}
if (text->str[i] == split_char) {
left->len = i;
right->str = text->str + i + 1;
right->len = text->len - (i + 1);
return;
}
}
/* if the split_char is not found */
left->len = text->len;
right->len = 0;
right->str = NULL;
}
static bool cm_fetch_text(text_t *text, char split_char, char enclose_char, text_t *sub)
{
text_t remain;
if (text->len == 0) {
CM_TEXT_CLEAR(sub);
return false;
}
cm_split_text(text, split_char, enclose_char, sub, &remain);
text->len = remain.len;
text->str = remain.str;
return true;
}
static status_t cm_cs_ssl_distinguish_cipher(const char *cipher, char *tls12_cipher, uint32_t *tls12_offset,
char *tls13_cipher, uint32_t *tls13_offset)
{
bool support = false;
text_t text, left, right;
cm_str2text((char *)cipher, &text);
cm_split_text(&text, ':', '\0', &left, &right);
CmStr2Text((char *)cipher, &text);
CmSplitText(&text, ':', '\0', &left, &right);
text = right;
while (left.len > 0) {
@ -870,7 +795,7 @@ static status_t cm_cs_ssl_distinguish_cipher(const char *cipher, char *tls12_cip
return CM_ERROR;
}
cm_split_text(&text, ':', '\0', &left, &right);
CmSplitText(&text, ':', '\0', &left, &right);
text = right;
}
@ -922,106 +847,13 @@ static status_t cm_cs_ssl_set_cipher(SSL_CTX *ctx, const ssl_config_t *config, b
return CM_SUCCESS;
}
static void cm_rtrim_text(text_t *text)
{
int32 index;
if (text->str == NULL) {
text->len = 0;
return;
} else if (text->len == 0) {
return;
}
index = (int32)text->len - 1;
while (index >= 0) {
if ((unsigned char)text->str[index] > (unsigned char)' ') {
text->len = (uint32)(index + 1);
return;
}
--index;
}
}
static bool cm_is_bracket_text(const text_t *text)
{
bool in_string = false;
uint32 depth;
const int minLen = 2;
if (text->len < minLen) {
return false;
}
bool flag = CM_TEXT_BEGIN(text) != '(' || CM_TEXT_END(text) != ')';
if (flag) {
return false;
}
depth = 1;
for (uint32 i = 1; i < text->len; i++) {
if (text->str[i] == '\'') {
in_string = !in_string;
continue;
}
if (in_string) {
continue;
} else if (text->str[i] == '(') {
depth++;
} else if (text->str[i] == ')') {
depth--;
if (depth == 0) {
return (i == text->len - 1);
}
}
}
return false;
}
static void cm_ltrim_text(text_t *text)
{
if (text->str == NULL) {
text->len = 0;
return;
} else if (text->len == 0) {
return;
}
while (text->len > 0) {
if ((unsigned char)*text->str > ' ') {
break;
}
text->str++;
text->len--;
}
}
static inline void cm_trim_text(text_t *text)
{
cm_ltrim_text(text);
cm_rtrim_text(text);
}
static inline void cm_remove_brackets(text_t *text)
{
const int lenReduce = 2;
while (cm_is_bracket_text(text)) {
text->str++;
text->len -= lenReduce;
cm_trim_text(text);
}
}
static inline void cm_cs_ssl_fetch_file_name(text_t *files, text_t *name)
{
if (!cm_fetch_text(files, ',', '\0', name)) {
if (!CmFetchText(files, ',', '\0', name)) {
return;
}
cm_trim_text(name);
CmTrimText(name);
if (name->str[0] == '\'') {
name->str++;
if (name->len >= 2) {
@ -1030,7 +862,7 @@ static inline void cm_cs_ssl_fetch_file_name(text_t *files, text_t *name)
name->len = 0;
}
cm_trim_text(name);
CmTrimText(name);
}
}
@ -1042,8 +874,8 @@ static status_t cm_cs_ssl_set_ca_chain(SSL_CTX *ctx, ssl_config_t *config, bool
if (config->ca_file == NULL) {
return CM_SUCCESS;
}
cm_str2text((char *)config->ca_file, &file_list);
cm_remove_brackets(&file_list);
CmStr2Text((char *)config->ca_file, &file_list);
CmRemoveBrackets(&file_list);
cm_cs_ssl_fetch_file_name(&file_list, &file_name);
while (file_name.len > 0) {
@ -1102,8 +934,8 @@ static status_t cm_cs_ssl_set_crl_file(SSL_CTX *ctx, ssl_config_t *config)
char filepath[CM_FILE_NAME_BUFFER_SIZE];
if (config->crl_file != NULL) {
cm_str2text((char *)config->crl_file, &file_list);
cm_remove_brackets(&file_list);
CmStr2Text((char *)config->crl_file, &file_list);
CmRemoveBrackets(&file_list);
cm_cs_ssl_fetch_file_name(&file_list, &file_name);
while (file_name.len > 0) {
@ -1225,7 +1057,7 @@ static status_t cm_cs_ssl_resolve_file_name(const char *filename, char *buf, uin
*res_buf = filename;
return CM_SUCCESS;
}
cm_str2text((char *)filename, &text);
CmStr2Text((char *)filename, &text);
CM_REMOVE_ENCLOSED_CHAR(&text);
CM_RETURN_IFERR(CmText2Str(&text, buf, buf_len));
*res_buf = buf;

View File

@ -39,6 +39,7 @@
#include "hotpatch/hotpatch_client.h"
#include "ctl_common.h"
#include "ctl_global_params.h"
#include "config.h"
#include "cm_util.h"
#include "ctl_help.h"
@ -91,9 +92,6 @@ uint32 g_normal_cm_server_node_index = PG_UINT32_MAX;
time_t CHECK_BUILDING_DN_TIMEOUT = 60; // in seconds
bool is_check_building_dn = true;
CM_Conn* CmServer_conn = NULL;
CM_Conn* CmServer_conn1 = NULL;
CM_Conn* CmServer_conn2 = NULL;
char g_appPath[MAXPGPATH] = {0};
const char* g_progname;
static char* pgdata_opt = NULL;
@ -112,7 +110,6 @@ char *g_cmsPromoteMode = NULL;
bool g_gtmBalance = true;
bool g_datanodesBalance = true;
cm_to_ctl_central_node_status g_centralNode;
FILE* g_logFilePtr = NULL;
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
static char* hotpatch_exec = NULL;
@ -184,12 +181,15 @@ const int DCF_PRIORITY = 17;
const int RES_ADD = 18;
const int RES_EDIT = 19;
const int RES_DEL = 20;
const int RES_CONF_CHECK = 21;
const int RES_NAME = 22;
const int RES_ATTR = 23;
const int RES_ADD_INST = 24;
const int RES_DEL_INST = 25;
const int RES_TYPE = 26;
const int RES_CHECK = 21;
const int RES_NAME_INPUT = 22;
const int RES_ATTR_INPUT = 23;
const int RES_ADD_INST_INPUT = 24;
const int RES_DEL_INST_INPUT = 25;
const int RES_EDIT_INST_INPUT = 27;
const int RES_INST_ATTR_INPUT = 28;
const int RES_LIST = 29;
const int RES_LIST_INST_INPUT = 30;
const int ErrorCode = -2;
unordered_map<string, CtlCommand> g_optToCommand {
@ -1729,18 +1729,6 @@ static void MatchCmdArgCmsPmode(void)
}
}
static void MatchCmdArgResType(CtlOption *ctlCtx)
{
for (int32 i = 0; i < (int32)RES_TYPE_CEIL; ++i) {
if (strcmp(optarg, g_resTypeMap[i].typeStr) == 0) {
ctlCtx->resOpt.type = g_resTypeMap[i].type;
return;
}
}
ctlCtx->resOpt.type = RES_TYPE_APP;
write_runlog(WARNING, "cannot find the --res_type(%s).\n", optarg);
}
static void ParseCmdArgsCore(int cmd, bool *setDataPath, CtlOption *ctlCtx)
{
switch (cmd) {
@ -1928,34 +1916,43 @@ static void ParseCmdArgsCore(int cmd, bool *setDataPath, CtlOption *ctlCtx)
MatchCmdArgDcfPriority(ctlCtx);
break;
case RES_ADD:
ctlCtx->resOpt.mode = RES_ADD_CONF;
ctlCtx->resOpt.mode = RES_OP_ADD;
break;
case RES_EDIT:
ctlCtx->resOpt.mode = RES_EDIT_CONF;
ctlCtx->resOpt.mode = RES_OP_EDIT;
break;
case RES_DEL:
ctlCtx->resOpt.mode = RES_DEL_CONF;
ctlCtx->resOpt.mode = RES_OP_DEL;
break;
case RES_CONF_CHECK:
ctlCtx->resOpt.mode = RES_CHECK_CONF;
case RES_CHECK:
ctlCtx->resOpt.mode = RES_OP_CHECK;
break;
case RES_NAME:
case RES_NAME_INPUT:
ctlCtx->resOpt.resName = xstrdup(optarg);
break;
case RES_ATTR:
case RES_ATTR_INPUT:
ctlCtx->resOpt.resAttr = xstrdup(optarg);
ctlCtx->resOpt.editMode = RES_EDIT_RES_CONF;
break;
case RES_ADD_INST:
ctlCtx->resOpt.addInstStr = xstrdup(optarg);
ctlCtx->resOpt.editMode = RES_ADD_INST_CONF;
case RES_ADD_INST_INPUT:
ctlCtx->resOpt.inst.instName = xstrdup(optarg);
ctlCtx->resOpt.inst.mode = RES_OP_ADD;
break;
case RES_DEL_INST:
ctlCtx->resOpt.delInstStr = xstrdup(optarg);
ctlCtx->resOpt.editMode = RES_DEL_INST_CONF;
case RES_DEL_INST_INPUT:
ctlCtx->resOpt.inst.instName = xstrdup(optarg);
ctlCtx->resOpt.inst.mode = RES_OP_DEL;
break;
case RES_TYPE:
MatchCmdArgResType(ctlCtx);
case RES_EDIT_INST_INPUT:
ctlCtx->resOpt.inst.instName = xstrdup(optarg);
ctlCtx->resOpt.inst.mode = RES_OP_EDIT;
break;
case RES_INST_ATTR_INPUT:
ctlCtx->resOpt.inst.instAttr = xstrdup(optarg);
break;
case RES_LIST:
ctlCtx->resOpt.mode = RES_OP_LIST;
break;
case RES_LIST_INST_INPUT:
ctlCtx->resOpt.inst.mode = RES_OP_LIST;
break;
default:
/* getopt_long already issued a suitable error message */
@ -2202,7 +2199,7 @@ static void CtlCommandProcessCore(int *status, CtlOption *ctlCtx)
*status = DoSwitch(ctlCtx);
break;
case CM_RES_COMMAND:
*status = DoResCommand(ctlCtx);
*status = DoResCommand(&(ctlCtx->resOpt));
break;
case CM_SHOW_COMMAND:
*status = DoShowCommand();
@ -2264,7 +2261,8 @@ int main(int argc, char** argv)
/* support --help and --version even if invoked as root */
CheckArgcType(argc, argv);
static struct option longOptions[] = {{"help", no_argument, NULL, '?'},
static struct option longOptions[] = {
{"help", no_argument, NULL, '?'},
{"version", no_argument, NULL, 'V'},
{"log", required_argument, NULL, 'l'},
{"log_level", optional_argument, NULL, 1},
@ -2303,14 +2301,18 @@ int main(int argc, char** argv)
{"add", no_argument, NULL, RES_ADD},
{"edit", no_argument, NULL, RES_EDIT},
{"del", no_argument, NULL, RES_DEL},
{"check", no_argument, NULL, RES_CONF_CHECK},
{"res_name", required_argument, NULL, RES_NAME},
{"res_attr", required_argument, NULL, RES_ATTR},
{"add_inst", required_argument, NULL, RES_ADD_INST},
{"del_inst", required_argument, NULL, RES_DEL_INST},
{"res_type", required_argument, NULL, RES_TYPE},
{"check", no_argument, NULL, RES_CHECK},
{"list", no_argument, NULL, RES_LIST},
{"res_name", required_argument, NULL, RES_NAME_INPUT},
{"res_attr", required_argument, NULL, RES_ATTR_INPUT},
{"add_inst", required_argument, NULL, RES_ADD_INST_INPUT},
{"del_inst", required_argument, NULL, RES_DEL_INST_INPUT},
{"edit_inst", required_argument, NULL, RES_EDIT_INST_INPUT},
{"inst_attr", required_argument, NULL, RES_INST_ATTR_INPUT},
{"list_inst", no_argument, NULL, RES_LIST_INST_INPUT},
{NULL, 0, NULL, 0}};
{NULL, 0, NULL, 0}
};
int optionIndex;
int c;

View File

@ -172,7 +172,7 @@ int FindInstanceIdAndType(uint32 node, const char *dataPath, uint32 *instanceId,
* ssh_exec
* exec command in remote host.
*/
int ssh_exec(const staticNodeConfig* node, const char* cmd)
int ssh_exec(const staticNodeConfig* node, const char* cmd, int32 logLevel)
{
#define MAXLINE 1024
char actualCmd[MAXLINE];
@ -194,7 +194,7 @@ int ssh_exec(const staticNodeConfig* node, const char* cmd)
}
rc = system(actualCmd);
if (rc != 0) {
write_runlog(ERROR, "ssh failed at \"%s\".\n", node->sshChannel[ii]);
write_runlog(logLevel, "ssh failed at \"%s\".\n", node->sshChannel[ii]);
write_runlog(DEBUG1, "cmd is %s, rc=%d, errno=%d.\n", actualCmd, WEXITSTATUS(rc), errno);
}
}
@ -1870,72 +1870,3 @@ void CtlGetCmJsonConf()
write_runlog(DEBUG1, "init res status failed.\n");
}
}
static void OutPutCmdResult(const char *option, const ExecDdbCmdAckMsg *ackPtr)
{
if (ackPtr->isSuccess) {
if (ackPtr->outputLen < DCC_CMD_MAX_OUTPUT_LEN) {
write_runlog(LOG, "exec ddb %s command success.\n", option);
write_runlog(LOG, "%s\n", ackPtr->output);
} else {
write_runlog(LOG, "exec ddb %s command failed, error msg's buf is smaller(%d/%d).\n",
option, DCC_CMD_MAX_OUTPUT_LEN, ackPtr->outputLen);
write_runlog(LOG, "part result is:\n %s\n", ackPtr->output);
}
} else {
write_runlog(LOG, "exec ddb %s command failed, err msg:\n%s\n", option, ackPtr->errMsg);
}
}
void GetExecCmdResult(const char *option, int expCmd)
{
int ret;
int recvTimeOut = EXEC_DDC_CMD_TIMEOUT;
char *receiveMsg = NULL;
cm_msg_type *rcvCmd = NULL;
for (;;) {
ret = cm_client_flush_msg(CmServer_conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION_WITHOUT_EXIT();
}
receiveMsg = recv_cm_server_cmd(CmServer_conn);
if (receiveMsg != NULL) {
rcvCmd = (cm_msg_type*)receiveMsg;
if (rcvCmd->msg_type == expCmd) {
switch (rcvCmd->msg_type) {
case EXEC_DDB_COMMAND_ACK: {
ExecDdbCmdAckMsg *ackPtr = (ExecDdbCmdAckMsg*)(receiveMsg);
OutPutCmdResult(option, ackPtr);
break;
}
case MSG_CTL_CM_RHB_STATUS_ACK: {
CmRhbStatAck *ackPtr = (CmRhbStatAck*)(receiveMsg);
HandleRhbAck(ackPtr);
break;
}
case MSG_CTL_CM_NODE_DISK_STATUS_ACK: {
CmNodeDiskStatAck *ackPtr = (CmNodeDiskStatAck*)(receiveMsg);
HandleNodeDiskAck(ackPtr);
break;
}
default:
break;
}
}
}
recvTimeOut--;
if (recvTimeOut <= 0 || (rcvCmd != NULL && rcvCmd->msg_type == expCmd)) {
break;
}
cm_sleep(1);
}
if (recvTimeOut <= 0) {
write_runlog(LOG, "command timeout.\n");
return;
}
return;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 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_global_params.cpp
* cm_ctl finishredo functions
*
* IDENTIFICATION
* src/cm_ctl/ctl_global_params.cpp
*
* -------------------------------------------------------------------------
*/
#include "ctl_global_params.h"
#include "cm/libpq-fe.h"
#include "cm/libpq-int.h"
// connect to cms
CM_Conn *CmServer_conn = NULL;
CM_Conn *CmServer_conn1 = NULL;
CM_Conn *CmServer_conn2 = NULL;
// the fd of fprintf
FILE *g_logFilePtr = stdout;
CM_Conn *GetCmsConn()
{
return CmServer_conn;
}

View File

@ -93,8 +93,10 @@ static void UsageHelp(const char *projectName)
(void)printf(_(" %s encrypt [-M MODE] -D DATADIR\n"), projectName);
(void)printf(_(" %s ddb DDB_CMD\n"), projectName);
(void)printf(_(" %s switch [--ddb_type=[DDB]] [--commit] [--rollback]\n"), projectName);
(void)printf(_(" %s res [--add | --edit | --del | --check] --res_name=\"NAME\" [--res_type=\"RES_TYPE\" "
"--res_attr=\"RES_INFO\" | --add_inst=\"INST_INFO\" | --del_inst=\"INST_INFO\"]\n"), projectName);
(void)printf(_(" %s res {--add --res_name=\"NAME\" --res_attr=\"RES_INFO\" | "
"--del --res_name=\"NAME\" | --edit --res_name=\"NAME\" | --list {--res_name=\"NAME\"} "
"{--res_attr=\"RES_INFO\" | --add_inst=\"INST_INFO\" | --del_inst=\"INST_INFO\" | --edit_inst=\"INST_INFO\" "
"{--inst_attr=\"INST_ATTR\"} | --list_inst} | --check }\n"), projectName);
(void)printf(_(" %s show\n"), projectName);
(void)printf(_(" %s pause\n"), projectName);
(void)printf(_(" %s resume\n"), projectName);
@ -387,12 +389,14 @@ static void ResCmdHelp()
(void)printf(_(" --edit edit one resource or resource instances configuration information.\n"));
(void)printf(_(" --del delete one resource or resource instances configuration information.\n"));
(void)printf(_(" --check check whether the resource configuration information regular.\n"));
(void)printf(_(" --list list one resource or resource instances configuration information.\n"));
(void)printf(_(" --res_name specifies the name of the resource to be operated.\n"));
(void)printf(_(" --res_type specifies the type of the resource to be operated, it can be \"APP\", "
"\"DN\".\n"));
(void)printf(_(" --res_attr common resource configuration information.\n"));
(void)printf(_(" --inst_attr common instances configuration information.\n"));
(void)printf(_(" --add_inst add instances configuration information of one resource.\n"));
(void)printf(_(" --del_inst delete instances configuration information of one resource.\n"));
(void)printf(_(" --edit_inst edit instances configuration information of one resource.\n"));
(void)printf(_(" --list_inst list instances configuration information of one resource.\n"));
}
void DoHelp(const char *projectName)

View File

@ -32,6 +32,7 @@
#include "cm/libpq-fe.h"
#include "cm/cm_misc.h"
#include "ctl_common.h"
#include "ctl_process_message.h"
#include "cm/cm_msg.h"
#include "cm/libpq-int.h"
#include "cm/cm_agent/cma_main.h"
@ -1811,6 +1812,12 @@ int DoReload()
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++) {
@ -1820,6 +1827,7 @@ int FindInstanceByInstId(uint32 instId, Instance *inst)
inst->instType = INST_TYPE_GTM;
inst->node = curNode->node;
inst->InstNode = curNode;
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, 0);
return 0;
}
}
@ -1829,6 +1837,7 @@ int FindInstanceByInstId(uint32 instId, Instance *inst)
inst->instType = INST_TYPE_CN;
inst->node = curNode->node;
inst->InstNode = curNode;
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, 0);
return 0;
}
}
@ -1838,6 +1847,7 @@ int FindInstanceByInstId(uint32 instId, Instance *inst)
inst->instType = INST_TYPE_CMSERVER;
inst->node = curNode->node;
inst->InstNode = curNode;
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, 0);
return 0;
}
}
@ -1847,6 +1857,7 @@ int FindInstanceByInstId(uint32 instId, Instance *inst)
inst->instType = INST_TYPE_DN;
inst->node = curNode->node;
inst->dnInst = &curNode->datanode[i];
SetNodeInstBaseInfo(&(inst->baseInfo), nodeIdx, i);
return 0;
}
}
@ -2016,6 +2027,7 @@ void DoDccCmd(int argc, char **argv)
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) {

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2022 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_process_message.cpp
*
* IDENTIFICATION
* src/cm_ctl/ctl_process_message.cpp
*
* -------------------------------------------------------------------------
*/
#include "ctl_process_message.h"
#include "cm_msg.h"
#include "cm/libpq-fe.h"
#include "cm/libpq-int.h"
#include "ctl_common.h"
#include "ctl_show.h"
static CtlDealCmdFunc g_ctlFunc[MSG_CM_TYPE_CEIL] = {0};
static status_t OutPutCmdResult(const char *option, char *recvMsg)
{
const ExecDdbCmdAckMsg *ackPtr = (const ExecDdbCmdAckMsg *)recvMsg;
if (ackPtr->isSuccess) {
if (ackPtr->outputLen < DCC_CMD_MAX_OUTPUT_LEN) {
write_runlog(LOG, "exec ddb %s command success.\n", option);
write_runlog(LOG, "%s\n", ackPtr->output);
} else {
write_runlog(LOG, "exec ddb %s command failed, error msg's buf is smaller(%d/%d).\n",
option, DCC_CMD_MAX_OUTPUT_LEN, ackPtr->outputLen);
write_runlog(LOG, "part result is:\n %s\n", ackPtr->output);
}
return CM_SUCCESS;
} else {
write_runlog(LOG, "exec ddb %s command failed, err msg:\n%s\n", option, ackPtr->errMsg);
}
return CM_ERROR;
}
static bool8 RecvAndDealCmd(status_t *cmStatus, CM_Conn *conn, const char *option, int32 expCmd)
{
char *receiveMsg = (char *)recv_cm_server_cmd(conn);
if (receiveMsg == NULL) {
return CM_FALSE;
}
int32 msgType = ((cm_msg_type *)receiveMsg)->msg_type;
if (expCmd != INVALID_EXPECT_CMD && msgType != expCmd) {
return CM_FALSE;
}
if (msgType < 0 || msgType >= (int32)MSG_CM_TYPE_CEIL) {
write_runlog(ERROR, "invalid msgType(%d).\n", msgType);
return CM_FALSE;
}
CtlDealCmdFunc ctlFunc = g_ctlFunc[msgType];
if (ctlFunc != NULL) {
*cmStatus = ctlFunc(option, receiveMsg);
return CM_TRUE;
}
write_runlog(DEBUG1, "msgType is %d, but ctlFunc is NULL.\n", msgType);
*cmStatus = CM_ERROR;
if (expCmd != INVALID_EXPECT_CMD) {
return CM_TRUE;
}
return CM_FALSE;
}
status_t GetExecCmdResult(const char *option, int32 expCmd, CM_Conn *conn)
{
int ret;
int recvTimeOut = EXEC_DDC_CMD_TIMEOUT;
bool8 dealRet;
status_t cmStatus;
for (;;) {
ret = cm_client_flush_msg(conn);
if (ret == TCP_SOCKET_ERROR_EPIPE) {
FINISH_CONNECTION_WITHOUT_EXIT();
write_runlog(ERROR, "failed to execute cmd(%d), tcp socket error epipe.\n", expCmd);
return CM_ERROR;
}
dealRet = RecvAndDealCmd(&cmStatus, conn, option, expCmd);
recvTimeOut--;
if (dealRet || recvTimeOut <= 0) {
break;
}
cm_sleep(1);
}
if (recvTimeOut <= 0) {
write_runlog(LOG, "command timeout.\n");
return CM_TIMEDOUT;
}
return cmStatus;
}
static void ResetCtlFunc()
{
errno_t rc = memset_s(g_ctlFunc, sizeof(g_ctlFunc), 0, sizeof(g_ctlFunc));
securec_check_errno(rc, (void)rc);
}
void InitDdbCmdMsgFunc()
{
ResetCtlFunc();
g_ctlFunc[EXEC_DDB_COMMAND_ACK] = OutPutCmdResult;
}
void InitCtlShowMsgFunc()
{
ResetCtlFunc();
g_ctlFunc[MSG_CTL_CM_RHB_STATUS_ACK] = HandleRhbAck;
g_ctlFunc[MSG_CTL_CM_NODE_DISK_STATUS_ACK] = HandleNodeDiskAck;
g_ctlFunc[MSG_CTL_CM_FLOAT_IP_ACK] = HandleFloatIpAck;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,681 @@
/*
* Copyright (c) 2023 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_res.cpp
* cm_ctl res --check
*
* IDENTIFICATION
* src/cm_ctl/ctl_res_check.cpp
*
* -------------------------------------------------------------------------
*/
#include "cjson/cJSON.h"
#include "cm_text.h"
#include "ctl_res.h"
#include "ctl_common.h"
#include "ctl_common_res.h"
typedef struct FloatIpResInfoT {
char ip[CM_IP_LENGTH];
int32 instId;
} FloatIpResInfo;
static status_t CheckAppResInfo(cJSON *resItem, const char *resName);
static status_t CheckDnResInfo(cJSON *resItem, const char *resName);
static status_t CheckVipResInfo(cJSON *resItem, const char *resName);
ResTypeMap g_resTypeMap[RES_TYPE_CEIL];
const char *g_instAttrMap[] = {"base_ip"};
static void PrintCheckJsonInfo(int level, const char* fmt, ...)
{
va_list ap;
char infoBuf[MAX_LOG_BUFF_LEN] = {0};
fmt = _(fmt);
va_start(ap, fmt);
int ret = vsnprintf_s(infoBuf, sizeof(infoBuf), sizeof(infoBuf) - 1, fmt, ap);
securec_check_intval(ret, (void)ret);
switch (level) {
case WARNING:
write_runlog(level, "warning: %s", infoBuf);
break;
case ERROR:
write_runlog(level, "error: %s", infoBuf);
break;
default:
write_runlog(level, "%s", infoBuf);
break;
}
va_end(ap);
}
static bool8 CmCheckIsJsonNumber(const cJSON *obj, const char *resName, const char *paraName, int logLevel)
{
const char *defValue = ResConfDefValue(paraName);
if (obj == NULL) {
PrintCheckJsonInfo(logLevel, "resource(%s)'s %s not configured, default(%s).\n", resName, paraName, defValue);
return CM_FALSE;
}
if (!cJSON_IsNumber(obj)) {
PrintCheckJsonInfo(logLevel, "resource(%s)'s %s is not a number, default(%s).\n", resName, paraName, defValue);
return CM_FALSE;
}
return CM_TRUE;
}
static bool8 CmCheckIsJsonString(const cJSON *obj, const char *resName, const char *paraName, int logLevel)
{
const char *defValue = ResConfDefValue(paraName);
if (obj == NULL) {
PrintCheckJsonInfo(logLevel, "resource(%s)'s %s not configured, default(%s).\n", resName, paraName, defValue);
return CM_FALSE;
}
if (!cJSON_IsString(obj)) {
PrintCheckJsonInfo(logLevel, "resource(%s)'s %s is not a string, default(%s).\n", resName, paraName, defValue);
return CM_FALSE;
}
return CM_TRUE;
}
static bool8 CmCheckIsJsonBool(const cJSON *obj, const char *resName, const char *paraName, int logLevel)
{
const char *defValue = ResConfDefValue(paraName);
if (obj == NULL) {
PrintCheckJsonInfo(logLevel, "resource(%s)'s %s not configured, default(%s).\n", resName, paraName, defValue);
return CM_FALSE;
}
if (!cJSON_IsBool(obj) && (!cJSON_IsString(obj) || !CheckBoolConfigParam(obj->valuestring))) {
PrintCheckJsonInfo(logLevel, "resource(%s)'s %s is not a bool, default(%s).\n", resName, paraName, defValue);
return CM_FALSE;
}
return CM_TRUE;
}
static status_t CheckOneResInst(cJSON *instItem, const char *resName)
{
cJSON *nodeJson = cJSON_GetObjectItem(instItem, INST_NODE_ID);
CM_RETERR_IF_FALSE(CmCheckIsJsonNumber(nodeJson, resName, "one instance node_id", ERROR));
if (!IsNodeIdValid(nodeJson->valueint)) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s one instance node_id(%d) is invalid.\n", resName, nodeJson->valueint);
return CM_ERROR;
}
cJSON *resInstValue = cJSON_GetObjectItem(instItem, INST_RES_INST_ID);
(void)CmCheckIsJsonNumber(resInstValue, resName, "one instance res_instance_id", WARNING);
resInstValue = cJSON_GetObjectItem(instItem, "res_args");
(void)CmCheckIsJsonString(resInstValue, resName, "one instance res_args", WARNING);
return CM_SUCCESS;
}
static status_t CheckAllResInst(cJSON *instArray, const char *resName)
{
cJSON *instItem;
cJSON_ArrayForEach(instItem, instArray) {
CM_RETURN_IFERR(CheckOneResInst(instItem, resName));
}
return CM_SUCCESS;
}
static status_t CheckResNumberOptInfo(cJSON *resItem, const char *resName, const char *checkKey)
{
cJSON *objValue = cJSON_GetObjectItem(resItem, checkKey);
CM_RETERR_IF_FALSE(CmCheckIsJsonNumber(objValue, resName, checkKey, WARNING));
if (!IsResConfValid(checkKey, objValue->valueint)) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s %s=%d out of range, range[%u %u], default(%s).\n",
resName, checkKey, objValue->valueint,
ResConfMinValue(checkKey), ResConfMaxValue(checkKey), ResConfDefValue(checkKey));
return CM_ERROR;
}
return CM_SUCCESS;
}
static bool ParseIsCritical(cJSON *objValue)
{
if (cJSON_IsBool(objValue)) {
return (bool)cJSON_IsTrue(objValue);
}
if (cJSON_IsString(objValue) && CheckBoolConfigParam(objValue->valuestring)) {
return IsBoolCmParamTrue(objValue->valuestring);
}
return true;
}
static void CheckLocationAttrFormat(const char *resName, const char *attr)
{
int paramLen = 0;
int valueLen = 0;
int flagCount = 0;
for (uint32 i = 0; i < strlen(attr); ++i) {
if (attr[i] == ':') {
++flagCount;
continue;
}
if (flagCount == 0) {
++paramLen;
}
if (flagCount == 1) {
++valueLen;
}
if (flagCount > 1) {
break;
}
}
if (flagCount == 0) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s location_attr(%s) format wrong, have no \':\'.\n",
resName, attr);
return;
}
if (flagCount > 1) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s location_attr(%s) format wrong, more than one \':\'.\n",
resName, attr);
return;
}
if (paramLen == 0) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s location_attr(%s) format wrong, have no parameter.\n",
resName, attr);
}
if (valueLen == 0) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s location_attr(%s) format wrong, have no right value.\n",
resName, attr);
}
}
static void CheckResLocalOptInfo(cJSON *resItem, const char *resName)
{
char localType[NAMEDATALEN] = {0};
cJSON *objType = cJSON_GetObjectItem(resItem, "location_type");
if (CmCheckIsJsonString(objType, resName, "location_type", WARNING)) {
errno_t rc = strcpy_s(localType, NAMEDATALEN, objType->valuestring);
securec_check_errno(rc, (void)rc);
} else {
cJSON *objValue = cJSON_GetObjectItem(resItem, "is_critical");
(void)CmCheckIsJsonBool(objValue, resName, "is_critical", WARNING);
return;
}
if (strcasecmp(localType, "local") != 0 && strcasecmp(localType, "any_one") != 0 &&
strcasecmp(localType, "qualified_one") != 0) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s location_type=\"%s\" not in (local/any_one/qualified_one), "
"default(%s).\n", resName, localType, ResConfDefValue("location_type"));
}
cJSON *objValue = cJSON_GetObjectItem(resItem, "is_critical");
bool isCritical = IsBoolCmParamTrue(ResConfDefValue("is_critical"));
if (CmCheckIsJsonBool(objValue, resName, "is_critical", WARNING)) {
isCritical = ParseIsCritical(objValue);
}
if (isCritical && (strcasecmp(localType, "any_one") == 0 || strcasecmp(localType, "qualified_one") == 0)) {
PrintCheckJsonInfo(WARNING, "resource(%s)'s location_type is %s, is_critical must be false.\n",
resName, localType);
}
if (strcasecmp(localType, "qualified_one") == 0) {
cJSON *objAttr = cJSON_GetObjectItem(resItem, "location_attr");
if (CmCheckIsJsonString(objType, resName, "location_attr", WARNING)) {
CheckLocationAttrFormat(resName, objAttr->valuestring);
}
}
}
static status_t CheckAppDnCommResInfo(cJSON *resItem, const char *resName)
{
cJSON *objValue = cJSON_GetObjectItem(resItem, "script");
CM_RETERR_IF_FALSE(CmCheckIsJsonString(objValue, resName, "script", ERROR));
(void)CheckResNumberOptInfo(resItem, resName, "check_interval");
(void)CheckResNumberOptInfo(resItem, resName, "time_out");
(void)CheckResNumberOptInfo(resItem, resName, "restart_delay");
(void)CheckResNumberOptInfo(resItem, resName, "restart_period");
(void)CheckResNumberOptInfo(resItem, resName, "restart_times");
CheckResLocalOptInfo(resItem, resName);
return CM_SUCCESS;
}
static status_t CheckAppResInfo(cJSON *resItem, const char *resName)
{
cJSON *instArray = cJSON_GetObjectItem(resItem, INSTANCES);
if (!cJSON_IsArray(instArray)) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s resource_type is APP, but instance array not configured.\n", resName);
return CM_ERROR;
}
if (cJSON_GetArraySize(instArray) == 0) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s resource_type is APP, but instance array is empty.\n", resName);
return CM_ERROR;
}
CM_RETURN_IFERR(CheckAllResInst(instArray, resName));
return CheckAppDnCommResInfo(resItem, resName);
}
static status_t CheckDnResInfo(cJSON *resItem, const char *resName)
{
cJSON *instArray = cJSON_GetObjectItem(resItem, INSTANCES);
if (cJSON_IsArray(instArray)) {
CM_RETURN_IFERR(CheckAllResInst(instArray, resName));
}
return CheckAppDnCommResInfo(resItem, resName);
}
static bool8 IsKeyInInstAttr(const char *key)
{
if (CM_IS_EMPTY_STR(key)) {
return CM_FALSE;
}
uint32 len = ELEMENT_COUNT(g_instAttrMap);
for (uint32 i = 0; i < len; ++i) {
if (cm_str_equal(key, g_instAttrMap[i])) {
return CM_TRUE;
}
}
return CM_FALSE;
}
static status_t GetExpIpFromJson(cJSON *resItem, const char *key, const char *resName, char *ip, uint32 ipLen)
{
bool8 isInInstAttr = IsKeyInInstAttr(key);
const char *trueKey = isInInstAttr ? INST_ATTR : key;
cJSON *objValue = cJSON_GetObjectItem(resItem, trueKey);
CM_RETERR_IF_FALSE(CmCheckIsJsonString(objValue, resName, trueKey, ERROR));
if (!isInInstAttr) {
check_input_for_security(objValue->valuestring);
errno_t rc = strcpy_s(ip, ipLen, objValue->valuestring);
securec_check_errno(rc, (void)rc);
return CM_SUCCESS;
}
char *point = strstr(objValue->valuestring, key);
if (point == NULL) {
write_runlog(ERROR, "Res(%s) cannot find %s from %s.\n", resName, key, INST_ATTR);
return CM_ERROR;
}
char tmpIp[MAX_PATH_LEN] = {0};
if (FetchStrFromText(point, tmpIp, MAX_PATH_LEN, KEY_VALUE_SPLIT_CHAR) != 0) {
write_runlog(ERROR, "Res(%s) cannot find [%s] from [%s] with the key[%s].\n",
resName, key, objValue->valuestring, INST_ATTR);
return CM_ERROR;
}
check_input_for_security(tmpIp);
errno_t rc = strncpy_s(ip, ipLen, tmpIp, ipLen - 1);
securec_check_errno(rc, (void)rc);
return CM_SUCCESS;
}
static status_t CheckIpValidInJson(cJSON *resItem, const char *key, const char *resName, char *ip, uint32 ipLen)
{
CM_RETURN_IFERR(GetExpIpFromJson(resItem, key, resName, ip, ipLen));
if (CheckIpValid(ip) == CM_FALSE) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s %s is an invalid ip.\n", resName, key);
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t CheckAndGetNumberFromJson(cJSON *resItem, const char *resName, const char *checkKey, int32 *value)
{
cJSON *objValue = cJSON_GetObjectItem(resItem, checkKey);
CM_RETERR_IF_FALSE(CmCheckIsJsonNumber(objValue, resName, checkKey, ERROR));
if (!IsResConfValid(checkKey, objValue->valueint)) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s %s=%d out of range, range[%u %u].\n", resName, checkKey,
objValue->valueint, ResConfMinValue(checkKey), ResConfMaxValue(checkKey));
return CM_ERROR;
}
if (value != NULL) {
*value = objValue->valueint;
}
return CM_SUCCESS;
}
static status_t CheckFloatIPResInfo(
const char *resName, FloatIpResInfo *info, int32 maxLen, int32 *index, const FloatIpResInfo *curInfo)
{
int32 point = *index;
if (point >= maxLen) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s point(%d) has more then MaxLen(%d).\n", resName, point, maxLen);
return CM_ERROR;
}
// instance_id
for (int32 i = 0; i < point; ++i) {
if (curInfo->instId == info[i].instId) {
PrintCheckJsonInfo(ERROR,
"resource(%s)'s FloatIp base_ip_list instance_id(%d) may be repeated.\n", resName, curInfo->instId);
return CM_ERROR;
}
}
// base_ip
for (int32 i = 0; i < point; ++i) {
if (strcmp(curInfo->ip, info[i].ip) == 0) {
PrintCheckJsonInfo(ERROR,
"resource(%s)'s FloatIp base_ip_list base_ip(%s) may be repeated.\n", resName, curInfo->ip);
return CM_ERROR;
}
}
info[point].instId = curInfo->instId;
errno_t rc = strcpy_s(info[point].ip, CM_IP_LENGTH, curInfo->ip);
securec_check_errno(rc, (void)rc);
++(*index);
return CM_SUCCESS;
}
static status_t CheckVipResInfo(cJSON *resItem, const char *resName)
{
// instances
cJSON *instArray = cJSON_GetObjectItem(resItem, INSTANCES);
if (!cJSON_IsArray(instArray)) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s resource_type is VIP, but base_ip_list not configured.\n", resName);
return CM_ERROR;
}
FloatIpResInfo info[CM_PRIMARY_STANDBY_MAX_NUM + 1] = {{{0}}};
int32 arrSize = cJSON_GetArraySize(instArray);
if (arrSize < 0 || arrSize > CM_PRIMARY_STANDBY_MAX_NUM) {
PrintCheckJsonInfo(ERROR,
"resource(%s)'s base_ip_list size(%d) must in [0: %d].\n", resName, arrSize, CM_PRIMARY_STANDBY_MAX_NUM);
return CM_ERROR;
}
// float_ip
CM_RETURN_IFERR(CheckIpValidInJson(resItem, "float_ip", resName, info[0].ip, CM_IP_LENGTH));
FloatIpResInfo curInfo = {0};
cJSON *instItem;
int32 index = 1;
cJSON_ArrayForEach(instItem, instArray) {
// res_instance_id
CM_RETURN_IFERR(CheckAndGetNumberFromJson(instItem, resName, INST_RES_INST_ID, &(curInfo.instId)));
// base_ip
CM_RETURN_IFERR(CheckIpValidInJson(instItem, g_instAttrMap[0], resName, curInfo.ip, CM_IP_LENGTH));
CM_RETURN_IFERR(CheckFloatIPResInfo(resName, info, CM_PRIMARY_STANDBY_MAX_NUM + 1, &index, &curInfo));
}
return CM_SUCCESS;
}
static status_t CheckResName(
const cJSON *resItem, char (*resName)[CM_MAX_RES_NAME], uint32 maxCnt, uint32 *curCnt, const char **curResName)
{
cJSON *objName = cJSON_GetObjectItem(resItem, RES_NAME);
CM_RETERR_IF_FALSE(CmCheckIsJsonString(objName, "", RES_NAME, ERROR));
if (strlen(objName->valuestring) >= CM_MAX_RES_NAME) {
PrintCheckJsonInfo(ERROR, "resource's name(%s) length exceeds the maximum(%d).\n",
objName->valuestring, CM_MAX_RES_NAME);
return CM_ERROR;
}
uint32 resNameCount = *curCnt;
if (resNameCount >= maxCnt) {
PrintCheckJsonInfo(ERROR, "resource count exceeds the maximum(%u).\n", maxCnt);
return CM_ERROR;
}
errno_t rc = strcpy_s(resName[resNameCount], CM_MAX_RES_NAME, objName->valuestring);
securec_check_errno(rc, (void)rc);
*curResName = resName[resNameCount];
for (uint32 i = 0; i < resNameCount; i++) {
if (strcmp(resName[resNameCount], resName[i]) == 0) {
PrintCheckJsonInfo(ERROR, "resource(%s)'s configure repeated.\n", objName->valuestring);
return CM_ERROR;
}
}
++(*curCnt);
return CM_SUCCESS;
}
static void GetAllRestypeStr(char *typeStr, uint32 maxlen)
{
errno_t rc;
uint32 arrLen = (uint32)(sizeof(g_resTypeMap) / sizeof(g_resTypeMap[0]));
char tmpStr[MAX_PATH_LEN] = {0};
for (uint32 i = 0; i < arrLen; ++i) {
if (g_resTypeMap[i].type == RES_TYPE_UNKNOWN) {
continue;
}
if (strlen(typeStr) + strlen(g_resTypeMap[i].typeStr) >= maxlen) {
return;
}
if (i == 0) {
rc = snprintf_s(tmpStr, MAX_PATH_LEN, MAX_PATH_LEN - 1, "\"%s\"", g_resTypeMap[i].typeStr);
} else {
rc = snprintf_s(tmpStr, MAX_PATH_LEN, MAX_PATH_LEN - 1, ", \"%s\"", g_resTypeMap[i].typeStr);
}
securec_check_intval(rc, (void)rc);
rc = strcat_s(typeStr, maxlen, tmpStr);
securec_check_errno(rc, (void)rc);
}
}
bool CompareResType(const char *value, uint32 *index)
{
if (value == NULL) {
write_runlog(ERROR, "value is NULL.\n");
return false;
}
char resTypeStr[MAX_PATH_LEN] = {0};
errno_t rc;
uint32 arrLen = (uint32)(sizeof(g_resTypeMap) / sizeof(g_resTypeMap[0]));
char tmpStr[MAX_PATH_LEN] = {0};
for (uint32 i = 0; i < arrLen; ++i) {
if (g_resTypeMap[i].typeStr == NULL) {
continue;
}
if (cm_str_equal(value, g_resTypeMap[i].typeStr)) {
*index = i;
return true;
}
if (i == 0) {
rc = snprintf_s(
tmpStr, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s-%s", g_resTypeMap[i].typeStr, g_resTypeMap[i].value);
} else {
rc = snprintf_s(
tmpStr, MAX_PATH_LEN, MAX_PATH_LEN - 1, ", %s-%s", g_resTypeMap[i].typeStr, g_resTypeMap[i].value);
}
securec_check_intval(rc, (void)rc);
rc = strcat_s(resTypeStr, MAX_PATH_LEN, tmpStr);
securec_check_errno(rc, (void)rc);
}
write_runlog(DEBUG1, "cannot find resType%s in g_resTypeMap%s.\n", value, resTypeStr);
return false;
}
static uint32 GetResTypeIndex(cJSON *resItem, const char *resName)
{
cJSON *objValue = cJSON_GetObjectItem(resItem, RESOURCE_TYPE);
if (!CmCheckIsJsonString(objValue, resName, RESOURCE_TYPE, WARNING)) {
return 0;
}
uint32 index = 0;
if (CompareResType(objValue->valuestring, &index)) {
return index;
}
char allResName[MAX_PATH_LEN] = {0};
GetAllRestypeStr(allResName, MAX_PATH_LEN);
PrintCheckJsonInfo(WARNING, "resource(%s)'s resources_type is (%s), not in range(%s), default(%s).\n",
resName, objValue->string, allResName, ResConfDefValue(RESOURCE_TYPE));
return 0;
}
ResType GetResTypeFromCjson(cJSON *resItem)
{
const char *resType = GetValueStrFromCJson(resItem, RESOURCE_TYPE);
if (resType == NULL) {
resType = ResConfDefValue(RESOURCE_TYPE);
}
if (CM_IS_EMPTY_STR(resType)) {
return RES_TYPE_UNKNOWN;
}
for (uint32 i = 0; i < (uint32)RES_TYPE_CEIL; ++i) {
if (g_resTypeMap[i].typeStr == NULL) {
continue;
}
if (g_resTypeMap[i].type == RES_TYPE_UNKNOWN) {
continue;
}
if (cm_str_equal(g_resTypeMap[i].typeStr, resType)) {
return g_resTypeMap[i].type;
}
}
return RES_TYPE_UNKNOWN;
}
static CheckResInfo GetResCheckFunc(uint32 curIndex)
{
if (curIndex >= (uint32)RES_TYPE_CEIL) {
return NULL;
}
return g_resTypeMap[curIndex].check;
}
status_t CheckResFromArray(cJSON *resArray)
{
cJSON *resItem;
const uint32 maxResCnt = CM_MAX_RES_COUNT + CM_MAX_VIP_COUNT;
char resName[maxResCnt][CM_MAX_RES_NAME];
uint32 resNameCount = 0;
cJSON_ArrayForEach(resItem, resArray) {
const char *curResName;
CM_RETURN_IFERR(CheckResName(resItem, resName, maxResCnt, &resNameCount, &curResName));
CheckResInfo check = GetResCheckFunc(GetResTypeIndex(resItem, curResName));
// resource may not be checked.
if (check != NULL) {
CM_RETURN_IFERR(check(resItem, curResName));
}
}
return CM_SUCCESS;
}
static status_t GetLocalJsonMd5(const char *jsonFile, char *result, uint32 resultLen)
{
char localMd5Cmd[MAX_PATH_LEN] = {0};
int ret = sprintf_s(localMd5Cmd, MAX_PATH_LEN, "md5sum -t %s | awk '{print $1}'", jsonFile);
securec_check_intval(ret, (void)ret);
FILE *fp = popen(localMd5Cmd, "r");
if (fp == NULL) {
PrintCheckJsonInfo(ERROR, "execute command:\"md5sum %s\" failed.\n", jsonFile);
return CM_ERROR;
}
if (fgets(result, ((int32)resultLen) - 1, fp) == NULL) {
(void)pclose(fp);
PrintCheckJsonInfo(ERROR, "can't get local md5sum of %s.\n", jsonFile);
return CM_ERROR;
}
(void)pclose(fp);
return CM_SUCCESS;
}
status_t CheckRemoteJson(const char *jsonFile)
{
char localMd5[NAMEDATALEN] = {0};
CM_RETURN_IFERR(GetLocalJsonMd5(jsonFile, localMd5, NAMEDATALEN));
char remoteMd5Cmd[MAX_PATH_LEN];
int ret = sprintf_s(remoteMd5Cmd, MAX_PATH_LEN, "md5sum -t %s | grep -w %s", jsonFile, localMd5);
securec_check_intval(ret, (void)ret);
status_t result = CM_SUCCESS;
for (uint32 i = 0; i < g_node_num; ++i) {
if (g_node[i].node == g_currentNode->node) {
continue;
}
if (ssh_exec(&g_node[i], remoteMd5Cmd, DEBUG1) != 0) {
PrintCheckJsonInfo(ERROR, "node(%u)'s cm_resource.json not same with local, please check ip(%s)'s json.\n",
g_node[i].node, g_node[i].sshChannel[0]);
result = CM_ERROR;
}
}
return result;
}
void InitResTypeMap()
{
errno_t rc = memset_s(g_resTypeMap, sizeof(g_resTypeMap), 0, sizeof(g_resTypeMap));
securec_check_errno(rc, (void)rc);
g_resTypeMap[RES_TYPE_UNKNOWN].type = RES_TYPE_UNKNOWN;
g_resTypeMap[RES_TYPE_UNKNOWN].typeStr = "APP";
g_resTypeMap[RES_TYPE_UNKNOWN].value = INSTANCES;
g_resTypeMap[RES_TYPE_UNKNOWN].check = CheckAppResInfo;
g_resTypeMap[RES_TYPE_APP].type = RES_TYPE_APP;
g_resTypeMap[RES_TYPE_APP].typeStr = "APP";
g_resTypeMap[RES_TYPE_APP].value = INSTANCES;
g_resTypeMap[RES_TYPE_APP].check = CheckAppResInfo;
g_resTypeMap[RES_TYPE_DN].type = RES_TYPE_DN;
g_resTypeMap[RES_TYPE_DN].typeStr = "DN";
g_resTypeMap[RES_TYPE_DN].value = NULL;
g_resTypeMap[RES_TYPE_DN].check = CheckDnResInfo;
g_resTypeMap[RES_TYPE_VIP].type = RES_TYPE_VIP;
g_resTypeMap[RES_TYPE_VIP].typeStr = "VIP";
g_resTypeMap[RES_TYPE_VIP].value = INSTANCES;
g_resTypeMap[RES_TYPE_VIP].check = CheckVipResInfo;
}
bool8 IsResCheckInstances(ResType resType)
{
uint32 len = ELEMENT_COUNT(g_resTypeMap);
for (uint32 i = 0; i < len; ++i) {
if (resType == g_resTypeMap[i].type && g_resTypeMap[i].value != NULL) {
return CM_TRUE;
}
}
return CM_FALSE;
}
bool8 IsCurNotCheckInstances(const ResOption *resCtx, const cJSON *resObj)
{
ResType type = GetResTypeInJson(resCtx, resObj);
uint32 len = ELEMENT_COUNT(g_resTypeMap);
for (uint32 i = 0; i < len; ++i) {
if (type == g_resTypeMap[i].type && g_resTypeMap[i].value == NULL) {
return CM_TRUE;
}
}
return CM_FALSE;
}
const char *GetResTypeValue(uint32 index)
{
return g_resTypeMap[index].value;
}

857
src/cm_ctl/ctl_res_list.cpp Normal file
View File

@ -0,0 +1,857 @@
/*
* Copyright (c) 2022 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_res_list.cpp
*
* IDENTIFICATION
* src/cm_ctl/ctl_res_list.cpp
*
* -------------------------------------------------------------------------
*/
#include "ctl_res_list.h"
#include "cjson/cJSON.h"
#include "cm_text.h"
#include "cm_elog.h"
#include "cm_misc_res.h"
#include "cm_misc.h"
#include "ctl_global_params.h"
#include "ctl_res.h"
typedef struct ResBaseInfoT {
CmConstText resName;
CmConstText resType;
} ResBaseInfo;
typedef struct PrintArrayT {
const char **arr;
uint32 arrLen;
} PrintArray;
typedef struct ResPrintInfoT {
PrintArray resArr;
PrintArray instArr;
} ResPrintInfo;
typedef struct ResValueInfoT {
char *attrChar;
uint32 attrValue;
uint32 len;
uint32 value[0];
} ResValueInfo;
// for str '\0'
static const uint32 TEXT_RESERVE_LEN = 10;
static const char *const PRINT_TABLE_SPEPARATOR = "-";
static const char *const PRINT_TABLE_SPLIT = "| ";
static const char *const PRINT_NULL = "Null";
static const uint32 LIST_RES_SPACE_LEN = 1;
static const int32 TEN_MECHAN = 10;
static const char *g_resCom[] = {RES_NAME, RESOURCE_TYPE};
static const char *g_appResArr[] = {
RES_SCRIPT, RES_CHECK_INTERVAL, RES_TIMEOUT, RES_RESTART_DELAY, RES_PERIOD, RES_RESTART_TIMES};
static const char *g_appInstArr[] = {INST_NODE_ID, INST_RES_INST_ID, INST_REG};
// VIP
static const char *g_vipResArr[] = {RES_FLOAT_IP};
static const char *g_vipInstArr[] = {INST_NODE_ID, INST_RES_INST_ID, INST_ATTR};
static const char *g_resAttr[] = {RES_FLOAT_IP, INST_ATTR};
static const char *g_resSkipAttr[] = {RES_ATTR, INST_ATTR};
static ResPrintInfo g_printInfo[RES_TYPE_CEIL];
static KvRestrict g_resAllKv[] = {{RES_KV_TYPE_STRING, RES_NAME},
{RES_KV_TYPE_STRING, RESOURCE_TYPE},
{RES_KV_TYPE_STRING, RES_SCRIPT},
{RES_KV_TYPE_INTEGER, RES_CHECK_INTERVAL},
{RES_KV_TYPE_INTEGER, RES_TIMEOUT},
{RES_KV_TYPE_INTEGER, RES_RESTART_DELAY},
{RES_KV_TYPE_INTEGER, RES_PERIOD},
{RES_KV_TYPE_INTEGER, RES_RESTART_TIMES},
{RES_KV_TYPE_INTEGER, INST_NODE_ID},
{RES_KV_TYPE_INTEGER, INST_RES_INST_ID},
{RES_KV_TYPE_STRING, RES_FLOAT_IP},
{RES_KV_TYPE_STRING, INST_REG},
{RES_KV_TYPE_STRING, INST_ATTR},
{RES_KV_TYPE_STRING, RES_ATTR}};
static void PrintListTitle()
{
(void)fprintf(g_logFilePtr, "\n[ CM Resource Info ]\n\n");
}
static bool8 IsInSkipAttr(const char *key)
{
if (CM_IS_EMPTY_STR(key)) {
return CM_FALSE;
}
uint32 len = ELEMENT_COUNT(g_resSkipAttr);
for (uint32 i = 0; i < len; ++i) {
if (cm_str_equal(g_resSkipAttr[i], key)) {
return CM_TRUE;
}
}
return CM_FALSE;
}
static void InitResBaseInfo(ResBaseInfo *info)
{
errno_t rc = memset_s(info, sizeof(ResBaseInfo), 0, sizeof(ResBaseInfo));
securec_check_errno(rc, (void)rc);
info->resName.str = RES_NAME;
info->resName.len = (uint32)strlen(RES_NAME);
info->resType.str = RESOURCE_TYPE;
info->resType.len = (uint32)strlen(RESOURCE_TYPE);
}
static status_t SetResBaseInfoInArray(ResBaseInfo *info, const cJSON *resArray, const ResOption *resCtx)
{
const cJSON *item;
const char *resName;
const char *resType;
bool8 isCanPrint = CM_FALSE;
cJSON_ArrayForEach(item, resArray) {
if (!cJSON_IsObject(item)) {
continue;
}
resName = GetValueStrFromCJson(item, RES_NAME);
if (resName == NULL) {
resName = NULL;
} else {
isCanPrint = CM_TRUE;
}
info->resName.len = CM_MAX(info->resName.len, (uint32)strlen(resName));
resType = GetValueStrFromCJson(item, RESOURCE_TYPE);
if (resType == NULL) {
resType = ResConfDefValue(RESOURCE_TYPE);
}
info->resType.len = CM_MAX(info->resType.len, (uint32)strlen(resType));
}
// space
info->resName.len += LIST_RES_SPACE_LEN;
info->resType.len += LIST_RES_SPACE_LEN;
if (!isCanPrint) {
write_runlog(ERROR, "%s%s Res(%s) cannot print res info, when no res in json.\n", GetResOperStr(resCtx->mode),
GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return CM_ERROR;
}
return CM_SUCCESS;
}
static void PrintAllResInfoTitle(const ResBaseInfo *info)
{
(void)fprintf(g_logFilePtr, "%-*s%s%-*s\n",
info->resName.len, info->resName.str,
PRINT_TABLE_SPLIT,
info->resType.len, info->resType.str);
// ---
uint32 totalLen = info->resName.len + info->resType.len + (uint32)strlen(PRINT_TABLE_SPLIT);
for (uint32 i = 0; i < totalLen; ++i) {
(void)fprintf(g_logFilePtr, "%s", PRINT_TABLE_SPEPARATOR);
}
(void)fprintf(g_logFilePtr, "\n");
}
static void PrintAllResInfoBody(const ResBaseInfo *info, const cJSON *resArray)
{
const cJSON *item;
const char *resName;
const char *resType;
cJSON_ArrayForEach(item, resArray) {
if (!cJSON_IsObject(item)) {
continue;
}
resName = GetValueStrFromCJson(item, RES_NAME);
if (resName == NULL) {
resName = NULL;
}
resType = GetValueStrFromCJson(item, RESOURCE_TYPE);
if (resType == NULL) {
resType = ResConfDefValue(RESOURCE_TYPE);
}
(void)fprintf(g_logFilePtr, "%-*s%s%-*s\n",
info->resName.len, resName,
PRINT_TABLE_SPLIT,
info->resType.len, resType);
}
}
static bool8 IsInResArr(const char *key)
{
if (key == NULL) {
return CM_FALSE;
}
uint32 len = ELEMENT_COUNT(g_resAttr);
for (uint32 i = 0; i < len; ++i) {
if (cm_str_equal(key, g_resAttr[i])) {
return CM_TRUE;
}
}
return CM_FALSE;
}
static uint32 GetValueLen(int32 value, int32 mechan = TEN_MECHAN)
{
if (mechan == 0) {
write_runlog(DEBUG1, "fail to get value len, whne mechan is 0.\n");
return 0;
}
uint32 len = 0;
int32 tmpValue = value;
int32 tmpMechan = abs(mechan);
if (tmpValue < 0) {
// minus sign
tmpValue = abs(tmpValue);
len += 1;
}
while (tmpValue != 0) {
tmpValue /= tmpMechan;
++len;
}
return len;
}
static status_t PrintAllResInfo(const cJSON *resArray, const ResOption *resCtx)
{
PrintListTitle();
ResBaseInfo info;
InitResBaseInfo(&info);
CM_RETURN_IFERR(SetResBaseInfoInArray(&info, resArray, resCtx));
PrintAllResInfoTitle(&info);
PrintAllResInfoBody(&info, resArray);
return CM_SUCCESS;
}
static status_t CheckListParam(cJSON *resArray, const ResOption *resCtx)
{
if (resArray == NULL) {
write_runlog(ERROR, "%s%s Res(%s) cannot list res, when resArray is NULL.\n", GetResOperStr(resCtx->mode),
GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return CM_ERROR;
}
return CM_SUCCESS;
}
static void InitListFunc()
{
errno_t rc = memset_s(g_printInfo, sizeof(g_printInfo), 0, sizeof(g_printInfo));
securec_check_errno(rc, (void)rc);
g_printInfo[RES_TYPE_APP].resArr.arr = g_appResArr;
g_printInfo[RES_TYPE_APP].resArr.arrLen = ELEMENT_COUNT(g_appResArr);
g_printInfo[RES_TYPE_APP].instArr.arr = g_appInstArr;
g_printInfo[RES_TYPE_APP].instArr.arrLen = ELEMENT_COUNT(g_appInstArr);
g_printInfo[RES_TYPE_DN].resArr.arr = g_appResArr;
g_printInfo[RES_TYPE_DN].resArr.arrLen = ELEMENT_COUNT(g_appResArr);
g_printInfo[RES_TYPE_VIP].resArr.arr = g_vipResArr;
g_printInfo[RES_TYPE_VIP].resArr.arrLen = ELEMENT_COUNT(g_vipResArr);
g_printInfo[RES_TYPE_VIP].instArr.arr = g_vipInstArr;
g_printInfo[RES_TYPE_VIP].instArr.arrLen = ELEMENT_COUNT(g_vipInstArr);
}
static ResPrintInfo *GetPrintInfo(cJSON *objItem, const ResOption *resCtx)
{
ResType type = GetResTypeFromCjson(objItem);
if (type == RES_TYPE_UNKNOWN) {
write_runlog(ERROR, "%s%s Res(%s) cannot get print Info, when type is %d.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, (int32)type);
return NULL;
}
if (type >= RES_TYPE_CEIL) {
write_runlog(ERROR, "%s%s Res(%s) cannot get print Info, when type is %d.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, (int32)type);
return NULL;
}
return &(g_printInfo[type]);
}
static ResValueInfo *InitValueArr(uint32 arrLen, const ResOption *resCtx)
{
uint32 totalLen = arrLen + (uint32)ELEMENT_COUNT(g_resCom);
size_t totalsize = sizeof(ResValueInfo) + sizeof(uint32) * totalLen;
ResValueInfo *valueArr = (ResValueInfo *)malloc(totalsize);
if (valueArr == NULL) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to print list info, when valueArr is NULL, and len=[%u: %zu].\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, totalLen, totalsize);
write_runlog(ERROR, "%s%s Res(%s) fails to print list info, when valueArr is NULL.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return NULL;
}
errno_t rc = memset_s(valueArr, totalsize, 0, totalsize);
securec_check_errno(rc, (void)rc);
valueArr->len = totalLen;
return valueArr;
}
static ResKvType GetCurKvType(const char *key)
{
if (key == NULL) {
return RES_KV_TYPE_UNKNOWN;
}
uint32 len = ELEMENT_COUNT(g_resAllKv);
for (uint32 i = 0; i < len; ++i) {
if (cm_str_equal(g_resAllKv[i].key, key)) {
return g_resAllKv[i].type;
}
}
return RES_KV_TYPE_UNKNOWN;
}
static int32 GetValueIntOrDefValueFromJson(const cJSON *root, const char *key)
{
int32 value = GetValueIntFromCJson(root, key, DEBUG1);
if (value == -1) {
value = CmAtoi(ResConfDefValue(key), -1);
}
return value;
}
static uint32 GetValueLenFromJson(const cJSON *root, const char *key)
{
int32 value = GetValueIntOrDefValueFromJson(root, key);
return GetValueLen(value);
}
static const char *GetValueStrOrDefValueFromJson(const cJSON *root, const char *key)
{
const char *value = GetValueStrFromCJson(root, key, DEBUG1);
if (value == NULL) {
value = ResConfDefValue(key);
}
if (value == NULL) {
value = PRINT_NULL;
}
return value;
}
static uint32 GetValueStrLenFromJson(const cJSON *root, const char *key)
{
const char *value = GetValueStrOrDefValueFromJson(root, key);
if (value == NULL) {
return 0;
}
return (uint32)strlen(value);
}
static uint32 GetCJsonItemLen(const cJSON *root, const char *key, const ResOption *resCtx)
{
if (!cJSON_IsObject(root)) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to get cJson item len, when root is not object.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return 0;
}
if (CM_IS_EMPTY_STR(key)) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to get cJson item len, when key is empty.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return 0;
}
ResKvType type = GetCurKvType(key);
if (type == RES_KV_TYPE_UNKNOWN) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to get cJson item len, when type is unknown.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return 0;
}
uint32 valueLen = 0;
switch (type) {
case RES_KV_TYPE_INTEGER:
valueLen = GetValueLenFromJson(root, key);
break;
case RES_KV_TYPE_STRING:
valueLen = GetValueStrLenFromJson(root, key);
break;
default:;
}
if (!IsInResArr(key)) {
return valueLen;
}
if (!IsInSkipAttr(key)) {
// "="
const uint32 splitLen = 1;
return (uint32)strlen(key) + splitLen + valueLen;
}
return valueLen;
}
static void InitArrItemLen(
ResValueInfo *valueArr, const PrintArray *printInfo, uint32 *index, const ResOption *resCtx, const char *attrName)
{
uint32 tmpIndex = *index;
const char *key;
for (uint32 i = 0; i < printInfo->arrLen; ++i) {
if (tmpIndex + i >= valueArr->len) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to init arr Item len, when tmpIndex=%u, i=%u, len=%u.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, tmpIndex, i,
valueArr->len);
break;
}
key = printInfo->arr[i];
if (!IsInResArr(key)) {
valueArr->value[tmpIndex + i] = (uint32)strlen(key);
} else {
valueArr->attrValue = (uint32)strlen(attrName);
}
}
*index = tmpIndex + printInfo->arrLen;
}
static void InitListArrItem(ResValueInfo *valueArr, const ResOption *resCtx, const PrintArray *printInfo)
{
uint32 index = 0;
// g_resComm
PrintArray tmpArray = {.arr = g_resCom, .arrLen = ELEMENT_COUNT(g_resCom)};
InitArrItemLen(valueArr, &tmpArray, &index, resCtx, INST_ATTR);
// printInfo
InitArrItemLen(valueArr, printInfo, &index, resCtx, INST_ATTR);
}
static void ComputeArrItemLen(
const cJSON *objItem, ResValueInfo *valueArr, uint32 *index, const PrintArray *printInfo, const ResOption *resCtx)
{
uint32 tmpIndex = *index;
const char *key;
for (uint32 i = 0; i < printInfo->arrLen; ++i) {
if (tmpIndex + i >= valueArr->len) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to compute arr Item len, when tmpIndex=%u, i=%u, len=%u.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, tmpIndex, i,
valueArr->len);
break;
}
key = printInfo->arr[i];
if (!IsInResArr(key)) {
valueArr->value[tmpIndex + i] =
CM_MAX(GetCJsonItemLen(objItem, key, resCtx), valueArr->value[tmpIndex + i]);
} else {
if (valueArr->attrValue == 0) {
valueArr->attrValue += GetCJsonItemLen(objItem, key, resCtx);
} else {
// ","
valueArr->attrValue += GetCJsonItemLen(objItem, key, resCtx) + 1;
}
}
}
*index = tmpIndex + printInfo->arrLen;
}
static void AddSplit(ResValueInfo *valueArr)
{
// add split
for (uint32 i = 0; i < valueArr->len; ++i) {
if (valueArr->value[i] == 0) {
continue;
}
valueArr->value[i] += LIST_RES_SPACE_LEN;
}
if (valueArr->attrValue != 0) {
valueArr->attrValue += LIST_RES_SPACE_LEN;
}
}
static status_t ComputeListTableItemLen(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
// record attrValue
uint32 attrValue = valueArr->attrValue;
valueArr->attrValue = 0;
// g_resComm
uint32 index = 0;
PrintArray tmpArray = {.arr = g_resCom, .arrLen = ELEMENT_COUNT(g_resCom)};
ComputeArrItemLen(objItem, valueArr, &index, &tmpArray, resCtx);
// printInfo
cJSON *objArray = cJSON_GetObjectItem(objItem, INSTANCES);
if (!cJSON_IsArray(objArray)) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to compute cur table item len.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return CM_ERROR;
}
cJSON *item;
uint32 tmpAttrValue = valueArr->attrValue;
cJSON_ArrayForEach(item, objArray) {
if (!cJSON_IsObject(item)) {
continue;
}
attrValue = CM_MAX(valueArr->attrValue, attrValue);
valueArr->attrValue = tmpAttrValue;
ComputeArrItemLen(item, valueArr, &index, printInfo, resCtx);
}
valueArr->attrValue = CM_MAX(valueArr->attrValue, attrValue);
AddSplit(valueArr);
return CM_SUCCESS;
}
static void PrintTableTileItem(
const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx, uint32 *index, bool8 isFirst)
{
uint32 tmpIndex = *index;
bool8 isTmpFirst = isFirst;
for (uint32 i = 0; i < printInfo->arrLen; ++i) {
if (tmpIndex + i >= valueArr->len) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to print table title item, when tmpIndex=%u, i=%u, len=%u.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, tmpIndex, i,
valueArr->len);
break;
}
if (valueArr->value[tmpIndex + i] == 0) {
continue;
}
if (isTmpFirst) {
isTmpFirst = CM_FALSE;
(void)fprintf(g_logFilePtr, "%-*s", valueArr->value[tmpIndex + i], printInfo->arr[i]);
} else {
(void)fprintf(g_logFilePtr, "%s%-*s", PRINT_TABLE_SPLIT, valueArr->value[tmpIndex + i], printInfo->arr[i]);
}
}
*index = tmpIndex + printInfo->arrLen;
}
static void PrintListTableTile(
const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx, const char *attrName)
{
uint32 index = 0;
// g_resComm
PrintArray tmpArray = {.arr = g_resCom, .arrLen = ELEMENT_COUNT(g_resCom)};
PrintTableTileItem(&tmpArray, valueArr, resCtx, &index, CM_TRUE);
// prinfInfo
PrintTableTileItem(printInfo, valueArr, resCtx, &index, CM_FALSE);
if (valueArr->attrValue != 0) {
(void)fprintf(g_logFilePtr, "%s%-*s", PRINT_TABLE_SPLIT, valueArr->attrValue, attrName);
}
(void)fprintf(g_logFilePtr, "\n");
}
static void PrintListTableSperatorBar(ResValueInfo *valueArr)
{
uint32 totalLen = valueArr->attrValue;
uint32 trueCnt = 0;
if (totalLen != 0) {
++trueCnt;
}
for (uint32 i = 0; i < valueArr->len; ++i) {
if (valueArr->value[i] == 0) {
continue;
}
totalLen += valueArr->value[i];
++trueCnt;
}
if (trueCnt >= 1) {
totalLen += (trueCnt - 1) * (uint32)strlen(PRINT_TABLE_SPLIT);
}
for (uint32 i = 0; i < totalLen; ++i) {
(void)fprintf(g_logFilePtr, "%s", PRINT_TABLE_SPEPARATOR);
}
(void)fprintf(g_logFilePtr, "\n");
}
static status_t PrintListTableInfo(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
InitListArrItem(valueArr, resCtx, printInfo);
CM_RETURN_IFERR(ComputeListTableItemLen(objItem, printInfo, valueArr, resCtx));
PrintListTableTile(printInfo, valueArr, resCtx, INST_ATTR);
PrintListTableSperatorBar(valueArr);
return CM_SUCCESS;
}
static void PrintNameAndResType(const char *resName, const char *resType, ResValueInfo *valueArr)
{
(void)fprintf(g_logFilePtr, "%-*s%s%-*s", valueArr->value[0], resName, PRINT_TABLE_SPLIT, valueArr->value[1],
resType);
}
static void SetResAttrFromJson(const cJSON *root, const char *key, ResValueInfo *valueArr, const ResOption *resCtx)
{
ResKvType type = GetCurKvType(key);
if (type == RES_KV_TYPE_UNKNOWN) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to set res attr from json, when type is unknown.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return;
}
errno_t rc;
uint32 curLen = (uint32)strlen(valueArr->attrChar);
if (curLen != 0) {
rc = strcat_s(valueArr->attrChar, valueArr->attrValue, ",");
securec_check_errno(rc, (void)rc);
++curLen;
}
if (!IsInSkipAttr(key)) {
rc = snprintf_s(valueArr->attrChar + curLen, valueArr->attrValue - curLen, (valueArr->attrValue - curLen) - 1,
"%s=", key);
securec_check_intval(rc, (void)rc);
}
curLen = (uint32)strlen(valueArr->attrChar);
switch (type) {
case RES_KV_TYPE_INTEGER:
rc = snprintf_s(valueArr->attrChar + curLen, valueArr->attrValue - curLen,
(valueArr->attrValue - curLen) - 1, "%d", GetValueIntOrDefValueFromJson(root, key));
securec_check_intval(rc, (void)rc);
break;
case RES_KV_TYPE_STRING:
rc = snprintf_s(valueArr->attrChar + curLen, valueArr->attrValue - curLen,
(valueArr->attrValue - curLen) - 1, "%s", GetValueStrOrDefValueFromJson(root, key));
securec_check_intval(rc, (void)rc);
break;
default:;
}
return;
}
static void PrintInfoFromCjson(const cJSON *root, const char *key, uint32 len, const ResOption *resCtx)
{
ResKvType type = GetCurKvType(key);
if (type == RES_KV_TYPE_UNKNOWN) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to set res attr from json, when type is unknown.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return;
}
switch (type) {
case RES_KV_TYPE_INTEGER:
(void)fprintf(g_logFilePtr, "%s%-*d", PRINT_TABLE_SPLIT, len, GetValueIntOrDefValueFromJson(root, key));
break;
case RES_KV_TYPE_STRING:
(void)fprintf(g_logFilePtr, "%s%-*s", PRINT_TABLE_SPLIT, len, GetValueStrOrDefValueFromJson(root, key));
break;
default:;
}
return;
}
static void PrintCJsonBody(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
const char *key;
const uint32 otherIndex = 2;
for (uint32 i = 0; i < printInfo->arrLen; ++i) {
if (otherIndex + i >= valueArr->len) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to print cjson body, when index=%u, i=%u, len=%u.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, otherIndex, i,
valueArr->len);
break;
}
key = printInfo->arr[i];
if (IsInResArr(key)) {
SetResAttrFromJson(objItem, key, valueArr, resCtx);
} else {
PrintInfoFromCjson(objItem, key, valueArr->value[otherIndex + i], resCtx);
}
}
if (valueArr->attrValue != 0) {
(void)fprintf(g_logFilePtr, "%s%-*s", PRINT_TABLE_SPLIT, valueArr->attrValue, valueArr->attrChar);
}
(void)fprintf(g_logFilePtr, "\n");
}
static void SetAttrChar(ResValueInfo *valueArr)
{
if (valueArr->attrValue == 0 || valueArr->attrChar == NULL) {
return;
}
errno_t rc =
memset_s(valueArr->attrChar, valueArr->attrValue + TEXT_RESERVE_LEN, 0, valueArr->attrValue + TEXT_RESERVE_LEN);
securec_check_errno(rc, (void)rc);
}
static status_t InitAttrChar(ResValueInfo *valueArr, const ResOption *resCtx)
{
if (valueArr->attrValue == 0) {
return CM_SUCCESS;
}
valueArr->attrChar = (char *)malloc(valueArr->attrValue + TEXT_RESERVE_LEN);
if (valueArr->attrChar == NULL) {
write_runlog(ERROR, "%s%s res(%s) fails to malloc attr char.\n", GetResOperStr(resCtx->mode),
GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return CM_ERROR;
}
SetAttrChar(valueArr);
return CM_SUCCESS;
}
static status_t PrintListTableBody(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
const uint32 minValueLen = 2;
if (valueArr->value == NULL || valueArr->len < minValueLen) {
write_runlog(ERROR, "%s%s Res(%s) fails to print list table body, when value is NULL, or len=[%u: %u].\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, valueArr->len,
minValueLen);
return CM_ERROR;
}
const char *resName = GetValueStrOrDefValueFromJson(objItem, RES_NAME);
const char *resType = GetValueStrOrDefValueFromJson(objItem, RESOURCE_TYPE);
cJSON *objArray = cJSON_GetObjectItem(objItem, INSTANCES);
if (!cJSON_IsArray(objArray)) {
write_runlog(DEBUG1, "%s%s Res(%s) fails to print list table body, when objArray is not array.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return CM_ERROR;
}
CM_RETURN_IFERR(InitAttrChar(valueArr, resCtx));
cJSON *item;
cJSON_ArrayForEach(item, objArray) {
PrintNameAndResType(resName, resType, valueArr);
PrintCJsonBody(item, printInfo, valueArr, resCtx);
SetAttrChar(valueArr);
}
FREE_AND_RESET(valueArr->attrChar);
return CM_SUCCESS;
}
static status_t PrintListInfo(const cJSON *objItem, const ResOption *resCtx, const PrintArray *printInfo)
{
if (printInfo->arr == NULL || printInfo->arrLen == 0) {
return CM_SUCCESS;
}
PrintListTitle();
ResValueInfo *valueArr = InitValueArr(printInfo->arrLen, resCtx);
CM_RETERR_IF_NULL(valueArr);
status_t st = CM_SUCCESS;
do {
st = PrintListTableInfo(objItem, printInfo, valueArr, resCtx);
CM_BREAK_IF_ERROR(st);
st = PrintListTableBody(objItem, printInfo, valueArr, resCtx);
CM_BREAK_IF_ERROR(st);
} while (0);
FREE_AND_RESET(valueArr);
return st;
}
static void InitResArrItem(ResValueInfo *valueArr, const ResOption *resCtx, const PrintArray *printInfo)
{
uint32 index = 0;
// g_resComm
PrintArray tmpArray = {.arr = g_resCom, .arrLen = ELEMENT_COUNT(g_resCom)};
InitArrItemLen(valueArr, &tmpArray, &index, resCtx, RES_NAME);
// printInfo
InitArrItemLen(valueArr, printInfo, &index, resCtx, RES_NAME);
}
static void ComputeResTableItemLen(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
// record attrValue
uint32 attrValue = valueArr->attrValue;
valueArr->attrValue = 0;
// g_resComm
uint32 index = 0;
PrintArray tmpArray = {.arr = g_resCom, .arrLen = ELEMENT_COUNT(g_resCom)};
ComputeArrItemLen(objItem, valueArr, &index, &tmpArray, resCtx);
ComputeArrItemLen(objItem, valueArr, &index, printInfo, resCtx);
valueArr->attrValue = CM_MAX(valueArr->attrValue, attrValue);
AddSplit(valueArr);
}
static void PrintResTableInfo(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
InitResArrItem(valueArr, resCtx, printInfo);
ComputeResTableItemLen(objItem, printInfo, valueArr, resCtx);
PrintListTableTile(printInfo, valueArr, resCtx, RES_ATTR);
PrintListTableSperatorBar(valueArr);
}
static status_t PrintResTableBody(
const cJSON *objItem, const PrintArray *printInfo, ResValueInfo *valueArr, const ResOption *resCtx)
{
const uint32 minValueLen = 2;
if (valueArr->value == NULL || valueArr->len < minValueLen) {
write_runlog(ERROR, "%s%s Res(%s) fails to print res table body, when value is NULL, or len=[%u: %u].\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName,
valueArr->len, minValueLen);
return CM_ERROR;
}
const char *resName = GetValueStrOrDefValueFromJson(objItem, RES_NAME);
const char *resType = GetValueStrOrDefValueFromJson(objItem, RESOURCE_TYPE);
CM_RETURN_IFERR(InitAttrChar(valueArr, resCtx));
PrintNameAndResType(resName, resType, valueArr);
PrintCJsonBody(objItem, printInfo, valueArr, resCtx);
FREE_AND_RESET(valueArr->attrChar);
return CM_SUCCESS;
}
static status_t PrintResInfo(const cJSON *objItem, const ResOption *resCtx, const PrintArray *printInfo)
{
if (printInfo->arr == NULL || printInfo->arrLen == 0) {
return CM_SUCCESS;
}
PrintListTitle();
ResValueInfo *valueArr = InitValueArr(printInfo->arrLen, resCtx);
CM_RETERR_IF_NULL(valueArr);
status_t st = CM_SUCCESS;
do {
PrintResTableInfo(objItem, printInfo, valueArr, resCtx);
st = PrintResTableBody(objItem, printInfo, valueArr, resCtx);
CM_BREAK_IF_ERROR(st);
} while (0);
FREE_AND_RESET(valueArr);
return st;
}
status_t ListResInJson(cJSON *resArray, const ResOption *resCtx)
{
InitListFunc();
CM_RETURN_IFERR(CheckListParam(resArray, resCtx));
if (CM_IS_EMPTY_STR(resCtx->resName)) {
return PrintAllResInfo(resArray, resCtx);
}
cJSON *objItem = GetCurResInArray(resArray, resCtx->resName, resCtx);
if (objItem == NULL) {
write_runlog(ERROR, "%s%s cannot list Res, because can't find the res(%s) in json.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName);
return CM_ERROR;
}
ResPrintInfo *printInfo = GetPrintInfo(objItem, resCtx);
if (printInfo == NULL) {
return CM_ERROR;
}
if (resCtx->inst.mode == RES_OP_LIST) {
return PrintListInfo(objItem, resCtx, &(printInfo->instArr));
}
if (resCtx->inst.mode != RES_OP_INIT) {
write_runlog(ERROR, "%s%s Res(%s) cannot list Res, because inst_mode(%u) may not be supported.\n",
GetResOperStr(resCtx->mode), GetInstOperStr(resCtx->inst.mode), resCtx->resName, (uint32)resCtx->inst.mode);
return CM_ERROR;
}
return PrintResInfo(objItem, resCtx, &(printInfo->resArr));
}

View File

@ -21,21 +21,349 @@
*
* -------------------------------------------------------------------------
*/
#include "cm/libpq-fe.h"
#include "ctl_common.h"
#include "ctl_show.h"
#include <time.h>
#include "c.h"
#include "cm_text.h"
#include "cm/libpq-fe.h"
#include "cm_msg_common.h"
#include "cm_elog.h"
#include "cm_rhb.h"
#include "cm_voting_disk.h"
#include "cm_json_parse_floatIp.h"
#include "ctl_global_params.h"
#include "ctl_misc.h"
#include "ctl_common.h"
#include "ctl_process_message.h"
#include "ctl_query_base.h"
#include "cm_misc_res.h"
typedef struct CtlFloatIpInstT {
uint32 dnIdx;
DnFloatIp floatIp;
} CtlFloatIpInst;
typedef struct CtlFloatIpNodeT {
uint32 nodeIdx;
uint32 instCnt;
CtlFloatIpInst floapIpInst[CM_MAX_DATANODE_PER_NODE];
} CtlFloatIpNode;
typedef struct CtlFloatIpMapT {
uint32 nodeCnt;
CtlFloatIpNode floatIpNode[0];
} CtlFloatIpMap;
typedef struct CtlFloatIpHeadSizeT {
CmConstText nodeText;
CmConstText instText;
CmConstText floatIpNameText;
CmConstText floatIpText;
CmConstText baseIpText;
} CtlFloatIpHeadSize;
static ParseFloatIpFunc g_ctlParseFuc = {0};
static CtlFloatIpMap *g_floatIpMap = NULL;
static uint32 g_floatIpCnt = 0;
static void GetMaxFloatIpNameLen(CtlFloatIpHeadSize *floatIpLen)
{
DnFloatIp *dnFloatIp;
uint32 len;
for (uint32 i = 0; i < g_floatIpMap->nodeCnt; ++i) {
for (uint32 j = 0; j < g_floatIpMap->floatIpNode[i].instCnt; ++j) {
for (uint32 k = 0; k < g_floatIpMap->floatIpNode[i].floapIpInst[j].floatIp.dnFloatIpCount; ++k) {
dnFloatIp = &(g_floatIpMap->floatIpNode[i].floapIpInst[j].floatIp);
// float_ip_name
len = (uint32)strlen(dnFloatIp->floatIpName[k]);
floatIpLen->floatIpNameText.len = CM_MAX(len, floatIpLen->floatIpNameText.len);
// base_ip
len = (uint32)strlen(dnFloatIp->baseIp[i]);
floatIpLen->baseIpText.len = CM_MAX(len, floatIpLen->baseIpText.len);
// float_ip
len = (uint32)strlen(dnFloatIp->dnFloatIp[i]);
floatIpLen->floatIpText.len = CM_MAX(len, floatIpLen->floatIpText.len);
}
}
}
floatIpLen->floatIpNameText.len += SPACE_LEN;
floatIpLen->baseIpText.len += SPACE_LEN;
floatIpLen->floatIpText.len += SPACE_LEN;
}
static void CalcFloatIpHeaderSize(CtlFloatIpHeadSize *floatIpLen)
{
// node
uint32 tmpNodeLen = (uint32)(MAX_NODE_ID_LEN + SPACE_LEN + max_node_name_len + SPACE_LEN);
floatIpLen->nodeText.len = CM_MAX(tmpNodeLen, floatIpLen->nodeText.len);
// instance
uint32 tmpInstLen = (uint32)(INSTANCE_ID_LEN + SPACE_LEN + DEFAULT_PATH_LEN);
floatIpLen->instText.len = CM_MAX(tmpInstLen, floatIpLen->instText.len);
GetMaxFloatIpNameLen(floatIpLen);
}
static void PrintFloatIpHeaderLine(const CtlFloatIpHeadSize *floatIpLen)
{
(void)fprintf(g_logFilePtr, "%-*s%-*s%-*s%-*s%-*s\n",
floatIpLen->nodeText.len, floatIpLen->nodeText.str,
floatIpLen->instText.len, floatIpLen->instText.str,
floatIpLen->baseIpText.len, floatIpLen->baseIpText.str,
floatIpLen->floatIpNameText.len, floatIpLen->floatIpNameText.str,
floatIpLen->floatIpText.len, floatIpLen->floatIpText.str);
uint32 totalLen = floatIpLen->nodeText.len + floatIpLen->instText.len + floatIpLen->baseIpText.len +
floatIpLen->floatIpNameText.len + floatIpLen->floatIpText.len;
for (uint32 i = 0; i < totalLen; ++i) {
(void)fprintf(g_logFilePtr, "-");
}
if (totalLen != 0) {
(void)fprintf(g_logFilePtr, "\n");
}
}
static bool8 CheckFloatIpInput(uint32 nodeIdx, uint32 instIdx, uint32 ipIdx)
{
if (g_floatIpMap == NULL) {
write_runlog(DEBUG1, "Failed to checkFloatIpInput, because g_floatIpMap is NULL.\n");
return CM_FALSE;
}
if (nodeIdx >= g_floatIpMap->nodeCnt) {
write_runlog(DEBUG1, "Failed to checkFloatIpInput, because nodeIdx is [%u: %u].\n",
nodeIdx, g_floatIpMap->nodeCnt);
return CM_FALSE;
}
if (instIdx >= g_floatIpMap->floatIpNode[nodeIdx].instCnt) {
write_runlog(DEBUG1, "Failed to checkFloatIpInput, because instId is [%u: %u].\n",
instIdx, g_floatIpMap->floatIpNode[nodeIdx].instCnt);
return CM_FALSE;
}
if (ipIdx >= g_floatIpMap->floatIpNode[nodeIdx].floapIpInst[instIdx].floatIp.dnFloatIpCount) {
return CM_FALSE;
}
return CM_TRUE;
}
static const char *GetBaseIp(uint32 nodeIdx, uint32 instIdx, uint32 ipIdx)
{
if (!CheckFloatIpInput(nodeIdx, instIdx, ipIdx)) {
return "Unknown";
}
return g_floatIpMap->floatIpNode[nodeIdx].floapIpInst[instIdx].floatIp.baseIp[ipIdx];
}
static const char *GetFloatIp(uint32 nodeIdx, uint32 instIdx, uint32 ipIdx)
{
if (!CheckFloatIpInput(nodeIdx, instIdx, ipIdx)) {
return "Unknown";
}
return g_floatIpMap->floatIpNode[nodeIdx].floapIpInst[instIdx].floatIp.dnFloatIp[ipIdx];
}
static const char *GetFloatIpName(uint32 nodeIdx, uint32 instIdx, uint32 ipIdx)
{
if (!CheckFloatIpInput(nodeIdx, instIdx, ipIdx)) {
return "Unknown";
}
return g_floatIpMap->floatIpNode[nodeIdx].floapIpInst[instIdx].floatIp.floatIpName[ipIdx];
}
static void PrintFloatIpContent(const CmFloatIpStatAck *ack, const CtlFloatIpHeadSize *floatIpLen)
{
Instance inst;
errno_t rc;
for (uint32 i = 0; i < ack->count; ++i) {
rc = memset_s(&inst, sizeof(Instance), 0, sizeof(Instance));
securec_check_errno(rc, (void)rc);
rc = FindInstanceByInstId(ack->info[i].instId, &inst);
if (rc != 0) {
continue;
}
for (uint32 j = 0; j < ack->info[i].count; ++j) {
if (ack->info[i].nicNetState[j] != (int32)NETWORK_STATE_UP) {
continue;
}
// node
(void)fprintf(g_logFilePtr, "%-2u ", g_node[inst.baseInfo.nodeIdx].node);
(void)fprintf(g_logFilePtr, "%-*s ", max_node_name_len, g_node[inst.baseInfo.nodeIdx].nodeName);
// instance
(void)fprintf(g_logFilePtr, "%u ", ack->info[i].instId);
(void)fprintf(g_logFilePtr, " ");
// base_ip
(void)fprintf(g_logFilePtr, "%-*s ", (floatIpLen->baseIpText.len - 1),
GetBaseIp(inst.baseInfo.nodeIdx, inst.baseInfo.instIdx, j));
// floatIpName
(void)fprintf(g_logFilePtr, "%-*s ", (floatIpLen->floatIpNameText.len - 1),
GetFloatIpName(inst.baseInfo.nodeIdx, inst.baseInfo.instIdx, j));
// floatIp
(void)fprintf(g_logFilePtr, "%-*s \n", (floatIpLen->floatIpText.len - 1),
GetFloatIp(inst.baseInfo.nodeIdx, inst.baseInfo.instIdx, j));
}
}
}
static void InitCtlFloatIpHeadSize(CtlFloatIpHeadSize *floatIpLen)
{
errno_t rc = memset_s(floatIpLen, sizeof(CtlFloatIpHeadSize), 0, sizeof(CtlFloatIpHeadSize));
securec_check_errno(rc, (void)rc);
// node
CmConststr2Text("node", &(floatIpLen->nodeText));
// instance
CmConststr2Text("instance", &(floatIpLen->instText));
// baseIp
CmConststr2Text("base_ip", &(floatIpLen->baseIpText));
// floatIpName
CmConststr2Text("float_ip_name", &(floatIpLen->floatIpNameText));
// floatIp
CmConststr2Text("float_ip", &(floatIpLen->floatIpText));
}
status_t HandleFloatIpAck(const char *option, char *recvMsg)
{
const CmFloatIpStatAck *ack = (const CmFloatIpStatAck *)recvMsg;
if (!ack->canShow) {
write_runlog(DEBUG1, "cur cluster can't show floatIp.\n");
return CM_SUCCESS;
}
(void)fprintf(g_logFilePtr, "\n[ FloatIp Network State ]\n\n");
if (ack->count == 0) {
return CM_ERROR;
}
CtlFloatIpHeadSize floatIpLen;
InitCtlFloatIpHeadSize(&floatIpLen);
CalcFloatIpHeaderSize(&floatIpLen);
PrintFloatIpHeaderLine(&floatIpLen);
PrintFloatIpContent(ack, &floatIpLen);
return CM_SUCCESS;
}
static int32 InitFloatIpMap()
{
size_t len = sizeof(CtlFloatIpMap) + sizeof(CtlFloatIpNode) * g_node_num;
g_floatIpMap = (CtlFloatIpMap *)malloc(len);
if (g_floatIpMap == NULL) {
write_runlog(DEBUG1, "failed to malloc g_floatIpMap, and len=%zu.\n", len);
return -1;
}
errno_t rc = memset_s(g_floatIpMap, len, 0, len);
securec_check_errno(rc, (void)rc);
g_floatIpMap->nodeCnt = g_node_num;
for (uint32 i = 0; i < g_node_num; ++i) {
g_floatIpMap->floatIpNode[i].nodeIdx = i;
for (uint32 j = 0; j < g_node[i].datanodeCount && j < CM_MAX_DATANODE_PER_NODE; ++j) {
g_floatIpMap->floatIpNode[i].floapIpInst[j].dnIdx = j;
}
}
return 0;
}
static bool8 CtlFindNodeInfoByNodeIdx(uint32 instId, uint32 *nodeIdx, uint32 *dnIdx, const char *str)
{
Instance instance;
errno_t rc = memset_s(&instance, sizeof(Instance), 0, sizeof(Instance));
securec_check_errno(rc, (void)rc);
int32 ret = FindInstanceByInstId(instId, &instance);
if (ret != 0) {
write_runlog(DEBUG1, "[%s] cannot find the instance by instId(%u).\n", str, instId);
return CM_FALSE;
}
*nodeIdx = instance.baseInfo.nodeIdx;
*dnIdx = instance.baseInfo.instIdx;
return CM_TRUE;
}
static DnFloatIp *CtlGetDnFloatIpByNodeInfo(uint32 nodeIdx, uint32 dnIdx)
{
if (nodeIdx >= g_floatIpMap->nodeCnt || dnIdx >= CM_MAX_DATANODE_PER_NODE) {
write_runlog(DEBUG1, "failed to get Dn floatIp, because nodeIdx(%u) beyond the nodeNum(%u), "
"dnIdx(%u) beyond the dnNum(%d).\n", nodeIdx, g_floatIpMap->nodeCnt, dnIdx, CM_MAX_DATANODE_PER_NODE);
return NULL;
}
return &(g_floatIpMap->floatIpNode[nodeIdx].floapIpInst[dnIdx].floatIp);
}
static void CtlIncreDnFloatIpCnt(uint32 nodeIdx)
{
++g_floatIpMap->floatIpNode[nodeIdx].instCnt;
++g_floatIpCnt;
}
static void CtlInitFloatIpFunc()
{
g_ctlParseFuc.findNodeInfo = CtlFindNodeInfoByNodeIdx;
g_ctlParseFuc.getFloatIp = CtlGetDnFloatIpByNodeInfo;
g_ctlParseFuc.increaseCnt = CtlIncreDnFloatIpCnt;
InitParseFloatIpFunc(&g_ctlParseFuc);
}
static int32 CtlParseFloatIp()
{
CtlGetCmJsonConf();
CM_RETURN_INT_IFERR(InitFloatIpMap());
CtlInitFloatIpFunc();
ParseVipConf(DEBUG1);
return 0;
}
static void ReleaseFloatIp()
{
FREE_AND_RESET(g_floatIpMap);
g_floatIpCnt = 0;
}
static int32 SetQueryFloatIpMsg()
{
CmShowStatReq req = { 0 };
req.msgType = (int32)MSG_CTL_CM_FLOAT_IP_REQ;
if (cm_client_send_msg(GetCmsConn(), 'C', (char*)(&req), sizeof(CmShowStatReq)) != 0) {
FINISH_CONNECTION_WITHOUT_EXIT();
write_runlog(ERROR, "ctl send show node disk msg to cms failed.\n");
(void)printf(_("ctl send msg to cms failed.\n"));
return 1;
}
return 0;
}
static int32 QueryCmsFloatIp()
{
CM_RETURN_INT_IFERR(CtlParseFloatIp());
if (g_floatIpCnt == 0) {
return 0;
}
CM_RETURN_INT_IFERR(SetQueryFloatIpMsg());
if (GetExecCmdResult(NULL, (int)MSG_CTL_CM_FLOAT_IP_ACK) != CM_SUCCESS) {
return -1;
}
return 0;
}
static int32 QueryCmsFloatIpMain()
{
int32 ret = QueryCmsFloatIp();
ReleaseFloatIp();
return ret;
}
extern CM_Conn* CmServer_conn;
// cm_ctl rhb print
int DoShowCommand()
{
InitCtlShowMsgFunc();
do_conn_cmserver(false, 0);
if (CmServer_conn == NULL) {
write_runlog(LOG, "show command, can't connect to cmserver.\n");
@ -63,12 +391,19 @@ int DoShowCommand()
}
GetExecCmdResult(NULL, (int)MSG_CTL_CM_NODE_DISK_STATUS_ACK);
if (QueryCmsFloatIpMain() != 0) {
FINISH_CONNECTION_WITHOUT_EXIT();
write_runlog(ERROR, "Failed to show floatIp.\n");
return -1;
}
FINISH_CONNECTION_WITHOUT_EXIT();
return 0;
}
void HandleRhbAck(CmRhbStatAck *ack)
status_t HandleRhbAck(const char *option, char *recvMsg)
{
CmRhbStatAck *ack = (CmRhbStatAck *)recvMsg;
(void)printf("\n[ Network Connect State ]\n\n");
(void)printf("Network timeout: %us\n", ack->timeout);
@ -82,9 +417,10 @@ void HandleRhbAck(CmRhbStatAck *ack)
(void)printf("Network stat('Y' means connected, otherwise 'N'):\n");
char *rs = GetRhbSimple((time_t *)ack->hbs, MAX_RHB_NUM, ack->hwl, ack->baseTime, ack->timeout);
CM_RETURN_IF_NULL(rs);
CM_RETERR_IF_NULL(rs);
(void)printf("%s\n", rs);
free(rs);
FREE_AND_RESET(rs);
return CM_SUCCESS;
}
// | Y | Y | Y | Y | Y |
@ -111,8 +447,9 @@ static char *GetNodeDiskSimple(time_t *ndHbs, uint32 hwl, time_t baseTime, uint3
return buf;
}
void HandleNodeDiskAck(CmNodeDiskStatAck *ack)
status_t HandleNodeDiskAck(const char *option, char *recvMsg)
{
CmNodeDiskStatAck *ack = (CmNodeDiskStatAck *)recvMsg;
(void)printf("\n[ Node Disk HB State ]\n\n");
(void)printf("Node disk hb timeout: %us\n", ack->timeout);
@ -126,6 +463,8 @@ void HandleNodeDiskAck(CmNodeDiskStatAck *ack)
(void)printf("Node disk hb stat('Y' means connected, otherwise 'N'):\n");
char *rs = GetNodeDiskSimple(ack->nodeDiskStats, ack->hwl, ack->baseTime, ack->timeout);
CM_RETERR_IF_NULL(rs);
(void)printf("%s\n", rs);
free(rs);
FREE_AND_RESET(rs);
return CM_SUCCESS;
}

View File

@ -478,7 +478,7 @@ static void PrintMaxNodeCluster(const MaxNodeCluster *maxNodeCluster, const char
for (int32 i = 0; i < maxNodeCluster->nodeCluster.clusterNum; ++i) {
StrcatNextNodeStr(clusterStr, MAX_PATH_LEN, maxNodeCluster->nodeCluster.cluster[i]);
}
write_runlog(logLevel, "%s the max node cluster: %s.\n", str, clusterStr);
write_runlog(LOG, "%s the max node cluster: %s.\n", str, clusterStr);
}
static void GetClusterKeyInDdb(char *key, uint32 keyLen)

View File

@ -1549,7 +1549,7 @@ static bool IsInstanceNoCmd(const DnArbCtx *ctx, const char *str)
static void SendSwitchoverMessage(const DnArbCtx *ctx, int32 memIdx, const char *str)
{
if (IsMaintenanceModeDisableOperation(CMS_SWITCHOVER_DN, ctx->maintaMode)) {
if (IsMaintenanceModeDisableOperation(CMS_SWITCHOVER_DN, ctx->maintaMode) || backup_open != CLUSTER_PRIMARY) {
write_runlog(LOG, "%s, %u Maintaining cluster: cm server cannot switchover dn.\n", str, ctx->instId);
return;
}

View File

@ -310,16 +310,6 @@ void get_paramter_coordinator_heartbeat_timeout()
#endif
bool CheckBoolConfigParam(const char* value)
{
if (strcasecmp(value, "on") == 0 || strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0 ||
strcasecmp(value, "1") == 0 || strcasecmp(value, "off") == 0 || strcasecmp(value, "no") == 0 ||
strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
return true;
}
return false;
}
void GetDdbTypeParam(void)
{
int32 ddbType = get_int_value_from_config(configDir, "ddb_type", 0);

View File

@ -285,6 +285,7 @@ void UpdateIsworkList(uint32 cmInstId, int newIswork)
++g_resStatus[i].status.version;
ProcessReportResChangedMsg(false, g_resStatus[i].status);
SaveOneResStatusToDdb(&g_resStatus[i].status);
PrintCusInfoResList(&g_resStatus[i].status, __FUNCTION__);
return;
}
}
@ -530,27 +531,13 @@ void GetOneResStatusFromDdb(OneResStatList *resStat)
cJSON_Delete(root);
}
static inline void PrintNewResStatus(const OneResStatList *resStatus)
{
write_runlog(LOG, "res(%s), version=%llu:\n", resStatus->resName, resStatus->version);
for (uint32 j = 0; j < resStatus->instanceCount; ++j) {
write_runlog(LOG, "nodeId=%u, cmInstId=%u, resInstId=%u, isWork=%u, status=%u;\n",
resStatus->resStat[j].nodeId,
resStatus->resStat[j].cmInstanceId,
resStatus->resStat[j].resInstanceId,
resStatus->resStat[j].isWorkMember,
resStatus->resStat[j].status);
}
}
void GetAllResStatusFromDdb()
{
for (uint32 i = 0; i < CusResCount(); ++i) {
(void)pthread_rwlock_wrlock(&g_resStatus[i].rwlock);
GetOneResStatusFromDdb(&g_resStatus[i].status);
write_runlog(LOG, "show res status get from ddb.\n");
PrintNewResStatus(&g_resStatus[i].status);
(void)pthread_rwlock_unlock(&g_resStatus[i].rwlock);
PrintCusInfoResList(&g_resStatus[i].status, __FUNCTION__);
}
}

View File

@ -26,6 +26,7 @@
#include <sys/prctl.h>
#include <sys/epoll.h>
#include "cm/cm_elog.h"
#include "cm_debug.h"
#include "cms_common.h"
#include "cms_global_params.h"
#include "cms_conn.h"

View File

@ -259,10 +259,6 @@ status_t GetAllKVFromDDb(char *key, uint32 keyLen, DrvKeyValue *keyValue, uint32
*ddbResult = SUCCESS_GET_VALUE;
}
}
if (getStatus == CM_SUCCESS) {
logLevel = (g_HA_status->local_role == CM_SERVER_PRIMARY) ? LOG : DEBUG1;
PrintKeyValueMsg(key, keyValue, len, logLevel);
}
RestDdbConn(ddbConn, getStatus, ddbResult);
return getStatus;
}

View File

@ -71,6 +71,9 @@ static bool g_allHealth = true;
bool CheckReadOnlyStatus(uint32 instanceId)
{
if (!IsBoolCmParamTrue(g_enableSetReadOnly)) {
return false;
}
write_runlog(DEBUG1, "[%s] instanceId: %u\n", __FUNCTION__, instanceId);
for (uint32 i = 0; i < g_node_num; i++) {
if (g_dynamicNodeReadOnlyInfo[i].coordinateNode.readOnly &&

View File

@ -158,6 +158,8 @@ static void datanode_status_reset(uint32 group_index, int member_index, bool isN
.instance_status.data_node_member[member_index]
.local_status.buildReason = INSTANCE_HA_DATANODE_BUILD_REASON_UNKNOWN;
g_instance_group_report_status_ptr[group_index].instance_status.data_node_member[member_index].floatIp.count = 0;
rc = memset_s(&g_instance_group_report_status_ptr[group_index]
.instance_status.data_node_member[member_index] .sender_status[0].sender_sent_location,
8 * sizeof(XLogRecPtr), 0, 8 * sizeof(XLogRecPtr));

View File

@ -22,9 +22,9 @@
* -------------------------------------------------------------------------
*/
#include "elog.h"
#include "cm_c.h"
#include "cm_util.h"
#include "cm_misc_base.h"
#include "cm_msg_buf_pool.h"
#include "cms_msg_que.h"
@ -40,7 +40,7 @@ void InitMsgQue(PriMsgQues &que)
}
(void)pthread_mutex_init(&que.msgLock, NULL);
(void)pthread_cond_init(&que.msgCond, NULL);
InitPthreadCondMonotonic(&que.msgCond);
}
void setWakeSenderFunc(wakeSenderFuncType func)
@ -133,7 +133,7 @@ const MsgRecvInfo *getRecvMsg(PriMsgQues *priQue, MsgSourceType src, uint32 wait
const MsgRecvInfo* msg = getRecvMsgInner(priQue, src, threadInfo);
if (msg == NULL && waitTime > 0) {
(void)clock_gettime(CLOCK_REALTIME, &tv);
(void)clock_gettime(CLOCK_MONOTONIC, &tv);
tv.tv_sec = tv.tv_sec + (long long)waitTime;
(void)pthread_mutex_lock(&priQue->msgLock);
(void)pthread_cond_timedwait(&priQue->msgCond, &priQue->msgLock, &tv);

View File

@ -1573,6 +1573,15 @@ void ProcessNodeDiskStatReq(MsgRecvInfo *recvMsgInfo, const CmShowStatReq *req)
(void)RespondMsg(recvMsgInfo, 'S', (char *)(&ack), sizeof(CmNodeDiskStatAck));
}
void ProcessFloatIpReq(MsgRecvInfo *recvMsgInfo, const CmShowStatReq *req)
{
write_runlog(DEBUG1, "[ProcessFloatIpReq] receive float ip query msg.\n");
char sendMsg[DDB_MAX_KEY_VALUE_LEN] = {0};
size_t msgLen = sizeof(CmFloatIpStatAck);
GetFloatIpSet((CmFloatIpStatAck*)sendMsg, DDB_MAX_KEY_VALUE_LEN, &msgLen);
(void)RespondMsg(recvMsgInfo, 'S', sendMsg, msgLen);
}
static void MsgShowStatus(MsgRecvInfo* recvMsgInfo, int msgType, CmdMsgProc *msgProc)
{
CmShowStatReq *req = NULL;
@ -1583,12 +1592,24 @@ static void MsgShowStatus(MsgRecvInfo* recvMsgInfo, int msgType, CmdMsgProc *msg
case MSG_CTL_CM_NODE_DISK_STATUS_REQ:
PROCESS_MSG_BY_TYPE(CmShowStatReq, req, ProcessNodeDiskStatReq);
break;
case MSG_CTL_CM_FLOAT_IP_REQ:
PROCESS_MSG_BY_TYPE(CmShowStatReq, req, ProcessFloatIpReq);
break;
default:
write_runlog(ERROR, "[MsgShowStatus] unknown request(%d)\n", msgType);
break;
}
}
static void MsgGetFloatIpInfo(MsgRecvInfo *recvMsgInfo, int msgType, CmdMsgProc *msgProc)
{
if (!IsNeedCheckFloatIp() || (backup_open != CLUSTER_PRIMARY)) {
return;
}
CmaDnFloatIpInfo *floatIpInfo;
PROCESS_MSG_BY_TYPE(CmaDnFloatIpInfo, floatIpInfo, ProcessDnFloatIpMsg);
}
static void MsgResIsreg(MsgRecvInfo *recvMsgInfo, int msgType, CmdMsgProc *msgProc)
{
CmaToCmsIsregMsg *isregMsg;
@ -1632,6 +1653,7 @@ static void InitCmCtlCmdProc()
g_cmdProc[MSG_CTL_CM_QUERY_RES_INST] = MsgCmQueryOneResInst;
g_cmdProc[MSG_CTL_CM_RHB_STATUS_REQ] = MsgShowStatus;
g_cmdProc[MSG_CTL_CM_NODE_DISK_STATUS_REQ] = MsgShowStatus;
g_cmdProc[MSG_CTL_CM_FLOAT_IP_REQ] = MsgShowStatus;
}
static void InitCmAgentCmdProc()
@ -1653,7 +1675,7 @@ static void InitCmAgentCmdProc()
g_cmdProc[MSG_GET_SHARED_STORAGE_INFO] = MsgGetSharedStorageInfo;
g_cmdProc[MSG_CM_RES_LOCK] = MsgCmResLock;
g_cmdProc[MSG_CM_RHB] = MsgCmRhb;
g_cmdProc[MSG_AGENT_CM_FLOAT_IP] = NULL;
g_cmdProc[MSG_AGENT_CM_FLOAT_IP] = MsgGetFloatIpInfo;
g_cmdProc[MSG_AGENT_CM_ISREG_REPORT] = MsgResIsreg;
}

View File

@ -771,3 +771,145 @@ void ProcessDnLocalPeerMsg(MsgRecvInfo* recvMsgInfo, AgentCmDnLocalPeer *dnLpInf
&(g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member[memIdx].dnLp.peerInst),
groupIdx, &(dnLpInfo->dnLpInfo));
}
static status_t FindAvaliableFloatIpPrimary(uint32 groupIdx, int32 *memIdx)
{
cm_instance_datanode_report_status *dnReport =
g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member;
cm_local_replconninfo *dnLocal;
uint32 primaryDnCnt = 0;
for (int32 i = 0; i < g_instance_role_group_ptr[groupIdx].count; ++i) {
dnLocal = &(dnReport[i].local_status);
if (dnLocal->local_role == INSTANCE_ROLE_PRIMARY && dnLocal->db_state == INSTANCE_HA_STATE_NORMAL) {
*memIdx = i;
++primaryDnCnt;
}
}
if (primaryDnCnt != 1) {
return CM_ERROR;
}
return CM_SUCCESS;
}
static void ArbitrateFloatIpOper(
MsgRecvInfo *recvMsgInfo, const CmaDnFloatIpInfo *floatIp, NetworkOper oper, NetworkState state)
{
CmsDnFloatIpAck ack = {{0}};
errno_t rc = memcpy_s(&(ack.baseInfo), sizeof(BaseInstInfo), &(floatIp->baseInfo), sizeof(BaseInstInfo));
securec_check_errno(rc, (void)rc);
ack.baseInfo.msgType = (int32)MSG_CM_AGENT_FLOAT_IP_ACK;
ack.oper = (int32)oper;
const DnFloatIpInfo *dnFloatIp = &(floatIp->info);
for (uint32 i = 0; i < dnFloatIp->count; ++i) {
if (dnFloatIp->dnNetState[i] != (int32)state || dnFloatIp->nicNetState[i] != (int32)state) {
(void)RespondMsg(recvMsgInfo, 'S', (const char *)(&ack), sizeof(CmsDnFloatIpAck));
return;
}
}
}
static void ArbitateFloatIp(MsgRecvInfo *recvMsgInfo, const CmaDnFloatIpInfo *floatIp, uint32 groupIdx, int32 memIdx)
{
cm_instance_datanode_report_status *dnReport =
&(g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member[memIdx]);
(void)pthread_rwlock_wrlock(&(g_instance_group_report_status_ptr[groupIdx].lk_lock));
errno_t rc = memcpy_s(&(dnReport->floatIp), sizeof(DnFloatIpInfo), &(floatIp->info), sizeof(DnFloatIpInfo));
(void)pthread_rwlock_unlock(&(g_instance_group_report_status_ptr[groupIdx].lk_lock));
securec_check_errno(rc, (void)rc);
int32 avaliMemIdx = -1;
status_t st = FindAvaliableFloatIpPrimary(groupIdx, &avaliMemIdx);
if (st != CM_SUCCESS) {
return;
}
if (avaliMemIdx == memIdx) {
ArbitrateFloatIpOper(recvMsgInfo, floatIp, NETWORK_OPER_UP, NETWORK_STATE_UP);
} else {
ArbitrateFloatIpOper(recvMsgInfo, floatIp, NETWORK_OPER_DOWN, NETWORK_STATE_DOWN);
}
}
void ProcessDnFloatIpMsg(MsgRecvInfo *recvMsgInfo, CmaDnFloatIpInfo *floatIp)
{
const char *str = "[ProcessDnLocalPeerMsg]";
const BaseInstInfo *baseInst = &(floatIp->baseInfo);
if (baseInst->instType != INSTANCE_TYPE_DATANODE) {
write_runlog(ERROR, "%s cms get instance(%u) is not dn, this type is %d.\n",
str, baseInst->instId, baseInst->instType);
return;
}
uint32 groupIdx = 0;
int32 memIdx = 0;
uint32 node = baseInst->node;
uint32 instId = baseInst->instId;
// get groupIndex, memberIndex
int32 ret = find_node_in_dynamic_configure(node, instId, &groupIdx, &memIdx);
if (ret != 0) {
write_runlog(LOG, "[%s] can't find the instance(node=%u instanceid =%u)\n", __FUNCTION__, node, instId);
return;
}
write_runlog(DEBUG1, "cms receive dnFloatIpMsg, and group[%u: %d], node[%u], instId[%u].\n",
groupIdx, memIdx, node, instId);
ArbitateFloatIp(recvMsgInfo, floatIp, groupIdx, memIdx);
}
static void InitFloatIpAck(CmFloatIpStatAck *ack)
{
ack->msgType = (int32)MSG_CTL_CM_FLOAT_IP_ACK;
ack->count = 0;
ack->canShow = CM_TRUE;
}
static bool8 IsCurInstanceExistingFloatIp(uint32 groupIdx, int32 memIdx)
{
DnFloatIpInfo *dnFloatIp =
&(g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member[memIdx].floatIp);
for (uint32 i = 0; i < dnFloatIp->count; ++i) {
if (dnFloatIp->nicNetState[i] == (int32)NETWORK_STATE_UP) {
return CM_TRUE;
}
}
return CM_FALSE;
}
static void GetFloatIpInfo(CmFloatIpStatAck *ack, size_t *curMsgLen, uint32 groupIdx, int32 memIdx)
{
uint32 point = ack->count;
CmFloatIpStatInfo *info = &(ack->info[point]);
info->nodeId = g_instance_role_group_ptr[groupIdx].instanceMember[memIdx].node;
info->instId = g_instance_role_group_ptr[groupIdx].instanceMember[memIdx].instanceId;
if (!IsCurInstanceExistingFloatIp(groupIdx, memIdx)) {
return;
}
DnFloatIpInfo *dnFloatIp =
&(g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member[memIdx].floatIp);
(void)pthread_rwlock_rdlock(&(g_instance_group_report_status_ptr[groupIdx].lk_lock));
uint32 i = 0;
for (; i < dnFloatIp->count && i < MAX_FLOAT_IP_COUNT; ++i) {
info->nicNetState[i] = dnFloatIp->nicNetState[i];
}
info->count = i;
(void)pthread_rwlock_unlock(&(g_instance_group_report_status_ptr[groupIdx].lk_lock));
++ack->count;
*curMsgLen += sizeof(CmFloatIpStatInfo);
}
void GetFloatIpSet(CmFloatIpStatAck *ack, size_t maxMsgLen, size_t *curMsgLen)
{
InitFloatIpAck(ack);
if (!IsNeedCheckFloatIp() || (backup_open != CLUSTER_PRIMARY)) {
ack->canShow = CM_FALSE;
return;
}
for (uint32 i = 0; i < g_dynamic_header->relationCount; ++i) {
if (g_instance_role_group_ptr[i].instanceMember[0].instanceType != INSTANCE_TYPE_DATANODE) {
continue;
}
for (int32 j = 0; j < g_instance_role_group_ptr[i].count; ++j) {
if (*curMsgLen + sizeof(CmFloatIpStatInfo) > maxMsgLen) {
write_runlog(LOG, "tmpMsgLen is %zu, and maxMsgLen is %zu.\n", *curMsgLen, maxMsgLen);
return;
}
GetFloatIpInfo(ack, curMsgLen, i, j);
}
}
}

View File

@ -2314,8 +2314,10 @@ void process_ctl_to_cm_get_datanode_relation_msg(
for (int i = 0; i < CM_PRIMARY_STANDBY_MAX_NUM; i++) {
ack.instanceMember[i] =
g_instance_role_group_ptr[group_index].instanceMember[i];
ack.data_node_member[i] =
g_instance_group_report_status_ptr[group_index].instance_status.data_node_member[i];
errno_t rc = memcpy_s(&(ack.data_node_member[i]), sizeof(CmDnReportStatusMsg),
&(g_instance_group_report_status_ptr[group_index].instance_status.data_node_member[i]),
sizeof(CmDnReportStatusMsg));
securec_check_errno(rc, (void)rc);
ack.gtm_member[i] =
g_instance_group_report_status_ptr[group_index].instance_status.gtm_member[i];
}

View File

@ -42,16 +42,6 @@ void ProcessReportResChangedMsg(bool notifyClient, const OneResStatList &status)
errno_t rc = memcpy_s(&sendMsg.resList, sizeof(OneResStatList), &status, sizeof(OneResStatList));
securec_check_errno(rc, (void)rc);
write_runlog(LOG, "[CLIENT] res(%s), version=%llu, status:\n", status.resName, status.version);
for (uint32 i = 0; i < status.instanceCount; ++i) {
write_runlog(LOG, "[CLIENT] nodeId=%u, cmInstId=%u, resInstId=%u, isWork=%u, status=%u;\n",
status.resStat[i].nodeId,
status.resStat[i].cmInstanceId,
status.resStat[i].resInstanceId,
status.resStat[i].isWorkMember,
status.resStat[i].status);
}
(void)BroadcastMsg('S', (char *)(&sendMsg), sizeof(CmsReportResStatList));
}
@ -169,6 +159,7 @@ static bool IsCusResStatValid(const OneNodeResourceStatus *nodeStat)
for (uint32 i = 0; i < nodeStat->count; ++i) {
if (nodeStat->status[i].status != CUS_RES_CHECK_STAT_ONLINE &&
nodeStat->status[i].status != CUS_RES_CHECK_STAT_OFFLINE &&
nodeStat->status[i].status != CUS_RES_CHECK_STAT_ABNORMAL &&
nodeStat->status[i].status != CUS_RES_CHECK_STAT_TIMEOUT) {
return false;
}
@ -270,6 +261,9 @@ static uint32 GetResInstStat(uint32 recvStat)
if (recvStat == CUS_RES_CHECK_STAT_OFFLINE) {
return (uint32)CM_RES_STAT_OFFLINE;
}
if (recvStat == CUS_RES_CHECK_STAT_ABNORMAL) {
return (uint32)CM_RES_STAT_ONLINE;
}
return (uint32)CM_RES_STAT_UNKNOWN;
}
@ -302,6 +296,7 @@ static void ProcessOneResInstStatReport(CmResourceStatus *stat)
(void)pthread_rwlock_rdlock(&(resStat->rwlock));
SaveOneResStatusToDdb(&resStat->status);
(void)pthread_rwlock_unlock(&(resStat->rwlock));
PrintCusInfoResList(&resStat->status, __FUNCTION__);
write_runlog(LOG, "[CLIENT] [%u:%u] res(%s) changed\n", stat->nodeId, stat->cmInstanceId, stat->resName);
}
}
@ -431,6 +426,7 @@ void ReleaseResLockOwner(const char *resName, uint32 instId)
}
return;
}
PrintKeyValueMsg(key, kvs, kvCount, DEBUG5);
for (uint32 i = 0; i < kvCount; ++i) {
if (kvs[i].key[0] == '\0' || kvs[i].value[0] == '\0') {

View File

@ -24,6 +24,8 @@
#ifndef CMA_LIBPQ_API_H
#define CMA_LIBPQ_API_H
#include <assert.h>
typedef void cltPqConn_t;
typedef void cltPqResult_t;

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2023 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.
* -------------------------------------------------------------------------
*
* cma_libpq_com.h
*
* IDENTIFICATION
* include/cm/cm_agent/clients/libpq/cma_libpq_com.h
*
* -------------------------------------------------------------------------
*/
#ifndef CMA_LIBPQ_COM_H
#define CMA_LIBPQ_COM_H
#include "cma_libpq_api.h"
typedef void *CltResultSet;
typedef struct SqlCondT {
const char *str;
unsigned int instId;
} SqlCond;
typedef int (*ResultSetHandle)(CltResultSet set, const cltPqResult_t *nodeResult, const char *sqlCommand,
const SqlCond *sqlCond);
int ExecDmlSqlCmd(ResultSetHandle handle, CltResultSet set, cltPqConn_t **conn, const char *sqlCommand,
const SqlCond *sqlCond);
#endif

View File

@ -31,7 +31,7 @@ void StartDatanodeCheck(void);
int CheckDnStausPhonyDead(int dnId, int agentCheckTimeInterval);
int DatanodeStatusCheck(DnStatus *dnStatus, uint32 dataNodeIndex);
int DatanodeStatusCheck(DnStatus *dnStatus, uint32 dataNodeIndex, int32 dnProcess);
int CheckDatanodeStatus(const char *dataDir, int *role);
int ProcessUnlockCmd(const cm_to_agent_unlock *unlockMsg);
@ -42,4 +42,6 @@ void *DNSyncCheckMain(void *arg);
void ProcessStreamingStandbyClusterBuildCommand(
int instanceType, const char* dataDir, const cm_to_agent_build *buildMsg);
void* DNBackupStatusCheckMain(void *arg);
void DnCheckFloatIp(DnStatus *dnStatus, uint32 dnIdx, bool8 isRunning);
uint32 DelFloatIpInDatanode(uint32 dnIdx);
#endif // CM_CMA_CLIENT_ADPT_H

View File

@ -43,6 +43,10 @@ typedef enum {
CM_RES_CORPSE = 3,
} CM_ResStatus;
const int ERROR_EXECUTE_CMD = -2;
const int FAILED_EXECUTE_CMD = -1;
const int SUCCESS_EXECUTE_CMD = 0;
void save_thread_id(pthread_t thrId);
void set_thread_state(pthread_t thrId);
void immediate_stop_one_instance(const char* instance_data_path, InstanceTypes instance_type);
@ -73,7 +77,7 @@ int search_HA_node(uint32 localPort, uint32 LocalHAListenCount, char LocalHAIP[]
int agentCheckPort(uint32 port);
uint32 CheckDiskForLogPath(void);
uint32 GetDiskUsageForPath(const char *pathName);
int ExecuteSystemCmd(const char *cmd);
int ExecuteSystemCmd(const char *cmd, int32 logLevel = ERROR, int32 *errCode = NULL);
void CheckDnNicDown(uint32 index);
void CheckDnDiskDamage(uint32 index);
bool IsDirectoryDestoryed(const char *path);

View File

@ -45,6 +45,7 @@ uint32 GetLibcommPort(const char* file_path, uint32 base_port, int port_type);
extern bool UpdateLibcommConfig();
int stop_instance_check(void);
int killInstanceByPid(const char *processName, const char *cmdLine);
void DelAndDownFloatIpInDn(uint32 index);
#ifdef ENABLE_UT
extern void StopOneZengine(uint32 index);

View File

@ -27,7 +27,6 @@
#include "cm_misc.h"
int SystemExecute(const char *scriptPath, const char *oper, uint32 timeout);
status_t StartOneResInst(const CmResConfList *conf);
void StopOneResInst(const CmResConfList *conf);
void OneResInstShutdown(const CmResConfList *oneResConf);

View File

@ -47,6 +47,7 @@ void PushMsgToCmsSendQue(const char *msgPtr, uint32 msgLen, const char *msgInfo)
void PushMsgToCmsRecvQue(const char *msgPtr, uint32 msgLen);
void PushMsgToClientSendQue(const char *msgPtr, uint32 msgLen, uint32 conId);
void PushMsgToClientRecvQue(const char *msgPtr, uint32 msgLen, uint32 conId);
void PushMsgToAllClientSendQue(const char *msgPtr, uint32 msgLen);
void CleanCmsMsgQueue();
void CleanClientMsgQueue(uint32 conId);

View File

@ -24,7 +24,11 @@
#ifndef CMA_NETWORK_CHECK_H
#define CMA_NETWORK_CHECK_H
#include "cm_defs.h"
#include "common/config/cm_config.h"
#include "cm_msg_common.h"
#include "cm_json_parse_floatIp.h"
typedef enum CmaInstTypeE {
CM_INSTANCE_TYPE_CMA = 0, // it cannot smaller than 0
@ -42,6 +46,12 @@ typedef enum NetworkTypeE {
NETWORK_TYPE_CEIL // it must be end
} NetworkType;
typedef struct DnFloatIpOperMapT {
uint32 count;
NetworkOper oper[CM_MAX_DATANODE_PER_NODE];
DnFloatIp floatIp[CM_MAX_DATANODE_PER_NODE];
} DnFloatIpMapOper;
bool GetNicStatus(unsigned int instId, CmaInstType instType, NetworkType type = NETWORK_TYPE_LISTEN);
void SetNicOper(uint32 instId, CmaInstType instType, NetworkType type, NetworkOper oper);
void GetFloatIpNicStatus(uint32 instId, CmaInstType instType, NetworkState *state, uint32 count);
@ -50,6 +60,10 @@ status_t CreateNetworkResource();
NetworkState GetNetworkStateByOper(NetworkOper oper);
NetworkOper GetNetworkOperByState(NetworkState state);
NetworkOper ChangeInt2NetworkOper(int32 oper);
void SetFloatIpOper(uint32 dnIdx, NetworkOper oper, const char *str);
NetworkOper GetFloatIpOper(uint32 dnIdx);
DnFloatIp *GetDnFloatIpByDnIdx(uint32 dnIdx);
const char *GetOperMapString(NetworkOper oper);
bool8 CheckNetworkStatusByIps(const char (*ips)[CM_IP_LENGTH], uint32 cnt);
#endif

View File

@ -29,5 +29,6 @@ void ProcessResStatusChanged(const CmsReportResStatList *msg);
void ProcessResLockAckFromCms(const CmsReportLockResult *recvMsg);
void ProcessResRegFromCms(const CmsNotifyAgentRegMsg *recvMsg);
void ProcessIsregCheckListChanged(const CmsFlushIsregCheckList *recvMsg);
void NotifyClientConnectClose();
#endif // CMA_PROCESS_MESSAGES_CLIENT_H

View File

@ -30,6 +30,9 @@
#include "cm/cm_defs.h"
#include "cm_ddb_adapter.h"
#include "cm_cipher.h"
#include "ctl_global_params.h"
#include "cm_json_config.h"
#include "ctl_res.h"
#define DEFAULT_WAIT 60
#define DYNAMIC_PRIMARY 0
@ -200,48 +203,6 @@ typedef struct DcfOptionSt {
int priority;
} DcfOption;
typedef enum ResOptModeEn {
RES_CONF_UNKNOWN = 0,
RES_ADD_CONF = 1,
RES_EDIT_CONF = 2,
RES_DEL_CONF = 3,
RES_CHECK_CONF = 4,
} ResOptMode;
typedef enum ResEditModeEn {
RES_EDIT_UNKNOWN = 0,
RES_ADD_INST_CONF = 1,
RES_DEL_INST_CONF = 2,
RES_EDIT_RES_CONF = 3,
RES_EDIT_CEIL, // it must be end
} ResEditMode;
typedef enum ResTypeE {
RES_TYPE_UNKOWN,
RES_TYPE_APP,
RES_TYPE_DN,
RES_TYPE_CEIL, // it must be end
} ResType;
typedef struct ResOptionSt {
ResOptMode mode;
ResType type;
char *resName;
char *resAttr;
ResEditMode editMode;
char *addInstStr;
char *delInstStr;
} ResOption;
typedef status_t (*CheckResInfo)(cJSON *resItem, const char *resName);
typedef struct ResTypeMapT {
ResType type;
const char *typeStr;
const char *value;
CheckResInfo check;
} ResTypeMap;
typedef struct CtlOptionSt {
CommonOption comm;
GucOption guc;
@ -255,7 +216,6 @@ typedef struct CtlOptionSt {
extern bool g_isRestop;
extern DdbConn *g_sess;
extern TlsAuthPath g_tlsPath;
extern ResTypeMap g_resTypeMap[];
status_t do_start(void);
int DoStop(void);
@ -284,13 +244,8 @@ void DoDccCmd(int argc, char **argv);
int DoGuc(CtlOption *ctx);
int DoEncrypt(const CtlOption *ctx);
int DoSwitch(const CtlOption *ctx);
int DoResCommand(const CtlOption *ctx);
int DoShowCommand();
void GetExecCmdResult(const char *option, int expCmd);
void HandleRhbAck(CmRhbStatAck *ack);
void HandleNodeDiskAck(CmNodeDiskStatAck *ack);
void stop_etcd_cluster(void);
int stop_check_node(uint32 node_id_check);
void stop_etcd_node(uint32 nodeid);
@ -302,13 +257,13 @@ uint32 get_node_index(uint32 node_id);
bool isMajority(const char* cm_arbitration_mode);
bool isMinority(const char* cm_arbitration_mode);
int FindInstanceIdAndType(uint32 node, const char* dataPath, uint32* instanceId, int* instanceType);
int ssh_exec(const staticNodeConfig* node, const char* cmd);
int ssh_exec(const staticNodeConfig* node, const char* cmd, int32 logLevel = ERROR);
int SshExec(const staticNodeConfig* node, const char* cmd);
int RunEtcdCmd(const char* command, uint32 nodeIndex);
void do_conn_cmserver(bool queryCmserver, uint32 nodeIndex, bool queryEtcd = false, CM_Conn **curConn = NULL);
int cm_client_flush_msg(CM_Conn* conn);
int cm_client_send_msg(CM_Conn* conn, char msgtype, const char* s, size_t len);
char* recv_cm_server_cmd(CM_Conn* conn);
void do_conn_cmserver(bool queryCmserver, uint32 nodeIndex, bool queryEtcd = false, struct cm_conn **curConn = NULL);
int cm_client_flush_msg(struct cm_conn* conn);
int cm_client_send_msg(struct cm_conn* conn, char msgtype, const char* s, size_t len);
char* recv_cm_server_cmd(struct cm_conn* conn);
void init_hosts();
bool is_node_stopping(uint32 checkNode, uint32 currentNode, const char *manualStartFile, const char *resultFile,
const char *mppEnvSeperateFile);
@ -348,8 +303,8 @@ status_t KillAllCms(bool isNeedKillPrimaryCms);
uint32 *GetCmsNodeIndex(void);
status_t CheckGucOptionValidate(const GucOption &gucCtx);
void GetUpgradeVersionFromCmaConfig();
bool SetOfflineNode(uint32 nodeIndex, CM_Conn *con);
void ReleaseConn(CM_Conn *con);
bool SetOfflineNode(uint32 nodeIndex, struct cm_conn *con);
void ReleaseConn(struct cm_conn *con);
bool IsCmSharedStorageMode();
void CtlGetCmJsonConf();
int DoRhbPrint();

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2022 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_distribute.h
*
*
* IDENTIFICATION
* include/cm/cm_ctl/ctl_common.h
*
* -------------------------------------------------------------------------
*/
#ifndef CTL_GLOBAL_PARAMS_H
#define CTL_GLOBAL_PARAMS_H
#include <stdio.h>
struct cm_conn;
extern struct cm_conn *CmServer_conn;
extern struct cm_conn *CmServer_conn1;
extern struct cm_conn *CmServer_conn2;
extern FILE *g_logFilePtr;
struct cm_conn *GetCmsConn();
#endif

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 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.h
*
* IDENTIFICATION
* include/cm/cm_ctl/ctl_misc.h
*
* -------------------------------------------------------------------------
*/
#ifndef CTL_MISC_H
#define CTL_MISC_H
#include "c.h"
#include "cm_misc.h"
int FindInstanceByInstId(uint32 instId, Instance *inst);
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2022 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_process_message.h
*
*
* IDENTIFICATION
* include/cm/cm_ctl/ctl_process_message.h
*
* -------------------------------------------------------------------------
*/
#ifndef CTL_PROCESS_MESSAGE_H
#define CTL_PROCESS_MESSAGE_H
#include "c.h"
#include "cm_defs.h"
#include "ctl_global_params.h"
const int32 INVALID_EXPECT_CMD = -1;
typedef status_t (*CtlDealCmdFunc)(const char *option, char *msg);
struct cm_conn;
status_t GetExecCmdResult(const char *option, int32 expCmd = INVALID_EXPECT_CMD, struct cm_conn *conn = GetCmsConn());
void InitDdbCmdMsgFunc();
void InitCtlShowMsgFunc();
#endif

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2023 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_res.h
*
*
* IDENTIFICATION
* include/cm/cm_ctl/ctl_res.h
*
* -------------------------------------------------------------------------
*/
#ifndef CTL_RES_H
#define CTL_RES_H
#include "c.h"
#include "cm_defs.h"
#include "cjson/cJSON.h"
#include "cm_elog.h"
typedef enum ResTypeE {
RES_TYPE_INIT = 0,
RES_TYPE_UNKNOWN,
RES_TYPE_APP,
RES_TYPE_DN,
RES_TYPE_VIP,
RES_TYPE_CEIL, // it must be end
} ResType;
typedef enum ResOpModeE {
RES_OP_INIT = 0,
RES_OP_UNKNOWN,
RES_OP_ADD,
RES_OP_DEL,
RES_OP_EDIT,
RES_OP_CHECK,
RES_OP_LIST,
RES_OP_CEIL // it must be end
} ResOpMode;
typedef struct ResInstOpT {
ResOpMode mode;
char reserved[4]; // for alignment
char *instName;
char *instAttr;
} ResInstOp;
typedef struct ResOptionT {
ResOpMode mode;
char reserved[4]; // for alignment
char *resName;
char *resAttr;
ResInstOp inst;
} ResOption;
typedef struct ResTypeStrT {
ResType type;
const char *str;
} ResTypeStr;
typedef enum ResLevelE {
RES_LEVEL_INIT = 0,
RES_LEVEL_UNKNOWN,
RES_LEVEL_RES,
RES_LEVEL_INST,
RES_LEVEL_CEIL
} ResLevel;
typedef enum ResKvTypeE {
RES_KV_TYPE_INIT = 0,
RES_KV_TYPE_UNKNOWN,
RES_KV_TYPE_INTEGER,
RES_KV_TYPE_STRING,
RES_KV_TYPE_ARRAY,
RES_KV_TYPE_OBJECT,
RES_KV_TYPE_CEIL
} ResKvType;
typedef struct KvRestrictT {
ResKvType type;
const char *key;
} KvRestrict;
typedef struct ResInstInfoT {
int32 instId;
int32 nodeId;
} ResInstInfo;
// res
const char KEY_VALUE_SPLIT_CHAR = '=';
const char KEY_VALUE_SPLIT_ARRAY[] = {KEY_VALUE_SPLIT_CHAR, '\0'};
const char *const RES_NAME = "name";
const char *const RESOURCE_TYPE = "resources_type";
const char *const RESOURCES = "resources";
const char *const INSTANCES = "instances";
const char *const RES_ATTR = "res_attr";
// instances
const char *const INST_NODE_ID = "node_id";
const char *const INST_RES_INST_ID = "res_instance_id";
// APP or DN
const char *const RES_SCRIPT = "script";
const char *const RES_CHECK_INTERVAL = "check_interval";
const char *const RES_TIMEOUT = "time_out";
const char *const RES_RESTART_DELAY = "restart_delay";
const char *const RES_PERIOD = "restart_period";
const char *const RES_RESTART_TIMES = "restart_times";
const char *const INST_REG = "res_args";
// VIP
const char *const RES_FLOAT_IP = "float_ip";
const char *const INST_ATTR = "inst_attr";
typedef status_t (*CheckResInfo)(cJSON *resItem, const char *resName);
typedef struct ResTypeMapT {
ResType type;
const char *typeStr;
const char *value;
CheckResInfo check;
} ResTypeMap;
status_t GetIntFromText(
const ResOption *resCtx, const char *str, const char *expectValue, int32 *value, int32 logLevel);
status_t CheckResFromArray(cJSON *resArray);
bool CompareResType(const char *value, uint32 *index);
status_t CheckResFromArray(cJSON *resArray);
int DoResCommand(ResOption *resCtx);
const char *GetResOperStr(ResOpMode opMode);
const char *GetInstOperStr(ResOpMode opMode);
int GetValueIntFromCJson(const cJSON *object, const char *infoKey, int32 logLevel = ERROR);
char *GetValueStrFromCJson(const cJSON *object, const char *infoKey, int32 logLevel = ERROR);
cJSON *GetCurResInArray(cJSON *resArray, const char *resName, const ResOption *resCtx, int32 *resIdx = NULL);
ResType GetResTypeFromCjson(cJSON *resItem);
bool CompareResType(const char *value, uint32 *index);
void InitResTypeMap();
bool8 IsResCheckInstances(ResType resType);
bool8 IsCurNotCheckInstances(const ResOption *resCtx, const cJSON *resObj);
const char *GetResTypeValue(uint32 index);
ResType GetResTypeInJson(const ResOption *resCtx, const cJSON *resObj);
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2023 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_res_list.h
*
* IDENTIFICATION
* include/cm/cm_ctl/ctl_res_list.h
*
* -------------------------------------------------------------------------
*/
#ifndef CTL_RES_LIST_H
#define CTL_RES_LIST_H
#include "c.h"
#include "cm_defs.h"
#include "cjson/cJSON.h"
#include "ctl_res.h"
status_t ListResInJson(cJSON *resArray, const ResOption *resCtx);
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022 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_show.h
*
*
* IDENTIFICATION
* include/cm/cm_ctl/ctl_show.h
*
* -------------------------------------------------------------------------
*/
#ifndef CTL_SHOW_H
#define CTL_SHOW_H
#include "cm_defs.h"
status_t HandleRhbAck(const char *option, char *recvMsg);
status_t HandleNodeDiskAck(const char *option, char *recvMsg);
status_t HandleFloatIpAck(const char *option, char *recvMsg);
#endif

45
src/include/cm/cm_debug.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 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.
* -------------------------------------------------------------------------
*
* cm_debug.h
*
* IDENTIFICATION
* include/cm/cm_debug.h
*
* -------------------------------------------------------------------------
*/
#ifndef CM_DEBUG_H
#define CM_DEBUG_H
#include "c.h"
static inline void cm_assert(bool condition)
{
if (!condition) {
*((uint32 *)NULL) = 1;
}
}
#ifdef CM_DEBUG_VERSION
#define CM_ASSERT(expr) cm_assert((bool)(expr))
#else
#define CM_ASSERT(expr) ((void)(expr))
#endif
static inline void cm_exit(int32 exitcode)
{
_exit(exitcode);
}
#endif

View File

@ -274,6 +274,17 @@ typedef int socket_t;
#define CM_IS_EMPTY_STR(str) (((str) == NULL) || ((str)[0] == 0))
/* simple mathematical calculation */
#define CM_MIN(A, B) ((B) < (A) ? (B) : (A))
#define CM_MAX(A, B) ((B) > (A) ? (B) : (A))
#define CM_SWAP(type, A, B) \
do { \
type t_ = (A); \
(A) = (B); \
(B) = t_; \
} while (0)
#define CM_DELTA(A, B) (((A) > (B)) ? ((A) - (B)) : ((B) - (A)))
#define CM_PASSWORD_BUFFER_SIZE (uint32)512
#ifndef ITERATE_TIMES
#define ITERATE_TIMES 10000

View File

@ -58,6 +58,18 @@ typedef struct log_level_string_st {
int level_val;
} log_level_string;
static inline int32 GetCmLogMessage()
{
if (log_min_messages == WARNING) {
return LOG;
}
if (log_min_messages == LOG) {
return WARNING;
}
return log_min_messages;
}
typedef status_t (*SetParam)(const char *key, const char *value);
void LoadParamterFromConfigWithPrefixKey(const char *configFile, const char *prefixKey, SetParam setParam);

View File

@ -38,6 +38,9 @@
#define CM_JSON_STR_LEN 1024
const char SEPARATOR_CHAR = ',';
const char SEPARATOR_ARRAY[] = {SEPARATOR_CHAR, '\0'};
typedef void (*CmJsonLogOutput)(int logLevel, const char *format, ...) __attribute__((format(printf, 2, 3)));
typedef struct CusResInstConfSt {
@ -54,6 +57,7 @@ typedef struct CusResConfJson {
int restartDelay;
int restartPeriod;
int restartTimes;
int abnormalTimeout;
struct {
CusResInstConf *conf;
uint32 count;
@ -65,17 +69,28 @@ typedef struct BaseIpListConfSt {
char baseIp[CM_JSON_STR_LEN];
} BaseIpListConf;
typedef struct VipCusResConfJsonSt {
char resName[CM_JSON_STR_LEN];
char floatIp[CM_JSON_STR_LEN];
struct {
BaseIpListConf *conf;
uint32 count;
} baseIpList;
} VipCusResConfJson;
typedef enum CusResTypeEn {
CUSTOM_RESOURCE_UNKNOWN,
CUSTOM_RESOURCE_APP,
CUSTOM_RESOURCE_DN,
CUSTOM_RESOURCE_VIP,
} CusResType;
typedef struct OneCusResConfJsonSt {
CusResType resType; // resources_type (APP,DN)
CusResType resType; // resources_type (APP,DN,VIP)
union {
AppCusResConfJson appResConf; // APP
DnCusResConfJson dnResConf; // DN
VipCusResConfJson vipResConf; // VIP
};
} OneCusResConfJson;
@ -93,5 +108,7 @@ int ReadConfJsonFile(const char *jsonFile);
void SetReadJsonConfWriteLog(CmJsonLogOutput logFunc);
bool IsConfJsonEmpty();
cJSON *ReadJsonFile(const char *jsonPath, int *err);
int FetchStrFromText(const char *textStr, char *result, uint32 len, char beginPoint);
int GetValueStrFromText(char *result, uint32 resultLen, const char *textStr, const char *expectValue);
#endif // CM_CM_JSON_CONFIG_H

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2022 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.
* -------------------------------------------------------------------------
*
* cm_json_parse_floatIp.h
*
*
* IDENTIFICATION
* include/cm/cm_json_parse_floatIp.h
*
* -------------------------------------------------------------------------
*/
#ifndef CM_JSON_PARSE_FLOATIP_H
#define CM_JSON_PARSE_FLOATIP_H
#include "c.h"
#include "cm_defs.h"
#include "cm_msg.h"
#include "cm_misc_res.h"
typedef struct DnFloatIpT {
uint32 instId;
const char *dataPath;
// float ip and manage ip
uint32 dnFloatIpCount;
char baseIp[MAX_FLOAT_IP_COUNT][CM_IP_LENGTH];
char dnFloatIp[MAX_FLOAT_IP_COUNT][CM_IP_LENGTH];
char floatIpName[MAX_FLOAT_IP_COUNT][CM_MAX_RES_NAME];
uint32 dnFloatIpPort;
} DnFloatIp;
typedef bool8 (*findNodeInfoByNodeIdx)(uint32 instId, uint32 *nodeIdx, uint32 *dnIdx, const char *str);
typedef DnFloatIp *(*getDnFloatIpByNodeInfo)(uint32 nodeIdx, uint32 dnIdx);
typedef void (*increDnFloatIpCnt)(uint32 nodeIdx);
typedef struct ParseFloatIpFuncT {
findNodeInfoByNodeIdx findNodeInfo;
getDnFloatIpByNodeInfo getFloatIp;
increDnFloatIpCnt increaseCnt;
} ParseFloatIpFunc;
void ParseVipConf(int32 logLevel);
void InitParseFloatIpFunc(const ParseFloatIpFunc *parseFuc);
#endif

View File

@ -142,12 +142,14 @@ typedef struct ResStatusCheckInfoSt {
long brokeTime;
int startCount;
int onlineTimes;
long abnormalTime;
int checkInterval;
int timeOut;
int restartDelay;
int restartPeriod;
int restartTimes;
int abnormalTimeout;
} ResStatusCheckInfo;
typedef struct CmResConfListSt {
@ -170,8 +172,14 @@ typedef enum {
INST_TYPE_FENCED_UDF = 5,
} InstanceType;
typedef struct NodeInstBaseInfoT {
uint32 nodeIdx;
uint32 instIdx;
} NodeInstBaseInfo;
typedef struct Instance_t {
uint32 node;
NodeInstBaseInfo baseInfo;
InstanceType instType;
union {
dataNodeInfo *dnInst;
@ -279,4 +287,5 @@ void listen_ip_merge(uint32 ipCnt, const char (*ipListen)[CM_IP_LENGTH], char *r
bool IsNodeIdValid(int nodeId);
void FreeSslOpton();
bool IsNeedCheckFloatIp();
#endif

View File

@ -58,7 +58,10 @@ bool IsSharedStorageMode();
bool IsBoolCmParamTrue(const char *param);
status_t TcpSendMsg(int socket, const char *buf, size_t remainSize, uint32 timeout = CM_TCP_TIMEOUT);
status_t TcpRecvMsg(int socket, char *buf, size_t remainSize, uint32 timeout = CM_TCP_TIMEOUT);
long GetCurMonotonicTimeSec();
void InitPthreadCondMonotonic(pthread_cond_t *cond);
bool CmFileExist(const char *file_path);
bool CheckBoolConfigParam(const char* value);
#endif // CM_MISC_API_H

View File

@ -48,6 +48,7 @@ const uint32 CM_MAX_VIP_COUNT = 16;
#define CUS_RES_CHECK_STAT_ONLINE 0
#define CUS_RES_CHECK_STAT_OFFLINE 1
#define CUS_RES_CHECK_STAT_UNKNOWN 2
#define CUS_RES_CHECK_STAT_ABNORMAL 3
#define CUS_RES_CHECK_STAT_TIMEOUT 137
#define CUS_RES_START_FAIL_DEPEND_NOT_ALIVE 6
@ -94,6 +95,10 @@ typedef struct CmResStatListSt {
extern bool g_enableSharedStorage;
extern CmResStatList g_resStatus[CM_MAX_RES_COUNT];
int ResConfMaxValue(const char *param);
int ResConfMinValue(const char *param);
const char* ResConfDefValue(const char *param);
bool IsResConfValid(const char *param, int value);
void GetCmConfJsonPath(char *path, uint32 pathLen);
int ReadCmConfJson(void *logFunc);
@ -108,5 +113,10 @@ uint8 CheckIpValid(const char *ip);
uint32 CusResCount();
bool IsCusResExist();
const char *GetIsregStatus(int isreg);
void PrintCusInfoResList(const OneResStatList *status, const char *info);
bool8 IsDatanodeSSMode();
const char* ResConfDefValue(const char *param);
int ResConfMinValue(const char *param);
int ResConfMaxValue(const char *param);
#endif // CM_CM_MISC_RES_H

View File

@ -224,7 +224,7 @@ typedef enum CM_MessageType_st {
MSG_AGENT_CLIENT_HEARTBEAT_ACK = 141,
MSG_AGENT_CLIENT_RES_STATUS_LIST = 142,
MSG_AGENT_CLIENT_RES_STATUS_CHANGE = 143,
MSG_AGENT_CLIENT_SET_RES_DATA_STATUS = 144,
MSG_AGENT_CLIENT_NOTIFY_CONN_CLOSE = 144,
MSG_AGENT_CLIENT_REPORT_RES_DATA = 145,
MSG_EXEC_DDB_COMMAND = 146,
@ -260,6 +260,13 @@ typedef enum CM_MessageType_st {
MSG_FINISHREDO_RETRIVE = 173,
MSG_AGENT_CM_ISREG_REPORT = 174,
MSG_CM_AGENT_ISREG_CHECK_LIST_CHANGED = 175,
MSG_CM_AGENT_DISKUSAGE_STATUS_ACK = 176,
MSG_AGENT_CM_EXT_IP_STATUS = 177,
MSG_CTL_CM_EXT_IP_STATUS_REQ = 178,
MSG_CM_CTL_EXT_IP_DATA = 179,
MSG_CM_CTL_EXT_IP_DATA_END = 180,
MSG_CTL_CM_FLOAT_IP_REQ = 181,
MSG_CTL_CM_FLOAT_IP_ACK = 182,
MSG_CM_TYPE_CEIL, // new message types should be added before this.
} CM_MessageType;
@ -1274,6 +1281,24 @@ typedef struct BaseInstInfoT {
const uint32 FLOAT_IP_MSG_RES = 512;
typedef struct DnFloatIpInfoT {
uint32 count;
int32 dnNetState[MAX_FLOAT_IP_COUNT];
int32 nicNetState[MAX_FLOAT_IP_COUNT];
} DnFloatIpInfo;
typedef struct CmaDnFloatIpInfoT {
BaseInstInfo baseInfo;
DnFloatIpInfo info;
char remain[FLOAT_IP_MSG_RES];
} CmaDnFloatIpInfo;
typedef struct CmsDnFloatIpAckT {
BaseInstInfo baseInfo;
int32 oper;
char remain[FLOAT_IP_MSG_RES];
} CmsDnFloatIpAck;
typedef struct DnStatus_t {
CM_MessageType barrierMsgType;
agent_to_cm_datanode_status_report reportMsg;
@ -1283,6 +1308,7 @@ typedef struct DnStatus_t {
};
AgentCmDnLocalPeer lpInfo;
AgentToCmDiskUsageStatusReport diskUsageMsg;
CmaDnFloatIpInfo floatIpInfo;
} DnStatus;
typedef struct DnSyncListInfo_t {
@ -1422,6 +1448,39 @@ typedef struct DatanodelocalPeer_t {
uint32 peerInst;
} DatanodelocalPeer;
typedef struct CmDnReportStatusMsgT {
cm_local_replconninfo local_status;
int sender_count;
BuildState build_info;
cm_sender_replconninfo sender_status[CM_MAX_SENDER_NUM];
cm_receiver_replconninfo receive_status;
RedoStatsData parallel_redo_status;
cm_redo_stats local_redo_stats;
synchronous_standby_mode sync_standby_mode;
int send_gs_guc_time;
int dn_restart_counts;
bool arbitrateFlag;
int failoverStep;
int failoverTimeout;
int phony_dead_times;
int phony_dead_interval;
int dn_restart_counts_in_hour;
bool is_finish_redo_cmd_sent;
uint64 ckpt_redo_point;
char barrierID[BARRIERLEN];
char query_barrierId[BARRIERLEN];
uint64 barrierLSN;
uint64 archive_LSN;
uint64 flush_LSN;
DatanodeSyncList dnSyncList;
int32 syncDone;
uint32 arbiTime;
uint32 sendFailoverTimes;
bool is_barrier_exist;
cmTime_t printBegin; // print synclist time
DatanodelocalPeer dnLp;
} CmDnReportStatusMsg;
// need to keep consist with cm_to_ctl_instance_datanode_status
typedef struct cm_instance_datanode_report_status_st {
cm_local_replconninfo local_status;
@ -1454,6 +1513,7 @@ typedef struct cm_instance_datanode_report_status_st {
bool is_barrier_exist;
cmTime_t printBegin; // print synclist time
DatanodelocalPeer dnLp;
DnFloatIpInfo floatIp;
} cm_instance_datanode_report_status;
typedef struct cm_instance_gtm_report_status_st {
@ -1585,7 +1645,7 @@ typedef struct cm_to_ctl_get_datanode_relation_ack_st {
int member_index;
cm_instance_role_status instanceMember[CM_PRIMARY_STANDBY_MAX_NUM];
cm_instance_gtm_report_status gtm_member[CM_PRIMARY_STANDBY_NUM];
cm_instance_datanode_report_status data_node_member[CM_PRIMARY_STANDBY_MAX_NUM];
CmDnReportStatusMsg data_node_member[CM_PRIMARY_STANDBY_MAX_NUM];
} cm_to_ctl_get_datanode_relation_ack;
// need to keep consist with the struct cm_instance_datanode_report_status
@ -1970,6 +2030,11 @@ typedef struct LockResultSt {
char lockName[CM_MAX_LOCK_NAME];
} LockResult;
typedef struct CmaNotifyClientSt {
bool8 isCmaConnClose;
char reserve[7];
} CmaNotifyClient;
// cms to cma
typedef struct CmsReportResStatListSt {
int msgType;
@ -2060,6 +2125,11 @@ typedef struct AgentToClientResLockResultSt {
LockResult result;
} AgentToClientResLockResult;
typedef struct AgentToClientNotifySt {
MsgHead head;
CmaNotifyClient notify;
} AgentToClientNotify;
// client to cma
typedef struct ClientHbMsgSt {
MsgHead head;
@ -2098,4 +2168,20 @@ typedef struct CmsSSLConnSt {
uint64 startConnTime;
} CmsSSLConnMsg;
typedef struct CmFloatIpStatInfoT {
uint32 nodeId;
uint32 instId;
uint32 count;
int32 nicNetState[MAX_FLOAT_IP_COUNT];
} CmFloatIpStatInfo;
typedef struct CmFloatIpStatAckT {
int32 msgType;
bool8 canShow;
char reserved1[3]; // for alignment
char reserved2[52]; // the reserved
uint32 count;
CmFloatIpStatInfo info[0];
} CmFloatIpStatAck; // the totol size is 64
#endif

View File

@ -43,7 +43,6 @@ void SendSignalToAgentThreads();
extern int GetCtlThreadNum();
int UpdateDynamicConfig();
void UpdateAzNodeInfo();
bool CheckBoolConfigParam(const char* value);
void GetDdbTypeParam(void);
void GetDdbArbiCfg(int32 loadWay);
status_t GetMaintainPath(char *maintainFile, uint32 fileLen);

View File

@ -159,6 +159,8 @@ void ProcessCmRhbMsg(MsgRecvInfo* recvMsgInfo, const CmRhbMsg *rhbMsg);
void ProcessResIsregMsg(MsgRecvInfo *recvMsgInfo, CmaToCmsIsregMsg *isreg);
void ReleaseResLockOwner(const char *resName, uint32 instId);
void ResetResNodeStat();
void ProcessDnFloatIpMsg(MsgRecvInfo *recvMsgInfo, CmaDnFloatIpInfo *floatIp);
void GetFloatIpSet(CmFloatIpStatAck *ack, size_t maxMsgLen, size_t *curMsgLen);
#ifdef ENABLE_MULTIPLE_NODES
void SetCmdStautus(int32 ret);

View File

@ -108,13 +108,6 @@ typedef struct st_cs_pipe {
int32 l_linger;
} cs_pipe_t;
#pragma pack(4)
typedef struct st_text {
char *str;
uint32 len;
} text_t;
#pragma pack()
#define MESSAGE_BUFFER_SIZE (SIZE_M(1))
#define PADDING_BUFFER_SIZE (SIZE_K(1))
#define MAX_BATCH_SIZE 500
@ -128,19 +121,6 @@ typedef struct st_text {
#define CS_INVALID_SOCKET (-1)
#define CM_TEXT_BEGIN(text) ((text)->str[0])
#define CM_TEXT_FIRST(text) ((text)->str[0])
#define CM_TEXT_SECOND(text) ((text)->str[1])
#define CM_TEXT_END(text) ((text)->str[(text)->len - 1])
#define CM_TEXT_SECONDTOLAST(text) (((text)->len >= 2) ? ((text)->str[(text)->len - 2]) : '\0')
#define CM_NULL_TERM(text) \
{ \
(text)->str[(text)->len] = '\0'; \
}
#define CM_IS_EMPTY(text) (((text)->str == NULL) || ((text)->len == 0))
#define CM_IS_QUOTE_CHAR(c1) ((c1)== '\'' || (c1) == '"' || (c1) == '`')
#define CM_IS_QUOTE_STRING(c1, c2) ((c1) == (c2) && CM_IS_QUOTE_CHAR(c1))
#define CS_WAIT_FOR_READ 1
#define CS_WAIT_FOR_WRITE 2
@ -158,52 +138,5 @@ typedef struct st_text {
#define CM_TIME_THOUSAND_UN (uint32)1000
#define CM_HANDSHAKE_TIMEOUT (uint32)600000 /* mill-seconds */
#define cm_str_equal(str1, str2) (strcmp(str1, str2) == 0)
/* Remove the enclosed char or the head and the tail of the text */
#define CM_REMOVE_ENCLOSED_CHAR(text) \
do { \
++((text)->str); \
(text)->len -= 2; \
} while (0)
static inline void cm_assert(bool condition)
{
if (!condition) {
*((uint32 *)NULL) = 1;
}
}
#ifdef CM_DEBUG_VERSION
#define CM_ASSERT(expr) cm_assert((bool)(expr))
#else
#define CM_ASSERT(expr) ((void)(expr))
#endif
static inline void cm_exit(int32 exitcode)
{
_exit(exitcode);
}
#define CM_TEXT_CLEAR(text) ((text)->len = 0)
#define CM_FILE_NAME_BUFFER_SIZE (uint32)256
#define CM_MAX_FILE_NAME_LEN (uint32)(CM_FILE_NAME_BUFFER_SIZE - 1)
static inline void cm_str2text(char *str, text_t *text)
{
text->str = str;
text->len = (str == NULL) ? 0 : (uint32)strlen(str);
}
#define UPPER(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 32) : (c))
#define LOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) + 32) : (c))
#ifndef ELEMENT_COUNT
#define ELEMENT_COUNT(x) ((uint32)(sizeof(x) / sizeof((x)[0])))
#endif
#endif

126
src/include/cm/cm_text.h Normal file
View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2022 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.
* -------------------------------------------------------------------------
*
* cm_text.h
*
*
* IDENTIFICATION
* include/cm/cm_text.h
*
* -------------------------------------------------------------------------
*/
#ifndef CM_TEXT_H
#define CM_TEXT_H
#include <string.h>
#include "c.h"
#include "cm_defs.h"
#pragma pack(4)
typedef struct st_text {
char *str;
uint32 len;
} text_t;
typedef struct CmConstTextT {
const char *str;
uint32 len;
} CmConstText;
#pragma pack()
#define CM_TEXT_BEGIN(text) ((text)->str[0])
#define CM_TEXT_FIRST(text) ((text)->str[0])
#define CM_TEXT_SECOND(text) ((text)->str[1])
#define CM_TEXT_END(text) ((text)->str[(text)->len - 1])
#define CM_TEXT_SECONDTOLAST(text) (((text)->len >= 2) ? ((text)->str[(text)->len - 2]) : '\0')
#define CM_NULL_TERM(text) \
{ \
(text)->str[(text)->len] = '\0'; \
}
#define CM_IS_EMPTY(text) (((text)->str == NULL) || ((text)->len == 0))
#define CM_IS_QUOTE_CHAR(c1) ((c1) == '\'' || (c1) == '"' || (c1) == '`')
#define CM_IS_QUOTE_STRING(c1, c2) ((c1) == (c2) && CM_IS_QUOTE_CHAR(c1))
#define CM_TEXT_CLEAR(text) ((text)->len = 0)
#define CM_FILE_NAME_BUFFER_SIZE (uint32)256
#define CM_MAX_FILE_NAME_LEN (uint32)(CM_FILE_NAME_BUFFER_SIZE - 1)
#define UPPER(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 32) : (c))
#define LOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) + 32) : (c))
#ifndef ELEMENT_COUNT
#define ELEMENT_COUNT(x) ((uint32)(sizeof(x) / sizeof((x)[0])))
#endif
#define CM_C2D(c) ((c) - '0')
#ifdef WIN32
#define cm_strcmpi _strcmpi
#define cm_strcmpni _strnicmp
#define cm_strstri stristr
#else
#define cm_strcmpi strcasecmp
#define cm_strcmpni strncasecmp
#define cm_strstri strcasestr
#endif
#define cm_compare_str(str1, str2) strcmp(str1, str2)
#define cm_compare_str_ins(str1, str2) cm_strcmpi(str1, str2)
#define cm_str_str(str1, str2) strstr(str1, str)
#define cm_str_str_ins(str1, str2) cm_strstri(str1, str2)
#define cm_str_equal(str1, str2) (strcmp(str1, str2) == 0)
#define cm_str_equal_ins(str1, str2) (cm_strcmpi(str1, str2) == 0)
#define cm_str_match(str1, str2) (strstr(str1, str2) != NULL)
#define cm_str_match_ins(str1, str2) (cm_strstri(str1, str2) != NULL)
static inline void CmStr2Text(char *str, text_t *text)
{
text->str = str;
text->len = (str == NULL) ? 0 : (uint32)strlen(str);
}
static inline void CmConststr2Text(const char *str, CmConstText *text)
{
text->str = str;
text->len = (str == NULL) ? 0 : (uint32)strlen(str);
}
/* Remove the enclosed char or the head and the tail of the text */
#define CM_REMOVE_ENCLOSED_CHAR(text) \
do { \
++((text)->str); \
(text)->len -= 2; \
} while (0)
#define CM_TEXT_EMPTY_STR_TO_NULL(str) \
if ((str) != NULL && (str)[0] == '\0') { \
(str) = NULL; \
}
void CmFetchFileName(text_t *files, text_t *name);
bool8 CmTextStrEqualIns(const text_t *text, const char *str);
bool8 CmFetchText(text_t *text, char splitChar, char encloseChar, text_t *sub);
void CmSplitText(const text_t *text, char splitChar, char encloseChar, text_t *left, text_t *right);
void CmRemoveBrackets(text_t *text);
void CmTrimText(text_t *text);
void CmLtrimText(text_t *text);
void CmRtrimText(text_t *text);
bool8 IsCmBracketText(const text_t *text);
status_t CmText2Str(const text_t *text, char *buf, uint32 bufSize);
void CmTrimStr(char *str);
#endif