void test_inserting_and_finding() { struct avl_tree_node* root; int* value; root = avl_tree_create(); root = avl_tree_insert(root, "esa", 3); root = avl_tree_insert(root, "vesa", 4); root = avl_tree_insert(root, "vvv", 5); root = avl_tree_insert(root, "aaa", 7); value = avl_tree_find(root, "vesa"); assertIntEquals(4, *value); value = avl_tree_find(root, "esa"); assertIntEquals(3, *value); value = avl_tree_find(root, "vvv"); assertIntEquals(5, *value); value = avl_tree_find(root, "aaa"); assertIntEquals(7, *value); value = avl_tree_find(root, "bbb"); assertNull(value); avl_tree_destroy(root); }
void test_finding() { struct avl_tree_node* root; int* value; root = avl_tree_create(); root = avl_tree_insert(root, "esa", 3); value = avl_tree_find(root, "vesa"); assertNull(value); value = avl_tree_find(root, "esa"); assertIntEquals(3, *value); avl_tree_destroy(root); }
void test_that_keys_are_copied() { struct avl_tree_node* root; int* value; char key[] = "esa"; root = avl_tree_create(); root = avl_tree_insert(root, key, 3); value = avl_tree_find(root, "esa"); assertIntEquals(3, *value); key[0] = 'a'; value = avl_tree_find(root, "esa"); assertIntEquals(3, *value); avl_tree_destroy(root); }
static avl_tree_pos avl_tree_rfind( VALUE self, VALUE obj ) { avl_tree_r *t; avl_tree_elem elem = (avl_tree_elem *)obj; Data_Get_Struct( self, avl_tree_r, t ); return avl_tree_find( t->root, elem, cmp ); }
void test_increasing() { struct avl_tree_node* root; root = avl_tree_create(); root = avl_tree_increase(root, "moi"); root = avl_tree_increase(root, "hello"); root = avl_tree_increase(root, "abc"); root = avl_tree_increase(root, "hello"); root = avl_tree_increase(root, "hello"); root = avl_tree_increase(root, "eee"); root = avl_tree_increase(root, "moi"); assertIntEquals(3, *avl_tree_find(root, "hello")); assertIntEquals(1, *avl_tree_find(root, "abc")); assertIntEquals(2, *avl_tree_find(root, "moi")); assertIntEquals(1, *avl_tree_find(root, "eee")); assertNull(avl_tree_find(root, "dummy")); avl_tree_destroy(root); }
static int trunk_restore_node(const FDFSTrunkFullInfo *pTrunkInfo) { FDFSTrunkSlot target_slot; char buff[256]; FDFSTrunkSlot *pSlot; FDFSTrunkNode *pCurrent; target_slot.size = pTrunkInfo->file.size; target_slot.head = NULL; pthread_mutex_lock(&trunk_mem_lock); pSlot = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + \ pTrunkInfo->path.store_path_index, &target_slot); if (pSlot == NULL) { pthread_mutex_unlock(&trunk_mem_lock); logError("file: "__FILE__", line: %d, " \ "can't find trunk entry: %s", __LINE__, \ trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); return ENOENT; } pCurrent = pSlot->head; while (pCurrent != NULL && memcmp(&(pCurrent->trunk), \ pTrunkInfo, sizeof(FDFSTrunkFullInfo)) != 0) { pCurrent = pCurrent->next; } if (pCurrent == NULL) { pthread_mutex_unlock(&trunk_mem_lock); logError("file: "__FILE__", line: %d, " \ "can't find trunk entry: %s", __LINE__, \ trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); return ENOENT; } pCurrent->trunk.status = FDFS_TRUNK_STATUS_FREE; pthread_mutex_unlock(&trunk_mem_lock); return 0; }
int trunk_free_block_insert(FDFSTrunkFullInfo *pTrunkInfo) { int result; FDFSTrunkFileIdentifier target; FDFSTrunksById *pTrunksById; FILL_FILE_IDENTIFIER(target, pTrunkInfo); pTrunksById = (FDFSTrunksById *)avl_tree_find(&tree_info_by_id, &target); if (pTrunksById == NULL) { pTrunksById = (FDFSTrunksById *)malloc(sizeof(FDFSTrunksById)); if (pTrunksById == NULL) { result = errno != 0 ? errno : ENOMEM; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(FDFSTrunksById), \ result, STRERROR(result)); return result; } memset(pTrunksById, 0, sizeof(FDFSTrunksById)); memcpy(&(pTrunksById->trunk_file_id), &target, \ sizeof(FDFSTrunkFileIdentifier)); if (avl_tree_insert(&tree_info_by_id, pTrunksById) != 1) { result = errno != 0 ? errno : ENOMEM; logError("file: "__FILE__", line: %d, " \ "avl_tree_insert fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); return result; } } return trunk_free_block_do_insert(pTrunkInfo, \ &(pTrunksById->block_array)); }
/* returns process structure by its id */ process_t *proc_get_process_by_id(proc_id pid) { process_t *look4, *proc; unsigned int irqs_state; /* look for */ look4 = containerof(&pid, process_t, id); /* acquire lock before tree-search */ irqs_state = spin_lock_irqsave(&processes_lock); /* search */ proc = avl_tree_find(&processes_tree, look4, NULL); /* increment refs count on success search */ if(proc && proc->state != PROCESS_STATE_DEATH) atomic_inc((atomic_t*)&proc->ref_count); /* release lock */ spin_unlock_irqrstor(&processes_lock, irqs_state); return proc; }
static int trunk_delete_space(const FDFSTrunkFullInfo *pTrunkInfo, \ const bool bWriteBinLog) { int result; FDFSTrunkSlot target_slot; char buff[256]; FDFSTrunkSlot *pSlot; FDFSTrunkNode *pPrevious; FDFSTrunkNode *pCurrent; target_slot.size = pTrunkInfo->file.size; target_slot.head = NULL; pthread_mutex_lock(&trunk_mem_lock); pSlot = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + \ pTrunkInfo->path.store_path_index, &target_slot); if (pSlot == NULL) { pthread_mutex_unlock(&trunk_mem_lock); logError("file: "__FILE__", line: %d, " \ "can't find trunk entry: %s", __LINE__, \ trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); return ENOENT; } pPrevious = NULL; pCurrent = pSlot->head; while (pCurrent != NULL && memcmp(&(pCurrent->trunk), pTrunkInfo, \ sizeof(FDFSTrunkFullInfo)) != 0) { pPrevious = pCurrent; pCurrent = pCurrent->next; } if (pCurrent == NULL) { pthread_mutex_unlock(&trunk_mem_lock); logError("file: "__FILE__", line: %d, " \ "can't find trunk entry: %s", __LINE__, \ trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); return ENOENT; } if (pPrevious == NULL) { pSlot->head = pCurrent->next; if (pSlot->head == NULL) { trunk_delete_size_tree_entry(pTrunkInfo->path. \ store_path_index, pSlot); } } else { pPrevious->next = pCurrent->next; } trunk_free_block_delete(&(pCurrent->trunk)); pthread_mutex_unlock(&trunk_mem_lock); if (bWriteBinLog) { result = trunk_mem_binlog_write(g_current_time, \ TRUNK_OP_TYPE_DEL_SPACE, &(pCurrent->trunk)); } else { pthread_mutex_lock(&trunk_file_lock); g_trunk_total_free_space -= pCurrent->trunk.file.size; pthread_mutex_unlock(&trunk_file_lock); result = 0; } fast_mblock_free(&free_blocks_man, pCurrent->pMblockNode); 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; }
int trunk_free_block_check_duplicate(FDFSTrunkFullInfo *pTrunkInfo) { FDFSTrunkFileIdentifier target; FDFSTrunksById *pFound; FDFSTrunkFullInfo **blocks; int end_offset; int left; int right; int mid; int result; /* char buff[256]; logWarning("file: "__FILE__", line: %d, " \ "trunk entry: %s", __LINE__, \ trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); */ FILL_FILE_IDENTIFIER(target, pTrunkInfo); pFound = (FDFSTrunksById *)avl_tree_find(&tree_info_by_id, &target); if (pFound == NULL) { return 0; } /* { logWarning("file: "__FILE__", line: %d, " \ "ARRAY COUNT: %d, trunk entry: %s", \ __LINE__, pFound->block_array.count, \ trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); } */ if (pFound->block_array.count == 0) { return 0; } blocks = pFound->block_array.blocks; end_offset = pTrunkInfo->file.offset + pTrunkInfo->file.size; if (end_offset <= blocks[0]->file.offset) { return 0; } right = pFound->block_array.count - 1; if (pTrunkInfo->file.offset >= blocks[right]->file.offset + \ blocks[right]->file.size) { return 0; } result = 0; mid = 0; left = 0; while (left <= right) { mid = (left + right) / 2; if (pTrunkInfo->file.offset < blocks[mid]->file.offset) { if (blocks[mid]->file.offset < end_offset) { result = EEXIST; break; } right = mid - 1; } else if (pTrunkInfo->file.offset == blocks[mid]->file.offset) { if (pTrunkInfo->file.size == blocks[mid]->file.size) { char buff[256]; logWarning("file: "__FILE__", line: %d, " \ "node already exist, trunk entry: %s", \ __LINE__, trunk_info_dump(pTrunkInfo, \ buff, sizeof(buff))); return EEXIST; } result = EEXIST; break; } else { if (pTrunkInfo->file.offset < (blocks[mid]->file.offset + \ blocks[mid]->file.size)) { result = EEXIST; break; } left = mid + 1; } } if (result != 0) { char buff1[256]; char buff2[256]; logWarning("file: "__FILE__", line: %d, " \ "node overlap, current trunk entry: %s, " \ "existed trunk entry: %s", __LINE__, \ trunk_info_dump(pTrunkInfo, buff1, sizeof(buff1)), \ trunk_info_dump(blocks[mid], buff2, sizeof(buff2))); } 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; }
static int storage_do_split_trunk_binlog(const int store_path_index, StorageBinLogReader *pReader) { FILE *fp; char *pBasePath; FDFSTrunkFileIdInfo *pFound; char binlogFullFilename[MAX_PATH_SIZE]; char tmpFullFilename[MAX_PATH_SIZE]; FDFSTrunkFullInfo trunk_info; FDFSTrunkFileIdInfo trunkFileId; StorageBinLogRecord record; AVLTreeInfo tree_unique_trunks; int record_length; int result; pBasePath = g_fdfs_store_paths.paths[store_path_index]; recovery_get_full_filename(pBasePath, \ RECOVERY_BINLOG_FILENAME".tmp", tmpFullFilename); fp = fopen(tmpFullFilename, "w"); if (fp == NULL) { result = errno != 0 ? errno : EPERM; logError("file: "__FILE__", line: %d, " \ "open file: %s fail, " \ "errno: %d, error info: %s.", \ __LINE__, tmpFullFilename, result, STRERROR(result)); return result; } if ((result=avl_tree_init(&tree_unique_trunks, free, \ storage_compare_trunk_id_info)) != 0) { logError("file: "__FILE__", line: %d, " \ "avl_tree_init fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); fclose(fp); return result; } memset(&trunk_info, 0, sizeof(trunk_info)); memset(&trunkFileId, 0, sizeof(trunkFileId)); result = 0; while (g_continue_flag) { result=storage_binlog_read(pReader, &record, &record_length); if (result != 0) { if (result == ENOENT) { result = 0; } break; } if (fdfs_is_trunk_file(record.filename, record.filename_len)) { if (fdfs_decode_trunk_info(store_path_index, \ record.true_filename, record.true_filename_len,\ &trunk_info) != 0) { continue; } trunkFileId.path = trunk_info.path; trunkFileId.id = trunk_info.file.id; pFound = (FDFSTrunkFileIdInfo *)avl_tree_find( \ &tree_unique_trunks, &trunkFileId); if (pFound != NULL) { continue; } pFound = (FDFSTrunkFileIdInfo *)malloc( \ sizeof(FDFSTrunkFileIdInfo)); if (pFound == NULL) { result = errno != 0 ? errno : ENOMEM; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", __LINE__,\ (int)sizeof(FDFSTrunkFileIdInfo), \ result, STRERROR(result)); break; } sprintf(trunkFileId.line, "%d %c %s", \ (int)record.timestamp, \ record.op_type, record.filename); memcpy(pFound, &trunkFileId, sizeof(FDFSTrunkFileIdInfo)); if (avl_tree_insert(&tree_unique_trunks, pFound) != 1) { result = errno != 0 ? errno : ENOMEM; logError("file: "__FILE__", line: %d, " \ "avl_tree_insert fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); break; } } else { if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE) { if (fprintf(fp, "%d %c %s\n", \ (int)record.timestamp, \ record.op_type, record.filename) < 0) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "write to file: %s fail, " \ "errno: %d, error info: %s.", \ __LINE__, tmpFullFilename, result, STRERROR(result)); break; } } else { if (fprintf(fp, "%d %c %s %s\n", \ (int)record.timestamp, \ record.op_type, record.filename, \ record.src_filename) < 0) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "write to file: %s fail, " \ "errno: %d, error info: %s.", \ __LINE__, tmpFullFilename, result, STRERROR(result)); break; } } } } if (result == 0) { int tree_node_count; tree_node_count = avl_tree_count(&tree_unique_trunks); if (tree_node_count > 0) { logInfo("file: "__FILE__", line: %d, " \ "recovering trunk file count: %d", __LINE__, \ tree_node_count); result = avl_tree_walk(&tree_unique_trunks, \ tree_write_file_walk_callback, fp); } } avl_tree_destroy(&tree_unique_trunks); fclose(fp); if (!g_continue_flag) { return EINTR; } if (result != 0) { return result; } recovery_get_full_filename(pBasePath, \ RECOVERY_BINLOG_FILENAME, binlogFullFilename); if (rename(tmpFullFilename, binlogFullFilename) != 0) { logError("file: "__FILE__", line: %d, " \ "rename file %s to %s fail, " \ "errno: %d, error info: %s", __LINE__, \ tmpFullFilename, binlogFullFilename, \ errno, STRERROR(errno)); return errno != 0 ? errno : EPERM; } return 0; }