static FDFSTrunkNode *trunk_create_trunk_file(const int store_path_index, \ int *err_no) { FDFSTrunkNode *pTrunkNode; struct fast_mblock_node *pMblockNode; pMblockNode = fast_mblock_alloc(&free_blocks_man); if (pMblockNode == NULL) { *err_no = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(FDFSTrunkNode), \ *err_no, STRERROR(*err_no)); return NULL; } pTrunkNode = (FDFSTrunkNode *)pMblockNode->data; pTrunkNode->pMblockNode = pMblockNode; if (store_path_index >= 0) { pTrunkNode->trunk.path.store_path_index = store_path_index; } else { int result; int new_store_path_index; if ((result=storage_get_storage_path_index( \ &new_store_path_index)) != 0) { logError("file: "__FILE__", line: %d, " \ "get_storage_path_index fail, " \ "errno: %d, error info: %s", __LINE__, \ result, STRERROR(result)); return NULL; } pTrunkNode->trunk.path.store_path_index = new_store_path_index; } pTrunkNode->trunk.file.offset = 0; pTrunkNode->trunk.file.size = g_trunk_file_size; pTrunkNode->trunk.status = FDFS_TRUNK_STATUS_FREE; pTrunkNode->next = NULL; *err_no = trunk_create_next_file(&(pTrunkNode->trunk)); if (*err_no != 0) { fast_mblock_free(&free_blocks_man, pMblockNode); return NULL; } *err_no = trunk_mem_binlog_write(g_current_time, \ TRUNK_OP_TYPE_ADD_SPACE, &(pTrunkNode->trunk)); return pTrunkNode; }
int trunk_free_space(const FDFSTrunkFullInfo *pTrunkInfo, \ const bool bWriteBinLog) { int result; struct fast_mblock_node *pMblockNode; FDFSTrunkNode *pTrunkNode; if (!g_if_trunker_self) { logError("file: "__FILE__", line: %d, " \ "I am not trunk server!", __LINE__); return EINVAL; } if (trunk_init_flag != STORAGE_TRUNK_INIT_FLAG_DONE) { if (bWriteBinLog) { logError("file: "__FILE__", line: %d, " \ "I am not inited!", __LINE__); return EINVAL; } } if (pTrunkInfo->file.size < g_slot_min_size) { logDebug("file: "__FILE__", line: %d, " \ "space: %d is too small, do not need recycle!", \ __LINE__, pTrunkInfo->file.size); return 0; } pMblockNode = fast_mblock_alloc(&free_blocks_man); if (pMblockNode == NULL) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(FDFSTrunkNode), \ result, STRERROR(result)); return result; } pTrunkNode = (FDFSTrunkNode *)pMblockNode->data; memcpy(&pTrunkNode->trunk, pTrunkInfo, sizeof(FDFSTrunkFullInfo)); pTrunkNode->pMblockNode = pMblockNode; pTrunkNode->trunk.status = FDFS_TRUNK_STATUS_FREE; pTrunkNode->next = NULL; return trunk_add_free_block(pTrunkNode, bWriteBinLog); }
static int trunk_split(FDFSTrunkNode *pNode, const int size) { int result; struct fast_mblock_node *pMblockNode; FDFSTrunkNode *pTrunkNode; if (pNode->trunk.file.size - size < g_slot_min_size) { return trunk_mem_binlog_write(g_current_time, \ TRUNK_OP_TYPE_DEL_SPACE, &(pNode->trunk)); } pMblockNode = fast_mblock_alloc(&free_blocks_man); if (pMblockNode == NULL) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(FDFSTrunkNode), \ result, STRERROR(result)); return result; } result = trunk_mem_binlog_write(g_current_time, \ TRUNK_OP_TYPE_DEL_SPACE, &(pNode->trunk)); if (result != 0) { fast_mblock_free(&free_blocks_man, pMblockNode); return result; } pTrunkNode = (FDFSTrunkNode *)pMblockNode->data; memcpy(pTrunkNode, pNode, sizeof(FDFSTrunkNode)); pTrunkNode->pMblockNode = pMblockNode; pTrunkNode->trunk.file.offset = pNode->trunk.file.offset + size; pTrunkNode->trunk.file.size = pNode->trunk.file.size - size; pTrunkNode->trunk.status = FDFS_TRUNK_STATUS_FREE; pTrunkNode->next = NULL; result = trunk_add_free_block(pTrunkNode, true); if (result != 0) { return result; } pNode->trunk.file.size = size; return 0; }
static FDFSTrunkNode *trunk_create_trunk_file(int *err_no) { FDFSTrunkNode *pTrunkNode; struct fast_mblock_node *pMblockNode; pMblockNode = fast_mblock_alloc(&free_blocks_man); if (pMblockNode == NULL) { *err_no = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(FDFSTrunkNode), \ *err_no, STRERROR(*err_no)); return NULL; } pTrunkNode = (FDFSTrunkNode *)pMblockNode->data; pTrunkNode->pMblockNode = pMblockNode; pTrunkNode->trunk.file.offset = 0; pTrunkNode->trunk.file.size = g_trunk_file_size; pTrunkNode->trunk.status = FDFS_TRUNK_STATUS_FREE; pTrunkNode->next = NULL; *err_no = trunk_create_next_file(&(pTrunkNode->trunk)); if (*err_no != 0) { fast_mblock_free(&free_blocks_man, pMblockNode); return NULL; } *err_no = trunk_mem_binlog_write(g_current_time, \ TRUNK_OP_TYPE_ADD_SPACE, &(pTrunkNode->trunk)); return pTrunkNode; }
static int storage_trunk_restore(const int64_t restore_offset) { int64_t trunk_binlog_size; int64_t line_count; TrunkBinLogReader reader; TrunkBinLogRecord record; char trunk_mark_filename[MAX_PATH_SIZE]; char buff[256]; int record_length; int result; AVLTreeInfo tree_info_by_offset; struct fast_mblock_node *pMblockNode; FDFSTrunkNode *pTrunkNode; FDFSTrunkNode trunkNode; bool trunk_init_reload_from_binlog; trunk_binlog_size = storage_trunk_get_binlog_size(); if (trunk_binlog_size < 0) { return errno != 0 ? errno : EPERM; } if (restore_offset == trunk_binlog_size) { return 0; } if (restore_offset > trunk_binlog_size) { logWarning("file: "__FILE__", line: %d, " \ "restore_offset: %"PRId64 \ " > trunk_binlog_size: %"PRId64, \ __LINE__, restore_offset, trunk_binlog_size); return storage_trunk_save(); } logDebug("file: "__FILE__", line: %d, " \ "trunk metadata recovering, start offset: " \ "%"PRId64", need recovery binlog bytes: " \ "%"PRId64, __LINE__, \ restore_offset, trunk_binlog_size - restore_offset); trunk_init_reload_from_binlog = (restore_offset == 0); if (trunk_init_reload_from_binlog) { memset(&trunkNode, 0, sizeof(trunkNode)); if ((result=avl_tree_init(&tree_info_by_offset, \ storage_trunk_free_node, \ storage_trunk_node_compare_offset)) != 0) { logError("file: "__FILE__", line: %d, " \ "avl_tree_init fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); return result; } } memset(&record, 0, sizeof(record)); memset(&reader, 0, sizeof(reader)); reader.binlog_offset = restore_offset; if ((result=trunk_reader_init(NULL, &reader)) != 0) { return result; } line_count = 0; while (1) { record_length = 0; result = trunk_binlog_read(&reader, &record, &record_length); if (result != 0) { if (result == ENOENT) { if (record_length > 0) //skip incorrect record { line_count++; reader.binlog_offset += record_length; continue; } result = (reader.binlog_offset >= \ trunk_binlog_size) ? 0 : EINVAL; if (result != 0) { logError("file: "__FILE__", line: %d, " \ "binlog offset: %"PRId64 \ " < binlog size: %"PRId64 \ ", please check the end of trunk " \ "binlog", __LINE__, \ reader.binlog_offset, trunk_binlog_size); } } break; } line_count++; if (record.op_type == TRUNK_OP_TYPE_ADD_SPACE) { record.trunk.status = FDFS_TRUNK_STATUS_FREE; if (trunk_init_reload_from_binlog) { pMblockNode = fast_mblock_alloc(&free_blocks_man); if (pMblockNode == NULL) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, "\ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, \ (int)sizeof(FDFSTrunkNode), \ result, STRERROR(result)); return result; } pTrunkNode = (FDFSTrunkNode *)pMblockNode->data; memcpy(&pTrunkNode->trunk, &(record.trunk), \ sizeof(FDFSTrunkFullInfo)); pTrunkNode->pMblockNode = pMblockNode; pTrunkNode->next = NULL; result = avl_tree_insert(&tree_info_by_offset,\ pTrunkNode); if (result < 0) //error { result *= -1; logError("file: "__FILE__", line: %d, "\ "avl_tree_insert fail, " \ "errno: %d, error info: %s", \ __LINE__, result, \ STRERROR(result)); return result; } else if (result == 0) { trunk_info_dump(&(record.trunk), \ buff, sizeof(buff)); logWarning("file: "__FILE__", line: %d"\ ", trunk data line: " \ "%"PRId64", trunk "\ "space already exist, "\ "trunk info: %s", \ __LINE__, line_count, buff); } } else if ((result=trunk_add_space_by_trunk( \ &record.trunk)) != 0) { break; } } else if (record.op_type == TRUNK_OP_TYPE_DEL_SPACE) { record.trunk.status = FDFS_TRUNK_STATUS_FREE; if (trunk_init_reload_from_binlog) { memcpy(&trunkNode.trunk, &record.trunk, \ sizeof(FDFSTrunkFullInfo)); if (avl_tree_delete(&tree_info_by_offset,\ &trunkNode) != 1) { trunk_info_dump(&(record.trunk), \ buff, sizeof(buff)); logWarning("file: "__FILE__", line: %d"\ ", binlog offset: %"PRId64 \ ", trunk data line: %"PRId64 \ " trunk node not exist, " \ "trunk info: %s", __LINE__, \ reader.binlog_offset, \ line_count, buff); } } else if ((result=trunk_delete_space( \ &record.trunk, false)) != 0) { if (result == ENOENT) { logDebug("file: "__FILE__", line: %d, "\ "binlog offset: %"PRId64 \ ", trunk data line: %"PRId64,\ __LINE__, reader.binlog_offset, \ line_count); result = 0; } else { break; } } } reader.binlog_offset += record_length; } trunk_reader_destroy(&reader); trunk_mark_filename_by_reader(&reader, trunk_mark_filename); if (unlink(trunk_mark_filename) != 0) { logError("file: "__FILE__", line: %d, " \ "unlink file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ trunk_mark_filename, errno, STRERROR(errno)); } if (result != 0) { if (trunk_init_reload_from_binlog) { avl_tree_destroy(&tree_info_by_offset); } logError("file: "__FILE__", line: %d, " \ "trunk load fail, errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); return result; } if (trunk_init_reload_from_binlog) { logInfo("file: "__FILE__", line: %d, " \ "free tree node count: %d", \ __LINE__, avl_tree_count(&tree_info_by_offset)); result = avl_tree_walk(&tree_info_by_offset, \ storage_trunk_add_free_blocks_callback, NULL); tree_info_by_offset.free_data_func = NULL; avl_tree_destroy(&tree_info_by_offset); } if (result == 0) { logDebug("file: "__FILE__", line: %d, " \ "trunk metadata recovery done. start offset: " \ "%"PRId64", recovery file size: " \ "%"PRId64, __LINE__, \ restore_offset, trunk_binlog_size - restore_offset); return storage_trunk_save(); } return result; }
static int trunk_add_free_block(FDFSTrunkNode *pNode, const bool bWriteBinLog) { int result; struct fast_mblock_node *pMblockNode; FDFSTrunkSlot target_slot; FDFSTrunkSlot *chain; pthread_mutex_lock(&trunk_mem_lock); if ((result=trunk_free_block_check_duplicate(&(pNode->trunk))) != 0) { pthread_mutex_unlock(&trunk_mem_lock); return result; } target_slot.size = pNode->trunk.file.size; target_slot.head = NULL; chain = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + \ pNode->trunk.path.store_path_index, &target_slot); if (chain == NULL) { pMblockNode = fast_mblock_alloc(&tree_nodes_man); if (pMblockNode == NULL) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(FDFSTrunkSlot), \ result, STRERROR(result)); pthread_mutex_unlock(&trunk_mem_lock); return result; } chain = (FDFSTrunkSlot *)pMblockNode->data; chain->pMblockNode = pMblockNode; chain->size = pNode->trunk.file.size; pNode->next = NULL; chain->head = pNode; if (avl_tree_insert(tree_info_by_sizes + pNode->trunk. \ path.store_path_index, chain) != 1) { result = errno != 0 ? errno : ENOMEM; logError("file: "__FILE__", line: %d, " \ "avl_tree_insert fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); pthread_mutex_unlock(&trunk_mem_lock); return result; } } else { pNode->next = chain->head; chain->head = pNode; } if (bWriteBinLog) { result = trunk_mem_binlog_write(g_current_time, \ TRUNK_OP_TYPE_ADD_SPACE, &(pNode->trunk)); } else { pthread_mutex_lock(&trunk_file_lock); g_trunk_total_free_space += pNode->trunk.file.size; pthread_mutex_unlock(&trunk_file_lock); result = 0; } if (result == 0) { result = trunk_free_block_insert(&(pNode->trunk)); } else { trunk_free_block_insert(&(pNode->trunk)); } pthread_mutex_unlock(&trunk_mem_lock); return result; }