begeekmyfriend / bplustree Goto Github PK
View Code? Open in Web Editor NEWA minimal but extreme fast B+ tree indexing structure demo for billions of key-value storage
License: MIT License
A minimal but extreme fast B+ tree indexing structure demo for billions of key-value storage
License: MIT License
list_next_entry 遍历叶子节点时,最后的叶子节点再次调用list_next_entry返回的指针不是NULL而是未知量,与你list_next_entry实现有关。
请问value可以自定义类型吗?
如上图,此时是否应该将34作为split_key提到根节点比较合适?
问题逻辑如下:
static key_t non_leaf_split_right2(struct bplus_tree *tree, struct bplus_node *node,
struct bplus_node *right, struct bplus_node *l_ch,
struct bplus_node *r_ch, key_t key, int insert)
{
int i;
/* split = [m/2] */
int split = (_max_order + 1) / 2;
/* split as right sibling */
right_node_add(tree, node, right);
/* split key is key[split] */
key_t split_key = key(node)[split]; // it's here, split_key = key(node)[split - 1] maybe better?
/* calculate split nodes' children (sum as (order + 1))*/
int pivot = insert - split - 1;
node->children = split + 1;
right->children = _max_order - split;
/* sum = right->children = pivot + 2 + (_max_order - insert - 1) */
/* replicate from key[split + 1] to key[insert] */
memmove(&key(right)[0], &key(node)[split + 1], pivot * sizeof(key_t));
memmove(&sub(right)[0], &sub(node)[split + 1], pivot * sizeof(off_t));
/* insert new key and sub-node */
key(right)[pivot] = key;
sub_node_update(tree, right, pivot, l_ch);
sub_node_update(tree, right, pivot + 1, r_ch);
/* replicate from key[insert] to key[order - 1] */
memmove(&key(right)[pivot + 1], &key(node)[insert], (_max_order - insert - 1) * sizeof(key_t));
memmove(&sub(right)[pivot + 2], &sub(node)[insert + 1], (_max_order - insert - 1) * sizeof(off_t));
/* flush sub-nodes of the new splitted right node */
for (i = 0; i < right->children; i++) {
if (i != pivot && i != pivot + 1) {
sub_node_flush(tree, right, sub(right)[i]);
}
}
return split_key;
}
when I excute command like below:
./coverage_build.sh
Please wait about 10 seconds for test case generation...
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
Compatibility with CMake < 2.8.12 will be removed from a future version of
CMake.
Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions.
-- The C compiler identification is AppleClang 13.0.0.13000029
-- The CXX compiler identification is AppleClang 13.0.0.13000029
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at cmake/CodeCoverage.cmake:127 (MESSAGE):
lcov not found! Aborting...
Call Stack (most recent call first):
tests/CMakeLists.txt:16 (setup_target_for_coverage)
OS: [Bigsur 11.3.1]
key(root)[0]= key这行代码如何理解呢
To better understand the code,I add some code annotation in head file(bplustree.h).
I think it miht be nesscary for others to understand.
would you mind to merge it to in-memory branch or I can send PR
/*
* Copyright (C) 2015, Leo Ma <[email protected]>
*/
#ifndef _BPLUS_TREE_H
#define _BPLUS_TREE_H
#define BPLUS_MIN_ORDER 3
#define BPLUS_MAX_ORDER 64
#define BPLUS_MAX_ENTRIES 64
#define BPLUS_MAX_LEVEL 10
typedef int key_t;
struct list_head {
struct list_head *prev, *next;
};
static inline void list_init(struct list_head *link)
{
link->prev = link;
link->next = link;
}
static inline void
__list_add(struct list_head *link, struct list_head *prev, struct list_head *next)
{
link->next = next;
link->prev = prev;
next->prev = link;
prev->next = link;
}
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
prev->next = next;
next->prev = prev;
}
static inline void list_add(struct list_head *link, struct list_head *prev)
{
__list_add(link, prev, prev->next);
}
static inline void list_add_tail(struct list_head *link, struct list_head *head)
{
__list_add(link, head->prev, head);
}
static inline void list_del(struct list_head *link)
{
__list_del(link->prev, link->next);
list_init(link);
}
static inline int list_is_first(struct list_head *link, struct list_head *head)
{
return link->prev == head;
}
static inline int list_is_last(struct list_head *link, struct list_head *head)
{
return link->next == head;
}
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) - (size_t)(&((type *)0)->member)))
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
#define list_prev_entry(pos, member) \
list_entry((pos)->member.prev, typeof(*(pos)), member)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* b plus tree basic node
*
*
*/
struct bplus_node {
/** type indicates leaf node or not
* BPLUS_TREE_LEAF is 0 and BPLUS_TREE_NON_LEAF is 1
*/
int type;
/** parent_key_idx: index of parent node */
int parent_key_idx;
/** piointer to parent node */
struct bplus_non_leaf *parent;
/** pointer to first node(head) in leaf linked list */
struct list_head link;
/** */
int count;
};
/** b plus tree non-leaf(internal) node
* non-leaf node need to carry children node information
* node contains only keys not key-value-pairs
*/
struct bplus_non_leaf {
/** type indicates leaf node or not
* BPLUS_TREE_LEAF is 0 and BPLUS_TREE_NON_LEAF is 1
*/
int type;
/** parent_key_idx: index of parent node */
int parent_key_idx;
/** piointer to parent node */
struct bplus_non_leaf *parent;
/** pointer to first node(head) in leaf linked list
*/
struct list_head link;
/** number of child node */
int children;
/** key array */
int key[BPLUS_MAX_ORDER - 1];
/** pointers to child node */
struct bplus_node *sub_ptr[BPLUS_MAX_ORDER];
};
/** b plus tree leaf node
* leaf node need to carry key-value-pairs
*/
struct bplus_leaf {
/** type indicates leaf node or not
* BPLUS_TREE_LEAF is 0 and BPLUS_TREE_NON_LEAF is 1
*/
int type;
/** parent_key_idx: index of parent node */
int parent_key_idx;
/** piointer to parent node */
struct bplus_non_leaf *parent;
/** pointer to first node(head) in leaf linked list
*/
struct list_head link;
/** number of actual key-value pairs in leaf node */
int entries;
/** key array */
int key[BPLUS_MAX_ENTRIES];
/** val array */
int data[BPLUS_MAX_ENTRIES];
};
/** b plus tree structure */
struct bplus_tree {
/** The actual number of children for a node, referred to here as order */
int order;
/** number of actual key-value pairs in tree */
int entries;
/** height of the tree */
int level;
struct bplus_node *root;
/** double linked list to search leaf node */
struct list_head list[BPLUS_MAX_LEVEL];
};
/** print the whole tree for debugging
*
* @param tree pointer to bplus tree
*/
void bplus_tree_dump(struct bplus_tree *tree);
/** return value acordding to key
*
* @param tree pointer to bplus tree
* @param key key in key-value pair
*/
int bplus_tree_get(struct bplus_tree *tree, key_t key);
/** insert key-value pair to tree
*
* @param tree pointer to bplus tree
* @param key key in key-value pair
* @param data value in key-value pair
*/
int bplus_tree_put(struct bplus_tree *tree, key_t key, int data);
/** return data between [key1,key2]
*
* @param tree pointer to bplus tree
* @param key1 key in key-value pair
* @param key2 value in key-value pair
*/
int bplus_tree_get_range(struct bplus_tree *tree, key_t key1, key_t key2);
/** init b plus tree
* @return a pointer to tree
*
* @param order The actual number of children for a node, referred to here as order
* @param key1 key in key-value pair
* @param key2 key in key-value pair
*/
struct bplus_tree *bplus_tree_init(int order, int entries);
/** destory the tree safely
* @return a pointer to tree
* @param order The actual number of children for a node, referred to here as order
* @param entries number of actual key-value pairs in tree
*/
void bplus_tree_deinit(struct bplus_tree *tree);
#endif /* _BPLUS_TREE_H */
It seems tree->root dump during tree deinit but in case if a process
has shutdown ungracefully in that case the function bplus_tree_init would
not be able to load the tree because no .boot file is available.
there is a bplus_tree_get_range
method there and it turns out this method only returns the first element of bplustree belong the range. However, this is not so great considering range query.
So how to iterator the results of range query, the interfaces which have been provided currently is not enough. How can do that? help wanted::::
in-memory 版本在析构树时内存泄露,未对叶子结点和非叶子结点进行析构。
Let's suppose the non_leaf node has 3 entries 7, 17, 25, and max_order
of the tree is 3. If suppose a non_leaf node has received a split node request from children for key 20.
Non_leaf_node : 7, 17, 25
split_key: 20
split_index = 2(3 + 1 ) / 2
split_key = 17
pivot = 0
node->children = 2
right->children = 2
right_node[0] = 20
Ideally right_node[1] key should be 25 but as per the condition
memmove(&key(right)[pivot + 1], &key(node)[split], (right->children - 2) * sizeof(key_t));
no key will be copied to right[1] because the number of elements will be 0.
I think It should be right->children - 1. Please correct me if I am wrong.
static key_t non_leaf_split_right1(struct bplus_tree *tree, struct bplus_node *node,
struct bplus_node *right, struct bplus_node *l_ch,
struct bplus_node *r_ch, key_t key, int insert)
{
int i;
/* split = [m/2] */
int split = (_max_order + 1) / 2;
/* split as right sibling */
right_node_add(tree, node, right);
/* split key is key[split - 1] */
key_t split_key = key(node)[split - 1];
/* calculate split nodes' children (sum as (order + 1))*/
int pivot = 0;
node->children = split;
right->children = _max_order - split + 1;
/* insert new key and sub-nodes */
key(right)[0] = key;
sub_node_update(tree, right, pivot, l_ch);
sub_node_update(tree, right, pivot + 1, r_ch);
/* sum = right->children = 2 + (right->children - 2) */
/* replicate from key[split] to key[_max_order - 2] */
memmove(&key(right)[pivot + 1], &key(node)[split], (right->children - 2) * sizeof(key_t));
memmove(&sub(right)[pivot + 2], &sub(node)[split + 1], (right->children - 2) * sizeof(off_t));
}
-- B+tree setting...
Set b+tree non-leaf order (3 < order <= 64 e.g. 7): 3
Set b+tree leaf entries (<= 64 e.g. 10): 3
Please input command (Type 'h' for help): i 1-20
Please input command (Type 'h' for help): d
node: 19
+-------node: 7 13
| +-------node: 3 5
| | +-------leaf: 1 2
| | +-------leaf: 3 4
| | +-------leaf: 5 6
| +-------node: 9 11
| | +-------leaf: 7 8
| | +-------leaf: 9 10
| | +-------leaf: 11 12
| +-------node: 15 17
| +-------leaf: 13 14
| +-------leaf: 15 16
| +-------leaf: 17 18
+-------node:
+-------node:
+-------leaf: 19 20
Please input command (Type 'h' for help): r 19
./demo_build.sh: 行 7: 24789 段错误 (核心已转储) ./bin/bplustree_demo
您好 前辈 执行./coverage_build.sh 时有如下错误
please wait about 10 seconds for test case generation...
-- The C compiler identification is GNU 4.3.4
-- The CXX compiler identification is GNU 4.3.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liding/coding/bplustree-disk-io/build
Scanning dependencies of target bplustree_coverage
[ 50%] Building C object tests/CMakeFiles/bplustree_coverage.dir/__/lib/bplustree.c.o
/home/liding/coding/bplustree-disk-io/lib/bplustree.c: In function ‘node_fetch’:
/home/liding/coding/bplustree-disk-io/lib/bplustree.c:128: warning: implicit declaration of function ‘pread’
/home/liding/coding/bplustree-disk-io/lib/bplustree.c: In function ‘node_flush’:
/home/liding/coding/bplustree-disk-io/lib/bplustree.c:154: warning: implicit declaration of function ‘pwrite’
[100%] Building C object tests/CMakeFiles/bplustree_coverage.dir/bplustree_coverage.c.o
Linking C executable ../bin/bplustree_coverage
[100%] Built target bplustree_coverage
Scanning dependencies of target coverage
Deleting all .da files in . and subdirectories
Done.
config node order:39 and leaf entries:39
bplustree_coverage: /home/liding/coding/bplustree-disk-io/lib/bplustree.c:144: node_seek: Assertion `len == _block_size' failed.
make[3]: *** [tests/CMakeFiles/coverage] Aborted
make[2]: *** [tests/CMakeFiles/coverage.dir/all] Error 2
make[1]: *** [tests/CMakeFiles/coverage.dir/rule] Erro
您好,我执行 ./demo_build.sh
时有如下错误
/home/yxy/桌面/bplustree/tests/bplustree_demo.c: In function ‘bplus_tree_setting’:
/home/yxy/桌面/bplustree/tests/bplustree_demo.c:29:25: error: this statement may fall through [-Werror=implicit-fallthrough=]
printf("\n");
^~~~~~~~~~~~
/home/yxy/桌面/bplustree/tests/bplustree_demo.c:30:17: note: here
case 'q':
^~~~
/home/yxy/桌面/bplustree/tests/bplustree_demo.c:54:25: error: this statement may fall through [-Werror=implicit-fallthrough=]
printf("\n");
^~~~~~~~~~~~
/home/yxy/桌面/bplustree/tests/bplustree_demo.c:55:17: note: here
case 'q':
^~~~
/home/yxy/桌面/bplustree/tests/bplustree_demo.c: In function ‘command_process’:
/home/yxy/桌面/bplustree/tests/bplustree_demo.c:196:28: error: this statement may fall through [-Werror=implicit-fallthrough=]
if (number_process(tree, c) < 0) {
^
/home/yxy/桌面/bplustree/tests/bplustree_demo.c:199:17: note: here
case '\n':
^~~~
cc1: all warnings being treated as errors
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.