Пример #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_insertion()
{
	struct avl_tree_node* root;
	root = avl_tree_create();
	root = avl_tree_insert(root, "esa", 0);
	root = avl_tree_insert(root, "vesa", 1);
	root = avl_tree_insert(root, "hesa", 2);
	avl_tree_destroy(root);
}
Пример #3
0
void test_inserting()
{
	struct avl_tree_node* root;

	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);

	avl_tree_destroy(root);
}
Пример #4
0
void test_for_each()
{
	struct avl_tree_node* root;
	root = avl_tree_create();
	root = avl_tree_insert(root, "aaa", 3);
	root = avl_tree_insert(root, "vesa", 5);
	root = avl_tree_insert(root, "esa", 7);
	TOTAL = 1;
	avl_tree_for_each(root, test_function);
	assertIntEquals(3*5*7, TOTAL);

	avl_tree_destroy(root);
}
Пример #5
0
void avl_tree_find_median ( void ) {
  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);
  IntBucket * median;

  IntBucket ib[] = {
    {30272}, {16274}, {11768}, {10231}, {28474}, { 7272}, {15032}, {13196}, {29825}, { 6840},
    {18444}, {18793}, {13786}, {21125}, {25311}, {23414}, {18374}, {24110}, {15465}, {26300},
    { 1181}, { 6297}, { 3693}, {20957}, {22585}, { 8915}, {30371}, { 2036}, {18499}, {18391},
    {15360}, {32509}, {23336}, {18848}, {25712}, { 6162}, { 1483}, { 4309}, {13482}, {14809},
    { 5596}, {22524}, {13958}, {16918}, {25668}, {31621}, {30060}, {24637}, {28116}, {15994},
    {30595}, {30642}, {30017}, { 7221}, { 2916}, { 7010}, {29356}, {22282}, {30649}, {17493},
    {28780}, { 6725}, {26998}, {28805}, {24689}, {25547}, {17625}, {14250}, {11250}, {16195},
    { 9542}, {26029}, { 2734}, {23373}, {21176}, {28102}, { 1894}, {  325}, { 9406}, { 4915},
    { 8759}, {32413}, {14144}, { 5394}, { 3495}, {32030}, {23904}, { 4260}, {11579}, {11100},
    {27212}, {20562}, {30264}, {30850}, {22393}, {28107}, {21299}, {25306}, { 2668}, { 3894},
  };

  int i;

  for ( i = 0; i < 100; i += 1 ) {
    avl_tree_insert(t, ib+i);
  }

  median = (IntBucket*)(avl_tree_get_median(t)->bucket);
  ASSERT(median->p == 18391, "Wrong median!");

  destroy_avl_tree(t);
}
Пример #6
0
void avl_test_find_node ( void ) {
  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);
  BTNode * found;
  IntBucket x;

  IntBucket ib[] = {
    {30272}, {16274}, {11768}, {10231}, {28474}, { 7272}, {15032}, {13196}, {29825}, { 6840},
    {18444}, {18793}, {13786}, {21125}, {25311}, {23414}, {18374}, {24110}, {15465}, {26300},
    { 1181}, { 6297}, { 3693}, {20957}, {22585}, { 8915}, {30371}, { 2036}, {18499}, {18391},
    {15360}, {32509}, {23336}, {18848}, {25712}, { 6162}, { 1483}, { 4309}, {13482}, {14809},
    { 5596}, {22524}, {13958}, {16918}, {25668}, {31621}, {30060}, {24637}, {28116}, {15994},
    {30595}, {30642}, {30017}, { 7221}, { 2916}, { 7010}, {29356}, {22282}, {30649}, {17493},
    {28780}, { 6725}, {26998}, {28805}, {24689}, {25547}, {17625}, {14250}, {11250}, {16195},
    { 9542}, {26029}, { 2734}, {23373}, {21176}, {28102}, { 1894}, {  325}, { 9406}, { 4915},
    { 8759}, {32413}, {14144}, { 5394}, { 3495}, {32030}, {23904}, { 4260}, {11579}, {11100},
    {27212}, {20562}, {30264}, {30850}, {22393}, {28107}, {21299}, {25306}, { 2668}, { 3894},
  };

  int i;

  for ( i = 0; i < 100; i += 1 ) {
    avl_tree_insert(t, ib+i);
  }
  ASSERT(avl_verify_consistency(t, t->root), "Tree starting inconsistent.");

  x.p = 700;
  ASSERT(NULL == avl_find_exact ( t, &x ), "Found an element that wasn't there ...");
  x.p = 26029;
  ASSERT( ((IntBucket*)(avl_find_exact(t,&x)->bucket))->p == 26029, "Couldn't find an easy one.");

  destroy_avl_tree(t);
}
void test_avl_tree_to_array(void)
{
	AVLTree *tree;
	int entries[] = { 89, 23, 42, 4, 16, 15, 8, 99, 50, 30 };
	int sorted[]  = { 4, 8, 15, 16, 23, 30, 42, 50, 89, 99 };
	int num_entries = sizeof(entries) / sizeof(int);
	int i;
	int **array;

	/* Add all entries to the tree */

	tree = avl_tree_new((AVLTreeCompareFunc) int_compare);

	for (i=0; i<num_entries; ++i) {
		avl_tree_insert(tree, &entries[i], NULL);
	}

	assert(avl_tree_num_entries(tree) == num_entries);

	/* Convert to an array and check the contents */

	array = (int **) avl_tree_to_array(tree);

	for (i=0; i<num_entries; ++i) {
		assert(*array[i] == sorted[i]);
	}

	free(array);
}
Пример #8
0
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;
}
Пример #9
0
/** Create a new semaphore.
 * @param name		Optional name for the semaphore, for debugging purposes.
 * @param count		Initial count of the semaphore.
 * @param security	Security attributes for the ACL. If NULL, default
 *			attributes will be constructed which grant full access
 *			to the semaphore to the calling process' user.
 * @param rights	Access rights for the handle.
 * @param handlep	Where to store handle to the semaphore.
 * @return		Status code describing result of the operation. */
