예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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 );
}
예제 #5
0
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);
}
예제 #6
0
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));
}
예제 #8
0
파일: process.c 프로젝트: skarpenko/phlox
/* 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;
}
예제 #9
0
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;
}
예제 #10
0
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;
}
예제 #13
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;
}