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

📄 btree.c

📁 基于btree索引算法的数据库代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			{
				/* 记录合并后的下一个空闲块的索引 */
				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 _DEBUG
memset(&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 */

	unsigned char * wb = NULL;

	assert(node && node->btree_mgr);

	wb = PageHeadMakeWritable(node->pg);
	if(NULL == wb)
		return -1;

	node->ncell = 0;
	node->nfree = node->btree_mgr->pg_sz - BTREE_CELL_PTR_OFFSET;
	node->idx_changed = 1;
	
	memset(wb, 0, node->btree_mgr->pg_sz);

	wb[BTREE_HDR_NODEFLAG_OFFSET] = node->node_flag;

	btree_mgr_clear_ovfl(node);

	return 0;
}

/**
 * @brief 在页缓存内分配指定大小的存储空间,返回的时空间距离用户页缓存可用地址起始的偏移
 */
static __INLINE__ unsigned int btree_mgr_alloc_space(btree_node * node, unsigned int sz)
{
	/*
	* 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.
	*/

	/*
	* 页内空闲块定义
	*    SIZE    DESCRIPTION
	*      2     Byte offset of the next freeblock
	*      2     Bytes in this freeblock
	*/

	unsigned int free_idx = 0;
	unsigned int pc_prev = 0;
	unsigned int block_sz = 0;
	unsigned int ret_alloc = 0;
	unsigned int ret_idx = 0;

	/* cell"指针"的结束 */
	unsigned int cell_ptr_end = 0;
	/* cell content的起始 */
	unsigned int cell_content = 0;
	unsigned char * write_buf = NULL;

	assert(node && sz);
	assert(node->nfree >= sz + BTREE_CELL_PTR_SIZE);
	assert(0 == node->has_cell_ovfl);
	assert(node->read_buf == PageHeadMakeReadable(node->pg));

	write_buf = PageHeadMakeWritable(node->pg);
	if(NULL == write_buf)
		return 0;

	/*
	* 如果存在空间块,则从空间链表里搜索
	* 如果不存在空闲块,则从cell指针数组的未尾与 cell content之间的那段区域获取(以下简称gap)
	* 如果仍然获取不到,则应合并空闲碎片,
	* 从gap里分配需要的存储空间
	*/

	/* 至gap里分配,如果仍然分配不到,此时就需要进行空闲碎片整理 */
	cell_ptr_end = BTREE_CELL_PTR_OFFSET + BTREE_CELL_PTR_SIZE * node->ncell;
	get_2byte(&(write_buf[BTREE_HDR_FIRST_CONTENT]), BTREE_CELL_PTR_SIZE, cell_content);

	/* cell_content为0,说明是一个新的节点 */
	if(0 == cell_content)
		cell_content = node->btree_mgr->pg_sz;

	assert(cell_content >= cell_ptr_end);

	/* 为cell ptr数组的增长预留字节 */
	if((cell_content - cell_ptr_end) < BTREE_CELL_PTR_SIZE)
	{
		if(0 != btree_mgr_defrag_node(node))
			return 0;

		get_2byte(&(write_buf[BTREE_HDR_FIRST_CONTENT]), BTREE_CELL_PTR_SIZE, cell_content);
	}
	else
	{
		get_2byte(&write_buf[BTREE_HDR_FIRST_FREE_OFFSET], sizeof(unsigned short), free_idx);
		pc_prev = (unsigned int)BTREE_HDR_FIRST_FREE_OFFSET;

		assert(((cell_content < node->btree_mgr->pg_sz) && free_idx) || free_idx == 0);

		/* 如果空闲碎片小于BTREE_MAX_FRAG */
		if(write_buf[BTREE_HDR_NFRAG_OFFSET] < BTREE_MAX_FRAG)
		{
			while(free_idx)
			{
				get_2byte(&(write_buf[free_idx + BTREE_FREE_BLOCK_SZ_OFFSET]),
					sizeof(unsigned short),
					block_sz);

				assert(block_sz >= BTREE_FREE_BLOCK_MIN_SZ);

				if(block_sz >= sz)
				{
					if(block_sz < sz + BTREE_FREE_BLOCK_MIN_SZ)
					{
						/*
						* 如果剩余的内存不足4字节,无法形成一个空闲块"链表"节点
						* 则整个空闲块都分配出去,但空闲空间却只扣减相应的sz值,并相应增加nfrag的值
						* 当空闲碎片达到上限,此时进行碎片整理,释放出所有的空闲碎片,供分配使用
						*/
						memcpy(&(write_buf[pc_prev]), 
							&(write_buf[free_idx + BTREE_FREE_BLOCK_NEXT_OFFSET]),
							sizeof(unsigned short));

						assert((block_sz - sz) <= BTREE_FREE_BLOCK_MIN_SZ);

						assert(write_buf[BTREE_HDR_NFRAG_OFFSET] <= BTREE_MAX_FRAG);

						write_buf[BTREE_HDR_NFRAG_OFFSET] += (block_sz - sz);
					}
					else
					{
						/* 扣减相应的sz,返回 */
						put_2byte(block_sz - sz,
							&(write_buf[free_idx + BTREE_FREE_BLOCK_SZ_OFFSET]),
							sizeof(unsigned short));
					}

					/* 从空闲块的底部拿出一块来 */
					ret_idx = free_idx + block_sz - sz;
					goto btree_mgr_alloc_space_end_;
				}

				/* 循环继续 */
				pc_prev = free_idx + BTREE_FREE_BLOCK_NEXT_OFFSET;
				get_2byte(&(write_buf[free_idx + BTREE_FREE_BLOCK_NEXT_OFFSET]),
					sizeof(unsigned short),
					free_idx);
			}
		}
		else
		{
			/* 碎片超过上限了,进行碎片整理 */
			if(0 != btree_mgr_defrag_node(node))
				return 0;

			get_2byte(&(write_buf[BTREE_HDR_FIRST_CONTENT]), BTREE_CELL_PTR_SIZE, cell_content);
		}

		/* 如果仍然分配不到,需要进行空闲碎片整理 */
		if((cell_content - cell_ptr_end) < btree_mgr_cal_cell_real_fill_sz(sz))
		{
			if(0 != btree_mgr_defrag_node(node))
				return 0;

			get_2byte(&(write_buf[BTREE_HDR_FIRST_CONTENT]), BTREE_CELL_PTR_SIZE, cell_content);
		}
	}

	assert((cell_content - cell_ptr_end) >= btree_mgr_cal_cell_real_fill_sz(sz));

	ret_idx = cell_content - sz;
	put_2byte(ret_idx, &(write_buf[BTREE_HDR_FIRST_CONTENT]), BTREE_CELL_PTR_SIZE);

btree_mgr_alloc_space_end_:

	node->nfree -= btree_mgr_cal_cell_real_fill_sz(sz);
	return ret_idx;
}

/**
 * @brief 将一个cell吃进来
 */
static __INLINE__ int btree_mgr_eat_cell(btree_node * node,
										 unsigned int idx,
										 unsigned char * cell, unsigned int cell_sz)
{
	unsigned int ptr = 0;
	unsigned char * wb = NULL;
	unsigned int i = 0;
	unsigned int end = 0;
	unsigned int ins = 0;
	unsigned char * p = NULL;

	assert(node && cell && cell_sz);
	assert(idx <= node->ncell);
	assert(node->nfree >= (cell_sz + BTREE_CELL_PTR_SIZE));

	/* 空间足够,分配空间,存储 */
	ptr = btree_mgr_alloc_space(node, cell_sz);
	if(0 == ptr)
		return -1;

	wb = PageHeadMakeWritable(node->pg);
	if(NULL == wb)
		return -1;

	/* 存储cell内容 */
	memcpy(&wb[ptr], cell, cell_sz);

	/* 更改cell ptr数组 */
	end = BTREE_CELL_PTR_OFFSET + node->ncell * BTREE_CELL_PTR_SIZE;
	ins = BTREE_CELL_PTR_OFFSET + idx * BTREE_CELL_PTR_SIZE;
	for(i = end; i > ins; i -= BTREE_CELL_PTR_SIZE)
	{
		wb[i] = wb[i - 2];
		wb[i + 1] = wb[i - 1];
	}

	put_2byte(ptr, &wb[ins], BTREE_HDR_NCELL_SZ);

	/* 更改标识位idx_change */
	node->idx_changed = 1;

	return 0;
}

/**
 * @brief 将一个打包好的cell添加到指定的位置
 */
static __INLINE__ int btree_mgr_insert_cell(btree_node * node,
											unsigned int idx,
											unsigned char * cell, unsigned int cell_sz)
{
	/*
	* 如果该节点使用的页上的存储空间足够,
	* 则将新的cell拷进去
	* 如果不够,就挂在附加空间上,在之后的平衡过程里再拷贝进去
	*/

	unsigned char * wb = NULL;

	assert(node && cell && cell_sz);
	assert(0 == node->has_cell_ovfl);
	assert(idx <= node->ncell);

	wb = PageHeadMakeWritable(node->pg);
	if(NULL == wb)
		return -1;

	/* 空间不够,挂在cell_ovfl信息里,待balance函数之后再转存至正常的页缓存里 */
	if(node->nfree < (cell_sz + BTREE_CELL_PTR_SIZE))
	{
		if(NULL == node->cell_ovfl.cell_buf)
			node->cell_ovfl.cell_buf = MyBufferConstruct(node->btree_mgr->hm, cell_sz);

		MyBufferSet(node->cell_ovfl.cell_buf, cell, cell_sz);
		node->cell_ovfl.idx = idx;
		node->has_cell_ovfl = 1;

		/* 更改标识位idx_change */
		node->idx_changed = 1;

		assert(node->cell_ovfl.idx <= node->ncell);

		goto btree_mgr_insert_cell_end_;
	}

	if(0 != btree_mgr_eat_cell(node, idx, cell, cell_sz))
		return -1;

btree_mgr_insert_cell_end_:

	/* 更新ncell的值+1 */
	node->ncell += 1;
	put_2byte(node->ncell, &wb[BTREE_HDR_NCELL_OFFSET], BTREE_HDR_NCELL_SZ);

	return 0;
}

/**
 * @brief 将溢出的cell去除,ncell要减1
 */
static __INLINE__ int btree_mgr_throwup_cell_ovfl(btree_node * node)
{
	unsigned char * wb = NULL;

	assert(node->has_cell_ovfl && node->cell_ovfl.cell_buf);
	assert(node && node->ncell);

	wb = PageHeadMakeWritable(node->pg);
	if(NULL == wb)
		return -1;

	btree_mgr_clear_ovfl(node);

	node->ncell -= 1;
	put_2byte(node->ncell, &wb[BTREE_HDR_NCELL_OFFSET], BTREE_HDR_NCELL_SZ);

	return 0;
}

/**
 * @brief 将溢出的cell吃回来
 */
static __INLINE__ int btree_mgr_eat_cell_ovfl(btree_node * node)
{
	unsigned char * cell = NULL;
	unsigned int cell_sz = 0;
	HMYBUFFER hbuf = NULL;
	int ret = 0;

	assert(node);
	assert(node->has_cell_ovfl && node->cell_ovfl.cell_buf);

	hbuf = MyBufferConstruct(node->btree_mgr->hm, 0);

	MyBufferRef(node->cell_ovfl.cell_buf, hbuf);
	btree_mgr_clear_ovfl(node);

	cell = MyBufferGet(hbuf, &cell_sz);

	ret = btree_mgr_eat_cell(node, node->cell_ovfl.idx, cell, cell_sz);

	MyBufferDestruct(hbuf);

	return ret;
}

/**
 * @brief 从节点中删除一个cell
 */
static __INLINE__ int btree_mgr_drop_cell(btree_node * node, unsigned int idx, btree_cellinfo * cell_info)
{
	unsigned int cell_ptr = 0;
	unsigned int cell_sz = 0;
	unsigned char * wb = NULL;
	unsigned int ncell_in = 0;

	assert(node && idx < node->ncell);

	wb = PageHeadMakeWritable(node->pg);
	if(NULL == wb)
		return -1;

	btree_mgr_find_cellptr(node, idx, cell_ptr);

	if(NULL == cell_info)
	{
		btree_cellinfo temp_cell_info;
		btree_mgr_parse_cellptr(node, cell_ptr, &temp_cell_info);
		cell_sz = temp_cell_info.cell_sz;
	}
	else
	{

#ifdef _DEBUG
btree_cellinfo temp_cellinfo;
btree_mgr_parse_idx(node, idx, &temp_cellinfo);
assert(0 == memcmp(&temp_cellinfo, cell_info, sizeof(temp_cellinfo)));
#endif

		assert(PageHeadMakeReadable(node->pg) == node->read_buf);
		assert((cell_info->cell - node->read_buf) == cell_ptr);
		cell_sz = cell_info->cell_sz;
	}

	/* ncell计数减1,并调整cell ptr数组,idx change标识置1 */
	if(0 != btree_mgr_free_space(node, cell_ptr, cell_sz))
		return -1;

	if(node->has_cell_ovfl)
		ncell_in = node->ncell - 1;
	else
		ncell_in = node->ncell;

	/* 将后继的ptr往前整 */
	if(idx < ncell_in - 1)
	{
		unsigned int i;
		unsigned char * ptr;

		ptr = &wb[BTREE_CELL_PTR_OFFSET + idx * BTREE_CELL_PTR_SIZE];
		for(i = 0; i < ncell_in - idx - 1; i ++)
		{
			ptr[i * BTREE_CELL_PTR_SIZE] = ptr[i * BTREE_CELL_PTR_SIZE + 2];
			ptr[i * BTREE_CELL_PTR_SIZE + 1] = ptr[i * BTREE_CELL_PTR_SIZE + 3];
		}
	}

	/* ncell计数减1 */
	node->ncell -= 1;
	put_2byte(node->ncell, &wb[BTREE_HDR_NCELL_OFFSET], BTREE_HDR_NCELL_SZ);

	/* idx change标识置1 */
	node->idx_changed = 1;

	return 0;
}

/**
 * @brief 从节点中删除一条记录,放弃本节点的cell,以及后继的ovfl页(如果有)
 */
static __INLINE__ int btree_mgr_delete_record(btree_node * node, unsigned int idx, btree_cellinfo * cell_info)
{
	unsigned int pgno_ovfl = 0;
	HPAGER hpgr = NULL;

	assert(node && idx < node->ncell);

	if(cell_info)
	{
#ifdef _DEBUG
btree_cellinfo temp_cellinfo;
btree_mgr_parse_idx(node, idx, &temp_cellinfo);
assert(0 == memcmp(&temp_cellinfo, cell_info, sizeof(temp_cellinfo)));
#endif
		pgno_ovfl = cell_info->overflow_pgno;

		if(0 != btree_mgr_drop_cell(node, idx, cell_info))
			return -1;

		assert(((cell_info->data_sz + cell_info->key_sz * ((no

⌨️ 快捷键说明

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