fastdfs/tracker/tracker_mem.c

6226 lines
158 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 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.
**/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include "fdfs_define.h"
#include "fastcommon/logger.h"
#include "fastcommon/sockopt.h"
#include "fdfs_global.h"
#include "fastcommon/shared_func.h"
#include "fastcommon/pthread_func.h"
#include "fastcommon/sched_thread.h"
#include "fdfs_shared_func.h"
#include "tracker_global.h"
#include "tracker_proto.h"
#include "tracker_func.h"
#include "tracker_relationship.h"
#include "tracker_mem.h"
#define TRACKER_MEM_ALLOC_ONCE 2
#define GROUP_SECTION_NAME_GLOBAL "Global"
#define GROUP_SECTION_NAME_PREFIX "Group"
#define GROUP_SECTION_NO_FORMAT "%03d"
#define GROUP_ITEM_GROUP_COUNT "group_count"
#define GROUP_ITEM_GROUP_NAME "group_name"
#define GROUP_ITEM_STORAGE_PORT "storage_port"
#define GROUP_ITEM_STORAGE_HTTP_PORT "storage_http_port"
#define GROUP_ITEM_STORE_PATH_COUNT "store_path_count"
#define GROUP_ITEM_SUBDIR_COUNT_PER_PATH "subdir_count_per_path"
#define GROUP_ITEM_CURRENT_TRUNK_FILE_ID "current_trunk_file_id"
#define GROUP_ITEM_LAST_TRUNK_SERVER "last_trunk_server"
#define GROUP_ITEM_TRUNK_SERVER "trunk_server"
#define STORAGE_SECTION_NAME_GLOBAL "Global"
#define STORAGE_SECTION_NAME_PREFIX "Storage"
#define STORAGE_SECTION_NO_FORMAT "%03d"
#define STORAGE_ITEM_STORAGE_COUNT "storage_count"
#define STORAGE_ITEM_GROUP_NAME "group_name"
#define STORAGE_ITEM_SERVER_ID "id"
#define STORAGE_ITEM_IP_ADDR "ip_addr"
#define STORAGE_ITEM_STATUS "status"
#define STORAGE_ITEM_DOMAIN_NAME "domain_name"
#define STORAGE_ITEM_VERSION "version"
#define STORAGE_ITEM_SYNC_SRC_SERVER "sync_src_server"
#define STORAGE_ITEM_SYNC_UNTIL_TIMESTAMP "sync_until_timestamp"
#define STORAGE_ITEM_JOIN_TIME "join_time"
#define STORAGE_ITEM_TOTAL_MB "total_mb"
#define STORAGE_ITEM_FREE_MB "free_mb"
#define STORAGE_ITEM_CHANGELOG_OFFSET "changelog_offset"
#define STORAGE_ITEM_STORE_PATH_COUNT "store_path_count"
#define STORAGE_ITEM_SUBDIR_COUNT_PER_PATH "subdir_count_per_path"
#define STORAGE_ITEM_UPLOAD_PRIORITY "upload_priority"
#define STORAGE_ITEM_STORAGE_PORT "storage_port"
#define STORAGE_ITEM_STORAGE_HTTP_PORT "storage_http_port"
#define STORAGE_ITEM_TOTAL_UPLOAD_COUNT "total_upload_count"
#define STORAGE_ITEM_SUCCESS_UPLOAD_COUNT "success_upload_count"
#define STORAGE_ITEM_TOTAL_APPEND_COUNT "total_append_count"
#define STORAGE_ITEM_SUCCESS_APPEND_COUNT "success_append_count"
#define STORAGE_ITEM_TOTAL_SET_META_COUNT "total_set_meta_count"
#define STORAGE_ITEM_SUCCESS_SET_META_COUNT "success_set_meta_count"
#define STORAGE_ITEM_TOTAL_DELETE_COUNT "total_delete_count"
#define STORAGE_ITEM_SUCCESS_DELETE_COUNT "success_delete_count"
#define STORAGE_ITEM_TOTAL_DOWNLOAD_COUNT "total_download_count"
#define STORAGE_ITEM_SUCCESS_DOWNLOAD_COUNT "success_download_count"
#define STORAGE_ITEM_TOTAL_GET_META_COUNT "total_get_meta_count"
#define STORAGE_ITEM_SUCCESS_GET_META_COUNT "success_get_meta_count"
#define STORAGE_ITEM_TOTAL_CREATE_LINK_COUNT "total_create_link_count"
#define STORAGE_ITEM_SUCCESS_CREATE_LINK_COUNT "success_create_link_count"
#define STORAGE_ITEM_TOTAL_DELETE_LINK_COUNT "total_delete_link_count"
#define STORAGE_ITEM_SUCCESS_DELETE_LINK_COUNT "success_delete_link_count"
#define STORAGE_ITEM_TOTAL_UPLOAD_BYTES "total_upload_bytes"
#define STORAGE_ITEM_SUCCESS_UPLOAD_BYTES "success_upload_bytes"
#define STORAGE_ITEM_TOTAL_APPEND_BYTES "total_append_bytes"
#define STORAGE_ITEM_SUCCESS_APPEND_BYTES "success_append_bytes"
#define STORAGE_ITEM_TOTAL_DOWNLOAD_BYTES "total_download_bytes"
#define STORAGE_ITEM_SUCCESS_DOWNLOAD_BYTES "success_download_bytes"
#define STORAGE_ITEM_TOTAL_SYNC_IN_BYTES "total_sync_in_bytes"
#define STORAGE_ITEM_SUCCESS_SYNC_IN_BYTES "success_sync_in_bytes"
#define STORAGE_ITEM_TOTAL_SYNC_OUT_BYTES "total_sync_out_bytes"
#define STORAGE_ITEM_SUCCESS_SYNC_OUT_BYTES "success_sync_out_bytes"
#define STORAGE_ITEM_TOTAL_FILE_OPEN_COUNT "total_file_open_count"
#define STORAGE_ITEM_SUCCESS_FILE_OPEN_COUNT "success_file_open_count"
#define STORAGE_ITEM_TOTAL_FILE_READ_COUNT "total_file_read_count"
#define STORAGE_ITEM_SUCCESS_FILE_READ_COUNT "success_file_read_count"
#define STORAGE_ITEM_TOTAL_FILE_WRITE_COUNT "total_file_write_count"
#define STORAGE_ITEM_SUCCESS_FILE_WRITE_COUNT "success_file_write_count"
#define STORAGE_ITEM_LAST_SOURCE_UPDATE "last_source_update"
#define STORAGE_ITEM_LAST_SYNC_UPDATE "last_sync_update"
#define STORAGE_ITEM_LAST_SYNCED_TIMESTAMP "last_synced_timestamp"
#define STORAGE_ITEM_LAST_HEART_BEAT_TIME "last_heart_beat_time"
TrackerServerGroup g_tracker_servers = {0, 0, -1, NULL};
TrackerServerInfo *g_last_tracker_servers = NULL; //for delay free
int g_next_leader_index = -1; //next leader index
int g_trunk_server_chg_count = 1; //for notify other trackers
int g_tracker_leader_chg_count = 0; //for notify storage servers
int64_t g_changelog_fsize = 0; //storage server change log file size
static int changelog_fd = -1; //storage server change log fd for write
static bool need_get_sys_files = true;
static bool get_sys_files_done = false;
static pthread_mutex_t mem_thread_lock;
static pthread_mutex_t mem_file_lock;
static void tracker_mem_find_store_server(FDFSGroupInfo *pGroup);
static int tracker_mem_find_trunk_server(FDFSGroupInfo *pGroup,
const bool save);
static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup,
FDFSStorageDetail **ppStorageServer, const char *id,
const char *ip_addr, const bool bNeedSleep,
const bool bNeedLock, bool *bInserted);
static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo,
const char *id, const char *ip_addr,
const bool bNeedSleep, const bool bNeedLock, bool *bInserted);
static int tracker_mem_add_storage_from_file(FDFSGroups *pGroups,
const char *data_path, TrackerClientInfo *pClientInfo,
const char *group_name, const char *storage_id, char *ip_addr);
static int tracker_mem_add_group_ex(FDFSGroups *pGroups,
TrackerClientInfo *pClientInfo, const char *group_name,
const bool bNeedSleep, bool *bInserted);
static int tracker_mem_destroy_groups(FDFSGroups *pGroups, const bool saveFiles);
char *g_tracker_sys_filenames[TRACKER_SYS_FILE_COUNT] = {
STORAGE_GROUPS_LIST_FILENAME_NEW,
STORAGE_SERVERS_LIST_FILENAME_NEW,
STORAGE_SYNC_TIMESTAMP_FILENAME,
STORAGE_SERVERS_CHANGELOG_FILENAME
};
int tracker_mem_pthread_lock()
{
int result;
if ((result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
int tracker_mem_pthread_unlock()
{
int result;
if ((result=pthread_mutex_unlock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
int tracker_mem_file_lock()
{
int result;
if ((result=pthread_mutex_lock(&mem_file_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
int tracker_mem_file_unlock()
{
int result;
if ((result=pthread_mutex_unlock(&mem_file_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
static int tracker_write_to_changelog(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pStorage, const char *pArg)
{
char buff[256];
int len;
int result;
tracker_mem_file_lock();
len = snprintf(buff, sizeof(buff), "%d %s %s %d %s\n", \
(int)g_current_time, pGroup->group_name, pStorage->id, \
pStorage->status, pArg != NULL ? pArg : "");
if (fc_safe_write(changelog_fd, buff, len) != len)
{
tracker_mem_file_unlock();
result = errno != 0 ? errno : EIO;
logError("file: "__FILE__", line: %d, " \
"write to file: %s fail, " \
"errno: %d, error info: %s", \
__LINE__, STORAGE_SERVERS_CHANGELOG_FILENAME, \
result, STRERROR(result));
return result;
}
g_changelog_fsize += len;
result = fsync(changelog_fd);
if (result != 0)
{
result = errno != 0 ? errno : EIO;
logError("file: "__FILE__", line: %d, " \
"call fsync of file: %s fail, " \
"errno: %d, error info: %s", \
__LINE__, STORAGE_SERVERS_CHANGELOG_FILENAME, \
result, STRERROR(result));
}
tracker_mem_file_unlock();
return result;
}
static int tracker_malloc_storage_path_mbs(FDFSStorageDetail *pStorage, \
const int store_path_count)
{
int alloc_bytes;
if (store_path_count <= 0)
{
return 0;
}
alloc_bytes = sizeof(int64_t) * store_path_count;
pStorage->path_total_mbs = (int64_t *)malloc(alloc_bytes);
if (pStorage->path_total_mbs == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, alloc_bytes, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
pStorage->path_free_mbs = (int64_t *)malloc(alloc_bytes);
if (pStorage->path_free_mbs == NULL)
{
free(pStorage->path_total_mbs);
pStorage->path_total_mbs = NULL;
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, alloc_bytes, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
memset(pStorage->path_total_mbs, 0, alloc_bytes);
memset(pStorage->path_free_mbs, 0, alloc_bytes);
return 0;
}
static int tracker_realloc_storage_path_mbs(FDFSStorageDetail *pStorage, \
const int old_store_path_count, const int new_store_path_count)
{
int alloc_bytes;
int copy_bytes;
int64_t *new_path_total_mbs;
int64_t *new_path_free_mbs;
if (new_store_path_count <= 0)
{
return EINVAL;
}
alloc_bytes = sizeof(int64_t) * new_store_path_count;
new_path_total_mbs = (int64_t *)malloc(alloc_bytes);
if (new_path_total_mbs == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, alloc_bytes, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
new_path_free_mbs = (int64_t *)malloc(alloc_bytes);
if (new_path_free_mbs == NULL)
{
free(new_path_total_mbs);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, alloc_bytes, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
memset(new_path_total_mbs, 0, alloc_bytes);
memset(new_path_free_mbs, 0, alloc_bytes);
if (old_store_path_count == 0)
{
pStorage->path_total_mbs = new_path_total_mbs;
pStorage->path_free_mbs = new_path_free_mbs;
return 0;
}
copy_bytes = (old_store_path_count < new_store_path_count ? \
old_store_path_count : new_store_path_count) * sizeof(int64_t);
memcpy(new_path_total_mbs, pStorage->path_total_mbs, copy_bytes);
memcpy(new_path_free_mbs, pStorage->path_free_mbs, copy_bytes);
free(pStorage->path_total_mbs);
free(pStorage->path_free_mbs);
pStorage->path_total_mbs = new_path_total_mbs;
pStorage->path_free_mbs = new_path_free_mbs;
return 0;
}
static int tracker_realloc_group_path_mbs(FDFSGroupInfo *pGroup, \
const int new_store_path_count)
{
FDFSStorageDetail **ppStorage;
FDFSStorageDetail **ppEnd;
int result;
ppEnd = pGroup->all_servers + pGroup->alloc_size;
for (ppStorage=pGroup->all_servers; ppStorage<ppEnd; ppStorage++)
{
if ((result=tracker_realloc_storage_path_mbs(*ppStorage, \
pGroup->store_path_count, new_store_path_count)) != 0)
{
return result;
}
}
pGroup->store_path_count = new_store_path_count;
return 0;
}
static int tracker_malloc_group_path_mbs(FDFSGroupInfo *pGroup)
{
FDFSStorageDetail **ppStorage;
FDFSStorageDetail **ppEnd;
int result;
ppEnd = pGroup->all_servers + pGroup->alloc_size;
for (ppStorage=pGroup->all_servers; ppStorage<ppEnd; ppStorage++)
{
if ((result=tracker_malloc_storage_path_mbs(*ppStorage, \
pGroup->store_path_count)) != 0)
{
return result;
}
}
return 0;
}
static int tracker_malloc_all_group_path_mbs(FDFSGroups *pGroups)
{
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppEnd;
int result;
ppEnd = pGroups->groups + pGroups->alloc_size;
for (ppGroup=pGroups->groups; ppGroup<ppEnd; ppGroup++)
{
if ((*ppGroup)->store_path_count == 0)
{
continue;
}
if ((result=tracker_malloc_group_path_mbs(*ppGroup)) != 0)
{
return result;
}
}
return 0;
}
static int tracker_load_groups_old(FDFSGroups *pGroups, const char *data_path)
{
#define STORAGE_DATA_GROUP_FIELDS 4
FILE *fp;
char szLine[256];
char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
char *fields[STORAGE_DATA_GROUP_FIELDS];
int result;
int col_count;
TrackerClientInfo clientInfo;
bool bInserted;
if ((fp=fopen(STORAGE_GROUPS_LIST_FILENAME_OLD, "r")) == NULL)
{
logError("file: "__FILE__", line: %d, " \
"open file \"%s/%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, data_path, STORAGE_GROUPS_LIST_FILENAME_OLD, \
errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
result = 0;
while (fgets(szLine, sizeof(szLine), fp) != NULL)
{
if (*szLine == '\0')
{
continue;
}
col_count = splitEx(szLine, STORAGE_DATA_FIELD_SEPERATOR, \
fields, STORAGE_DATA_GROUP_FIELDS);
if (col_count != STORAGE_DATA_GROUP_FIELDS && \
col_count != STORAGE_DATA_GROUP_FIELDS - 2)
{
logError("file: "__FILE__", line: %d, " \
"the format of the file \"%s/%s\" is invalid", \
__LINE__, data_path, \
STORAGE_GROUPS_LIST_FILENAME_OLD);
result = errno != 0 ? errno : EINVAL;
break;
}
memset(&clientInfo, 0, sizeof(TrackerClientInfo));
snprintf(group_name, sizeof(group_name),\
"%s", fc_trim(fields[0]));
if ((result=tracker_mem_add_group_ex(pGroups, &clientInfo, \
group_name, false, &bInserted)) != 0)
{
break;
}
if (!bInserted)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"group \"%s\" is duplicate", \
__LINE__, data_path, \
STORAGE_GROUPS_LIST_FILENAME_OLD, \
group_name);
result = errno != 0 ? errno : EEXIST;
break;
}
clientInfo.pGroup->storage_port = atoi(fc_trim(fields[1]));
if (col_count == STORAGE_DATA_GROUP_FIELDS - 2)
{ //version < V1.12
clientInfo.pGroup->store_path_count = 0;
clientInfo.pGroup->subdir_count_per_path = 0;
}
else
{
clientInfo.pGroup->store_path_count = \
atoi(fc_trim(fields[2]));
clientInfo.pGroup->subdir_count_per_path = \
atoi(fc_trim(fields[3]));
}
}
fclose(fp);
return result;
}
static int tracker_mem_get_storage_id(const char *group_name, \
const char *pIpAddr, char *storage_id)
{
FDFSStorageIdInfo *pStorageIdInfo;
pStorageIdInfo = fdfs_get_storage_id_by_ip(group_name, pIpAddr);
if (pStorageIdInfo == NULL)
{
return ENOENT;
}
strcpy(storage_id, pStorageIdInfo->id);
return 0;
}
static int tracker_load_groups_new(FDFSGroups *pGroups, const char *data_path,
FDFSStorageSync **ppTrunkServers, int *nTrunkServerCount)
{
IniContext iniContext;
FDFSGroupInfo *pGroup;
char *group_name;
char *pValue;
int nStorageSyncSize;
int group_count;
int result;
int i;
char section_name[64];
TrackerClientInfo clientInfo;
bool bInserted;
*nTrunkServerCount = 0;
*ppTrunkServers = NULL;
if (!fileExists(STORAGE_GROUPS_LIST_FILENAME_NEW) && \
fileExists(STORAGE_GROUPS_LIST_FILENAME_OLD))
{
logDebug("file: "__FILE__", line: %d, " \
"convert old data file %s to new data file %s", \
__LINE__, STORAGE_GROUPS_LIST_FILENAME_OLD, \
STORAGE_GROUPS_LIST_FILENAME_NEW);
if ((result=tracker_load_groups_old(pGroups, data_path)) == 0)
{
if ((result=tracker_save_groups()) == 0)
{
unlink(STORAGE_GROUPS_LIST_FILENAME_OLD);
}
}
return result;
}
if ((result=iniLoadFromFile(STORAGE_GROUPS_LIST_FILENAME_NEW, \
&iniContext)) != 0)
{
return result;
}
group_count = iniGetIntValue(GROUP_SECTION_NAME_GLOBAL, \
GROUP_ITEM_GROUP_COUNT, \
&iniContext, -1);
if (group_count < 0)
{
iniFreeContext(&iniContext);
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"item \"%s\" is not found", \
__LINE__, data_path, \
STORAGE_GROUPS_LIST_FILENAME_NEW, \
GROUP_ITEM_GROUP_COUNT);
return ENOENT;
}
nStorageSyncSize = 0;
for (i=1; i<=group_count; i++)
{
sprintf(section_name, "%s"GROUP_SECTION_NO_FORMAT, \
GROUP_SECTION_NAME_PREFIX, i);
group_name = iniGetStrValue(section_name, \
GROUP_ITEM_GROUP_NAME, &iniContext);
if (group_name == NULL)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"item \"%s\" is not found", \
__LINE__, data_path, \
STORAGE_GROUPS_LIST_FILENAME_NEW, \
GROUP_ITEM_GROUP_NAME);
result = ENOENT;
break;
}
memset(&clientInfo, 0, sizeof(TrackerClientInfo));
if ((result=tracker_mem_add_group_ex(pGroups, &clientInfo, \
group_name, false, &bInserted)) != 0)
{
break;
}
if (!bInserted)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"group \"%s\" is duplicate", \
__LINE__, data_path, \
STORAGE_GROUPS_LIST_FILENAME_NEW, \
group_name);
result = errno != 0 ? errno : EEXIST;
break;
}
pGroup = clientInfo.pGroup;
pGroup->storage_port = iniGetIntValue(section_name, \
GROUP_ITEM_STORAGE_PORT, &iniContext, 0);
pGroup->storage_http_port = iniGetIntValue(section_name, \
GROUP_ITEM_STORAGE_HTTP_PORT, &iniContext, 0);
pGroup->store_path_count = iniGetIntValue(section_name, \
GROUP_ITEM_STORE_PATH_COUNT, &iniContext, 0);
pGroup->subdir_count_per_path = iniGetIntValue(section_name, \
GROUP_ITEM_SUBDIR_COUNT_PER_PATH, &iniContext, 0);
pGroup->current_trunk_file_id = iniGetIntValue(section_name, \
GROUP_ITEM_CURRENT_TRUNK_FILE_ID, &iniContext, 0);
pValue = iniGetStrValue(section_name, \
GROUP_ITEM_LAST_TRUNK_SERVER, &iniContext);
if (pValue != NULL)
{
snprintf(pGroup->last_trunk_server_id,
sizeof(pGroup->last_trunk_server_id), \
"%s", pValue);
if (g_use_storage_id && (*pValue != '\0' && \
!fdfs_is_server_id_valid(pValue)))
{
if (tracker_mem_get_storage_id( \
pGroup->group_name, pValue, \
pGroup->last_trunk_server_id) != 0)
{
logWarning("file: "__FILE__", line: %d,"\
"server id of group name: %s " \
"and last trunk ip address: %s"\
" NOT exist", __LINE__, \
pGroup->group_name, pValue);
*pGroup->last_trunk_server_id = '\0';
}
}
}
pValue = iniGetStrValue(section_name, \
GROUP_ITEM_TRUNK_SERVER, &iniContext);
if (pValue != NULL && *pValue != '\0')
{
if (nStorageSyncSize <= *nTrunkServerCount)
{
nStorageSyncSize += 8;
FDFSStorageSync *new_trunk_servers = (FDFSStorageSync *)
realloc(*ppTrunkServers, \
sizeof(FDFSStorageSync) * nStorageSyncSize);
if (new_trunk_servers == NULL)
{
result = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"realloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageSync) * \
nStorageSyncSize);
free(*ppTrunkServers);
*ppTrunkServers = NULL;
break;
}
*ppTrunkServers = new_trunk_servers;
}
strcpy((*ppTrunkServers)[*nTrunkServerCount].group_name, \
clientInfo.pGroup->group_name);
snprintf((*ppTrunkServers)[*nTrunkServerCount].id, \
FDFS_STORAGE_ID_MAX_SIZE, "%s", pValue);
if (g_use_storage_id && !fdfs_is_server_id_valid(pValue))
{
if ((result=tracker_mem_get_storage_id( \
clientInfo.pGroup->group_name, pValue, \
(*ppTrunkServers)[*nTrunkServerCount].id)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"server id of group name: %s and " \
"trunk server ip address: %s NOT " \
"exist", __LINE__, \
clientInfo.pGroup->group_name, pValue);
break;
}
}
(*nTrunkServerCount)++;
}
}
iniFreeContext(&iniContext);
return result;
}
static int tracker_locate_group_trunk_servers(FDFSGroups *pGroups, \
FDFSStorageSync *pTrunkServers, \
const int nTrunkServerCount, const bool bLoadFromFile)
{
FDFSGroupInfo *pGroup;
FDFSStorageDetail *pStorage;
FDFSStorageSync *pServer;
FDFSStorageSync *pTrunkEnd;
if (nTrunkServerCount == 0)
{
return 0;
}
pTrunkEnd = pTrunkServers + nTrunkServerCount;
for (pServer=pTrunkServers; pServer<pTrunkEnd; pServer++)
{
pGroup = tracker_mem_get_group_ex(pGroups, \
pServer->group_name);
if (pGroup == NULL)
{
continue;
}
pStorage = tracker_mem_get_storage(pGroup, pServer->id);
if (pStorage == NULL)
{
char buff[MAX_PATH_SIZE+64];
if (bLoadFromFile)
{
snprintf(buff, sizeof(buff), \
"in the file \"%s/data/%s\", ", \
SF_G_BASE_PATH_STR, \
STORAGE_GROUPS_LIST_FILENAME_NEW);
}
else
{
*buff = '\0';
}
logError("file: "__FILE__", line: %d, " \
"%sgroup_name: %s, trunk server \"%s\" " \
"does not exist", __LINE__, buff, \
pServer->group_name, pServer->id);
return ENOENT;
}
pGroup->pTrunkServer = pStorage;
pGroup->trunk_chg_count++;
if (*(pGroup->last_trunk_server_id) == '\0')
{
strcpy(pGroup->last_trunk_server_id, pStorage->id);
}
}
return 0;
}
static int tracker_locate_storage_sync_server(FDFSGroups *pGroups, \
FDFSStorageSync *pStorageSyncs, \
const int nStorageSyncCount, const bool bLoadFromFile)
{
FDFSGroupInfo *pGroup;
FDFSStorageDetail *pStorage;
FDFSStorageSync *pSyncServer;
FDFSStorageSync *pSyncEnd;
if (nStorageSyncCount == 0)
{
return 0;
}
pSyncEnd = pStorageSyncs + nStorageSyncCount;
for (pSyncServer=pStorageSyncs; pSyncServer<pSyncEnd; pSyncServer++)
{
pGroup = tracker_mem_get_group_ex(pGroups, \
pSyncServer->group_name);
if (pGroup == NULL)
{
continue;
}
pStorage=tracker_mem_get_storage(pGroup, pSyncServer->id);
if (pStorage == NULL)
{
continue;
}
pStorage->psync_src_server = tracker_mem_get_storage(pGroup, \
pSyncServer->sync_src_id);
if (pStorage->psync_src_server == NULL)
{
char buff[MAX_PATH_SIZE+64];
if (bLoadFromFile)
{
snprintf(buff, sizeof(buff), \
"in the file \"%s/data/%s\", ", \
SF_G_BASE_PATH_STR, \
STORAGE_SERVERS_LIST_FILENAME_NEW);
}
else
{
*buff = '\0';
}
logError("file: "__FILE__", line: %d, " \
"%sgroup_name: %s, storage server \"%s\" " \
"does not exist", __LINE__, buff, \
pSyncServer->group_name, \
pSyncServer->sync_src_id);
return ENOENT;
}
}
return 0;
}
static int tracker_load_storages_old(FDFSGroups *pGroups, const char *data_path)
{
#define STORAGE_DATA_SERVER_FIELDS 22
FILE *fp;
char szLine[256];
char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
char *fields[STORAGE_DATA_SERVER_FIELDS];
char ip_addr[IP_ADDRESS_SIZE];
char *psync_src_id;
FDFSStorageDetail *pStorage;
FDFSStorageSync *pStorageSyncs;
int nStorageSyncSize;
int nStorageSyncCount;
int cols;
int result;
TrackerClientInfo clientInfo;
bool bInserted;
if ((fp=fopen(STORAGE_SERVERS_LIST_FILENAME_OLD, "r")) == NULL)
{
logError("file: "__FILE__", line: %d, " \
"open file \"%s/%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, data_path, STORAGE_SERVERS_LIST_FILENAME_OLD, \
errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
nStorageSyncSize = 0;
nStorageSyncCount = 0;
pStorageSyncs = NULL;
result = 0;
while (fgets(szLine, sizeof(szLine), fp) != NULL)
{
if (*szLine == '\0')
{
continue;
}
cols = splitEx(szLine, STORAGE_DATA_FIELD_SEPERATOR, \
fields, STORAGE_DATA_SERVER_FIELDS);
if (cols != STORAGE_DATA_SERVER_FIELDS && \
cols != STORAGE_DATA_SERVER_FIELDS - 2 && \
cols != STORAGE_DATA_SERVER_FIELDS - 4 && \
cols != STORAGE_DATA_SERVER_FIELDS - 5)
{
logError("file: "__FILE__", line: %d, " \
"the format of the file \"%s/%s\" is invalid" \
", colums: %d != expect colums: " \
"%d or %d or %d or %d", \
__LINE__, data_path, \
STORAGE_SERVERS_LIST_FILENAME_OLD, \
cols, STORAGE_DATA_SERVER_FIELDS, \
STORAGE_DATA_SERVER_FIELDS - 2, \
STORAGE_DATA_SERVER_FIELDS - 4, \
STORAGE_DATA_SERVER_FIELDS - 5);
result = EINVAL;
break;
}
memset(&clientInfo, 0, sizeof(TrackerClientInfo));
snprintf(group_name, sizeof(group_name), "%s", fc_trim(fields[0]));
snprintf(ip_addr, sizeof(ip_addr), "%s", fc_trim(fields[1]));
if ((clientInfo.pGroup=tracker_mem_get_group_ex(pGroups, \
group_name)) == NULL)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"group \"%s\" is not found", \
__LINE__, data_path, \
STORAGE_SERVERS_LIST_FILENAME_OLD, \
group_name);
result = errno != 0 ? errno : ENOENT;
break;
}
if ((result=tracker_mem_add_storage(&clientInfo, NULL, ip_addr,
false, false, &bInserted)) != 0)
{
break;
}
if (!bInserted)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"storage \"%s\" is duplicate", \
__LINE__, data_path, \
STORAGE_SERVERS_LIST_FILENAME_OLD, ip_addr);
result = errno != 0 ? errno : EEXIST;
break;
}
pStorage = clientInfo.pStorage;
pStorage->status = atoi(trim_left(fields[2]));
if (!((pStorage->status == \
FDFS_STORAGE_STATUS_WAIT_SYNC) || \
(pStorage->status == \
FDFS_STORAGE_STATUS_SYNCING) || \
(pStorage->status == \
FDFS_STORAGE_STATUS_INIT)))
{
pStorage->status = \
FDFS_STORAGE_STATUS_OFFLINE;
}
psync_src_id = fc_trim(fields[3]);
pStorage->sync_until_timestamp = atoi( \
trim_left(fields[4]));
pStorage->stat.total_upload_count = strtoll( \
trim_left(fields[5]), NULL, 10);
pStorage->stat.success_upload_count = strtoll( \
trim_left(fields[6]), NULL, 10);
pStorage->stat.total_set_meta_count = strtoll( \
trim_left(fields[7]), NULL, 10);
pStorage->stat.success_set_meta_count = strtoll( \
trim_left(fields[8]), NULL, 10);
pStorage->stat.total_delete_count = strtoll( \
trim_left(fields[9]), NULL, 10);
pStorage->stat.success_delete_count = strtoll( \
trim_left(fields[10]), NULL, 10);
pStorage->stat.total_download_count = strtoll( \
trim_left(fields[11]), NULL, 10);
pStorage->stat.success_download_count = strtoll( \
trim_left(fields[12]), NULL, 10);
pStorage->stat.total_get_meta_count = strtoll( \
trim_left(fields[13]), NULL, 10);
pStorage->stat.success_get_meta_count = strtoll( \
trim_left(fields[14]), NULL, 10);
pStorage->stat.last_source_update = atoi( \
trim_left(fields[15]));
pStorage->stat.last_sync_update = atoi( \
trim_left(fields[16]));
if (cols > STORAGE_DATA_SERVER_FIELDS - 5)
{
pStorage->changelog_offset = strtoll( \
trim_left(fields[17]), NULL, 10);
if (pStorage->changelog_offset < 0)
{
pStorage->changelog_offset = 0;
}
if (pStorage->changelog_offset > \
g_changelog_fsize)
{
pStorage->changelog_offset = \
g_changelog_fsize;
}
if (cols > STORAGE_DATA_SERVER_FIELDS - 4)
{
pStorage->storage_port = \
atoi(trim_left(fields[18]));
pStorage->storage_http_port = \
atoi(trim_left(fields[19]));
if (cols > STORAGE_DATA_SERVER_FIELDS - 2)
{
pStorage->join_time = \
(time_t)atoi(trim_left(fields[20]));
snprintf(pStorage->version, \
sizeof(pStorage->version),
"%s", fc_trim(fields[21]));
}
}
}
if (*psync_src_id == '\0')
{
continue;
}
if (nStorageSyncSize <= nStorageSyncCount)
{
nStorageSyncSize += 8;
FDFSStorageSync *pNewStorageSyncs = (FDFSStorageSync *)
realloc(pStorageSyncs, \
sizeof(FDFSStorageSync) * nStorageSyncSize);
if (pNewStorageSyncs == NULL)
{
result = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"realloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageSync) * \
nStorageSyncSize);
free(pStorageSyncs);
pStorageSyncs = NULL;
break;
}
pStorageSyncs = pNewStorageSyncs;
}
strcpy(pStorageSyncs[nStorageSyncCount].group_name, \
clientInfo.pGroup->group_name);
strcpy(pStorageSyncs[nStorageSyncCount].id, pStorage->id);
snprintf(pStorageSyncs[nStorageSyncCount].sync_src_id, \
FDFS_STORAGE_ID_MAX_SIZE, "%s", psync_src_id);
nStorageSyncCount++;
}
fclose(fp);
if (pStorageSyncs == NULL)
{
return result;
}
if (result != 0)
{
free(pStorageSyncs);
return result;
}
result = tracker_locate_storage_sync_server(pGroups, pStorageSyncs, \
nStorageSyncCount, true);
free(pStorageSyncs);
return result;
}
static int tracker_load_storages_new(FDFSGroups *pGroups, const char *data_path)
{
IniContext iniContext;
char *group_name;
char *storage_id;
char *ip_addr;
char *psync_src_id;
char *pValue;
FDFSStorageDetail *pStorage;
FDFSStorageStat *pStat;
FDFSStorageSync *pStorageSyncs;
int nStorageSyncSize;
int nStorageSyncCount;
int storage_count;
int i;
int result;
char section_name[64];
TrackerClientInfo clientInfo;
if (!fileExists(STORAGE_SERVERS_LIST_FILENAME_NEW) && \
fileExists(STORAGE_SERVERS_LIST_FILENAME_OLD))
{
logDebug("file: "__FILE__", line: %d, " \
"convert old data file %s to new data file %s", \
__LINE__, STORAGE_SERVERS_LIST_FILENAME_OLD, \
STORAGE_SERVERS_LIST_FILENAME_NEW);
if ((result=tracker_load_storages_old(pGroups, data_path)) == 0)
{
if ((result=tracker_save_storages()) == 0)
{
unlink(STORAGE_SERVERS_LIST_FILENAME_OLD);
}
}
return result;
}
if ((result=iniLoadFromFile(STORAGE_SERVERS_LIST_FILENAME_NEW, \
&iniContext)) != 0)
{
return result;
}
storage_count = iniGetIntValue(STORAGE_SECTION_NAME_GLOBAL, \
STORAGE_ITEM_STORAGE_COUNT, \
&iniContext, -1);
if (storage_count < 0)
{
iniFreeContext(&iniContext);
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"item \"%s\" is not found", \
__LINE__, data_path, \
STORAGE_SERVERS_LIST_FILENAME_NEW, \
STORAGE_ITEM_STORAGE_COUNT);
return ENOENT;
}
nStorageSyncSize = 0;
nStorageSyncCount = 0;
pStorageSyncs = NULL;
result = 0;
for (i=1; i<=storage_count; i++)
{
sprintf(section_name, "%s"STORAGE_SECTION_NO_FORMAT, \
STORAGE_SECTION_NAME_PREFIX, i);
group_name = iniGetStrValue(section_name, \
STORAGE_ITEM_GROUP_NAME, &iniContext);
if (group_name == NULL)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"item \"%s\" is not found", \
__LINE__, data_path, \
STORAGE_SERVERS_LIST_FILENAME_NEW, \
STORAGE_ITEM_GROUP_NAME);
result = ENOENT;
break;
}
storage_id = iniGetStrValue(section_name, \
STORAGE_ITEM_SERVER_ID, &iniContext);
ip_addr = iniGetStrValue(section_name, \
STORAGE_ITEM_IP_ADDR, &iniContext);
if ((result=tracker_mem_add_storage_from_file(pGroups,
data_path, &clientInfo, group_name,
storage_id, ip_addr)) != 0)
{
break;
}
pStorage = clientInfo.pStorage;
pStat = &(pStorage->stat);
pStorage->status = iniGetIntValue(section_name, \
STORAGE_ITEM_STATUS, &iniContext, 0);
pValue = iniGetStrValue(section_name, \
STORAGE_ITEM_DOMAIN_NAME, &iniContext);
if (pValue != NULL)
{
snprintf(pStorage->domain_name, \
sizeof(pStorage->domain_name), "%s", pValue);
}
pValue = iniGetStrValue(section_name, \
STORAGE_ITEM_VERSION, &iniContext);
if (pValue != NULL)
{
snprintf(pStorage->version, \
sizeof(pStorage->version), "%s", pValue);
}
if (!((pStorage->status == \
FDFS_STORAGE_STATUS_WAIT_SYNC) || \
(pStorage->status == \
FDFS_STORAGE_STATUS_SYNCING) || \
(pStorage->status == \
FDFS_STORAGE_STATUS_INIT)))
{
pStorage->status = FDFS_STORAGE_STATUS_OFFLINE;
}
psync_src_id = iniGetStrValue(section_name, \
STORAGE_ITEM_SYNC_SRC_SERVER, &iniContext);
if (psync_src_id == NULL)
{
psync_src_id = "";
}
pStorage->sync_until_timestamp = iniGetIntValue(section_name, \
STORAGE_ITEM_SYNC_UNTIL_TIMESTAMP, &iniContext, 0);
pStorage->join_time = iniGetIntValue(section_name, \
STORAGE_ITEM_JOIN_TIME, &iniContext, 0);
pStorage->total_mb = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_MB, &iniContext, 0);
pStorage->free_mb = iniGetInt64Value(section_name, \
STORAGE_ITEM_FREE_MB, &iniContext, 0);
pStorage->store_path_count = iniGetIntValue(section_name, \
STORAGE_ITEM_STORE_PATH_COUNT, &iniContext, 0);
pStorage->subdir_count_per_path = iniGetIntValue(section_name, \
STORAGE_ITEM_SUBDIR_COUNT_PER_PATH, &iniContext, 0);
pStorage->upload_priority = iniGetIntValue(section_name, \
STORAGE_ITEM_UPLOAD_PRIORITY, &iniContext, 0);
pStorage->storage_port = iniGetIntValue(section_name, \
STORAGE_ITEM_STORAGE_PORT, &iniContext, 0);
pStorage->storage_http_port = iniGetIntValue(section_name, \
STORAGE_ITEM_STORAGE_HTTP_PORT, &iniContext, 0);
pStat->total_upload_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_UPLOAD_COUNT, &iniContext, 0);
pStat->success_upload_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_UPLOAD_COUNT, &iniContext, 0);
pStat->total_append_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_APPEND_COUNT, &iniContext, 0);
pStat->success_append_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_APPEND_COUNT, &iniContext, 0);
pStat->total_set_meta_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_SET_META_COUNT, &iniContext, 0);
pStat->success_set_meta_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_SET_META_COUNT, &iniContext, 0);
pStat->total_delete_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_DELETE_COUNT, &iniContext, 0);
pStat->success_delete_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_DELETE_COUNT, &iniContext, 0);
pStat->total_download_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_DOWNLOAD_COUNT, &iniContext, 0);
pStat->success_download_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_DOWNLOAD_COUNT, &iniContext, 0);
pStat->total_get_meta_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_GET_META_COUNT, &iniContext, 0);
pStat->success_get_meta_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_GET_META_COUNT, &iniContext, 0);
pStat->total_create_link_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_CREATE_LINK_COUNT, &iniContext, 0);
pStat->success_create_link_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_CREATE_LINK_COUNT, &iniContext, 0);
pStat->total_delete_link_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_DELETE_LINK_COUNT, &iniContext, 0);
pStat->success_delete_link_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_DELETE_LINK_COUNT, &iniContext, 0);
pStat->total_upload_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_UPLOAD_BYTES, &iniContext, 0);
pStat->success_upload_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_UPLOAD_BYTES, &iniContext, 0);
pStat->total_append_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_APPEND_BYTES, &iniContext, 0);
pStat->success_append_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_APPEND_BYTES, &iniContext, 0);
pStat->total_download_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_DOWNLOAD_BYTES, &iniContext, 0);
pStat->success_download_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_DOWNLOAD_BYTES, &iniContext, 0);
pStat->total_sync_in_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_SYNC_IN_BYTES, &iniContext, 0);
pStat->success_sync_in_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_SYNC_IN_BYTES, &iniContext, 0);
pStat->total_sync_out_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_SYNC_OUT_BYTES, &iniContext, 0);
pStat->success_sync_out_bytes = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_SYNC_OUT_BYTES, &iniContext, 0);
pStat->total_file_open_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_FILE_OPEN_COUNT, &iniContext, 0);
pStat->success_file_open_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_FILE_OPEN_COUNT, &iniContext, 0);
pStat->total_file_read_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_FILE_READ_COUNT, &iniContext, 0);
pStat->success_file_read_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_FILE_READ_COUNT, &iniContext, 0);
pStat->total_file_write_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_TOTAL_FILE_WRITE_COUNT, &iniContext, 0);
pStat->success_file_write_count = iniGetInt64Value(section_name, \
STORAGE_ITEM_SUCCESS_FILE_WRITE_COUNT, &iniContext, 0);
pStat->last_source_update = iniGetIntValue(section_name, \
STORAGE_ITEM_LAST_SOURCE_UPDATE, &iniContext, 0);
pStat->last_sync_update = iniGetIntValue(section_name, \
STORAGE_ITEM_LAST_SYNC_UPDATE, &iniContext, 0);
pStat->last_synced_timestamp = iniGetIntValue(section_name, \
STORAGE_ITEM_LAST_SYNCED_TIMESTAMP, &iniContext, 0);
pStat->last_heart_beat_time = iniGetIntValue(section_name, \
STORAGE_ITEM_LAST_HEART_BEAT_TIME, &iniContext, 0);
pStorage->changelog_offset = iniGetInt64Value(section_name, \
STORAGE_ITEM_CHANGELOG_OFFSET, &iniContext, 0);
if (*psync_src_id == '\0')
{
continue;
}
if (nStorageSyncSize <= nStorageSyncCount)
{
if (nStorageSyncSize == 0)
{
nStorageSyncSize = 8;
}
else
{
nStorageSyncSize *= 2;
}
FDFSStorageSync *pNewStorageSyncs = (FDFSStorageSync *)
realloc(pStorageSyncs, \
sizeof(FDFSStorageSync) * nStorageSyncSize);
if (pNewStorageSyncs == NULL)
{
result = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"realloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageSync) * \
nStorageSyncSize);
free(pStorageSyncs);
pStorageSyncs = NULL;
break;
}
pStorageSyncs = pNewStorageSyncs;
}
strcpy(pStorageSyncs[nStorageSyncCount].group_name, \
clientInfo.pGroup->group_name);
strcpy(pStorageSyncs[nStorageSyncCount].id, pStorage->id);
snprintf(pStorageSyncs[nStorageSyncCount].sync_src_id, \
FDFS_STORAGE_ID_MAX_SIZE, "%s", psync_src_id);
if (g_use_storage_id && !fdfs_is_server_id_valid( \
psync_src_id))
{
if ((result=tracker_mem_get_storage_id( \
clientInfo.pGroup->group_name, psync_src_id, \
pStorageSyncs[nStorageSyncCount].sync_src_id))\
!= 0)
{
logError("file: "__FILE__", line: %d, " \
"server id of group name: %s and " \
"src storage ip address: %s NOT " \
"exist", __LINE__, \
clientInfo.pGroup->group_name, \
psync_src_id);
break;
}
}
nStorageSyncCount++;
}
iniFreeContext(&iniContext);
if (pStorageSyncs == NULL)
{
return result;
}
if (result != 0)
{
free(pStorageSyncs);
return result;
}
result = tracker_locate_storage_sync_server(pGroups, pStorageSyncs, \
nStorageSyncCount, true);
free(pStorageSyncs);
return result;
}
static int tracker_load_sync_timestamps(FDFSGroups *pGroups, const char *data_path)
{
#define STORAGE_SYNC_TIME_MAX_FIELDS 2 + FDFS_MAX_SERVERS_EACH_GROUP
FILE *fp;
char szLine[512];
char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
char previous_group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
char src_storage_id[FDFS_STORAGE_ID_MAX_SIZE];
char *fields[STORAGE_SYNC_TIME_MAX_FIELDS];
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppEnd;
FDFSGroupInfo *pGroup;
int cols;
int src_index;
int dest_index;
int curr_synced_timestamp;
int result;
if (!fileExists(STORAGE_SYNC_TIMESTAMP_FILENAME))
{
return 0;
}
if ((fp=fopen(STORAGE_SYNC_TIMESTAMP_FILENAME, "r")) == NULL)
{
logError("file: "__FILE__", line: %d, " \
"open file \"%s/%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, data_path, STORAGE_SYNC_TIMESTAMP_FILENAME, \
errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
pGroup = NULL;
src_index = 0;
*previous_group_name = '\0';
result = 0;
while (fgets(szLine, sizeof(szLine), fp) != NULL)
{
if (*szLine == '\0' || *szLine == '\n')
{
continue;
}
if ((cols=splitEx(szLine, STORAGE_DATA_FIELD_SEPERATOR, \
fields, STORAGE_SYNC_TIME_MAX_FIELDS)) <= 2)
{
logError("file: "__FILE__", line: %d, " \
"the format of the file \"%s/%s\" is invalid" \
", colums: %d <= 2", \
__LINE__, data_path, \
STORAGE_SYNC_TIMESTAMP_FILENAME, cols);
result = errno != 0 ? errno : EINVAL;
break;
}
snprintf(group_name, sizeof(group_name), \
"%s", fc_trim(fields[0]));
snprintf(src_storage_id, sizeof(src_storage_id), \
"%s", fc_trim(fields[1]));
if (strcmp(group_name, previous_group_name) != 0 || \
pGroup == NULL)
{
if ((pGroup=tracker_mem_get_group_ex(pGroups, \
group_name)) == NULL)
{
logError("file: "__FILE__", line: %d, " \
"in the file \"%s/%s\", " \
"group \"%s\" is not found", \
__LINE__, data_path, \
STORAGE_SYNC_TIMESTAMP_FILENAME, \
group_name);
result = errno != 0 ? errno : ENOENT;
break;
}
strcpy(previous_group_name, group_name);
src_index = 0;
}
if (src_index >= pGroup->count)
{
logError("file: "__FILE__", line: %d, " \
"the format of the file \"%s/%s\" is invalid" \
", group: %s, row count:%d > server count:%d",\
__LINE__, data_path, \
STORAGE_SYNC_TIMESTAMP_FILENAME, \
group_name, src_index+1, pGroup->count);
result = errno != 0 ? errno : EINVAL;
break;
}
if (g_use_storage_id && !fdfs_is_server_id_valid( \
src_storage_id))
{
if ((result=tracker_mem_get_storage_id( \
group_name, src_storage_id, \
src_storage_id)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"server id of group name: %s and " \
"storage ip address: %s NOT " \
"exist", __LINE__, \
group_name, src_storage_id);
break;
}
}
if (strcmp(pGroup->all_servers[src_index]->id, \
src_storage_id) != 0)
{
logError("file: "__FILE__", line: %d, " \
"in data file: \"%s/%s\", " \
"group: %s, src server id: %s != %s",\
__LINE__, data_path, \
STORAGE_SYNC_TIMESTAMP_FILENAME, \
group_name, src_storage_id, \
pGroup->all_servers[src_index]->id);
result = errno != 0 ? errno : EINVAL;
break;
}
if (cols > pGroup->count + 2)
{
logError("file: "__FILE__", line: %d, " \
"the format of the file \"%s/%s\" is invalid" \
", group_name: %s, colums: %d > %d", \
__LINE__, data_path, \
STORAGE_SYNC_TIMESTAMP_FILENAME, \
group_name, cols, pGroup->count + 2);
result = errno != 0 ? errno : EINVAL;
break;
}
for (dest_index=0; dest_index<cols-2; dest_index++)
{
pGroup->last_sync_timestamps[src_index][dest_index] = \
atoi(trim_left(fields[2 + dest_index]));
}
src_index++;
}
fclose(fp);
if (result != 0)
{
return result;
}
ppEnd = pGroups->groups + pGroups->count;
for (ppGroup=pGroups->groups; ppGroup<ppEnd; ppGroup++)
{
if ((*ppGroup)->count <= 1)
{
continue;
}
for (dest_index=0; dest_index<(*ppGroup)->count; dest_index++)
{
if (pGroups->store_server == FDFS_STORE_SERVER_ROUND_ROBIN)
{
int min_synced_timestamp;
min_synced_timestamp = 0;
for (src_index=0; src_index<(*ppGroup)->count; \
src_index++)
{
if (src_index == dest_index)
{
continue;
}
curr_synced_timestamp = \
(*ppGroup)->last_sync_timestamps \
[src_index][dest_index];
if (curr_synced_timestamp == 0)
{
continue;
}
if (min_synced_timestamp == 0)
{
min_synced_timestamp = \
curr_synced_timestamp;
}
else if (curr_synced_timestamp < \
min_synced_timestamp)
{
min_synced_timestamp = \
curr_synced_timestamp;
}
}
(*ppGroup)->all_servers[dest_index]->stat. \
last_synced_timestamp = min_synced_timestamp;
}
else
{
int max_synced_timestamp;
max_synced_timestamp = 0;
for (src_index=0; src_index<(*ppGroup)->count; \
src_index++)
{
if (src_index == dest_index)
{
continue;
}
curr_synced_timestamp = \
(*ppGroup)->last_sync_timestamps \
[src_index][dest_index];
if (curr_synced_timestamp > \
max_synced_timestamp)
{
max_synced_timestamp = \
curr_synced_timestamp;
}
}
(*ppGroup)->all_servers[dest_index]->stat. \
last_synced_timestamp = max_synced_timestamp;
}
}
}
return result;
}
static int tracker_load_data(FDFSGroups *pGroups)
{
char data_path[MAX_PATH_SIZE];
int result;
FDFSStorageSync *pTrunkServers;
int nTrunkServerCount;
snprintf(data_path, sizeof(data_path), "%s/data", SF_G_BASE_PATH_STR);
if (!fileExists(data_path))
{
if (mkdir(data_path, 0755) != 0)
{
logError("file: "__FILE__", line: %d, " \
"mkdir \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, data_path, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
SF_CHOWN_TO_RUNBY_RETURN_ON_ERROR(data_path);
}
if (chdir(data_path) != 0)
{
logError("file: "__FILE__", line: %d, " \
"chdir \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, data_path, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
if (!fileExists(STORAGE_GROUPS_LIST_FILENAME_OLD) && \
!fileExists(STORAGE_GROUPS_LIST_FILENAME_NEW))
{
return 0;
}
if ((result=tracker_load_groups_new(pGroups, data_path, \
&pTrunkServers, &nTrunkServerCount)) != 0)
{
return result;
}
if ((result=tracker_load_storages_new(pGroups, data_path)) != 0)
{
return result;
}
if ((result=tracker_malloc_all_group_path_mbs(pGroups)) != 0)
{
return result;
}
if ((result=tracker_load_sync_timestamps(pGroups, data_path)) != 0)
{
return result;
}
if (g_if_use_trunk_file)
{
if ((result=tracker_locate_group_trunk_servers(pGroups, \
pTrunkServers, nTrunkServerCount, true)) != 0)
{
return result;
}
}
if (pTrunkServers != NULL)
{
free(pTrunkServers);
}
return 0;
}
int tracker_save_groups()
{
char tmpFilename[MAX_PATH_SIZE];
char trueFilename[MAX_PATH_SIZE];
char buff[FDFS_GROUP_NAME_MAX_LEN + 256];
int fd;
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppEnd;
int result;
int len;
tracker_mem_file_lock();
snprintf(trueFilename, sizeof(trueFilename), "%s/data/%s", \
SF_G_BASE_PATH_STR, STORAGE_GROUPS_LIST_FILENAME_NEW);
snprintf(tmpFilename, sizeof(tmpFilename), "%s.tmp", trueFilename);
if ((fd=open(tmpFilename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0)
{
tracker_mem_file_unlock();
logError("file: "__FILE__", line: %d, " \
"open \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
len = sprintf(buff, \
"# global section\n" \
"[%s]\n" \
"\t%s=%d\n\n", \
GROUP_SECTION_NAME_GLOBAL, \
GROUP_ITEM_GROUP_COUNT, g_groups.count);
if (fc_safe_write(fd, buff, len) != len)
{
logError("file: "__FILE__", line: %d, " \
"write to file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
else
{
result = 0;
ppEnd = g_groups.sorted_groups + g_groups.count;
for (ppGroup=g_groups.sorted_groups; ppGroup<ppEnd; ppGroup++)
{
len = sprintf(buff, \
"# group: %s\n" \
"[%s"GROUP_SECTION_NO_FORMAT"]\n" \
"\t%s=%s\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%s\n" \
"\t%s=%s\n\n", \
(*ppGroup)->group_name, \
GROUP_SECTION_NAME_PREFIX, \
(int)(ppGroup - g_groups.sorted_groups) + 1, \
GROUP_ITEM_GROUP_NAME, \
(*ppGroup)->group_name, \
GROUP_ITEM_STORAGE_PORT, \
(*ppGroup)->storage_port, \
GROUP_ITEM_STORAGE_HTTP_PORT, \
(*ppGroup)->storage_http_port, \
GROUP_ITEM_STORE_PATH_COUNT, \
(*ppGroup)->store_path_count, \
GROUP_ITEM_SUBDIR_COUNT_PER_PATH, \
(*ppGroup)->subdir_count_per_path, \
GROUP_ITEM_CURRENT_TRUNK_FILE_ID, \
(*ppGroup)->current_trunk_file_id, \
GROUP_ITEM_TRUNK_SERVER, \
(*ppGroup)->pTrunkServer != NULL ? \
(*ppGroup)->pTrunkServer->id : "",
GROUP_ITEM_LAST_TRUNK_SERVER, \
(*ppGroup)->last_trunk_server_id
);
if (fc_safe_write(fd, buff, len) != len)
{
logError("file: "__FILE__", line: %d, " \
"write to file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
break;
}
}
}
if (result == 0)
{
if (fsync(fd) != 0)
{
logError("file: "__FILE__", line: %d, " \
"fsync file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
}
close(fd);
if (result == 0)
{
if (rename(tmpFilename, trueFilename) != 0)
{
logError("file: "__FILE__", line: %d, " \
"rename file \"%s\" to \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, trueFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
SF_CHOWN_TO_RUNBY_RETURN_ON_ERROR(trueFilename);
}
if (result != 0)
{
unlink(tmpFilename);
}
tracker_mem_file_unlock();
return result;
}
int tracker_save_storages()
{
char tmpFilename[MAX_PATH_SIZE];
char trueFilename[MAX_PATH_SIZE];
char buff[4096];
char id_buff[128];
int fd;
int len;
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
FDFSStorageDetail **ppStorage;
FDFSStorageDetail **ppStorageEnd;
FDFSStorageDetail *pStorage;
int result;
int count;
tracker_mem_file_lock();
snprintf(trueFilename, sizeof(trueFilename), "%s/data/%s", \
SF_G_BASE_PATH_STR, STORAGE_SERVERS_LIST_FILENAME_NEW);
snprintf(tmpFilename, sizeof(tmpFilename), "%s.tmp", trueFilename);
if ((fd=open(tmpFilename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0)
{
tracker_mem_file_unlock();
logError("file: "__FILE__", line: %d, " \
"open \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
*id_buff = '\0';
count = 0;
result = 0;
ppGroupEnd = g_groups.sorted_groups + g_groups.count;
for (ppGroup=g_groups.sorted_groups; \
(ppGroup < ppGroupEnd) && (result == 0); ppGroup++)
{
ppStorageEnd = (*ppGroup)->all_servers + (*ppGroup)->count;
for (ppStorage=(*ppGroup)->all_servers; \
ppStorage<ppStorageEnd; ppStorage++)
{
pStorage = *ppStorage;
if (pStorage->status == FDFS_STORAGE_STATUS_DELETED
|| pStorage->status == FDFS_STORAGE_STATUS_IP_CHANGED)
{
continue;
}
if (g_use_storage_id)
{
sprintf(id_buff, "\t%s=%s\n",
STORAGE_ITEM_SERVER_ID, pStorage->id);
}
count++;
len = sprintf(buff, \
"# storage %s:%u\n" \
"[%s"STORAGE_SECTION_NO_FORMAT"]\n" \
"%s" \
"\t%s=%s\n" \
"\t%s=%s\n" \
"\t%s=%d\n" \
"\t%s=%s\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%s\n" \
"\t%s=%s\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%"PRId64"\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%d\n" \
"\t%s=%"PRId64"\n\n", \
FDFS_CURRENT_IP_ADDR(pStorage), \
pStorage->storage_port, \
STORAGE_SECTION_NAME_PREFIX, count, id_buff, \
STORAGE_ITEM_GROUP_NAME, \
(*ppGroup)->group_name, \
STORAGE_ITEM_IP_ADDR, FDFS_CURRENT_IP_ADDR(pStorage), \
STORAGE_ITEM_STATUS, pStorage->status, \
STORAGE_ITEM_VERSION, pStorage->version, \
STORAGE_ITEM_JOIN_TIME, \
(int)pStorage->join_time, \
STORAGE_ITEM_STORAGE_PORT, \
pStorage->storage_port, \
STORAGE_ITEM_STORAGE_HTTP_PORT, \
pStorage->storage_http_port, \
STORAGE_ITEM_DOMAIN_NAME, \
pStorage->domain_name, \
STORAGE_ITEM_SYNC_SRC_SERVER, \
(pStorage->psync_src_server != NULL ? \
pStorage->psync_src_server->id: ""), \
STORAGE_ITEM_SYNC_UNTIL_TIMESTAMP, \
(int)pStorage->sync_until_timestamp, \
STORAGE_ITEM_STORE_PATH_COUNT, \
pStorage->store_path_count, \
STORAGE_ITEM_SUBDIR_COUNT_PER_PATH, \
pStorage->subdir_count_per_path, \
STORAGE_ITEM_UPLOAD_PRIORITY, \
pStorage->upload_priority, \
STORAGE_ITEM_TOTAL_MB, pStorage->total_mb, \
STORAGE_ITEM_FREE_MB, pStorage->free_mb, \
STORAGE_ITEM_TOTAL_UPLOAD_COUNT, \
pStorage->stat.total_upload_count, \
STORAGE_ITEM_SUCCESS_UPLOAD_COUNT, \
pStorage->stat.success_upload_count, \
STORAGE_ITEM_TOTAL_APPEND_COUNT, \
pStorage->stat.total_append_count, \
STORAGE_ITEM_SUCCESS_APPEND_COUNT, \
pStorage->stat.success_append_count, \
STORAGE_ITEM_TOTAL_SET_META_COUNT, \
pStorage->stat.total_set_meta_count, \
STORAGE_ITEM_SUCCESS_SET_META_COUNT, \
pStorage->stat.success_set_meta_count, \
STORAGE_ITEM_TOTAL_DELETE_COUNT, \
pStorage->stat.total_delete_count, \
STORAGE_ITEM_SUCCESS_DELETE_COUNT, \
pStorage->stat.success_delete_count, \
STORAGE_ITEM_TOTAL_DOWNLOAD_COUNT, \
pStorage->stat.total_download_count, \
STORAGE_ITEM_SUCCESS_DOWNLOAD_COUNT, \
pStorage->stat.success_download_count, \
STORAGE_ITEM_TOTAL_GET_META_COUNT, \
pStorage->stat.total_get_meta_count, \
STORAGE_ITEM_SUCCESS_GET_META_COUNT, \
pStorage->stat.success_get_meta_count, \
STORAGE_ITEM_TOTAL_CREATE_LINK_COUNT, \
pStorage->stat.total_create_link_count, \
STORAGE_ITEM_SUCCESS_CREATE_LINK_COUNT, \
pStorage->stat.success_create_link_count, \
STORAGE_ITEM_TOTAL_DELETE_LINK_COUNT, \
pStorage->stat.total_delete_link_count, \
STORAGE_ITEM_SUCCESS_DELETE_LINK_COUNT, \
pStorage->stat.success_delete_link_count, \
STORAGE_ITEM_TOTAL_UPLOAD_BYTES, \
pStorage->stat.total_upload_bytes, \
STORAGE_ITEM_SUCCESS_UPLOAD_BYTES, \
pStorage->stat.success_upload_bytes, \
STORAGE_ITEM_TOTAL_APPEND_BYTES, \
pStorage->stat.total_append_bytes, \
STORAGE_ITEM_SUCCESS_APPEND_BYTES, \
pStorage->stat.success_append_bytes, \
STORAGE_ITEM_TOTAL_DOWNLOAD_BYTES, \
pStorage->stat.total_download_bytes, \
STORAGE_ITEM_SUCCESS_DOWNLOAD_BYTES, \
pStorage->stat.success_download_bytes, \
STORAGE_ITEM_TOTAL_SYNC_IN_BYTES, \
pStorage->stat.total_sync_in_bytes, \
STORAGE_ITEM_SUCCESS_SYNC_IN_BYTES, \
pStorage->stat.success_sync_in_bytes, \
STORAGE_ITEM_TOTAL_SYNC_OUT_BYTES, \
pStorage->stat.total_sync_out_bytes, \
STORAGE_ITEM_SUCCESS_SYNC_OUT_BYTES, \
pStorage->stat.success_sync_out_bytes, \
STORAGE_ITEM_TOTAL_FILE_OPEN_COUNT, \
pStorage->stat.total_file_open_count, \
STORAGE_ITEM_SUCCESS_FILE_OPEN_COUNT, \
pStorage->stat.success_file_open_count, \
STORAGE_ITEM_TOTAL_FILE_READ_COUNT, \
pStorage->stat.total_file_read_count, \
STORAGE_ITEM_SUCCESS_FILE_READ_COUNT, \
pStorage->stat.success_file_read_count, \
STORAGE_ITEM_TOTAL_FILE_WRITE_COUNT, \
pStorage->stat.total_file_write_count, \
STORAGE_ITEM_SUCCESS_FILE_WRITE_COUNT, \
pStorage->stat.success_file_write_count, \
STORAGE_ITEM_LAST_SOURCE_UPDATE, \
(int)(pStorage->stat.last_source_update), \
STORAGE_ITEM_LAST_SYNC_UPDATE, \
(int)(pStorage->stat.last_sync_update), \
STORAGE_ITEM_LAST_SYNCED_TIMESTAMP, \
(int)pStorage->stat.last_synced_timestamp, \
STORAGE_ITEM_LAST_HEART_BEAT_TIME, \
(int)pStorage->stat.last_heart_beat_time, \
STORAGE_ITEM_CHANGELOG_OFFSET, \
pStorage->changelog_offset \
);
if (fc_safe_write(fd, buff, len) != len)
{
logError("file: "__FILE__", line: %d, " \
"write to file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
break;
}
}
}
if (result == 0)
{
len = sprintf(buff, \
"\n# global section\n" \
"[%s]\n" \
"\t%s=%d\n", \
STORAGE_SECTION_NAME_GLOBAL, \
STORAGE_ITEM_STORAGE_COUNT, count);
if (fc_safe_write(fd, buff, len) != len)
{
logError("file: "__FILE__", line: %d, " \
"write to file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
}
if (result == 0)
{
if (fsync(fd) != 0)
{
logError("file: "__FILE__", line: %d, " \
"fsync file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
}
close(fd);
if (result == 0)
{
if (rename(tmpFilename, trueFilename) != 0)
{
logError("file: "__FILE__", line: %d, " \
"rename file \"%s\" to \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, trueFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
SF_CHOWN_TO_RUNBY_RETURN_ON_ERROR(trueFilename);
}
if (result != 0)
{
unlink(tmpFilename);
}
tracker_mem_file_unlock();
return result;
}
int tracker_save_sync_timestamps()
{
char tmpFilename[MAX_PATH_SIZE];
char trueFilename[MAX_PATH_SIZE];
char buff[512];
int fd;
int len;
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
int **last_sync_timestamps;
int i;
int k;
int result;
tracker_mem_file_lock();
snprintf(trueFilename, sizeof(trueFilename), "%s/data/%s", \
SF_G_BASE_PATH_STR, STORAGE_SYNC_TIMESTAMP_FILENAME);
snprintf(tmpFilename, sizeof(tmpFilename), "%s.tmp", trueFilename);
if ((fd=open(tmpFilename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0)
{
tracker_mem_file_unlock();
logError("file: "__FILE__", line: %d, " \
"open \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
result = 0;
ppGroupEnd = g_groups.sorted_groups + g_groups.count;
for (ppGroup=g_groups.sorted_groups; \
(ppGroup < ppGroupEnd) && (result == 0); ppGroup++)
{
last_sync_timestamps = (*ppGroup)->last_sync_timestamps;
for (i=0; i<(*ppGroup)->count; i++)
{
if ((*ppGroup)->all_servers[i]->status == \
FDFS_STORAGE_STATUS_DELETED \
|| (*ppGroup)->all_servers[i]->status == \
FDFS_STORAGE_STATUS_IP_CHANGED)
{
continue;
}
len = sprintf(buff, "%s%c%s", (*ppGroup)->group_name, \
STORAGE_DATA_FIELD_SEPERATOR, \
(*ppGroup)->all_servers[i]->id);
for (k=0; k<(*ppGroup)->count; k++)
{
if ((*ppGroup)->all_servers[k]->status == \
FDFS_STORAGE_STATUS_DELETED \
|| (*ppGroup)->all_servers[k]->status == \
FDFS_STORAGE_STATUS_IP_CHANGED)
{
continue;
}
len += sprintf(buff + len, "%c%d", \
STORAGE_DATA_FIELD_SEPERATOR, \
last_sync_timestamps[i][k]);
}
*(buff + len) = '\n';
len++;
if (fc_safe_write(fd, buff, len) != len)
{
logError("file: "__FILE__", line: %d, " \
"write to file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
break;
}
}
}
if (result == 0)
{
if (fsync(fd) != 0)
{
logError("file: "__FILE__", line: %d, " \
"fsync file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
}
close(fd);
if (result == 0)
{
if (rename(tmpFilename, trueFilename) != 0)
{
logError("file: "__FILE__", line: %d, " \
"rename file \"%s\" to \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, tmpFilename, trueFilename, \
errno, STRERROR(errno));
result = errno != 0 ? errno : EIO;
}
SF_CHOWN_TO_RUNBY_RETURN_ON_ERROR(trueFilename);
}
if (result != 0)
{
unlink(tmpFilename);
}
tracker_mem_file_unlock();
return result;
}
int tracker_save_sys_files()
{
int result;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
if ((result=tracker_save_storages()) != 0)
{
return result;
}
return tracker_save_sync_timestamps();
}
static int tracker_open_changlog_file()
{
char data_path[MAX_PATH_SIZE];
char filename[MAX_PATH_SIZE];
snprintf(data_path, sizeof(data_path), "%s/data", SF_G_BASE_PATH_STR);
if (!fileExists(data_path))
{
if (mkdir(data_path, 0755) != 0)
{
logError("file: "__FILE__", line: %d, " \
"mkdir \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, data_path, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
SF_CHOWN_TO_RUNBY_RETURN_ON_ERROR(data_path);
}
snprintf(filename, sizeof(filename), "%s/data/%s", \
SF_G_BASE_PATH_STR, STORAGE_SERVERS_CHANGELOG_FILENAME);
changelog_fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
if (changelog_fd < 0)
{
logError("file: "__FILE__", line: %d, " \
"open \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, filename, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
g_changelog_fsize = lseek(changelog_fd, 0, SEEK_END);
if (g_changelog_fsize < 0)
{
logError("file: "__FILE__", line: %d, " \
"lseek file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, filename, errno, STRERROR(errno));
return errno != 0 ? errno : EIO;
}
SF_FCHOWN_TO_RUNBY_RETURN_ON_ERROR(changelog_fd, filename);
return 0;
}
static int tracker_mem_init_groups(FDFSGroups *pGroups)
{
int result;
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
pGroups->alloc_size = TRACKER_MEM_ALLOC_ONCE;
pGroups->count = 0;
pGroups->current_write_group = 0;
pGroups->pStoreGroup = NULL;
pGroups->groups = (FDFSGroupInfo **)malloc( \
sizeof(FDFSGroupInfo *) * pGroups->alloc_size);
if (pGroups->groups == NULL)
{
logCrit("file: "__FILE__", line: %d, " \
"malloc %d bytes fail!", __LINE__, \
(int)sizeof(FDFSGroupInfo *) * pGroups->alloc_size);
return errno != 0 ? errno : ENOMEM;
}
memset(pGroups->groups, 0, \
sizeof(FDFSGroupInfo *) * pGroups->alloc_size);
ppGroupEnd = pGroups->groups + pGroups->alloc_size;
for (ppGroup=pGroups->groups; ppGroup<ppGroupEnd; ppGroup++)
{
*ppGroup = (FDFSGroupInfo *)malloc(sizeof(FDFSGroupInfo));
if (*ppGroup == NULL)
{
logCrit("file: "__FILE__", line: %d, " \
"malloc %d bytes fail!", \
__LINE__, (int)sizeof(FDFSGroupInfo));
return errno != 0 ? errno : ENOMEM;
}
memset(*ppGroup, 0, sizeof(FDFSGroupInfo));
}
pGroups->sorted_groups = (FDFSGroupInfo **) \
malloc(sizeof(FDFSGroupInfo *) * pGroups->alloc_size);
if (pGroups->sorted_groups == NULL)
{
free(pGroups->groups);
pGroups->groups = NULL;
logCrit("file: "__FILE__", line: %d, " \
"malloc %d bytes fail!", __LINE__, \
(int)sizeof(FDFSGroupInfo *) * pGroups->alloc_size);
return errno != 0 ? errno : ENOMEM;
}
memset(pGroups->sorted_groups, 0, \
sizeof(FDFSGroupInfo *) * pGroups->alloc_size);
if ((result=tracker_load_data(pGroups)) != 0)
{
return result;
}
return 0;
}
int tracker_mem_init()
{
int result;
if ((result=init_pthread_lock(&mem_thread_lock)) != 0)
{
return result;
}
if ((result=init_pthread_lock(&mem_file_lock)) != 0)
{
return result;
}
if ((result=tracker_open_changlog_file()) != 0)
{
return result;
}
return tracker_mem_init_groups(&g_groups);
}
static void tracker_free_last_sync_timestamps(int **last_sync_timestamps, \
const int alloc_size)
{
int i;
if (last_sync_timestamps != NULL)
{
for (i=0; i<alloc_size; i++)
{
if (last_sync_timestamps[i] != NULL)
{
free(last_sync_timestamps[i]);
last_sync_timestamps[i] = NULL;
}
}
free(last_sync_timestamps);
}
}
static int **tracker_malloc_last_sync_timestamps(const int alloc_size, \
int *err_no)
{
int **results;
int i;
results = (int **)malloc(sizeof(int *) * alloc_size);
if (results == NULL)
{
*err_no = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(int *) * alloc_size);
return NULL;
}
memset(results, 0, sizeof(int *) * alloc_size);
for (i=0; i<alloc_size; i++)
{
results[i] = (int *)malloc(sizeof(int) * alloc_size);
if (results[i] == NULL)
{
*err_no = errno != 0 ? errno : ENOMEM;
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(int) * alloc_size);
tracker_free_last_sync_timestamps(results, alloc_size);
return NULL;
}
memset(results[i], 0, sizeof(int) * alloc_size);
}
*err_no = 0;
return results;
}
static void tracker_mem_free_storages(FDFSStorageDetail **servers, const int count)
{
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
ppServerEnd = servers + count;
for (ppServer=servers; ppServer<ppServerEnd; ppServer++)
{
if (*ppServer != NULL)
{
free(*ppServer);
}
}
free(servers);
}
static void tracker_mem_free_group(FDFSGroupInfo *pGroup)
{
if (pGroup->sorted_servers != NULL)
{
free(pGroup->sorted_servers);
pGroup->sorted_servers = NULL;
}
if (pGroup->active_servers != NULL)
{
free(pGroup->active_servers);
pGroup->active_servers = NULL;
}
if (pGroup->all_servers != NULL)
{
tracker_mem_free_storages(pGroup->all_servers, \
pGroup->alloc_size);
pGroup->all_servers = NULL;
}
#ifdef WITH_HTTPD
if (g_http_check_interval > 0)
{
if (pGroup->http_servers != NULL)
{
free(pGroup->http_servers);
pGroup->http_servers = NULL;
}
}
#endif
tracker_free_last_sync_timestamps(pGroup->last_sync_timestamps, \
pGroup->alloc_size);
pGroup->last_sync_timestamps = NULL;
}
static int tracker_mem_init_group(FDFSGroupInfo *pGroup)
{
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
int err_no;
pGroup->alloc_size = TRACKER_MEM_ALLOC_ONCE;
pGroup->count = 0;
pGroup->all_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
if (pGroup->all_servers == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
return errno != 0 ? errno : ENOMEM;
}
memset(pGroup->all_servers, 0, \
sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
ppServerEnd = pGroup->all_servers + pGroup->alloc_size;
for (ppServer=pGroup->all_servers; ppServer<ppServerEnd; ppServer++)
{
*ppServer = (FDFSStorageDetail *)malloc( \
sizeof(FDFSStorageDetail));
if (*ppServer == NULL)
{
tracker_mem_free_group(pGroup);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail));
return errno != 0 ? errno : ENOMEM;
}
memset(*ppServer, 0, sizeof(FDFSStorageDetail));
}
pGroup->sorted_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
if (pGroup->sorted_servers == NULL)
{
tracker_mem_free_group(pGroup);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
return errno != 0 ? errno : ENOMEM;
}
memset(pGroup->sorted_servers, 0, \
sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
pGroup->active_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
if (pGroup->active_servers == NULL)
{
tracker_mem_free_group(pGroup);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
return errno != 0 ? errno : ENOMEM;
}
memset(pGroup->active_servers, 0, \
sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
#ifdef WITH_HTTPD
if (g_http_check_interval <= 0)
{
pGroup->http_servers = pGroup->active_servers;
}
else
{
pGroup->http_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *)*pGroup->alloc_size);
if (pGroup->http_servers == NULL)
{
tracker_mem_free_group(pGroup);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail *) * \
pGroup->alloc_size);
return errno != 0 ? errno : ENOMEM;
}
memset(pGroup->http_servers, 0, \
sizeof(FDFSStorageDetail *) * pGroup->alloc_size);
g_http_servers_dirty = true;
}
#endif
pGroup->last_sync_timestamps = tracker_malloc_last_sync_timestamps( \
pGroup->alloc_size, &err_no);
return err_no;
}
static int tracker_mem_destroy_groups(FDFSGroups *pGroups, const bool saveFiles)
{
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppEnd;
int result;
if (pGroups->groups == NULL)
{
result = 0;
}
else
{
if (saveFiles)
{
result = tracker_save_sys_files();
}
else
{
result = 0;
}
ppEnd = pGroups->groups + pGroups->count;
for (ppGroup=pGroups->groups; ppGroup<ppEnd; ppGroup++)
{
tracker_mem_free_group(*ppGroup);
}
if (pGroups->sorted_groups != NULL)
{
free(pGroups->sorted_groups);
pGroups->sorted_groups = NULL;
}
free(pGroups->groups);
pGroups->groups = NULL;
}
return result;
}
int tracker_mem_destroy()
{
int result;
result = tracker_mem_destroy_groups(&g_groups, true);
if (changelog_fd >= 0)
{
close(changelog_fd);
changelog_fd = -1;
}
if (pthread_mutex_destroy(&mem_thread_lock) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_destroy fail", \
__LINE__);
}
if (pthread_mutex_destroy(&mem_file_lock) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_destroy fail", \
__LINE__);
}
return result;
}
static void tracker_mem_free_groups(FDFSGroupInfo **groups, const int count)
{
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
ppGroupEnd = groups + count;
for (ppGroup=groups; ppGroup<ppGroupEnd; ppGroup++)
{
if (*ppGroup != NULL)
{
free(*ppGroup);
}
}
free(groups);
}
static int tracker_mem_realloc_groups(FDFSGroups *pGroups, const bool bNeedSleep)
{
FDFSGroupInfo **old_groups;
FDFSGroupInfo **old_sorted_groups;
FDFSGroupInfo **new_groups;
FDFSGroupInfo **new_sorted_groups;
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
int new_size;
new_size = pGroups->alloc_size + TRACKER_MEM_ALLOC_ONCE;
new_groups = (FDFSGroupInfo **)malloc(sizeof(FDFSGroupInfo *) * new_size);
if (new_groups == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", \
__LINE__, (int)sizeof(FDFSGroupInfo *) * new_size);
return errno != 0 ? errno : ENOMEM;
}
memset(new_groups, 0, sizeof(FDFSGroupInfo *) * new_size);
ppGroupEnd = new_groups + new_size;
for (ppGroup=new_groups+pGroups->count; ppGroup<ppGroupEnd; ppGroup++)
{
*ppGroup = (FDFSGroupInfo *)malloc(sizeof(FDFSGroupInfo));
if (*ppGroup == NULL)
{
tracker_mem_free_groups(new_groups, new_size);
logCrit("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", \
__LINE__, (int)sizeof(FDFSGroupInfo));
return errno != 0 ? errno : ENOMEM;
}
memset(*ppGroup, 0, sizeof(FDFSGroupInfo));
}
memcpy(new_groups, pGroups->groups, \
sizeof(FDFSGroupInfo *) * pGroups->count);
new_sorted_groups = (FDFSGroupInfo **)malloc( \
sizeof(FDFSGroupInfo *) * new_size);
if (new_sorted_groups == NULL)
{
tracker_mem_free_groups(new_groups, new_size);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", \
__LINE__, (int)sizeof(FDFSGroupInfo *) * new_size);
return errno != 0 ? errno : ENOMEM;
}
memset(new_sorted_groups, 0, sizeof(FDFSGroupInfo *) * new_size);
memcpy(new_sorted_groups, pGroups->sorted_groups, \
sizeof(FDFSGroupInfo *) * pGroups->count);
old_groups = pGroups->groups;
old_sorted_groups = pGroups->sorted_groups;
pGroups->alloc_size = new_size;
pGroups->groups = new_groups;
pGroups->sorted_groups = new_sorted_groups;
if (bNeedSleep)
{
sleep(1);
}
free(old_groups);
free(old_sorted_groups);
return 0;
}
int tracker_get_group_file_count(FDFSGroupInfo *pGroup)
{
int count;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
count = 0;
ppServerEnd = pGroup->all_servers + pGroup->count;
for (ppServer=pGroup->all_servers; ppServer<ppServerEnd; ppServer++)
{
count += (*ppServer)->stat.success_upload_count - \
(*ppServer)->stat.success_delete_count;
}
return count;
}
int tracker_get_group_success_upload_count(FDFSGroupInfo *pGroup)
{
int count;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
count = 0;
ppServerEnd = pGroup->all_servers + pGroup->count;
for (ppServer=pGroup->all_servers; ppServer<ppServerEnd; ppServer++)
{
count += (*ppServer)->stat.success_upload_count;
}
return count;
}
FDFSStorageDetail *tracker_get_group_sync_src_server(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pDestServer)
{
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
ppServerEnd = pGroup->active_servers + pGroup->active_count;
for (ppServer=pGroup->active_servers; ppServer<ppServerEnd; ppServer++)
{
if (strcmp((*ppServer)->id, pDestServer->id) == 0)
{
continue;
}
return *ppServer;
}
return NULL;
}
static int tracker_mem_realloc_store_servers(FDFSGroupInfo *pGroup, \
const int inc_count, const bool bNeedSleep)
{
int result;
FDFSStorageDetail **old_servers;
FDFSStorageDetail **old_sorted_servers;
FDFSStorageDetail **old_active_servers;
int **old_last_sync_timestamps;
FDFSStorageDetail **new_servers;
FDFSStorageDetail **new_sorted_servers;
FDFSStorageDetail **new_active_servers;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
#ifdef WITH_HTTPD
FDFSStorageDetail **old_http_servers;
FDFSStorageDetail **new_http_servers;
#endif
int **new_last_sync_timestamps;
int old_size;
int new_size;
int err_no;
int i;
new_size = pGroup->alloc_size + inc_count + TRACKER_MEM_ALLOC_ONCE;
new_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * new_size);
if (new_servers == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", \
__LINE__, (int)sizeof(FDFSStorageDetail *) * new_size);
return errno != 0 ? errno : ENOMEM;
}
memset(new_servers, 0, sizeof(FDFSStorageDetail *) * new_size);
ppServerEnd = new_servers + new_size;
for (ppServer=new_servers+pGroup->count; ppServer<ppServerEnd; ppServer++)
{
*ppServer = (FDFSStorageDetail *)malloc( \
sizeof(FDFSStorageDetail));
if (*ppServer == NULL)
{
tracker_mem_free_storages(new_servers, new_size);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail));
return errno != 0 ? errno : ENOMEM;
}
memset(*ppServer, 0, sizeof(FDFSStorageDetail));
}
memcpy(new_servers, pGroup->all_servers, \
sizeof(FDFSStorageDetail *) * pGroup->count);
new_sorted_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * new_size);
if (new_sorted_servers == NULL)
{
free(new_servers);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", \
__LINE__, (int)sizeof(FDFSStorageDetail *) * new_size);
return errno != 0 ? errno : ENOMEM;
}
new_active_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * new_size);
if (new_active_servers == NULL)
{
free(new_servers);
free(new_sorted_servers);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", \
__LINE__, (int)sizeof(FDFSStorageDetail *) * new_size);
return errno != 0 ? errno : ENOMEM;
}
#ifdef WITH_HTTPD
if (g_http_check_interval > 0)
{
new_http_servers = (FDFSStorageDetail **) \
malloc(sizeof(FDFSStorageDetail *) * new_size);
if (new_http_servers == NULL)
{
free(new_servers);
free(new_sorted_servers);
free(new_active_servers);
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, \
(int)sizeof(FDFSStorageDetail *) * new_size);
return errno != 0 ? errno : ENOMEM;
}
memset(new_http_servers,0,sizeof(FDFSStorageDetail *)*new_size);
memcpy(new_http_servers, pGroup->http_servers, \
sizeof(FDFSStorageDetail *) * pGroup->count);
}
else
{
new_http_servers = NULL;
}
#endif
memset(new_sorted_servers, 0, sizeof(FDFSStorageDetail *) * new_size);
memset(new_active_servers, 0, sizeof(FDFSStorageDetail *) * new_size);
if (pGroup->store_path_count > 0)
{
for (i=pGroup->count; i<new_size; i++)
{
result=tracker_malloc_storage_path_mbs(*(new_servers+i), \
pGroup->store_path_count);
if (result != 0)
{
free(new_servers);
free(new_sorted_servers);
free(new_active_servers);
return result;
}
}
}
memcpy(new_sorted_servers, pGroup->sorted_servers, \
sizeof(FDFSStorageDetail *) * pGroup->count);
memcpy(new_active_servers, pGroup->active_servers, \
sizeof(FDFSStorageDetail *) * pGroup->count);
new_last_sync_timestamps = tracker_malloc_last_sync_timestamps( \
new_size, &err_no);
if (new_last_sync_timestamps == NULL)
{
free(new_servers);
free(new_sorted_servers);
free(new_active_servers);
return err_no;
}
for (i=0; i<pGroup->alloc_size; i++)
{
memcpy(new_last_sync_timestamps[i], \
pGroup->last_sync_timestamps[i], \
(int)sizeof(int) * pGroup->alloc_size);
}
old_size = pGroup->alloc_size;
old_servers = pGroup->all_servers;
old_sorted_servers = pGroup->sorted_servers;
old_active_servers = pGroup->active_servers;
old_last_sync_timestamps = pGroup->last_sync_timestamps;
pGroup->alloc_size = new_size;
pGroup->all_servers = new_servers;
pGroup->sorted_servers = new_sorted_servers;
pGroup->active_servers = new_active_servers;
pGroup->last_sync_timestamps = new_last_sync_timestamps;
tracker_mem_find_store_server(pGroup);
if (g_if_leader_self && g_if_use_trunk_file)
{
tracker_mem_find_trunk_server(pGroup, true);
}
#ifdef WITH_HTTPD
if (g_http_check_interval <= 0)
{
old_http_servers = NULL;
pGroup->http_servers = pGroup->active_servers;
}
else
{
old_http_servers = pGroup->http_servers;
pGroup->http_servers = new_http_servers;
g_http_servers_dirty = true;
}
#endif
if (bNeedSleep)
{
sleep(1);
}
free(old_servers);
free(old_sorted_servers);
free(old_active_servers);
#ifdef WITH_HTTPD
if (old_http_servers != NULL)
{
free(old_http_servers);
}
#endif
tracker_free_last_sync_timestamps(old_last_sync_timestamps, \
old_size);
return 0;
}
static int tracker_mem_cmp_by_group_name(const void *p1, const void *p2)
{
return strcmp((*((FDFSGroupInfo **)p1))->group_name,
(*((FDFSGroupInfo **)p2))->group_name);
}
static int tracker_mem_cmp_by_storage_id(const void *p1, const void *p2)
{
return strcmp((*((FDFSStorageDetail **)p1))->id,
(*((FDFSStorageDetail **)p2))->id);
}
static void tracker_mem_insert_into_sorted_servers( \
FDFSStorageDetail *pTargetServer, \
FDFSStorageDetail **sorted_servers, const int count)
{
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppEnd;
ppEnd = sorted_servers + count;
for (ppServer=ppEnd; ppServer>sorted_servers; ppServer--)
{
if (strcmp(pTargetServer->id, (*(ppServer-1))->id) > 0)
{
break;
}
else
{
*ppServer = *(ppServer-1);
}
}
*ppServer = pTargetServer;
}
static void tracker_mem_insert_into_sorted_groups(FDFSGroups *pGroups, \
FDFSGroupInfo *pTargetGroup)
{
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppEnd;
ppEnd = pGroups->sorted_groups + pGroups->count;
for (ppGroup=ppEnd; ppGroup > pGroups->sorted_groups; ppGroup--)
{
if (strcmp(pTargetGroup->group_name, \
(*(ppGroup-1))->group_name) > 0)
{
*ppGroup = pTargetGroup;
return;
}
else
{
*ppGroup = *(ppGroup-1);
}
}
*ppGroup = pTargetGroup;
}
FDFSGroupInfo *tracker_mem_get_group_ex(FDFSGroups *pGroups, \
const char *group_name)
{
FDFSGroupInfo target_groups;
FDFSGroupInfo *pTargetGroups;
FDFSGroupInfo **ppGroup;
memset(&target_groups, 0, sizeof(target_groups));
strcpy(target_groups.group_name, group_name);
pTargetGroups = &target_groups;
ppGroup = (FDFSGroupInfo **)bsearch(&pTargetGroups, \
pGroups->sorted_groups, \
pGroups->count, sizeof(FDFSGroupInfo *), \
tracker_mem_cmp_by_group_name);
if (ppGroup != NULL)
{
return *ppGroup;
}
else
{
return NULL;
}
}
static int tracker_mem_add_group_ex(FDFSGroups *pGroups, \
TrackerClientInfo *pClientInfo, const char *group_name, \
const bool bNeedSleep, bool *bInserted)
{
FDFSGroupInfo *pGroup;
int result;
if ((result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
do
{
result = 0;
*bInserted = false;
pGroup = tracker_mem_get_group_ex(pGroups, group_name);
if (pGroup != NULL)
{
break;
}
if (pGroups->count >= pGroups->alloc_size)
{
result = tracker_mem_realloc_groups(pGroups, bNeedSleep);
if (result != 0)
{
break;
}
}
pGroup = *(pGroups->groups + pGroups->count);
result = tracker_mem_init_group(pGroup);
if (result != 0)
{
break;
}
strcpy(pGroup->group_name, group_name);
tracker_mem_insert_into_sorted_groups(pGroups, pGroup);
pGroups->count++;
if ((pGroups->store_lookup == \
FDFS_STORE_LOOKUP_SPEC_GROUP) && \
(pGroups->pStoreGroup == NULL) && \
(strcmp(pGroups->store_group, \
pGroup->group_name) == 0))
{
pGroups->pStoreGroup = pGroup;
}
*bInserted = true;
} while (0);
if (pthread_mutex_unlock(&mem_thread_lock) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail", \
__LINE__);
}
if (result != 0)
{
return result;
}
pClientInfo->pGroup = pGroup;
return 0;
}
static FDFSStorageDetail *tracker_mem_get_active_storage_by_id( \
FDFSGroupInfo *pGroup, const char *id)
{
FDFSStorageDetail target_storage;
FDFSStorageDetail *pTargetStorage;
FDFSStorageDetail **ppStorageServer;
if (id == NULL)
{
return NULL;
}
memset(&target_storage, 0, sizeof(target_storage));
strcpy(target_storage.id, id);
pTargetStorage = &target_storage;
ppStorageServer = (FDFSStorageDetail **)bsearch(&pTargetStorage, \
pGroup->active_servers, \
pGroup->active_count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer != NULL)
{
return *ppStorageServer;
}
else
{
return NULL;
}
}
static FDFSStorageDetail *tracker_mem_get_active_storage_by_ip( \
FDFSGroupInfo *pGroup, const char *ip_addr)
{
FDFSStorageIdInfo *pStorageId;
if (!g_use_storage_id)
{
return tracker_mem_get_active_storage_by_id(pGroup, ip_addr);
}
pStorageId = fdfs_get_storage_id_by_ip(pGroup->group_name, ip_addr);
if (pStorageId == NULL)
{
return NULL;
}
return tracker_mem_get_active_storage_by_id(pGroup, pStorageId->id);
}
#ifdef WITH_HTTPD
static FDFSStorageDetail *tracker_mem_get_active_http_server_by_ip( \
FDFSGroupInfo *pGroup, const char *ip_addr)
{
FDFSStorageDetail target_storage;
FDFSStorageDetail *pTargetStorage;
FDFSStorageDetail **ppStorageServer;
memset(&target_storage, 0, sizeof(target_storage));
if (!g_use_storage_id)
{
strcpy(target_storage.id, ip_addr);
// 当IP地址为IPv6时其storage_id值为IP地址的short code
if(is_ipv6_addr(ip_addr)){
strcpy(target_storage.id, fdfs_ip_to_shortcode(ip_addr, FDFS_DEFAULT_STORAGE_ID_LEN));
}
}
else
{
FDFSStorageIdInfo *pStorageId;
pStorageId = fdfs_get_storage_id_by_ip( \
pGroup->group_name, ip_addr);
if (pStorageId == NULL)
{
return NULL;
}
strcpy(target_storage.id, pStorageId->id);
}
pTargetStorage = &target_storage;
ppStorageServer = (FDFSStorageDetail **)bsearch(&pTargetStorage, \
pGroup->http_servers, \
pGroup->http_server_count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer != NULL)
{
return *ppStorageServer;
}
else
{
return NULL;
}
}
static FDFSStorageDetail *tracker_mem_get_active_http_server_by_id( \
FDFSGroupInfo *pGroup, const char *storage_id)
{
FDFSStorageDetail target_storage;
FDFSStorageDetail *pTargetStorage;
FDFSStorageDetail **ppStorageServer;
memset(&target_storage, 0, sizeof(target_storage));
strcpy(target_storage.id, storage_id);
pTargetStorage = &target_storage;
ppStorageServer = (FDFSStorageDetail **)bsearch(&pTargetStorage, \
pGroup->http_servers, \
pGroup->http_server_count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer != NULL)
{
return *ppStorageServer;
}
else
{
return NULL;
}
}
#endif
FDFSStorageDetail *tracker_mem_get_storage_by_ip(FDFSGroupInfo *pGroup, \
const char *ip_addr)
{
const char *storage_id;
if (g_use_storage_id)
{
FDFSStorageIdInfo *pStorageIdInfo;
pStorageIdInfo = fdfs_get_storage_id_by_ip( \
pGroup->group_name, ip_addr);
if (pStorageIdInfo == NULL)
{
return NULL;
}
storage_id = pStorageIdInfo->id;
}
else
{
storage_id = ip_addr;
// 当IP地址为IPv6时其storage_id值为IP地址的short code
if(is_ipv6_addr(ip_addr)){
storage_id = fdfs_ip_to_shortcode(ip_addr, FDFS_DEFAULT_STORAGE_ID_LEN);
}
}
return tracker_mem_get_storage(pGroup, storage_id);
}
FDFSStorageDetail *tracker_mem_get_storage(FDFSGroupInfo *pGroup, \
const char *id)
{
FDFSStorageDetail target_storage;
FDFSStorageDetail *pTargetStorage;
FDFSStorageDetail **ppStorageServer;
memset(&target_storage, 0, sizeof(target_storage));
strcpy(target_storage.id, id);
pTargetStorage = &target_storage;
ppStorageServer = (FDFSStorageDetail **)bsearch(&pTargetStorage, \
pGroup->sorted_servers, \
pGroup->count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer != NULL)
{
return *ppStorageServer;
}
else
{
return NULL;
}
}
static void tracker_mem_clear_storage_fields(FDFSStorageDetail *pStorageServer)
{
if (pStorageServer->path_total_mbs != NULL)
{
memset(pStorageServer->path_total_mbs, 0, sizeof(int64_t) \
* pStorageServer->store_path_count);
}
if (pStorageServer->path_free_mbs != NULL)
{
memset(pStorageServer->path_free_mbs, 0, sizeof(int64_t) \
* pStorageServer->store_path_count);
}
pStorageServer->psync_src_server = NULL;
pStorageServer->sync_until_timestamp = 0;
pStorageServer->total_mb = 0;
pStorageServer->free_mb = 0;
pStorageServer->changelog_offset = 0;
pStorageServer->store_path_count = 0;
pStorageServer->subdir_count_per_path = 0;
pStorageServer->upload_priority = 0;
pStorageServer->current_write_path = 0;
memset(&(pStorageServer->stat), 0, sizeof(FDFSStorageStat));
}
static int tracker_mem_remove_group(FDFSGroupInfo **groups, FDFSGroupInfo *pGroup)
{
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppEnd;
FDFSGroupInfo **pp;
ppEnd = groups + g_groups.count;
for (ppGroup=groups; ppGroup<ppEnd; ppGroup++)
{
if (*ppGroup == pGroup)
{
break;
}
}
if (ppGroup == ppEnd)
{
return ENOENT;
}
for (pp=ppGroup + 1; pp<ppEnd; pp++)
{
*(pp - 1) = *pp;
}
return 0;
}
int tracker_mem_delete_group(const char *group_name)
{
FDFSGroupInfo *pGroup;
int result;
pGroup = tracker_mem_get_group(group_name);
if (pGroup == NULL)
{
return ENOENT;
}
if (pGroup->count != 0)
{
return EBUSY;
}
pthread_mutex_lock(&mem_thread_lock);
if (pGroup->count != 0)
{
result = EBUSY;
}
else
{
result = tracker_mem_remove_group(g_groups.groups, pGroup);
if (result == 0)
{
result = tracker_mem_remove_group(g_groups.sorted_groups, pGroup);
}
}
if (result == 0)
{
if (g_groups.pStoreGroup == pGroup)
{
g_groups.pStoreGroup = NULL;
}
g_groups.count--;
}
pthread_mutex_unlock(&mem_thread_lock);
if (result != 0)
{
return result;
}
logDebug("file: "__FILE__", line: %d, " \
"delete empty group: %s", \
__LINE__, group_name);
sleep(1);
free(pGroup);
return tracker_save_groups();
}
int tracker_mem_delete_storage(FDFSGroupInfo *pGroup, const char *id)
{
FDFSStorageDetail *pStorageServer;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppEnd;
pStorageServer = tracker_mem_get_storage(pGroup, id);
if (pStorageServer == NULL || pStorageServer->status == \
FDFS_STORAGE_STATUS_IP_CHANGED)
{
return ENOENT;
}
if (pStorageServer->status == FDFS_STORAGE_STATUS_ONLINE || \
pStorageServer->status == FDFS_STORAGE_STATUS_ACTIVE || \
pStorageServer->status == FDFS_STORAGE_STATUS_RECOVERY)
{
return EBUSY;
}
if (pStorageServer->status == FDFS_STORAGE_STATUS_DELETED)
{
return EALREADY;
}
ppEnd = pGroup->all_servers + pGroup->count;
for (ppServer=pGroup->all_servers; ppServer<ppEnd; ppServer++)
{
if ((*ppServer)->psync_src_server != NULL && \
strcmp((*ppServer)->psync_src_server->id, id) == 0)
{
(*ppServer)->psync_src_server = NULL;
}
}
logDebug("file: "__FILE__", line: %d, "
"delete storage server: %s:%u, group: %s",
__LINE__, pStorageServer->ip_addrs.ips[0].address,
pStorageServer->storage_port, pGroup->group_name);
tracker_mem_clear_storage_fields(pStorageServer);
pStorageServer->status = FDFS_STORAGE_STATUS_DELETED;
pGroup->chg_count++;
tracker_write_to_changelog(pGroup, pStorageServer, NULL);
return 0;
}
int tracker_mem_storage_ip_changed(FDFSGroupInfo *pGroup, \
const char *old_storage_ip, const char *new_storage_ip)
{
FDFSStorageDetail *pOldStorageServer;
FDFSStorageDetail *pNewStorageServer;
int result;
bool bInserted;
if (g_use_storage_id)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, do NOT support ip changed adjust " \
"because cluster use server ID instead of " \
"IP address", __LINE__, new_storage_ip);
return EOPNOTSUPP;
}
pOldStorageServer = tracker_mem_get_storage(pGroup, old_storage_ip);
if (pOldStorageServer == NULL || pOldStorageServer->status == \
FDFS_STORAGE_STATUS_DELETED)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, old storage server: %s not exists", \
__LINE__, new_storage_ip, old_storage_ip);
return ENOENT;
}
if (pOldStorageServer->status == FDFS_STORAGE_STATUS_ONLINE || \
pOldStorageServer->status == FDFS_STORAGE_STATUS_ACTIVE || \
pOldStorageServer->status == FDFS_STORAGE_STATUS_RECOVERY)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, old storage server: %s is online", \
__LINE__, new_storage_ip, old_storage_ip);
return EBUSY;
}
if (pOldStorageServer->status == FDFS_STORAGE_STATUS_IP_CHANGED)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, old storage server: %s " \
"'s ip address already changed", \
__LINE__, new_storage_ip, old_storage_ip);
return EALREADY;
}
pNewStorageServer = tracker_mem_get_storage(pGroup, new_storage_ip);
if (!(pNewStorageServer == NULL || pNewStorageServer->status == \
FDFS_STORAGE_STATUS_DELETED))
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, new storage server: %s already exists",\
__LINE__, new_storage_ip, new_storage_ip);
return EEXIST;
}
result = _tracker_mem_add_storage(pGroup, &pNewStorageServer, \
new_storage_ip, new_storage_ip, true, true, &bInserted);
if (result != 0)
{
return result;
}
if (!bInserted)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, new storage server: %s already exists",\
__LINE__, new_storage_ip, new_storage_ip);
return EEXIST;
}
pthread_mutex_lock(&mem_thread_lock);
//exchange old and new storage server
snprintf(pOldStorageServer->id, sizeof(pOldStorageServer->id),
"%s", new_storage_ip);
snprintf(pOldStorageServer->ip_addrs.ips[0].address,
sizeof(pOldStorageServer->ip_addrs.ips[0].address),
"%s", new_storage_ip);
snprintf(pNewStorageServer->id, sizeof(pNewStorageServer->id),
"%s", old_storage_ip);
pNewStorageServer->ip_addrs.count = 1;
snprintf(pNewStorageServer->ip_addrs.ips[0].address,
sizeof(pNewStorageServer->ip_addrs.ips[0].address),
"%s", old_storage_ip);
pNewStorageServer->status = FDFS_STORAGE_STATUS_IP_CHANGED;
pGroup->chg_count++;
//need re-sort
qsort(pGroup->sorted_servers, pGroup->count,
sizeof(FDFSStorageDetail *), tracker_mem_cmp_by_storage_id);
pthread_mutex_unlock(&mem_thread_lock);
tracker_write_to_changelog(pGroup, pNewStorageServer, new_storage_ip);
return tracker_save_sys_files();
}
static int tracker_mem_add_storage(TrackerClientInfo *pClientInfo,
const char *id, const char *ip_addr,
const bool bNeedSleep, const bool bNeedLock, bool *bInserted)
{
int result;
FDFSStorageDetail *pStorageServer;
pStorageServer = NULL;
result = _tracker_mem_add_storage(pClientInfo->pGroup, \
&pStorageServer, id, ip_addr, bNeedSleep, \
bNeedLock, bInserted);
if (result == 0)
{
pClientInfo->pStorage = pStorageServer;
}
return result;
}
static int tracker_mem_add_storage_from_file(FDFSGroups *pGroups,
const char *data_path, TrackerClientInfo *pClientInfo,
const char *group_name, const char *storage_id, char *ip_addr)
{
int result;
bool bInserted;
if (g_use_storage_id)
{
if (storage_id == NULL || *storage_id == '\0')
{
FDFSStorageIdInfo *idInfo;
idInfo = fdfs_get_storage_id_by_ip(group_name, ip_addr);
if (idInfo == NULL)
{
logError("file: "__FILE__", line: %d, "
"in the file \"%s/%s\", "
"group: %s, item \"%s\" is not found or empty, "
"and storage ip %s not configed in storage_ids.conf",
__LINE__, data_path,
STORAGE_SERVERS_LIST_FILENAME_NEW,
group_name, STORAGE_ITEM_SERVER_ID, ip_addr);
return ENOENT;
}
storage_id = idInfo->id;
}
}
if (ip_addr == NULL)
{
logError("file: "__FILE__", line: %d, "
"in the file \"%s/%s\", "
"group: %s, item \"%s\" is not found",
__LINE__, data_path,
STORAGE_SERVERS_LIST_FILENAME_NEW,
group_name, STORAGE_ITEM_IP_ADDR);
return ENOENT;
}
if (*ip_addr == '\0')
{
logWarning("file: "__FILE__", line: %d, "
"in the file \"%s/%s\", "
"group: %s, item \"%s\" is empty",
__LINE__, data_path,
STORAGE_SERVERS_LIST_FILENAME_NEW,
group_name, STORAGE_ITEM_IP_ADDR);
return ENOENT;
}
memset(pClientInfo, 0, sizeof(TrackerClientInfo));
if ((pClientInfo->pGroup=tracker_mem_get_group_ex(pGroups,
group_name)) == NULL)
{
logError("file: "__FILE__", line: %d, "
"in the file \"%s/%s\", "
"group \"%s\" is not found",
__LINE__, data_path,
STORAGE_SERVERS_LIST_FILENAME_NEW,
group_name);
return errno != 0 ? errno : ENOENT;
}
if ((result=tracker_mem_add_storage(pClientInfo, storage_id,
ip_addr, false, false, &bInserted)) != 0)
{
return result;
}
if (!bInserted)
{
logError("file: "__FILE__", line: %d, "
"in the file \"%s/%s\", "
"storage \"%s\" is duplicate",
__LINE__, data_path,
STORAGE_SERVERS_LIST_FILENAME_NEW, ip_addr);
return EEXIST;
}
return 0;
}
static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup,
FDFSStorageDetail **ppStorageServer, const char *id,
const char *ip_addr, const bool bNeedSleep,
const bool bNeedLock, bool *bInserted)
{
int result;
const char *storage_id;
FDFSStorageIdInfo *pStorageIdInfo;
FDFSMultiIP multi_ip;
if (*ip_addr == '\0')
{
logError("file: "__FILE__", line: %d, " \
"ip address is empty!", __LINE__);
return EINVAL;
}
memset(&multi_ip, 0, sizeof(multi_ip));
if (!g_use_storage_id)
{
multi_ip.count = 1;
multi_ip.index = 0;
strcpy(multi_ip.ips[0].address, ip_addr);
}
if (id != NULL)
{
if (g_use_storage_id)
{
pStorageIdInfo = fdfs_get_storage_by_id(id);
if (pStorageIdInfo == NULL)
{
logError("file: "__FILE__", line: %d, "
"storage id: %s not exist in config file, "
"group_name: %s, storage ip: %s", __LINE__,
id, pGroup->group_name, ip_addr);
return ENOENT;
}
if (strcmp(pStorageIdInfo->group_name, pGroup->group_name) != 0)
{
logError("file: "__FILE__", line: %d, "
"check storage id fail, inconsistent group names, "
"id: %s, storage ip: %s, "
"reported group_name: %s != "
"group name in config file: %s", __LINE__,
pGroup->group_name, id, ip_addr,
pStorageIdInfo->group_name);
return EINVAL;
}
multi_ip = pStorageIdInfo->ip_addrs;
}
storage_id = id;
}
else if (g_use_storage_id)
{
pStorageIdInfo = fdfs_get_storage_id_by_ip(
pGroup->group_name, ip_addr);
if (pStorageIdInfo == NULL)
{
logError("file: "__FILE__", line: %d, "
"get storage id info fail, "
"group_name: %s, storage ip: %s not exist in config file",
__LINE__, pGroup->group_name, ip_addr);
return ENOENT;
}
multi_ip = pStorageIdInfo->ip_addrs;
storage_id = pStorageIdInfo->id;
}
else
{
storage_id = ip_addr;
// 当IP地址为IPv6时其storage_id值为IP地址的short code
if(is_ipv6_addr(ip_addr)){
storage_id = fdfs_ip_to_shortcode(ip_addr, FDFS_DEFAULT_STORAGE_ID_LEN);
}
}
if (bNeedLock && (result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
do
{
result = 0;
*bInserted = false;
*ppStorageServer = tracker_mem_get_storage(pGroup, storage_id);
if (*ppStorageServer != NULL)
{
if (g_use_storage_id)
{
fdfs_set_multi_ip_index(&(*ppStorageServer)->ip_addrs, ip_addr);
}
if ((*ppStorageServer)->status==FDFS_STORAGE_STATUS_DELETED \
|| (*ppStorageServer)->status==FDFS_STORAGE_STATUS_IP_CHANGED)
{
(*ppStorageServer)->status = FDFS_STORAGE_STATUS_INIT;
}
break;
}
if (pGroup->count >= pGroup->alloc_size)
{
result = tracker_mem_realloc_store_servers(
pGroup, 1, bNeedSleep);
if (result != 0)
{
break;
}
}
*ppStorageServer = *(pGroup->all_servers + pGroup->count);
snprintf((*ppStorageServer)->id, FDFS_STORAGE_ID_MAX_SIZE,
"%s", storage_id);
(*ppStorageServer)->ip_addrs = multi_ip;
if (g_use_storage_id)
{
fdfs_set_multi_ip_index(&(*ppStorageServer)->ip_addrs, ip_addr);
}
tracker_mem_insert_into_sorted_servers(*ppStorageServer,
pGroup->sorted_servers, pGroup->count);
pGroup->count++;
pGroup->chg_count++;
*bInserted = true;
} while (0);
if (bNeedLock && pthread_mutex_unlock(&mem_thread_lock) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail", \
__LINE__);
}
return result;
}
void tracker_calc_running_times(TrackerRunningStatus *pStatus)
{
pStatus->running_time = g_current_time - g_sf_global_vars.up_time;
if (g_tracker_last_status.last_check_time == 0)
{
pStatus->restart_interval = 0;
}
else
{
pStatus->restart_interval = g_sf_global_vars.up_time -
g_tracker_last_status.last_check_time;
}
#define FDFS_TRIM_TIME(t, i) (t / i) * i
pStatus->running_time = FDFS_TRIM_TIME(pStatus->running_time, \
TRACKER_SYNC_STATUS_FILE_INTERVAL);
pStatus->restart_interval = FDFS_TRIM_TIME(pStatus->restart_interval, \
TRACKER_SYNC_STATUS_FILE_INTERVAL);
}
static int tracker_mem_get_sys_file_piece(ConnectionInfo *pTrackerServer, \
const int file_index, int fd, int64_t *offset, int64_t *file_size)
{
char out_buff[sizeof(TrackerHeader) + 1 + FDFS_PROTO_PKG_LEN_SIZE];
char in_buff[TRACKER_MAX_PACKAGE_SIZE];
TrackerHeader *pHeader;
char *p;
char *pInBuff;
char *pContent;
int64_t in_bytes;
int64_t write_bytes;
int result;
memset(out_buff, 0, sizeof(out_buff));
pHeader = (TrackerHeader *)out_buff;
pHeader->cmd = TRACKER_PROTO_CMD_TRACKER_GET_ONE_SYS_FILE;
long2buff(1 + FDFS_PROTO_PKG_LEN_SIZE, pHeader->pkg_len);
p = out_buff + sizeof(TrackerHeader);
*p++ = file_index;
long2buff(*offset, p);
if ((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, \
sizeof(out_buff), SF_G_NETWORK_TIMEOUT)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"send data to tracker server %s:%u fail, " \
"errno: %d, error info: %s", __LINE__, \
pTrackerServer->ip_addr, \
pTrackerServer->port, \
result, STRERROR(result));
return (result == ENOENT ? EACCES : result);
}
pInBuff = in_buff;
result = fdfs_recv_response(pTrackerServer, &pInBuff, \
sizeof(in_buff), &in_bytes);
if (result != 0)
{
logError("file: "__FILE__", line: %d, "
"fdfs_recv_response fail, result: %d",
__LINE__, result);
return result;
}
if (in_bytes < FDFS_PROTO_PKG_LEN_SIZE)
{
logError("file: "__FILE__", line: %d, " \
"tracker server %s:%u response data " \
"length: %"PRId64" is invalid, " \
"expect length >= %d.", __LINE__, \
pTrackerServer->ip_addr, pTrackerServer->port, \
in_bytes, FDFS_PROTO_PKG_LEN_SIZE);
return EINVAL;
}
*file_size = buff2long(in_buff);
write_bytes = in_bytes - FDFS_PROTO_PKG_LEN_SIZE;
if (*file_size < 0)
{
logError("file: "__FILE__", line: %d, " \
"tracker server %s:%u, file size: %"PRId64\
" < 0", __LINE__, pTrackerServer->ip_addr, \
pTrackerServer->port, *file_size);
return EINVAL;
}
if (*file_size > 0 && write_bytes == 0)
{
logError("file: "__FILE__", line: %d, " \
"tracker server %s:%u, file size: %"PRId64\
" > 0, but file content is empty", __LINE__, \
pTrackerServer->ip_addr, pTrackerServer->port, \
*file_size);
return EINVAL;
}
pContent = pInBuff + FDFS_PROTO_PKG_LEN_SIZE;
if (write_bytes > 0 &&
fc_safe_write(fd, pContent, write_bytes) != write_bytes)
{
logError("file: "__FILE__", line: %d, " \
"write to file %s fail, " \
"errno: %d, error info: %s", \
__LINE__, g_tracker_sys_filenames[file_index], \
errno, STRERROR(errno));
return errno != 0 ? errno : EIO;
}
*offset += write_bytes;
return 0;
}
static int tracker_mem_get_one_sys_file(ConnectionInfo *pTrackerServer, \
const int file_index)
{
char full_filename[MAX_PATH_SIZE];
int fd;
int result;
int64_t offset;
int64_t file_size;
snprintf(full_filename, sizeof(full_filename), "%s/data/%s", \
SF_G_BASE_PATH_STR, g_tracker_sys_filenames[file_index]);
fd = open(full_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0)
{
logError("file: "__FILE__", line: %d, " \
"open file %s fail, " \
"errno: %d, error info: %s", \
__LINE__, full_filename, \
errno, STRERROR(errno));
return errno != 0 ? errno : EACCES;
}
SF_FCHOWN_TO_RUNBY_RETURN_ON_ERROR(fd, full_filename);
offset = 0;
file_size = 0;
while (1)
{
result = tracker_mem_get_sys_file_piece(pTrackerServer, \
file_index, fd, &offset, &file_size);
if (result != 0)
{
break;
}
if (offset >= file_size)
{
break;
}
}
close(fd);
return result;
}
static int tracker_mem_get_sys_files(TrackerServerInfo *pTrackerServer)
{
ConnectionInfo *conn;
int result;
int index;
fdfs_server_sock_reset(pTrackerServer);
if ((conn=tracker_connect_server(pTrackerServer, &result)) == NULL)
{
return result;
}
if ((result=tracker_get_sys_files_start(conn)) != 0)
{
tracker_close_connection_ex(conn, true);
return result;
}
for (index=0; index<TRACKER_SYS_FILE_COUNT; index++)
{
result = tracker_mem_get_one_sys_file(conn, index);
if (result != 0)
{
break;
}
}
result = tracker_get_sys_files_end(conn);
tracker_close_connection_ex(conn, result != 0);
return result;
}
static int tracker_mem_cmp_tracker_running_status(const void *p1, const void *p2)
{
TrackerRunningStatus *pStatus1;
TrackerRunningStatus *pStatus2;
int sub;
pStatus1 = (TrackerRunningStatus *)p1;
pStatus2 = (TrackerRunningStatus *)p2;
if (pStatus1->if_leader)
{
return 1;
}
else if (pStatus2->if_leader)
{
return -1;
}
sub = pStatus1->running_time - pStatus2->running_time;
if (sub != 0)
{
return sub;
}
return pStatus2->restart_interval - pStatus1->restart_interval;
}
static int find_my_ip_in_tracker_list()
{
const char *current_ip;
const char *previous_ip;
TrackerServerInfo *pServer;
char buff[256];
previous_ip = NULL;
while ((current_ip=get_next_local_ip(previous_ip)) != NULL)
{
pServer = fdfs_tracker_group_get_server(&g_tracker_servers,
current_ip, SF_G_INNER_PORT);
if (pServer != NULL)
{
if (pServer->count > 1)
{
ConnectionInfo *conn;
ConnectionInfo *end;
end = pServer->connections + pServer->count;
for (conn=pServer->connections; conn<end; conn++)
{
insert_into_local_host_ip(conn->ip_addr);
}
}
return 0;
}
previous_ip = current_ip;
}
logError("file: "__FILE__", line: %d, "
"my ip NOT in tracker server list. %s",
__LINE__, local_host_ip_addrs_to_string(buff, sizeof(buff)));
return ENOENT;
}
static int tracker_mem_first_add_tracker_servers(FDFSStorageJoinBody *pJoinBody)
{
TrackerServerInfo *pLocalTracker;
TrackerServerInfo *pLocalEnd;
TrackerServerInfo *servers;
int tracker_count;
int bytes;
tracker_count = pJoinBody->tracker_count;
bytes = sizeof(TrackerServerInfo) * tracker_count;
servers = (TrackerServerInfo *)malloc(bytes);
if (servers == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, bytes, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
memcpy(servers, pJoinBody->tracker_servers, bytes);
pLocalEnd = servers + tracker_count;
for (pLocalTracker=servers; pLocalTracker<pLocalEnd; \
pLocalTracker++)
{
fdfs_server_sock_reset(pLocalTracker);
}
g_tracker_servers.servers = servers;
g_tracker_servers.server_count = tracker_count;
return find_my_ip_in_tracker_list();
}
static int tracker_mem_copy_uniq_tracker_servers(
TrackerServerInfo *pSrcServer,
TrackerServerInfo *pDestServer)
{
ConnectionInfo *conn;
ConnectionInfo *end;
end = pSrcServer->connections + pSrcServer->count;
for (conn=pSrcServer->connections; conn<end; conn++)
{
if (!fdfs_server_contain1(pDestServer, conn))
{
if (pDestServer->count == FDFS_MULTI_IP_MAX_COUNT)
{
logError("file: "__FILE__", line: %d, "
"tracker IPs reach max count: %d",
__LINE__, FDFS_MULTI_IP_MAX_COUNT);
return ENOSPC;
}
pDestServer->connections[pDestServer->count++] = *conn;
}
}
return 0;
}
static int tracker_mem_check_add_tracker_servers(FDFSStorageJoinBody *pJoinBody)
{
TrackerServerInfo *pJoinTracker;
TrackerServerInfo *pJoinEnd;
TrackerServerInfo *pLocalTracker;
TrackerServerInfo *pLocalEnd;
TrackerServerInfo *pNewServer;
TrackerServerInfo *new_servers;
char ip_str_join[256];
char ip_str_before[256];
char ip_str_after[256];
int add_count;
int bytes;
add_count = 0;
pLocalEnd = g_tracker_servers.servers + g_tracker_servers.server_count;
pJoinEnd = pJoinBody->tracker_servers + pJoinBody->tracker_count;
for (pJoinTracker=pJoinBody->tracker_servers;
pJoinTracker<pJoinEnd; pJoinTracker++)
{
for (pLocalTracker=g_tracker_servers.servers;
pLocalTracker<pLocalEnd; pLocalTracker++)
{
if (fdfs_server_equal(pJoinTracker, pLocalTracker))
{
break;
}
if (fdfs_server_contain_ex(pJoinTracker, pLocalTracker))
{
fdfs_server_info_to_string(pJoinTracker,
ip_str_join, sizeof(ip_str_join));
fdfs_server_info_to_string(pLocalTracker,
ip_str_before, sizeof(ip_str_before));
logWarning("file: "__FILE__", line: %d, "
"tracker server ips not consistent, "
"join: %s, local: %s", __LINE__,
ip_str_join, ip_str_before);
if (pJoinTracker->count > pLocalTracker->count)
{
if (tracker_mem_copy_uniq_tracker_servers(pJoinTracker,
pLocalTracker) == 0)
{
fdfs_server_info_to_string(pLocalTracker,
ip_str_after, sizeof(ip_str_after));
logInfo("file: "__FILE__", line: %d, "
"merge tracker server ips, before: %s, "
"after: %s", __LINE__,
ip_str_before, ip_str_after);
}
}
break;
}
}
if (pLocalTracker == pLocalEnd)
{
add_count++;
}
}
if (add_count == 0)
{
return 0;
}
if (g_last_tracker_servers != NULL)
{
logError("file: "__FILE__", line: %d, " \
"last tracker servers does not freed, " \
"should try again!", __LINE__);
return EAGAIN;
}
if (g_tracker_servers.server_count + add_count > FDFS_MAX_TRACKERS)
{
logError("file: "__FILE__", line: %d, "
"too many tracker servers: %d",
__LINE__, g_tracker_servers.server_count + add_count);
return ENOSPC;
}
bytes = sizeof(TrackerServerInfo) * (g_tracker_servers.server_count
+ add_count);
new_servers = (TrackerServerInfo *)malloc(bytes);
if (new_servers == NULL)
{
logError("file: "__FILE__", line: %d, "
"malloc %d bytes fail, "
"errno: %d, error info: %s",
__LINE__, bytes, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
memcpy(new_servers, g_tracker_servers.servers, sizeof(TrackerServerInfo) *
g_tracker_servers.server_count);
pNewServer = new_servers + g_tracker_servers.server_count;
for (pJoinTracker=pJoinBody->tracker_servers;
pJoinTracker<pJoinEnd; pJoinTracker++)
{
for (pLocalTracker=new_servers;
pLocalTracker<pNewServer; pLocalTracker++)
{
if (fdfs_server_contain_ex(pJoinTracker, pLocalTracker))
{
break;
}
}
if (pLocalTracker == pNewServer)
{
memcpy(pNewServer, pJoinTracker,
sizeof(TrackerServerInfo));
fdfs_server_sock_reset(pNewServer);
pNewServer++;
}
}
add_count = (pNewServer - new_servers) - g_tracker_servers.server_count;
g_last_tracker_servers = g_tracker_servers.servers;
g_tracker_servers.servers = new_servers;
g_tracker_servers.server_count += add_count;
logInfo("file: "__FILE__", line: %d, "
"add %d tracker servers, total tracker servers: %d",
__LINE__, add_count, g_tracker_servers.server_count);
return find_my_ip_in_tracker_list();
}
static int tracker_mem_get_tracker_server(FDFSStorageJoinBody *pJoinBody, \
TrackerRunningStatus *pTrackerStatus)
{
TrackerServerInfo *pTrackerServer;
TrackerServerInfo *pTrackerEnd;
TrackerRunningStatus *pStatus;
TrackerRunningStatus trackerStatus[FDFS_MAX_TRACKERS];
int count;
int result;
int r;
int i;
memset(pTrackerStatus, 0, sizeof(TrackerRunningStatus));
pStatus = trackerStatus;
result = 0;
pTrackerEnd = pJoinBody->tracker_servers + pJoinBody->tracker_count;
for (pTrackerServer=pJoinBody->tracker_servers;
pTrackerServer<pTrackerEnd; pTrackerServer++)
{
if (fdfs_server_contain_local_service(pTrackerServer, SF_G_INNER_PORT))
{
continue;
}
pStatus->pTrackerServer = pTrackerServer;
r = fdfs_get_tracker_status(pTrackerServer, pStatus);
if (r == 0)
{
pStatus++;
}
else if (r != ENOENT)
{
result = r;
}
}
count = pStatus - trackerStatus;
if (count == 0)
{
return result == 0 ? ENOENT : result;
}
if (count > 1)
{
qsort(trackerStatus, count, sizeof(TrackerRunningStatus), \
tracker_mem_cmp_tracker_running_status);
}
for (i=0; i<count; i++)
{
logDebug("file: "__FILE__", line: %d, "
"%s:%u leader: %d, running time: %d, "
"restart interval: %d", __LINE__,
trackerStatus[i].pTrackerServer->connections[0].ip_addr,
trackerStatus[i].pTrackerServer->connections[0].port,
trackerStatus[i].if_leader,
trackerStatus[i].running_time,
trackerStatus[i].restart_interval);
}
//copy the last
memcpy(pTrackerStatus, trackerStatus + (count - 1), \
sizeof(TrackerRunningStatus));
return 0;
}
static int tracker_mem_get_sys_files_from_others(FDFSStorageJoinBody *pJoinBody,
TrackerRunningStatus *pRunningStatus)
{
int result;
TrackerRunningStatus trackerStatus;
TrackerServerInfo *pTrackerServer;
FDFSGroups newGroups;
FDFSGroups tempGroups;
if (pJoinBody->tracker_count == 0)
{
return 0;
}
result = tracker_mem_get_tracker_server(pJoinBody, &trackerStatus);
if (result != 0)
{
return result == ENOENT ? 0 : result;
}
if (pRunningStatus != NULL)
{
if (tracker_mem_cmp_tracker_running_status(pRunningStatus,
&trackerStatus) >= 0)
{
logDebug("file: "__FILE__", line: %d, "
"%s:%u running time: %d, restart interval: %d, "
"my running time: %d, restart interval: %d, "
"do not need sync system files", __LINE__,
trackerStatus.pTrackerServer->connections[0].ip_addr,
trackerStatus.pTrackerServer->connections[0].port,
trackerStatus.running_time,
trackerStatus.restart_interval,
pRunningStatus->running_time,
pRunningStatus->restart_interval);
return 0;
}
}
pTrackerServer = trackerStatus.pTrackerServer;
result = tracker_mem_get_sys_files(pTrackerServer);
if (result != 0)
{
return result;
}
logInfo("file: "__FILE__", line: %d, "
"sys files loaded from tracker server %s:%u",
__LINE__, pTrackerServer->connections[0].ip_addr,
pTrackerServer->connections[0].port);
memset(&newGroups, 0, sizeof(newGroups));
newGroups.store_lookup = g_groups.store_lookup;
newGroups.store_server = g_groups.store_server;
newGroups.download_server = g_groups.download_server;
newGroups.store_path = g_groups.store_path;
strcpy(newGroups.store_group, g_groups.store_group);
if ((result=tracker_mem_init_groups(&newGroups)) != 0)
{
tracker_mem_destroy_groups(&newGroups, false);
return result;
}
memcpy(&tempGroups, &g_groups, sizeof(FDFSGroups));
memcpy(&g_groups, &newGroups, sizeof(FDFSGroups));
usleep(100000);
tracker_mem_destroy_groups(&tempGroups, false);
tracker_write_status_to_file(NULL);
if (changelog_fd >= 0)
{
close(changelog_fd);
changelog_fd = -1;
}
return tracker_open_changlog_file();
}
int tracker_mem_add_group_and_storage(TrackerClientInfo *pClientInfo, \
const char *ip_addr, FDFSStorageJoinBody *pJoinBody, \
const bool bNeedSleep)
{
int result;
bool bStorageInserted;
bool bGroupInserted;
FDFSStorageDetail *pStorageServer;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppEnd;
FDFSStorageIdInfo *pStorageIdInfo;
const char *storage_id;
tracker_mem_file_lock();
if (need_get_sys_files)
{
if (g_tracker_last_status.last_check_time > 0 && g_sf_global_vars.
up_time - g_tracker_last_status.last_check_time >
2 * TRACKER_SYNC_STATUS_FILE_INTERVAL)
{ /* stop time exceeds 2 * interval */
TrackerRunningStatus runningStatus;
runningStatus.if_leader = false;
tracker_calc_running_times(&runningStatus);
result = tracker_mem_get_sys_files_from_others(\
pJoinBody, &runningStatus);
if (result != 0)
{
tracker_mem_file_unlock();
logError("file: "__FILE__", line: %d, "
"get sys files from other trackers fail, errno: %d",
__LINE__, result);
return EAGAIN;
}
get_sys_files_done = true;
}
need_get_sys_files = false;
}
if ((!get_sys_files_done) && (g_groups.count == 0))
{
if (g_groups.count == 0)
{
if ((result=tracker_mem_get_sys_files_from_others( \
pJoinBody, NULL)) != 0)
{
tracker_mem_file_unlock();
logError("file: "__FILE__", line: %d, "
"get sys files from other trackers fail, errno: %d",
__LINE__, result);
return EAGAIN;
}
get_sys_files_done = true;
}
}
if (g_tracker_servers.servers == NULL)
{
result = tracker_mem_first_add_tracker_servers(pJoinBody);
if (result != 0)
{
tracker_mem_file_unlock();
return result;
}
}
else
{
result = tracker_mem_check_add_tracker_servers(pJoinBody);
if (result != 0)
{
tracker_mem_file_unlock();
return result;
}
}
tracker_mem_file_unlock();
if ((result=tracker_mem_add_group_ex(&g_groups, pClientInfo, \
pJoinBody->group_name, bNeedSleep, &bGroupInserted)) != 0)
{
return result;
}
if (bGroupInserted)
{
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
if (g_use_storage_id)
{
pStorageIdInfo = fdfs_get_storage_id_by_ip(
pClientInfo->pGroup->group_name, ip_addr);
if (pStorageIdInfo == NULL)
{
logError("file: "__FILE__", line: %d, " \
"get storage id info fail, group_name: %s, " \
"storage ip: %s", __LINE__, \
pClientInfo->pGroup->group_name, ip_addr);
return ENOENT;
}
storage_id = pStorageIdInfo->id;
}
else
{
pStorageIdInfo = NULL;
storage_id = ip_addr;
// 当IP地址为IPv6时其storage_id值为IP地址的short code
if(is_ipv6_addr(ip_addr)){
storage_id = fdfs_ip_to_shortcode(ip_addr, FDFS_DEFAULT_STORAGE_ID_LEN);
}
}
if (pClientInfo->pGroup->storage_port == 0)
{
pClientInfo->pGroup->storage_port = pJoinBody->storage_port;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
if (pClientInfo->pGroup->storage_port != \
pJoinBody->storage_port)
{
ppEnd = pClientInfo->pGroup->all_servers + \
pClientInfo->pGroup->count;
for (ppServer=pClientInfo->pGroup->all_servers; \
ppServer<ppEnd; ppServer++)
{
if (strcmp((*ppServer)->id, storage_id) == 0)
{
(*ppServer)->storage_port = \
pJoinBody->storage_port;
break;
}
}
for (ppServer=pClientInfo->pGroup->all_servers; \
ppServer<ppEnd; ppServer++)
{
if ((*ppServer)->storage_port != \
pJoinBody->storage_port)
{
break;
}
}
if (ppServer == ppEnd) //all servers are same, adjust
{
pClientInfo->pGroup->storage_port = \
pJoinBody->storage_port;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, port %d is not same " \
"in the group \"%s\", group port is %d", \
__LINE__, ip_addr, pJoinBody->storage_port, \
pJoinBody->group_name, \
pClientInfo->pGroup->storage_port);
return EINVAL;
}
}
}
if (pClientInfo->pGroup->storage_http_port == 0)
{
pClientInfo->pGroup->storage_http_port = \
pJoinBody->storage_http_port;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
if (pClientInfo->pGroup->storage_http_port != \
pJoinBody->storage_http_port)
{
ppEnd = pClientInfo->pGroup->all_servers + \
pClientInfo->pGroup->count;
for (ppServer=pClientInfo->pGroup->all_servers; \
ppServer<ppEnd; ppServer++)
{
if (strcmp((*ppServer)->id, storage_id) == 0)
{
(*ppServer)->storage_http_port = \
pJoinBody->storage_http_port;
break;
}
}
for (ppServer=pClientInfo->pGroup->all_servers; \
ppServer<ppEnd; ppServer++)
{
if ((*ppServer)->storage_http_port != \
pJoinBody->storage_http_port)
{
break;
}
}
if (ppServer == ppEnd) //all servers are same, adjust
{
pClientInfo->pGroup->storage_http_port = \
pJoinBody->storage_http_port;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, http port %d is not same " \
"in the group \"%s\", group http port is %d", \
__LINE__, ip_addr, \
pJoinBody->storage_http_port, \
pJoinBody->group_name, \
pClientInfo->pGroup->storage_http_port);
#ifdef WITH_HTTPD
return EINVAL;
#endif
}
}
}
if ((result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
pStorageServer = tracker_mem_get_storage(pClientInfo->pGroup, storage_id);
if (pthread_mutex_unlock(&mem_thread_lock) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail", \
__LINE__);
}
if (pStorageServer == NULL)
{
if (!pJoinBody->init_flag)
{
if (pJoinBody->status < 0 || \
pJoinBody->status == FDFS_STORAGE_STATUS_DELETED || \
pJoinBody->status == FDFS_STORAGE_STATUS_IP_CHANGED || \
pJoinBody->status == FDFS_STORAGE_STATUS_NONE)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s:%u, invalid storage " \
"status %d, in the group \"%s\"", \
__LINE__, ip_addr, \
pJoinBody->storage_port, \
pJoinBody->status, \
pJoinBody->group_name);
return EFAULT;
}
}
}
if ((result=tracker_mem_add_storage(pClientInfo, storage_id, ip_addr,
bNeedSleep, true, &bStorageInserted)) != 0)
{
return result;
}
pStorageServer = pClientInfo->pStorage;
pStorageServer->store_path_count = pJoinBody->store_path_count;
pStorageServer->subdir_count_per_path = pJoinBody->subdir_count_per_path;
pStorageServer->upload_priority = pJoinBody->upload_priority;
pStorageServer->join_time = pJoinBody->join_time;
pStorageServer->up_time = pJoinBody->up_time;
snprintf(pStorageServer->version, sizeof(pStorageServer->version), \
"%s", pJoinBody->version);
snprintf(pStorageServer->domain_name, \
sizeof(pStorageServer->domain_name), \
"%s", pJoinBody->domain_name);
pStorageServer->storage_port = pJoinBody->storage_port;
pStorageServer->storage_http_port = pJoinBody->storage_http_port;
if (pClientInfo->pGroup->store_path_count == 0)
{
pClientInfo->pGroup->store_path_count = \
pJoinBody->store_path_count;
if ((result=tracker_malloc_group_path_mbs( \
pClientInfo->pGroup)) != 0)
{
return result;
}
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
if (pClientInfo->pGroup->store_path_count !=
pJoinBody->store_path_count)
{
ppEnd = pClientInfo->pGroup->all_servers +
pClientInfo->pGroup->count;
for (ppServer=pClientInfo->pGroup->all_servers;
ppServer<ppEnd; ppServer++)
{
if ((*ppServer)->status == FDFS_STORAGE_STATUS_DELETED)
{
continue;
}
if ((*ppServer)->store_path_count !=
pJoinBody->store_path_count)
{
break;
}
}
if (ppServer == ppEnd) //all servers are same, adjust
{
if ((result=tracker_realloc_group_path_mbs(
pClientInfo->pGroup, pJoinBody->
store_path_count)) != 0)
{
return result;
}
if ((result=tracker_save_groups()) != 0)
{
return result;
}
logDebug("file: "__FILE__", line: %d, " \
"all storage server's store_path_count " \
"are same, adjust to %d", \
__LINE__, pJoinBody->store_path_count);
}
else if (pJoinBody->store_path_count < \
pClientInfo->pGroup->store_path_count)
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, store_path_count %d less " \
"than that of the group \"%s\", " \
"the group store_path_count is %d", \
__LINE__, ip_addr, \
pJoinBody->store_path_count, \
pJoinBody->group_name, \
pClientInfo->pGroup->store_path_count);
return EINVAL;
}
}
}
if (pClientInfo->pGroup->subdir_count_per_path == 0)
{
pClientInfo->pGroup->subdir_count_per_path = \
pJoinBody->subdir_count_per_path;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
if (pClientInfo->pGroup->subdir_count_per_path != \
pJoinBody->subdir_count_per_path)
{
ppEnd = pClientInfo->pGroup->all_servers + \
pClientInfo->pGroup->count;
for (ppServer=pClientInfo->pGroup->all_servers; \
ppServer<ppEnd; ppServer++)
{
if ((*ppServer)->subdir_count_per_path != \
pJoinBody->subdir_count_per_path)
{
break;
}
}
if (ppServer == ppEnd) //all servers are same, adjust
{
pClientInfo->pGroup->subdir_count_per_path = \
pJoinBody->subdir_count_per_path;
if ((result=tracker_save_groups()) != 0)
{
return result;
}
}
else
{
logError("file: "__FILE__", line: %d, " \
"client ip: %s, subdir_count_per_path %d is " \
"not same in the group \"%s\", " \
"group subdir_count_per_path is %d", \
__LINE__, ip_addr, \
pJoinBody->subdir_count_per_path, \
pJoinBody->group_name,\
pClientInfo->pGroup->subdir_count_per_path);
return EINVAL;
}
}
}
if (bStorageInserted)
{
if ((!pJoinBody->init_flag) && pJoinBody->status > 0)
{
if (pJoinBody->status == FDFS_STORAGE_STATUS_ACTIVE)
{
pStorageServer->status = FDFS_STORAGE_STATUS_ONLINE;
}
else
{
pStorageServer->status = pJoinBody->status;
}
}
if ((result=tracker_save_sys_files()) != 0)
{
return result;
}
}
if (pStorageServer->status == FDFS_STORAGE_STATUS_OFFLINE || \
pStorageServer->status == FDFS_STORAGE_STATUS_RECOVERY)
{
pStorageServer->status = FDFS_STORAGE_STATUS_ONLINE;
}
else if (pStorageServer->status == FDFS_STORAGE_STATUS_INIT)
{
pStorageServer->changelog_offset = g_changelog_fsize;
}
logDebug("file: "__FILE__", line: %d, " \
"storage server %s::%s join in, remain changelog bytes: " \
"%"PRId64, __LINE__, \
pClientInfo->pGroup->group_name, ip_addr, \
g_changelog_fsize - pStorageServer->changelog_offset);
return 0;
}
int tracker_mem_sync_storages(FDFSGroupInfo *pGroup, \
FDFSStorageBrief *briefServers, const int server_count)
{
int result;
FDFSStorageBrief *pServer;
FDFSStorageBrief *pEnd;
FDFSStorageDetail target_storage;
FDFSStorageDetail *pTargetStorage;
FDFSStorageDetail **ppFound;
if ((result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
result = 0;
do
{
memset(&target_storage, 0, sizeof(target_storage));
pEnd = briefServers + server_count;
for (pServer=briefServers; pServer<pEnd; pServer++)
{
pServer->id[FDFS_STORAGE_ID_MAX_SIZE - 1] = '\0';
pServer->ip_addr[IP_ADDRESS_SIZE - 1] = '\0';
if (pServer->status == FDFS_STORAGE_STATUS_NONE)
{
continue;
}
memcpy(target_storage.id, pServer->id,
FDFS_STORAGE_ID_MAX_SIZE);
pTargetStorage = &target_storage;
if ((ppFound=(FDFSStorageDetail **)bsearch(
&pTargetStorage,
pGroup->sorted_servers,
pGroup->count,
sizeof(FDFSStorageDetail *),
tracker_mem_cmp_by_storage_id)) != NULL)
{
if ((*ppFound)->status == pServer->status \
|| (*ppFound)->status == \
FDFS_STORAGE_STATUS_INIT \
|| (*ppFound)->status == \
FDFS_STORAGE_STATUS_ONLINE \
|| (*ppFound)->status == \
FDFS_STORAGE_STATUS_ACTIVE
|| (*ppFound)->status == \
FDFS_STORAGE_STATUS_RECOVERY)
{
continue;
}
logWarning("file: "__FILE__", line: %d, "
"storage server: %s:%u, dest status: %d, "
"my status: %d, should change my status!",
__LINE__, FDFS_CURRENT_IP_ADDR(*ppFound),
(*ppFound)->storage_port,
pServer->status, (*ppFound)->status);
if (pServer->status == \
FDFS_STORAGE_STATUS_DELETED
|| pServer->status == \
FDFS_STORAGE_STATUS_IP_CHANGED)
{
(*ppFound)->status = pServer->status;
pGroup->chg_count++;
continue;
}
if (pServer->status > (*ppFound)->status)
{
(*ppFound)->status = pServer->status;
pGroup->chg_count++;
}
}
else if (pServer->status == FDFS_STORAGE_STATUS_DELETED
|| pServer->status == FDFS_STORAGE_STATUS_IP_CHANGED)
{
//ignore deleted storage server
}
else if (pServer->status == FDFS_STORAGE_STATUS_ACTIVE
|| pServer->status == FDFS_STORAGE_STATUS_ONLINE)
{
//ignore online or active storage server
}
else
{
FDFSStorageDetail *pStorageServer;
bool bInserted;
result = _tracker_mem_add_storage(pGroup,
&pStorageServer, pServer->id,
pServer->ip_addr, true, false,
&bInserted);
if (result == 0 && bInserted)
{
pStorageServer->status = pServer->status;
}
}
}
} while (0);
if (pthread_mutex_unlock(&mem_thread_lock) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail", \
__LINE__);
}
return result;
}
static void tracker_mem_find_store_server(FDFSGroupInfo *pGroup)
{
if (pGroup->active_count == 0)
{
pGroup->pStoreServer = NULL;
return;
}
if (g_groups.store_server == FDFS_STORE_SERVER_FIRST_BY_PRI)
{
FDFSStorageDetail **ppEnd;
FDFSStorageDetail **ppServer;
FDFSStorageDetail *pMinPriServer;
pMinPriServer = *(pGroup->active_servers);
ppEnd = pGroup->active_servers + pGroup->active_count;
for (ppServer=pGroup->active_servers+1; ppServer<ppEnd; \
ppServer++)
{
if ((*ppServer)->upload_priority < \
pMinPriServer->upload_priority)
{
pMinPriServer = *ppServer;
}
}
pGroup->pStoreServer = pMinPriServer;
}
else
{
pGroup->pStoreServer = *(pGroup->active_servers);
}
}
static int _storage_get_trunk_binlog_size(
ConnectionInfo *pStorageServer, int64_t *file_size)
{
char out_buff[sizeof(TrackerHeader)];
char in_buff[8];
TrackerHeader *pHeader;
char *pInBuff;
int64_t in_bytes;
int result;
pHeader = (TrackerHeader *)out_buff;
memset(out_buff, 0, sizeof(out_buff));
pHeader->cmd = STORAGE_PROTO_CMD_TRUNK_GET_BINLOG_SIZE;
if ((result=tcpsenddata_nb(pStorageServer->sock, out_buff, \
sizeof(out_buff), SF_G_NETWORK_TIMEOUT)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"storage server %s:%u, send data fail, " \
"errno: %d, error info: %s.", \
__LINE__, pStorageServer->ip_addr, \
pStorageServer->port, \
result, STRERROR(result));
return result;
}
pInBuff = in_buff;
if ((result=fdfs_recv_response(pStorageServer, \
&pInBuff, sizeof(in_buff), &in_bytes)) != 0)
{
logError("file: "__FILE__", line: %d, "
"fdfs_recv_response fail, result: %d",
__LINE__, result);
return result;
}
if (in_bytes != sizeof(in_buff))
{
logError("file: "__FILE__", line: %d, " \
"storage server %s:%u, recv body length: " \
"%"PRId64" != %d", \
__LINE__, pStorageServer->ip_addr, \
pStorageServer->port, in_bytes, (int)sizeof(in_buff));
return EINVAL;
}
*file_size = buff2long(in_buff);
return 0;
}
static int tracker_mem_get_trunk_binlog_size(
const char *storage_ip, const int port, int64_t *file_size)
{
ConnectionInfo storage_server;
ConnectionInfo *conn;
int result;
*file_size = 0;
strcpy(storage_server.ip_addr, storage_ip);
storage_server.port = port;
storage_server.sock = -1;
if ((conn=tracker_make_connection(&storage_server, &result)) == NULL)
{
return result;
}
result = _storage_get_trunk_binlog_size(conn, file_size);
tracker_close_connection_ex(conn, result != 0);
logDebug("file: "__FILE__", line: %d, " \
"storage %s:%u, trunk binlog file size: %"PRId64, \
__LINE__, storage_server.ip_addr, storage_server.port, \
*file_size);
return result;
}
static int tracker_write_to_trunk_change_log(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pLastTrunkServer)
{
char full_filename[MAX_PATH_SIZE];
char buff[256];
int fd;
int len;
struct tm tm;
time_t current_time;
FDFSStorageDetail *pLastTrunk;
tracker_mem_file_lock();
snprintf(full_filename, sizeof(full_filename), "%s/logs/%s", \
SF_G_BASE_PATH_STR, TRUNK_SERVER_CHANGELOG_FILENAME);
if ((fd=open(full_filename, O_WRONLY | O_CREAT | O_APPEND, 0644)) < 0)
{
tracker_mem_file_unlock();
logError("file: "__FILE__", line: %d, " \
"open \"%s\" fail, errno: %d, error info: %s", \
__LINE__, full_filename, errno, STRERROR(errno));
return errno != 0 ? errno : ENOENT;
}
current_time = g_current_time;
localtime_r(&current_time, &tm);
len = sprintf(buff, "[%04d-%02d-%02d %02d:%02d:%02d] %s ", \
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, \
tm.tm_hour, tm.tm_min, tm.tm_sec, pGroup->group_name);
pLastTrunk = pLastTrunkServer;
if (pLastTrunk == NULL && *(pGroup->last_trunk_server_id) != '\0')
{
pLastTrunk = tracker_mem_get_storage(pGroup, \
pGroup->last_trunk_server_id);
}
if (g_use_storage_id)
{
if (pLastTrunk == NULL)
{
len += sprintf(buff + len, " %s/%s => ",
*(pGroup->last_trunk_server_id) == '\0' ?
"-" : pGroup->last_trunk_server_id, "-");
}
else
{
len += sprintf(buff + len, " %s/%s => ",
pLastTrunk->id, FDFS_CURRENT_IP_ADDR(pLastTrunk));
}
if (pGroup->pTrunkServer == NULL)
{
len += sprintf(buff + len, " %s/%s\n", "-", "-");
}
else
{
len += sprintf(buff + len, " %s/%s\n",
pGroup->pTrunkServer->id,
FDFS_CURRENT_IP_ADDR(pGroup->pTrunkServer));
}
}
else
{
if (pLastTrunk == NULL)
{
len += sprintf(buff + len, " %s => ",
*(pGroup->last_trunk_server_id) == '\0' ?
"-" : pGroup->last_trunk_server_id);
}
else
{
len += sprintf(buff + len, " %s => ",
FDFS_CURRENT_IP_ADDR(pLastTrunk));
}
if (pGroup->pTrunkServer == NULL)
{
len += sprintf(buff + len, " %s\n", "-");
}
else
{
len += sprintf(buff + len, " %s\n",
FDFS_CURRENT_IP_ADDR(pGroup->pTrunkServer));
}
}
if (fc_safe_write(fd, buff, len) != len)
{
logError("file: "__FILE__", line: %d, " \
"write to file \"%s\" fail, " \
"errno: %d, error info: %s", \
__LINE__, full_filename, \
errno, STRERROR(errno));
}
close(fd);
tracker_mem_file_unlock();
return 0;
}
static int tracker_set_trunk_server_and_log(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pNewTrunkServer)
{
FDFSStorageDetail *pLastTrunkServer;
pLastTrunkServer = pGroup->pTrunkServer;
pGroup->pTrunkServer = pNewTrunkServer;
if (pNewTrunkServer == NULL || strcmp(pNewTrunkServer->id, \
pGroup->last_trunk_server_id) != 0)
{
int result;
result = tracker_write_to_trunk_change_log(pGroup, \
pLastTrunkServer);
if (pNewTrunkServer == NULL)
{
*(pGroup->last_trunk_server_id) = '\0';
}
else
{
strcpy(pGroup->last_trunk_server_id, \
pNewTrunkServer->id);
}
return result;
}
return 0;
}
static int tracker_mem_do_set_trunk_server(FDFSGroupInfo *pGroup,
FDFSStorageDetail *pTrunkServer, const bool save)
{
int result;
if (*(pGroup->last_trunk_server_id) != '\0' &&
strcmp(pTrunkServer->id, pGroup->last_trunk_server_id) != 0)
{
if ((result=fdfs_deal_no_body_cmd_ex(
FDFS_CURRENT_IP_ADDR(pTrunkServer),
pGroup->storage_port,
STORAGE_PROTO_CMD_TRUNK_DELETE_BINLOG_MARKS)) != 0)
{
logError("file: "__FILE__", line: %d, "
"fdfs_deal_no_body_cmd_ex fail, result: %d",
__LINE__, result);
return result;
}
}
tracker_set_trunk_server_and_log(pGroup, pTrunkServer);
pGroup->trunk_chg_count++;
g_trunk_server_chg_count++;
logInfo("file: "__FILE__", line: %d, "
"group: %s, trunk server set to %s(%s:%u)", __LINE__,
pGroup->group_name, pGroup->pTrunkServer->id,
FDFS_CURRENT_IP_ADDR(pGroup->pTrunkServer),
pGroup->storage_port);
if (save)
{
return tracker_save_groups();
}
return 0;
}
static int tracker_mem_find_trunk_server(FDFSGroupInfo *pGroup,
const bool save)
{
FDFSStorageDetail *pStoreServer;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
int result;
int64_t file_size;
int64_t max_file_size;
pStoreServer = pGroup->pStoreServer;
if (pStoreServer == NULL)
{
return ENOENT;
}
result = tracker_mem_get_trunk_binlog_size(
FDFS_CURRENT_IP_ADDR(pStoreServer),
pGroup->storage_port, &max_file_size);
if (result != 0)
{
return result;
}
ppServerEnd = pGroup->active_servers + pGroup->active_count;
for (ppServer=pGroup->active_servers; ppServer<ppServerEnd; ppServer++)
{
if (*ppServer == pStoreServer)
{
continue;
}
result = tracker_mem_get_trunk_binlog_size(
FDFS_CURRENT_IP_ADDR(*ppServer),
pGroup->storage_port, &file_size);
if (result != 0)
{
continue;
}
if (file_size > max_file_size)
{
pStoreServer = *ppServer;
}
}
return tracker_mem_do_set_trunk_server(pGroup, pStoreServer, save);
}
const FDFSStorageDetail *tracker_mem_set_trunk_server( \
FDFSGroupInfo *pGroup, const char *pStroageId, int *result)
{
FDFSStorageDetail *pServer;
FDFSStorageDetail *pTrunkServer;
if (!(g_if_leader_self && g_if_use_trunk_file))
{
*result = EOPNOTSUPP;
return NULL;
}
pTrunkServer = pGroup->pTrunkServer;
if (pStroageId == NULL || *pStroageId == '\0')
{
if (pTrunkServer != NULL && pTrunkServer-> \
status == FDFS_STORAGE_STATUS_ACTIVE)
{
*result = 0;
return pTrunkServer;
}
*result = tracker_mem_find_trunk_server(pGroup, true);
if (*result != 0)
{
return NULL;
}
return pGroup->pTrunkServer;
}
if (pTrunkServer != NULL && pTrunkServer->status == \
FDFS_STORAGE_STATUS_ACTIVE)
{
if (strcmp(pStroageId, pTrunkServer->id) == 0)
{
*result = EALREADY;
}
else
{
*result = EEXIST;
}
return pTrunkServer;
}
pServer = tracker_mem_get_storage(pGroup, pStroageId);
if (pServer == NULL)
{
*result = ENOENT;
return NULL;
}
if (pServer->status != FDFS_STORAGE_STATUS_ACTIVE)
{
*result = ENONET;
return NULL;
}
*result = tracker_mem_do_set_trunk_server(pGroup, \
pServer, true);
return *result == 0 ? pGroup->pTrunkServer : NULL;
}
int tracker_mem_deactive_store_server(FDFSGroupInfo *pGroup,
FDFSStorageDetail *pTargetServer)
{
int result;
FDFSStorageDetail **ppStorageServer;
FDFSStorageDetail **ppEnd;
FDFSStorageDetail **ppServer;
if ((result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
ppStorageServer = (FDFSStorageDetail **)bsearch( \
&pTargetServer, \
pGroup->active_servers, \
pGroup->active_count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer != NULL)
{
(*ppStorageServer)->chg_count = 0;
(*ppStorageServer)->trunk_chg_count = 0;
ppEnd = pGroup->active_servers + pGroup->active_count - 1;
for (ppServer=ppStorageServer; ppServer<ppEnd; ppServer++)
{
*ppServer = *(ppServer+1);
}
pGroup->active_count--;
pGroup->chg_count++;
#ifdef WITH_HTTPD
if (g_http_check_interval <= 0)
{
pGroup->http_server_count = pGroup->active_count;
}
#endif
}
tracker_mem_find_store_server(pGroup);
if ((result=pthread_mutex_unlock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
int tracker_mem_active_store_server(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pTargetServer)
{
int result;
FDFSStorageDetail **ppStorageServer;
if ((pTargetServer->status == FDFS_STORAGE_STATUS_WAIT_SYNC) || \
(pTargetServer->status == FDFS_STORAGE_STATUS_SYNCING) || \
(pTargetServer->status == FDFS_STORAGE_STATUS_IP_CHANGED) || \
(pTargetServer->status == FDFS_STORAGE_STATUS_INIT))
{
return 0;
}
/*
if (pTargetServer->status == FDFS_STORAGE_STATUS_DELETED)
{
logError("file: "__FILE__", line: %d, " \
"storage ip: %s already deleted, you can " \
"restart the tracker servers to reset.", \
__LINE__, pTargetServer->ip_addr);
return EAGAIN;
}
*/
pTargetServer->status = FDFS_STORAGE_STATUS_ACTIVE;
ppStorageServer = (FDFSStorageDetail **)bsearch(&pTargetServer, \
pGroup->active_servers, \
pGroup->active_count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer != NULL)
{
return 0;
}
if ((result=pthread_mutex_lock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
ppStorageServer = (FDFSStorageDetail **)bsearch(&pTargetServer, \
pGroup->active_servers, \
pGroup->active_count, \
sizeof(FDFSStorageDetail *), \
tracker_mem_cmp_by_storage_id);
if (ppStorageServer == NULL)
{
tracker_mem_insert_into_sorted_servers( \
pTargetServer, pGroup->active_servers, \
pGroup->active_count);
pGroup->active_count++;
pGroup->chg_count++;
#ifdef WITH_HTTPD
if (g_http_check_interval <= 0)
{
pGroup->http_server_count = pGroup->active_count;
}
#endif
if (g_use_storage_id)
{
logDebug("file: "__FILE__", line: %d, "
"storage server %s::%s(%s) now active",
__LINE__, pGroup->group_name,
pTargetServer->id, FDFS_CURRENT_IP_ADDR(pTargetServer));
}
else
{
logDebug("file: "__FILE__", line: %d, "
"storage server %s::%s now active",
__LINE__, pGroup->group_name,
FDFS_CURRENT_IP_ADDR(pTargetServer));
}
}
tracker_mem_find_store_server(pGroup);
if (g_if_leader_self && g_if_use_trunk_file && \
pGroup->pTrunkServer == NULL)
{
tracker_mem_find_trunk_server(pGroup, true);
}
if ((result=pthread_mutex_unlock(&mem_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
void tracker_mem_find_trunk_servers()
{
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
if (!(g_if_leader_self && g_if_use_trunk_file))
{
return;
}
pthread_mutex_lock(&mem_thread_lock);
ppGroupEnd = g_groups.groups + g_groups.count;
for (ppGroup=g_groups.groups; ppGroup<ppGroupEnd; ppGroup++)
{
if ((*ppGroup)->pTrunkServer == NULL)
{
tracker_mem_find_trunk_server(*ppGroup, true);
}
}
g_trunk_server_chg_count++;
pthread_mutex_unlock(&mem_thread_lock);
}
int tracker_mem_offline_store_server(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pStorage)
{
pStorage->up_time = 0;
if ((pStorage->status == FDFS_STORAGE_STATUS_WAIT_SYNC) || \
(pStorage->status == FDFS_STORAGE_STATUS_SYNCING) || \
(pStorage->status == FDFS_STORAGE_STATUS_INIT) || \
(pStorage->status == FDFS_STORAGE_STATUS_DELETED) || \
(pStorage->status == FDFS_STORAGE_STATUS_IP_CHANGED) || \
(pStorage->status == FDFS_STORAGE_STATUS_RECOVERY))
{
return 0;
}
if (g_use_storage_id)
{
logDebug("file: "__FILE__", line: %d, "
"storage server %s::%s (%s) offline",
__LINE__, pGroup->group_name,
pStorage->id, FDFS_CURRENT_IP_ADDR(pStorage));
}
else
{
logDebug("file: "__FILE__", line: %d, "
"storage server %s::%s offline",
__LINE__, pGroup->group_name,
FDFS_CURRENT_IP_ADDR(pStorage));
}
pStorage->status = FDFS_STORAGE_STATUS_OFFLINE;
return tracker_mem_deactive_store_server(pGroup, pStorage);
}
FDFSStorageDetail *tracker_get_writable_storage(FDFSGroupInfo *pStoreGroup)
{
int write_server_index;
if (g_groups.store_server == FDFS_STORE_SERVER_ROUND_ROBIN)
{
write_server_index = pStoreGroup->current_write_server++;
if (pStoreGroup->current_write_server >= \
pStoreGroup->active_count)
{
pStoreGroup->current_write_server = 0;
}
if (write_server_index >= pStoreGroup->active_count)
{
write_server_index = 0;
}
return *(pStoreGroup->active_servers + write_server_index);
}
else //use the first server
{
return pStoreGroup->pStoreServer;
}
}
int tracker_mem_get_storage_by_filename(const byte cmd,FDFS_DOWNLOAD_TYPE_PARAM\
const char *group_name, const char *filename, const int filename_len, \
FDFSGroupInfo **ppGroup, FDFSStorageDetail **ppStoreServers, \
int *server_count)
{
char szIpAddr[IP_ADDRESS_SIZE];
char storage_id[FDFS_STORAGE_ID_MAX_SIZE];
FDFSStorageDetail *pStoreSrcServer;
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
FDFSStorageDetail *pGroupStoreServer;
int file_timestamp;
int storage_ip;
int read_server_index;
int cmp_res;
struct in_addr ip_addr;
time_t current_time;
bool bNormalFile;
*server_count = 0;
*ppGroup = tracker_mem_get_group(group_name);
if (*ppGroup == NULL)
{
logError("file: "__FILE__", line: %d, " \
"invalid group_name: %s", \
__LINE__, group_name);
return ENOENT;
}
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
if ((*ppGroup)->active_count == 0)
{
return ENOENT;
}
}
else
{
if ((*ppGroup)->http_server_count == 0)
{
return ENOENT;
}
}
#else
if ((*ppGroup)->active_count == 0)
{
return ENOENT;
}
#endif
pGroupStoreServer = (*ppGroup)->pStoreServer;
if (pGroupStoreServer == NULL)
{
return ENOENT;
}
//file generated by version < v1.12
if (filename_len < 32 + (FDFS_FILE_EXT_NAME_MAX_LEN + 1))
{
storage_ip = INADDR_NONE;
*storage_id = '\0';
file_timestamp = 0;
bNormalFile = true;
}
else //file generated by version >= v1.12
{
int64_t file_size;
char name_buff[64];
int decoded_len;
base64_decode_auto(&g_base64_context, (char *)filename + \
FDFS_LOGIC_FILE_PATH_LEN, FDFS_FILENAME_BASE64_LENGTH, \
name_buff, &decoded_len);
storage_ip = ntohl(buff2int(name_buff));
file_timestamp = buff2int(name_buff+sizeof(int));
file_size = buff2long(name_buff + sizeof (int) * 2);
if (fdfs_get_server_id_type(storage_ip) == FDFS_ID_TYPE_SERVER_ID)
{
sprintf(storage_id, "%d", storage_ip);
}
else
{
*storage_id = '\0';
}
bNormalFile = !(IS_SLAVE_FILE(filename_len, file_size) || \
IS_APPENDER_FILE(file_size));
}
/*
//logInfo("cmd=%d, bNormalFile=%d, storage_ip=%d, storage_id=%s, "
"file_timestamp=%d\n", cmd, bNormalFile, storage_ip,
storage_id, file_timestamp);
*/
memset(szIpAddr, 0, sizeof(szIpAddr));
if (cmd == TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE)
{
if (g_groups.download_server == \
FDFS_DOWNLOAD_SERVER_SOURCE_FIRST)
{
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_storage_by_id(\
*ppGroup, storage_id);
}
else
{
memset(&ip_addr, 0, sizeof(ip_addr));
ip_addr.s_addr = storage_ip;
pStoreSrcServer=tracker_mem_get_active_storage_by_ip( \
*ppGroup, inet_ntop(AF_INET, &ip_addr, \
szIpAddr, sizeof(szIpAddr)));
}
}
else
{
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_http_server_by_id( \
*ppGroup, storage_id);
}
else
{
memset(&ip_addr, 0, sizeof(ip_addr));
ip_addr.s_addr = storage_ip;
pStoreSrcServer=tracker_mem_get_active_http_server_by_ip( \
*ppGroup, inet_ntop(AF_INET, &ip_addr, \
szIpAddr, sizeof(szIpAddr)));
}
}
#else
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_storage_by_id(\
*ppGroup, storage_id);
}
else
{
memset(&ip_addr, 0, sizeof(ip_addr));
ip_addr.s_addr = storage_ip;
pStoreSrcServer=tracker_mem_get_active_storage_by_ip(\
*ppGroup, inet_ntop(AF_INET, &ip_addr, \
szIpAddr, sizeof(szIpAddr)));
}
#endif
if (pStoreSrcServer != NULL)
{
ppStoreServers[(*server_count)++] = \
pStoreSrcServer;
return 0;
}
}
//round robin
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
read_server_index = (*ppGroup)->current_read_server;
if (read_server_index >= (*ppGroup)->active_count)
{
read_server_index = 0;
}
ppStoreServers[(*server_count)++]=*((*ppGroup)->active_servers \
+ read_server_index);
}
else
{
read_server_index = (*ppGroup)->current_http_server;
if (read_server_index >= (*ppGroup)->http_server_count)
{
read_server_index = 0;
}
ppStoreServers[(*server_count)++]=*((*ppGroup)->http_servers \
+ read_server_index);
}
#else
read_server_index = (*ppGroup)->current_read_server;
if (read_server_index >= (*ppGroup)->active_count)
{
read_server_index = 0;
}
ppStoreServers[(*server_count)++]=*((*ppGroup)->active_servers \
+ read_server_index);
#endif
/*
//logInfo("filename=%s, storage server ip=%s, " \
"file_timestamp=%d, last_synced_timestamp=%d\n",
filename, ppStoreServers[0]->ip_addr, file_timestamp, \
(int)ppStoreServers[0]->stat.last_synced_timestamp);
*/
do
{
if (bNormalFile)
{
current_time = g_current_time;
if ((file_timestamp < current_time - \
g_storage_sync_file_max_delay) || \
(ppStoreServers[0]->stat.last_synced_timestamp > \
file_timestamp) || \
(ppStoreServers[0]->stat.last_synced_timestamp + 1 >= \
file_timestamp && current_time - file_timestamp > \
g_storage_sync_file_max_time)\
|| (storage_ip == INADDR_NONE \
&& g_groups.store_server == FDFS_STORE_SERVER_ROUND_ROBIN))
{
break;
}
if (storage_ip == INADDR_NONE)
{
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
ppStoreServers[0] = pGroupStoreServer;
break;
}
else
{
pStoreSrcServer=tracker_mem_get_active_storage_by_id(
*ppGroup, pGroupStoreServer->id);
if (pStoreSrcServer != NULL)
{
ppStoreServers[0] = pStoreSrcServer;
break;
}
}
#else
ppStoreServers[0] = pGroupStoreServer;
break;
#endif
}
}
memset(&ip_addr, 0, sizeof(ip_addr));
if (*storage_id != '\0')
{
cmp_res = strcmp(storage_id, ppStoreServers[0]->id);
}
else
{
ip_addr.s_addr = storage_ip;
inet_ntop(AF_INET, &ip_addr, szIpAddr, sizeof(szIpAddr));
cmp_res = strcmp(szIpAddr, FDFS_CURRENT_IP_ADDR(ppStoreServers[0]));
}
if (cmp_res == 0)
{
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
break;
}
else //http
{
if (*storage_id != '\0')
{
if (tracker_mem_get_active_http_server_by_id(
*ppGroup, storage_id) != NULL)
{
break;
}
}
else if (tracker_mem_get_active_http_server_by_ip(
*ppGroup, szIpAddr) != NULL)
{
break;
}
}
#else
break;
#endif
}
if (g_groups.download_server == \
FDFS_DOWNLOAD_SERVER_ROUND_ROBIN)
{ //avoid search again
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_storage_by_id(
*ppGroup, storage_id);
}
else
{
pStoreSrcServer=tracker_mem_get_active_storage_by_ip(
*ppGroup, szIpAddr);
}
}
else //http
{
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_http_server_by_id(
*ppGroup, storage_id);
}
else
{
pStoreSrcServer=tracker_mem_get_active_http_server_by_ip(
*ppGroup, szIpAddr);
}
}
#else
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_storage_by_id(
*ppGroup, storage_id);
}
else
{
pStoreSrcServer=tracker_mem_get_active_storage_by_ip(
*ppGroup, szIpAddr);
}
#endif
if (pStoreSrcServer != NULL)
{
ppStoreServers[0] = pStoreSrcServer;
break;
}
}
if (g_groups.store_server != \
FDFS_STORE_SERVER_ROUND_ROBIN)
{
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
ppStoreServers[0] = pGroupStoreServer;
}
else //http
{
pStoreSrcServer=tracker_mem_get_active_http_server_by_id(
*ppGroup, pGroupStoreServer->id);
if (pStoreSrcServer != NULL)
{
ppStoreServers[0] = pStoreSrcServer;
}
else
{
ppStoreServers[0] = *((*ppGroup)->http_servers);
}
}
#else
ppStoreServers[0] = pGroupStoreServer;
#endif
break;
}
} while (0);
#ifdef WITH_HTTPD
if (download_type == FDFS_DOWNLOAD_TYPE_TCP)
{
(*ppGroup)->current_read_server++;
if ((*ppGroup)->current_read_server >= (*ppGroup)->active_count)
{
(*ppGroup)->current_read_server = 0;
}
}
else //http
{
(*ppGroup)->current_http_server++;
if ((*ppGroup)->current_http_server >= \
(*ppGroup)->http_server_count)
{
(*ppGroup)->current_http_server = 0;
}
}
#else
(*ppGroup)->current_read_server++;
if ((*ppGroup)->current_read_server >= (*ppGroup)->active_count)
{
(*ppGroup)->current_read_server = 0;
}
#endif
}
else if (cmd == TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE)
{
if (storage_ip != INADDR_NONE)
{
if (*storage_id != '\0')
{
pStoreSrcServer=tracker_mem_get_active_storage_by_id(\
*ppGroup, storage_id);
}
else
{
memset(&ip_addr, 0, sizeof(ip_addr));
ip_addr.s_addr = storage_ip;
pStoreSrcServer=tracker_mem_get_active_storage_by_ip(\
*ppGroup, inet_ntop(AF_INET, &ip_addr, \
szIpAddr, sizeof(szIpAddr)));
}
if (pStoreSrcServer != NULL)
{
ppStoreServers[(*server_count)++] = \
pStoreSrcServer;
return 0;
}
}
ppStoreServers[0] = tracker_get_writable_storage(*ppGroup);
*server_count = ppStoreServers[0] != NULL ? 1 : 0;
}
else //TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL
{
memset(szIpAddr, 0, sizeof(szIpAddr));
if (storage_ip != INADDR_NONE)
{
memset(&ip_addr, 0, sizeof(ip_addr));
ip_addr.s_addr = storage_ip;
inet_ntop(AF_INET, &ip_addr,szIpAddr,sizeof(szIpAddr));
}
if (bNormalFile)
{
current_time = g_current_time;
ppServerEnd = (*ppGroup)->active_servers + \
(*ppGroup)->active_count;
for (ppServer=(*ppGroup)->active_servers; \
ppServer<ppServerEnd; ppServer++)
{
if ((file_timestamp < current_time -
g_storage_sync_file_max_delay) ||
((*ppServer)->stat.last_synced_timestamp >
file_timestamp) ||
((*ppServer)->stat.last_synced_timestamp + 1 >=
file_timestamp && current_time - file_timestamp >
g_storage_sync_file_max_time)
|| (storage_ip == INADDR_NONE
&& g_groups.store_server ==
FDFS_STORE_SERVER_ROUND_ROBIN)
|| strcmp(FDFS_CURRENT_IP_ADDR(*ppServer), szIpAddr) == 0)
{
ppStoreServers[(*server_count)++] = *ppServer;
}
}
}
else
{
if (*storage_id != '\0')
{
pStoreSrcServer = tracker_mem_get_active_storage_by_id( \
*ppGroup, storage_id);
}
else
{
pStoreSrcServer = tracker_mem_get_active_storage_by_ip( \
*ppGroup, szIpAddr);
}
if (pStoreSrcServer != NULL)
{
ppStoreServers[(*server_count)++] = \
pStoreSrcServer;
}
}
if (*server_count == 0)
{
ppStoreServers[(*server_count)++] = pGroupStoreServer;
}
}
return *server_count > 0 ? 0 : ENOENT;
}
int tracker_mem_check_alive(void *arg)
{
FDFSStorageDetail **ppServer;
FDFSStorageDetail **ppServerEnd;
FDFSGroupInfo **ppGroup;
FDFSGroupInfo **ppGroupEnd;
FDFSStorageDetail *deactiveServers[FDFS_MAX_SERVERS_EACH_GROUP];
int deactiveCount;
time_t current_time;
current_time = g_current_time;
ppGroupEnd = g_groups.groups + g_groups.count;
for (ppGroup=g_groups.groups; ppGroup<ppGroupEnd; ppGroup++)
{
deactiveCount = 0;
ppServerEnd = (*ppGroup)->active_servers + (*ppGroup)->active_count;
for (ppServer=(*ppGroup)->active_servers; ppServer<ppServerEnd; ppServer++)
{
if (current_time - (*ppServer)->stat.last_heart_beat_time > \
g_check_active_interval)
{
deactiveServers[deactiveCount] = *ppServer;
deactiveCount++;
if (deactiveCount >= FDFS_MAX_SERVERS_EACH_GROUP)
{
break;
}
}
}
if (deactiveCount == 0)
{
continue;
}
ppServerEnd = deactiveServers + deactiveCount;
for (ppServer=deactiveServers; ppServer<ppServerEnd; ppServer++)
{
(*ppServer)->status = FDFS_STORAGE_STATUS_OFFLINE;
tracker_mem_deactive_store_server(*ppGroup, *ppServer);
if (g_use_storage_id)
{
logInfo("file: "__FILE__", line: %d, "
"storage server %s(%s:%u) idle too long, "
"status change to offline!", __LINE__,
(*ppServer)->id, FDFS_CURRENT_IP_ADDR(*ppServer),
(*ppGroup)->storage_port);
}
else
{
logInfo("file: "__FILE__", line: %d, "
"storage server %s:%u idle too long, "
"status change to offline!", __LINE__,
FDFS_CURRENT_IP_ADDR(*ppServer),
(*ppGroup)->storage_port);
}
}
}
if ((!g_if_leader_self) || (!g_if_use_trunk_file))
{
return 0;
}
for (ppGroup=g_groups.groups; ppGroup<ppGroupEnd; ppGroup++)
{
if ((*ppGroup)->pTrunkServer != NULL)
{
int check_trunk_times;
int check_trunk_interval;
int last_beat_interval;
if (current_time - (*ppGroup)->pTrunkServer->up_time <= \
10 * g_check_active_interval)
{
if (g_trunk_init_check_occupying)
{
check_trunk_times = 5;
}
else
{
check_trunk_times = 3;
}
if (g_trunk_init_reload_from_binlog)
{
check_trunk_times *= 2;
}
}
else
{
check_trunk_times = 2;
}
last_beat_interval = current_time - (*ppGroup)-> \
pTrunkServer->stat.last_heart_beat_time;
check_trunk_interval = check_trunk_times * \
g_check_active_interval;
if (last_beat_interval > check_trunk_interval)
{
logInfo("file: "__FILE__", line: %d, "
"trunk server %s(%s:%u) offline because idle "
"time: %d s > threshold: %d s, should "
"re-select trunk server", __LINE__,
(*ppGroup)->pTrunkServer->id,
FDFS_CURRENT_IP_ADDR((*ppGroup)->pTrunkServer),
(*ppGroup)->storage_port, last_beat_interval,
check_trunk_interval);
(*ppGroup)->pTrunkServer = NULL;
tracker_mem_find_trunk_server(*ppGroup, false);
if ((*ppGroup)->pTrunkServer == NULL)
{
tracker_set_trunk_server_and_log(*ppGroup, NULL);
}
(*ppGroup)->trunk_chg_count++;
g_trunk_server_chg_count++;
tracker_save_groups();
}
}
else
{
tracker_mem_find_trunk_server(*ppGroup, true);
}
}
return 0;
}
int tracker_mem_get_storage_index(FDFSGroupInfo *pGroup, \
FDFSStorageDetail *pStorage)
{
FDFSStorageDetail **ppStorage;
FDFSStorageDetail **ppEnd;
ppEnd = pGroup->all_servers + pGroup->count;
for (ppStorage=pGroup->all_servers; ppStorage<ppEnd; ppStorage++)
{
if (*ppStorage == pStorage)
{
return ppStorage - pGroup->all_servers;
}
}
logError("file: "__FILE__", line: %d, "
"get index of storage %s fail!!!",
__LINE__, FDFS_CURRENT_IP_ADDR(pStorage));
return -1;
}