add files: server_id_func.[hc]

pull/37/head
YuQing 2020-02-14 21:21:36 +08:00
parent 5d3c3c576c
commit 7459f7ded4
8 changed files with 1016 additions and 16 deletions

View File

@ -1,5 +1,5 @@
Version 1.44 2020-02-12
Version 1.44 2020-02-14
* add test file src/tests/test_pthread_lock.c
* add uniq_skiplist.[hc]
* add function split_string_ex
@ -8,6 +8,7 @@ Version 1.44 2020-02-12
* add function fc_memrchr
* add function is_network_error
* add function fast_mpool_log_stats
* add files: server_id_func.[hc]
Version 1.43 2019-12-25
* replace function call system to getExecResult,

View File

@ -15,7 +15,7 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \
system_info.lo fast_blocked_queue.lo id_generator.lo \
char_converter.lo char_convert_loader.lo common_blocked_queue.lo \
multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \
json_parser.lo buffered_file_writer.lo
json_parser.lo buffered_file_writer.lo server_id_func.lo
FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
logger.o sockopt.o base64.o sched_thread.o \
@ -27,7 +27,7 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
system_info.o fast_blocked_queue.o id_generator.o \
char_converter.o char_convert_loader.o common_blocked_queue.o \
multi_socket_client.o skiplist_set.o uniq_skiplist.o \
json_parser.o buffered_file_writer.o
json_parser.o buffered_file_writer.o server_id_func.lo
HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
shared_func.h pthread_func.h ini_file_reader.h _os_define.h \
@ -40,7 +40,7 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
php7_ext_wrapper.h id_generator.h char_converter.h \
char_convert_loader.h common_blocked_queue.h \
multi_socket_client.h skiplist_set.h uniq_skiplist.h \
fc_list.h json_parser.h buffered_file_writer.h
fc_list.h json_parser.h buffered_file_writer.h server_id_func.h
ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS)

View File

