⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btree.c

📁 基于btree索引算法的数据库代码
💻 C
📖 第 1 页 / 共 5 页
字号:

	if(NULL == pg)
		return NULL;

	node = (btree_node *)PageHeadGetUserData(pg);

	assert((!node->init_flag && !node->parent) || node->init_flag);

	if(parent)
	{
		assert(parent->init_flag);

		if(parent != node->parent)
		{
			if(node->parent)
				btree_mgr_release_node(node->parent);

			btree_mgr_ref_node(parent);

			node->parent = parent;
		}

		node->idx_in_parent_cellarray = idx_in_parent;
	}
	else
	{
		assert(!(node->node_flag & e_btree_page_flag_leaf) || NULL == node->parent);

		if(node->parent)
			btree_mgr_release_node(node->parent);

		node->idx_in_parent_cellarray = 0;
		node->parent = NULL;
	}

	assert(PageHeadGetUserDataSize(pg) == sizeof(*node));

	/* 如果已经初始化过了,不用再做这些操作 */
	if(node->init_flag)
		return node;

	node->pg = pg;
	node->pg_no = pgno;

	node->read_buf = (unsigned char *)PageHeadMakeReadable(pg);
	node->btree_mgr = btree_mgr;

	assert(node->read_buf);
	assert(PagePtrIsInpage(node->pg, node->read_buf));

	btree_mgr_init_node(node, b_new);

	node->init_flag = 1;

	return node;
}

/**
 * @brief 获取一个节点
 */
#define btree_mgr_get_node_new(__btr_mgr, __pgno, __parent, __idx_in_parent) \
	btree_mgr_get_node_aux(__btr_mgr, __pgno, __parent, __idx_in_parent, 0, 1)

/**
 * @brief 获取一个节点
 */
#define btree_mgr_get_node(__btr_mgr, __pgno, __parent, __idx_in_parent) \
	btree_mgr_get_node_aux(__btr_mgr, __pgno, __parent, __idx_in_parent, 0, 0)

/**
 * @brief 获取一个缓存中节点,不在缓存中,则失败返回
 */
#define btree_mgr_get_cached_node(__btr_mgr, __pgno, __parent, __idx_in_parent) \
	btree_mgr_get_node_aux(__btr_mgr, __pgno, __parent, __idx_in_parent, 1, 0)

/**
 * @brief 销毁一个节点,对这个节点的承载页引用计数减少1
 */
static __INLINE__ int btree_mgr_delete_node(btree_node * node)
{
	unsigned int pgno = 0;
	assert(node && node->pg_no);
	assert(node->btree_mgr && node->btree_mgr->hpgr);

	pgno = node->pg_no;
	btree_mgr_release_node(node);

	if(0 != PagerReleasePageNo(node->btree_mgr->hpgr, pgno))
		return -1;

	return 0;
}

/**
 * @brief 向pager申请一页,创建一个新的节点
 */
static __INLINE__ btree_node * btree_mgr_new_node(btree_mgr_t * btree_mgr, btree_node * parent, int idx_in_parent, unsigned char node_flag)
{
	unsigned int pgno = 0;
	btree_node * node = NULL;

	assert(btree_mgr && btree_mgr->hpgr);

	pgno = PagerGetPageNo(btree_mgr->hpgr);
	if(0 == pgno)
		return NULL;

	node = btree_mgr_get_node_new(btree_mgr, pgno, parent, idx_in_parent);

	assert(btree_mgr->pg_sz - BTREE_HDR_SZ == node->nfree);
	assert(0 == node->ncell);

	if(NULL == node)
	{
		PagerReleasePageNo(btree_mgr->hpgr, pgno);
		return NULL;
	}

	if(0 != btree_mgr_set_nodeflag(node, node_flag))
	{
		btree_mgr_delete_node(node);
		return NULL;
	}

	return node;
}

/**
 * @brief 将游标加入链表
 */
static __INLINE__ int btree_mgr_add_to_cursor_list(btree_mgr_t * btree_mgr, btree_cursor * cursor)
{
	assert(btree_mgr && cursor);
	assert(btree_mgr == cursor->btree_mgr);
	assert(NULL == cursor->cursor_next && NULL == cursor->cursor_prev);

	if(NULL == btree_mgr->cursor_lst)
	{
		btree_mgr->cursor_lst = cursor;
		return 0;
	}

	cursor->cursor_next = btree_mgr->cursor_lst;
	btree_mgr->cursor_lst->cursor_prev = cursor;

	btree_mgr->cursor_lst = cursor;

	return 0;
}

/**
 * @brief 将游标从链表中脱离
 */
static __INLINE__ int btree_mgr_out_of_cursor_list(btree_mgr_t * btree_mgr, btree_cursor * cursor)
{
	assert(btree_mgr && cursor);
	assert(btree_mgr == cursor->btree_mgr);
	assert(cursor->cursor_next || cursor->cursor_prev || cursor == btree_mgr->cursor_lst);

	if(cursor == btree_mgr->cursor_lst)
		btree_mgr->cursor_lst = cursor->cursor_next;

	if(cursor->cursor_prev)
		cursor->cursor_prev->cursor_next = cursor->cursor_next;

	if(cursor->cursor_next)
		cursor->cursor_next->cursor_prev = cursor->cursor_prev;

	cursor->cursor_prev = NULL;
	cursor->cursor_next = NULL;

	return 0;
}

