From 8bd39447a772e29fed90f22dc4d003392dcad6c2 Mon Sep 17 00:00:00 2001 From: chenxiaobin <1025221611@qq.com> Date: Sat, 13 Mar 2021 21:32:18 +0800 Subject: [PATCH] 1.Add verification when modifying synchronous_standby_names by using alter system set. 2.Fix bug when using gs_guc set synchronous_standby_names --- src/bin/gs_guc/cluster_config.cpp | 216 +------------ src/bin/gs_guc/cluster_guc.cpp | 106 ++----- src/bin/gs_guc/pg_guc.cpp | 14 +- .../storage/replication/syncrep.cpp | 102 ++++++ src/include/common/config/cm_config.h | 19 ++ src/lib/config/cm_config.cpp | 298 ++++++++++++++++++ 6 files changed, 458 insertions(+), 297 deletions(-) diff --git a/src/bin/gs_guc/cluster_config.cpp b/src/bin/gs_guc/cluster_config.cpp index dc800cbc5..8341da5d9 100644 --- a/src/bin/gs_guc/cluster_config.cpp +++ b/src/bin/gs_guc/cluster_config.cpp @@ -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 */ diff --git a/src/bin/gs_guc/cluster_guc.cpp b/src/bin/gs_guc/cluster_guc.cpp index f02ef2c87..7d995c252 100644 --- a/src/bin/gs_guc/cluster_guc.cpp +++ b/src/bin/gs_guc/cluster_guc.cpp @@ -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; diff --git a/src/bin/gs_guc/pg_guc.cpp b/src/bin/gs_guc/pg_guc.cpp index 5e22f8b80..9a439b092 100644 --- a/src/bin/gs_guc/pg_guc.cpp +++ b/src/bin/gs_guc/pg_guc.cpp @@ -55,6 +55,7 @@ #include "bin/elog.h" #include "openssl/rand.h" +#include "common/config/cm_config.h" #if defined(__CYGWIN__) #include #include @@ -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); } diff --git a/src/gausskernel/storage/replication/syncrep.cpp b/src/gausskernel/storage/replication/syncrep.cpp index 912c826ce..a9c6c1ecc 100644 --- a/src/gausskernel/storage/replication/syncrep.cpp +++ b/src/gausskernel/storage/replication/syncrep.cpp @@ -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); diff --git a/src/include/common/config/cm_config.h b/src/include/common/config/cm_config.h index beb5c1fa1..b26ca991e 100644 --- a/src/include/common/config/cm_config.h +++ b/src/include/common/config/cm_config.h @@ -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 diff --git a/src/lib/config/cm_config.cpp b/src/lib/config/cm_config.cpp index 330f1c52c..30333aec1 100644 --- a/src/lib/config/cm_config.cpp +++ b/src/lib/config/cm_config.cpp @@ -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; +}