1.Add verification when modifying synchronous_standby_names by using alter system set. 2.Fix bug when using gs_guc set synchronous_standby_names

This commit is contained in:
chenxiaobin
2021-03-13 21:32:18 +08:00
parent 5ccd8bf4c1
commit 8bd39447a7
6 changed files with 458 additions and 297 deletions

View File

@ -63,9 +63,6 @@
#include "securec_check.h"
#include "port.h"
#define STATIC_CONFIG_FILE "cluster_static_config"
#define DYNAMIC_DNROLE_FILE "cluster_dnrole_config"
#define MAX_VALUE_LEN 1024
#define MAX_PARAM_LEN 1024
#define CLUSTER_CONFIG_SUCCESS 0
@ -76,8 +73,6 @@
#define STD_FORMAT_ARG_POSITION 2
#define CASCADE_STANDBY_TYPE 3
extern char** cndn_param;
extern char** cmserver_param;
extern char** cmagent_param;
@ -93,7 +88,6 @@ extern int cmserver_param_number;
extern int cmagent_param_number;
extern int gtm_param_number;
extern int lc_param_number;
extern uint32 g_local_node_idx;
extern uint32 g_local_dn_idx;
extern char* g_current_data_dir;
@ -144,7 +138,6 @@ int get_all_cmserver_num();
int get_all_cmagent_num();
int get_all_cndn_num();
int get_all_gtm_num();
char* get_nodename_list_by_AZ(const char* AZName, const char* data_dir);
char* get_AZname_by_nodename(const char* nodename);
int find_gucoption_available(
const char** optlines, const char* opt_name, int* name_offset, int* name_len, int* value_offset, int* value_len);
@ -153,19 +146,11 @@ char** readfile(const char* path, int reserve_num_lines);
void freefile(char** lines);
extern bool get_env_value(const char* env_var, char* output_env_value, size_t env_var_value_len);
extern int checkPath(const char* fileName);
void* pg_malloc_memory(size_t size);
extern char* xstrdup(const char* s);
extern char* g_lcname;
extern char* g_local_node_name;
extern char* g_local_instance_path;
extern void check_env_value(const char* input_env_value);
typedef struct AZ_Info {
char* nodeName;
uint32 azPriority;
} AZList;
/*
******************************************************************************
Function : get_local_num_datanode
@ -487,161 +472,6 @@ char* get_AZname_by_nodename(const char* nodename)
}
return azName;
}
/*
******************************************************************************
Function : get_nodename_list_by_AZ
Description : get node name list by azName, don't include local node
Input : AZName -
Output : nodename list
Return : None
******************************************************************************
*/
char* get_nodename_list_by_AZ(const char* AZName, const char* data_dir)
{
uint32 nodeidx = 0;
uint32 count = 0;
uint32 len = 0;
uint32 i = 0;
uint32 j = 0;
AZList* azList = NULL;
uint32 tmpAZPriority = 0;
char* tmpNodeName = NULL;
size_t buflen = 1;
char* buffer = NULL;
int nRet = 0;
size_t curlen = 0;
// get the node number which in azName
for (nodeidx = 0; nodeidx < g_node_num; nodeidx++) {
if (strcmp(g_node[nodeidx].azName, AZName) == 0) {
count++;
}
}
// maybe the AZName is incorrect, so return null
if (count < 1) {
return NULL;
}
// init azList, i must less than count
azList = (AZList*)malloc(sizeof(AZList) * count);
if (NULL == azList) {
write_stderr("Failed: out of memory\n");
exit(1);
}
dataNodeInfo* dni = NULL;
{
uint32 idx = 0;
for (idx = 0; idx < g_currentNode->datanodeCount; idx++) {
dataNodeInfo* dni_tmp = &(g_currentNode->datanode[idx]);
if (strcmp(dni_tmp->datanodeLocalDataPath, data_dir) == 0) {
dni = dni_tmp;
break;
}
}
}
if (dni == NULL) {
write_stderr("Failed: cannot find the expected data dir\n");
exit(1);
}
for (nodeidx = 0, i = 0; nodeidx < g_node_num; nodeidx++) {
staticNodeConfig* dest = &(g_node[nodeidx]);
bool get_dn_in_same_shard = false;
if (nodeidx != g_local_node_idx && strcmp(dest->azName, AZName) == 0) {
uint32 l = 0;
for (l = 0; l < dest->datanodeCount && !get_dn_in_same_shard; l++) {
dataNodeInfo* dn = &(dest->datanode[l]);
int n = 0;
if (dn->datanodeId == 0)
continue;
if (dn->datanodeRole == CASCADE_STANDBY_TYPE)
continue;
for (n = 0; n < CM_MAX_DATANODE_STANDBY_NUM && !get_dn_in_same_shard; n++) {
peerDatanodeInfo* peer_datanode = &(dn->peerDatanodes[n]);
if (strlen(peer_datanode->datanodePeerHAIP[0]) == 0)
continue;
if (strcmp(peer_datanode->datanodePeerHAIP[0], dni->datanodeLocalHAIP[0]) == 0 &&
peer_datanode->datanodePeerHAPort == dni->datanodeLocalHAPort) {
char dn_instance_id[64] = {0};
int nRet = snprintf_s(dn_instance_id,
sizeof(dn_instance_id) / sizeof(char),
sizeof(dn_instance_id) / sizeof(char) - 1,
"dn_%4u",
dn->datanodeId);
securec_check_ss_c(nRet, "\0", "\0");
azList[i].nodeName = xstrdup(dn_instance_id);
azList[i].azPriority = dest->azPriority;
buflen += strlen(azList[i].nodeName) + 1;
i++;
get_dn_in_same_shard = true;
break;
}
}
}
}
}
// the real node name number
len = i;
// sort by azPriority asc
for (i = 0; len > 0 && i < len - 1; i++) {
for (j = 0; len > 0 && j < len - i - 1; j++) {
if (azList[j].azPriority > azList[j + 1].azPriority) {
// swap azPriority
tmpAZPriority = azList[j].azPriority;
azList[j].azPriority = azList[j + 1].azPriority;
azList[j + 1].azPriority = tmpAZPriority;
// swap nodename
tmpNodeName = xstrdup(azList[j].nodeName);
free(azList[j].nodeName);
azList[j].nodeName = NULL;
azList[j].nodeName = xstrdup(azList[j + 1].nodeName);
free(azList[j + 1].nodeName);
azList[j + 1].nodeName = NULL;
azList[j + 1].nodeName = xstrdup(tmpNodeName);
GS_FREE(tmpNodeName);
}
}
}
// Exclude the local node name and output the remaining information
buffer = (char*)malloc(sizeof(char) * (buflen + 1));
if (NULL == buffer) {
write_stderr("Failed: out of memory\n");
exit(1);
}
nRet = memset_s(buffer, buflen + 1, 0, buflen + 1);
securec_check_c(nRet, buffer, "\0");
for (i = 0; i < len; i++) {
if (strcmp(g_local_node_name, azList[i].nodeName) == 0) {
continue;
}
// the type like this: node1,node2,
nRet = snprintf_s(buffer + curlen, (buflen + 1 - curlen), (buflen - curlen), "%s,", azList[i].nodeName);
securec_check_ss_c(nRet, buffer, "\0");
curlen = curlen + nRet;
}
// skip the last character ','
if (strlen(buffer) >= 1) {
buffer[strlen(buffer) - 1] = '\0';
}
// free AZList
for (i = 0; i < len; i++) {
GS_FREE(azList[i].nodeName);
}
GS_FREE(azList);
return buffer;
}
/*
******************************************************************************
@ -767,50 +597,6 @@ int32 get_local_gtm_name(char* instancename)
return CLUSTER_CONFIG_ERROR;
}
int get_dynamic_dn_role(void)
{
char path[MAXPGPATH];
char gausshome[MAXPGPATH] = {0};
int nRet = 0;
FILE* fp = NULL;
char line_info[MAXPGPATH] = {0};
char* node_name = nullptr;
char* dn_role = nullptr;
uint32 nodeidx = 0;
struct stat statbuf;
if (!get_env_value("GAUSSHOME", gausshome, sizeof(gausshome) / sizeof(char)))
return 1;
check_env_value(gausshome);
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", gausshome, DYNAMIC_DNROLE_FILE);
securec_check_ss_c(nRet, "\0", "\0");
if (lstat(path, &statbuf) != 0) {
return 0;
}
fp = fopen(path, "r");
if (fp == NULL) {
write_stderr("ERROR: Failed to open file\"%s\"\n", path);
return 1;
}
while ((fgets(line_info, 1023 - 1, fp)) != NULL) {
line_info[(int)strlen(line_info) - 1] = '\0';
node_name = strtok_r(line_info, "=", &dn_role);
for (nodeidx = 0; node_name && (nodeidx < g_node_num); nodeidx++) {
if (strncmp(g_node[nodeidx].nodeName, node_name, strlen(node_name)) == 0) {
g_node[nodeidx].datanode[0].datanodeRole = (uint32)atoi(dn_role);
}
}
}
(void)fclose(fp);
return 0;
}
/*
******************************************************************************
Function : init_gauss_cluster_config
@ -849,6 +635,7 @@ int init_gauss_cluster_config(void)
securec_check_ss_c(nRet, "\0", "\0");
if (checkPath(path) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), path, strerror(errno));
return 1;
}
@ -933,6 +720,7 @@ int save_guc_para_info()
securec_check_ss_c(rc, "\0", "\0");
if (checkPath(guc_file) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), guc_file, strerror(errno));
return FAILURE;
}
/* maybe fail because of privilege */

