int main(int argc, char *argv[]) { int idx; avl_tree_t *tree; if (!(tree = avl_tree_init((cmp_t *)cmp))) { fprintf(stderr, "error on avl_tree_init\n"); return -1; } for (idx = 0; idx < sizeof(test_ints)/sizeof(test_ints[0]); idx++) { #if RAND_TEST test_ints[idx] = rand(); if (test_ints[idx] == 0) { test_ints[idx]++; } #endif if (avl_tree_insert(tree, &test_ints[idx]) < 0) { fprintf(stderr, "error on avl_tree_insert\n"); return -1; } } /* printf("%s", avl_tree_str(tree, node2s)); */ if (iter_list(tree, !RAND_TEST)) { return -1; } /* printf("\n"); */ for (idx = 0; idx < 20; idx++) { if (*(int *)avl_tree_search(tree, &test_ints[idx]) != test_ints[idx]) { fprintf(stderr, "error on avl_tree_search\n"); return -1; } } #if RAND_TEST for (idx = 0; idx < sizeof(test_ints)/sizeof(test_ints[0])/2; idx++) { avl_tree_delete(tree, &test_ints[idx]); } #else avl_tree_delete(tree, &test_ints[6]); avl_tree_delete(tree, &test_ints[2]); avl_tree_delete(tree, &test_ints[1]); avl_tree_delete(tree, &test_ints[9]); avl_tree_delete(tree, &test_ints[11]); avl_tree_delete(tree, &test_ints[4]); #endif /* printf("%s", avl_tree_str(tree, node2s)); */ if (iter_list(tree, !RAND_TEST)) { return -1; } printf("Test successful!\n"); return 0; }
static void trunk_delete_size_tree_entry(FDFSTrunkSlot *pSlot) { if (avl_tree_delete(&tree_info_by_size, pSlot) == 1) { fast_mblock_free(&tree_nodes_man, \ pSlot->pMblockNode); } else { logWarning("file: "__FILE__", line: %d, " \ "can't delete slot entry, size: %d", \ __LINE__, pSlot->size); } }
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; }
int trunk_free_block_delete(FDFSTrunkFullInfo *pTrunkInfo) { int result; int left; int right; int mid; int move_count; FDFSTrunkFileIdentifier target; FDFSTrunksById *pTrunksById; char buff[256]; FILL_FILE_IDENTIFIER(target, pTrunkInfo); pTrunksById = (FDFSTrunksById *)avl_tree_find(&tree_info_by_id, &target); if (pTrunksById == NULL) { logWarning("file: "__FILE__", line: %d, " \ "node NOT exist, trunk entry: %s", \ __LINE__, trunk_info_dump(pTrunkInfo, \ buff, sizeof(buff))); return ENOENT; } result = ENOENT; mid = 0; left = 0; right = pTrunksById->block_array.count - 1; while (left <= right) { mid = (left + right) / 2; if (pTrunksById->block_array.blocks[mid]->file.offset > \ pTrunkInfo->file.offset) { right = mid - 1; } else if (pTrunksById->block_array.blocks[mid]->file.offset == \ pTrunkInfo->file.offset) { result = 0; break; } else { left = mid + 1; } } if (result == ENOENT) { logWarning("file: "__FILE__", line: %d, " \ "trunk node NOT exist, trunk entry: %s", \ __LINE__, trunk_info_dump(pTrunkInfo, \ buff, sizeof(buff))); return result; } move_count = pTrunksById->block_array.count - (mid + 1); if (move_count > 0) { memmove(&(pTrunksById->block_array.blocks[mid]), \ &(pTrunksById->block_array.blocks[mid + 1]), \ move_count * sizeof(FDFSTrunkFullInfo *)); } pTrunksById->block_array.count--; if (pTrunksById->block_array.count == 0) { free(pTrunksById->block_array.blocks); if (avl_tree_delete(&tree_info_by_id, pTrunksById) != 1) { memset(&(pTrunksById->block_array), 0, \ sizeof(FDFSBlockArray)); logWarning("file: "__FILE__", line: %d, " \ "can't delete block node, trunk info: %s", \ __LINE__, trunk_info_dump(pTrunkInfo, buff, \ sizeof(buff))); return ENOENT; } } else { if ((pTrunksById->block_array.count < \ pTrunksById->block_array.alloc / 2) && \ (pTrunksById->block_array.count > \ TRUNK_FREE_BLOCK_ARRAY_INIT_SIZE / 2)) //small the array { if ((result=trunk_free_block_realloc( \ &(pTrunksById->block_array), \ pTrunksById->block_array.alloc / 2)) != 0) { return result; } } } return 0; }