text: /*
   * 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_process_messages_append.cpp
   *
   *
   * IDENTIFICATION
   *    src/cm_server/cms_process_messages_append.cpp
   *
   * -------------------------------------------------------------------------
   */
  #include "cms_global_params.h"
  #include "cms_process_messages.h"
  #include "cms_disk_check.h"
  #include "cms_common.h"
  #include "cms_alarm.h"
  #include "cms_ddb_adapter.h"
  #include "cms_threads.h"
  
  typedef struct NodeInstanceCnt {
      uint32 nodeNum;
      uint32 dnRepNum;
      uint32 cnNum;
      uint32 relationNum;
      uint32 dnNum;
      uint32 etcdNum;
      uint32 cmsNum;
      uint32 gtmNum;
  } NodeInstanceCnt;
  
  void StoreGlobalValue(NodeInstanceCnt *globalValue)
  {
      globalValue->nodeNum = g_node_num;
      globalValue->dnRepNum = g_dn_replication_num;
      globalValue->cnNum = g_coordinator_num;
      globalValue->relationNum = g_dynamic_header->relationCount;
      globalValue->dnNum = g_datanode_instance_count;
      globalValue->etcdNum = g_etcd_num;
      globalValue->cmsNum = g_cm_server_num;
      globalValue->gtmNum = g_gtm_num;
      return;
  }
  
  void RestoreGlobalValue(NodeInstanceCnt lastGlobalValue)
  {
      g_node_num = lastGlobalValue.nodeNum;
      g_dn_replication_num = lastGlobalValue.dnRepNum;
      g_coordinator_num = lastGlobalValue.cnNum;
      g_dynamic_header->relationCount = lastGlobalValue.relationNum;
      g_datanode_instance_count = lastGlobalValue.dnNum;
      g_etcd_num = lastGlobalValue.etcdNum;
      g_cm_server_num = lastGlobalValue.cmsNum;
      g_gtm_num = lastGlobalValue.gtmNum;
      return;
  }
  
  int CheckInstanceCnt(NodeInstanceCnt lastGlobalValue)
  {
      if (g_etcd_num != lastGlobalValue.etcdNum || g_cm_server_num != lastGlobalValue.cmsNum ||
          g_gtm_num != lastGlobalValue.gtmNum) {
          return -1;
      }
  
      return 0;
  }
  
  static void FreeAndInitNotifyMsg()
  {
      write_runlog(DEBUG1, "[reload] begin to free notify msg.\n");
      FreeNotifyMsg();
      write_runlog(DEBUG1, "[reload] end to free notify msg.\n");
  #ifdef ENABLE_MULTIPLE_NODES
      write_runlog(DEBUG1, "[reload] begin to init notify msg.\n");
      (void)cm_notify_msg_init();
      write_runlog(DEBUG1, "[reload] end to init notify msg.\n");
  #endif
  }
  
  
  int UpdateBasicInfo(NodeInstanceCnt lastGlobalValue)
  {
      if (CheckInstanceCnt(lastGlobalValue) != 0) {
          write_runlog(ERROR, "[reload] unexpected instance type increase, only support add cn/dn instance.\n");
          return -1;
      }
  
      if (UpdateDynamicConfig() != 0) {
          write_runlog(ERROR, "[reload] UpdateDynamicConfig failed.\n");
          return -1;
      }
  
      UpdatePhonyDeadAlarm();
      FreeAndInitNotifyMsg();
      UpdateAzNodeInfo();
  
      if (UpdateNodeReadonlyInfo(lastGlobalValue.nodeNum) != 0) {
          write_runlog(ERROR, "[reload] UpdateNodeReadonlyInfo failed.\n");
          return -1;
      }
  
      return 0;
  }
  
  /**
   * @brief 
   * 
   * @param  con              My Param doc
   */
  void ProcessCtlToCmReloadMsg(CM_Connection* con)
  {
      int err = 0;
      int status = 0;
      uint32 i = 0;
      NodeInstanceCnt lastGlobalValue;
      CMToCtlReloadAck reloadAckMsg;
      timespec waitBegin = {0, 0};
      timespec waitEnd = {0, 0};
  
      write_runlog(LOG, "[reload] ProcessCtlToCmReloadMsg start.\n");
      StoreGlobalValue(&lastGlobalValue);
      g_inReload = true;
      (void)clock_gettime(CLOCK_MONOTONIC, &waitBegin);
  
      while (i < g_loopState.count) {
          (void)clock_gettime(CLOCK_MONOTONIC, &waitEnd);
          if ((waitEnd.tv_sec - waitBegin.tv_sec) > RELOADWAIT_TIMEOUT) {
              write_runlog(LOG, "execute cm_ctl reload command timeout.\n");
              return;
          }
          if (g_loopState.execStatus[i] == 0) {
              write_runlog(LOG, "[reload] unfinished thread loop-index:%u.\n", i);
              i = 0;
              cm_sleep(1);
              continue;
          }
          i++;
      }
  
      write_runlog(LOG, "[reload] begin to reload config file.\n");
      reloadAckMsg.msgType = MSG_CM_CTL_RELOAD_ACK;
      status = read_config_file(g_cmStaticConfigurePath, &err, true);
      if (status != 0) {
          switch (status) {
              case OPEN_FILE_ERROR: {
                  write_runlog(ERROR, "[reload] Failed to open the cluster static file: [errno %d].\n", err);
                  break;
              }
              case READ_FILE_ERROR: {
                  write_runlog(ERROR, "[reload] Failed to read the cluster static file: [errno %d].\n", err);
                  break;
              }
              default:
                  break;
          }
          reloadAckMsg.reloadOk = false;
          (void)cm_server_send_msg(con, 'S', (char*)(&reloadAckMsg), sizeof(CMToCtlReloadAck));
          g_inReload = false;
          return;
      }
  
      if (UpdateBasicInfo(lastGlobalValue) != 0) {
          write_runlog(ERROR, "[reload] UpdateBasicInfo failed.\n");
          RestoreGlobalValue(lastGlobalValue);
          FreeAndInitNotifyMsg();
          reloadAckMsg.reloadOk = false;
          (void)cm_server_send_msg(con, 'S', (char*)(&reloadAckMsg), sizeof(CMToCtlReloadAck));
          g_inReload = false;
          return;
      }
  
      write_runlog(LOG, "[reload] reload config file success.\n");
  
  #if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
      if (g_isEnableUpdateSyncList == CANNOT_START_SYNCLIST_THREADS) {
          bool ret = CreateDnGroupStatusCheckAndArbitrateThread();
          if (!ret) {
              write_runlog(LOG, "[reload] cannot start synclist threads.\n");
          }
      }
  #endif
  
      write_runlog(LOG, "[reload] reload config file success.\n");
      reloadAckMsg.reloadOk = true;
      (void)cm_server_send_msg(con, 'S', (char*)(&reloadAckMsg), sizeof(CMToCtlReloadAck));
      g_inReload = false;
      return;
  }
  
  void ProcessCtlToCmExecDccCmdMsg(CM_Connection *con, ExecDdbCmdMsg *msg)
  {
      msg->cmdLine[DCC_CMD_MAX_LEN - 1] = '\0';
      errno_t rc;
      ExecDdbCmdAckMsg ackMsg;
  
      ackMsg.msgType = static_cast<int>(EXEC_DDB_COMMAND_ACK);
  
      if (g_inMaintainMode) {
          ackMsg.isSuccess = false;
          rc = strcpy_s(ackMsg.errMsg, ERR_MSG_LENGTH, "in maintain mode, can't do ddb cmd.");
          securec_check_errno(rc, (void)rc);
      } else {
          ackMsg.isSuccess = (DoDdbExecCmd(msg->cmdLine, ackMsg.output, &ackMsg.outputLen, ackMsg.errMsg,
              DCC_CMD_MAX_OUTPUT_LEN) == CM_SUCCESS);
      }
  
      (void)cm_server_send_msg(con, 'S', reinterpret_cast<char*>(&ackMsg), sizeof(ExecDdbCmdAckMsg));
  
      return;
  }
  