diff --git a/.gitignore b/.gitignore index 5f8b3dc..8b9f551 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ src/tests/test_thourands_seperator src/tests/test_pthread_lock src/tests/test_split_string src/tests/test_uniq_skiplist +src/tests/test_server_id_func # other *.swp diff --git a/HISTORY b/HISTORY index d3bf776..959967b 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.44 2020-02-14 +Version 1.44 2020-02-15 * add test file src/tests/test_pthread_lock.c * add uniq_skiplist.[hc] * add function split_string_ex diff --git a/src/connection_pool.c b/src/connection_pool.c index 49340eb..b01be57 100644 --- a/src/connection_pool.c +++ b/src/connection_pool.c @@ -400,13 +400,13 @@ int conn_pool_parse_server_info(const char *pServerStr, len = strlen(pServerStr); if (len == 0) { logError("file: "__FILE__", line: %d, " - "pServerStr \"%s\" is empty!", + "host \"%s\" is empty!", __LINE__, pServerStr); return EINVAL; } if (len >= sizeof(server_info)) { logError("file: "__FILE__", line: %d, " - "pServerStr \"%s\" is too long!", + "host \"%s\" is too long!", __LINE__, pServerStr); return ENAMETOOLONG; } @@ -423,7 +423,7 @@ int conn_pool_parse_server_info(const char *pServerStr, pServerInfo->port = (int)strtol(parts[1], &endptr, 10); if ((endptr != NULL && *endptr != '\0') || pServerInfo->port <= 0) { logError("file: "__FILE__", line: %d, " - "pServerStr: %s, invalid port: %s!", + "host: %s, invalid port: %s!", __LINE__, pServerStr, parts[1]); return EINVAL; } @@ -433,7 +433,7 @@ int conn_pool_parse_server_info(const char *pServerStr, sizeof(pServerInfo->ip_addr)) == INADDR_NONE) { logError("file: "__FILE__", line: %d, " - "pServerStr: %s, invalid hostname: %s!", + "host: %s, invalid hostname: %s!", __LINE__, pServerStr, parts[0]); return EINVAL; } diff --git a/src/connection_pool.h b/src/connection_pool.h index 606fdd2..135e490 100644 --- a/src/connection_pool.h +++ b/src/connection_pool.h @@ -28,6 +28,10 @@ extern "C" { (strcmp((conn).ip_addr, target_ip) == 0 && \ (conn).port == target_port) +#define FC_CONNECTION_SERVER_EQUAL1(conn1, conn2) \ + (strcmp((conn1).ip_addr, (conn2).ip_addr) == 0 && \ + (conn1).port == (conn2).port) + typedef struct { int sock; diff --git a/src/server_id_func.c b/src/server_id_func.c index f8515ca..ac4b7ff 100644 --- a/src/server_id_func.c +++ b/src/server_id_func.c @@ -13,6 +13,9 @@ #define SERVER_SECTION_PREFIX_STR "server-" #define SERVER_SECTION_PREFIX_LEN (sizeof(SERVER_SECTION_PREFIX_STR) - 1) +#define SERVER_ITEM_PORT_STR "port" +#define SERVER_ITEM_PORT_LEN (sizeof(SERVER_ITEM_PORT_STR) - 1) + #define SERVER_ITEM_HOST_STR "host" #define SERVER_ITEM_HOST_LEN (sizeof(SERVER_ITEM_HOST_STR) - 1) @@ -34,6 +37,9 @@ #define SUB_NET_TYPE_INNER_172_STR3 "inner172" #define SUB_NET_TYPE_INNER_192_STR3 "inner192" +#define FC_SERVER_GROUP_PORT(group) \ + (group->server_port > 0 ? group->server_port : group->port) + static int fc_server_cmp_server_id(const void *p1, const void *p2) { return ((FCServerInfo *)p1)->id - ((FCServerInfo *)p2)->id; @@ -96,8 +102,8 @@ static int fc_server_calc_ip_port_count(FCServerContext *ctx) for (server=ctx->sorted_server_arrays.by_id.servers; servergroup_array.group_addrs + server->group_array.count; - for (gaddr=server->group_array.group_addrs; gaddrgroup_addrs + ctx->group_array.count; + for (gaddr=server->group_addrs; gaddraddress_array.count; } } @@ -138,8 +144,8 @@ static int fc_server_init_ip_port_array(FCServerContext *ctx) for (server=ctx->sorted_server_arrays.by_id.servers; servergroup_array.group_addrs + server->group_array.count; - for (gaddr=server->group_array.group_addrs; gaddrgroup_addrs + ctx->group_array.count; + for (gaddr=server->group_addrs; gaddraddress_array.count; i++) { map->server = server; FC_SET_STRING(map->ip_addr, gaddr->address_array. @@ -228,7 +234,7 @@ FCServerInfo *fc_server_get_by_ip_port_ex(FCServerContext *ctx, return NULL; } -static inline void fc_server_set_group_name(FCServerGroupInfo *ginfo, +static inline void fc_server_set_group_ptr_name(FCServerGroupInfo *ginfo, const char *group_name) { ginfo->group_name.str = ginfo->name_buff; @@ -291,42 +297,91 @@ static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo, static int fc_server_load_one_group(FCServerContext *ctx, const char *config_filename, IniContext *ini_context, - const char *section_name) + const int group_count, const char *section_name) { - FCServerGroupInfo *current; + FCServerGroupInfo *group; char new_name[FAST_INI_ITEM_NAME_SIZE]; + char *port_str; 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); + group = ctx->group_array.groups + ctx->group_array.count; + fc_server_set_group_ptr_name(group, new_name + GROUP_SECTION_PREFIX_LEN); - if (current->group_name.len == 0) { + if (group->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); + port_str = iniGetStrValue(section_name, SERVER_ITEM_PORT_STR, ini_context); + if (port_str == NULL) { + if (group_count == 1) { + group->port = ctx->default_port; + } else { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, no item: %s!", + __LINE__, config_filename, section_name, + SERVER_ITEM_PORT_STR); + return ENOENT; + } + } else { + char *endptr = NULL; + group->port = strtol(port_str, &endptr, 10); + if (group->port <= 0 || (endptr != NULL && *endptr != '\0')) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, item: %s, " + "invalid port: %s", __LINE__, config_filename, + section_name, SERVER_ITEM_PORT_STR, port_str); + return EINVAL; + } + } net_type = iniGetStrValue(section_name, "net_type", ini_context); if ((result=fc_server_set_net_type(config_filename, - current, net_type)) != 0) + group, net_type)) != 0) { return result; } ip_prefix = iniGetStrValue(section_name, "ip_prefix", ini_context); - fc_server_set_ip_prefix(current, ip_prefix); + fc_server_set_ip_prefix(group, ip_prefix); ctx->group_array.count++; return 0; } +static int check_group_ports_duplicate(FCServerContext *ctx, + const char *config_filename) +{ + FCServerGroupInfo *g1; + FCServerGroupInfo *g2; + FCServerGroupInfo *end; + int port1; + int port2; + + end = ctx->group_array.groups + ctx->group_array.count; + for (g1=ctx->group_array.groups; g1group_name.len, g1->group_name.str, + g2->group_name.len, g2->group_name.str); + return EEXIST; + } + } + } + + return 0; +} + static int fc_server_load_groups(FCServerContext *ctx, const char *config_filename, IniContext *ini_context) { @@ -349,7 +404,7 @@ static int fc_server_load_groups(FCServerContext *ctx, if (count == 0) { ctx->group_array.count = 1; - fc_server_set_group_name(ctx->group_array.groups + 0, ""); + fc_server_set_group_ptr_name(ctx->group_array.groups + 0, ""); ctx->group_array.groups[0].port = iniGetIntValue(NULL, "port", ini_context, ctx->default_port); return 0; @@ -358,7 +413,7 @@ static int fc_server_load_groups(FCServerContext *ctx, end = sections + count; for (section=sections; sectionsection_name)) != 0) + ini_context, count, section->section_name)) != 0) { return result; } @@ -408,10 +463,252 @@ static inline void fc_server_clear_server_port(FCServerGroupArray *array) } } -static int fc_server_load_group_port(FCServerContext *ctx, - const string_t *group_name, char *port_str) +static FCServerGroupInfo *fc_server_get_group_by_name(FCServerContext *ctx, + const string_t *group_name) { - //TODO + FCServerGroupInfo *group; + FCServerGroupInfo *end; + + end = ctx->group_array.groups + ctx->group_array.count; + for (group=ctx->group_array.groups; groupgroup_name, group_name)) { + return group; + } + } + + return NULL; +} + +static int fc_server_load_group_port(FCServerContext *ctx, + const char *config_filename, const char *section_name, + const string_t *group_name, IniItem *port_item) +{ + FCServerGroupInfo *group; + char *endptr; + + if ((group=fc_server_get_group_by_name(ctx, group_name)) == NULL) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, group: %.*s " + "in item: %s not found!", __LINE__, config_filename, + section_name, group_name->len, group_name->str, + port_item->name); + return ENOENT; + } + + endptr = NULL; + group->server_port = strtol(port_item->value, &endptr, 10); + if (group->server_port <= 0 || (endptr != NULL && *endptr != '\0')) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, item: %s, " + "invalid port: %s", __LINE__, config_filename, + section_name, port_item->name, port_item->value); + return EINVAL; + } + + return 0; +} + +static int check_server_addresses_duplicate(FCServerContext *ctx, + const char *config_filename, const char *section_name, + const FCAddressInfo *addresses, const int count) +{ + const FCAddressInfo *addr1; + const FCAddressInfo *addr2; + const FCAddressInfo *end; + char port_caption[32]; + char port_prompt[16]; + + end = addresses + count; + for (addr1=addresses; addr1conn, addr2->conn)) { + if (addr1->conn.port > 0) { + strcpy(port_caption, " and port"); + sprintf(port_prompt, ":%d", addr1->conn.port); + } else { + *port_caption = *port_prompt = '\0'; + } + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, duplicate ip%s %s%s", + __LINE__, config_filename, section_name, port_caption, + addr1->conn.ip_addr, port_prompt); + return EEXIST; + } + } + } + + return 0; +} + +static int check_server_group_addresses_duplicate(FCServerContext *ctx, + FCServerInfo *server, const char *config_filename, + const char *section_name) +{ + int result; + FCGroupAddresses *gaddr; + FCGroupAddresses *end; + + end = server->group_addrs + ctx->group_array.count; + for (gaddr=server->group_addrs; gaddraddress_array.addrs, + gaddr->address_array.count)) != 0) + { + return result; + } + } + + return 0; +} + +static bool fc_server_group_match(const FCServerGroupInfo *group, + const FCAddressInfo *addr) +{ + int ip_len; + + if ((addr->conn.port > 0) && (addr->conn.port != + FC_SERVER_GROUP_PORT(group))) + { + return false; + } + + if ((group->filter.net_type != FC_NET_TYPE_NONE) && + ((addr->net_type & group->filter.net_type) != + group->filter.net_type)) + { + return false; + } + + if (group->filter.ip_prefix.len > 0) { + ip_len = strlen(addr->conn.ip_addr); + if (!(ip_len >= group->filter.ip_prefix.len && + memcmp(addr->conn.ip_addr, + group->filter.ip_prefix.str, + group->filter.ip_prefix.len) == 0)) + { + return false; + } + } + + return true; +} + +static int fc_server_set_host(FCServerContext *ctx, FCServerInfo *server, + const char *config_filename, const char *section_name, + FCAddressInfo *addr) +{ + FCServerGroupInfo *group; + FCServerGroupInfo *end; + FCGroupAddresses *group_addr; + FCAddressInfo *current; + int count; + int group_index; + + count = 0; + end = ctx->group_array.groups + ctx->group_array.count; + for (group=ctx->group_array.groups; groupgroup_array.groups; + group_addr = server->group_addrs + group_index; + + current = group_addr->address_array.addrs + group_addr-> + address_array.count++; + *current = *addr; + if (addr->conn.port == 0) { + current->conn.port = FC_SERVER_GROUP_PORT(group); + } + + count++; + } + } + + if (count == 0) { + char port_prompt[16]; + if (addr->conn.port > 0) { + sprintf(port_prompt, ":%d", addr->conn.port); + } else { + *port_prompt = '\0'; + } + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, " + "host %s%s not belong to any group", + __LINE__, config_filename, section_name, + addr->conn.ip_addr, port_prompt); + return ENOENT; + } + + if (!ctx->share_between_groups && (count > 1 && addr->conn.port > 0)) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, " + "host %s:%d belongs to %d groups", + __LINE__, config_filename, section_name, + addr->conn.ip_addr, addr->conn.port, count); + return EEXIST; + } + + return 0; +} + +static int fc_server_set_hosts(FCServerContext *ctx, FCServerInfo *server, + const char *config_filename, const char *section_name, + char **hosts, const int host_count) +{ + int result; + FCAddressInfo addresses[FC_MAX_SERVER_IP_COUNT]; + FCAddressInfo *addr; + FCAddressInfo *addr_end; + char **host; + char **hend; + int no_port_count; + + no_port_count = 0; + addr = addresses; + hend = hosts + host_count; + for (host=hosts; hostconn, 0)) != 0) + { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, " + "invalid host: %s", __LINE__, + config_filename, section_name, *host); + return result; + } + + addr->net_type = fc_get_net_type(addr->conn.ip_addr); + if (addr->conn.port == 0) { + no_port_count++; + } + addr++; + } + + if ((result=check_server_addresses_duplicate(ctx, config_filename, + section_name, addresses, host_count)) != 0) + { + return result; + } + + if (no_port_count > 0 && !ctx->share_between_groups) { + if ((result=check_group_ports_duplicate(ctx, config_filename)) != 0) { + return result; + } + } + + addr_end = addresses + host_count; + for (addr=addresses; addrname; group_name.len = name_len - SERVER_ITEM_PORT_AFFIX_LEN; - if ((result=fc_server_load_group_port(ctx, - &group_name, it->value)) != 0) + if ((result=fc_server_load_group_port(ctx, config_filename, + section_name, &group_name, it)) != 0) { return result; } - } else if (name_len > SERVER_ITEM_HOST_LEN && memcmp(it->name, + } 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) { @@ -483,23 +780,32 @@ static int fc_server_load_hosts(FCServerContext *ctx, FCServerInfo *server, return ENOENT; } - /* -inner-port = 5106 -outer-port = 5107 - - current->port = iniGetIntValue(section_name, "port", - ini_context, ctx->default_port); - - */ + if ((result=fc_server_set_hosts(ctx, server, config_filename, + section_name, hosts, host_count)) != 0) + { + return result; + } return 0; } +static void fc_server_set_group_ptr(FCServerContext *ctx, FCServerInfo *server) +{ + FCGroupAddresses *gaddr; + FCGroupAddresses *end; + + end = server->group_addrs + ctx->group_array.count; + for (gaddr=server->group_addrs; gaddrserver_group = ctx->group_array.groups + (gaddr - + server->group_addrs); + } +} + static int fc_server_load_one_server(FCServerContext *ctx, const char *config_filename, IniContext *ini_context, const char *section_name) { - FCServerInfo *current; + FCServerInfo *server; char *endptr; int result; @@ -509,12 +815,13 @@ static int fc_server_load_one_server(FCServerContext *ctx, return result; } - current = ctx->sorted_server_arrays.by_id.servers + + server = 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) { + server->id = strtol(section_name + SERVER_SECTION_PREFIX_LEN, + &endptr, 10); + if (server->id <= 0 || (endptr != NULL && *endptr != '\0')) { logError("file: "__FILE__", line: %d, " "config filename: %s, section: %s, invalid server id! " "server section format is [%s$id]", @@ -523,7 +830,9 @@ static int fc_server_load_one_server(FCServerContext *ctx, return EINVAL; } - if ((result=fc_server_load_hosts(ctx, current, config_filename, + fc_server_set_group_ptr(ctx, server); + + if ((result=fc_server_load_hosts(ctx, server, config_filename, ini_context, section_name)) != 0) { return result; @@ -625,19 +934,21 @@ int fc_server_load_data(FCServerContext *ctx, IniContext *ini_context, return fc_server_check_ip_port(ctx, config_filename); } -#define FC_SERVER_INIT_CONTEXT(ctx, port) \ +#define FC_SERVER_INIT_CONTEXT(ctx, port, shared) \ do { \ memset(ctx, 0, sizeof(FCServerContext)); \ ctx->default_port = port; \ + ctx->share_between_groups = shared; \ } while (0) int fc_server_load_from_file_ex(FCServerContext *ctx, - const char *config_filename, const int default_port) + const char *config_filename, const int default_port, + const bool share_between_groups) { IniContext ini_context; int result; - FC_SERVER_INIT_CONTEXT(ctx, default_port); + FC_SERVER_INIT_CONTEXT(ctx, default_port, share_between_groups); if ((result=iniLoadFromFile(config_filename, &ini_context)) != 0) { return result; } @@ -648,12 +959,13 @@ int fc_server_load_from_file_ex(FCServerContext *ctx, } int fc_server_load_from_buffer_ex(FCServerContext *ctx, char *content, - const char *caption, const int default_port) + const char *caption, const int default_port, + const bool share_between_groups) { IniContext ini_context; int result; - FC_SERVER_INIT_CONTEXT(ctx, default_port); + FC_SERVER_INIT_CONTEXT(ctx, default_port, share_between_groups); if ((result=iniLoadFromBuffer(content, &ini_context)) != 0) { return result; } @@ -677,3 +989,50 @@ void fc_server_destroy(FCServerContext *ctx) ctx->sorted_server_arrays.by_id.count = 0; } } + +static void fc_server_log_groups(FCServerContext *ctx) +{ + FCServerGroupInfo *group; + FCServerGroupInfo *end; + + end = ctx->group_array.groups + ctx->group_array.count; + for (group=ctx->group_array.groups; groupgroup_name.len, group->group_name.str, group->port, + get_net_type_caption(group->filter.net_type), + group->filter.ip_prefix.len, group->filter.ip_prefix.str); + } +} + +static void fc_server_log_one_server(FCServerContext *ctx, FCServerInfo *server) +{ + FCGroupAddresses *gaddr; + FCGroupAddresses *end; + + logInfo("server id: %d", server->id); + + end = server->group_addrs + ctx->group_array.count; + for (gaddr=server->group_addrs; gaddrserver_group->group_name)); + //TODO log server ip and port + } +} + +static void fc_server_log_servers(FCServerContext *ctx) +{ + FCServerInfo *server; + FCServerInfo *end; + + end = ctx->sorted_server_arrays.by_id.servers + + ctx->sorted_server_arrays.by_id.count; + for (server=ctx->sorted_server_arrays.by_id.servers; server= 16 && b < 32) + { + return FC_SUB_NET_TYPE_INNER_172; + } + } + + return FC_NET_TYPE_OUTER; +} diff --git a/src/sockopt.h b/src/sockopt.h index 808a811..ba07979 100644 --- a/src/sockopt.h +++ b/src/sockopt.h @@ -587,6 +587,8 @@ static inline void tcp_dont_try_again_when_interrupt() tcp_set_try_again_when_interrupt(false); } +int fc_get_net_type(const char *ip); + static inline bool is_network_error(const int err_no) { switch (err_no) @@ -610,6 +612,27 @@ static inline bool is_network_error(const int err_no) } } +static inline const char *get_net_type_caption(const int net_type) +{ + switch (net_type) + { + case FC_NET_TYPE_NONE: + return "none"; + case FC_NET_TYPE_OUTER: + return "outer"; + case FC_NET_TYPE_INNER: + return "inner"; + case FC_SUB_NET_TYPE_INNER_10: + return "inner-10"; + case FC_SUB_NET_TYPE_INNER_172: + return "inner-172"; + case FC_SUB_NET_TYPE_INNER_192: + return "inner-192"; + default: + return "UNKOWN"; + } +} + #ifdef __cplusplus } #endif diff --git a/src/tests/Makefile b/src/tests/Makefile index b61efb5..4243bdb 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -7,7 +7,8 @@ LIB_PATH = -lfastcommon -lpthread ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blocked_queue \ test_id_generator test_ini_parser test_char_convert test_char_convert_loader \ test_logger test_skiplist_set test_crc32 test_thourands_seperator test_sched_thread \ - test_json_parser test_pthread_lock test_uniq_skiplist test_split_string + test_json_parser test_pthread_lock test_uniq_skiplist test_split_string \ + test_server_id_func all: $(ALL_PRGS) .c: diff --git a/src/tests/test_server_id_func.c b/src/tests/test_server_id_func.c new file mode 100644 index 0000000..0841a20 --- /dev/null +++ b/src/tests/test_server_id_func.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fastcommon/logger.h" +#include "fastcommon/shared_func.h" +#include "fastcommon/server_id_func.h" + +int main(int argc, char *argv[]) +{ + int result; + const char *config_filename = "servers.conf"; + FCServerContext ctx; + const int default_port = 1111; + const bool share_between_groups = false; + + if (argc > 1) { + config_filename = argv[1]; + } + + log_init(); + + if ((result=fc_server_load_from_file_ex(&ctx, config_filename, + default_port, share_between_groups)) != 0) + { + return result; + } + + fc_server_to_log(&ctx); + + fc_server_destroy(&ctx); + return 0; +}