tracker support multi ip for storage server

multi_ipaddr
YuQing 2019-10-09 21:26:56 +08:00
parent f60d96989a
commit 82e95ccee7
12 changed files with 1090 additions and 820 deletions

View File

@ -12,7 +12,7 @@ CONFIG_PATH = $(TARGET_CONF_PATH)
FDFS_STATIC_OBJS = ../common/fdfs_global.o ../common/fdfs_http_shared.o \ FDFS_STATIC_OBJS = ../common/fdfs_global.o ../common/fdfs_http_shared.o \
../common/mime_file_parser.o ../tracker/tracker_proto.o \ ../common/mime_file_parser.o ../tracker/tracker_proto.o \
../tracker/fdfs_shared_func.o \ ../tracker/fdfs_shared_func.o ../tracker/fdfs_server_id_func.o \
../storage/trunk_mgr/trunk_shared.o \ ../storage/trunk_mgr/trunk_shared.o \
tracker_client.o client_func.o \ tracker_client.o client_func.o \
client_global.o storage_client.o client_global.o storage_client.o
@ -21,7 +21,7 @@ STATIC_OBJS = $(FDFS_STATIC_OBJS)
FDFS_SHARED_OBJS = ../common/fdfs_global.lo ../common/fdfs_http_shared.lo \ FDFS_SHARED_OBJS = ../common/fdfs_global.lo ../common/fdfs_http_shared.lo \
../common/mime_file_parser.lo ../tracker/tracker_proto.lo \ ../common/mime_file_parser.lo ../tracker/tracker_proto.lo \
../tracker/fdfs_shared_func.lo \ ../tracker/fdfs_shared_func.lo ../tracker/fdfs_server_id_func.lo \
../storage/trunk_mgr/trunk_shared.lo \ ../storage/trunk_mgr/trunk_shared.lo \
tracker_client.lo client_func.lo \ tracker_client.lo client_func.lo \
client_global.lo storage_client.lo client_global.lo storage_client.lo
@ -29,7 +29,7 @@ FDFS_SHARED_OBJS = ../common/fdfs_global.lo ../common/fdfs_http_shared.lo \
FDFS_HEADER_FILES = ../common/fdfs_define.h ../common/fdfs_global.h \ FDFS_HEADER_FILES = ../common/fdfs_define.h ../common/fdfs_global.h \
../common/mime_file_parser.h ../common/fdfs_http_shared.h \ ../common/mime_file_parser.h ../common/fdfs_http_shared.h \
../tracker/tracker_types.h ../tracker/tracker_proto.h \ ../tracker/tracker_types.h ../tracker/tracker_proto.h \
../tracker/fdfs_shared_func.h \ ../tracker/fdfs_shared_func.h ../tracker/fdfs_server_id_func.h \
../storage/trunk_mgr/trunk_shared.h \ ../storage/trunk_mgr/trunk_shared.h \
tracker_client.h storage_client.h storage_client1.h \ tracker_client.h storage_client.h storage_client1.h \
client_func.h client_global.h fdfs_client.h client_func.h client_global.h fdfs_client.h

View File

@ -380,7 +380,7 @@ static int fdfs_client_do_init_ex(TrackerServerGroup *pTrackerGroup, \
g_fdfs_network_timeout, pTrackerGroup->server_count, \ g_fdfs_network_timeout, pTrackerGroup->server_count, \
g_anti_steal_token, g_anti_steal_secret_key.length, \ g_anti_steal_token, g_anti_steal_secret_key.length, \
g_use_connection_pool, g_connection_pool_max_idle_time, \ g_use_connection_pool, g_connection_pool_max_idle_time, \
use_storage_id, g_storage_id_count); use_storage_id, g_storage_ids_by_id.count);
#endif #endif
return 0; return 0;

View File