View File

@ -40,7 +40,6 @@
const int CLUSTER_CONFIG_SUCCESS = 0;
const int CLUSTER_CONFIG_ERROR = 1;
#define LOOP_COUNT 3
#define MAX_REALPATH_LEN 4096
#define DOUBLE_PRECISE 0.000000001
#define MAX_HOST_NAME_LENGTH 255
#define LARGE_INSTANCE_NUM 2
@ -57,6 +56,17 @@ const int CLUSTER_CONFIG_ERROR = 1;
} \
} while (0)
#define PROCESS_STATUS(status) \
do { \
if (status == OUT_OF_MEMORY) { \
write_stderr("Failed: out of memory\n"); \
exit(1); \
} \
if (status == OPEN_FILE_ERROR) { \
write_stderr("Failed: cannot find the expected data dir\n"); \
exit(1); \
} \
} while (0)
const int GTM_INSTANCE_LEN = 3; // eg: one
const int CN_INSTANCE_LEN = 7; // eg: cn_5001
@ -105,10 +115,6 @@ extern gucInfo* g_real_gucInfo;
/* expect result */
extern gucInfo* g_expect_gucInfo;
/* the local node name and idx */
extern uint32 g_local_node_idx;
extern char* g_local_node_name;
extern char gucconf_file[MAXPGPATH];
extern int config_param_number;
extern char** config_param;
@ -134,7 +140,6 @@ extern char** cmagent_guc_info;
extern char** gtm_guc_info;
extern char** lc_guc_info;
extern const char* progname;
extern char* g_lcname;
/* status which perform remote connection */
extern bool g_remote_connection_signal;
@ -307,7 +312,6 @@ int get_all_cmserver_num();
int get_all_cmagent_num();
int get_all_cndn_num();
int get_all_gtm_num();
char* get_nodename_list_by_AZ(char* AZName, const char* data_dir);
char* get_AZ_value(const char* value, const char* data_dir);
char* get_AZname_by_nodename(char* nodename);
@ -1235,56 +1239,6 @@ bool get_env_value(const char* env_var, char* output_env_value, size_t env_var_v
return true;
}
/*
******************************************************************************
Function : checkPath
Description :
Input : fileName
Output : None
Return : None
******************************************************************************
*/
int checkPath(const char* fileName)
{
char* retVal = NULL;
char realFileName[MAX_REALPATH_LEN + 1] = {0};
retVal = realpath(fileName, realFileName);
if (NULL == retVal) {
write_stderr(_("realpath(%s) failed : %s!\n"), fileName, gs_strerror(errno));
return -1;
}
return 0;
}
static bool has_static_config()
{
char path[MAXPGPATH];
char gausshome[MAXPGPATH] = {0};
int nRet = 0;
struct stat statbuf;
if (!get_env_value("GAUSSHOME", gausshome, sizeof(gausshome) / sizeof(char)))
return false;
check_env_value(gausshome);
if (NULL != g_lcname) {
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s.%s", gausshome, g_lcname, STATIC_CONFIG_FILE);
} else {
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", gausshome, STATIC_CONFIG_FILE);
}
securec_check_ss_c(nRet, "\0", "\0");
if (checkPath(path) != 0) {
return false;
}
if (lstat(path, &statbuf) == 0) {
return true;
}
return false;
}
/*
******************************************************************************
Function : process_cluster_guc_option
@ -1536,6 +1490,7 @@ char* parse_AZ_result(char* AZStr, const char* data_dir)
const int az1_index = 0;
const int az2_index = 1;
const int az3_index = 2;
int resultStatus = 0;
// init tmp az string, array which storage az string
nRet = memset_s(tmp, MAX_VALUE_LEN, '\0', MAX_VALUE_LEN);
@ -1635,7 +1590,8 @@ char* parse_AZ_result(char* AZStr, const char* data_dir)
array[1] = NULL;
array[2] = NULL;
array[0] = get_nodename_list_by_AZ(azList[0], data_dir);
resultStatus = get_nodename_list_by_AZ(azList[0], data_dir, &array[0]);
PROCESS_STATUS(resultStatus);
// input az name is incorrect
if (NULL == array[0]) {
(void)write_log("ERROR: The AZ name \"%s\" does not be found on cluster. please makesure the AZ string "
@ -1647,7 +1603,8 @@ char* parse_AZ_result(char* AZStr, const char* data_dir)
len += strlen(array[0]) + 1;
if ('\0' != azList[1][0]) {
array[1] = get_nodename_list_by_AZ(azList[1], data_dir);
resultStatus = get_nodename_list_by_AZ(azList[1], data_dir, &array[1]);
PROCESS_STATUS(resultStatus);
// input az name is incorrect
if (NULL == array[1]) {
(void)write_log("ERROR: The AZ name \"%s\" does not be found on cluster. please makesure the AZ string "
@ -1660,7 +1617,8 @@ char* parse_AZ_result(char* AZStr, const char* data_dir)
}
if ('\0' != azList[2][0]) {
array[2] = get_nodename_list_by_AZ(azList[2], data_dir);
resultStatus = get_nodename_list_by_AZ(azList[2], data_dir, &array[2]);
PROCESS_STATUS(resultStatus);
// input az name is incorrect
if (NULL == array[2]) {
(void)write_log("ERROR: The AZ name \"%s\" does not be found on cluster. please makesure the AZ string "
@ -1717,11 +1675,7 @@ int get_nodename_number_from_nodelist(const char* namelist)
{
char* ptr = NULL;
char* outer_ptr = NULL;
#ifdef ENABLE_MULTIPLE_NODES
char delims[] = ",";
#else
char delims[] = "_";
#endif
size_t len = 0;
int count = 0;
char* buffer = NULL;
@ -1892,6 +1846,7 @@ char* get_AZ_value(const char* value, const char* data_dir)
char delims[] = ",";
char* vptr = NULL;
char emptyvalue[] = "''";
int resultStatus = 0;
bool isNodeName = false;
if (az1 != NULL) {
@ -1991,32 +1946,29 @@ char* get_AZ_value(const char* value, const char* data_dir)
if (NULL == nodenameList) {
// try dn
nodenameList = get_nodename_list_by_AZ(az1, data_dir);
resultStatus = get_nodename_list_by_AZ(az1, data_dir, &nodenameList);
PROCESS_STATUS(resultStatus);
if (nodenameList == NULL) {
goto failed;
}
nodenameList[strlen(nodenameList)] = ',';
len = strlen(q);
len = strlen(q) + 1;
s = (char *)pg_malloc_zero(len * sizeof(char));
nRet = snprintf_s(s, len + 1, len, "%s", q);
nRet = snprintf_s(s, len, len - 1, "%s", q);
securec_check_ss_c(nRet, s, "\0");
vptr = strtok_r(s, delims, &vouter_ptr);
while (vptr != NULL) {
p = vptr;
int len_p = strlen(p) + 1;
char *temp = (char *)pg_malloc_zero(len_p * sizeof(char));
nRet = snprintf_s(temp, len_p + 1, len_p, "%s,", p);
securec_check_ss_c(nRet, temp, "\0");
if (strstr(nodenameList, temp) == NULL) {
if (!contain_nodename(nodenameList, p)) {
goto failed;
}
vptr = strtok_r(NULL, delims, &vouter_ptr);
}
GS_FREE(s);
len = strlen(nodenameList);
nRet = snprintf_s(nodenameList, len + 1, len, "%s", q);
securec_check_ss_c(nRet, nodenameList, "\0");
} else if ('\0' == nodenameList[0]) {
@ -2180,13 +2132,17 @@ void do_command_in_local_node(int type, char* indatadir)
check_env_value(datadir);
}
/* process the PGDATA / GTMDATA */
(void)checkPath(datadir);
if (checkPath(datadir) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), datadir, strerror(errno));
}
save_expect_instance_info(datadir);
if (FAILURE == do_local_guc_command(type, datadir))
return;
} else {
/* process the -D option */
(void)checkPath(indatadir);
if (checkPath(indatadir) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), indatadir, strerror(errno));
}
save_expect_instance_info(indatadir);
if (FAILURE == do_local_guc_command(type, indatadir))
return;

