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

📄 btree.c

📁 sourceforge历史版本完整下载: http://sourceforge.net/project/showfiles.php?group_id=202044 提供了基于b树索引算法的文件数据数据
💻 C
📖 第 1 页 / 共 5 页
字号:
		if(0 == space_left)		{			/* 如果空间不够,分配一页over flow */			unsigned int pgno = PagerGetPageNo(btree_mgr->hpgr);			if(0 == pgno)			{				ret = -1;				goto btree_mgr_pack_cell_end_;/* 取消对某些节点的引用 */			}			if(pg_ovfl)				PagerReleasePage(pg_ovfl);			pg_ovfl = PagerGetPage(btree_mgr->hpgr, pgno);			if(NULL == pg_ovfl)			{				ret = -1;				PagerReleasePageNo(btree_mgr->hpgr, pgno);				goto btree_mgr_pack_cell_end_;			}			pPayload = (unsigned char *)PageHeadMakeWritable(pg_ovfl);			if(NULL == pPayload)			{				ret = -1;				PagerReleasePageNo(btree_mgr->hpgr, pgno);				goto btree_mgr_pack_cell_end_;			}			assert(pPrior);			/* 将溢出页号写入预留的内存空间 */			uint_to_big_endian(pgno, pPrior, sizeof(unsigned int));			pPrior = pPayload;			pPayload += BTREE_OVERFLOW_HDR_SZ;			space_left = btree_mgr->pg_sz - BTREE_OVERFLOW_HDR_SZ;		}		if(Src_sz > space_left)			n = space_left;		else			n = Src_sz;		memcpy(pPayload, pSrc, n);		space_left -= n;		pPayload += n;		Src_sz -= n;		pSrc += n;		payload_sz -= n;		if(0 == Src_sz && payload_sz)		{			Src_sz = data_sz;			pSrc = (unsigned char *)data;		}	}btree_mgr_pack_cell_end_:	if(pg_ovfl)		PagerReleasePage(pg_ovfl);	if(pPrior)	{		assert(pPrior != cell);		uint_to_big_endian(0, pPrior, sizeof(unsigned int));	}	return ret;	}/** * @brief 游标当前所指的位置的cell信息 */static __INLINE__ int btree_mgr_get_cell(btree_cursor * cursor, btree_cellinfo * cellinfo){	assert(cursor && cursor->cur_node && cursor->root_pgno && cellinfo);	assert(cursor->cur_node->pg && cursor->cur_node->pg_no);	/* 取出cell"指针" */	/* 根据cell"指针"取出cell的内容 */	btree_mgr_parse_idx(cursor->cur_node, cursor->idx, cellinfo);	return 0;}/** * @brief 查找cell的回调函数 *  > 0  表示 key 大于 data *  == 0 表示 key 等于 data *  < 0  表示 key 小于 data * * @param key:关键字 * @param key_sz:关键字的缓冲区大小 * @param context:用户自定义的上下文数据 * @param context_sz:用户自定义的上下文数据的长度 */static int binarysearch_compare(const void * key, unsigned int key_sz,								const void * data,								const void * context, unsigned int context_sz){	unsigned char * cell_key = NULL;	btree_cursor * cursor = (btree_cursor *)context;	unsigned int cell_ptr = 0;	btree_cellinfo cell_info;	assert(cursor && context_sz == sizeof(*cursor));	assert(PagePtrIsInpage(cursor->cur_node->pg, data));	get_2byte((unsigned char *)data, BTREE_CELL_PTR_SIZE, cell_ptr);	btree_mgr_parse_cellptr(cursor->cur_node, cell_ptr, &cell_info);	if(cursor->cur_node->node_flag & e_btree_page_flag_intkey)	{		btree_mgr_cell_get_key(cursor->cur_node, &cell_info, NULL, 0);		return cursor->key_cmp(key, key_sz,			NULL, cell_info.key_sz,			cursor->context, cursor->context_sz);	}	else	{		int ret = 0;		cell_key = MyMemPoolMalloc(cursor->btree_mgr->hm, cell_info.key_sz);		if(0 != btree_mgr_cell_get_key(cursor->cur_node, &cell_info, cell_key, cell_info.key_sz))		{			cursor->err = -1;			ret = 0;		}		else		{			ret = cursor->key_cmp(key, key_sz, 				cell_key, cell_info.key_sz,				cursor->context, cursor->context_sz);		}		MyMemPoolFree(cursor->btree_mgr->hm, cell_key);		return ret;	}}/** * @brief 获取right most */#define btree_mgr_get_rmost(_n, _rm) do{\		assert(_n);\		assert(!(_n->node_flag & e_btree_page_flag_leaf));\		assert(_n->read_buf == PageHeadMakeReadable(_n->pg));\		array_to_uint_as_big_endian(&_n->read_buf[BTREE_HDR_MOST_RIGHT_CHILD_OFFSET], sizeof(unsigned int), _rm);\		assert(_rm);\	}while(0)/** * @brief 查找关键值 * @param pres:0表示找到了关键字 *         大于零:表示没找到关键字 *         小于零:表示没找到关键字 *         如果 序列为 1 3 4 查找 2  */static __INLINE__ int btree_mgr_search(btree_cursor * cursor, const void * key, const unsigned int key_sz, int * pres){	int ret = 0;	unsigned int pgno_child = 0;	btree_mgr_t * btree_mgr = NULL;	btree_node * sub_node = NULL;	btree_cellinfo cell_info;	assert(cursor && cursor->btree_mgr && cursor->cur_node);	assert(cursor->cur_node->btree_mgr == cursor->btree_mgr);	assert(pres);	btree_mgr = cursor->btree_mgr;	/* 将游标移至根节点 */	if(0 != btree_mgr_move_to_root(cursor))		return -1;	assert(cursor->cur_node->init_flag);	assert(cursor->cur_node->pg_no == cursor->root_pgno);	while(1)	{		/* 在当前节点里做二分查找 */		const unsigned char * rbuf = cursor->cur_node->read_buf;		assert(PagePtrIsInpage(cursor->cur_node->pg, &rbuf[BTREE_CELL_PTR_OFFSET]));		assert(PagePtrIsInpage(cursor->cur_node->pg, 			rbuf + BTREE_CELL_PTR_OFFSET + cursor->cur_node->ncell * BTREE_CELL_PTR_SIZE - 1));		if(0 == cursor->cur_node->ncell)		{			/* 如果没有cell,直接返回即可 */			assert(NULL == cursor->cur_node->parent);			assert(cursor->cur_node->node_flag & e_btree_page_flag_leaf);			*pres = 1;			return 0;		}		/* 如果找到,返回 */		ret = MyBinarySearch(&rbuf[BTREE_CELL_PTR_OFFSET], cursor->cur_node->ncell, BTREE_CELL_PTR_SIZE,			key, key_sz, binarysearch_compare,			&cursor->idx, cursor, sizeof(*cursor));		if(0 != cursor->err)		{			/* 如果出错 */			cursor->err = 0;			return -1;		}		if(0 == ret)		{			/* 如果找到 */			*pres = 0;			return 0;		}		if(cursor->cur_node->node_flag & e_btree_page_flag_leaf)		{			/* 如果当前已经是叶节点,则返回 */			*pres = ret;			return 0;		}		/* 根据"指针"去取cell信息 */		if(cursor->idx < cursor->cur_node->ncell)		{			btree_mgr_get_cell(cursor, &cell_info);			pgno_child = cell_info.lchild_pgno;		}		else			btree_mgr_get_rmost(cursor->cur_node, pgno_child);		assert(pgno_child);		/* 找不到,进入相应的子分支继续查找 */		sub_node = btree_mgr_get_node(cursor->btree_mgr,			pgno_child,			cursor->cur_node,			cursor->idx);		assert(sub_node->parent == cursor->cur_node);		if(NULL == sub_node)			return -1;		btree_mgr_release_node(cursor->cur_node);		cursor->cur_node = sub_node;		assert(PagerGetPageRefCount(cursor->cur_node->pg) && PagerGetPageRefCount(cursor->cur_node->parent->pg));	}	*pres = ret;	return 0;}/** * @brief 整理某一个节点的空闲碎片 */static __INLINE__ int btree_mgr_defrag_node(btree_node * node){	/* 记录备份的content存储区域的指针 */	unsigned char * content_new = NULL;	unsigned int new_cell_ptr = 0;	/* 记录整理碎片前的content起始 */	unsigned int content_begin = 0;	/* 在回拷过程中的临时变量,记录cell的"指针" */	unsigned int cell_ptr = 0;	/* 临时存储某个cell的信息 */	btree_cellinfo cell_info;	unsigned char * write_buf = NULL;	unsigned int i = 0;	assert(node);	/*	* 将节点内的cell content备份起来	* 轮循cell ptr数组,将里头的内容顺次解析拷贝.	* 重置相应的值first_free,cell_content,nfrag	*/	write_buf = PageHeadMakeWritable(node->pg);	if(NULL == write_buf)		return -1;	get_2byte(&(write_buf[BTREE_HDR_FIRST_CONTENT]), BTREE_CELL_PTR_SIZE, content_begin);	content_new = MyMemPoolMalloc(node->btree_mgr->hm, node->btree_mgr->pg_sz);	if(NULL == content_new)		return -1;	/* 开始循环 */	content_new += node->btree_mgr->pg_sz;	new_cell_ptr = node->btree_mgr->pg_sz;	for(i = 0; i < node->ncell; i ++)	{		btree_mgr_find_cellptr(node, i, cell_ptr);		assert(cell_ptr);		/* 解析相应的cell信息 */		btree_mgr_parse_cellptr(node,cell_ptr, &cell_info);		assert(new_cell_ptr > (BTREE_CELL_PTR_OFFSET + node->ncell * BTREE_CELL_PTR_SIZE + node->nfree));		/* 拷贝回节点页缓存 */		content_new -= cell_info.cell_sz;		new_cell_ptr -= cell_info.cell_sz;		assert(new_cell_ptr);		assert(cell_ptr >= content_begin);		memcpy(content_new, &write_buf[cell_ptr], cell_info.cell_sz);		/* 更新相应的cell ptr */		put_2byte(new_cell_ptr, &write_buf[BTREE_CELL_PTR_OFFSET + i * BTREE_CELL_PTR_SIZE], BTREE_CELL_PTR_SIZE);	}	content_begin = new_cell_ptr;	/* 所有的free空间应都集中在gap里 */	assert((content_begin - node->nfree) == BTREE_CELL_PTR_OFFSET + node->ncell * BTREE_CELL_PTR_SIZE);	assert(content_begin <= node->btree_mgr->pg_sz);	memcpy(&write_buf[content_begin], content_new, node->btree_mgr->pg_sz - content_begin);	/*	* 重置相应的值first_free,cell_content,nfrag	* btree page head define	*   OFFSET   SIZE     DESCRIPTION	*      0       1      Flags. 1: intkey, 2: hasdata, 4: leaf	*      1       1      记录碎片的大小	*      2       2      byte offset to the first freeblock	*      4       2      number of cells on this page	*      6       2      first byte of the cell content area	*      8       4      Right child (the Ptr(N+1) value).  reserve on leaves.	*/	write_buf[BTREE_HDR_NFRAG_OFFSET] = 0;	put_2byte(0, &write_buf[BTREE_HDR_FIRST_FREE_OFFSET], BTREE_CELL_PTR_SIZE);	put_2byte(content_begin,		&write_buf[BTREE_HDR_FIRST_CONTENT],		BTREE_CELL_PTR_SIZE);	assert(content_new);	MyMemPoolFree(node->btree_mgr->hm, content_new - content_begin);	return 0;}/** * @brief 当指定偏移的页内存储空间归还,与btree_mgr_alloc_space是对偶操作 */static __INLINE__ int btree_mgr_free_space(btree_node * node, unsigned int ptr, const unsigned int sz){	/*	* 如果ptr恰好紧跟在gap之后,则不需要加入free"链表",	* 顺着链表前进,直到链表时的free_ptr大于ptr为止,将ptr加入链表,此时要注意判断是否可以合差相邻的合闲块	* 更新nfree值,	* 根据需要更新first content与first free	*/	unsigned int content = 0;	unsigned int cur_free = 0;	unsigned int pre_free_store = 0;	unsigned int next_sz = 0;	unsigned char * wb = PageHeadMakeWritable(node->pg);	assert(node && ptr && sz);	if(NULL == wb)		return -1;	get_2byte(&wb[BTREE_HDR_FIRST_CONTENT], BTREE_CELL_PTR_SIZE, content);	/* 如果ptr紧挨着content,则将它并入content */	if(ptr == content)	{		content = ptr + sz;		/* 看看是否还可以合并更多的合闲块 */		get_2byte(&wb[BTREE_HDR_FIRST_FREE_OFFSET], BTREE_CELL_PTR_SIZE, cur_free);		while(cur_free)		{			unsigned int temp;			unsigned int temp_sz;			if(content != cur_free)				break;			get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short), temp_sz);			content = cur_free + temp_sz;			get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_NEXT_OFFSET], sizeof(unsigned short), temp);			cur_free = temp;		}		put_2byte(content, &wb[BTREE_HDR_FIRST_CONTENT], BTREE_CELL_PTR_SIZE);		put_2byte(cur_free, &wb[BTREE_HDR_FIRST_FREE_OFFSET], BTREE_CELL_PTR_SIZE);		goto btree_mgr_free_space_end_;	}	get_2byte(&wb[BTREE_HDR_FIRST_FREE_OFFSET], BTREE_CELL_PTR_SIZE, cur_free);	/* 寻找ptr应加入的位置 */	pre_free_store = 0;	while(cur_free)	{		unsigned int temp;		if(cur_free > ptr)			break;		pre_free_store = cur_free + BTREE_FREE_BLOCK_NEXT_OFFSET;		get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_NEXT_OFFSET], BTREE_CELL_PTR_SIZE, temp);		cur_free = temp;	}	/* 将ptr加入"链表" */	if(pre_free_store)	{		unsigned int pre_sz = 0;		unsigned int total_sz = 0;		get_2byte(&wb[pre_free_store + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short), pre_sz);		if(pre_free_store + pre_sz == ptr)		{			/* 可以与前一块合并 */			total_sz = pre_sz + sz;			/* 是否可以三块都合并 */			if(ptr + sz == cur_free && cur_free)			{				/* 记录合并后的下一个空闲块的索引 */				unsigned int cur_free_next = 0;				get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short), next_sz);				total_sz += next_sz;				get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_NEXT_OFFSET], sizeof(unsigned short), cur_free_next);				put_2byte(cur_free_next, &wb[pre_free_store + BTREE_FREE_BLOCK_NEXT_OFFSET], sizeof(unsigned short));			}			put_2byte(total_sz, &wb[pre_free_store + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short));			goto btree_mgr_free_space_end_;		}		else		{			/* 前一块空闲内存next指向ptr */			put_2byte(ptr, &wb[pre_free_store + BTREE_FREE_BLOCK_NEXT_OFFSET], BTREE_CELL_PTR_SIZE);		}	}	else	{		put_2byte(ptr, &wb[BTREE_HDR_FIRST_FREE_OFFSET], BTREE_CELL_PTR_SIZE);	}	if(ptr + sz == cur_free)	{		/* 如果可以与下一个空闲块合并 */		unsigned int cur_next = 0;		get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short), next_sz);		get_2byte(&wb[cur_free + BTREE_FREE_BLOCK_NEXT_OFFSET], BTREE_CELL_PTR_SIZE, cur_next);				/* 填入下块空闲块,本空闲块的大小 */		put_2byte(cur_next, &wb[ptr + BTREE_FREE_BLOCK_NEXT_OFFSET], BTREE_CELL_PTR_SIZE);		put_2byte(sz + next_sz, &wb[ptr + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short));	}	else	{		/* 不能合并,则ptr的next域指向cur_free, 填入本空闲块的大小 */		put_2byte(cur_free, &wb[ptr + BTREE_FREE_BLOCK_NEXT_OFFSET], BTREE_CELL_PTR_SIZE);		put_2byte(sz, &wb[ptr + BTREE_FREE_BLOCK_SZ_OFFSET], sizeof(unsigned short));	}btree_mgr_free_space_end_:#ifdef _DEBUGmemset(&wb[ptr] + BTREE_FREE_BLOCK_MIN_SZ, 0, sz - BTREE_FREE_BLOCK_MIN_SZ);#endif	node->nfree += btree_mgr_cal_cell_real_fill_sz(sz);	assert(node->nfree <= node->btree_mgr->pg_sz - BTREE_CELL_PTR_OFFSET);	return 0;}/** * @brief 将一个node所存储的cell置成空 */static __INLINE__ int btree_mgr_clear_node(btree_node * node){	/* 将frag置成0,将ncell置成0,将content置到底部,将first free置成零 */	/* right most置成0 */

⌨️ 快捷键说明

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