status_t kern_semaphore_create(const char *name, size_t count,
	const object_security_t *security, object_rights_t rights,
	handle_t *handlep)
{
	object_security_t ksecurity = { -1, -1, NULL };
	user_semaphore_t *sem;
	status_t ret;

	if(!handlep)
		return STATUS_INVALID_ARG;

	if(security) {
		ret = object_security_from_user(&ksecurity, security, true);
		if(ret != STATUS_SUCCESS)
			return ret;
	}

	/* Construct a default ACL if required. */
	if(!ksecurity.acl) {
		ksecurity.acl = kmalloc(sizeof(*ksecurity.acl), MM_WAIT);
		object_acl_init(ksecurity.acl);
		object_acl_add_entry(ksecurity.acl, ACL_ENTRY_USER, -1, SEMAPHORE_RIGHT_USAGE);
	}

	sem = kmalloc(sizeof(user_semaphore_t), MM_WAIT);
	sem->id = id_allocator_alloc(&semaphore_id_allocator);
	if(sem->id < 0) {
		kfree(sem);
		object_security_destroy(&ksecurity);
		return STATUS_NO_SEMAPHORES;
	}
	if(name) {
		ret = strndup_from_user(name, SEMAPHORE_NAME_MAX, &sem->name);
		if(ret != STATUS_SUCCESS) {
			id_allocator_free(&semaphore_id_allocator, sem->id);
			kfree(sem);
			object_security_destroy(&ksecurity);
			return ret;
		}
	} else {
		sem->name = NULL;
	}

	object_init(&sem->obj, &semaphore_object_type, &ksecurity, NULL);
	object_security_destroy(&ksecurity);
	semaphore_init(&sem->sem, (sem->name) ? sem->name : "user_semaphore", count);
	refcount_set(&sem->count, 1);

	rwlock_write_lock(&semaphore_tree_lock);
	avl_tree_insert(&semaphore_tree, &sem->tree_link, sem->id, sem);
	rwlock_unlock(&semaphore_tree_lock);

	ret = object_handle_create(&sem->obj, NULL, rights, NULL, 0, NULL, NULL, handlep);
	if(ret != STATUS_SUCCESS)
		user_semaphore_release(sem);

	return ret;
}
Пример #10
0
static VALUE avl_tree_rinsert( VALUE self, VALUE obj )
{
  avl_tree_r *t;
  avl_tree_elem elem = (avl_tree_elem *)obj;

  Data_Get_Struct( self, avl_tree_r, t );

  t->root = avl_tree_insert( t->root, elem, cmp );

  return obj;
}
Пример #11
0
//you should get down_write for inode_inf before running this function
int add_event_to_inode( struct inode* inode, unsigned short child_index, unsigned char type, void* data, unsigned int datalen, unsigned char flags){
	struct avl_tree_node* atn;
	struct GSFS_inode* inode_info=(struct GSFS_inode*)inode->i_private;
	struct child* child;
	int ret;
	
	if(unlikely(type>=Events_Num))
		return -1;
	
	ret=0;
	
	atn=avl_tree_search( inode_info->children, child_index);
	if(atn){
		child=atn->data;
		//printk("<0>" "add event to inode: pino:%lu index:%d type%d len:%d\n",inode->i_ino, child_index, type,datalen);
	}
	else{
		//be care full that it is possible to go here for example
		//for traverse all gdirents for a has_sec_child dir 
		//therefore we should make this part active to add child
		
		gt(printk("<0>" "add event to inode with no child_index: pino:%lu index:%d type:%d len:%d\n",inode->i_ino, child_index, type,datalen));
		
		child=kzalloc(sizeof(struct child),GFP_KERNEL);
		child->index=child_index;
		inode_info->children=avl_tree_insert(inode_info->children, child);
		
		if(!inode_info->children){
			printk("<1>" "Some errors in inserting new child_events.\n");
			ret=-1;
		}
		
		if(ret==-1)
			goto back;
	}
	
	if(child->events[type].flags & event_flag_is_present)
		if(child->events[type].data)
			if(child->events[type].data != data)
				free_one_present_event(&child->events[type],type);
	
	child->events[type].data=data;
	child->events[type].datalen=datalen;
	child->events[type].flags=flags|event_flag_is_present;	

back:	
	//print_all_events(child);
	return ret;
}
Пример #12
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);
}
AVLTree *create_tree(void)
{
	AVLTree *tree;
	int i;

	/* Create a tree and fill with nodes */

	tree = avl_tree_new((AVLTreeCompareFunc) int_compare);

	for (i=0; i<NUM_TEST_VALUES; ++i) {
		test_array[i] = i;
		avl_tree_insert(tree, &test_array[i], &test_array[i]);
	}

	return tree;
}
Пример #14
0
void avl_tree_traverse_test ( void ) {
  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);
  IntBucket bucket;

  int i;

  srand(12345678);

  for ( i = 0; i < 1000; i += 1 ) {
    bucket.p = rand();
    avl_tree_insert(t, &bucket);
  }

  avl_tree_traverse(t, doit);

  destroy_avl_tree(t);
}
Пример #15
0
void avl_tree_insert_random ( void ) {
  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);
  IntBucket bucket;

  int i;

  srand(12345678);

  for ( i = 0; i < 100000; i += 1 ) {
    bucket.p = rand();
    avl_tree_insert(t, &bucket);
    ASSERT(t->root->count == i+1, "Wrong count after insert");
  }
  ASSERT(avl_verify_consistency(t, t->root)==true, "Tree inconsistent after insert");

  destroy_avl_tree(t);
}
Пример #16
0
void avl_tree_test_delete ( void ) {
  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);
  BTNode * median_node;
  IntBucket x;

  IntBucket ib[] = {
    {30272}, {16274}, {11768}, {10231}, {28474}, { 7272}, {15032}, {13196}, {29825}, { 6840},
    {18444}, {18793}, {13786}, {21125}, {25311}, {23414}, {18374}, {24110}, {15465}, {26300},
    { 1181}, { 6297}, { 3693}, {20957}, {22585}, { 8915}, {30371}, { 2036}, {18499}, {18391},
    {15360}, {32509}, {23336}, {18848}, {25712}, { 6162}, { 1483}, { 4309}, {13482}, {14809},
    { 5596}, {22524}, {13958}, {16918}, {25668}, {31621}, {30060}, {24637}, {28116}, {15994},
    {30595}, {30642}, {30017}, { 7221}, { 2916}, { 7010}, {29356}, {22282}, {30649}, {17493},
    {28780}, { 6725}, {26998}, {28805}, {24689}, {25547}, {17625}, {14250}, {11250}, {16195},
    { 9542}, {26029}, { 2734}, {23373}, {21176}, {28102}, { 1894}, {  325}, { 9406}, { 4915},
    { 8759}, {32413}, {14144}, { 5394}, { 3495}, {32030}, {23904}, { 4260}, {11579}, {11100},
    {27212}, {20562}, {30264}, {30850}, {22393}, {28107}, {21299}, {25306}, { 2668}, { 3894},
  };

  int i;

  for ( i = 0; i < 100; i += 1 ) {
    avl_tree_insert(t, ib+i);
  }
  ASSERT(avl_verify_consistency(t, t->root), "Tree starting inconsistent.");

  median_node = avl_tree_get_median(t);
  avl_delete_node(t, median_node);
  ASSERT(avl_verify_consistency(t, t->root), "Tree inconsistent after delete.");
  median_node = avl_tree_get_median(t);
  ASSERT( ((IntBucket*)(median_node->bucket))->p == 18374, "Wrong median after delete." );

  while ( t->root->count > 1 ) {
    avl_delete_node(t, t->root);
    ASSERT(avl_verify_consistency(t, t->root), "Tree inconsistent after delete.");
  }
  avl_delete_node(t, t->root);

  x.p = 99; avl_tree_insert(t, &x);
  x.p = 199; avl_tree_insert(t, &x);
  x.p = 299; avl_tree_insert(t, &x);
  x.p = 399; avl_tree_insert(t, &x);
  x.p = 499; avl_tree_insert(t, &x);

  ASSERT(5 == t->root->count, "Wrong count after 5 inserts.");
  ASSERT(avl_verify_consistency(t, t->root), "Tree inconsistent after 5 inserts.");

  avl_delete_node(t, t->root->right);
  ASSERT(4 == t->root->count, "Wrong count after first delete.");
  ASSERT(avl_verify_consistency(t, t->root), "Tree inconsistent after first delete.");

  destroy_avl_tree(t);
}
Пример #17
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);
}
void test_avl_tree_child(void)
{
	AVLTree *tree;
	AVLTreeNode *root;
	AVLTreeNode *left;
	AVLTreeNode *right;
	int values[] = { 1, 2, 3 };
	int *p;
	int i;

	/* Create a tree containing some values. Validate the
	 * tree is consistent at all stages. */

	tree = avl_tree_new((AVLTreeCompareFunc) int_compare);

	for (i=0; i<3; ++i) {
		avl_tree_insert(tree, &values[i], &values[i]);
	}

	/* Check the tree */

	root = avl_tree_root_node(tree);
	p = avl_tree_node_value(root);
	assert(*p == 2);

	left = avl_tree_node_child(root, AVL_TREE_NODE_LEFT);
	p = avl_tree_node_value(left);
	assert(*p == 1);

	right = avl_tree_node_child(root, AVL_TREE_NODE_RIGHT);
	p = avl_tree_node_value(right);
	assert(*p == 3);

	/* Check invalid values */

	assert(avl_tree_node_child(root, -1) == NULL);
	assert(avl_tree_node_child(root, 10000) == NULL);
	assert(avl_tree_node_child(root, 2) == NULL);
	assert(avl_tree_node_child(root, -100000) == NULL);

	avl_tree_free(tree);
}
void test_avl_tree_insert_lookup(void)
{
	AVLTree *tree;
	AVLTreeNode *node;
	int i;
	int *value;

	/* Create a tree containing some values. Validate the
	 * tree is consistent at all stages. */

	tree = avl_tree_new((AVLTreeCompareFunc) int_compare);

	for (i=0; i<NUM_TEST_VALUES; ++i) {
		test_array[i] = i;
		avl_tree_insert(tree, &test_array[i], &test_array[i]);

		assert(avl_tree_num_entries(tree) == i + 1);
		validate_tree(tree);
	}

	assert(avl_tree_root_node(tree) != NULL);

	/* Check that all values can be read back again */

	for (i=0; i<NUM_TEST_VALUES; ++i) {
		node = avl_tree_lookup_node(tree, &i);
		assert(node != NULL);
		value = avl_tree_node_key(node);
		assert(*value == i);
		value = avl_tree_node_value(node);
		assert(*value == i);
	}

	/* Check that invalid nodes are not found */

	i = -1;
	assert(avl_tree_lookup_node(tree, &i) == NULL);
	i = NUM_TEST_VALUES + 100;
	assert(avl_tree_lookup_node(tree, &i) == NULL);

	avl_tree_free(tree);
}
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));
}
Пример #21
0
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;
}
Пример #22
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;
}
Пример #23
0
void perform_avl_tree_test (avl_tree_t *avlt, int use_odd_numbers)
{
    int i, lo, hi, d, fail_search;
    int rv;
    int fine, not_fine;
    char *oddness = use_odd_numbers ? "odd" : "even";
    char *reverse = use_odd_numbers ? "even" : "odd";
    unsigned long long int bytes_used;
    double megabytes_used;
    void *fwdata, *searched, *found, *removed;
    chunk_manager_parameters_t chparams;

    printf("size of ONE avl node is: %lu bytes\n",
            sizeof(avl_node_t));

    /* 
    ** Fill opposing ends of array, converge in middle.
    ** This gives some sort of randomness to data.
    */
    printf("filling array of size %d with %s number data\n", 
        MAX_SZ, oddness);
    d = use_odd_numbers ? 1 : 0;
    lo = 0; 
    hi = MAX_SZ - 1;
    while (1) {
        data[lo++] = d;
        d += 2;
        data[hi--] = d;
        d += 2;
        if (lo > hi) break;
    }

    if (max_value_reached < d) {
        max_value_reached = d + 10;
        printf("max value recorded so far is %d\n", max_value_reached);
    }

    chparams.initial_number_of_chunks = max_value_reached + 10;
    chparams.grow_size = 1024;

    avl_tree_init(avlt, 1, int_compare, NULL, &chparams);

    /* enter all array data into avl tree */
    printf("now entering all %s number data into the avl tree\n", oddness);
    timer_start(&timr);
    for (i = 0; i < MAX_SZ; i++) {
        fwdata = &data[i];
        rv = avl_tree_insert(avlt, fwdata, &found);
        if (rv != 0) {
            printf("populate_data: avl_tree_insert error: %d failed\n", i);
        }
    }
    timer_end(&timr);
    timer_report(&timr, MAX_SZ, NULL);
    OBJECT_MEMORY_USAGE(avlt, bytes_used, megabytes_used);
    printf("total memory used by the avl tree of %d nodes: %llu bytes (%lf Mbytes)\n",
        avlt->n, bytes_used, megabytes_used);

    printf("searching for non existant data\n");
    fine = not_fine = 0;
    timer_start(&timr);
    for (i = max_value_reached; i < (max_value_reached + EXTRA); i++) {
        searched = &i;
        rv = avl_tree_search(avlt, searched, &found);
        if ((rv == 0) || found) {
            not_fine++;
        } else {
            fine++;
        }
    }
    timer_end(&timr);
    timer_report(&timr, EXTRA, NULL);
    printf("expected %d, NOT expected %d\n", fine, not_fine);

    /* now search all data that should be found (all of them) */
    printf("now searching all %s numbers in the avl tree\n", oddness);
    fine = not_fine = 0;
    timer_start(&timr);
    for (i = 0; i < MAX_SZ; i++) {
        searched = &data[i];
        rv = avl_tree_search(avlt, searched, &found);

        if ((rv != 0) || (data[i] != *((int*) found))) {
            not_fine++;
        } else {
            fine++;
        }
    }
    timer_end(&timr);
    timer_report(&timr, MAX_SZ, NULL);
    printf("found %d as expected and %d as NOT expected\n", fine, not_fine);

    /* now search for all entries that should NOT be in the tree */
    printf("now searching for all %s numbers in the avl tree\n", reverse);
    fine = not_fine = 0;
    d = use_odd_numbers ? 0 : 1;
    timer_start(&timr);
    for (i = 0; i < MAX_SZ; i++) {
        searched = &d;
        rv = avl_tree_search(avlt, searched, &found);
        if ((rv == 0) || found) {
            not_fine++;
        } else {
            fine++;
        }
        d += 2;
    }
    timer_end(&timr);
    timer_report(&timr, MAX_SZ, NULL);
    printf("%d as expected and %d as NOT expected\n", fine, not_fine);

#if 0

int tree_nodes = avlt->n;
printf("now deleting the whole tree (%d nodes)\n", tree_nodes);
timer_start(&timr);
avl_tree_destroy(avlt);
timer_end(&timr);
timer_report(&timr, tree_nodes, NULL);
return;

#endif // 0

    /* now delete one entry at a time and search it (should not be there) */
    printf("now deleting and searching\n");
    fine = not_fine = fail_search = 0;
    timer_start(&timr);
    for (i = 0; i < MAX_SZ; i++) {
        searched =  &data[i];
        rv = avl_tree_remove(avlt, searched, &removed);
        if ((rv != 0) || (data[i] != *((int*) removed))) {
            not_fine++;
        } else {
            fine++;
        }
        rv = avl_tree_search(avlt, searched, &found);
        if ((rv == 0) || found) {
            fail_search++;
        }
    }
    timer_end(&timr);
    timer_report(&timr, MAX_SZ*2, NULL);
    printf("deleted %d, could NOT delete %d, erroneous search %d\n",
        fine, not_fine, fail_search);

    OBJECT_MEMORY_USAGE(avlt, bytes_used, megabytes_used);
    printf("total memory used by the avl tree (%d nodes) after deletes: "
        "%llu bytes (%f Mbytes)\n",
        avlt->n, bytes_used, megabytes_used);

    avl_tree_destroy(avlt);
}
Пример #24
0
void avl_tree_insert_elements ( void )
{
  IntBucket *a,*b,*c,*d,*e,*f,*g;
  a = malloc(sizeof(IntBucket));
  b = malloc(sizeof(IntBucket));
  c = malloc(sizeof(IntBucket));
  d = malloc(sizeof(IntBucket));
  e = malloc(sizeof(IntBucket));
  f = malloc(sizeof(IntBucket));
  g = malloc(sizeof(IntBucket));

  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);

  a->p = 99;
  b->p = 8;
  c->p = 7;
  d->p = 100;
  e->p = 101;
  f->p = 75;
  g->p = 90;

  avl_tree_insert ( t, a );
  ASSERT (t->root->count == 1, "Wrong count of children.");
  ASSERT (t->root->height == 1, "Root with no children has wrong height.");
  ASSERT (t->root->balance_factor == 0, "Root with no children has wrong balance factor.");

  avl_tree_insert ( t, b );
  ASSERT (t->root->count == 2, "Wrong count of children in root after inserting one child.");
  ASSERT (t->root->height == 2, "Wrong height for root with one child.");
  ASSERT (t->root->balance_factor == 1, "Root with one child has wrong balance factor.");
  ASSERT (t->root->left->count == 1, "Child has wrong count.");
  ASSERT (t->root->left->height == 1, "Child has wrong height.");
  ASSERT (t->root->left->balance_factor == 0, "Node with no children has wrong balance factor.");
  ASSERT (t->root->left->parent == t->root, "Left child has wrong parent after first insert.");

  ASSERT ( ((IntBucket*)(t->root->bucket))->p == 99, "Wrong value for root" );
  ASSERT ( ((IntBucket*)(t->root->left->bucket))->p == 8, "Wrong value for left child" );

  avl_tree_insert(t,c); // ROOT->LEFT->LEFT, should get balance
  ASSERT ( ((IntBucket*)(t->root->bucket))->p == 8, "Wrong root after insert requiring rotate");
  ASSERT ( ((IntBucket*)(t->root->right->bucket))->p == 99, "Wrong root after insert requiring rotate");
  ASSERT ( ((IntBucket*)(t->root->left->bucket))->p == 7, "Wrong root after insert requiring rotate");

  ASSERT (t->root->left->parent == t->root, "Left has wrong parent after rebalance.");
  ASSERT (t->root->right->parent == t->root, "Right has wrong parent after rebalance.");

  ASSERT(t->root->count==3, "Wrong count of children at root after 2nd insert");
  ASSERT(t->root->height==2, "Wrong height after 2nd insert");
  ASSERT(t->root->balance_factor==0, "Wrong balance factor after 2nd insert");
  ASSERT(t->root->left->count==1, "Wrong child count after 2nd insert");
  ASSERT(t->root->left->height==1, "Wrong child height after 2nd insert");
  ASSERT(t->root->left->balance_factor==0, "Wrong child balance factor after 2nd insert");

  avl_tree_insert(t,d);
  ASSERT(t->root->balance_factor == -1, "Wrong balance");
  avl_tree_insert(t,e);
  ASSERT(t->root->balance_factor == -1, "Wrong balance");
  ASSERT(t->root->height == 3, "Wrong height");
  avl_tree_insert(t,f);
  avl_tree_insert(t,g);
  ASSERT(t->root->count == 7, "wrong count");

  destroy_avl_tree(t);

  free(g);
  free(f);
  free(e);
  free(d);
  free(c);
  free(b);
  free(a);
}
Пример #25
0
void avl_tree_insert_many ( void )
{
  AVLTree * t = init_avl_tree(sizeof(IntBucket), &bucket_int_compare);

  int insert_qty = 13;

  IntBucket ib[] = {
    {30272}, {16274}, {11768}, {10231}, {28474}, { 7272}, {15032}, {13196}, {29825}, { 6840},
    {18444}, {18793}, {13786}, {21125}, {25311}, {23414}, {18374}, {24110}, {15465}, {26300},
    { 1181}, { 6297}, { 3693}, {20957}, {22585}, { 8915}, {30371}, { 2036}, {18499}, {18391},
    {15360}, {32509}, {23336}, {18848}, {25712}, { 6162}, { 1483}, { 4309}, {13482}, {14809},
    { 5596}, {22524}, {13958}, {16918}, {25668}, {31621}, {30060}, {24637}, {28116}, {15994},
    {30595}, {30642}, {30017}, { 7221}, { 2916}, { 7010}, {29356}, {22282}, {30649}, {17493},
    {28780}, { 6725}, {26998}, {28805}, {24689}, {25547}, {17625}, {14250}, {11250}, {16195},
    { 9542}, {26029}, { 2734}, {23373}, {21176}, {28102}, { 1894}, {  325}, { 9406}, { 4915},
    { 8759}, {32413}, {14144}, { 5394}, { 3495}, {32030}, {23904}, { 4260}, {11579}, {11100},
    {27212}, {20562}, {30264}, {30850}, {22393}, {28107}, {21299}, {25306}, { 2668}, { 3894},
  };

  int i;

  /*
  avl_tree_insert(t, ib+0);
  ASSERT( ((IntBucket*)t->root->bucket)->p == 30272, "Wrong value in root after first insert");
  ASSERT(t->root->count == 1, "Wrong count after first insert");
  ASSERT(t->root->height == 1, "Wrong height after first insert");
  ASSERT(t->root->balance_factor == 0, "Wrong balance factor after first insert");
  ASSERT(t->root->multiplicity == 1, "Wrong multiplicity after first insert");
  ASSERT(t->root->left == NULL, "Left not NULL after first insert");
  ASSERT(t->root->right == NULL, "Right not NULL after first insert");
  ASSERT(t->root->parent == NULL, "Root node parent not NULL");
  ASSERT(avl_verify_consistency(t, t->root)==true, "Tree inconsistent after inserting");

  avl_tree_insert(t, ib+1);
  ASSERT( ((IntBucket*)t->root->bucket)->p == 30272, "Wrong value in root after second insert");
  ASSERT( ((IntBucket*)t->root->left->bucket)->p == 16274, "Wrong value in root after second insert");
  ASSERT(t->root->count == 2, "Wrong count after second insert");
  ASSERT(t->root->height == 2, "Wrong height after second insert");
  ASSERT(t->root->balance_factor == 1, "Wrong balance factor after second insert");
  ASSERT(t->root->left != NULL, "no left child after second insert");
  ASSERT(t->root->right == NULL, "right child exists after second insert");
  ASSERT(t->root->left->parent == t->root, "Left child has wrong parent after second insert");
  ASSERT(avl_verify_consistency(t, t->root)==true, "Tree inconsistent after inserting");
  */

  for (i = 0; i < insert_qty; i += 1) {
    avl_tree_insert(t, &(ib[i]));
    // fprintf(stderr, "%d: %d\n", i, ib[i].p);
    ASSERT(avl_verify_consistency(t, t->root)==true, "Tree inconsistent after inserting");
  }

  ASSERT(t->root->height == 5, "Wrong height after 13 inserts");
  ASSERT(t->root->balance_factor = 1, "Wrong balance factor after 13 inserts");
  ASSERT(t->root->count == 13, "Wrong count after 13 inserts");
  ASSERT( ((IntBucket*)t->root->left->bucket)->p == 10231, "Wrong");
  ASSERT( ((IntBucket*)t->root->left->left->bucket)->p == 7272, "Wrong");
  ASSERT( ((IntBucket*)t->root->left->left->left->bucket)->p == 6840, "Wrong");
  ASSERT( ((IntBucket*)t->root->left->right->bucket)->p == 13196, "Wrong");
  ASSERT( ((IntBucket*)t->root->left->right->left->bucket)->p == 11768, "Wrong");
  ASSERT( ((IntBucket*)t->root->left->right->right->bucket)->p == 15032, "Wrong");
  ASSERT( ((IntBucket*)t->root->left->right->right->left->bucket)->p == 13786, "Wrong");

  ASSERT( ((IntBucket*)t->root->right->bucket)->p == 29825, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->left->bucket)->p == 18793, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->left->left->bucket)->p == 18444, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->left->right->bucket)->p == 28474, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->right->bucket)->p == 30272, "Wrong");

  avl_tree_insert(t, ib+i);
  ASSERT( ((IntBucket*)t->root->right->bucket)->p == 28474, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->left->bucket)->p == 18793, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->left->left->bucket)->p == 18444, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->left->right->bucket)->p == 21125, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->right->bucket)->p == 29825, "Wrong");
  ASSERT( ((IntBucket*)t->root->right->right->right->bucket)->p == 30272, "Wrong");

  ASSERT(avl_verify_consistency(t, t->root) == true, "Inconsistent after insert 14");

  for (; i < 100; i += 1) {
    avl_tree_insert(t, &(ib[i]));
    // fprintf(stderr, "%d: %d\n", i, ib[i].p);
    ASSERT(avl_verify_consistency(t, t->root)==true, "Tree inconsistent after inserting");
  }

  destroy_avl_tree(t);
}
Пример #26
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;
}