View File

@ -55,6 +55,7 @@
#include "bin/elog.h"
#include "openssl/rand.h"
#include "common/config/cm_config.h"
#if defined(__CYGWIN__)
#include <sys/cygwin.h>
#include <windows.h>
@ -218,8 +219,6 @@ char* g_prefix = NULL;
// whether change the value of synchronous_standby_names
bool g_need_changed = true;
char* g_local_instance_path = NULL;
// the logical cluster name
char* g_lcname = NULL;
typedef struct {
char** nodename_array;
@ -244,10 +243,7 @@ gucInfo* g_real_gucInfo = NULL;
/* expect result */
gucInfo* g_expect_gucInfo = NULL;
/* the local node name and idx */
uint32 g_local_node_idx = 0;
uint32 g_local_dn_idx = 0;
char* g_local_node_name = NULL;
char* g_current_data_dir = NULL;
void* pg_malloc(size_t size);
@ -318,7 +314,6 @@ bool allocate_memory_list();
extern int init_gauss_cluster_config(void);
extern char* get_AZ_value(char* value, const char* data_dir);
extern bool get_hostname_or_ip(char* out_name, size_t name_len);
extern int checkPath(const char* fileName);
#ifdef __cplusplus
}
@ -390,6 +385,7 @@ bool allocate_memory_list()
securec_check_ss_c(rc, "\0", "\0");
if (checkPath(guc_file) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), guc_file, strerror(errno));
return false;
}
/* maybe fail because of privilege*/
@ -797,7 +793,9 @@ ErrCode get_file_lock(const char* path, FileLock* filelock)
}
ret = strcpy_s(newpath, sizeof(newpath), path);
canonicalize_path(newpath);
(void)checkPath(newpath);
if (checkPath(newpath) != 0) {
write_stderr(_("realpath(%s) failed : %s!\n"), newpath, strerror(errno));
}
if (lstat(newpath, &statbuf) != 0) {
fp = fopen(newpath, PG_BINARY_W);
@ -2254,7 +2252,7 @@ int main(int argc, char** argv)
config_value = ((char**)pg_malloc_zero(arraysize * sizeof(char*)));
}
if (false == allocate_memory_list()) {
write_stderr(_("ERROR:: Failed to allocate memory to list.\n"));
write_stderr(_("ERROR: Failed to allocate memory to list.\n"));
exit(1);
}

