Rev 1150 | Rev 1177 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1150 | Rev 1164 | ||
---|---|---|---|
Line 26... | Line 26... | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | /* |
29 | /* |
30 | * This B-tree has the following properties: |
30 | * This B-tree has the following properties: |
31 | * - it is a ballanced 2-3-4-5 tree (i.e. BTREE_M = 5) |
31 | * - it is a ballanced 3-4-5 tree (i.e. BTREE_M = 5) |
32 | * - values (i.e. pointers to values) are stored only in leaves |
32 | * - values (i.e. pointers to values) are stored only in leaves |
33 | * - leaves are linked in a list |
33 | * - leaves are linked in a list |
34 | * - technically, it is a B+tree (because of the previous properties) |
34 | * - technically, it is a B+tree (because of the previous properties) |
35 | * |
35 | * |
36 | * Be carefull when using these trees. They need to allocate |
36 | * Be carefull when using these trees. They need to allocate |
Line 72... | Line 72... | ||
72 | #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2) |
72 | #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2) |
73 | #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2) |
73 | #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2) |
74 | #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]); |
74 | #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]); |
75 | #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]); |
75 | #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]); |
76 | 76 | ||
- | 77 | static slab_cache_t *btree_node_slab; |
|
- | 78 | ||
- | 79 | /** Initialize B-trees. */ |
|
- | 80 | void btree_init(void) |
|
- | 81 | { |
|
- | 82 | btree_node_slab = slab_cache_create("btree_node_slab", sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED); |
|
- | 83 | } |
|
- | 84 | ||
77 | /** Create empty B-tree. |
85 | /** Create empty B-tree. |
78 | * |
86 | * |
79 | * @param t B-tree. |
87 | * @param t B-tree. |
80 | */ |
88 | */ |
81 | void btree_create(btree_t *t) |
89 | void btree_create(btree_t *t) |
82 | { |
90 | { |
83 | list_initialize(&t->leaf_head); |
91 | list_initialize(&t->leaf_head); |
84 | t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
92 | t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0); |
85 | node_initialize(t->root); |
93 | node_initialize(t->root); |
86 | list_append(&t->root->leaf_link, &t->leaf_head); |
94 | list_append(&t->root->leaf_link, &t->leaf_head); |
87 | } |
95 | } |
88 | 96 | ||
89 | /** Destroy empty B-tree. */ |
97 | /** Destroy empty B-tree. */ |
90 | void btree_destroy(btree_t *t) |
98 | void btree_destroy(btree_t *t) |
91 | { |
99 | { |
92 | ASSERT(!t->root->keys); |
100 | ASSERT(!t->root->keys); |
93 | free(t->root); |
101 | slab_free(btree_node_slab, t->root); |
94 | } |
102 | } |
95 | 103 | ||
96 | /** Insert key-value pair into B-tree. |
104 | /** Insert key-value pair into B-tree. |
97 | * |
105 | * |
98 | * @param t B-tree. |
106 | * @param t B-tree. |
Line 159... | Line 167... | ||
159 | 167 | ||
160 | if (ROOT_NODE(node)) { |
168 | if (ROOT_NODE(node)) { |
161 | /* |
169 | /* |
162 | * We split the root node. Create new root. |
170 | * We split the root node. Create new root. |
163 | */ |
171 | */ |
164 | t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
172 | t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0); |
165 | node->parent = t->root; |
173 | node->parent = t->root; |
166 | rnode->parent = t->root; |
174 | rnode->parent = t->root; |
167 | node_initialize(t->root); |
175 | node_initialize(t->root); |
168 | 176 | ||
169 | /* |
177 | /* |
Line 212... | Line 220... | ||
212 | /* |
220 | /* |
213 | * Free the current root and set new root. |
221 | * Free the current root and set new root. |
214 | */ |
222 | */ |
215 | t->root = node->subtree[0]; |
223 | t->root = node->subtree[0]; |
216 | t->root->parent = NULL; |
224 | t->root->parent = NULL; |
217 | free(node); |
225 | slab_free(btree_node_slab, node); |
218 | } else { |
226 | } else { |
219 | /* |
227 | /* |
220 | * Remove the key from the root node. |
228 | * Remove the key from the root node. |
221 | * Note that the right subtree is removed because when |
229 | * Note that the right subtree is removed because when |
222 | * combining two nodes, the left-side sibling is preserved |
230 | * combining two nodes, the left-side sibling is preserved |
Line 267... | Line 275... | ||
267 | rnode = node_combine(node); |
275 | rnode = node_combine(node); |
268 | if (LEAF_NODE(rnode)) |
276 | if (LEAF_NODE(rnode)) |
269 | list_remove(&rnode->leaf_link); |
277 | list_remove(&rnode->leaf_link); |
270 | idx = find_key_by_subtree(parent, rnode, true); |
278 | idx = find_key_by_subtree(parent, rnode, true); |
271 | ASSERT((int) idx != -1); |
279 | ASSERT((int) idx != -1); |
272 | free(rnode); |
280 | slab_free(btree_node_slab, rnode); |
273 | _btree_remove(t, parent->key[idx], parent); |
281 | _btree_remove(t, parent->key[idx], parent); |
274 | } |
282 | } |
275 | } |
283 | } |
276 | 284 | ||
277 | /** Search key in a B-tree. |
285 | /** Search key in a B-tree. |
Line 560... | Line 568... | ||
560 | *median = MEDIAN_HIGH(node); |
568 | *median = MEDIAN_HIGH(node); |
561 | 569 | ||
562 | /* |
570 | /* |
563 | * Allocate and initialize new right sibling. |
571 | * Allocate and initialize new right sibling. |
564 | */ |
572 | */ |
565 | rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
573 | rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0); |
566 | node_initialize(rnode); |
574 | node_initialize(rnode); |
567 | rnode->parent = node->parent; |
575 | rnode->parent = node->parent; |
568 | rnode->depth = node->depth; |
576 | rnode->depth = node->depth; |
569 | 577 | ||
570 | /* |
578 | /* |