/**
 * @brief 创建的一个游标
 */
static __INLINE__ int btree_mgr_release_cursor(btree_cursor * cursor)
{
	assert(cursor && cursor->btree_mgr);

	btree_mgr_release_node(cursor->cur_node);

	/* 从链表中脱离 */
	assert(cursor->cursor_next || cursor->cursor_prev || cursor == cursor->btree_mgr->cursor_lst);
	btree_mgr_out_of_cursor_list(cursor->btree_mgr, cursor);

	MyMemPoolFree(cursor->btree_mgr->hm, cursor);

	return 0;
}

/**
 * @brief 创建的一个游标
 */
static __INLINE__ btree_cursor * btree_mgr_alloc_cursor(btree_mgr_t * btree_mgr,
														XCOMPARE cmp,
														const void * context, unsigned int context_sz)
{
	btree_cursor * cursor = NULL;
	assert(btree_mgr);

	cursor = MyMemPoolMalloc(btree_mgr->hm, sizeof(*cursor));
	if(NULL == cursor)
		return NULL;

	cursor->btree_mgr = btree_mgr;

	cursor->context = (void *)context;
	cursor->context_sz = context_sz;
	cursor->key_cmp = cmp;
	assert(cursor->key_cmp);

	cursor->cursor_next = NULL;
	cursor->cursor_prev = NULL;

	cursor->root_pgno = 0;
	cursor->idx = 0;
	cursor->cur_node = NULL;

	cursor->err = 0;

	/* 加入游标链表 */
	btree_mgr_add_to_cursor_list(btree_mgr, cursor);

	return cursor;
}

/**
 * @brief 将游标移至根节点
 */
static int btree_mgr_move_to_root(btree_cursor * cursor)
{
	btree_node * root_node = NULL;

	assert(cursor && cursor->btree_mgr);
	assert(cursor->root_pgno && cursor->cur_node);

	if(cursor->root_pgno == cursor->cur_node->pg_no)
	{
		assert(NULL == cursor->cur_node->parent);
		assert(cursor->cur_node->init_flag);

		return 0;
	}

	root_node = btree_mgr_get_node(cursor->btree_mgr, cursor->root_pgno, NULL, 0);
	if(NULL == root_node)
		return -1;

	btree_mgr_release_node(cursor->cur_node);

	cursor->cur_node = root_node;

	cursor->idx = 0;

	return 0;
}

/**
 * @brief 销毁btree管理器
 */
static int btree_mgr_destroy(btree_mgr_t * btree_mgr)
{
	btree_cursor * cursor;

	assert(btree_mgr);

	/* 释放所有游标 */
	cursor = btree_mgr->cursor_lst;
	while(cursor)
	{
		btree_mgr_release_cursor(cursor);
		cursor = btree_mgr->cursor_lst;
	}

	/* 销毁pager */
	if(btree_mgr->hpgr)
		PagerDestruct(btree_mgr->hpgr);

	/* 释放自己 */
	MyMemPoolFree(btree_mgr->hm, btree_mgr);

	return 0;
}

/**
 * @brief 去除ovfl信息
 */
#define btree_mgr_clear_ovfl(__n) do{\
		(__n)->has_cell_ovfl = 0;\
		MyBufferDestruct((__n)->cell_ovfl.cell_buf);\
		(__n)->cell_ovfl.cell_buf = NULL;\
	}while(0)

/**
 * @brief 页析构回调函数 
 */
static int btree_page_release(HPAGE_HEAD pg)
{
	btree_node * node = NULL;

	/* LOG_DEBUG(("btree_page_release")); */

	/* 引用计数为一定为零 */
	assert(PagerGetPageRefCount(pg) == 0);
	assert(sizeof(*node) == PageHeadGetUserDataSize(pg));

	node = PageHeadGetUserData(pg);
	assert(node);

	if(!node->init_flag)
	{
		assert(NULL == node->parent);
		assert(NULL == node->cell_ovfl.cell_buf);
		return 0;
	}

	/* 取消对父节点的引用 */
	if(node->parent)
	{
		btree_node * parent = node->parent;
		node->parent = NULL;
		btree_mgr_release_node(parent);
	}

	/* cell_ovfl里的buffer要释放,因为没有引用了,否则会造成内存泄漏 */
	btree_mgr_clear_ovfl(node);

	/* 初节点的初始化标志置成0 */
	node->init_flag = 0;

	return 0;
}

/**
 * @brief 页重新载入回调函数
 */
static int btree_page_reload(HPAGE_HEAD pg)
{
	btree_node * node = NULL;

	LOG_DEBUG(("btree_page_reload"));

	assert(sizeof(*node) == PageHeadGetUserDataSize(pg));

	node = PageHeadGetUserData(pg);

	assert(node);

	/* 将节点页里的信息重新读一遍 */
	btree_mgr_init_node(node, 0);

	return 0;
}