View File

@ -61,6 +61,7 @@
#include "utils/builtins.h"
#include "utils/ps_status.h"
#include "utils/distribute_test.h"
#include "common/config/cm_config.h"
/*
* To control whether a master configured with synchronous commit is
@ -1418,6 +1419,60 @@ static bool SyncRepQueueIsOrderedByLSN(int mode)
}
#endif
/*
* Obtain cluster information from cluster_static_config.
*/
int init_gauss_cluster_config(void)
{
char path[MAXPGPATH] = {0};
int err_no = 0;
int nRet = 0;
int status = 0;
uint32 nodeidx = 0;
struct stat statbuf {};
char* gausshome = gs_getenv_r("GAUSSHOME");
check_backend_env(gausshome);
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", gausshome, STATIC_CONFIG_FILE);
securec_check_ss_c(nRet, "\0", "\0");
if (lstat(path, &statbuf) != 0) {
return 1;
}
status = read_config_file(path, &err_no);
if (0 != status) {
return 1;
}
if (g_nodeHeader.node <= 0) {
free(g_node);
return 1;
}
for (nodeidx = 0; nodeidx < g_node_num; nodeidx++) {
if (g_node[nodeidx].node == g_nodeHeader.node) {
g_currentNode = &g_node[nodeidx];
break;
}
}
if (NULL == g_currentNode) {
free(g_node);
return 1;
}
if (get_dynamic_dn_role() != 0) {
// failed to get dynamic dn role
free(g_node);
return 1;
}
return 0;
}
/*
* ===========================================================
* Synchronous Replication functions executed by any process
@ -1431,6 +1486,12 @@ bool check_synchronous_standby_names(char **newval, void **extra, GucSource sour
int parse_rc;
SyncRepConfigData *pconf = NULL;
syncrep_scanner_yyscan_t yyscanner;
char* nodenameList = NULL;
char* az1 = g_instance.attr.attr_storage.available_zone;
char* data_dir = t_thrd.proc_cxt.DataDir;
uint32 idx;
char* p = NULL;
int resultStatus;
/* Reset communication variables to ensure a fresh start */
t_thrd.syncrepgram_cxt.syncrep_parse_result = NULL;
@ -1456,6 +1517,47 @@ bool check_synchronous_standby_names(char **newval, void **extra, GucSource sour
t_thrd.syncrepgram_cxt.syncrep_parse_result->config_size);
securec_check(rc, "", "");
if (strcmp(pconf->member_names, "*") == 0) {
goto pass;
}
if (pconf->num_sync > pconf->nmembers) {
// The sync number must less or equals to the number of standby node names.
return false;
}
/* get current cluster information from cluster_staic_config */
if (strcmp(u_sess->attr.attr_common.application_name, "gsql") == 0 && has_static_config()
&& 0 == init_gauss_cluster_config()) {
for (idx = 0; idx < g_node_num; idx++) {
if (g_currentNode->node == g_node[idx].node) {
g_local_node_idx = idx;
break;
}
}
} else {
goto pass;
}
g_local_node_name = g_node[g_local_node_idx].nodeName;
resultStatus = get_nodename_list_by_AZ(az1, data_dir, &nodenameList);
if (nodenameList == NULL) {
return false;
}
p = pconf->member_names;
for (int i = 1; i <= pconf->nmembers; i++) {
if (!contain_nodename(nodenameList, p)) {
// The value of pamameter synchronous_standby_names is incorrect.
free(nodenameList);
return false;
}
p += strlen(p) + 1;
}
free(nodenameList);
pass:
*extra = (void *)pconf;
if (t_thrd.syncrepgram_cxt.syncrep_parse_result) {
pfree(t_thrd.syncrepgram_cxt.syncrep_parse_result);

View File

@ -132,6 +132,12 @@
#define ETCD_KEY_LENGTH 1024
#define ETCD_VLAUE_LENGTH 1024
#define CASCADE_STANDBY_TYPE 3
#define STATIC_CONFIG_FILE "cluster_static_config"
#define DYNAMIC_DNROLE_FILE "cluster_dnrole_config"
/* the max real path length in linux is 4096, adapt this for realpath func */
#define MAX_REALPATH_LEN 4096
/* az_Priorities, only init the values when load config file */
const uint32 g_az_invalid = 0;
extern uint32 g_az_master;
@ -378,6 +384,11 @@ typedef struct logicClusterList {
logicClusterInfo lcInfoArray[LOGIC_CLUSTER_NUMBER];
} logicClusterList;
typedef struct AZ_Info {
char* nodeName;
uint32 azPriority;
} AZList;
extern staticConfigHeader g_nodeHeader;
extern staticNodeConfig* g_node;
extern staticNodeConfig* g_currentNode;
@ -407,6 +418,9 @@ extern bool logic_cluster_query;
extern bool logic_cluster_restart;
extern uint32 g_datanodeid;
extern char* g_logicClusterName;
extern uint32 g_local_node_idx;
extern char* g_local_node_name;
extern char* g_lcname;
extern int read_single_file(const char *file_path, int *err_no, uint32 nodeId, const char *dataPath);
extern int read_config_file(const char* file_path, int* err_no);
@ -419,5 +433,10 @@ extern int node_index_Comparator(const void* arg1, const void* arg2);
extern void set_cm_read_flag(bool falg);
extern char* getAZNamebyPriority(uint32 azPriority);
extern int cmconfig_getenv(const char* env_var, char* output_env_value, uint32 env_value_len);
extern bool contain_nodename(const char* namelist, const char* name);
extern int get_dynamic_dn_role(void);
extern int get_nodename_list_by_AZ(const char* AZName, const char* data_dir, char** nodeNameList);
extern int checkPath(const char* fileName);
extern bool has_static_config();
#endif

View File

@ -74,6 +74,13 @@ uint32 max_gtmpath_len = 0;
uint32 max_etcdpath_len = 0;
uint32 max_cmpath_len = 0;
/* the local node name and idx */
uint32 g_local_node_idx = 0;
char* g_local_node_name = NULL;
// the logical cluster name
char* g_lcname = NULL;
/* for datanode alarm */
uint32 g_datanodeid = 0;
char *g_logicClusterName = NULL;
@ -1312,3 +1319,294 @@ int read_single_file(const char *file_path, int *err_no, uint32 nodeId, const ch
return 0;
}
bool contain_nodename(const char* namelist, const char* name)
{
char* ptr = NULL;
char* outer_ptr = NULL;
char delims[] = ",";
size_t len = 0;
char* buffer = NULL;
int nRet = 0;
len = strlen(namelist) + 1;
buffer = (char*)calloc(len, sizeof(char));
if (buffer == NULL) {
fprintf(stderr, "Cannot alloc memory\n");
return false;
}
nRet = snprintf_s(buffer, len, len - 1, "%s", namelist);
securec_check_ss_c(nRet, buffer, "\0");
ptr = strtok_r(buffer, delims, &outer_ptr);
while (NULL != ptr) {
if (strcmp(ptr, name) == 0) {
free(buffer);
buffer = NULL;
return true;
}
ptr = strtok_r(NULL, delims, &outer_ptr);
}
free(buffer);
buffer = NULL;
return false;
}
int get_dynamic_dn_role(void)
{
char path[MAXPGPATH];
int nRet = 0;
FILE* fp = NULL;
char line_info[MAXPGPATH] = {0};
char* node_name = NULL;
char* dn_role = NULL;
uint32 nodeidx = 0;
struct stat statbuf;
char* gausshome = gs_getenv_r("GAUSSHOME");
check_input_for_security(gausshome);
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", gausshome, DYNAMIC_DNROLE_FILE);
securec_check_ss_c(nRet, "\0", "\0");
if (lstat(path, &statbuf) != 0) {
return 0;
}
fp = fopen(path, "r");
if (fp == NULL) {
return OPEN_FILE_ERROR;
}
while ((fgets(line_info, 1023 - 1, fp)) != NULL) {
line_info[(int)strlen(line_info) - 1] = '\0';
node_name = strtok_r(line_info, "=", &dn_role);
for (nodeidx = 0; node_name && (nodeidx < g_node_num); nodeidx++) {
if (strncmp(g_node[nodeidx].nodeName, node_name, strlen(node_name)) == 0){
g_node[nodeidx].datanode[0].datanodeRole = (uint32)atoi(dn_role);
break;
}
}
}
(void)fclose(fp);
return 0;
}
/*
******************************************************************************
Function : get_nodename_list_by_AZ
Description : get node name list by azName, don't include local node
Input : AZName -
Output : nodename list
Return : None
******************************************************************************
*/
int get_nodename_list_by_AZ(const char* AZName, const char* data_dir, char** nodeNameList)
{
uint32 nodeidx = 0;
uint32 count = 0;
uint32 len = 0;
uint32 i = 0;
uint32 j = 0;
AZList* azList = NULL;
uint32 tmpAZPriority = 0;
char* tmpNodeName = NULL;
size_t buflen = 1;
char* buffer = NULL;
int nRet = 0;
size_t curlen = 0;
// get the node number which in azName
for (nodeidx = 0; nodeidx < g_node_num; nodeidx++) {
if (strcmp(g_node[nodeidx].azName, AZName) == 0) {
count++;
}
}
// maybe the AZName is incorrect, so return null
if (count < 1) {
return 0;
}
// init azList, i must less than count
azList = (AZList*)malloc(sizeof(AZList) * count);
if (NULL == azList) {
return OUT_OF_MEMORY;
}
dataNodeInfo* dni = NULL;
{
uint32 idx = 0;
for (idx = 0; idx < g_currentNode->datanodeCount; idx++) {
dataNodeInfo* dni_tmp = &(g_currentNode->datanode[idx]);
if (strcmp(dni_tmp->datanodeLocalDataPath, data_dir) == 0) {
dni = dni_tmp;
break;
}
}
}
if (dni == NULL) {
free(azList);
azList = NULL;
return OPEN_FILE_ERROR;
}
for (nodeidx = 0, i = 0; nodeidx < g_node_num; nodeidx++) {
staticNodeConfig* dest = &(g_node[nodeidx]);
bool get_dn_in_same_shard = false;
if (nodeidx != g_local_node_idx && strcmp(dest->azName, AZName) == 0) {
uint32 l = 0;
for (l = 0; l < dest->datanodeCount && !get_dn_in_same_shard; l++) {
dataNodeInfo* dn = &(dest->datanode[l]);
int n = 0;
if (dn->datanodeId == 0)
continue;
if (dn->datanodeRole == CASCADE_STANDBY_TYPE)
continue;
for (n = 0; n < CM_MAX_DATANODE_STANDBY_NUM && !get_dn_in_same_shard; n++) {
peerDatanodeInfo* peer_datanode = &(dn->peerDatanodes[n]);
if (strlen(peer_datanode->datanodePeerHAIP[0]) == 0)
continue;
if (strcmp(peer_datanode->datanodePeerHAIP[0], dni->datanodeLocalHAIP[0]) == 0 &&
peer_datanode->datanodePeerHAPort == dni->datanodeLocalHAPort) {
char dn_instance_id[64] = {0};
int nRet = snprintf_s(dn_instance_id,
sizeof(dn_instance_id) / sizeof(char),
sizeof(dn_instance_id) / sizeof(char) - 1,
"dn_%4u",
dn->datanodeId);
securec_check_ss_c(nRet, "\0", "\0");
azList[i].nodeName = strdup(dn_instance_id);
azList[i].azPriority = dest->azPriority;
buflen += strlen(azList[i].nodeName) + 1;
i++;
get_dn_in_same_shard = true;
break;
}
}
}
}
}
// the real node name number
len = i;
// sort by azPriority asc
for (i = 0; len > 0 && i < len - 1; i++) {
for (j = 0; len > 0 && j < len - i - 1; j++) {
if (azList[j].azPriority > azList[j + 1].azPriority) {
// swap azPriority
tmpAZPriority = azList[j].azPriority;
azList[j].azPriority = azList[j + 1].azPriority;
azList[j + 1].azPriority = tmpAZPriority;
// swap nodename
tmpNodeName = strdup(azList[j].nodeName);
free(azList[j].nodeName);
azList[j].nodeName = NULL;
azList[j].nodeName = strdup(azList[j + 1].nodeName);
free(azList[j + 1].nodeName);
azList[j + 1].nodeName = NULL;
azList[j + 1].nodeName = strdup(tmpNodeName);
free(tmpNodeName);
tmpNodeName = NULL;
}
}
}
// Exclude the local node name and output the remaining information
buffer = (char*)malloc(sizeof(char) * (buflen + 1));
if (NULL == buffer) {
// free AZList
for (i = 0; i < len; i++) {
if (azList[i].nodeName != NULL) {
free(azList[i].nodeName);
azList[i].nodeName = NULL;
}
}
free(azList);
azList = NULL;
return OUT_OF_MEMORY;
}
nRet = memset_s(buffer, buflen + 1, 0, buflen + 1);
securec_check_c(nRet, buffer, "\0");
for (i = 0; i < len; i++) {
if (strcmp(g_local_node_name, azList[i].nodeName) == 0) {
continue;
}
// the type like this: node1,node2,
nRet = snprintf_s(buffer + curlen, (buflen + 1 - curlen), (buflen - curlen), "%s,", azList[i].nodeName);
securec_check_ss_c(nRet, buffer, "\0");
curlen = curlen + nRet;
}
// skip the last character ','
if (strlen(buffer) >= 1) {
buffer[strlen(buffer) - 1] = '\0';
}
// free AZList
for (i = 0; i < len; i++) {
if (azList[i].nodeName != NULL) {
free(azList[i].nodeName);
azList[i].nodeName = NULL;
}
}
free(azList);
azList = NULL;
*nodeNameList = buffer;
return 0;
}
/*
******************************************************************************
Function : checkPath
Description :
Input : fileName
Output : None
Return : None
******************************************************************************
*/
int checkPath(const char* fileName)
{
char* retVal = NULL;
char realFileName[MAX_REALPATH_LEN + 1] = {0};
retVal = realpath(fileName, realFileName);
if (NULL == retVal) {
return -1;
}
return 0;
}
bool has_static_config()
{
char path[MAXPGPATH];
int nRet = 0;
struct stat statbuf;
char* gausshome = gs_getenv_r("GAUSSHOME");
check_input_for_security(gausshome);
if (NULL != g_lcname) {
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s.%s", gausshome, g_lcname, STATIC_CONFIG_FILE);
} else {
nRet = snprintf_s(path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", gausshome, STATIC_CONFIG_FILE);
}
securec_check_ss_c(nRet, "\0", "\0");
if (checkPath(path) != 0) {
return false;
}
if (lstat(path, &statbuf) == 0) {
return true;
}
return false;
}