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:
@ -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 */
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user