add feature for vip and readonly check
This commit is contained in:
parent
9adc6a3580
commit
6c2b3f625c
@ -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"
|
||||
|
@ -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);
|
||||
|
1012
src/cm_agent/client_adpts/libpq/cma_datanode_check.cpp
Normal file
1012
src/cm_agent/client_adpts/libpq/cma_datanode_check.cpp
Normal file
File diff suppressed because it is too large
Load Diff
62
src/cm_agent/client_adpts/libpq/cma_libpq_com.cpp
Normal file
62
src/cm_agent/client_adpts/libpq/cma_libpq_com.cpp
Normal 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;
|
||||
}
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
166
src/cm_common/cm_json_parse_floatIp.cpp
Normal file
166
src/cm_common/cm_json_parse_floatIp.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
267
src/cm_common/cm_text.cpp
Normal 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;
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
#include "cm_error.h"
|
||||
#include "cm/cm_elog.h"
|
||||
#include "cm_text.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
40
src/cm_ctl/ctl_global_params.cpp
Normal file
40
src/cm_ctl/ctl_global_params.cpp
Normal 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;
|
||||
}
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
127
src/cm_ctl/ctl_process_message.cpp
Normal file
127
src/cm_ctl/ctl_process_message.cpp
Normal 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
681
src/cm_ctl/ctl_res_check.cpp
Normal file
681
src/cm_ctl/ctl_res_check.cpp
Normal 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
857
src/cm_ctl/ctl_res_list.cpp
Normal 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));
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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__);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 &&
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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') {
|
||||
|
@ -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;
|
||||
|
||||
|
42
src/include/cm/cm_agent/clients/libpq/cma_libpq_com.h
Normal file
42
src/include/cm/cm_agent/clients/libpq/cma_libpq_com.h
Normal 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
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
38
src/include/cm/cm_ctl/ctl_global_params.h
Normal file
38
src/include/cm/cm_ctl/ctl_global_params.h
Normal 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
|
31
src/include/cm/cm_ctl/ctl_misc.h
Normal file
31
src/include/cm/cm_ctl/ctl_misc.h
Normal 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
|
41
src/include/cm/cm_ctl/ctl_process_message.h
Normal file
41
src/include/cm/cm_ctl/ctl_process_message.h
Normal 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
|
157
src/include/cm/cm_ctl/ctl_res.h
Normal file
157
src/include/cm/cm_ctl/ctl_res.h
Normal 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
|
36
src/include/cm/cm_ctl/ctl_res_list.h
Normal file
36
src/include/cm/cm_ctl/ctl_res_list.h
Normal 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
|
32
src/include/cm/cm_ctl/ctl_show.h
Normal file
32
src/include/cm/cm_ctl/ctl_show.h
Normal 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
45
src/include/cm/cm_debug.h
Normal 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
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
55
src/include/cm/cm_json_parse_floatIp.h
Normal file
55
src/include/cm/cm_json_parse_floatIp.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
126
src/include/cm/cm_text.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user