JCEC-comp/JCEC-fastdfs/client/client_func.c

565 lines
13 KiB
C
Executable File

/**
* 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.fastken.com/ for more detail.
**/
//client_func.c
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include "fdfs_define.h"
#include "fastcommon/logger.h"
#include "fdfs_global.h"
#include "fastcommon/base64.h"
#include "fastcommon/sockopt.h"
#include "fastcommon/shared_func.h"
#include "fastcommon/ini_file_reader.h"
#include "fastcommon/connection_pool.h"
#include "tracker_types.h"
#include "tracker_proto.h"
#include "client_global.h"
#include "client_func.h"
static int storage_cmp_by_ip_and_port(const void *p1, const void *p2)
{
int res;
res = strcmp(((ConnectionInfo *)p1)->ip_addr,
((ConnectionInfo *)p2)->ip_addr);
if (res != 0)
{
return res;
}
return ((ConnectionInfo *)p1)->port -
((ConnectionInfo *)p2)->port;
}
static int storage_cmp_server_info(const void *p1, const void *p2)
{
TrackerServerInfo *server1;
TrackerServerInfo *server2;
ConnectionInfo *pc1;
ConnectionInfo *pc2;
ConnectionInfo *end1;
int res;
server1 = (TrackerServerInfo *)p1;
server2 = (TrackerServerInfo *)p2;
res = server1->count - server2->count;
if (res != 0)
{
return res;
}
if (server1->count == 1)
{
return storage_cmp_by_ip_and_port(server1->connections + 0,
server2->connections + 0);
}
end1 = server1->connections + server1->count;
for (pc1=server1->connections,pc2=server2->connections; pc1<end1; pc1++,pc2++)
{
if ((res=storage_cmp_by_ip_and_port(pc1, pc2)) != 0)
{
return res;
}
}
return 0;
}
static void insert_into_sorted_servers(TrackerServerGroup *pTrackerGroup, \
TrackerServerInfo *pInsertedServer)
{
TrackerServerInfo *pDestServer;
for (pDestServer=pTrackerGroup->servers+pTrackerGroup->server_count;
pDestServer>pTrackerGroup->servers; pDestServer--)
{
if (storage_cmp_server_info(pInsertedServer, pDestServer-1) > 0)
{
memcpy(pDestServer, pInsertedServer,
sizeof(TrackerServerInfo));
return;
}
memcpy(pDestServer, pDestServer-1, sizeof(TrackerServerInfo));
}
memcpy(pDestServer, pInsertedServer, sizeof(TrackerServerInfo));
}
static int copy_tracker_servers(TrackerServerGroup *pTrackerGroup,
const char *filename, char **ppTrackerServers)
{
char **ppSrc;
char **ppEnd;
TrackerServerInfo destServer;
int result;
memset(&destServer, 0, sizeof(TrackerServerInfo));
fdfs_server_sock_reset(&destServer);
ppEnd = ppTrackerServers + pTrackerGroup->server_count;
pTrackerGroup->server_count = 0;
for (ppSrc=ppTrackerServers; ppSrc<ppEnd; ppSrc++)
{
if ((result=fdfs_parse_server_info(*ppSrc,
FDFS_TRACKER_SERVER_DEF_PORT, &destServer)) != 0)
{
return result;
}
if (bsearch(&destServer, pTrackerGroup->servers,
pTrackerGroup->server_count,
sizeof(TrackerServerInfo),
storage_cmp_server_info) == NULL)
{
insert_into_sorted_servers(pTrackerGroup, &destServer);
pTrackerGroup->server_count++;
}
}
/*
{
TrackerServerInfo *pServer;
for (pServer=pTrackerGroup->servers; pServer<pTrackerGroup->servers+ \
pTrackerGroup->server_count; pServer++)
{
//printf("server=%s:%d\n", \
pServer->ip_addr, pServer->port);
}
}
*/
return 0;
}
static int fdfs_check_tracker_group(TrackerServerGroup *pTrackerGroup,
const char *conf_filename)
{
int result;
TrackerServerInfo *pServer;
TrackerServerInfo *pEnd;
char error_info[256];
pEnd = pTrackerGroup->servers + pTrackerGroup->server_count;
for (pServer=pTrackerGroup->servers; pServer<pEnd; pServer++)
{
if ((result=fdfs_check_server_ips(pServer,
error_info, sizeof(error_info))) != 0)
{
logError("file: "__FILE__", line: %d, "
"conf file: %s, tracker_server is invalid, "
"error info: %s", __LINE__, conf_filename, error_info);
return result;
}
}
return 0;
}
int fdfs_load_tracker_group_ex(TrackerServerGroup *pTrackerGroup,
const char *conf_filename, IniContext *pIniContext)
{
int result;
int bytes;
char *ppTrackerServers[FDFS_MAX_TRACKERS];
if ((pTrackerGroup->server_count=iniGetValues(NULL, "tracker_server",
pIniContext, ppTrackerServers, FDFS_MAX_TRACKERS)) <= 0)
{
logError("file: "__FILE__", line: %d, "
"conf file \"%s\", item \"tracker_server\" not exist",
__LINE__, conf_filename);
return ENOENT;
}
bytes = sizeof(TrackerServerInfo) * pTrackerGroup->server_count;
pTrackerGroup->servers = (TrackerServerInfo *)malloc(bytes);
if (pTrackerGroup->servers == NULL)
{
logError("file: "__FILE__", line: %d, "
"malloc %d bytes fail", __LINE__, bytes);
pTrackerGroup->server_count = 0;
return errno != 0 ? errno : ENOMEM;
}
memset(pTrackerGroup->servers, 0, bytes);
if ((result=copy_tracker_servers(pTrackerGroup, conf_filename,
ppTrackerServers)) != 0)
{
pTrackerGroup->server_count = 0;
free(pTrackerGroup->servers);
pTrackerGroup->servers = NULL;
return result;
}
return fdfs_check_tracker_group(pTrackerGroup, conf_filename);
}
int fdfs_load_tracker_group(TrackerServerGroup *pTrackerGroup,
const char *conf_filename)
{
IniContext iniContext;
int result;
if ((result=iniLoadFromFile(conf_filename, &iniContext)) != 0)
{
logError("file: "__FILE__", line: %d, "
"load conf file \"%s\" fail, ret code: %d",
__LINE__, conf_filename, result);
return result;
}
result = fdfs_load_tracker_group_ex(pTrackerGroup,
conf_filename, &iniContext);
iniFreeContext(&iniContext);
return result;
}
static int fdfs_get_params_from_tracker(bool *use_storage_id)
{
IniContext iniContext;
int result;
bool continue_flag;
continue_flag = false;
if ((result=fdfs_get_ini_context_from_tracker(&g_tracker_group,
&iniContext, &continue_flag, false, NULL)) != 0)
{
return result;
}
*use_storage_id = iniGetBoolValue(NULL, "use_storage_id",
&iniContext, false);
iniFreeContext(&iniContext);
if (*use_storage_id)
{
result = fdfs_get_storage_ids_from_tracker_group(
&g_tracker_group);
}
return result;
}
static int fdfs_client_do_init_ex(TrackerServerGroup *pTrackerGroup, \
const char *conf_filename, IniContext *iniContext)
{
char *pBasePath;
int result;
bool use_storage_id;
bool load_fdfs_parameters_from_tracker;
pBasePath = iniGetStrValue(NULL, "base_path", iniContext);
if (pBasePath == NULL)
{
strcpy(g_fdfs_base_path, "/tmp");
}
else
{
snprintf(g_fdfs_base_path, sizeof(g_fdfs_base_path),
"%s", pBasePath);
chopPath(g_fdfs_base_path);
if (!fileExists(g_fdfs_base_path))
{
logError("file: "__FILE__", line: %d, " \
"\"%s\" can't be accessed, error info: %s", \
__LINE__, g_fdfs_base_path, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
if (!isDir(g_fdfs_base_path))
{
logError("file: "__FILE__", line: %d, " \
"\"%s\" is not a directory!", \
__LINE__, g_fdfs_base_path);
return ENOTDIR;
}
}
g_fdfs_connect_timeout = iniGetIntValue(NULL, "connect_timeout", \
iniContext, DEFAULT_CONNECT_TIMEOUT);
if (g_fdfs_connect_timeout <= 0)
{
g_fdfs_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
}
g_fdfs_network_timeout = iniGetIntValue(NULL, "network_timeout", \
iniContext, DEFAULT_NETWORK_TIMEOUT);
if (g_fdfs_network_timeout <= 0)
{
g_fdfs_network_timeout = DEFAULT_NETWORK_TIMEOUT;
}
if ((result=fdfs_load_tracker_group_ex(pTrackerGroup, \
conf_filename, iniContext)) != 0)
{
return result;
}
g_anti_steal_token = iniGetBoolValue(NULL, \
"http.anti_steal.check_token", \
iniContext, false);
if (g_anti_steal_token)
{
char *anti_steal_secret_key;
anti_steal_secret_key = iniGetStrValue(NULL, \
"http.anti_steal.secret_key", \
iniContext);
if (anti_steal_secret_key == NULL || \
*anti_steal_secret_key == '\0')
{
logError("file: "__FILE__", line: %d, " \
"param \"http.anti_steal.secret_key\""\
" not exist or is empty", __LINE__);
return EINVAL;
}
buffer_strcpy(&g_anti_steal_secret_key, anti_steal_secret_key);
}
g_tracker_server_http_port = iniGetIntValue(NULL, \
"http.tracker_server_port", \
iniContext, 80);
if (g_tracker_server_http_port <= 0)
{
g_tracker_server_http_port = 80;
}
if ((result=fdfs_connection_pool_init(conf_filename, iniContext)) != 0)
{
return result;
}
load_fdfs_parameters_from_tracker = iniGetBoolValue(NULL, \
"load_fdfs_parameters_from_tracker", \
iniContext, false);
if (load_fdfs_parameters_from_tracker)
{
fdfs_get_params_from_tracker(&use_storage_id);
}
else
{
use_storage_id = iniGetBoolValue(NULL, "use_storage_id", \
iniContext, false);
if (use_storage_id)
{
result = fdfs_load_storage_ids_from_file( \
conf_filename, iniContext);
}
}
#ifdef DEBUG_FLAG
logDebug("base_path=%s, " \
"connect_timeout=%d, "\
"network_timeout=%d, "\
"tracker_server_count=%d, " \
"anti_steal_token=%d, " \
"anti_steal_secret_key length=%d, " \
"use_connection_pool=%d, " \
"g_connection_pool_max_idle_time=%ds, " \
"use_storage_id=%d, storage server id count: %d\n", \
g_fdfs_base_path, g_fdfs_connect_timeout, \
g_fdfs_network_timeout, pTrackerGroup->server_count, \
g_anti_steal_token, g_anti_steal_secret_key.length, \
g_use_connection_pool, g_connection_pool_max_idle_time, \
use_storage_id, g_storage_ids_by_id.count);
#endif
return 0;
}
int fdfs_client_init_from_buffer_ex(TrackerServerGroup *pTrackerGroup, \
const char *buffer)
{
IniContext iniContext;
char *new_buff;
int result;
new_buff = strdup(buffer);
if (new_buff == NULL)
{
logError("file: "__FILE__", line: %d, " \
"strdup %d bytes fail", __LINE__, (int)strlen(buffer));
return ENOMEM;
}
result = iniLoadFromBuffer(new_buff, &iniContext);
free(new_buff);
if (result != 0)
{
logError("file: "__FILE__", line: %d, " \
"load parameters from buffer fail, ret code: %d", \
__LINE__, result);
return result;
}
result = fdfs_client_do_init_ex(pTrackerGroup, "buffer", &iniContext);
iniFreeContext(&iniContext);
return result;
}
int fdfs_client_init_ex(TrackerServerGroup *pTrackerGroup, \
const char *conf_filename)
{
IniContext iniContext;
int result;
if ((result=iniLoadFromFile(conf_filename, &iniContext)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"load conf file \"%s\" fail, ret code: %d", \
__LINE__, conf_filename, result);
return result;
}
result = fdfs_client_do_init_ex(pTrackerGroup, conf_filename, \
&iniContext);
iniFreeContext(&iniContext);
return result;
}
int fdfs_copy_tracker_group(TrackerServerGroup *pDestTrackerGroup, \
TrackerServerGroup *pSrcTrackerGroup)
{
int bytes;
TrackerServerInfo *pDestServer;
TrackerServerInfo *pDestServerEnd;
bytes = sizeof(TrackerServerInfo) * pSrcTrackerGroup->server_count;
pDestTrackerGroup->servers = (TrackerServerInfo *)malloc(bytes);
if (pDestTrackerGroup->servers == NULL)
{
logError("file: "__FILE__", line: %d, "
"malloc %d bytes fail", __LINE__, bytes);
return errno != 0 ? errno : ENOMEM;
}
pDestTrackerGroup->server_index = 0;
pDestTrackerGroup->leader_index = 0;
pDestTrackerGroup->server_count = pSrcTrackerGroup->server_count;
memcpy(pDestTrackerGroup->servers, pSrcTrackerGroup->servers, bytes);
pDestServerEnd = pDestTrackerGroup->servers +
pDestTrackerGroup->server_count;
for (pDestServer=pDestTrackerGroup->servers;
pDestServer<pDestServerEnd; pDestServer++)
{
fdfs_server_sock_reset(pDestServer);
}
return 0;
}
bool fdfs_tracker_group_equals(TrackerServerGroup *pGroup1,
TrackerServerGroup *pGroup2)
{
TrackerServerInfo *pServer1;
TrackerServerInfo *pServer2;
TrackerServerInfo *pEnd1;
if (pGroup1->server_count != pGroup2->server_count)
{
return false;
}
pEnd1 = pGroup1->servers + pGroup1->server_count;
pServer1 = pGroup1->servers;
pServer2 = pGroup2->servers;
while (pServer1 < pEnd1)
{
if (!fdfs_server_equal(pServer1, pServer2))
{
return false;
}
pServer1++;
pServer2++;
}
return true;
}
void fdfs_client_destroy_ex(TrackerServerGroup *pTrackerGroup)
{
if (pTrackerGroup->servers != NULL)
{
free(pTrackerGroup->servers);
pTrackerGroup->servers = NULL;
pTrackerGroup->server_count = 0;
pTrackerGroup->server_index = 0;
}
}
const char *fdfs_get_file_ext_name_ex(const char *filename,
const bool twoExtName)
{
const char *fileExtName;
const char *p;
const char *pStart;
int extNameLen;
fileExtName = strrchr(filename, '.');
if (fileExtName == NULL)
{
return NULL;
}
extNameLen = strlen(fileExtName + 1);
if (extNameLen > FDFS_FILE_EXT_NAME_MAX_LEN)
{
return NULL;
}
if (strchr(fileExtName + 1, '/') != NULL) //invalid extension name
{
return NULL;
}
if (!twoExtName)
{
return fileExtName + 1;
}
pStart = fileExtName - (FDFS_FILE_EXT_NAME_MAX_LEN - extNameLen) - 1;
if (pStart < filename)
{
pStart = filename;
}
p = fileExtName - 1; //before .
while ((p > pStart) && (*p != '.'))
{
p--;
}
if (p > pStart) //found (extension name have a dot)
{
if (strchr(p + 1, '/') == NULL) //valid extension name
{
return p + 1; //skip .
}
}
return fileExtName + 1; //skip .
}