📄 btree.c
字号:
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 + -