@ -2968,16 +2968,18 @@ void iniPrintItems(IniContext *pContext)
hash_walk(&pContext->sections, iniPrintHashData, NULL);
}
struct section_walk_arg {
struct section_name_walk_arg {
IniSectionInfo *sections;
IniSectionNameFilterFunc filter_func;
void *args;
int count;
int size;
};
static int iniSectionWalkCallback(const int index, const HashData *data,
void *args)
static int iniSectionNameWalkCallback(const int index,
const HashData *data, void *args)
{
struct section_walk_arg *walk_arg;
struct section_name_walk_arg *walk_arg;
IniSection *pSection;
char *section_name;
int section_len;
@ -2988,7 +2990,13 @@ static int iniSectionWalkCallback(const int index, const HashData *data,
return 0;
}
walk_arg = (struct section_walk_arg *)args;
walk_arg = (struct section_name_walk_arg *)args;
if (walk_arg->filter_func != NULL && !walk_arg->
filter_func(data->key, data->key_len, walk_arg->args))
{
return 0;
}
if (walk_arg->count >= walk_arg->size)
{
return ENOSPC;
@ -3009,20 +3017,101 @@ static int iniSectionWalkCallback(const int index, const HashData *data,
return 0;
}
int iniGetSectionNames(IniContext *pContext, IniSectionInfo *sections,
int iniGetSectionNamesEx(IniContext *pContext, IniSectionNameFilterFunc
filter_func, void *args, IniSectionInfo *sections,
const int max_size, int *nCount)
{
struct section_walk_arg walk_arg;
struct section_name_walk_arg walk_arg;
int result;
walk_arg.sections = sections;
walk_arg.count = 0;
walk_arg.filter_func = filter_func;
walk_arg.args = args;
walk_arg.size = max_size;
result = hash_walk(&pContext->sections, iniSectionWalkCallback, &walk_arg);
walk_arg.count = 0;
result = hash_walk(&pContext->sections, iniSectionNameWalkCallback,
&walk_arg);
*nCount = walk_arg.count;
return result;
}
int iniGetSectionNames(IniContext *pContext, IniSectionInfo *sections,
const int max_size, int *nCount)
{
return iniGetSectionNamesEx(pContext, NULL, NULL,
sections, max_size, nCount);
}
static bool iniSectionNameFilterByPrefix(const char *section_name,
const int name_len, void *args)
{
string_t *prefix;
prefix = (string_t *)args;
if (name_len < prefix->len) {
return false;
}
return memcmp(section_name, prefix->str, prefix->len) == 0;
}
int iniGetSectionNamesByPrefix(IniContext *pContext, const char *szPrefix,
IniSectionInfo *sections, const int max_size, int *nCount)
{
string_t prefix;
FC_SET_STRING(prefix, (char *)szPrefix);
return iniGetSectionNamesEx(pContext, iniSectionNameFilterByPrefix,
&prefix, sections, max_size, nCount);
}
struct section_count_walk_arg {
IniSectionNameFilterFunc filter_func;
void *args;
int count;
};
static int iniSectionCountWalkCallback(const int index,
const HashData *data, void *args)
{
struct section_count_walk_arg *walk_arg;
IniSection *pSection;
pSection = (IniSection *)data->value;
if (pSection == NULL)
{
return 0;
}
walk_arg = (struct section_count_walk_arg *)args;
if (walk_arg->filter_func == NULL || walk_arg->
filter_func(data->key, data->key_len, walk_arg->args))
{
walk_arg->count++;
}
return 0;
}
int iniGetSectionCountEx(IniContext *pContext, IniSectionNameFilterFunc
filter_func, void *args)
{
struct section_count_walk_arg walk_arg;
walk_arg.filter_func = filter_func;
walk_arg.args = args;
walk_arg.count = 0;
hash_walk(&pContext->sections, iniSectionCountWalkCallback, &walk_arg);
return walk_arg.count;
}
int iniGetSectionCountByPrefix(IniContext *pContext, const char *szPrefix)
{
string_t prefix;
FC_SET_STRING(prefix, (char *)szPrefix);
return iniGetSectionCountEx(pContext, iniSectionNameFilterByPrefix, &prefix);
}
IniItem *iniGetSectionItems(const char *szSectionName, IniContext *pContext,
int *nCount)
{

View File

@ -16,8 +16,8 @@
#include "common_define.h"
#include "hash.h"
#define FAST_INI_ITEM_NAME_LEN 64
#define FAST_INI_ITEM_VALUE_LEN 256
#define FAST_INI_ITEM_NAME_LEN 63
#define FAST_INI_ITEM_VALUE_LEN 255
#define FAST_INI_ITEM_NAME_SIZE (FAST_INI_ITEM_NAME_LEN + 1)
#define FAST_INI_ITEM_VALUE_SIZE (FAST_INI_ITEM_VALUE_LEN + 1)
@ -29,6 +29,9 @@
#define FAST_INI_FLAGS_NONE 0
#define FAST_INI_FLAGS_SHELL_EXECUTE 1
typedef bool (*IniSectionNameFilterFunc)(const char *section_name,
const int name_len, void *args);
typedef struct ini_item
{
char name[FAST_INI_ITEM_NAME_SIZE];
@ -244,7 +247,7 @@ static inline const char *iniGetConfigPath(IniContext *pContext)
return pContext->config_path;
}
/** return the items of global section
/** return the section names
* parameters:
* pContext: the ini context
* sections: the section array
@ -255,6 +258,60 @@ static inline const char *iniGetConfigPath(IniContext *pContext)
int iniGetSectionNames(IniContext *pContext, IniSectionInfo *sections,
const int max_size, int *nCount);
/** return the section names
* parameters:
* pContext: the ini context
* prefix: the prefix of section name
* sections: the section array
* max_size: the max size of sections
* nCount: return the section count
* return: errno, 0 for success, != 0 for fail
*/
int iniGetSectionNamesByPrefix(IniContext *pContext, const char *szPrefix,
IniSectionInfo *sections, const int max_size, int *nCount);
/** return the section names
* parameters:
* pContext: the ini context
* filter_func: the section name filter function
* args: the extra data pointer
* sections: the section array
* max_size: the max size of sections
* nCount: return the section count
* return: errno, 0 for success, != 0 for fail
*/
int iniGetSectionNamesEx(IniContext *pContext, IniSectionNameFilterFunc
filter_func, void *args, IniSectionInfo *sections,
const int max_size, int *nCount);
/** get matched section count
* parameters:
* pContext: the ini context
* filter_func: the section name filter function
* args: the extra data pointer
* return: matched section count
*/
int iniGetSectionCountEx(IniContext *pContext, IniSectionNameFilterFunc
filter_func, void *args);
/** get matched section count
* parameters:
* pContext: the ini context
* prefix: the prefix of section name
* return: matched section count
*/
int iniGetSectionCountByPrefix(IniContext *pContext, const char *szPrefix);
/** get section count
* parameters:
* pContext: the ini context
* return: section count
*/
static inline int iniGetSectionCount(IniContext *pContext)
{
return pContext->sections.item_count;
}
/** return the items of global section
* parameters:
* pContext: the ini context

679
src/server_id_func.c Normal file
View File

@ -0,0 +1,679 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <netdb.h>
#include "logger.h"
#include "shared_func.h"
#include "sockopt.h"
#include "server_id_func.h"
#define GROUP_SECTION_PREFIX_STR "group-"
#define GROUP_SECTION_PREFIX_LEN (sizeof(GROUP_SECTION_PREFIX_STR) - 1)
#define SERVER_SECTION_PREFIX_STR "server-"
#define SERVER_SECTION_PREFIX_LEN (sizeof(SERVER_SECTION_PREFIX_STR) - 1)
#define SERVER_ITEM_HOST_STR "host"
#define SERVER_ITEM_HOST_LEN (sizeof(SERVER_ITEM_HOST_STR) - 1)
#define SERVER_ITEM_PORT_AFFIX_STR "-port"
#define SERVER_ITEM_PORT_AFFIX_LEN (sizeof(SERVER_ITEM_PORT_AFFIX_STR) - 1)
#define NET_TYPE_OUTER_STR "outer"
#define NET_TYPE_INNER_STR "inner"
#define SUB_NET_TYPE_INNER_10_STR1 "inner-10"
#define SUB_NET_TYPE_INNER_172_STR1 "inner-172"
#define SUB_NET_TYPE_INNER_192_STR1 "inner-192"
#define SUB_NET_TYPE_INNER_10_STR2 "inner_10"
#define SUB_NET_TYPE_INNER_172_STR2 "inner_172"
#define SUB_NET_TYPE_INNER_192_STR2 "inner_192"
#define SUB_NET_TYPE_INNER_10_STR3 "inner10"
#define SUB_NET_TYPE_INNER_172_STR3 "inner172"
#define SUB_NET_TYPE_INNER_192_STR3 "inner192"
static int fc_server_cmp_server_id(const void *p1, const void *p2)
{
return ((FCServerInfo *)p1)->id - ((FCServerInfo *)p2)->id;
}
static int fc_server_cmp_ip_and_port(const void *p1, const void *p2)
{
FCServerMap *m1;
FCServerMap *m2;
int result;
int sub;
int min;
m1 = (FCServerMap *)p1;
m2 = (FCServerMap *)p2;
sub = m1->ip_addr.len - m2->ip_addr.len;
if (sub < 0) {
min = m1->ip_addr.len;
} else {
min = m2->ip_addr.len;
}
if (min > 0) {
result = memcmp(m1->ip_addr.str, m2->ip_addr.str, min);
if (result != 0) {
return result;
}
}
if (sub != 0) {
return sub;
}
return m1->port - m2->port;
}
FCServerInfo *fc_server_get_by_id(FCServerContext *ctx,
const int server_id)
{
FCServerInfo target;
target.id = server_id;
return (FCServerInfo *)bsearch(&target,
ctx->sorted_server_arrays.by_id.servers,
ctx->sorted_server_arrays.by_id.count,
sizeof(FCServerInfo), fc_server_cmp_server_id);
}
static int fc_server_calc_ip_port_count(FCServerContext *ctx)
{
FCServerInfo *server;
FCServerInfo *send;
FCGroupAddresses *gaddr;
FCGroupAddresses *gend;
int count;
count = 0;
send = ctx->sorted_server_arrays.by_id.servers +
ctx->sorted_server_arrays.by_id.count;
for (server=ctx->sorted_server_arrays.by_id.servers;
server<send; server++)
{
gend = server->group_array.group_addrs + server->group_array.count;
for (gaddr=server->group_array.group_addrs; gaddr<gend; gaddr++) {
count += gaddr->address_array.count;
}
}
return count;
}
static int fc_server_init_ip_port_array(FCServerContext *ctx)
{
int result;
int alloc_bytes;
int i;
FCServerMapArray *map_array;
FCServerMap *map;
FCServerInfo *server;
FCServerInfo *send;
FCGroupAddresses *gaddr;
FCGroupAddresses *gend;
map_array = &ctx->sorted_server_arrays.by_ip_port;
map_array->count = fc_server_calc_ip_port_count(ctx);
alloc_bytes = sizeof(FCServerMap) * map_array->count;
map_array->maps = (FCServerMap *)malloc(alloc_bytes);
if (map_array->maps == NULL) {
result = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, "
"malloc %d bytes fail, "
"errno: %d, error info: %s", __LINE__,
alloc_bytes, result, STRERROR(result));
return result;
}
memset(map_array->maps, 0, alloc_bytes);
send = ctx->sorted_server_arrays.by_id.servers +
ctx->sorted_server_arrays.by_id.count;
map = map_array->maps;
for (server=ctx->sorted_server_arrays.by_id.servers;
server<send; server++)
{
gend = server->group_array.group_addrs + server->group_array.count;
for (gaddr=server->group_array.group_addrs; gaddr<gend; gaddr++) {
for (i=0; i<gaddr->address_array.count; i++) {
map->server = server;
FC_SET_STRING(map->ip_addr, gaddr->address_array.
addrs[i].conn.ip_addr);
map->port = gaddr->address_array.addrs[i].conn.port;
map++;
}
}
}
qsort(map_array->maps, map_array->count, sizeof(FCServerMap),
fc_server_cmp_ip_and_port);
return 0;
}
static int fc_server_check_id_duplicated(FCServerContext *ctx,
const char *config_filename)
{
FCServerInfo *previous;
FCServerInfo *current;
FCServerInfo *send;
previous = ctx->sorted_server_arrays.by_id.servers + 0;
send = ctx->sorted_server_arrays.by_id.servers +
ctx->sorted_server_arrays.by_id.count;
for (current=ctx->sorted_server_arrays.by_id.servers + 1;
current<send; current++)
{
if (current->id == previous->id) {
logError("file: "__FILE__", line: %d, "
"config file: %s, duplicate server id: %d",
__LINE__, config_filename, current->id);
return EEXIST;
}
previous = current;
}
return 0;
}
static int fc_server_check_ip_port(FCServerContext *ctx,
const char *config_filename)
{
FCServerMap *previous;
FCServerMap *current;
FCServerMap *end;
previous = ctx->sorted_server_arrays.by_ip_port.maps + 0;
end = ctx->sorted_server_arrays.by_ip_port.maps +
ctx->sorted_server_arrays.by_ip_port.count;
for (current=ctx->sorted_server_arrays.by_ip_port.maps+1;
current<end; current++)
{
if (fc_server_cmp_ip_and_port(current, previous) == 0) {
logError("file: "__FILE__", line: %d, "
"config file: %s, duplicate ip:port %s:%d, "
"the server ids are %d and %d", __LINE__,
config_filename, previous->ip_addr.str, previous->port,
previous->server->id, current->server->id);
return EEXIST;
}
previous = current;
}
return 0;
}
FCServerInfo *fc_server_get_by_ip_port_ex(FCServerContext *ctx,
const string_t *ip_addr, const int port)
{
FCServerMap target;
FCServerMap *found;
target.ip_addr = *ip_addr;
target.port = port;
found = (FCServerMap *)bsearch(&target,
ctx->sorted_server_arrays.by_ip_port.maps,
ctx->sorted_server_arrays.by_ip_port.count,
sizeof(FCServerMap), fc_server_cmp_ip_and_port);
if (found != NULL) {
return found->server;
}
return NULL;
}
static inline void fc_server_set_group_name(FCServerGroupInfo *ginfo,
const char *group_name)
{
ginfo->group_name.str = ginfo->name_buff;
ginfo->group_name.len = snprintf(ginfo->name_buff,
sizeof(ginfo->name_buff) - 1, "%s", group_name);
if (ginfo->group_name.len == 0) {
return;
}
fc_trim(ginfo->group_name.str);
ginfo->group_name.len = strlen(ginfo->group_name.str);
}
static int fc_server_set_net_type(const char *config_filename,
FCServerGroupInfo *ginfo, const char *net_type)
{
if (net_type == NULL || *net_type == '\0') {
ginfo->filter.net_type = FC_NET_TYPE_NONE;
return 0;
}
if (strcasecmp(net_type, NET_TYPE_OUTER_STR) == 0) {
ginfo->filter.net_type = FC_NET_TYPE_OUTER;
} else if (strcasecmp(net_type, NET_TYPE_INNER_STR) == 0) {
ginfo->filter.net_type = FC_NET_TYPE_INNER;
} else if (strcasecmp(net_type, SUB_NET_TYPE_INNER_10_STR1) == 0 ||
strcasecmp(net_type, SUB_NET_TYPE_INNER_10_STR2) == 0 ||
strcasecmp(net_type, SUB_NET_TYPE_INNER_10_STR3) == 0)
{
ginfo->filter.net_type = FC_SUB_NET_TYPE_INNER_10;
} else if (strcasecmp(net_type, SUB_NET_TYPE_INNER_172_STR1) == 0 ||
strcasecmp(net_type, SUB_NET_TYPE_INNER_172_STR2) == 0 ||
strcasecmp(net_type, SUB_NET_TYPE_INNER_172_STR3) == 0)
{
ginfo->filter.net_type = FC_SUB_NET_TYPE_INNER_172;
} else if (strcasecmp(net_type, SUB_NET_TYPE_INNER_192_STR1) == 0 ||
strcasecmp(net_type, SUB_NET_TYPE_INNER_192_STR2) == 0 ||
strcasecmp(net_type, SUB_NET_TYPE_INNER_192_STR3) == 0)
{
ginfo->filter.net_type = FC_SUB_NET_TYPE_INNER_192;
} else {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, invalid net_type: %s",
__LINE__, config_filename, ginfo->group_name.str, net_type);
return EINVAL;
}
return 0;
}
static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo,
const char *ip_prefix)
{
ginfo->filter.ip_prefix.str = ginfo->filter.prefix_buff;
if (ip_prefix != NULL) {
ginfo->filter.ip_prefix.len = snprintf(ginfo->filter.prefix_buff,
sizeof(ginfo->filter.prefix_buff) - 1, "%s", ip_prefix);
}
}
static int fc_server_load_one_group(FCServerContext *ctx,
const char *config_filename, IniContext *ini_context,
const char *section_name)
{
FCServerGroupInfo *current;
char new_name[FAST_INI_ITEM_NAME_SIZE];
char *net_type;
char *ip_prefix;
int result;
strcpy(new_name, section_name);
current = ctx->group_array.groups + ctx->group_array.count;
fc_server_set_group_name(current, new_name + GROUP_SECTION_PREFIX_LEN);
if (current->group_name.len == 0) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, no group name!",
__LINE__, config_filename, section_name);
return EINVAL;
}
current->port = iniGetIntValue(section_name, "port",
ini_context, ctx->default_port);
net_type = iniGetStrValue(section_name, "net_type", ini_context);
if ((result=fc_server_set_net_type(config_filename,
current, net_type)) != 0)
{
return result;
}
ip_prefix = iniGetStrValue(section_name, "ip_prefix", ini_context);
fc_server_set_ip_prefix(current, ip_prefix);
ctx->group_array.count++;
return 0;
}
static int fc_server_load_groups(FCServerContext *ctx,
const char *config_filename, IniContext *ini_context)
{
int result;
int count;
IniSectionInfo sections[FC_MAX_GROUP_COUNT];
IniSectionInfo *section;
IniSectionInfo *end;
if ((result=iniGetSectionNamesByPrefix(ini_context,
GROUP_SECTION_PREFIX_STR, sections,
FC_MAX_GROUP_COUNT, &count)) != 0)
{
logError("file: "__FILE__", line: %d, "
"config filename: %s, get sections by prefix %s fail, "
"errno: %d, error info: %s", __LINE__, config_filename,
GROUP_SECTION_PREFIX_STR, result, STRERROR(result));
return result;
}
if (count == 0) {
ctx->group_array.count = 1;
fc_server_set_group_name(ctx->group_array.groups + 0, "");
ctx->group_array.groups[0].port = iniGetIntValue(NULL, "port",
ini_context, ctx->default_port);
return 0;
}
end = sections + count;
for (section=sections; section<end; section++) {
if ((result=fc_server_load_one_group(ctx, config_filename,
ini_context, section->section_name)) != 0)
{
return result;
}
}
return 0;
}
static int fc_server_check_alloc_servers(FCServerInfoArray *array)
{
int new_alloc;
int bytes;
FCServerInfo *new_servers;
if (array->count < array->alloc) {
return 0;
}
new_alloc = array->alloc > 0 ? 2 * array->alloc : 2;
bytes = sizeof(FCServerInfo) * new_alloc;
new_servers = (FCServerInfo *)malloc(bytes);
if (new_servers == NULL) {
logError("file: "__FILE__", line: %d, "
"malloc %d bytes fail", __LINE__, bytes);
return ENOMEM;
}
if (array->servers != NULL) {
memcpy(new_servers, array->servers,
sizeof(FCServerInfo) * array->count);
free(array->servers);
}
array->servers = new_servers;
array->alloc = new_alloc;
return 0;
}
static inline void fc_server_clear_server_port(FCServerGroupArray *array)
{
FCServerGroupInfo *group;
FCServerGroupInfo *end;
end = array->groups + array->count;
for (group=array->groups; group<end; group++) {
group->server_port = 0;
}
}
static int fc_server_load_group_port(FCServerContext *ctx,
const string_t *group_name, char *port_str)
{
//TODO
return 0;
}
static int fc_server_load_hosts(FCServerContext *ctx, FCServerInfo *server,
const char *config_filename, IniContext *ini_context,
const char *section_name)
{
IniItem *items;
IniItem *it;
IniItem *end;
char *hosts[FC_MAX_SERVER_IP_COUNT];
int item_count;
int host_count;
int name_len;
int result;
string_t group_name;
items = iniGetSectionItems(section_name, ini_context, &item_count);
if (item_count == 0) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, no items!",
__LINE__, config_filename, section_name);
return EINVAL;
}
fc_server_clear_server_port(&ctx->group_array);
host_count = 0;
end = items + item_count;
for (it=items; it<end; it++) {
name_len = strlen(it->name);
if (name_len > SERVER_ITEM_PORT_AFFIX_LEN &&
memcmp(it->name + name_len - SERVER_ITEM_PORT_AFFIX_LEN,
SERVER_ITEM_PORT_AFFIX_STR, SERVER_ITEM_PORT_AFFIX_LEN) == 0)
{
group_name.str = it->name;
group_name.len = name_len - SERVER_ITEM_PORT_AFFIX_LEN;
if ((result=fc_server_load_group_port(ctx,
&group_name, it->value)) != 0)
{
return result;
}
} else if (name_len > SERVER_ITEM_HOST_LEN && memcmp(it->name,
SERVER_ITEM_HOST_STR, SERVER_ITEM_HOST_LEN) == 0)
{
if (host_count >= FC_MAX_SERVER_IP_COUNT) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, "
"too many %s items exceeds %d", __LINE__,
config_filename, section_name,
SERVER_ITEM_HOST_STR, FC_MAX_SERVER_IP_COUNT);
return ENOSPC;
}
hosts[host_count++] = it->value;
} else {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, unkown item name: %s",
__LINE__, config_filename, section_name, it->name);
return EINVAL;
}
}
if (host_count == 0) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, no item: %s!",
__LINE__, config_filename, section_name,
SERVER_ITEM_HOST_STR);
return ENOENT;
}
/*
inner-port = 5106
outer-port = 5107
current->port = iniGetIntValue(section_name, "port",
ini_context, ctx->default_port);
*/
return 0;
}
static int fc_server_load_one_server(FCServerContext *ctx,
const char *config_filename, IniContext *ini_context,
const char *section_name)
{
FCServerInfo *current;
char *endptr;
int result;
if ((result=fc_server_check_alloc_servers(&ctx->
sorted_server_arrays.by_id)) != 0)
{
return result;
}
current = ctx->sorted_server_arrays.by_id.servers +
ctx->sorted_server_arrays.by_id.count;
endptr = NULL;
current->id = strtol(section_name + SERVER_SECTION_PREFIX_LEN, &endptr, 10);
if (current->id <= 0 || endptr != NULL) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, invalid server id! "
"server section format is [%s$id]",
__LINE__, config_filename, section_name,
SERVER_SECTION_PREFIX_STR);
return EINVAL;
}
if ((result=fc_server_load_hosts(ctx, current, config_filename,
ini_context, section_name)) != 0)
{
return result;
}
ctx->sorted_server_arrays.by_id.count++;
return 0;
}
static int fc_server_load_servers(FCServerContext *ctx,
const char *config_filename, IniContext *ini_context)
{
#define FIXED_SECTION_COUNT 16
int result;
int count;
IniSectionInfo *sections;
IniSectionInfo fixed[FIXED_SECTION_COUNT];
IniSectionInfo *section;
IniSectionInfo *end;
int alloc_bytes;
count = iniGetSectionCountByPrefix(ini_context, SERVER_SECTION_PREFIX_STR);
if (count == 0) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, no server section such as [%s$id]",
__LINE__, config_filename, SERVER_SECTION_PREFIX_STR);
return ENOENT;
}
if (count < FIXED_SECTION_COUNT) {
sections = fixed;
} else {
alloc_bytes = sizeof(IniSectionInfo) * count;
sections = (IniSectionInfo *)malloc(alloc_bytes);
if (sections == NULL) {
logError("file: "__FILE__", line: %d, "
"malloc %d bytes fail", __LINE__, alloc_bytes);
return ENOMEM;
}
}
do {
if ((result=iniGetSectionNamesByPrefix(ini_context,
SERVER_SECTION_PREFIX_STR, sections,
count, &count)) != 0)
{
logError("file: "__FILE__", line: %d, "
"config filename: %s, get sections by prefix %s fail, "
"errno: %d, error info: %s", __LINE__, config_filename,
SERVER_SECTION_PREFIX_STR, result, STRERROR(result));
break;
}
end = sections + count;
for (section=sections; section<end; section++) {
if ((result=fc_server_load_one_server(ctx, config_filename,
ini_context, section->section_name)) != 0)
{
break;
}
}
} while (0);
if (sections != fixed) {
free(sections);
}
return result;
}
int fc_server_load_data(FCServerContext *ctx, IniContext *ini_context,
const char *config_filename)
{
int result;
if ((result=fc_server_load_groups(ctx, config_filename,
ini_context)) != 0)
{
return result;
}
if ((result=fc_server_load_servers(ctx, config_filename,
ini_context)) != 0)
{
return result;
}
qsort(ctx->sorted_server_arrays.by_id.servers,
ctx->sorted_server_arrays.by_id.count,
sizeof(FCServerInfo), fc_server_cmp_server_id);
if ((result=fc_server_check_id_duplicated(ctx, config_filename)) != 0) {
return result;
}
if ((result=fc_server_init_ip_port_array(ctx)) != 0) {
return result;
}
return fc_server_check_ip_port(ctx, config_filename);
}
#define FC_SERVER_INIT_CONTEXT(ctx, port) \
do { \
memset(ctx, 0, sizeof(FCServerContext)); \
ctx->default_port = port; \
} while (0)
int fc_server_load_from_file_ex(FCServerContext *ctx,
const char *config_filename, const int default_port)
{
IniContext ini_context;
int result;
FC_SERVER_INIT_CONTEXT(ctx, default_port);
if ((result=iniLoadFromFile(config_filename, &ini_context)) != 0) {
return result;
}
result = fc_server_load_data(ctx, &ini_context, config_filename);
iniFreeContext(&ini_context);
return result;
}
int fc_server_load_from_buffer_ex(FCServerContext *ctx, char *content,
const char *caption, const int default_port)
{
IniContext ini_context;
int result;
FC_SERVER_INIT_CONTEXT(ctx, default_port);
if ((result=iniLoadFromBuffer(content, &ini_context)) != 0) {
return result;
}
result = fc_server_load_data(ctx, &ini_context, caption);
iniFreeContext(&ini_context);
return result;
}
void fc_server_destroy(FCServerContext *ctx)
{
if (ctx->sorted_server_arrays.by_ip_port.maps != NULL) {
free(ctx->sorted_server_arrays.by_ip_port.maps);
ctx->sorted_server_arrays.by_ip_port.maps = NULL;
ctx->sorted_server_arrays.by_ip_port.count = 0;
}
if (ctx->sorted_server_arrays.by_id.servers != NULL) {
free(ctx->sorted_server_arrays.by_id.servers);
ctx->sorted_server_arrays.by_id.servers = NULL;
ctx->sorted_server_arrays.by_id.count = 0;
}
}

