6257 lines
159 KiB
C
6257 lines
159 KiB
C
/**
|
||
* 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)
|
||
{
|
||
// 当IP地址为IPv6时,其storage_id值为IP地址的short code
|
||
if (is_ipv6_addr(ip_addr))
|
||
{
|
||
fdfs_ip_to_shortcode(ip_addr, target_storage.id);
|
||
}
|
||
else
|
||
{
|
||
strcpy(target_storage.id, ip_addr);
|
||
}
|
||
}
|
||
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)
|
||
{
|
||
FDFSStorageId 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.ptr = pStorageIdInfo->id;
|
||
}
|
||
else
|
||
{
|
||
// 当IP地址为IPv6时,其storage_id值为IP地址的short code
|
||
if (is_ipv6_addr(ip_addr))
|
||
{
|
||
storage_id.ptr = fdfs_ip_to_shortcode(ip_addr,
|
||
storage_id.holder);
|
||
}
|
||
else
|
||
{
|
||
storage_id.ptr = (char *)ip_addr;
|
||
}
|
||
}
|
||
|
||
return tracker_mem_get_storage(pGroup, storage_id.ptr);
|
||
}
|
||
|
||
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;
|
||
FDFSStorageId 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.ptr = (char *)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.ptr = pStorageIdInfo->id;
|
||
}
|
||
else
|
||
{
|
||
// 当IP地址为IPv6时,其storage_id值为IP地址的short code
|
||
if (is_ipv6_addr(ip_addr))
|
||
{
|
||
storage_id.ptr = fdfs_ip_to_shortcode(ip_addr, storage_id.holder);
|
||
}
|
||
else
|
||
{
|
||
storage_id.ptr = (char *)ip_addr;
|
||
}
|
||
}
|
||
|
||
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.ptr);
|
||
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.ptr);
|
||
(*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;
|
||
FDFSStorageId 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)
|
||
{
|
||
FDFSStorageIdInfo *pStorageIdInfo;
|
||
|
||
if (g_trust_storage_server_id && *(pJoinBody->storage_id) != '\0')
|
||
{
|
||
pStorageIdInfo = fdfs_get_storage_by_id(pJoinBody->storage_id);
|
||
if (pStorageIdInfo == NULL)
|
||
{
|
||
logError("file: "__FILE__", line: %d, "
|
||
"get storage id info fail, storage id: %s",
|
||
__LINE__, pJoinBody->storage_id);
|
||
return ENOENT;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
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.ptr = pStorageIdInfo->id;
|
||
}
|
||
else
|
||
{
|
||
// 当IP地址为IPv6时,其storage_id值为IP地址的short code
|
||
if (is_ipv6_addr(ip_addr))
|
||
{
|
||
storage_id.ptr = fdfs_ip_to_shortcode(ip_addr, storage_id.holder);
|
||
}
|
||
else
|
||
{
|
||
storage_id.ptr = (char *)ip_addr;
|
||
}
|
||
}
|
||
|
||
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.ptr) == 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.ptr) == 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.ptr);
|
||
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.ptr,
|
||
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(¤t_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_fdfs_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;
|
||
}
|
||
|