blob: 62e964b601ac866abfb6a70774884e4b10bce2ef [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* etcdutils.c
* A simple lib for etcd config file parsing
*
*
* Portions Copyright (c) 2022-2023, Greenplum Inc.
*
*-------------------------------------------------------------------------
*/
#include "common/etcdutils.h"
/*
* split: function used to split a string with special separator.
* parameter src OUT
* parameter separator IN
* parameter dest OUT
* parameter num OUT
* return ture if configuration parse succeeded, otherwise retrun false.
*/
static bool
split(char *src, const char *separator, char **dest, int *num)
{
char *pNext;
int count = 0;
if (src == NULL || src[0] == '\0')
return false;
if (separator == NULL || separator[0] == '\0')
return false;
pNext = (char *)strtok(src,separator);
while (pNext != NULL)
{
*dest++ = pNext;
++count;
pNext = (char *)strtok(NULL,separator);
}
*num = count;
return true;
}
/*
* parseEtcdHostConfiguration: function used to parse etcdhost and etcdport inforamtion from a ETCD configure parameter.
* parameter gp_etcd_endpoint IN
* parameter gp_etcd_host OUT
* parameter gp_etcd_port OUT
* return ture if configuration parse succeeded, otherwise retrun false.
*/
static bool
parseEtcdHostConfiguration(const char *gp_etcd_endpoint, char *gp_etcd_host, int *gp_etcd_port)
{
char etcd_host[GP_ETCD_HOSTNAME_LEN];
char etcd_port[GP_ETCD_PORT_LEN];
memset(etcd_host, 0, GP_ETCD_HOSTNAME_LEN);
memset(etcd_port, 0, GP_ETCD_PORT_LEN);
Assert(gp_etcd_endpoint != NULL && (strcmp(gp_etcd_endpoint, "") != 0));
if (sscanf(gp_etcd_endpoint, "%[^':']:%s", etcd_host, etcd_port) == GPETCDCONFIGNUMATTR)
{
if (gp_etcd_host != NULL)
{
if (strlen(etcd_host) >= GP_ETCD_HOSTNAME_LEN-1)
return false;
strncpy(gp_etcd_host, etcd_host, GP_ETCD_HOSTNAME_LEN);
}
if (gp_etcd_port != NULL)
{
*gp_etcd_port = atoi(etcd_port);
}
}
else
return false;
return true;
}
/*
* generateGPSegConfigKey: function used to generate ETCD configuration key and endpoint information.
* parameter fts_dump_file_key OUT
* parameter gp_etcd_namespace IN
* parameter gp_etcd_account_id IN
* parameter gp_etcd_cluster_id IN
* parameter gp_etcd_endpoints OUT
* parameter etcd_endpoints OUT
* parameter etcd_endpoints_num OUT
* return ture if configuration parse succeeded, otherwise retrun false.
*/
bool
generateGPSegConfigKey(char *fts_dump_file_key, const char *gp_etcd_namespace, const char *gp_etcd_account_id,
const char *gp_etcd_cluster_id, char *gp_etcd_endpoints, etcdlib_endpoint_t *etcd_endpoints,
int *etcd_endpoints_num)
{
char *endpoints_list[GP_ETCD_ENDPOINTS_NUM] = {0};
etcdlib_endpoint_t *petcd_endpoints = etcd_endpoints;
bool ret = true;
int fts_dump_file_key_length = 0;
int etcd_port = 0;
char etcd_host[GP_ETCD_HOSTNAME_LEN];
memset(etcd_host, 0, GP_ETCD_HOSTNAME_LEN);
Assert(fts_dump_file_key != NULL);
Assert(gp_etcd_namespace != NULL && (strcmp(gp_etcd_namespace, "") != 0));
Assert(gp_etcd_account_id != NULL && (strcmp(gp_etcd_account_id, "") != 0));
Assert(gp_etcd_cluster_id != NULL && (strcmp(gp_etcd_cluster_id, "") != 0));
Assert(gp_etcd_endpoints != NULL && (strcmp(gp_etcd_endpoints, "") != 0));
fts_dump_file_key_length = snprintf(fts_dump_file_key, GP_ETCD_KEY_LEN, "%s/%s/%s/%s/%s", \
FTS_METADATA_DIR_PREFIX, gp_etcd_namespace, gp_etcd_account_id, gp_etcd_cluster_id, FTS_DUMP_FILE_KEY);
if (fts_dump_file_key_length == 0 || fts_dump_file_key_length > GP_ETCD_KEY_LEN)
return false;
if (fts_dump_file_key == NULL || fts_dump_file_key[0] == '\0')
return false;
ret = split(gp_etcd_endpoints, GP_ETCD_SEPERATOR, endpoints_list, etcd_endpoints_num);
if (!ret)
return false;
if (etcd_endpoints_num == 0 || *etcd_endpoints_num > GP_ETCD_ENDPOINTS_NUM)
return false;
for (int i = 0; i < (*etcd_endpoints_num); i++, petcd_endpoints++)
{
ret = parseEtcdHostConfiguration(endpoints_list[i], etcd_host, &etcd_port);
if (!ret || etcd_host[0] == '\0' || etcd_port == 0 )
return false;
petcd_endpoints->etcd_host = pstrdup(etcd_host);
petcd_endpoints->etcd_port = etcd_port;
etcd_port = 0;
}
return true;
}
/*
* generateGPFtsPromoteReadyKey: function used to generate FTS promote ready key.
* parameter fts_standby_promote_ready_key OUT
* parameter gp_etcd_namespace IN
* parameter gp_etcd_account_id IN
* parameter gp_etcd_cluster_id IN
* return ture if configuration parse succeeded, otherwise retrun false.
*/
void
generateGPFtsPromoteReadyKey(char *fts_standby_promote_ready_key, const char *gp_etcd_namespace, const char *gp_etcd_account_id, const char *gp_etcd_cluster_id)
{
Assert(fts_standby_promote_ready_key != NULL);
Assert((gp_etcd_namespace != NULL) && (strcmp(gp_etcd_namespace, "") != 0));
Assert(gp_etcd_account_id != NULL && (strcmp(gp_etcd_account_id, "") != 0));
Assert(gp_etcd_cluster_id != NULL && (strcmp(gp_etcd_cluster_id, "") != 0));
snprintf(fts_standby_promote_ready_key, GP_ETCD_KEY_LEN, "%s/%s/%s/%s/%s",
FTS_METADATA_DIR_PREFIX, gp_etcd_namespace, gp_etcd_account_id, gp_etcd_cluster_id, FTS_STANDBY_PROMOTE_READY_KEY);
}