618 lines
23 KiB
C++
618 lines
23 KiB
C++
/*
|
|
* 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.
|
|
* -------------------------------------------------------------------------
|
|
*
|
|
* cms_common.cpp
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/cm_server/cms_common_res.cpp
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
#include "cjson/cJSON.h"
|
|
#include "cms_ddb_adapter.h"
|
|
#include "cms_global_params.h"
|
|
#include "cms_process_messages.h"
|
|
#include "cms_common_res.h"
|
|
|
|
typedef struct NodeIsregCheckListSt {
|
|
uint32 nodeId;
|
|
volatile uint32 reportInter;
|
|
bool isValid;
|
|
uint32 defCheckCount;
|
|
uint32 defCheckList[CM_MAX_RES_INST_COUNT];
|
|
uint32 checkCount;
|
|
uint32 checkList[CM_MAX_RES_INST_COUNT];
|
|
} NodeIsregCheckList;
|
|
|
|
typedef struct AgentIsregCheckListSt {
|
|
uint32 nodeCount;
|
|
NodeIsregCheckList nodeCheck[CM_MAX_RES_NODE_COUNT];
|
|
} AgentIsregCheckList;
|
|
|
|
typedef struct OneResInstIsregSt {
|
|
uint32 cmInstId;
|
|
ResIsregStatus isreg;
|
|
} OneResInstIsreg;
|
|
|
|
typedef struct OneResIsregSt {
|
|
char resName[CM_MAX_RES_NAME];
|
|
uint32 instCount;
|
|
OneResInstIsreg resStat[CM_MAX_RES_INST_COUNT];
|
|
} OneResIsreg;
|
|
|
|
typedef struct AllResIsregSt {
|
|
uint64 version;
|
|
uint32 resCount;
|
|
OneResIsreg res[CM_MAX_RES_COUNT];
|
|
} AllResIsreg;
|
|
|
|
static AllResIsreg g_isregStatus = {0};
|
|
static AgentIsregCheckList g_isregCheckList = {0};
|
|
|
|
static void InitCheckList(uint32 nodeId, NodeIsregCheckList *isregCheck)
|
|
{
|
|
isregCheck->checkCount = 0;
|
|
isregCheck->defCheckCount = 0;
|
|
for (uint32 i = 0; i < CusResCount(); ++i) {
|
|
for (uint32 j = 0; j < g_resStatus[i].status.instanceCount; ++j) {
|
|
if (g_resStatus[i].status.resStat[j].nodeId == nodeId) {
|
|
isregCheck->checkList[isregCheck->checkCount++] = g_resStatus[i].status.resStat[j].cmInstanceId;
|
|
isregCheck->defCheckList[isregCheck->defCheckCount++] = g_resStatus[i].status.resStat[j].cmInstanceId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void InitIsregVariable()
|
|
{
|
|
g_isregStatus.version = 0;
|
|
g_isregStatus.resCount = CusResCount();
|
|
for (uint32 i = 0; i < g_isregStatus.resCount; ++i) {
|
|
errno_t rc = strcpy_s(g_isregStatus.res[i].resName, CM_MAX_RES_NAME, g_resStatus[i].status.resName);
|
|
securec_check_errno(rc, (void)rc);
|
|
g_isregStatus.res[i].instCount = g_resStatus[i].status.instanceCount;
|
|
for (uint32 j = 0; j < g_isregStatus.res[i].instCount; ++j) {
|
|
g_isregStatus.res[i].resStat[j].isreg = CM_RES_ISREG_INIT;
|
|
g_isregStatus.res[i].resStat[j].cmInstId = g_resStatus[i].status.resStat[j].cmInstanceId;
|
|
}
|
|
}
|
|
|
|
g_isregCheckList.nodeCount = GetResNodeCount();
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
g_isregCheckList.nodeCheck[i].nodeId = GetResNodeId(i);
|
|
g_isregCheckList.nodeCheck[i].reportInter = 0;
|
|
g_isregCheckList.nodeCheck[i].isValid = true;
|
|
InitCheckList(g_isregCheckList.nodeCheck[i].nodeId, &g_isregCheckList.nodeCheck[i]);
|
|
}
|
|
}
|
|
|
|
static void PrintOneNodeCheckList(const uint32 *checkList, uint32 Len, int logLevel)
|
|
{
|
|
char checkListStr[MAX_PATH_LEN] = {0};
|
|
for (uint32 i = 0; i < Len; ++i) {
|
|
const uint32 itemLen = 16;
|
|
char itemStr[itemLen] = {0};
|
|
int ret = snprintf_s(itemStr, itemLen, itemLen - 1, "%u, ", checkList[i]);
|
|
securec_check_intval(ret, (void)ret);
|
|
errno_t rc = strcat_s(checkListStr, MAX_PATH_LEN, itemStr);
|
|
securec_check_errno(rc, (void)rc);
|
|
}
|
|
|
|
write_runlog(logLevel, "check list: %s.\n", checkListStr);
|
|
}
|
|
|
|
static void PrintAllCheckList(int logLevel)
|
|
{
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
const NodeIsregCheckList *oneNodeCheckList = &g_isregCheckList.nodeCheck[i];
|
|
write_runlog(logLevel, "node(%u) check list, is_valid(%d), report_inter(%u).\n",
|
|
oneNodeCheckList->nodeId, oneNodeCheckList->isValid, oneNodeCheckList->reportInter);
|
|
PrintOneNodeCheckList(oneNodeCheckList->checkList, oneNodeCheckList->checkCount, logLevel);
|
|
}
|
|
}
|
|
|
|
void UpdateReportInter()
|
|
{
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
++g_isregCheckList.nodeCheck[i].reportInter;
|
|
}
|
|
}
|
|
|
|
static void DelInstCheckList(uint32 instId, NodeIsregCheckList *nodeCheckList)
|
|
{
|
|
uint32 destIndex = nodeCheckList->checkCount;
|
|
for (uint32 i = 0; i < nodeCheckList->checkCount; ++i) {
|
|
if (nodeCheckList->checkList[i] == instId) {
|
|
destIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
if (destIndex == nodeCheckList->checkCount) {
|
|
return;
|
|
}
|
|
|
|
for (uint32 i = destIndex; i < nodeCheckList->checkCount - 1; ++i) {
|
|
nodeCheckList->checkList[i] = nodeCheckList->checkList[i + 1];
|
|
}
|
|
nodeCheckList->checkList[nodeCheckList->checkCount - 1] = 0;
|
|
--nodeCheckList->checkCount;
|
|
PrintAllCheckList(LOG);
|
|
}
|
|
|
|
static void RestoreCheckList(uint32 index)
|
|
{
|
|
uint32 *defCheckList = g_isregCheckList.nodeCheck[index].defCheckList;
|
|
uint32 defCheckCount = g_isregCheckList.nodeCheck[index].defCheckCount;
|
|
|
|
for (uint32 i = 0; i < defCheckCount; ++i) {
|
|
uint32 instId = defCheckList[i];
|
|
for (uint32 k = 0; k < g_isregCheckList.nodeCount; ++k) {
|
|
if (k == index) {
|
|
continue;
|
|
}
|
|
DelInstCheckList(instId, &g_isregCheckList.nodeCheck[k]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CleanReportInter(uint32 nodeId)
|
|
{
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
if (g_isregCheckList.nodeCheck[i].nodeId == nodeId) {
|
|
g_isregCheckList.nodeCheck[i].reportInter = 0;
|
|
g_isregCheckList.nodeCheck[i].isValid = true;
|
|
RestoreCheckList(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void AddCheckList(uint32 newIndex, uint32 errIndex)
|
|
{
|
|
NodeIsregCheckList *newCheckList = &g_isregCheckList.nodeCheck[newIndex];
|
|
const NodeIsregCheckList *errCheckList = &g_isregCheckList.nodeCheck[errIndex];
|
|
|
|
for (uint32 i = 0; i < errCheckList->checkCount; ++i) {
|
|
newCheckList->checkList[newCheckList->checkCount + i] = errCheckList->checkList[i];
|
|
}
|
|
newCheckList->checkCount += errCheckList->checkCount;
|
|
}
|
|
|
|
static uint32 GetFirstValidIndex(uint32 errIndex)
|
|
{
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
if (i == errIndex) {
|
|
continue;
|
|
}
|
|
if (g_isregCheckList.nodeCheck[i].isValid) {
|
|
return i;
|
|
}
|
|
}
|
|
return g_isregCheckList.nodeCount;
|
|
}
|
|
|
|
static void ChangeCheckList(uint32 errIndex)
|
|
{
|
|
uint32 newIndex = GetFirstValidIndex(errIndex);
|
|
if (newIndex == g_isregCheckList.nodeCount) {
|
|
write_runlog(ERROR, "no node is valid to report isreg status.\n");
|
|
return;
|
|
}
|
|
|
|
for (uint32 i = (newIndex + 1); i < g_isregCheckList.nodeCount; ++i) {
|
|
if ((i == errIndex) && !g_isregCheckList.nodeCheck[i].isValid) {
|
|
continue;
|
|
}
|
|
if (g_isregCheckList.nodeCheck[i].checkCount < g_isregCheckList.nodeCheck[newIndex].checkCount) {
|
|
newIndex = i;
|
|
}
|
|
}
|
|
|
|
AddCheckList(newIndex, errIndex);
|
|
|
|
g_isregCheckList.nodeCheck[errIndex].checkCount = g_isregCheckList.nodeCheck[errIndex].defCheckCount;
|
|
errno_t rc = memcpy_s(g_isregCheckList.nodeCheck[errIndex].checkList, (sizeof(uint32) * CM_MAX_RES_INST_COUNT),
|
|
g_isregCheckList.nodeCheck[errIndex].defCheckList, (sizeof(uint32) * CM_MAX_RES_INST_COUNT));
|
|
securec_check_errno(rc, (void)rc);
|
|
|
|
write_runlog(LOG, "transfer node(%u) check list to node(%u).\n", g_isregCheckList.nodeCheck[errIndex].nodeId,
|
|
g_isregCheckList.nodeCheck[newIndex].nodeId);
|
|
PrintAllCheckList(LOG);
|
|
}
|
|
|
|
void UpdateCheckListAfterTimeout()
|
|
{
|
|
const uint32 isregTimeout = g_agentNetworkTimeout;
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
if ((g_isregCheckList.nodeCheck[i].reportInter > isregTimeout) && g_isregCheckList.nodeCheck[i].isValid) {
|
|
g_isregCheckList.nodeCheck[i].isValid = false;
|
|
ChangeCheckList(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
ResIsregStatus GetIsregStatusByCmInstId(uint32 cmInstId)
|
|
{
|
|
for (uint32 i = 0; i < g_isregStatus.resCount; ++i) {
|
|
for (uint32 j = 0; j < g_isregStatus.res[i].instCount; ++j) {
|
|
if (g_isregStatus.res[i].resStat[j].cmInstId == cmInstId) {
|
|
return g_isregStatus.res[i].resStat[j].isreg;
|
|
}
|
|
}
|
|
}
|
|
write_runlog(ERROR, "%s, unknown instId:%u.\n", __FUNCTION__, cmInstId);
|
|
return CM_RES_ISREG_UNKNOWN;
|
|
}
|
|
|
|
void GetCheckListByNodeId(uint32 nodeId, uint32 *checkList, uint32 *checkCount)
|
|
{
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
if (g_isregCheckList.nodeCheck[i].nodeId != nodeId) {
|
|
continue;
|
|
}
|
|
(*checkCount) = g_isregCheckList.nodeCheck[i].checkCount;
|
|
for (uint32 j = 0; j < (*checkCount); ++j) {
|
|
checkList[j] = g_isregCheckList.nodeCheck[i].checkList[j];
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void UpdateIsworkList(uint32 cmInstId, int newIswork)
|
|
{
|
|
for (uint32 i = 0; i < CusResCount(); ++i) {
|
|
for (uint32 j = 0; j < g_resStatus[i].status.instanceCount; ++j) {
|
|
if (g_resStatus[i].status.resStat[j].cmInstanceId != cmInstId) {
|
|
continue;
|
|
}
|
|
if (newIswork == RES_INST_WORK_STATUS_UNAVAIL) {
|
|
ReleaseResLockOwner(g_resStatus[i].status.resName, g_resStatus[i].status.resStat[j].cmInstanceId);
|
|
}
|
|
if (g_resStatus[i].status.resStat[j].isWorkMember != (uint32)newIswork) {
|
|
(void)pthread_rwlock_wrlock(&g_resStatus[i].rwlock);
|
|
g_resStatus[i].status.resStat[j].isWorkMember = (uint32)newIswork;
|
|
++(g_resStatus[i].status.version);
|
|
OneResStatList resStat = g_resStatus[i].status;
|
|
(void)pthread_rwlock_unlock(&g_resStatus[i].rwlock);
|
|
|
|
ProcessReportResChangedMsg(false, &resStat);
|
|
PrintCusInfoResList(&resStat, __FUNCTION__);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintCurrentIsregStatusList()
|
|
{
|
|
write_runlog(LOG, "isreg status list, version:%lu.\n", g_isregStatus.version);
|
|
for (uint32 i = 0; i < g_isregStatus.resCount; ++i) {
|
|
char resIsreg[MAX_PATH_LEN] = {0};
|
|
for (uint32 j = 0; j < g_isregStatus.res[i].instCount; ++j) {
|
|
const uint32 instIsregLen = 32;
|
|
char instStr[instIsregLen] = {0};
|
|
int ret = snprintf_s(instStr, instIsregLen, instIsregLen - 1, "%u:%s, ",
|
|
g_isregStatus.res[i].resStat[j].cmInstId, GetIsregStatus((int)g_isregStatus.res[i].resStat[j].isreg));
|
|
securec_check_intval(ret, (void)ret);
|
|
errno_t rc = strcat_s(resIsreg, MAX_PATH_LEN, instStr);
|
|
securec_check_errno(rc, (void)rc);
|
|
}
|
|
write_runlog(LOG, "res(%s) isreg list: %s\n", g_isregStatus.res[i].resName, resIsreg);
|
|
}
|
|
}
|
|
|
|
void UpdateIsregStatusList(uint32 cmInstId, ResIsregStatus newIsreg)
|
|
{
|
|
for (uint32 i = 0; i < g_isregStatus.resCount; ++i) {
|
|
for (uint32 j = 0; j < g_isregStatus.res[i].instCount; ++j) {
|
|
if (g_isregStatus.res[i].resStat[j].cmInstId != cmInstId) {
|
|
continue;
|
|
}
|
|
if (g_isregStatus.res[i].resStat[j].isreg != newIsreg) {
|
|
g_isregStatus.res[i].resStat[j].isreg = newIsreg;
|
|
++g_isregStatus.version;
|
|
PrintCurrentIsregStatusList();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
write_runlog(ERROR, "%s, unknown instId:%u.\n", __FUNCTION__, cmInstId);
|
|
}
|
|
|
|
bool IsRecvIsregStatValid(int stat)
|
|
{
|
|
return (stat >= (int)CM_RES_ISREG_INIT && stat < (int)CM_RES_ISREG_CEIL);
|
|
}
|
|
|
|
static ResIsregStatus GetNewIsregStatus(uint32 instId, ResInstIsreg *isregList, uint32 isregCount)
|
|
{
|
|
for (uint32 i = 0; i < isregCount; ++i) {
|
|
if (isregList[i].cmInstId != instId) {
|
|
continue;
|
|
}
|
|
if (!IsRecvIsregStatValid(isregList[i].isreg)) {
|
|
write_runlog(ERROR, "recv inst(%u) isreg status(%d) invalid.\n", isregList[i].cmInstId, isregList[i].isreg);
|
|
return CM_RES_ISREG_UNKNOWN;
|
|
}
|
|
return (ResIsregStatus)isregList[i].isreg;
|
|
}
|
|
return CM_RES_ISREG_INIT;
|
|
}
|
|
|
|
void UpdateResIsregStatusList(uint32 nodeId, ResInstIsreg *isregList, uint32 isregCount, bool *needChangCheckList)
|
|
{
|
|
(*needChangCheckList) = false;
|
|
|
|
for (uint32 i = 0; i < g_isregCheckList.nodeCount; ++i) {
|
|
if (g_isregCheckList.nodeCheck[i].nodeId != nodeId) {
|
|
continue;
|
|
}
|
|
for (uint32 k = 0; k < g_isregCheckList.nodeCheck[i].checkCount; ++k) {
|
|
ResIsregStatus stat = GetNewIsregStatus(g_isregCheckList.nodeCheck[i].checkList[k], isregList, isregCount);
|
|
if (stat == CM_RES_ISREG_INIT) {
|
|
(*needChangCheckList) = true;
|
|
continue;
|
|
}
|
|
UpdateIsregStatusList(g_isregCheckList.nodeCheck[i].checkList[k], stat);
|
|
}
|
|
if (g_isregCheckList.nodeCheck[i].checkCount != isregCount) {
|
|
(*needChangCheckList) = true;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
static inline void GetResStatusDdbKey(char *key, size_t keyLen, const char *resName)
|
|
{
|
|
errno_t rc = snprintf_s(key, keyLen, keyLen - 1, "/%s/CM/CMServer/ResStatus/%s", pw->pw_name, resName);
|
|
securec_check_intval(rc, (void)rc);
|
|
}
|
|
|
|
static cJSON *CreateOneInstStatusObj(const CmResStatInfo *status)
|
|
{
|
|
cJSON *instStat = cJSON_CreateObject();
|
|
(void)cJSON_AddNumberToObject(instStat, "cmInstId", (const double)status->cmInstanceId);
|
|
(void)cJSON_AddNumberToObject(instStat, "isWorkMember", (const double)status->isWorkMember);
|
|
(void)cJSON_AddNumberToObject(instStat, "status", (const double)status->status);
|
|
if (!cJSON_IsObject(instStat)) {
|
|
cJSON_Delete(instStat);
|
|
return NULL;
|
|
}
|
|
return instStat;
|
|
}
|
|
|
|
static status_t AddAllResInstStatToJson(cJSON *root, const OneResStatList *oneResStat)
|
|
{
|
|
char versionStr[MAX_PATH_LEN];
|
|
int ret = sprintf_s(versionStr, MAX_PATH_LEN, "%llu", oneResStat->version);
|
|
securec_check_intval(ret, (void)ret);
|
|
(void)cJSON_AddStringToObject(root, "version", versionStr);
|
|
cJSON *instArray = cJSON_AddArrayToObject(root, "instStatus");
|
|
if (!cJSON_IsArray(instArray)) {
|
|
write_runlog(ERROR, "get res(%s)'s all inst status array failed.\n", oneResStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
for (uint32 i = 0; i < oneResStat->instanceCount; ++i) {
|
|
cJSON *instStat = CreateOneInstStatusObj(&oneResStat->resStat[i]);
|
|
if (instStat == NULL) {
|
|
write_runlog(ERROR, "get res(%s)'s one inst status obj failed.\n", oneResStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
if (!cJSON_AddItemToArray(instArray, instStat)) {
|
|
write_runlog(ERROR, "add res(%s)'s one inst to instArray failed.\n", oneResStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
}
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
static status_t SetResStatJsonToDdb(const cJSON *root, const char *resName)
|
|
{
|
|
char *resStatJson = cJSON_PrintUnformatted(root);
|
|
CM_RETERR_IF_NULL(resStatJson);
|
|
char key[MAX_PATH_LEN] = {0};
|
|
GetResStatusDdbKey(key, MAX_PATH_LEN, resName);
|
|
if (SetKV2Ddb(key, MAX_PATH_LEN, resStatJson, (uint32)strlen(resStatJson), NULL) != CM_SUCCESS) {
|
|
cJSON_free(resStatJson);
|
|
return CM_ERROR;
|
|
}
|
|
cJSON_free(resStatJson);
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
status_t SaveOneResStatusToDdb(const OneResStatList *oneResStat)
|
|
{
|
|
const char *resName = oneResStat->resName;
|
|
cJSON *root = cJSON_CreateObject();
|
|
if (!cJSON_IsObject(root)) {
|
|
write_runlog(ERROR, "create res status json obj failed, save res(%s) status failed.\n", resName);
|
|
cJSON_Delete(root);
|
|
return CM_ERROR;
|
|
}
|
|
|
|
if (AddAllResInstStatToJson(root, oneResStat) != CM_SUCCESS) {
|
|
write_runlog(ERROR, "fill res status json obj failed, save res(%s) status failed.\n", resName);
|
|
cJSON_Delete(root);
|
|
return CM_ERROR;
|
|
}
|
|
|
|
if (SetResStatJsonToDdb(root, resName) != CM_SUCCESS) {
|
|
write_runlog(ERROR, "set res status json obj to ddb failed, save res(%s) status failed.\n", resName);
|
|
cJSON_Delete(root);
|
|
return CM_ERROR;
|
|
}
|
|
|
|
write_runlog(LOG, "save res(%s) version(%llu) status json to ddb success.\n", resName, oneResStat->version);
|
|
cJSON_Delete(root);
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
static status_t ParseAndProcessOneResInst(cJSON *instItem, OneResStatList *resStat)
|
|
{
|
|
cJSON *tmpObj = cJSON_GetObjectItem(instItem, "cmInstId");
|
|
if (!cJSON_IsNumber(tmpObj)) {
|
|
write_runlog(ERROR, "get cmInstId from res(%s) status json failed.\n", resStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
uint32 cmInstId = (uint32)tmpObj->valueint;
|
|
for (uint32 i = 0; i < resStat->instanceCount; ++i) {
|
|
if (resStat->resStat[i].cmInstanceId != cmInstId) {
|
|
continue;
|
|
}
|
|
tmpObj = cJSON_GetObjectItem(instItem, "isWorkMember");
|
|
if (!cJSON_IsNumber(tmpObj)) {
|
|
write_runlog(ERROR, "get isWorkMember from res(%s) status json failed.\n", resStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
resStat->resStat[i].isWorkMember = (uint32)tmpObj->valueint;
|
|
tmpObj = cJSON_GetObjectItem(instItem, "status");
|
|
if (!cJSON_IsNumber(tmpObj)) {
|
|
write_runlog(ERROR, "get status from res(%s) status json failed.\n", resStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
resStat->resStat[i].status = (uint32)tmpObj->valueint;
|
|
}
|
|
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
static status_t UpdateResStatus(OneResStatList *resStat, const cJSON * const resObj)
|
|
{
|
|
cJSON *versionObj = cJSON_GetObjectItem(resObj, "version");
|
|
if (!cJSON_IsString(versionObj)) {
|
|
write_runlog(ERROR, "get version from res(%s) status json failed.\n", resStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
resStat->version = (unsigned long long)CmAtol(versionObj->valuestring, 0);
|
|
cJSON *instStatArray = cJSON_GetObjectItem(resObj, "instStatus");
|
|
if (!cJSON_IsArray(instStatArray)) {
|
|
write_runlog(ERROR, "get instStatus array from res(%s) status json failed.\n", resStat->resName);
|
|
return CM_ERROR;
|
|
}
|
|
|
|
cJSON *instItem;
|
|
cJSON_ArrayForEach(instItem, instStatArray) {
|
|
CM_RETURN_IFERR(ParseAndProcessOneResInst(instItem, resStat));
|
|
}
|
|
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
status_t GetOneResStatusFromDdb(OneResStatList *resStat)
|
|
{
|
|
char key[MAX_PATH_LEN] = {0};
|
|
char value[MAX_PATH_LEN] = {0};
|
|
GetResStatusDdbKey(key, MAX_PATH_LEN, resStat->resName);
|
|
DDB_RESULT ddbResult = SUCCESS_GET_VALUE;
|
|
if (GetKVFromDDb(key, MAX_PATH_LEN, value, MAX_PATH_LEN, &ddbResult) != CM_SUCCESS) {
|
|
if (ddbResult == CAN_NOT_FIND_THE_KEY) {
|
|
write_runlog(LOG, "not exit res(%s) status, key:\"%s\" in ddb.\n", resStat->resName, key);
|
|
return CM_SUCCESS;
|
|
} else {
|
|
write_runlog(ERROR, "get res(%s) status %s from ddb failed: %d.\n", resStat->resName, key, (int)ddbResult);
|
|
return CM_ERROR;
|
|
}
|
|
}
|
|
|
|
write_runlog(LOG, "get res(%s) status json str success, str:\"%s\".\n", resStat->resName, value);
|
|
cJSON *root = cJSON_Parse(value);
|
|
if (cJSON_IsObject(root)) {
|
|
OneResStatList tmpResStat = (*resStat);
|
|
if (UpdateResStatus(&tmpResStat, root) == CM_SUCCESS) {
|
|
errno_t rc = memcpy_s(resStat, sizeof(OneResStatList), &tmpResStat, sizeof(OneResStatList));
|
|
securec_check_errno(rc, (void)rc);
|
|
}
|
|
} else {
|
|
write_runlog(ERROR, "res(%s) status json str in ddb is irregular.\n", resStat->resName);
|
|
}
|
|
|
|
cJSON_Delete(root);
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
status_t GetAllResStatusFromDdb()
|
|
{
|
|
write_runlog(LOG, "get latest res status from ddb.\n");
|
|
for (uint32 i = 0; i < CusResCount(); ++i) {
|
|
OneResStatList tmpResStat = g_resStatus[i].status;
|
|
CM_RETURN_IFERR(GetOneResStatusFromDdb(&tmpResStat));
|
|
PrintCusInfoResList(&tmpResStat, __FUNCTION__);
|
|
|
|
(void)pthread_rwlock_wrlock(&g_resStatus[i].rwlock);
|
|
errno_t rc = memcpy_s(&g_resStatus[i].status, sizeof(OneResStatList), &tmpResStat, sizeof(OneResStatList));
|
|
securec_check_errno(rc, (void)rc);
|
|
(void)pthread_rwlock_unlock(&g_resStatus[i].rwlock);
|
|
}
|
|
|
|
return CM_SUCCESS;
|
|
}
|
|
|
|
void SendRegMsgToCma(uint32 destNodeId, int resMode, uint32 resInstId, const char *resName)
|
|
{
|
|
CmsNotifyAgentRegMsg sendMsg = {0};
|
|
sendMsg.msgType = (int32)MSG_CM_RES_REG;
|
|
sendMsg.resMode = resMode;
|
|
sendMsg.nodeId = destNodeId;
|
|
sendMsg.resInstId = resInstId;
|
|
errno_t rc = strcpy_s(sendMsg.resName, CM_MAX_RES_NAME, resName);
|
|
securec_check_errno(rc, (void)rc);
|
|
|
|
if (resMode == 0) {
|
|
(void)BroadcastMsg('S', (char *)(&sendMsg), sizeof(CmsNotifyAgentRegMsg), LOG);
|
|
} else if (resMode == 1) {
|
|
(void)SendToAgentMsg(destNodeId, 'S', (char *)(&sendMsg), sizeof(CmsNotifyAgentRegMsg), LOG);
|
|
} else {
|
|
write_runlog(ERROR, "%s, unknown resMode(%d).\n", __FUNCTION__, resMode);
|
|
}
|
|
}
|
|
|
|
void NotifyCmaDoReg(uint32 destNodeId)
|
|
{
|
|
for (uint32 i = 0; i < CusResCount(); ++i) {
|
|
const OneResStatList *resInfo = &g_resStatus[i].status;
|
|
for (uint32 j = 0; j < resInfo->instanceCount; ++j) {
|
|
if (resInfo->resStat[j].nodeId != destNodeId) {
|
|
continue;
|
|
}
|
|
ResIsregStatus isreg = GetIsregStatusByCmInstId(resInfo->resStat[j].cmInstanceId);
|
|
if (isreg == CM_RES_ISREG_REG) {
|
|
UpdateIsworkList(resInfo->resStat[j].cmInstanceId, RES_INST_WORK_STATUS_AVAIL);
|
|
} else if (isreg == CM_RES_ISREG_UNREG || isreg == CM_RES_ISREG_PENDING || isreg == CM_RES_ISREG_INIT) {
|
|
SendRegMsgToCma(destNodeId, 1, resInfo->resStat[j].resInstanceId, resInfo->resName);
|
|
} else if (isreg == CM_RES_ISREG_NOT_SUPPORT && resInfo->resStat[j].status == (uint32)CM_RES_STAT_OFFLINE) {
|
|
UpdateIsworkList(resInfo->resStat[j].cmInstanceId, RES_INST_WORK_STATUS_AVAIL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NotifyCmaDoUnreg(uint32 destNodeId)
|
|
{
|
|
for (uint32 i = 0; i < CusResCount(); ++i) {
|
|
const OneResStatList *resInfo = &g_resStatus[i].status;
|
|
for (uint32 j = 0; j < g_resStatus[i].status.instanceCount; ++j) {
|
|
if (g_resStatus[i].status.resStat[j].nodeId != destNodeId) {
|
|
continue;
|
|
}
|
|
ResIsregStatus isreg = GetIsregStatusByCmInstId(g_resStatus[i].status.resStat[j].cmInstanceId);
|
|
if (isreg == CM_RES_ISREG_REG || isreg == CM_RES_ISREG_PENDING || isreg == CM_RES_ISREG_INIT) {
|
|
SendRegMsgToCma(destNodeId, 0, resInfo->resStat[j].resInstanceId, resInfo->resName);
|
|
} else if (isreg == CM_RES_ISREG_UNREG || isreg == CM_RES_ISREG_NOT_SUPPORT) {
|
|
UpdateIsworkList(g_resStatus[i].status.resStat[j].cmInstanceId, RES_INST_WORK_STATUS_UNAVAIL);
|
|
}
|
|
}
|
|
}
|
|
}
|