* Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
*
* GR 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.
* -------------------------------------------------------------------------
*
* gr_nodes_list.c
*
*
* IDENTIFICATION
* src/params/gr_nodes_list.c
*
* -------------------------------------------------------------------------
*/
#include "gr_nodes_list.h"
#include "cm_log.h"
#include "cm_ip.h"
#include "cm_defs.h"
#include "cm_config.h"
#include "mes_interface.h"
#include "gr_param.h"
#include "gr_param_verify.h"
#include "gr_malloc.h"
#include "gr_errno.h"
#include "gr_log.h"
#include "gr_diskgroup.h"
status_t gr_extract_nodes_list(char *nodes_list_str, gr_nodes_list_t *nodes_list)
{
status_t status = cm_split_mes_urls(nodes_list->nodes, nodes_list->ports, nodes_list_str);
GR_RETURN_IFERR2(status, GR_THROW_ERROR(ERR_GR_INVALID_PARAM, "GR_NODES_LIST format is wrong"));
int32_t node_cnt = 0;
for (int i = 0; i < GR_MAX_INSTANCES; i++) {
if (nodes_list->ports[i] != 0) {
nodes_list->inst_map |= ((uint64)1 << i);
node_cnt++;
}
}
nodes_list->inst_cnt = (uint32_t)node_cnt;
LOG_RUN_INF("There are %d instances in incoming GR_NODES_LIST.", node_cnt);
return CM_SUCCESS;
}
static status_t gr_alloc_and_extract_inst_addrs(char *nodes_list_str, uint32_t *inst_cnt, mes_addr_t **inst_addrs)
{
gr_nodes_list_t nodes_list;
securec_check_ret(memset_sp(&nodes_list, sizeof(gr_nodes_list_t), 0, sizeof(gr_nodes_list_t)));
CM_RETURN_IFERR(gr_extract_nodes_list(nodes_list_str, &nodes_list));
size_t mes_addrs_size = nodes_list.inst_cnt * sizeof(mes_addr_t);
*inst_addrs = (mes_addr_t *)cm_malloc(mes_addrs_size);
if (*inst_addrs == NULL) {
GR_THROW_ERROR(ERR_GR_ALLOC_MEMORY, mes_addrs_size, "gr_extract_inst_addrs");
return CM_ERROR;
}
errno_t err = memset_sp(*inst_addrs, mes_addrs_size, 0, mes_addrs_size);
if (err != 0) {
CM_FREE_PTR(*inst_addrs);
CM_THROW_ERROR(ERR_SYSTEM_CALL, err);
return CM_ERROR;
}
mes_addr_t *inst_addr = &((*inst_addrs)[0]);
for (uint32_t i = 0; i < GR_MAX_INSTANCES; ++i) {
if (nodes_list.ports[i] != 0) {
inst_addr->inst_id = i;
err = strcpy_sp(inst_addr->ip, sizeof(inst_addr->ip), nodes_list.nodes[i]);
if (err != EOK) {
CM_THROW_ERROR(ERR_SYSTEM_CALL, err);
CM_FREE_PTR(*inst_addrs);
return CM_ERROR;
}
inst_addr->port = nodes_list.ports[i];
inst_addr->need_connect = CM_TRUE;
++inst_addr;
}
}
*inst_cnt = nodes_list.inst_cnt;
return CM_SUCCESS;
}
status_t gr_verify_nodes_list(void *lex, void *def)
{
const char *nodes_list_str = (const char *)lex;
size_t len = strlen(nodes_list_str);
for (size_t i = 0; i < len; ++i) {
if ((nodes_list_str[i] != '|') && (!(CM_IS_DIGIT(nodes_list_str[i]))) && (nodes_list_str[i] != '.') &&
(nodes_list_str[i] != ',') && (nodes_list_str[i] != ':')) {
GR_THROW_ERROR(ERR_GR_INVALID_PARAM, "GR_NODES_LIST contains invalid characters");
return CM_ERROR;
}
}
securec_check_ret(strcpy_sp(((gr_def_t *)def)->value, CM_PARAM_BUFFER_SIZE, nodes_list_str));
return CM_SUCCESS;
}
static status_t check_nodes_list_validity(uint32_t inst_cnt, const mes_addr_t *inst_addrs)
{
if (inst_cnt != g_inst_cfg->params.nodes_list.inst_cnt) {
GR_THROW_ERROR(
ERR_GR_INVALID_PARAM, "instance_ids in GR_NODES_LIST are not allowed to be changed dynamically");
return CM_ERROR;
}
for (uint32_t i = 0; i < inst_cnt; ++i) {
uint32_t inst_id = inst_addrs[i].inst_id;
if (inst_addrs[i].port == 0) {
GR_THROW_ERROR(ERR_GR_INVALID_PARAM, "IP ports in GR_NODES_LIST cannot be zero");
return CM_ERROR;
}
if (g_inst_cfg->params.nodes_list.ports[inst_id] == 0) {
GR_THROW_ERROR(
ERR_GR_INVALID_PARAM, "instance_ids in GR_NODES_LIST are not allowed to be changed dynamically");
return CM_ERROR;
}
}
LOG_RUN_INF("the user-inputted GR_NODES_LIST is valid.");
return CM_SUCCESS;
}
static status_t modify_ips_in_params(uint32_t inst_cnt, const mes_addr_t *inst_addrs)
{
for (uint32_t i = 0; i < inst_cnt; ++i) {
uint32_t inst_id = inst_addrs[i].inst_id;
g_inst_cfg->params.nodes_list.ports[inst_id] = inst_addrs[i].port;
if (strcmp(g_inst_cfg->params.nodes_list.nodes[inst_id], inst_addrs[i].ip) != 0) {
securec_check_ret(strcpy_sp(g_inst_cfg->params.nodes_list.nodes[inst_id], CM_MAX_IP_LEN, inst_addrs[i].ip));
}
}
return CM_SUCCESS;
}
status_t gr_update_local_nodes_list(char *nodes_list_str)
{
uint32_t inst_cnt = 0;
mes_addr_t *inst_addrs = NULL;
CM_RETURN_IFERR(gr_alloc_and_extract_inst_addrs(nodes_list_str, &inst_cnt, &inst_addrs));
CM_RETURN_IFERR(check_nodes_list_validity(inst_cnt, inst_addrs));
status_t status = mes_update_instance(inst_cnt, inst_addrs);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to update local mes connections.");
CM_FREE_PTR(inst_addrs);
return status;
}
CM_RETURN_IFERR(modify_ips_in_params(inst_cnt, inst_addrs));
LOG_RUN_INF("Success to update local mes connections.");
CM_FREE_PTR(inst_addrs);
return CM_SUCCESS;
}
status_t gr_notify_gr_nodes_list(void *se, void *item, char *value)
{
return gr_update_local_nodes_list(value);
}