/** * 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 #include #include #include #include #include #include #include #include #include #include #include #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; ppStoragestore_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; ppStoragestore_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; ppGroupstore_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; pServergroup_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; pSyncServergroup_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_indexlast_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; ppGroupcount <= 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; ppGroupgroup_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; \ ppStoragestatus == 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; ppGroupsorted_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; isorted_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; ppServersorted_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; ppGroupsorted_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; ppGroupalloc_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; ppGroupgroups, \ 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; ppServerstat.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; ppServerstat.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; ppServerid, 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; ppServerall_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; istore_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; ialloc_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; ppGroupcount != 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; ppServerpsync_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; indexif_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; connip_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; pLocalTrackerconnections + pSrcServer->count; for (conn=pSrcServer->connections; conncount == 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; pJoinTrackercount > 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; pJoinTrackertracker_servers + pJoinBody->tracker_count; for (pTrackerServer=pJoinBody->tracker_servers; pTrackerServerpTrackerServer = 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; iconnections[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; \ ppServerid, storage_id.ptr) == 0) { (*ppServer)->storage_port = \ pJoinBody->storage_port; break; } } for (ppServer=pClientInfo->pGroup->all_servers; \ ppServerstorage_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; \ ppServerid, storage_id.ptr) == 0) { (*ppServer)->storage_http_port = \ pJoinBody->storage_http_port; break; } } for (ppServer=pClientInfo->pGroup->all_servers; \ ppServerstorage_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; ppServerstatus == 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; \ ppServersubdir_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; pServerid[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; ppServerupload_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; ppServerstorage_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; ppServeractive_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; ppGrouppTrunkServer == 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; \ ppServerstat.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; ppGroupactive_servers + (*ppGroup)->active_count; for (ppServer=(*ppGroup)->active_servers; ppServerstat.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; ppServerstatus = 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; ppGrouppTrunkServer != 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; ppStorageall_servers; } } logError("file: "__FILE__", line: %d, " "get index of storage %s fail!!!", __LINE__, FDFS_CURRENT_IP_ADDR(pStorage)); return -1; }