@ -2171,7 +2171,7 @@ int fdfs_get_file_info_ex(const char *group_name, const char *remote_filename, \
if (fdfs_get_server_id_type(ip_addr.s_addr) == FDFS_ID_TYPE_SERVER_ID) if (fdfs_get_server_id_type(ip_addr.s_addr) == FDFS_ID_TYPE_SERVER_ID)
{ {
pFileInfo->source_id = ip_addr.s_addr; pFileInfo->source_id = ip_addr.s_addr;
if (g_storage_ids_by_id != NULL && g_storage_id_count > 0) if (g_storage_ids_by_id.count > 0)
{ {
char id[16]; char id[16];
FDFSStorageIdInfo *pStorageId; FDFSStorageIdInfo *pStorageId;
@ -2180,8 +2180,8 @@ int fdfs_get_file_info_ex(const char *group_name, const char *remote_filename, \
pStorageId = fdfs_get_storage_by_id(id); pStorageId = fdfs_get_storage_by_id(id);
if (pStorageId != NULL) if (pStorageId != NULL)
{ {
strcpy(pFileInfo->source_ip_addr, \ strcpy(pFileInfo->source_ip_addr,
pStorageId->ip_addr); pStorageId->ip_addrs.ips[0]);
} }
else else
{ {

View File

@ -6,8 +6,8 @@ LIB_PATH = $(LIBS) -lfastcommon
TARGET_PATH = $(TARGET_PREFIX)/bin TARGET_PATH = $(TARGET_PREFIX)/bin
CONFIG_PATH = $(TARGET_CONF_PATH) CONFIG_PATH = $(TARGET_CONF_PATH)
SHARED_OBJS = ../common/fdfs_global.o \ SHARED_OBJS = ../common/fdfs_global.o ../tracker/fdfs_shared_func.o \
../tracker/fdfs_shared_func.o ../tracker/tracker_proto.o \ ../tracker/fdfs_server_id_func.o ../tracker/tracker_proto.o \
tracker_client_thread.o storage_global.o storage_func.o \ tracker_client_thread.o storage_global.o storage_func.o \
storage_service.o storage_sync.o storage_nio.o storage_dio.o \ storage_service.o storage_sync.o storage_nio.o storage_dio.o \
storage_ip_changed_dealer.o storage_param_getter.o \ storage_ip_changed_dealer.o storage_param_getter.o \

View File

@ -3668,7 +3668,9 @@ static int storage_server_query_file_info(struct fast_task_info *pTask)
pStorageIdInfo = fdfs_get_storage_by_id(id); pStorageIdInfo = fdfs_get_storage_by_id(id);
if (pStorageIdInfo != NULL) if (pStorageIdInfo != NULL)
{ {
strcpy(p, pStorageIdInfo->ip_addr); strcpy(p, fdfs_get_ipaddr_by_client_ip(
&pStorageIdInfo->ip_addrs,
pTask->client_ip));
} }
} }
} }

View File

@ -8,7 +8,7 @@ CONFIG_PATH = $(TARGET_CONF_PATH)
SHARED_OBJS = ../common/fdfs_global.o \ SHARED_OBJS = ../common/fdfs_global.o \
tracker_proto.o tracker_mem.o tracker_service.o tracker_status.o \ tracker_proto.o tracker_mem.o tracker_service.o tracker_status.o \
tracker_global.o tracker_func.o \ tracker_global.o tracker_func.o fdfs_server_id_func.o \
fdfs_shared_func.o tracker_nio.o tracker_relationship.o \ fdfs_shared_func.o tracker_nio.o tracker_relationship.o \
$(TRACKER_EXTRA_OBJS) $(TRACKER_EXTRA_OBJS)

View File

@ -0,0 +1,803 @@
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS may be copied only under the terms of the GNU General
* Public License V3, which may be found in the FastDFS source kit.
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <netdb.h>
#include "fastcommon/logger.h"
#include "fastcommon/sockopt.h"
#include "fastcommon/shared_func.h"
#include "tracker_proto.h"
#include "fdfs_global.h"
#include "fdfs_shared_func.h"
#include "fdfs_server_id_func.h"
FDFSStorageIdInfoArray g_storage_ids_by_id = {0, NULL}; //sorted by storage ID
FDFSStorageIdMapArray g_storage_ids_by_ip = {0, NULL}; //sorted by group name and storage IP
static FDFSStorageIdMapArray g_storage_ids_by_ip_port = {0, NULL}; //sorted by storage ip and port
bool fdfs_is_server_id_valid(const char *id)
{
long n;
char *endptr;
char buff[FDFS_STORAGE_ID_MAX_SIZE];
if (*id == '\0')
{
return false;
}
endptr = NULL;
n = strtol(id, &endptr, 10);
if (endptr != NULL && *endptr != '\0')
{
return false;
}
if (n <= 0 || n > FDFS_MAX_SERVER_ID)
{
return false;
}
snprintf(buff, sizeof(buff), "%ld", n);
return strcmp(buff, id) == 0;
}
int fdfs_get_server_id_type(const int id)
{
if (id > 0 && id <= FDFS_MAX_SERVER_ID)
{
return FDFS_ID_TYPE_SERVER_ID;
}
else
{
return FDFS_ID_TYPE_IP_ADDRESS;
}
}
static int fdfs_cmp_group_name_and_ip(const void *p1, const void *p2)
{
int result;
result = strcmp(((FDFSStorageIdMap *)p1)->group_name,
((FDFSStorageIdMap *)p2)->group_name);
if (result != 0)
{
return result;
}
return strcmp(((FDFSStorageIdMap *)p1)->ip_addr,
((FDFSStorageIdMap *)p2)->ip_addr);
}
static int fdfs_cmp_server_id(const void *p1, const void *p2)
{
return strcmp((*((FDFSStorageIdInfo **)p1))->id,
(*((FDFSStorageIdInfo **)p2))->id);
}
static int fdfs_cmp_ip_and_port(const void *p1, const void *p2)
{
int result;
result = strcmp(((FDFSStorageIdMap *)p1)->ip_addr,
((FDFSStorageIdMap *)p2)->ip_addr);
if (result != 0)
{
return result;
}
return ((FDFSStorageIdMap *)p1)->port -
((FDFSStorageIdMap *)p2)->port;
}
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip(const char *group_name,
const char *pIpAddr)
{
FDFSStorageIdMap target;
FDFSStorageIdMap *pFound;
target.group_name = group_name;
target.ip_addr = pIpAddr;
target.port = 0;
target.idInfo = NULL;
pFound = (FDFSStorageIdMap *)bsearch(&target,
g_storage_ids_by_ip.maps, g_storage_ids_by_ip.count,
sizeof(FDFSStorageIdMap), fdfs_cmp_group_name_and_ip);
if (pFound == NULL)
{
return NULL;
}
else
{
return pFound->idInfo;
}
}
FDFSStorageIdInfo *fdfs_get_storage_by_id(const char *id)
{
FDFSStorageIdInfo target;
memset(&target, 0, sizeof(FDFSStorageIdInfo));
snprintf(target.id, sizeof(target.id), "%s", id);
return (FDFSStorageIdInfo *)bsearch(&target,
g_storage_ids_by_id.ids, g_storage_ids_by_id.count,
sizeof(FDFSStorageIdInfo), fdfs_cmp_server_id);
}
static int fdfs_calc_ip_count()
{
FDFSStorageIdInfo *idInfo;
FDFSStorageIdInfo *idEnd;
int ip_count;
ip_count = 0;
idEnd = g_storage_ids_by_id.ids + g_storage_ids_by_id.count;
for (idInfo=g_storage_ids_by_id.ids; idInfo<idEnd; idInfo++)
{
ip_count += idInfo->ip_addrs.count;
}
return ip_count;
}
static int fdfs_init_ip_array(FDFSStorageIdMapArray *mapArray,
int (*compare_func)(const void *, const void *))
{
int result;
int i;
int alloc_bytes;
FDFSStorageIdMap *idMap;
FDFSStorageIdInfo *idInfo;
FDFSStorageIdInfo *idEnd;
mapArray->count = fdfs_calc_ip_count();
alloc_bytes = sizeof(FDFSStorageIdMap) * mapArray->count;
mapArray->maps = (FDFSStorageIdMap *)malloc(alloc_bytes);
if (mapArray->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(mapArray->maps, 0, alloc_bytes);
idEnd = g_storage_ids_by_id.ids + g_storage_ids_by_id.count;
idMap = mapArray->maps;
for (idInfo=g_storage_ids_by_id.ids; idInfo<idEnd; idInfo++)
{
for (i=0; i<idInfo->ip_addrs.count; i++)
{
idMap->idInfo = idInfo;
idMap->group_name = idInfo->group_name;
idMap->ip_addr = idInfo->ip_addrs.ips[i];
idMap->port = idInfo->port;
idMap++;
}
}
qsort(mapArray->maps, mapArray->count,
sizeof(FDFSStorageIdMap), compare_func);
return 0;
}
static int fdfs_check_ip_port()
{
int i;
int port_count;
FDFSStorageIdMap *previous;
FDFSStorageIdMap *current;
FDFSStorageIdMap *end;
port_count = 0;
for (i=0; i<g_storage_ids_by_id.count; i++)
{
if (g_storage_ids_by_id.ids[i].port > 0)
{
port_count++;
}
}
if (port_count > 0 && port_count != g_storage_ids_by_id.count)
{
logError("file: "__FILE__", line: %d, "
"config file: storage_ids.conf, "
"some storages without port, "
"must be the same format as host:port", __LINE__);
return EINVAL;
}
previous = g_storage_ids_by_ip_port.maps + 0;
end = g_storage_ids_by_ip_port.maps + g_storage_ids_by_ip_port.count;
for (current=g_storage_ids_by_ip_port.maps+1; current<end; current++)
{
if (fdfs_cmp_ip_and_port(current, previous) == 0)
{
char szPortPart[16];
if (previous->port > 0)
{
sprintf(szPortPart, ":%d", previous->port);
}
else
{
*szPortPart = '\0';
}
logError("file: "__FILE__", line: %d, "
"config file: storage_ids.conf, "
"duplicate storage: %s%s", __LINE__,
previous->ip_addr, szPortPart);
free(g_storage_ids_by_ip_port.maps);
g_storage_ids_by_ip_port.maps = NULL;
return EEXIST;
}
previous = current;
}
return 0;
}
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip_port(const char *pIpAddr,
const int port)
{
FDFSStorageIdMap target;
FDFSStorageIdMap *pFound;
int ports[2];
int i;
target.ip_addr = pIpAddr;
target.group_name = NULL;
target.idInfo = NULL;
ports[0] = port;
ports[1] = 0;
for (i=0; i<2; i++)
{
target.port = ports[i];
pFound = (FDFSStorageIdMap *)bsearch(&target,
g_storage_ids_by_ip_port.maps,
g_storage_ids_by_ip_port.count,
sizeof(FDFSStorageIdMap), fdfs_cmp_ip_and_port);
if (pFound != NULL)
{
return pFound->idInfo;
}
}
return NULL;
}
int fdfs_check_storage_id(const char *group_name, const char *id)
{
FDFSStorageIdInfo *pFound;
pFound = fdfs_get_storage_by_id(id);
if (pFound == NULL)
{
return ENOENT;
}
return strcmp(pFound->group_name, group_name) == 0 ? 0 : EINVAL;
}
int fdfs_load_storage_ids(char *content, const char *pStorageIdsFilename)
{
char **lines;
char *line;
char *id;
char *group_name;
char *pHost;
char *pPort;
FDFSStorageIdInfo *pStorageIdInfo;
char error_info[256];
int alloc_bytes;
int result;
int line_count;
int i;
lines = split(content, '\n', 0, &line_count);
if (lines == NULL)
{
return ENOMEM;
}
result = 0;
do
{
g_storage_ids_by_id.count = 0;
for (i=0; i<line_count; i++)
{
trim(lines[i]);
if (*lines[i] == '\0' || *lines[i] == '#')
{
continue;
}
g_storage_ids_by_id.count++;
}
if (g_storage_ids_by_id.count == 0)
{
logError("file: "__FILE__", line: %d, " \
"config file: %s, no storage id!", \
__LINE__, pStorageIdsFilename);
result = ENOENT;
break;
}
alloc_bytes = sizeof(FDFSStorageIdInfo) * g_storage_ids_by_id.count;
g_storage_ids_by_id.ids = (FDFSStorageIdInfo *)malloc(alloc_bytes);
if (g_storage_ids_by_id.ids == 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));
break;
}
memset(g_storage_ids_by_id.ids, 0, alloc_bytes);
pStorageIdInfo = g_storage_ids_by_id.ids;
for (i=0; i<line_count; i++)
{
line = lines[i];
if (*line == '\0' || *line == '#')
{
continue;
}
id = line;
group_name = line;
while (!(*group_name == ' ' || *group_name == '\t' \
|| *group_name == '\0'))
{
group_name++;
}
if (*group_name == '\0')
{
logError("file: "__FILE__", line: %d, " \
"config file: %s, line no: %d, " \
"content: %s, invalid format, " \
"expect group name and ip address!", \
__LINE__, pStorageIdsFilename, \
i + 1, line);
result = EINVAL;
break;
}
*group_name = '\0';
group_name++; //skip space char
while (*group_name == ' ' || *group_name == '\t')
{
group_name++;
}
pHost = group_name;
while (!(*pHost == ' ' || *pHost == '\t' \
|| *pHost == '\0'))
{
pHost++;
}
if (*pHost == '\0')
{
logError("file: "__FILE__", line: %d, " \
"config file: %s, line no: %d, " \
"content: %s, invalid format, " \
"expect ip address!", __LINE__, \
pStorageIdsFilename, i + 1, line);
result = EINVAL;
break;
}
*pHost = '\0';
pHost++; //skip space char
while (*pHost == ' ' || *pHost == '\t')
{
pHost++;
}
pPort = strchr(pHost, ':');
if (pPort != NULL)
{
*pPort = '\0';
pStorageIdInfo->port = atoi(pPort + 1);
}
else
{
pStorageIdInfo->port = 0;
}
if ((result=fdfs_parse_multi_ips(pHost, &pStorageIdInfo->ip_addrs,
error_info, sizeof(error_info))) != 0)
{
logError("file: "__FILE__", line: %d, "
"config file: %s, line no: %d, %s", __LINE__,
pStorageIdsFilename, i + 1, error_info);
break;
}
if ((result=fdfs_check_and_format_ips(&pStorageIdInfo->ip_addrs,
error_info, sizeof(error_info))) != 0)
{
logError("file: "__FILE__", line: %d, "
"config file: %s, line no: %d, %s", __LINE__,
pStorageIdsFilename, i + 1, error_info);
break;
}
if (!fdfs_is_server_id_valid(id))
{
logError("file: "__FILE__", line: %d, " \
"invalid server id: \"%s\", " \
"which must be a none zero start " \
"integer, such as 100001", __LINE__, id);
result = EINVAL;
break;
}
snprintf(pStorageIdInfo->id,
sizeof(pStorageIdInfo->id), "%s", id);
snprintf(pStorageIdInfo->group_name,
sizeof(pStorageIdInfo->group_name),
"%s", group_name);
pStorageIdInfo++;
}
} while (0);
freeSplit(lines);
if (result != 0)
{
return result;
}
if (g_log_context.log_level >= LOG_DEBUG)
{
logDebug("file: "__FILE__", line: %d, "
"g_storage_ids_by_id.count: %d",
__LINE__, g_storage_ids_by_id.count);
pStorageIdInfo = g_storage_ids_by_id.ids;
for (i=0; i<g_storage_ids_by_id.count; i++)
{
char szPortPart[16];
char ip_str[256];
if (pStorageIdInfo->port > 0)
{
sprintf(szPortPart, ":%d", pStorageIdInfo->port);
}
else
{
*szPortPart = '\0';
}
fdfs_multi_ips_to_string(&pStorageIdInfo->ip_addrs,
ip_str, sizeof(ip_str));
logDebug("%s %s %s%s", pStorageIdInfo->id,
pStorageIdInfo->group_name, ip_str, szPortPart);
pStorageIdInfo++;
}
}
qsort(g_storage_ids_by_id.ids, g_storage_ids_by_id.count,
sizeof(FDFSStorageIdInfo), fdfs_cmp_server_id);
if ((result=fdfs_init_ip_array(&g_storage_ids_by_ip,
fdfs_cmp_group_name_and_ip)) != 0)
{
return result;
}
if ((result=fdfs_init_ip_array(&g_storage_ids_by_ip_port,
fdfs_cmp_ip_and_port)) != 0)
{
return result;
}
return fdfs_check_ip_port();
}
int fdfs_get_storage_ids_from_tracker_server(TrackerServerInfo *pTrackerServer)
{
#define MAX_REQUEST_LOOP 32
TrackerHeader *pHeader;
ConnectionInfo *conn;
char out_buff[sizeof(TrackerHeader) + sizeof(int)];
char *p;
char *response;
struct data_info {
char *buffer; //for free
char *content;
int length;
} data_list[MAX_REQUEST_LOOP];
int list_count;
int total_count;
int current_count;
int result;
int i;
int start_index;
int64_t in_bytes;
if ((conn=tracker_connect_server(pTrackerServer, &result)) == NULL)
{
return result;
}
memset(data_list, 0, sizeof(data_list));
memset(out_buff, 0, sizeof(out_buff));
pHeader = (TrackerHeader *)out_buff;
p = out_buff + sizeof(TrackerHeader);
pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_FETCH_STORAGE_IDS;
long2buff(sizeof(int), pHeader->pkg_len);
start_index = 0;
list_count = 0;
result = 0;
while (1)
{
int2buff(start_index, p);
if ((result=tcpsenddata_nb(conn->sock, out_buff,
sizeof(out_buff), g_fdfs_network_timeout)) != 0)
{
logError("file: "__FILE__", line: %d, "
"send data to tracker server %s:%d fail, "
"errno: %d, error info: %s", __LINE__,
conn->ip_addr, conn->port,
result, STRERROR(result));
}
else
{
response = NULL;
result = fdfs_recv_response(conn, &response, 0, &in_bytes);
if (result != 0)
{
logError("file: "__FILE__", line: %d, "
"fdfs_recv_response fail, result: %d",
__LINE__, result);
}
}
if (result != 0)
{
break;
}
if (in_bytes < 2 * sizeof(int))
{
logError("file: "__FILE__", line: %d, "
"tracker server %s:%d, recv data length: %d "
"is invalid", __LINE__,
conn->ip_addr, conn->port, (int)in_bytes);
result = EINVAL;
break;
}
total_count = buff2int(response);
current_count = buff2int(response + sizeof(int));
if (total_count <= start_index)
{
logError("file: "__FILE__", line: %d, "
"tracker server %s:%d, total storage "
"count: %d is invalid, which <= start "
"index: %d", __LINE__, conn->ip_addr,
conn->port, total_count, start_index);
result = EINVAL;
break;
}
if (current_count <= 0)
{
logError("file: "__FILE__", line: %d, "
"tracker server %s:%d, current storage "
"count: %d is invalid, which <= 0", __LINE__,
conn->ip_addr, conn->port, current_count);
result = EINVAL;
break;
}
data_list[list_count].buffer = response;
data_list[list_count].content = response + 2 * sizeof(int);
data_list[list_count].length = in_bytes - 2 * sizeof(int);
list_count++;
/*
//logInfo("list_count: %d, total_count: %d, current_count: %d",
list_count, total_count, current_count);
*/
start_index += current_count;
if (start_index >= total_count)
{
break;
}
if (list_count == MAX_REQUEST_LOOP)
{
logError("file: "__FILE__", line: %d, " \
"response data from tracker " \
"server %s:%d is too large", \
__LINE__, conn->ip_addr,\
conn->port);
result = ENOSPC;
break;
}
}
tracker_close_connection_ex(conn, result != 0);
if (result == 0)
{
do
{
int total_length;
char *content;
total_length = 0;
for (i=0; i<list_count; i++)
{
total_length += data_list[i].length;
}
content = (char *)malloc(total_length + 1);
if (content == NULL)
{
result = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, total_length + 1, \
result, STRERROR(result));
break;
}
p = content;
for (i=0; i<list_count; i++)
{
memcpy(p, data_list[i].content, data_list[i].length);
p += data_list[i].length;
}
*p = '\0';
//logInfo("list_count: %d, storage ids:\n%s", list_count, content);
result = fdfs_load_storage_ids(content, \
"storage-ids-from-tracker");
free(content);
} while (0);
}
for (i=0; i<list_count; i++)
{
free(data_list[i].buffer);
}
return result;
}
int fdfs_get_storage_ids_from_tracker_group(TrackerServerGroup *pTrackerGroup)
{
TrackerServerInfo *pGServer;
TrackerServerInfo *pTServer;
TrackerServerInfo *pServerStart;
TrackerServerInfo *pServerEnd;
TrackerServerInfo trackerServer;
int result;
int leader_index;
int i;
pTServer = &trackerServer;
pServerEnd = pTrackerGroup->servers + pTrackerGroup->server_count;
leader_index = pTrackerGroup->leader_index;
if (leader_index >= 0)
{
pServerStart = pTrackerGroup->servers + leader_index;
}
else
{
pServerStart = pTrackerGroup->servers;
}
result = ENOENT;
for (i=0; i<5; i++)
{
for (pGServer=pServerStart; pGServer<pServerEnd; pGServer++)
{
memcpy(pTServer, pGServer, sizeof(TrackerServerInfo));
fdfs_server_sock_reset(pTServer);
result = fdfs_get_storage_ids_from_tracker_server(pTServer);
if (result == 0)
{
return result;
}
}
if (pServerStart != pTrackerGroup->servers)
{
pServerStart = pTrackerGroup->servers;
}
sleep(1);
}
return result;
}
int fdfs_load_storage_ids_from_file(const char *config_filename, \
IniContext *pItemContext)
{
char *pStorageIdsFilename;
char *content;
int64_t file_size;
int result;
pStorageIdsFilename = iniGetStrValue(NULL, "storage_ids_filename", \
pItemContext);
if (pStorageIdsFilename == NULL)
{
logError("file: "__FILE__", line: %d, " \
"conf file \"%s\" must have item " \
"\"storage_ids_filename\"!", __LINE__, config_filename);
return ENOENT;
}
if (*pStorageIdsFilename == '\0')
{
logError("file: "__FILE__", line: %d, " \
"conf file \"%s\", storage_ids_filename is emtpy!", \
__LINE__, config_filename);
return EINVAL;
}
if (*pStorageIdsFilename == '/') //absolute path
{
result = getFileContent(pStorageIdsFilename, \
&content, &file_size);
}
else
{
const char *lastSlash = strrchr(config_filename, '/');
if (lastSlash == NULL)
{
result = getFileContent(pStorageIdsFilename, \
&content, &file_size);
}
else
{
char filepath[MAX_PATH_SIZE];
char full_filename[MAX_PATH_SIZE];
int len;
len = lastSlash - config_filename;
if (len >= sizeof(filepath))
{
logError("file: "__FILE__", line: %d, " \
"conf filename: \"%s\" is too long!", \
__LINE__, config_filename);
return ENOSPC;
}
memcpy(filepath, config_filename, len);
*(filepath + len) = '\0';
snprintf(full_filename, sizeof(full_filename), \
"%s/%s", filepath, pStorageIdsFilename);
result = getFileContent(full_filename, \
&content, &file_size);
}
}
if (result != 0)
{
return result;
}
result = fdfs_load_storage_ids(content, pStorageIdsFilename);
free(content);
return result;
}

View File

@ -0,0 +1,82 @@
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS may be copied only under the terms of the GNU General
* Public License V3, which may be found in the FastDFS source kit.
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
//fdfs_server_id_func.h
#ifndef _FDFS_SERVER_ID_FUNC_H
#define _FDFS_SERVER_ID_FUNC_H
#include "fastcommon/common_define.h"
#include "fastcommon/ini_file_reader.h"
#include "fastcommon/logger.h"
#include "tracker_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
char id[FDFS_STORAGE_ID_MAX_SIZE];
char group_name[FDFS_GROUP_NAME_MAX_LEN + 8]; //for 8 bytes alignment
FDFSMultiIP ip_addrs;
int port; //since v5.05
} FDFSStorageIdInfo;
typedef struct
{
const char *group_name;
const char *ip_addr;
int port;
FDFSStorageIdInfo *idInfo;
} FDFSStorageIdMap;
typedef struct
{
int count;
FDFSStorageIdInfo *ids;
} FDFSStorageIdInfoArray;
typedef struct
{
int count;
FDFSStorageIdMap *maps;
} FDFSStorageIdMapArray;
extern FDFSStorageIdInfoArray g_storage_ids_by_id; //sorted by storage ID
extern FDFSStorageIdMapArray g_storage_ids_by_ip; //sorted by group name and storage IP
bool fdfs_is_server_id_valid(const char *id);
int fdfs_get_server_id_type(const int id);
int fdfs_load_storage_ids(char *content, const char *pStorageIdsFilename);
FDFSStorageIdInfo *fdfs_get_storage_by_id(const char *id);
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip(const char *group_name, \
const char *pIpAddr);
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip_port(const char *pIpAddr,
const int port);
int fdfs_check_storage_id(const char *group_name, const char *id);
int fdfs_get_storage_ids_from_tracker_server(TrackerServerInfo *pTrackerServer);
int fdfs_get_storage_ids_from_tracker_group(TrackerServerGroup *pTrackerGroup);
int fdfs_load_storage_ids_from_file(const char *config_filename, \
IniContext *pItemContext);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -17,12 +17,6 @@
#include "fdfs_global.h" #include "fdfs_global.h"
#include "fdfs_shared_func.h" #include "fdfs_shared_func.h"
FDFSStorageIdInfo *g_storage_ids_by_ip = NULL; //sorted by group name and storage IP
FDFSStorageIdInfo **g_storage_ids_by_id = NULL; //sorted by storage ID
static FDFSStorageIdInfo **g_storage_ids_by_ip_port = NULL; //sorted by storage ip and port
int g_storage_id_count = 0;
bool fdfs_server_contain(TrackerServerInfo *pServerInfo, bool fdfs_server_contain(TrackerServerInfo *pServerInfo,
const char *target_ip, const int target_port) const char *target_ip, const int target_port)
{ {
@ -359,749 +353,6 @@ bool fdfs_check_reserved_space_path(const int64_t total_mb, \
} }
} }
bool fdfs_is_server_id_valid(const char *id)
{
long n;
char *endptr;
char buff[FDFS_STORAGE_ID_MAX_SIZE];
if (*id == '\0')
{
return false;
}
endptr = NULL;
n = strtol(id, &endptr, 10);
if (endptr != NULL && *endptr != '\0')
{
return false;
}
if (n <= 0 || n > FDFS_MAX_SERVER_ID)
{
return false;
}
snprintf(buff, sizeof(buff), "%ld", n);
return strcmp(buff, id) == 0;
}
int fdfs_get_server_id_type(const int id)
{
if (id > 0 && id <= FDFS_MAX_SERVER_ID)
{
return FDFS_ID_TYPE_SERVER_ID;
}
else
{
return FDFS_ID_TYPE_IP_ADDRESS;
}
}
static int fdfs_cmp_group_name_and_ip(const void *p1, const void *p2)
{
int result;
result = strcmp(((FDFSStorageIdInfo *)p1)->group_name,
((FDFSStorageIdInfo *)p2)->group_name);
if (result != 0)
{
return result;
}
return strcmp(((FDFSStorageIdInfo *)p1)->ip_addr, \
((FDFSStorageIdInfo *)p2)->ip_addr);
}
static int fdfs_cmp_server_id(const void *p1, const void *p2)
{
return strcmp((*((FDFSStorageIdInfo **)p1))->id, \
(*((FDFSStorageIdInfo **)p2))->id);
}
static int fdfs_cmp_ip_and_port(const void *p1, const void *p2)
{
int result;
result = strcmp((*((FDFSStorageIdInfo **)p1))->ip_addr,
(*((FDFSStorageIdInfo **)p2))->ip_addr);
if (result != 0)
{
return result;
}
return (*((FDFSStorageIdInfo **)p1))->port -
(*((FDFSStorageIdInfo **)p2))->port;
}
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip(const char *group_name, \
const char *pIpAddr)
{
FDFSStorageIdInfo target;
memset(&target, 0, sizeof(FDFSStorageIdInfo));
snprintf(target.group_name, sizeof(target.group_name), "%s", group_name);
snprintf(target.ip_addr, sizeof(target.ip_addr), "%s", pIpAddr);
return (FDFSStorageIdInfo *)bsearch(&target, g_storage_ids_by_ip, \
g_storage_id_count, sizeof(FDFSStorageIdInfo), \
fdfs_cmp_group_name_and_ip);
}
FDFSStorageIdInfo *fdfs_get_storage_by_id(const char *id)
{
FDFSStorageIdInfo target;
FDFSStorageIdInfo *pTarget;
FDFSStorageIdInfo **ppFound;
memset(&target, 0, sizeof(FDFSStorageIdInfo));
snprintf(target.id, sizeof(target.id), "%s", id);
pTarget = &target;
ppFound = (FDFSStorageIdInfo **)bsearch(&pTarget, g_storage_ids_by_id, \
g_storage_id_count, sizeof(FDFSStorageIdInfo *), \
fdfs_cmp_server_id);
if (ppFound == NULL)
{
return NULL;
}
else
{
return *ppFound;
}
}
static int fdfs_init_ip_port_array()
{
int result;
int alloc_bytes;
int i;
int port_count;
FDFSStorageIdInfo *previous;
alloc_bytes = sizeof(FDFSStorageIdInfo *) * g_storage_id_count;
g_storage_ids_by_ip_port = (FDFSStorageIdInfo **)malloc(alloc_bytes);
if (g_storage_ids_by_ip_port == 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;
}
port_count = 0;
for (i=0; i<g_storage_id_count; i++)
{
g_storage_ids_by_ip_port[i] = g_storage_ids_by_ip + i;
if (g_storage_ids_by_ip_port[i]->port > 0)
{
port_count++;
}
}
if (port_count > 0 && port_count != g_storage_id_count)
{
logError("file: "__FILE__", line: %d, "
"config file: storage_ids.conf, some storages without port, "
"must be the same format as host:port", __LINE__);
free(g_storage_ids_by_ip_port);
g_storage_ids_by_ip_port = NULL;
return EINVAL;
}
qsort(g_storage_ids_by_ip_port, g_storage_id_count,
sizeof(FDFSStorageIdInfo *), fdfs_cmp_ip_and_port);
previous = g_storage_ids_by_ip_port[0];
for (i=1; i<g_storage_id_count; i++)
{
if (fdfs_cmp_ip_and_port(&g_storage_ids_by_ip_port[i],
&previous) == 0)
{
char szPortPart[16];
if (previous->port > 0)
{
sprintf(szPortPart, ":%d", previous->port);
}
else
{
*szPortPart = '\0';
}
logError("file: "__FILE__", line: %d, "
"config file: storage_ids.conf, "
"duplicate storage: %s%s", __LINE__,
previous->ip_addr, szPortPart);
free(g_storage_ids_by_ip_port);
g_storage_ids_by_ip_port = NULL;
return EEXIST;
}
previous = g_storage_ids_by_ip_port[i];
}
return 0;
}
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip_port(const char *pIpAddr,
const int port)
{
FDFSStorageIdInfo target;
FDFSStorageIdInfo *pTarget;
FDFSStorageIdInfo **ppFound;
int ports[2];
int i;
if (g_storage_ids_by_ip_port == NULL)
{
if (fdfs_init_ip_port_array() != 0)
{
return NULL;
}
}
pTarget = &target;
memset(&target, 0, sizeof(FDFSStorageIdInfo));
snprintf(target.ip_addr, sizeof(target.ip_addr), "%s", pIpAddr);
ports[0] = port;
ports[1] = 0;
for (i=0; i<2; i++)
{
target.port = ports[i];
ppFound = (FDFSStorageIdInfo **)bsearch(&pTarget,
g_storage_ids_by_ip_port, g_storage_id_count,
sizeof(FDFSStorageIdInfo *), fdfs_cmp_ip_and_port);
if (ppFound != NULL)
{
return *ppFound;
}
}
return NULL;
}
int fdfs_check_storage_id(const char *group_name, const char *id)
{
FDFSStorageIdInfo *pFound;
pFound = fdfs_get_storage_by_id(id);
if (pFound == NULL)
{
return ENOENT;
}
return strcmp(pFound->group_name, group_name) == 0 ? 0 : EINVAL;
}
int fdfs_load_storage_ids(char *content, const char *pStorageIdsFilename)
{
char **lines;
char *line;
char *id;
char *group_name;
char *pHost;
char *pIpAddr;
char *pPort;
FDFSStorageIdInfo *pStorageIdInfo;
FDFSStorageIdInfo **ppStorageIdInfo;
FDFSStorageIdInfo **ppStorageIdEnd;
int alloc_bytes;
int result;
int line_count;
int i;
lines = split(content, '\n', 0, &line_count);
if (lines == NULL)
{
return ENOMEM;
}
result = 0;
do
{
g_storage_id_count = 0;
for (i=0; i<line_count; i++)
{
trim(lines[i]);
if (*lines[i] == '\0' || *lines[i] == '#')
{
continue;
}
g_storage_id_count++;
}
if (g_storage_id_count == 0)
{
logError("file: "__FILE__", line: %d, " \
"config file: %s, no storage id!", \
__LINE__, pStorageIdsFilename);
result = ENOENT;
break;
}
alloc_bytes = sizeof(FDFSStorageIdInfo) * g_storage_id_count;
g_storage_ids_by_ip = (FDFSStorageIdInfo *)malloc(alloc_bytes);
if (g_storage_ids_by_ip == 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));
break;
}
memset(g_storage_ids_by_ip, 0, alloc_bytes);
alloc_bytes = sizeof(FDFSStorageIdInfo *) * g_storage_id_count;
g_storage_ids_by_id = (FDFSStorageIdInfo **)malloc(alloc_bytes);
if (g_storage_ids_by_id == 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));
free(g_storage_ids_by_ip);
break;
}
memset(g_storage_ids_by_id, 0, alloc_bytes);
pStorageIdInfo = g_storage_ids_by_ip;
for (i=0; i<line_count; i++)
{
line = lines[i];
if (*line == '\0' || *line == '#')
{
continue;
}
id = line;
group_name = line;
while (!(*group_name == ' ' || *group_name == '\t' \
|| *group_name == '\0'))
{
group_name++;
}
if (*group_name == '\0')
{
logError("file: "__FILE__", line: %d, " \
"config file: %s, line no: %d, " \
"content: %s, invalid format, " \
"expect group name and ip address!", \
__LINE__, pStorageIdsFilename, \
i + 1, line);
result = EINVAL;
break;
}
*group_name = '\0';
group_name++; //skip space char
while (*group_name == ' ' || *group_name == '\t')
{
group_name++;
}
pHost = group_name;
while (!(*pHost == ' ' || *pHost == '\t' \
|| *pHost == '\0'))
{
pHost++;
}
if (*pHost == '\0')
{
logError("file: "__FILE__", line: %d, " \
"config file: %s, line no: %d, " \
"content: %s, invalid format, " \
"expect ip address!", __LINE__, \
pStorageIdsFilename, i + 1, line);
result = EINVAL;
break;
}
*pHost = '\0';
pHost++; //skip space char
while (*pHost == ' ' || *pHost == '\t')
{
pHost++;
}
pIpAddr = pHost;
pPort = strchr(pHost, ':');
if (pPort != NULL)
{
*pPort = '\0';
pStorageIdInfo->port = atoi(pPort + 1);
}
else
{
pStorageIdInfo->port = 0;
}
if (getIpaddrByName(pIpAddr, pStorageIdInfo->ip_addr, \
sizeof(pStorageIdInfo->ip_addr)) == INADDR_NONE)
{
logError("file: "__FILE__", line: %d, " \
"invalid host name: %s", __LINE__, pIpAddr);
result = EINVAL;
break;
}
if (!fdfs_is_server_id_valid(id))
{
logError("file: "__FILE__", line: %d, " \
"invalid server id: \"%s\", " \
"which must be a none zero start " \
"integer, such as 100001", __LINE__, id);
result = EINVAL;
break;
}
snprintf(pStorageIdInfo->id, \
sizeof(pStorageIdInfo->id), "%s", id);
snprintf(pStorageIdInfo->group_name, \
sizeof(pStorageIdInfo->group_name), \
"%s", group_name);
pStorageIdInfo++;
}
} while (0);
freeSplit(lines);
if (result != 0)
{
return result;
}
logDebug("file: "__FILE__", line: %d, " \
"g_storage_id_count: %d", __LINE__, g_storage_id_count);
pStorageIdInfo = g_storage_ids_by_ip;
for (i=0; i<g_storage_id_count; i++)
{
char szPortPart[16];
if (pStorageIdInfo->port > 0)
{
sprintf(szPortPart, ":%d", pStorageIdInfo->port);
}
else
{
*szPortPart = '\0';
}
logDebug("%s %s %s%s", pStorageIdInfo->id,
pStorageIdInfo->group_name,
pStorageIdInfo->ip_addr, szPortPart);
pStorageIdInfo++;
}
ppStorageIdEnd = g_storage_ids_by_id + g_storage_id_count;
pStorageIdInfo = g_storage_ids_by_ip;
for (ppStorageIdInfo=g_storage_ids_by_id; ppStorageIdInfo < \
ppStorageIdEnd; ppStorageIdInfo++)
{
*ppStorageIdInfo = pStorageIdInfo++;
}
qsort(g_storage_ids_by_ip, g_storage_id_count, \
sizeof(FDFSStorageIdInfo), fdfs_cmp_group_name_and_ip);
qsort(g_storage_ids_by_id, g_storage_id_count, \
sizeof(FDFSStorageIdInfo *), fdfs_cmp_server_id);
return result;
}
int fdfs_get_storage_ids_from_tracker_server(TrackerServerInfo *pTrackerServer)
{
#define MAX_REQUEST_LOOP 32
TrackerHeader *pHeader;
ConnectionInfo *conn;
char out_buff[sizeof(TrackerHeader) + sizeof(int)];
char *p;
char *response;
struct data_info {
char *buffer; //for free
char *content;
int length;
} data_list[MAX_REQUEST_LOOP];
int list_count;
int total_count;
int current_count;
int result;
int i;
int start_index;
int64_t in_bytes;
if ((conn=tracker_connect_server(pTrackerServer, &result)) == NULL)
{
return result;
}
memset(data_list, 0, sizeof(data_list));
memset(out_buff, 0, sizeof(out_buff));
pHeader = (TrackerHeader *)out_buff;
p = out_buff + sizeof(TrackerHeader);
pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_FETCH_STORAGE_IDS;
long2buff(sizeof(int), pHeader->pkg_len);
start_index = 0;
list_count = 0;
result = 0;
while (1)
{
int2buff(start_index, p);
if ((result=tcpsenddata_nb(conn->sock, out_buff,
sizeof(out_buff), g_fdfs_network_timeout)) != 0)
{
logError("file: "__FILE__", line: %d, "
"send data to tracker server %s:%d fail, "
"errno: %d, error info: %s", __LINE__,
conn->ip_addr, conn->port,
result, STRERROR(result));
}
else
{
response = NULL;
result = fdfs_recv_response(conn, &response, 0, &in_bytes);
if (result != 0)
{
logError("file: "__FILE__", line: %d, "
"fdfs_recv_response fail, result: %d",
__LINE__, result);
}
}
if (result != 0)
{
break;
}
if (in_bytes < 2 * sizeof(int))
{
logError("file: "__FILE__", line: %d, "
"tracker server %s:%d, recv data length: %d "
"is invalid", __LINE__,
conn->ip_addr, conn->port, (int)in_bytes);
result = EINVAL;
break;
}
total_count = buff2int(response);
current_count = buff2int(response + sizeof(int));
if (total_count <= start_index)
{
logError("file: "__FILE__", line: %d, "
"tracker server %s:%d, total storage "
"count: %d is invalid, which <= start "
"index: %d", __LINE__, conn->ip_addr,
conn->port, total_count, start_index);
result = EINVAL;
break;
}
if (current_count <= 0)
{
logError("file: "__FILE__", line: %d, "
"tracker server %s:%d, current storage "
"count: %d is invalid, which <= 0", __LINE__,
conn->ip_addr, conn->port, current_count);
result = EINVAL;
break;
}
data_list[list_count].buffer = response;
data_list[list_count].content = response + 2 * sizeof(int);
data_list[list_count].length = in_bytes - 2 * sizeof(int);
list_count++;
/*
//logInfo("list_count: %d, total_count: %d, current_count: %d",
list_count, total_count, current_count);
*/
start_index += current_count;
if (start_index >= total_count)
{
break;
}
if (list_count == MAX_REQUEST_LOOP)
{
logError("file: "__FILE__", line: %d, " \
"response data from tracker " \
"server %s:%d is too large", \
__LINE__, conn->ip_addr,\
conn->port);
result = ENOSPC;
break;
}
}
tracker_close_connection_ex(conn, result != 0);
if (result == 0)
{
do
{
int total_length;
char *content;
total_length = 0;
for (i=0; i<list_count; i++)
{
total_length += data_list[i].length;
}
content = (char *)malloc(total_length + 1);
if (content == NULL)
{
result = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, total_length + 1, \
result, STRERROR(result));
break;
}
p = content;
for (i=0; i<list_count; i++)
{
memcpy(p, data_list[i].content, data_list[i].length);
p += data_list[i].length;
}
*p = '\0';
//logInfo("list_count: %d, storage ids:\n%s", list_count, content);
result = fdfs_load_storage_ids(content, \
"storage-ids-from-tracker");
free(content);
} while (0);
}
for (i=0; i<list_count; i++)
{
free(data_list[i].buffer);
}
return result;
}
int fdfs_get_storage_ids_from_tracker_group(TrackerServerGroup *pTrackerGroup)
{
TrackerServerInfo *pGServer;
TrackerServerInfo *pTServer;
TrackerServerInfo *pServerStart;
TrackerServerInfo *pServerEnd;
TrackerServerInfo trackerServer;
int result;
int leader_index;
int i;
pTServer = &trackerServer;
pServerEnd = pTrackerGroup->servers + pTrackerGroup->server_count;
leader_index = pTrackerGroup->leader_index;
if (leader_index >= 0)
{
pServerStart = pTrackerGroup->servers + leader_index;
}
else
{
pServerStart = pTrackerGroup->servers;
}
result = ENOENT;
for (i=0; i<5; i++)
{
for (pGServer=pServerStart; pGServer<pServerEnd; pGServer++)
{
memcpy(pTServer, pGServer, sizeof(TrackerServerInfo));
fdfs_server_sock_reset(pTServer);
result = fdfs_get_storage_ids_from_tracker_server(pTServer);
if (result == 0)
{
return result;
}
}
if (pServerStart != pTrackerGroup->servers)
{
pServerStart = pTrackerGroup->servers;
}
sleep(1);
}
return result;
}
int fdfs_load_storage_ids_from_file(const char *config_filename, \
IniContext *pItemContext)
{
char *pStorageIdsFilename;
char *content;
int64_t file_size;
int result;
pStorageIdsFilename = iniGetStrValue(NULL, "storage_ids_filename", \
pItemContext);
if (pStorageIdsFilename == NULL)
{
logError("file: "__FILE__", line: %d, " \
"conf file \"%s\" must have item " \
"\"storage_ids_filename\"!", __LINE__, config_filename);
return ENOENT;
}
if (*pStorageIdsFilename == '\0')
{
logError("file: "__FILE__", line: %d, " \
"conf file \"%s\", storage_ids_filename is emtpy!", \
__LINE__, config_filename);
return EINVAL;
}
if (*pStorageIdsFilename == '/') //absolute path
{
result = getFileContent(pStorageIdsFilename, \
&content, &file_size);
}
else
{
const char *lastSlash = strrchr(config_filename, '/');
if (lastSlash == NULL)
{
result = getFileContent(pStorageIdsFilename, \
&content, &file_size);
}
else
{
char filepath[MAX_PATH_SIZE];
char full_filename[MAX_PATH_SIZE];
int len;
len = lastSlash - config_filename;
if (len >= sizeof(filepath))
{
logError("file: "__FILE__", line: %d, " \
"conf filename: \"%s\" is too long!", \
__LINE__, config_filename);
return ENOSPC;
}
memcpy(filepath, config_filename, len);
*(filepath + len) = '\0';
snprintf(full_filename, sizeof(full_filename), \
"%s/%s", filepath, pStorageIdsFilename);
result = getFileContent(full_filename, \
&content, &file_size);
}
}
if (result != 0)
{
return result;
}
result = fdfs_load_storage_ids(content, pStorageIdsFilename);
free(content);
return result;
}
int fdfs_connection_pool_init(const char *config_filename, \ int fdfs_connection_pool_init(const char *config_filename, \
IniContext *pItemContext) IniContext *pItemContext)
{ {
@ -1198,13 +449,18 @@ int fdfs_parse_server_info_ex(char *server_str, const int default_port,
return 0; return 0;
} }
int fdfs_server_info_to_string_ex(TrackerServerInfo *pServer, int fdfs_server_info_to_string_ex(const TrackerServerInfo *pServer,
const int port, char *buff, const int buffSize) const int port, char *buff, const int buffSize)
{ {
ConnectionInfo *conn; const ConnectionInfo *conn;
ConnectionInfo *end; const ConnectionInfo *end;
int len; int len;
if (pServer->count <= 0)
{
*buff = '\0';
return 0;
}
if (pServer->count == 1) if (pServer->count == 1)
{ {
return snprintf(buff, buffSize, "%s:%d", return snprintf(buff, buffSize, "%s:%d",
@ -1221,7 +477,7 @@ int fdfs_server_info_to_string_ex(TrackerServerInfo *pServer,
return len; return len;
} }
int fdfs_check_server_ips(TrackerServerInfo *pServer, int fdfs_check_server_ips(const TrackerServerInfo *pServer,
char *error_info, const int error_size) char *error_info, const int error_size)
{ {
int private0; int private0;
@ -1262,3 +518,126 @@ int fdfs_check_server_ips(TrackerServerInfo *pServer,
*error_info = '\0'; *error_info = '\0';
return 0; return 0;
} }
int fdfs_parse_multi_ips_ex(char *ip_str, FDFSMultiIP *ip_addrs,
char *error_info, const int error_size, const bool resolve)
{
char *hosts[FDFS_MULTI_IP_MAX_COUNT];
int i;
ip_addrs->count = splitEx(ip_str, ',', hosts, FDFS_MULTI_IP_MAX_COUNT);
for (i=0; i<ip_addrs->count; i++)
{
if (resolve)
{
if (getIpaddrByName(hosts[i], ip_addrs->ips[i],
sizeof(ip_addrs->ips[i])) == INADDR_NONE)
{
snprintf(error_info, error_size,
"host \"%s\" is invalid, error info: %s",
hosts[i], hstrerror(h_errno));
return EINVAL;
}
}
else
{
snprintf(ip_addrs->ips[i], sizeof(ip_addrs->ips[i]), "%s", hosts[i]);
}
}
*error_info = '\0';
return 0;
}
int fdfs_multi_ips_to_string_ex(const FDFSMultiIP *ip_addrs,
const char seperator, char *buff, const int buffSize)
{
int i;
int len;
if (ip_addrs->count <= 0)
{
*buff = '\0';
return 0;
}
if (ip_addrs->count == 1)
{
return snprintf(buff, buffSize, "%s",
ip_addrs->ips[0]);
}
len = snprintf(buff, buffSize, "%s", ip_addrs->ips[0]);
for (i=1; i<ip_addrs->count; i++)
{
len += snprintf(buff + len, buffSize - len, "%c%s",
seperator, ip_addrs->ips[i]);
}
return len;
}
const char *fdfs_get_ipaddr_by_client_ip(const FDFSMultiIP *ip_addrs,
const char *client_ip)
{
int index;
if (ip_addrs->count == 1)
{
return ip_addrs->ips[0];
}
if (ip_addrs->count <= 0)
{
return "";
}
index = is_private_ip(client_ip) ? FDFS_MULTI_IP_INDEX_INNER : FDFS_MULTI_IP_INDEX_OUTER;
return ip_addrs->ips[index];
}
int fdfs_check_and_format_ips(FDFSMultiIP *ip_addrs,
char *error_info, const int error_size)
{
int privates[FDFS_MULTI_IP_MAX_COUNT];
char swap_ip[IP_ADDRESS_SIZE];
if (ip_addrs->count == 1)
{
*error_info = '\0';
return 0;
}
if (ip_addrs->count <= 0)
{
logError("file: "__FILE__", line: %d, "
"empty server", __LINE__);
return EINVAL;
}
if (ip_addrs->count > FDFS_MULTI_IP_MAX_COUNT)
{
snprintf(error_info, error_size,
"too many server ip addresses: %d, exceeds %d",
ip_addrs->count, FDFS_MULTI_IP_MAX_COUNT);
return EINVAL;
}
privates[0] = is_private_ip(ip_addrs->ips[0]) ? 1 : 0;
privates[1] = is_private_ip(ip_addrs->ips[1]) ? 1 : 0;
if ((privates[0] ^ privates[1]) == 0)
{
snprintf(error_info, error_size,
"invalid ip addresses %s and %s, "
"one MUST be an inner IP and another is a outer IP",
ip_addrs->ips[0], ip_addrs->ips[1]);
return EINVAL;
}
if (!privates[FDFS_MULTI_IP_INDEX_INNER])
{
strcpy(swap_ip, ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER]);
strcpy(ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER],
ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER]);
strcpy(ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER], swap_ip);
}
*error_info = '\0';
return 0;
}

View File

@ -15,15 +15,12 @@
#include "fastcommon/ini_file_reader.h" #include "fastcommon/ini_file_reader.h"
#include "fastcommon/logger.h" #include "fastcommon/logger.h"
#include "tracker_types.h" #include "tracker_types.h"
#include "fdfs_server_id_func.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern FDFSStorageIdInfo *g_storage_ids_by_ip; //sorted by group name and storage IP
extern FDFSStorageIdInfo **g_storage_ids_by_id; //sorted by storage ID
extern int g_storage_id_count; //storage id count
int fdfs_get_tracker_leader_index_ex(TrackerServerGroup *pServerGroup, \ int fdfs_get_tracker_leader_index_ex(TrackerServerGroup *pServerGroup, \
const char *leaderIp, const int leaderPort); const char *leaderIp, const int leaderPort);
@ -50,29 +47,6 @@ bool fdfs_check_reserved_space_path(const int64_t total_mb, \
const int64_t free_mb, const int avg_mb, \ const int64_t free_mb, const int avg_mb, \
FDFSStorageReservedSpace *pStorageReservedSpace); FDFSStorageReservedSpace *pStorageReservedSpace);
bool fdfs_is_server_id_valid(const char *id);
int fdfs_get_server_id_type(const int id);
int fdfs_load_storage_ids(char *content, const char *pStorageIdsFilename);
FDFSStorageIdInfo *fdfs_get_storage_by_id(const char *id);
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip(const char *group_name, \
const char *pIpAddr);
FDFSStorageIdInfo *fdfs_get_storage_id_by_ip_port(const char *pIpAddr,
const int port);
int fdfs_check_storage_id(const char *group_name, const char *id);
int fdfs_get_storage_ids_from_tracker_server(TrackerServerInfo *pTrackerServer);
int fdfs_get_storage_ids_from_tracker_group(TrackerServerGroup *pTrackerGroup);
int fdfs_load_storage_ids_from_file(const char *config_filename, \
IniContext *pItemContext);
int fdfs_connection_pool_init(const char *config_filename, \ int fdfs_connection_pool_init(const char *config_filename, \
IniContext *pItemContext); IniContext *pItemContext);
@ -108,19 +82,46 @@ static inline int fdfs_parse_server_info(char *server_str, const int default_por
pServer, resolve); pServer, resolve);
} }
int fdfs_server_info_to_string_ex(TrackerServerInfo *pServer, int fdfs_server_info_to_string_ex(const TrackerServerInfo *pServer,
const int port, char *buff, const int buffSize); const int port, char *buff, const int buffSize);
static inline int fdfs_server_info_to_string(TrackerServerInfo *pServer, static inline int fdfs_server_info_to_string(const TrackerServerInfo *pServer,
char *buff, const int buffSize) char *buff, const int buffSize)
{ {
return fdfs_server_info_to_string_ex(pServer, return fdfs_server_info_to_string_ex(pServer,
pServer->connections[0].port, buff, buffSize); pServer->connections[0].port, buff, buffSize);
} }
int fdfs_check_server_ips(TrackerServerInfo *pServer, int fdfs_multi_ips_to_string_ex(const FDFSMultiIP *ip_addrs,
const char seperator, char *buff, const int buffSize);
static inline int fdfs_multi_ips_to_string(const FDFSMultiIP *ip_addrs,
char *buff, const int buffSize)
{
const char seperator = ',';
return fdfs_multi_ips_to_string_ex(ip_addrs, seperator, buff, buffSize);
}
int fdfs_parse_multi_ips_ex(char *ip_str, FDFSMultiIP *ip_addrs,
char *error_info, const int error_size, const bool resolve);
static inline int fdfs_parse_multi_ips(char *ip_str, FDFSMultiIP *ip_addrs,
char *error_info, const int error_size)
{
const bool resolve = true;
return fdfs_parse_multi_ips_ex(ip_str, ip_addrs,
error_info, error_size, resolve);
}
int fdfs_check_server_ips(const TrackerServerInfo *pServer,
char *error_info, const int error_size); char *error_info, const int error_size);
int fdfs_check_and_format_ips(FDFSMultiIP *ip_addrs,
char *error_info, const int error_size);
const char *fdfs_get_ipaddr_by_client_ip(const FDFSMultiIP *ip_addrs,
const char *client_ip);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -124,9 +124,9 @@ static void tracker_mem_find_store_server(FDFSGroupInfo *pGroup);
static int tracker_mem_find_trunk_server(FDFSGroupInfo *pGroup, static int tracker_mem_find_trunk_server(FDFSGroupInfo *pGroup,
const bool save); const bool save);
static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup, \ static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup,
FDFSStorageDetail **ppStorageServer, const char *id, \ FDFSStorageDetail **ppStorageServer, const char *id,
const char *ip_addr, const bool bNeedSleep, \ const char *ip_addr, const bool bNeedSleep,
const bool bNeedLock, bool *bInserted); const bool bNeedLock, bool *bInserted);
static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo, \ static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo, \
@ -1849,6 +1849,7 @@ int tracker_save_storages()
char trueFilename[MAX_PATH_SIZE]; char trueFilename[MAX_PATH_SIZE];
char buff[4096]; char buff[4096];
char id_buff[128]; char id_buff[128];
char ip_buff[256];
int fd; int fd;
int len; int len;
FDFSGroupInfo **ppGroup; FDFSGroupInfo **ppGroup;
@ -1895,10 +1896,13 @@ int tracker_save_storages()
if (g_use_storage_id) if (g_use_storage_id)
{ {
sprintf(id_buff, "\t%s=%s\n", \ sprintf(id_buff, "\t%s=%s\n",
STORAGE_ITEM_SERVER_ID, pStorage->id); STORAGE_ITEM_SERVER_ID, pStorage->id);
} }
fdfs_multi_ips_to_string(&pStorage->ip_addrs,
ip_buff, sizeof(ip_buff));
count++; count++;
len = sprintf(buff, \ len = sprintf(buff, \
"# storage %s:%d\n" \ "# storage %s:%d\n" \
@ -1956,11 +1960,11 @@ int tracker_save_storages()
"\t%s=%d\n" \ "\t%s=%d\n" \
"\t%s=%d\n" \ "\t%s=%d\n" \
"\t%s=%"PRId64"\n\n", \ "\t%s=%"PRId64"\n\n", \
pStorage->ip_addr, pStorage->storage_port, \ ip_buff, pStorage->storage_port, \
STORAGE_SECTION_NAME_PREFIX, count, id_buff, \ STORAGE_SECTION_NAME_PREFIX, count, id_buff, \
STORAGE_ITEM_GROUP_NAME, \ STORAGE_ITEM_GROUP_NAME, \
(*ppGroup)->group_name, \ (*ppGroup)->group_name, \
STORAGE_ITEM_IP_ADDR, pStorage->ip_addr, \ STORAGE_ITEM_IP_ADDR, ip_buff, \
STORAGE_ITEM_STATUS, pStorage->status, \ STORAGE_ITEM_STATUS, pStorage->status, \
STORAGE_ITEM_VERSION, pStorage->version, \ STORAGE_ITEM_VERSION, pStorage->version, \
STORAGE_ITEM_JOIN_TIME, \ STORAGE_ITEM_JOIN_TIME, \
@ -3491,7 +3495,7 @@ int tracker_mem_delete_storage(FDFSGroupInfo *pGroup, const char *id)
logDebug("file: "__FILE__", line: %d, " \ logDebug("file: "__FILE__", line: %d, " \
"delete storage server: %s:%d, group: %s", \ "delete storage server: %s:%d, group: %s", \
__LINE__, pStorageServer->ip_addr, __LINE__, pStorageServer->ip_addrs.ips[0],
pStorageServer->storage_port, pGroup->group_name); pStorageServer->storage_port, pGroup->group_name);
tracker_mem_clear_storage_fields(pStorageServer); tracker_mem_clear_storage_fields(pStorageServer);
@ -3579,19 +3583,20 @@ int tracker_mem_storage_ip_changed(FDFSGroupInfo *pGroup, \
//exchange old and new storage server //exchange old and new storage server
snprintf(pOldStorageServer->id, sizeof(pOldStorageServer->id), \ snprintf(pOldStorageServer->id, sizeof(pOldStorageServer->id), \
"%s", new_storage_ip); "%s", new_storage_ip);
snprintf(pOldStorageServer->ip_addr, \ snprintf(pOldStorageServer->ip_addrs.ips[0],
sizeof(pOldStorageServer->ip_addr), "%s", new_storage_ip); sizeof(pOldStorageServer->ip_addrs.ips[0]), "%s", new_storage_ip);
snprintf(pNewStorageServer->id, sizeof(pNewStorageServer->id), \ snprintf(pNewStorageServer->id, sizeof(pNewStorageServer->id), \
"%s", old_storage_ip); "%s", old_storage_ip);
snprintf(pNewStorageServer->ip_addr, \ pNewStorageServer->ip_addrs.count = 1;
sizeof(pNewStorageServer->ip_addr), "%s", old_storage_ip); snprintf(pNewStorageServer->ip_addrs.ips[0],
sizeof(pNewStorageServer->ip_addrs.ips[0]), "%s", old_storage_ip);
pNewStorageServer->status = FDFS_STORAGE_STATUS_IP_CHANGED; pNewStorageServer->status = FDFS_STORAGE_STATUS_IP_CHANGED;
pGroup->chg_count++; pGroup->chg_count++;
//need re-sort //need re-sort
qsort(pGroup->sorted_servers, pGroup->count, \ qsort(pGroup->sorted_servers, pGroup->count,
sizeof(FDFSStorageDetail *), tracker_mem_cmp_by_storage_id); sizeof(FDFSStorageDetail *), tracker_mem_cmp_by_storage_id);
pthread_mutex_unlock(&mem_thread_lock); pthread_mutex_unlock(&mem_thread_lock);
@ -3601,8 +3606,8 @@ int tracker_mem_storage_ip_changed(FDFSGroupInfo *pGroup, \
return tracker_save_sys_files(); return tracker_save_sys_files();
} }
static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo, \ static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo,
const char *id, const char *ip_addr, \ const char *id, const char *ip_addr,
const bool bNeedSleep, const bool bNeedLock, bool *bInserted) const bool bNeedSleep, const bool bNeedLock, bool *bInserted)
{ {
int result; int result;
@ -3620,9 +3625,9 @@ static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo, \
return result; return result;
} }
static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup, \ static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup,
FDFSStorageDetail **ppStorageServer, const char *id, \ FDFSStorageDetail **ppStorageServer, const char *id,
const char *ip_addr, const bool bNeedSleep, \ const char *ip_addr, const bool bNeedSleep,
const bool bNeedLock, bool *bInserted) const bool bNeedLock, bool *bInserted)
{ {
int result; int result;

View File

@ -272,12 +272,18 @@ typedef struct
char sz_last_heart_beat_time[8]; char sz_last_heart_beat_time[8];
} FDFSStorageStatBuff; } FDFSStorageStatBuff;
typedef struct StructFDFSMultiIP
{
int count;
char ips[FDFS_MULTI_IP_MAX_COUNT][IP_ADDRESS_SIZE];
} FDFSMultiIP;
typedef struct StructFDFSStorageDetail typedef struct StructFDFSStorageDetail
{ {
char status; char status;
char padding; //just for padding char padding; //just for padding
char id[FDFS_STORAGE_ID_MAX_SIZE]; char id[FDFS_STORAGE_ID_MAX_SIZE];
char ip_addr[IP_ADDRESS_SIZE]; FDFSMultiIP ip_addrs;
char version[FDFS_VERSION_SIZE]; char version[FDFS_VERSION_SIZE];
char domain_name[FDFS_DOMAIN_NAME_MAX_SIZE]; char domain_name[FDFS_DOMAIN_NAME_MAX_SIZE];
@ -429,14 +435,6 @@ typedef struct
int version; //for binlog pre-read, compare with binlog_write_version int version; //for binlog pre-read, compare with binlog_write_version
} BinLogBuffer; } BinLogBuffer;
typedef struct
{
char id[FDFS_STORAGE_ID_MAX_SIZE];
char group_name[FDFS_GROUP_NAME_MAX_LEN + 8]; //for 8 bytes alignment
char ip_addr[IP_ADDRESS_SIZE];
int port; //since v5.05
} FDFSStorageIdInfo;
typedef struct typedef struct
{ {
char id[FDFS_STORAGE_ID_MAX_SIZE]; char id[FDFS_STORAGE_ID_MAX_SIZE];