132
src/server_id_func.h Normal file
View File

@ -0,0 +1,132 @@
//server_id_func.h
#ifndef _SERVER_ID_FUNC_H
#define _SERVER_ID_FUNC_H
#include "common_define.h"
#include "connection_pool.h"
#include "ini_file_reader.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FC_MAX_SERVER_IP_COUNT 8
#define FC_MAX_GROUP_COUNT 4
typedef struct
{
int net_type;
ConnectionInfo conn;
} FCAddressInfo;
typedef struct
{
string_t group_name;
int port; //default port
int server_port; //port in server section
struct {
int net_type;
string_t ip_prefix;
char prefix_buff[IP_ADDRESS_SIZE];
} filter;
char name_buff[FAST_INI_ITEM_NAME_SIZE]; //group_name string holder
} FCServerGroupInfo;
typedef struct
{
int count;
FCServerGroupInfo groups[FC_MAX_GROUP_COUNT];
} FCServerGroupArray;
typedef struct
{
FCServerGroupInfo *server_group;
struct {
int count;
FCAddressInfo addrs[FC_MAX_SERVER_IP_COUNT];
} address_array;
} FCGroupAddresses;
typedef struct
{
int id; //server id
struct {
int count;
FCGroupAddresses group_addrs[FC_MAX_GROUP_COUNT];
} group_array;
} FCServerInfo;
typedef struct
{
string_t ip_addr;
int port;
FCServerInfo *server;
} FCServerMap;
typedef struct
{
int alloc;
int count;
FCServerInfo *servers;
} FCServerInfoArray;
typedef struct
{
int count;
FCServerMap *maps;
} FCServerMapArray;
typedef struct
{
int default_port;
FCServerGroupArray group_array;
struct {
FCServerInfoArray by_id; //sorted by server id
FCServerMapArray by_ip_port; //sorted by IP and port
} sorted_server_arrays;
} FCServerContext;
FCServerInfo *fc_server_get_by_id(FCServerContext *ctx,
const int server_id);
FCServerInfo *fc_server_get_by_ip_port_ex(FCServerContext *ctx,
const string_t *ip_addr, const int port);
static inline FCServerInfo *fc_server_get_by_ip_port(FCServerContext *ctx,
const char *ip_addr, const int port)
{
string_t saddr;
FC_SET_STRING(saddr, (char *)ip_addr);
return fc_server_get_by_ip_port_ex(ctx, &saddr, port);
}
int fc_server_load_from_file_ex(FCServerContext *ctx,
const char *config_filename, const int default_port);
static inline int fc_server_load_from_file(FCServerContext *ctx,
const char *config_filename)
{
const int default_port = 0;
return fc_server_load_from_file_ex(ctx, config_filename, default_port);
}
int fc_server_load_from_buffer_ex(FCServerContext *ctx, char *content,
const char *caption, const int default_port);
static inline int fc_server_load_from_buffer(FCServerContext *ctx,
char *content)
{
const char *caption = "from-buffer";
const int default_port = 0;
return fc_server_load_from_buffer_ex(ctx, content, caption, default_port);
}
void fc_server_destroy(FCServerContext *ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -19,6 +19,14 @@
#include <sys/socket.h>
#include "common_define.h"
#define FC_NET_TYPE_NONE 0
#define FC_NET_TYPE_OUTER 1 //extranet IP
#define FC_NET_TYPE_INNER 2 //intranet IP
#define FC_SUB_NET_TYPE_INNER_10 (FC_NET_TYPE_INNER | 4)
#define FC_SUB_NET_TYPE_INNER_172 (FC_NET_TYPE_INNER | 8)
#define FC_SUB_NET_TYPE_INNER_192 (FC_NET_TYPE_INNER | 16)
#define FAST_WRITE_BUFF_SIZE (256 * 1024)
typedef struct fast_if_config {

34
src/tests/servers.conf Normal file
View File

@ -0,0 +1,34 @@
[group-inner]
port = 5108
# outer: extranet IP, such as 202.102.100.1
# inner: intranet IP such as 172.16.1.5 or 192.168.3.17
# inner-10: 10 leading network, such as 10.32.1.100
# inner-172: 172 leading network, such as 172.17.0.4
# inner-192: 192 leading network, such as 192.168.0.1
net_type = inner-172
ip_prefix = 172.
[group-outer]
port = 5109
net_type = outer
ip_prefix =
# config a server
# section format: [server-$id]
# server id is a 32 bits natural number (1, 2, 3 etc.),
[server-1]
# format: host[:port]
# host can be an IP or a hostname
# can occur more than once
host = 172.17.7.215
host = 39.100.8.166
[server-2]
inner-port = 5106
outer-port = 5107
host = 172.17.7.215
host = 39.100.8.166