/**
 * @brief 创建btree
 * @param pg_sz:btree 的 page size,可为0
 * @param cache_pg_count:btree页缓存最大值,可为0;
 * @param sector_sz:OS扇区的大小,可为0
 * @param rand_seed:随机数初始化种子
 * @param rand_seed_sz:rand_seed所指缓冲区的大小
 * @param user_rate:页文件使用率,可为0
 */
HBTREE_MGR btreeMgrConstruct(HMYMEMPOOL hm,
							 const char * page_file_name,
							 unsigned int pg_sz,
							 unsigned int cache_pg_count,
							 unsigned int sector_sz,
							 void * rand_seed,
							 unsigned int rand_seed_sz)
{
	btree_mgr_t * btree_mgr = NULL;
	if(NULL == page_file_name)
		return NULL;

	btree_mgr = MyMemPoolMalloc(hm, sizeof(*btree_mgr));
	if(NULL == btree_mgr)
		return NULL;

	btree_mgr->hm = hm;
	btree_mgr->pg_sz = pg_sz;
	btree_mgr->hpgr = PagerConstruct(hm,
		page_file_name,
		btree_page_release, btree_page_reload,
		sizeof(btree_node), cache_pg_count, &(btree_mgr->pg_sz),
		rand_seed, rand_seed_sz,
		sector_sz);

	if(NULL == btree_mgr->hpgr)
		goto btreeMgrConstruct_end_;

	/*
	* 记录溢出时,在本页存储的大小上限与下限
	* max_local应为page_sz的1/10,
	*/
	assert(btree_mgr->pg_sz / BTREE_PERCENT > (BTREE_CELL_PTR_SIZE + BTREE_CELL_HDR_SZ));

	btree_mgr->max_local = (((btree_mgr->pg_sz - BTREE_HDR_SZ) / BTREE_PERCENT 
		- (BTREE_CELL_PTR_SIZE + BTREE_CELL_HDR_SZ)) / SYS_ALIGNMENT) * SYS_ALIGNMENT;
	btree_mgr->min_local = ((btree_mgr->max_local / 2) / SYS_ALIGNMENT) * SYS_ALIGNMENT;

	btree_mgr->pg_min_fill_sz = ((btree_mgr->pg_sz - BTREE_HDR_SZ) * BTREE_FILL_RATE) / BTREE_PERCENT;
	assert(btree_mgr->pg_min_fill_sz > BTREE_HDR_SZ + btree_mgr->max_local);

	assert(btree_mgr->max_local >= 2 * BTREE_CELL_MIN_SZ);
	assert(btree_mgr->min_local >= 2 * BTREE_CELL_MIN_SZ);

	/* 游标链表头置空 */
	btree_mgr->cursor_lst = NULL;
	return btree_mgr;

btreeMgrConstruct_end_:

	btree_mgr_destroy(btree_mgr);
	return NULL;
}

/**
 * @brief 销毁btree
 */
int btreeMgrDestruct(HBTREE_MGR hbtreeMgr)
{
	if(hbtreeMgr)
		return btree_mgr_destroy(hbtreeMgr);

	return -1;
}

/**
 * @brief 释放游标 与btreeMgrGetCursor是对偶操作
 */
int btreeMgrReleaseCursor(HBTREE_CURSOR hcur)
{
	if(NULL == hcur || NULL == hcur->btree_mgr)
		return -1;

	btree_mgr_release_cursor(hcur);
	return 0;
}

/**
 * @brief 从cell里取出data
 */
static __INLINE__ int btree_mgr_cell_get_data(btree_node * node,
											  btree_cellinfo * cell_info,
											  unsigned char * data, unsigned int data_sz)
{
	unsigned int key_sz_left = 0;
	unsigned int pgno_ovfl = 0;
	HPAGE_HEAD pg_ovfl = NULL;
	const unsigned char * rb = NULL;

	assert(cell_info);

	if(!(node->node_flag & e_btree_page_flag_hasdata))
		return 0;

	assert(data && data_sz >= cell_info->data_sz);
	data_sz = cell_info->data_sz;

	/* 如果没有发生溢出,拷贝返回 */
	if(cell_info->local_sz == cell_info->payload_sz)
	{
		assert(((sizeof(unsigned int)) * ((node->node_flag & e_btree_page_flag_leaf) ? 0 : 1 ) + 
			4 * ((node->node_flag & e_btree_page_flag_hasdata) ? 1 : 0) + 4) == cell_info->head_sz);

		memcpy(data, 
			cell_info->cell + cell_info->head_sz + cell_info->key_sz * ((node->node_flag & e_btree_page_flag_intkey) ? 0 : 1),
			cell_info->data_sz);

		return 0;
	}

	assert(node && node->btree_mgr);

	if(cell_info->key_sz > cell_info->local_sz && !(node->node_flag & e_btree_page_flag_intkey))
	{
		key_sz_left = cell_info->key_sz - cell_info->local_sz;

		pgno_ovfl = cell_info->overflow_pgno;

		/* 跳过key所占有的区域 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -