📄 btree.c
字号:
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, (size_t *)&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 _DEBUGbtree_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((unsigned int)(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 _DEBUGbtree_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 * ((node->node_flag & e_btree_page_flag_intkey ? 0 : 1))) == cell_info->local_sz && 0 == pgno_ovfl) || (pgno_ovfl && (cell_info->data_sz + cell_info->key_sz * ((node->node_flag & e_btree_page_flag_intkey ? 0 : 1))) > node->btree_mgr->max_local)); } else { btree_cellinfo temp_cell_info; btree_mgr_parse_idx(node, idx, &temp_cell_info); pgno_ovfl = temp_cell_info.overflow_pgno; if(0 != btree_mgr_drop_cell(node, idx, &temp_cell_info)) return -1; assert(((temp_cell_info.data_sz + temp_cell_info.key_sz * ((node->node_flag & e_btree_page_flag_intkey ? 0 : 1))) == temp_cell_info.local_sz && 0 == pgno_ovfl) || (pgno_ovfl && (temp_cell_info.data_sz + temp_cell_info.key_sz * ((node->node_flag & e_btree_page_flag_intkey ? 0 : 1))) > node->btree_mgr->max_local)); } assert(node->btree_mgr); hpgr = node->btree_mgr->hpgr; assert(hpgr); /* 如果有溢出页 */ while(pgno_ovfl) { unsigned int temp_pgno = pgno_ovfl; const unsigned char * rb = NULL; HPAGE_HEAD pg_ovfl = PagerGetPage(hpgr, pgno_ovfl); if(NULL == pg_ovfl) return -1; rb = PageHeadMakeReadable(pg_ovfl); if(NULL == rb) { PagerReleasePage(pg_ovfl); return -1; } array_to_uint_as_big_endian(rb, sizeof(unsigned int), pgno_ovfl); if(0 != PagerReleasePage(pg_ovfl)) return -1; if(0 != PagerReleasePageNo(hpgr, temp_pgno)) return -1; } return 0;}/** * @brief 更新idx下标所指节点的lchild,如果起过ncell,则表示更新right most child */static __INLINE__ int btree_mgr_update_idx_lchild(btree_node * node, unsigned int idx, unsigned int pgno_child){ unsigned char * wb = NULL; unsigned int cell_ptr = 0; btree_cellinfo cell_info; assert((node && pgno_child) || ((node->node_flag & e_btree_page_flag_leaf) && 0 == pgno_child && idx == node->ncell)); assert(idx <= node->ncell); assert(!(node->node_flag & e_btree_page_flag_leaf) || (0 == pgno_child && idx == node->ncell)); assert(!node->has_cell_ovfl && NULL == node->cell_ovfl.cell_buf); wb = PageHeadMakeWritable(node->pg); if(NULL == wb) return -1; if(idx == node->ncell) { /* 更新right most即可 */ uint_to_big_endian(pgno_child, &wb[BTREE_HDR_MOST_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -