* Copyright (c) 2021 Huawei Technologies Co.,Ltd.
*
* CM is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* cma_instance_management_ext.cpp
*
*
* IDENTIFICATION
* src/cm_agent/cma_instance_management_ext.cpp
*
* -------------------------------------------------------------------------
*/
#include <sys/wait.h>
#include "cm/cm_json_config.h"
#include "cma_global_params.h"
#include "cma_alarm.h"
#include "cma_instance_management.h"
#include "cma_instance_management_res.h"
uint32 g_localResConfCount = 0;
static const char* StatToString(int stat)
{
switch (stat) {
case CUS_RES_CHECK_STAT_ONLINE:
return "online";
case CUS_RES_CHECK_STAT_OFFLINE:
return "offline";
case CUS_RES_CHECK_STAT_UNKNOWN:
return "unknown";
case CUS_RES_CHECK_STAT_ABNORMAL:
return "abnormal";
case CUS_RES_CHECK_STAT_TIMEOUT:
return "timeout";
case CUS_RES_CHECK_STAT_FAILED:
return "failed";
default:
return "invalid status";
}
}
static int CusResCmdExecute(const char *scriptPath, const char *oper, uint32 timeout, bool8 needNohup)
{
char command[MAX_PATH_LEN + MAX_OPTION_LEN] = {0};
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) {
write_runlog(ERROR, "run system command failed %s, errno(%d).\n", command, errno);
return -1;
}
if (WIFEXITED(status)) {
ret = WEXITSTATUS(status);
write_runlog(DEBUG1, "run script command %s %s, ret=%d.\n", scriptPath, oper, ret);
return ret;
}
write_runlog(ERROR, "run system command failed %s, status=%d, errno(%d).\n", command, status, errno);
return -1;
}
status_t StartOneResInst(CmResConfList *conf)
{
int ret;
char oper[MAX_OPTION_LEN] = {0};
if (conf->resType == CUSTOM_RESOURCE_DN && undocumentedVersion > 0) {
ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-start %u %s '-u %u'", conf->resInstanceId,
conf->arg, undocumentedVersion);
} else if (conf->resType == CUSTOM_RESOURCE_DN && g_ssDoubleClusterMode != SS_DOUBLE_NULL) {
ret = snprintf_s(oper, MAX_OPTION_LEN, MAX_OPTION_LEN - 1, "-start %u %s '-z %s'", conf->resInstanceId,
conf->arg, type_int_to_str_ss_double(g_ssDoubleClusterMode));
} else {
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 = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_FALSE);
if (ret == 0) {
conf->checkInfo.startCount++;
write_runlog(LOG, "StartOneResInst: run start script (%s %s) successfully.\n", conf->script, oper);
} else if (ret == CUS_RES_START_FAIL_DEPEND_NOT_ALIVE) {
write_runlog(LOG, "StartOneResInst: res(%s) inst(%u) can't do restart, cause depend resource inst not alive.\n",
conf->resName, conf->cmInstanceId);
return CM_ERROR;
} else {
conf->checkInfo.startCount++;
write_runlog(ERROR, "StartOneResInst: run start script (%s %s) failed, ret=%d.\n", conf->script, oper, ret);
}
return CM_SUCCESS;
}
void StopOneResInst(const CmResConfList *conf)
{
char oper[MAX_OPTION_LEN] = {0};
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 = 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 {
write_runlog(ERROR, "StopOneResInst: run stop command (%s %s) failed, ret=%d.\n", conf->script, oper, ret);
}
}
void OneResInstShutdown(const CmResConfList *oneResConf)
{
if (CheckOneResInst(oneResConf) != CUS_RES_CHECK_STAT_OFFLINE) {
write_runlog(LOG, "custom resource(%s:%u) shutdown.\n", oneResConf->resName, oneResConf->cmInstanceId);
StopOneResInst(oneResConf);
}
}
void OneResInstClean(const CmResConfList *oneResConf)
{
if (CheckOneResInst(oneResConf) != CUS_RES_CHECK_STAT_OFFLINE) {
(void)CleanOneResInst(oneResConf);
}
}
status_t RegOneResInst(const CmResConfList *conf, uint32 destInstId, bool8 needNohup)
{
char oper[MAX_OPTION_LEN] = {0};
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 = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, needNohup);
if (ret != 0) {
write_runlog(ERROR, "[%s]: cmd:(%s %s) execute failed, ret=%d.\n", __FUNCTION__, conf->script, oper, ret);
return CM_ERROR;
}
write_runlog(LOG, "[%s]: cmd:(%s %s) is executing.\n", __FUNCTION__, conf->script, oper);
return CM_SUCCESS;
}
status_t UnregOneResInst(const CmResConfList *conf, uint32 destInstId)
{
char oper[MAX_OPTION_LEN] = {0};
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 = CusResCmdExecute(conf->script, oper, (uint32)conf->checkInfo.timeOut, CM_TRUE);
if (ret != 0) {
write_runlog(ERROR, "[%s]: cmd:(%s %s) execute failed, ret=%d.\n", __FUNCTION__, conf->script, oper, ret);
return CM_ERROR;
}
write_runlog(LOG, "[%s]: cmd:(%s %s) is executing.\n", __FUNCTION__, conf->script, oper);
return CM_SUCCESS;
}
ResIsregStatus IsregOneResInst(const CmResConfList *conf, uint32 destInstId)
{
char oper[MAX_OPTION_LEN];
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 = 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);
return CM_RES_ISREG_UNKNOWN;
case RES_INST_ISREG_UNREG:
write_runlog(DEBUG5, "IsregOneResInst: res(%s) inst(%u) has been unreg.\n", conf->resName, destInstId);
return CM_RES_ISREG_UNREG;
case RES_INST_ISREG_PENDING:
write_runlog(DEBUG5, "IsregOneResInst: res(%s) inst(%u) has been pending.\n", conf->resName, destInstId);
return CM_RES_ISREG_PENDING;
case RES_INST_ISREG_REG:
write_runlog(DEBUG5, "IsregOneResInst: res(%s) inst(%u) has been reg.\n", conf->resName, destInstId);
return CM_RES_ISREG_REG;
case RES_INST_ISREG_NOT_SUPPORT:
write_runlog(DEBUG5, "IsregOneResInst: res(%s) inst(%u) not support isreg.\n", conf->resName, destInstId);
return CM_RES_ISREG_NOT_SUPPORT;
default:
write_runlog(ERROR, "IsregOneResInst: res(%s) inst(%u) get unknown isreg ret(%d).\n",
conf->resName, destInstId, ret);
break;
}
return CM_RES_ISREG_UNKNOWN;
}
status_t CleanOneResInst(const CmResConfList *conf)
{
char oper[MAX_OPTION_LEN];
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 = 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;
}
write_runlog(LOG, "CleanOneResInst: clean inst cmd(%s %s) success\n", conf->script, oper);
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 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 %s.\n",
resConf->resName, resConf->cmInstanceId, StatToString(curStat));
resConf->checkInfo.abnormalTime = 0;
}
}
static inline void CleanOneInstOnlineTimes(CmResConfList *resConf)
{
resConf->checkInfo.onlineTimes = 0;
}
void StopAllResInst()
{
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
if (g_enableWalRecord && strncmp(g_resConf[i].resName, CM_RES_RESTAPI, strlen(CM_RES_RESTAPI)) == 0) {
continue;
}
OneResInstClean(&g_resConf[i]);
}
StopCurNodeFloatIp();
}
int CheckOneResInst(const CmResConfList *conf)
{
char oper[MAX_OPTION_LEN] = {0};
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 = 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);
}
if (ret < 0) {
return CUS_RES_CHECK_STAT_FAILED;
}
return ret;
}
static status_t ManualStopOneLocalResInst(CmResConfList *conf)
{
char instanceStartFile[MAX_PATH_LEN] = {0};
int ret = snprintf_s(instanceStartFile, MAX_PATH_LEN, MAX_PATH_LEN - 1,
"%s_%u", g_cmInstanceManualStartPath, conf->cmInstanceId);
securec_check_intval(ret, (void)ret);
if (CmFileExist(instanceStartFile)) {
write_runlog(LOG, "instanceStartFile(%s) is exist, can't create again.\n", instanceStartFile);
return CM_SUCCESS;
}
char command[MAX_PATH_LEN] = {0};
ret = snprintf_s(command, MAX_PATH_LEN, MAX_PATH_LEN - 1,
SYSTEMQUOTE "touch %s;chmod 600 %s < \"%s\" 2>&1" SYSTEMQUOTE,
instanceStartFile, instanceStartFile, DEVNULL);
securec_check_intval(ret, (void)ret);
ret = system(command);
if (ret != 0) {
write_runlog(ERROR, "manual stop res(%s) inst(%u) failed, ret=%d.\n", conf->resName, conf->resInstanceId, ret);
return CM_ERROR;
}
write_runlog(LOG, "manual stop res(%s) inst(%u) success.\n", conf->resName, conf->resInstanceId);
return CM_SUCCESS;
}
static status_t ManuallStopAllLocalResInst()
{
status_t result = CM_SUCCESS;
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
if (ManualStopOneLocalResInst(&g_resConf[i]) != CM_SUCCESS) {
result = CM_ERROR;
}
}
return result;
}
void ManualStopLocalResInst(CmResConfList *conf)
{
if (ManuallStopAllLocalResInst() == CM_SUCCESS) {
CleanOneInstCheckCount(conf);
}
}
bool IsInstManualStopped(uint32 instId)
{
char manualStart[MAX_PATH_LEN] = {0};
int ret = snprintf_s(manualStart, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s_%u", g_cmInstanceManualStartPath, instId);
securec_check_intval(ret, (void)ret);
if (CmFileExist(manualStart)) {
write_runlog(DEBUG5, "res inst(%u) has been stop.\n", instId);
return true;
}
return false;
}
static inline void RestartOneResInst(CmResConfList *conf)
{
ResIsregStatus stat = IsregOneResInst(conf, conf->resInstanceId);
if ((stat != CM_RES_ISREG_REG) && (stat != CM_RES_ISREG_NOT_SUPPORT)) {
if (RegOneResInst(conf, conf->resInstanceId, CM_FALSE) != CM_SUCCESS) {
write_runlog(LOG, "cur inst(%u) isreg stat=(%u), and reg failed, restart failed.\n",
conf->cmInstanceId, (uint32)stat);
conf->checkInfo.startCount++;
return;
}
}
(void)StartOneResInst(conf);
}
static void ProcessOfflineInstance(CmResConfList *conf)
{
long curTime = GetCurMonotonicTimeSec();
if (conf->checkInfo.restartTimes == -1) {
RestartOneResInst(conf);
return;
}
if (conf->checkInfo.brokeTime == 0) {
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->cmInstanceId, conf->checkInfo.startCount,
conf->checkInfo.restartTimes);
ManualStopLocalResInst(conf);
return;
}
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, curTime, conf->checkInfo.brokeTime, conf->checkInfo.restartDelay);
return;
}
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;
}
RestartOneResInst(conf);
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 kill it.\n",
conf->resName, conf->cmInstanceId, duration, conf->checkInfo.abnormalTimeout);
if (CleanOneResInst(conf) == CM_SUCCESS) {
write_runlog(LOG, "res(%s) inst(%u) clean abnormal time.\n", conf->resName, conf->cmInstanceId);
} else {
conf->checkInfo.startCount++;
}
conf->checkInfo.startTime = curTime;
}
static inline bool NeedStopResInst(const char *resName, uint32 cmInstId)
{
return (IsInstManualStopped(cmInstId) || CmFileExist(g_cmManualStartPath) || !IsOneResInstWork(resName, cmInstId) ||
g_agentNicDown);
}
static void ProcessOnlineInstance(CmResConfList *resConf)
{
const int instNormalTimes = 5;
if (resConf->checkInfo.onlineTimes < instNormalTimes) {
++resConf->checkInfo.onlineTimes;
} else {
CleanOneInstCheckCount(resConf);
}
}
void StartResourceCheck()
{
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
int ret = CheckOneResInst(&g_resConf[i]);
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:
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;
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;
}
}
}
static bool IsInstReplaced(uint32 cmInstId)
{
char flag[MAX_PATH_LEN] = {0};
int ret = snprintf_s(flag, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/%s_%u", g_binPath, CM_INSTANCE_REPLACE, cmInstId);
securec_check_intval(ret, (void)ret);
if (CmFileExist(flag)) {
return true;
}
return false;
}
void StopResourceCheck()
{
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
if (IsInstReplaced(g_resConf[i].cmInstanceId)) {
write_runlog(LOG, "custom resource instance(%s:%u) is being replaced and can't be stopped.\n",
g_resConf[i].resName, g_resConf[i].cmInstanceId);
continue;
}
if (IsInstManualStopped(g_resConf[i].cmInstanceId)) {
OneResInstShutdown(&g_resConf[i]);
}
if ((!IsOneResInstWork(g_resConf[i].resName, g_resConf[i].cmInstanceId) && !g_isPauseArbitration) || CmFileExist(g_cmManualStartPath)) {
OneResInstClean(&g_resConf[i]);
}
}
}
int ResourceStoppedCheck(void)
{
for (uint32 i = 0; i < GetLocalResConfCount(); ++i) {
int ret = CheckOneResInst(&g_resConf[i]);
if (ret == CUS_RES_CHECK_STAT_ONLINE || ret == CUS_RES_CHECK_STAT_ABNORMAL) {
if (g_enableWalRecord && strncmp(g_resConf[i].resName, CM_RES_RESTAPI, strlen(CM_RES_RESTAPI)) == 0) {
write_runlog(LOG, "resource %s is running, no need to stop\n", g_resConf[i].resName);
return PROCESS_NOT_EXIST;
} else {
write_runlog(LOG, "resource is running, script is %s\n", g_resConf[i].script);
return PROCESS_RUNNING;
}
}
}
return PROCESS_NOT_EXIST;
}
static inline status_t PaddingResConf(const CmResConfList *oneConf)
{
if (g_localResConfCount >= CM_MAX_RES_INST_COUNT) {
write_runlog(ERROR, "custom resource inst count overflow, max:%d.\n", CM_MAX_RES_COUNT);
return CM_ERROR;
}
errno_t rc = memcpy_s(&g_resConf[g_localResConfCount], sizeof(CmResConfList), oneConf, sizeof(CmResConfList));
securec_check_errno(rc, (void)rc);
++g_localResConfCount;
return CM_SUCCESS;
}
static status_t InitResNameConf(const char *resNameJson, char *resNameConf)
{
if (CM_IS_EMPTY_STR(resNameJson)) {
write_runlog(ERROR, "[InitLocalRes] resource name is empty.\n");
return CM_ERROR;
}
if (strlen(resNameJson) >= CM_MAX_RES_NAME) {
write_runlog(ERROR, "[InitLocalRes] resName(%s) is longer than %d.\n", resNameJson, (CM_MAX_RES_NAME - 1));
return CM_ERROR;
}
errno_t rc = strcpy_s(resNameConf, CM_MAX_RES_NAME, resNameJson);
securec_check_errno(rc, (void)rc);
return CM_SUCCESS;
}
static inline void InitOneConfOfRes(const char *paraName, int value, int *newValue)
{
if (IsResConfValid(paraName, value)) {
*newValue = value;
} else {
*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);
}
}
static status_t InitLocalCommConfOfDefRes(const CusResConfJson *resJson, CmResConfList *localConf)
{
localConf->nodeId = g_currentNode->node;
CM_RETURN_IFERR(InitResNameConf(resJson->resName, localConf->resName));
errno_t rc = strcpy_s(localConf->script, MAX_PATH_LEN, resJson->resScript);
securec_check_errno(rc, (void)rc);
canonicalize_path(localConf->script);
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;
}
static uint32 GetCmInstId(const CmResConfList *newConf)
{
for (uint32 i = 0; i < CusResCount(); ++i) {
if (strcmp(g_resStatus[i].status.resName, newConf->resName) != 0) {
continue;
}
uint32 cmInstId = 0;
for (uint32 k = 0; k < g_resStatus[i].status.instanceCount; ++k) {
if (g_resStatus[i].status.resStat[k].resInstanceId == newConf->resInstanceId) {
cmInstId = g_resStatus[i].status.resStat[k].cmInstanceId;
break;
}
}
return cmInstId;
}
return 0;
}
static void InitLocalOneAppInstConf(const CusResInstConf *appInst, CmResConfList *newConf)
{
errno_t rc = memset_s(newConf->arg, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(rc, (void)rc);
rc = strcpy_s(newConf->arg, MAX_PATH_LEN, appInst->resArgs);
securec_check_errno(rc, (void)rc);
newConf->nodeId = (uint32)appInst->nodeId;
newConf->resInstanceId = (uint32)appInst->resInstId;
newConf->cmInstanceId = GetCmInstId(newConf);
}
static status_t InitLocalAllAppResInstConf(const AppCusResConfJson *appResJson, CmResConfList *newLocalConf)
{
for (uint32 i = 0; i < appResJson->instance.count; ++i) {
if (appResJson->instance.conf[i].nodeId == (int)newLocalConf->nodeId) {
InitLocalOneAppInstConf(&appResJson->instance.conf[i], newLocalConf);
CM_RETURN_IFERR(PaddingResConf(newLocalConf));
}
}
return CM_SUCCESS;
}
static void InitLocalOneDnInstConfByStaticConf(const dataNodeInfo *dnInfo, CmResConfList *newConf)
{
errno_t rc = memset_s(newConf->arg, MAX_PATH_LEN, 0, MAX_PATH_LEN);
securec_check_errno(rc, (void)rc);
rc = strcpy_s(newConf->arg, MAX_PATH_LEN, dnInfo->datanodeLocalDataPath);
securec_check_errno(rc, (void)rc);
newConf->cmInstanceId = dnInfo->datanodeId;
newConf->resInstanceId = dnInfo->datanodeId;
}
static void InitLocalOneDnInstConfByJsonConf(const CusResConfJson *resJson, CmResConfList *newConf)
{
for (uint32 i = 0; i < resJson->instance.count; ++i) {
if ((resJson->instance.conf[i].nodeId == (int)newConf->nodeId) &&
(resJson->instance.conf[i].resInstId == (int)newConf->resInstanceId)) {
errno_t rc = strcpy_s(newConf->arg, MAX_PATH_LEN, resJson->instance.conf[i].resArgs);
securec_check_errno(rc, (void)rc);
}
}
}
static status_t InitLocalAllDnResInstConf(const CusResConfJson *resJson, CmResConfList *newLocalConf)
{
for (uint32 i = 0; i < g_node_num; ++i) {
if (g_node[i].node != newLocalConf->nodeId) {
continue;
}
for (uint32 k = 0; k < g_node[i].datanodeCount; ++k) {
InitLocalOneDnInstConfByStaticConf(&g_node[i].datanode[k], newLocalConf);
InitLocalOneDnInstConfByJsonConf(resJson, newLocalConf);
CM_RETURN_IFERR(PaddingResConf(newLocalConf));
}
break;
}
return CM_SUCCESS;
}
static status_t InitLocalOneResConf(const OneCusResConfJson *oneResJson)
{
CmResConfList newLocalConf = {{0}};
newLocalConf.resType = (int)oneResJson->resType;
if (oneResJson->resType == CUSTOM_RESOURCE_APP) {
CM_RETURN_IFERR(InitLocalCommConfOfDefRes(&oneResJson->appResConf, &newLocalConf));
CM_RETURN_IFERR(InitLocalAllAppResInstConf(&oneResJson->appResConf, &newLocalConf));
} else if (oneResJson->resType == CUSTOM_RESOURCE_DN) {
CM_RETURN_IFERR(InitLocalCommConfOfDefRes(&oneResJson->dnResConf, &newLocalConf));
CM_RETURN_IFERR(InitLocalAllDnResInstConf(&oneResJson->dnResConf, &newLocalConf));
}
return CM_SUCCESS;
}
status_t InitLocalResConf()
{
if (IsConfJsonEmpty()) {
write_runlog(LOG, "[InitLocalRes] no resource exist.\n");
return CM_SUCCESS;
}
for (uint32 i = 0; i < g_confJson->resource.count; ++i) {
CM_RETURN_IFERR(InitLocalOneResConf(&g_confJson->resource.conf[i]));
}
return CM_SUCCESS;
}
uint32 GetLocalResConfCount()
{
return g_localResConfCount;
}
bool IsCusResExistLocal()
{
return (g_localResConfCount > 0);
}