* 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.
* -------------------------------------------------------------------------
*
* cms_global_params_utils.cpp
*
*
* IDENTIFICATION
* src/cm_server/cms_global_params_utils.cpp
*
* -------------------------------------------------------------------------
*/
#include <sys/epoll.h>
#include "cm/cm_elog.h"
#include "cms_ddb.h"
#include "cms_global_params.h"
#include "cms_process_messages.h"
#include "cms_alarm.h"
#include "cms_write_dynamic_config.h"
#include "cms_arbitrate_datanode_pms_utils.h"
#include "cms_az.h"
#include "cms_common.h"
void ChangeDnMemberIndex(const char *str, uint32 groupIdx, int32 memIdx, int32 instTypePur, int32 instTypeSor)
{
cm_instance_role_status *instMem = g_instance_role_group_ptr[groupIdx].instanceMember;
int32 count = g_instance_role_group_ptr[groupIdx].count;
cm_instance_command_status *cmd = g_instance_group_report_status_ptr[groupIdx].instance_status.command_member;
uint32 peerInstId = cmd[memIdx].peerInstId;
write_runlog(LOG, "%s: line %d: instd(%u) instTypePur is (%d: %s), instTypeSor is (%d: %s), peerInstId is %u.\n",
str, __LINE__, instMem[memIdx].instanceId, instTypePur, datanode_role_int_to_string(instTypePur),
instTypeSor, datanode_role_int_to_string(instTypeSor), peerInstId);
for (int32 i = 0; i < count; ++i) {
if (i == memIdx && instMem[i].role != instTypePur) {
write_runlog(LOG, "%s: %d: instance(%u) static role(%s) will change to be %s.\n",
str, __LINE__, instMem[i].instanceId, datanode_role_int_to_string(instMem[i].role),
datanode_role_int_to_string(instTypePur));
instMem[i].role = instTypePur;
cmd[i].role_changed = INSTANCE_ROLE_CHANGED;
} else if (((instTypePur == INSTANCE_ROLE_PRIMARY || instTypePur == INSTANCE_ROLE_MAIN_STANDBY
|| instTypePur == INSTANCE_ROLE_STANDBY) || peerInstId == instMem[i].instanceId)
&& (i != memIdx) && instMem[i].role == instTypePur) {
write_runlog(LOG, "%s: %d: instance(%u) static role(%s) will change to be %s.\n",
str, __LINE__, instMem[i].instanceId, datanode_role_int_to_string(instMem[i].role),
datanode_role_int_to_string(instTypeSor));
instMem[i].role = instTypeSor;
cmd[i].role_changed = INSTANCE_ROLE_CHANGED;
}
}
SetDynamicConfigChangeToDdb(groupIdx, 0);
}
void ChangeCascadeMemberIndex(const char *str, uint32 groupIdx, int32 memIdx, int32 peerId)
{
cm_instance_role_status *instMem = g_instance_role_group_ptr[groupIdx].instanceMember;
int32 count = g_instance_role_group_ptr[groupIdx].count;
cm_instance_command_status *cmd = g_instance_group_report_status_ptr[groupIdx].instance_status.command_member;
for (int32 i = 0; i < count; ++i) {
if (i == memIdx && instMem[i].role == INSTANCE_ROLE_CASCADE_STANDBY) {
write_runlog(LOG, "%s: %d: instance(%u) static role(%s) will change to be %s.\n",
str, __LINE__, instMem[i].instanceId, datanode_role_int_to_string(INSTANCE_ROLE_CASCADE_STANDBY),
datanode_role_int_to_string(INSTANCE_ROLE_STANDBY));
instMem[i].role = INSTANCE_ROLE_STANDBY;
cmd[i].role_changed = INSTANCE_ROLE_CHANGED;
} else if (i == peerId && instMem[i].role == INSTANCE_ROLE_STANDBY) {
write_runlog(LOG, "%s: %d: instance(%u) static role(%s) will change to be %s.\n",
str, __LINE__, instMem[i].instanceId, datanode_role_int_to_string(INSTANCE_ROLE_STANDBY),
datanode_role_int_to_string(INSTANCE_ROLE_CASCADE_STANDBY));
instMem[i].role = INSTANCE_ROLE_CASCADE_STANDBY;
cmd[i].role_changed = INSTANCE_ROLE_CHANGED;
}
}
SetDynamicConfigChangeToDdb(groupIdx, 0);
}
void ChangeDnPrimaryMemberIndex(uint32 group_index, int primary_member_index)
{
if (g_one_master_multi_slave) {
if (g_ssDoubleClusterMode == SS_DOUBLE_STANDBY) {
ChangeDnMemberIndex("[ChangeDnPrimaryMemberIndex]",
group_index, primary_member_index, INSTANCE_ROLE_MAIN_STANDBY, INSTANCE_ROLE_STANDBY);
} else {
ChangeDnMemberIndex("[ChangeDnPrimaryMemberIndex]",
group_index, primary_member_index, INSTANCE_ROLE_PRIMARY, INSTANCE_ROLE_STANDBY);
}
} else {
change_primary_member_index(group_index, primary_member_index);
}
}
void change_primary_member_index(uint32 group_index, int primary_member_index)
{
cm_instance_role_status* instanceMember = g_instance_role_group_ptr[group_index].instanceMember;
int count = g_instance_role_group_ptr[group_index].count;
cm_instance_command_status* status = g_instance_group_report_status_ptr[group_index].instance_status.command_member;
for (int i = 0; i < count; i++) {
if (i == primary_member_index &&
(instanceMember[i].role != INSTANCE_ROLE_PRIMARY && instanceMember[i].role != INSTANCE_ROLE_MAIN_STANDBY)) {
if (g_ssDoubleClusterMode == SS_DOUBLE_STANDBY) {
instanceMember[i].role = INSTANCE_ROLE_MAIN_STANDBY;
} else {
instanceMember[i].role = INSTANCE_ROLE_PRIMARY;
}
status[i].role_changed = INSTANCE_ROLE_CHANGED;
SetDynamicConfigChangeToDdb(group_index, i);
} else if (i != primary_member_index &&
(instanceMember[i].role == INSTANCE_ROLE_PRIMARY || instanceMember[i].role == INSTANCE_ROLE_MAIN_STANDBY)) {
instanceMember[i].role = INSTANCE_ROLE_STANDBY;
status[i].role_changed = INSTANCE_ROLE_CHANGED;
SetDynamicConfigChangeToDdb(group_index, i);
}
}
(void)WriteDynamicConfigFile(false);
}
int find_node_in_dynamic_configure(uint32 node, uint32 instanceId, uint32 *group_index, int *member_index)
{
*group_index = 0;
*member_index = 0;
getWalrecordMode();
for (uint32 i = 0; i < g_dynamic_header->relationCount; i++) {
for (int j = 0; j < Min(g_instance_role_group_ptr[i].count, CM_PRIMARY_STANDBY_MAX_NUM); j++) {
if ((node == g_instance_role_group_ptr[i].instanceMember[j].node) &&
((instanceId == g_instance_role_group_ptr[i].instanceMember[j].instanceId) || g_enableWalRecord)) {
*group_index = i;
*member_index = j;
return 0;
}
}
}
return -1;
}
void instance_delay_arbitrate_time_out_direct_clean(uint32 group_index, int member_index, uint32 delay_max_count)
{
g_instance_group_report_status_ptr[group_index].instance_status.command_member[member_index].arbitrate_delay_set =
INSTANCE_ARBITRATE_DELAY_NO_SET;
g_instance_group_report_status_ptr[group_index].instance_status.command_member[member_index]
.arbitrate_delay_time_out = (int)delay_max_count;
g_instance_group_report_status_ptr[group_index].instance_status.command_member[member_index]
.local_arbitrate_delay_role = INSTANCE_ROLE_UNKNOWN;
g_instance_group_report_status_ptr[group_index].instance_status.command_member[member_index]
.peerl_arbitrate_delay_role = INSTANCE_ROLE_UNKNOWN;
write_runlog(DEBUG1,
"instance_delay_arbitrate_time_out_direct_clean (node =%u instanceid =%u), delay_max_count=%u\n",
g_instance_role_group_ptr[group_index].instanceMember[member_index].node,
g_instance_role_group_ptr[group_index].instanceMember[member_index].instanceId, delay_max_count);
}
bool IsCurInstanceInVoteAz(uint32 groupIndex, int memberIndex)
{
uint32 azPriority = g_instance_role_group_ptr[groupIndex].instanceMember[memberIndex].azPriority;
for (int i = 0; i < AZ_MEMBER_MAX_COUNT; ++i) {
if (azPriority == g_cmAzInfo[i].azPriority && g_cmAzInfo[i].isVoteAz == IS_VOTE_AZ) {
write_runlog(DEBUG1, "instance(%u) in vote AZ.\n",
g_instance_role_group_ptr[groupIndex].instanceMember[memberIndex].instanceId);
return true;
}
}
return false;
}
int GetVoteAzIndex()
{
int voteAzIndex = AZ_ALL_INDEX;
for (int i = 0; i < AZ_MEMBER_MAX_COUNT; ++i) {
if (g_cmAzInfo[i].isVoteAz == IS_VOTE_AZ) {
voteAzIndex = i;
break;
}
}
return voteAzIndex;
}
uint32 GetClusterUpgradeMode()
{
int rcs;
struct stat statBuf = {0};
char pgHostPath[MAX_PATH_LEN] = {0};
char grayscaleUpgradeCheck[MAX_PATH_LEN] = {0};
char inplaceUpgradeFlag[MAX_PATH_LEN] = {0};
char upgradeFlag[MAX_PATH_LEN] = {0};
char agentConfigDir[MAX_PATH_LEN] = {0};
errno_t rc = snprintf_s(agentConfigDir, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/cm_agent/cm_agent.conf",
g_currentNode->cmDataPath);
securec_check_intval(rc, (void)rc);
check_input_for_security(agentConfigDir);
canonicalize_path(agentConfigDir);
uint32 upgradeMode = 0;
FILE *fd = fopen(agentConfigDir, "r");
if (fd == NULL) {
write_runlog(LOG, "Cannot open the cm agent config file %s.\n", agentConfigDir);
return upgradeMode;
}
(void)fclose(fd);
rcs = cmserver_getenv("PGHOST", pgHostPath, sizeof(pgHostPath), ERROR);
if (rcs == EOK) {
rcs = snprintf_s(grayscaleUpgradeCheck, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/binary_upgrade", pgHostPath);
securec_check_intval(rcs, (void)rcs);
if (access(grayscaleUpgradeCheck, F_OK) == 0) {
rcs = snprintf_s(
inplaceUpgradeFlag, MAX_PATH_LEN, MAX_PATH_LEN - 1,
"%s/inplace_upgrade_flag", grayscaleUpgradeCheck);
securec_check_intval(rcs, (void)rcs);
* then cluster is in grayscale upgrade */
if (stat(inplaceUpgradeFlag, &statBuf) == 0) {
upgradeMode = get_uint32_value_from_config(agentConfigDir, "upgrade_from", 0);
if (upgradeMode == 0) {
upgradeMode = 2;
}
}
rcs = snprintf_s(upgradeFlag, MAX_PATH_LEN, MAX_PATH_LEN - 1,
"%s/upgrade_step.csv", grayscaleUpgradeCheck);
securec_check_intval(rcs, (void)rcs);
if (stat(upgradeFlag, &statBuf) == 0) {
upgradeMode = MAINTENANCE_NODE_UPGRADED_GRAYSCALE;
}
}
} else {
write_runlog(ERROR, "get PGHOST failed!\n");
}
write_runlog(DEBUG1, "Cluster upgrade mode is %u\n", upgradeMode);
return upgradeMode;
}
bool ExistClusterMaintenance(bool *isInFailover)
{
if (access(cluster_maintance_path, F_OK) == 0) {
if (isInFailover == NULL) {
return true;
}
char maintenanceInfo[MAX_PATH_LEN] = {0};
FILE* fp = fopen(cluster_maintance_path, "r");
if (fp == NULL) {
return false;
}
if (fgets(maintenanceInfo, MAX_PATH_LEN, fp) == NULL) {
(void)fclose(fp);
return false;
}
if (strstr(maintenanceInfo, "failover") != NULL) {
*isInFailover = true;
}
(void)fclose(fp);
write_runlog(LOG, "Streaming standby cluster is in %s.\n", *isInFailover ? "failover" : "switchover");
return true;
}
return false;
}
int GetSendTimes(uint32 groupIndex, int memberIndex, bool isTotal)
{
if (memberIndex < 0 || memberIndex >= g_instance_role_group_ptr[groupIndex].count) {
return 0;
}
if (isTotal) {
return g_instance_group_report_status_ptr[groupIndex].instance_status.command_member[memberIndex].maxSendTimes;
}
return g_instance_group_report_status_ptr[groupIndex].instance_status.command_member[memberIndex]
.command_send_num;
}
void SetSendTimes(uint32 groupIndex, int memberIndex, int timeOut)
{
cm_instance_command_status *pCommand =
g_instance_group_report_status_ptr[groupIndex].instance_status.command_member;
if (timeOut < SWITCHOVER_SEND_CHECK_RATE) {
pCommand[memberIndex].maxSendTimes = SWITCHOVER_SEND_CHECK_NUM;
} else {
pCommand[memberIndex].maxSendTimes = timeOut / SWITCHOVER_SEND_CHECK_RATE;
}
}
bool IsArchiveMaxSendTimes(uint32 groupIndex, int memberIndex)
{
cm_instance_command_status *pCommand =
g_instance_group_report_status_ptr[groupIndex].instance_status.command_member;
if (pCommand[memberIndex].maxSendTimes == 0) {
return pCommand[memberIndex].command_send_num <= SWITCHOVER_SEND_CHECK_NUM;
} else {
return pCommand[memberIndex].command_send_num <= pCommand[memberIndex].maxSendTimes;
}
}
uint32 GetInstanceIdInGroup(uint32 groupIndex, int memberIndex)
{
if (memberIndex < 0 || memberIndex >= g_instance_role_group_ptr[groupIndex].count) {
return g_instance_role_group_ptr[groupIndex].instanceMember[0].instanceId;
}
return g_instance_role_group_ptr[groupIndex].instanceMember[memberIndex].instanceId;
}
int32 GetInstanceCountsInGroup(uint32 groupIndex)
{
return g_instance_role_group_ptr[groupIndex].count;
}
bool IncrementTermToFile()
{
uint32 curFileTerm = GetTermForMinorityStart();
uint32 finalTerm = curFileTerm;
if (curFileTerm != g_termCache) {
write_runlog(WARNING,
"curFileTerm(%u) is not equal with cached term(%u), we choose the largest one.\n",
curFileTerm, g_termCache);
finalTerm = (curFileTerm > g_termCache) ? curFileTerm : g_termCache;
}
finalTerm += CM_INCREMENT_TERM_VALUE;
char command[CM_MAX_COMMAND_LEN] = {0};
int32 rc = snprintf_s(command,
CM_MAX_COMMAND_LEN, CM_MAX_COMMAND_LEN - 1, "echo -e \'%u\' > %s;", finalTerm, cm_force_start_file_path);
securec_check_intval(rc, (void)rc);
write_runlog(LOG, "IncrementTermToFile, cmd: %s .\n", command);
rc = system(command);
if (rc != 0) {
write_runlog(ERROR,
"Failed to increment minority term cache to %u, result is %d-%d.\n", g_termCache, rc, WEXITSTATUS(rc));
return false;
}
g_termCache = finalTerm;
write_runlog(LOG, "Success to execute command: %s, increment minority term cache to %u.\n", command, g_termCache);
return true;
}
bool CurAzIsNeedToStop(const char *azName)
{
uint32 azPriority = 0;
int32 azIndex = -1;
int32 curAzIndex = -1;
for (int32 i = 0; i < AZ_MEMBER_MAX_COUNT; ++i) {
if (strcmp(azName, g_cmAzInfo[i].azName) == 0) {
azPriority = g_cmAzInfo[i].azPriority;
azIndex = i;
}
if (strcmp(g_currentNode->azName, g_cmAzInfo[i].azName) == 0) {
curAzIndex = i;
}
}
if ((azIndex == -1) || (curAzIndex == -1)) {
write_runlog(ERROR, "can not find azName(%s) or curAzName(%s) from cmAzInfo.\n", azName, g_currentNode->azName);
return false;
}
write_runlog(LOG, "dnCount is [%u: %u], azPriority is [%u: %u].\n",
g_cmAzInfo[curAzIndex].dnCount, g_cmAzInfo[azIndex].dnCount, g_currentNode->azPriority, azPriority);
* 2. azPriority is more,
* these condition is chosen to be stopped
*/
if (g_cmAzInfo[curAzIndex].dnCount < g_cmAzInfo[azIndex].dnCount) {
return true;
}
if (g_cmAzInfo[curAzIndex].dnCount > g_cmAzInfo[azIndex].dnCount) {
return false;
}
if (g_currentNode->azPriority < azPriority) {
return false;
}
return true;
}
void InitClientCrt(const char *appPath)
{
errno_t rcs =
snprintf_s(g_tlsPath.caFile, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/share/sslcert/etcd/etcdca.crt", appPath);
securec_check_intval(rcs, (void)rcs);
rcs = snprintf_s(g_tlsPath.crtFile, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/share/sslcert/etcd/client.crt", appPath);
securec_check_intval(rcs, (void)rcs);
rcs = snprintf_s(g_tlsPath.keyFile, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/share/sslcert/etcd/client.key", appPath);
securec_check_intval(rcs, (void)rcs);
}
bool CanArbitrate(MsgRecvInfo* recvMsgInfo, const char *arbitrateType)
{
const uint32 stopPrintInterval = 5;
if (g_HA_status->local_role == CM_SERVER_STANDBY) {
write_runlog(LOG, "%s: cm_server is in standby state, skip arbitrate\n", arbitrateType);
AsyncProcMsg(recvMsgInfo, PM_REMOVE_CONN, NULL, 0);
return false;
}
if (ctl_stop_cluster_server_halt_arbitration_timeout > 0) {
if (ctl_stop_cluster_server_halt_arbitration_timeout % stopPrintInterval == 0) {
write_runlog(LOG,
"cm_ctl is running a full cluster stop. %s are halted. "
"Waiting for another %u seconds.\n",
arbitrateType, ctl_stop_cluster_server_halt_arbitration_timeout);
}
return false;
}
return true;
}
void SetSwitchoverCmd(cm_instance_command_status *cmd, int32 localRole, uint32 instId, uint32 peerInstId)
{
cmd->command_status = INSTANCE_COMMAND_WAIT_EXEC;
cmd->pengding_command = (int)MSG_CM_AGENT_SWITCHOVER;
if (localRole == INSTANCE_ROLE_STANDBY) {
if (g_ssDoubleClusterMode == SS_DOUBLE_STANDBY) {
cmd->cmdPur = INSTANCE_ROLE_MAIN_STANDBY;
} else {
cmd->cmdPur = INSTANCE_ROLE_PRIMARY;
}
cmd->cmdSour = INSTANCE_ROLE_STANDBY;
} else if (localRole == INSTANCE_ROLE_CASCADE_STANDBY) {
cmd->cmdPur = INSTANCE_ROLE_STANDBY;
cmd->cmdSour = INSTANCE_ROLE_CASCADE_STANDBY;
}
cmd->peerInstId = peerInstId;
write_runlog(LOG, "instd(%u) localRole(%d: %s), cmdStatus[cmdPur(%d: %s), cmdSour(%d: %s), peer(%u)].\n", instId,
localRole, datanode_role_int_to_string(localRole), cmd->cmdPur, datanode_role_int_to_string(cmd->cmdPur),
cmd->cmdSour, datanode_role_int_to_string(cmd->cmdSour), peerInstId);
}
void HashCascadeStandby(cm_to_ctl_instance_datanode_status *dnReport, uint32 groupIdx, int32 memIdx)
{
int32 localRole =
g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member[memIdx].local_status.local_role;
if (localRole != INSTANCE_ROLE_STANDBY) {
return;
}
bool hasCascade = false;
cm_instance_role_status *dnRole = g_instance_role_group_ptr[groupIdx].instanceMember;
for (int32 i = 0; i < g_instance_role_group_ptr[groupIdx].count; ++i) {
if (dnRole[i].role == INSTANCE_ROLE_CASCADE_STANDBY) {
hasCascade = true;
write_runlog(LOG, "instd(%u) is cascade_standby.\n", dnRole[i].instanceId);
}
}
if (!hasCascade) {
return;
}
dnReport->sender_status[0].peer_role = INSTANCE_ROLE_CASCADE_STANDBY;
}
bool CheckCanDoSwitchover(uint32 groupIdx, int32 memIdx, int32 *pendCmd, const char *str)
{
cm_instance_report_status *instStatus = &g_instance_group_report_status_ptr[groupIdx].instance_status;
cm_instance_role_status *instRole = g_instance_role_group_ptr[groupIdx].instanceMember;
for (int32 i = 0; i < g_instance_role_group_ptr[groupIdx].count; i++) {
if (instStatus->command_member[i].command_status != INSTANCE_NONE_COMMAND) {
write_runlog(LOG,
"instanceId =%u try do switchover_msg, but instance(%u) is executing another command (%d)\n",
instRole[memIdx].instanceId, instRole[i].instanceId, instStatus->command_member[i].pengding_command);
return false;
}
}
if (IsCurInstanceInVoteAz(groupIdx, memIdx)) {
return true;
}
if (instStatus->data_node_member[memIdx].local_status.local_role != INSTANCE_ROLE_CASCADE_STANDBY &&
CheckInstInSyncList(groupIdx, memIdx, str) != SYNCLIST_IS_FINISTH) {
(*pendCmd) = (int32)MSG_CM_AGENT_DN_SYNC_LIST;
return false;
}
return true;
}
void PrintSyncListMsg(uint32 groupIdx, int32 memIdx, const char *str)
{
cm_instance_report_status *groupRep = &g_instance_group_report_status_ptr[groupIdx].instance_status;
uint32 instId = g_instance_role_group_ptr[groupIdx].instanceMember[memIdx].instanceId;
char curStr[MAX_PATH_LEN] = {0};
char expectStr[MAX_PATH_LEN] = {0};
char voteAzStr[MAX_PATH_LEN] = {0};
GetSyncListString(&(groupRep->currentSyncList), curStr, sizeof(curStr));
GetSyncListString(&(groupRep->exceptSyncList), expectStr, sizeof(expectStr));
GetDnStatusString(&(groupRep->voteAzInstance), voteAzStr, sizeof(voteAzStr));
write_runlog(LOG, "%s instd(%u) is modifing syncList, synclist is [cur:(%s), expect:(%s), voteAz:(%s)].\n",
str, instId, curStr, expectStr, voteAzStr);
}
bool CheckGroupAndMemIndex(uint32 groupIdx, int32 memIdx, const char *str)
{
if (groupIdx >= g_dynamic_header->relationCount) {
write_runlog(ERROR, "%s:%d, groupIdx is [%u: %u].\n", str, __LINE__, groupIdx, g_dynamic_header->relationCount);
return false;
}
if (memIdx < 0 || memIdx >= g_instance_role_group_ptr[groupIdx].count) {
write_runlog(ERROR, "%s:%d, memidx is [%d: %d].\n", str, __LINE__, memIdx,
g_instance_role_group_ptr[groupIdx].count);
return false;
}
return true;
}
EnCheckSynclist CheckInstInSyncList(uint32 groupIdx, int32 memIdx, const char *str)
{
if (!CheckGroupAndMemIndex(groupIdx, memIdx, str)) {
write_runlog(ERROR, "%s:%d, groupIdx is %u, memIdx is %d, cannot checkInstInSyncList.\n", str, __LINE__,
groupIdx, memIdx);
return SYNCLIST_IS_FINISTH;
}
if (g_instance_role_group_ptr[groupIdx].instanceMember[memIdx].instanceType != INSTANCE_TYPE_DATANODE) {
return SYNCLIST_IS_FINISTH;
}
cm_instance_report_status *groupRep = &g_instance_group_report_status_ptr[groupIdx].instance_status;
uint32 instId = g_instance_role_group_ptr[groupIdx].instanceMember[memIdx].instanceId;
if (!CompareCurWithExceptSyncList(groupIdx)) {
PrintSyncListMsg(groupIdx, memIdx, str);
return SYNCLIST_IS_NOT_SAME;
}
if (groupRep->data_node_member[memIdx].local_status.local_role != INSTANCE_ROLE_CASCADE_STANDBY &&
!IsInstanceIdInSyncList(instId, &(groupRep->exceptSyncList))) {
PrintSyncListMsg(groupIdx, memIdx, str);
return INST_IS_NOT_IN_SYNCLIST;
}
return SYNCLIST_IS_FINISTH;
}
bool CheckAllDnShardSynclist(const char *str)
{
for (uint32 i = 0; i < g_dynamic_header->relationCount; ++i) {
if (g_instance_role_group_ptr[i].instanceMember[0].instanceType != INSTANCE_TYPE_DATANODE) {
continue;
}
if (CheckInstInSyncList(i, 0, str) == SYNCLIST_IS_NOT_SAME) {
return false;
}
}
return true;
}
uint32 GetPeerInstIdWhenDnIsStandby(uint32 groupIdx, int32 memIdx)
{
cm_instance_datanode_report_status *dnRep =
g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member;
cm_instance_role_status *role = g_instance_role_group_ptr[groupIdx].instanceMember;
uint32 dyPriInstId = 0;
int32 staPrimIdx = -1;
int32 dyPrimIdx = -1;
for (int32 i = 0; i < g_instance_role_group_ptr[groupIdx].count; ++i) {
if (i == memIdx) {
continue;
}
cm_local_replconninfo *dnStatus = &(dnRep[i].local_status);
if (role[i].role == INSTANCE_ROLE_PRIMARY) {
if (dnStatus->local_role == INSTANCE_ROLE_PRIMARY && dnStatus->db_state == INSTANCE_HA_STATE_NORMAL) {
return role[i].instanceId;
}
staPrimIdx = i;
}
if (dnStatus->local_role == INSTANCE_ROLE_PRIMARY) {
if (dnStatus->db_state == INSTANCE_HA_STATE_NORMAL) {
dyPriInstId = role[i].instanceId;
}
dyPrimIdx = i;
}
}
if (dyPriInstId != 0) {
return dyPriInstId;
}
if (dyPrimIdx != -1) {
return role[dyPrimIdx].instanceId;
}
if (staPrimIdx != -1) {
return role[staPrimIdx].instanceId;
}
int32 peerIndex = (memIdx + 1) % g_instance_role_group_ptr[groupIdx].count;
return role[peerIndex].instanceId;
}
uint32 GetPeerInstId(uint32 groupIdx, int32 memIdx)
{
if (!CheckGroupAndMemIndex(groupIdx, memIdx, "[GetPeerInstId]")) {
return 0;
}
cm_instance_datanode_report_status *dnRep =
g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member;
if (dnRep[memIdx].local_status.local_role == INSTANCE_ROLE_STANDBY) {
return GetPeerInstIdWhenDnIsStandby(groupIdx, memIdx);
}
return g_instance_group_report_status_ptr[groupIdx].instance_status.data_node_member[memIdx].dnLp.peerInst;
}
static maintenance_mode GetClusterMaintenanceMode()
{
maintenance_mode mode = MAINTENANCE_MODE_NONE;
for (uint32 groupIndex = 0; groupIndex < g_dynamic_header->relationCount; ++groupIndex) {
mode = getMaintenanceMode(groupIndex);
if (mode != MAINTENANCE_MODE_NONE) {
return mode;
}
}
return MAINTENANCE_MODE_NONE;
}
status_t CmsCanArbitrate(CmsArbitrateStatus *cmsSt, const char *str)
{
cmsSt->upgradeMode = GetClusterMaintenanceMode();
cmsSt->isDdbHealth = IsDdbHealth(DDB_PRE_CONN);
cmsSt->cmsRole = g_HA_status->local_role;
bool isResult =
(cmsSt->cmsRole != CM_SERVER_PRIMARY) || !(cmsSt->isDdbHealth) ||
(cmsSt->upgradeMode != MAINTENANCE_MODE_NONE) || g_isPauseArbitration;
if (isResult) {
int32 logLevel = (g_HA_status->local_role != CM_SERVER_PRIMARY) ? DEBUG1 : LOG;
write_runlog(logLevel, "%s cannot arbitrate reduce or increase, in the condition that ddb is health is %d "
"or upgradeMode is %u.\n", str, cmsSt->isDdbHealth, (uint32)cmsSt->upgradeMode);
return CM_ERROR;
}
return CM_SUCCESS;
}
status_t GetNodeIdxByNodeId(uint32 nodeId, uint32 *nodeIdx, const char *str)
{
for (uint32 i = 0; i < g_node_num; ++i) {
if (nodeId == g_node[i].node) {
*nodeIdx = i;
return CM_SUCCESS;
}
}
write_runlog(ERROR, "%s cannot find the nodeId(%u).\n", str, nodeId);
return CM_ERROR;
}
bool8 IsCurInstIdCascadeStandby(uint32 groupIdx, int memberIdx)
{
if (g_instance_role_group_ptr[groupIdx].instanceMember[memberIdx].instanceType != INSTANCE_TYPE_DATANODE) {
return false;
}
if (g_instance_role_group_ptr[groupIdx].instanceMember[memberIdx].role == INSTANCE_ROLE_CASCADE_STANDBY) {
return true;
}
return CM_FALSE;
}