Rev 1136 | Rev 1142 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1136 | Rev 1140 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (C) 2006 Jakub Jermar |
2 | * Copyright (C) 2006 Jakub Jermar |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
8 | * |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
13 | * documentation and/or other materials provided with the distribution. |
14 | * - The name of the author may not be used to endorse or promote products |
14 | * - The name of the author may not be used to endorse or promote products |
15 | * derived from this software without specific prior written permission. |
15 | * derived from this software without specific prior written permission. |
16 | * |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
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 tree (i.e. BTREE_M = 4) |
31 | * - it is a ballanced 2-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 |
37 | * and deallocate memory for their index nodes and as such |
37 | * and deallocate memory for their index nodes and as such |
38 | * can sleep. |
38 | * can sleep. |
39 | */ |
39 | */ |
40 | 40 | ||
41 | #include <adt/btree.h> |
41 | #include <adt/btree.h> |
42 | #include <adt/list.h> |
42 | #include <adt/list.h> |
43 | #include <mm/slab.h> |
43 | #include <mm/slab.h> |
44 | #include <debug.h> |
44 | #include <debug.h> |
45 | #include <panic.h> |
45 | #include <panic.h> |
46 | #include <typedefs.h> |
46 | #include <typedefs.h> |
47 | #include <print.h> |
47 | #include <print.h> |
48 | 48 | ||
49 | static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node); |
49 | static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node); |
50 | static void node_initialize(btree_node_t *node); |
50 | static void node_initialize(btree_node_t *node); |
51 | static void node_insert_key_left(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
51 | static void node_insert_key_left(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
52 | static void node_insert_key_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
52 | static void node_insert_key_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
53 | static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median); |
53 | static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median); |
54 | static void node_remove_key_left(btree_node_t *node, __native key); |
54 | static void node_remove_key_left(btree_node_t *node, __native key); |
55 | static void node_remove_key_right(btree_node_t *node, __native key); |
55 | static void node_remove_key_right(btree_node_t *node, __native key); |
56 | static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right); |
56 | static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right); |
57 | static bool try_insert_by_left_rotation(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
57 | static bool try_insert_by_left_rotation(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
58 | static bool try_insert_by_right_rotation(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
58 | static bool try_insert_by_right_rotation(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
59 | 59 | ||
60 | #define ROOT_NODE(n) (!(n)->parent) |
60 | #define ROOT_NODE(n) (!(n)->parent) |
61 | #define INDEX_NODE(n) ((n)->subtree[0] != NULL) |
61 | #define INDEX_NODE(n) ((n)->subtree[0] != NULL) |
62 | #define LEAF_NODE(n) ((n)->subtree[0] == NULL) |
62 | #define LEAF_NODE(n) ((n)->subtree[0] == NULL) |
63 | 63 | ||
- | 64 | #define FILL_FACTOR ((BTREE_M-1)/2) |
|
- | 65 | ||
64 | #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2) |
66 | #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2) |
65 | #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2) |
67 | #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2) |
66 | #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]); |
68 | #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]); |
67 | #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]); |
69 | #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]); |
68 | 70 | ||
69 | /** Create empty B-tree. |
71 | /** Create empty B-tree. |
70 | * |
72 | * |
71 | * @param t B-tree. |
73 | * @param t B-tree. |
72 | */ |
74 | */ |
73 | void btree_create(btree_t *t) |
75 | void btree_create(btree_t *t) |
74 | { |
76 | { |
75 | list_initialize(&t->leaf_head); |
77 | list_initialize(&t->leaf_head); |
76 | t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
78 | t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
77 | node_initialize(t->root); |
79 | node_initialize(t->root); |
78 | list_append(&t->root->leaf_link, &t->leaf_head); |
80 | list_append(&t->root->leaf_link, &t->leaf_head); |
79 | } |
81 | } |
80 | 82 | ||
81 | /** Destroy empty B-tree. */ |
83 | /** Destroy empty B-tree. */ |
82 | void btree_destroy(btree_t *t) |
84 | void btree_destroy(btree_t *t) |
83 | { |
85 | { |
84 | ASSERT(!t->root->keys); |
86 | ASSERT(!t->root->keys); |
85 | free(t->root); |
87 | free(t->root); |
86 | } |
88 | } |
87 | 89 | ||
88 | /** Insert key-value pair into B-tree. |
90 | /** Insert key-value pair into B-tree. |
89 | * |
91 | * |
90 | * @param t B-tree. |
92 | * @param t B-tree. |
91 | * @param key Key to be inserted. |
93 | * @param key Key to be inserted. |
92 | * @param value Value to be inserted. |
94 | * @param value Value to be inserted. |
93 | * @param leaf_node Leaf node where the insertion should begin. |
95 | * @param leaf_node Leaf node where the insertion should begin. |
94 | */ |
96 | */ |
95 | void btree_insert(btree_t *t, __native key, void *value, btree_node_t *leaf_node) |
97 | void btree_insert(btree_t *t, __native key, void *value, btree_node_t *leaf_node) |
96 | { |
98 | { |
97 | btree_node_t *lnode; |
99 | btree_node_t *lnode; |
98 | 100 | ||
99 | ASSERT(value); |
101 | ASSERT(value); |
100 | 102 | ||
101 | lnode = leaf_node; |
103 | lnode = leaf_node; |
102 | if (!lnode) { |
104 | if (!lnode) { |
103 | if (btree_search(t, key, &lnode)) { |
105 | if (btree_search(t, key, &lnode)) { |
104 | panic("B-tree %P already contains key %d\n", t, key); |
106 | panic("B-tree %P already contains key %d\n", t, key); |
105 | } |
107 | } |
106 | } |
108 | } |
107 | 109 | ||
108 | _btree_insert(t, key, value, NULL, lnode); |
110 | _btree_insert(t, key, value, NULL, lnode); |
109 | } |
111 | } |
110 | 112 | ||
111 | /** Recursively insert into B-tree. |
113 | /** Recursively insert into B-tree. |
112 | * |
114 | * |
113 | * @param t B-tree. |
115 | * @param t B-tree. |
114 | * @param key Key to be inserted. |
116 | * @param key Key to be inserted. |
115 | * @param value Value to be inserted. |
117 | * @param value Value to be inserted. |
116 | * @param rsubtree Right subtree of the inserted key. |
118 | * @param rsubtree Right subtree of the inserted key. |
117 | * @param node Start inserting into this node. |
119 | * @param node Start inserting into this node. |
118 | */ |
120 | */ |
119 | void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node) |
121 | void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node) |
120 | { |
122 | { |
121 | if (node->keys < BTREE_MAX_KEYS) { |
123 | if (node->keys < BTREE_MAX_KEYS) { |
122 | /* |
124 | /* |
123 | * Node conatins enough space, the key can be stored immediately. |
125 | * Node conatins enough space, the key can be stored immediately. |
124 | */ |
126 | */ |
125 | node_insert_key_right(node, key, value, rsubtree); |
127 | node_insert_key_right(node, key, value, rsubtree); |
126 | } else if (try_insert_by_left_rotation(node, key, value, rsubtree)) { |
128 | } else if (try_insert_by_left_rotation(node, key, value, rsubtree)) { |
127 | /* |
129 | /* |
128 | * The key-value-rsubtree triplet has been inserted because |
130 | * The key-value-rsubtree triplet has been inserted because |
129 | * some keys could have been moved to the left sibling. |
131 | * some keys could have been moved to the left sibling. |
130 | */ |
132 | */ |
131 | } else if (try_insert_by_right_rotation(node, key, value, rsubtree)) { |
133 | } else if (try_insert_by_right_rotation(node, key, value, rsubtree)) { |
132 | /* |
134 | /* |
133 | * The key-value-rsubtree triplet has been inserted because |
135 | * The key-value-rsubtree triplet has been inserted because |
134 | * some keys could have been moved to the right sibling. |
136 | * some keys could have been moved to the right sibling. |
135 | */ |
137 | */ |
136 | } else { |
138 | } else { |
137 | btree_node_t *rnode; |
139 | btree_node_t *rnode; |
138 | __native median; |
140 | __native median; |
139 | 141 | ||
140 | /* |
142 | /* |
141 | * Node is full and both siblings (if both exist) are full too. |
143 | * Node is full and both siblings (if both exist) are full too. |
142 | * Split the node and insert the smallest key from the node containing |
144 | * Split the node and insert the smallest key from the node containing |
143 | * bigger keys (i.e. the new node) into its parent. |
145 | * bigger keys (i.e. the new node) into its parent. |
144 | */ |
146 | */ |
145 | 147 | ||
146 | rnode = node_split(node, key, value, rsubtree, &median); |
148 | rnode = node_split(node, key, value, rsubtree, &median); |
147 | 149 | ||
148 | if (LEAF_NODE(node)) { |
150 | if (LEAF_NODE(node)) { |
149 | list_append(&rnode->leaf_link, &node->leaf_link); |
151 | list_append(&rnode->leaf_link, &node->leaf_link); |
150 | } |
152 | } |
151 | 153 | ||
152 | if (ROOT_NODE(node)) { |
154 | if (ROOT_NODE(node)) { |
153 | /* |
155 | /* |
154 | * We split the root node. Create new root. |
156 | * We split the root node. Create new root. |
155 | */ |
157 | */ |
156 | t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
158 | t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
157 | node->parent = t->root; |
159 | node->parent = t->root; |
158 | rnode->parent = t->root; |
160 | rnode->parent = t->root; |
159 | node_initialize(t->root); |
161 | node_initialize(t->root); |
160 | 162 | ||
161 | /* |
163 | /* |
162 | * Left-hand side subtree will be the old root (i.e. node). |
164 | * Left-hand side subtree will be the old root (i.e. node). |
163 | * Right-hand side subtree will be rnode. |
165 | * Right-hand side subtree will be rnode. |
164 | */ |
166 | */ |
165 | t->root->subtree[0] = node; |
167 | t->root->subtree[0] = node; |
166 | 168 | ||
167 | t->root->depth = node->depth + 1; |
169 | t->root->depth = node->depth + 1; |
168 | } |
170 | } |
169 | _btree_insert(t, median, NULL, rnode, node->parent); |
171 | _btree_insert(t, median, NULL, rnode, node->parent); |
170 | } |
172 | } |
171 | 173 | ||
172 | } |
174 | } |
173 | 175 | ||
- | 176 | /** Remove B-tree node. |
|
- | 177 | * |
|
- | 178 | * @param B-tree. |
|
- | 179 | * @param key Key to be removed from the B-tree along with its associated value. |
|
- | 180 | * @param leaf_node If not NULL, pointer to the leaf node where the key is found. |
|
174 | /* TODO */ |
181 | */ |
175 | void btree_remove(btree_t *t, __native key) |
182 | void btree_remove(btree_t *t, __native key, btree_node_t *leaf_node) |
176 | { |
183 | { |
- | 184 | btree_node_t *lnode; |
|
- | 185 | ||
- | 186 | lnode = leaf_node; |
|
- | 187 | if (!lnode) { |
|
- | 188 | if (!btree_search(t, key, &lnode)) { |
|
- | 189 | panic("B-tree %P does not contain key %d\n", t, key); |
|
- | 190 | } |
|
- | 191 | } |
|
- | 192 | ||
- | 193 | /* TODO */ |
|
- | 194 | ||
177 | } |
195 | } |
178 | 196 | ||
179 | /** Search key in a B-tree. |
197 | /** Search key in a B-tree. |
180 | * |
198 | * |
181 | * @param t B-tree. |
199 | * @param t B-tree. |
182 | * @param key Key to be searched. |
200 | * @param key Key to be searched. |
183 | * @param leaf_node Address where to put pointer to visited leaf node. |
201 | * @param leaf_node Address where to put pointer to visited leaf node. |
184 | * |
202 | * |
185 | * @return Pointer to value or NULL if there is no such key. |
203 | * @return Pointer to value or NULL if there is no such key. |
186 | */ |
204 | */ |
187 | void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node) |
205 | void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node) |
188 | { |
206 | { |
189 | btree_node_t *cur, *next; |
207 | btree_node_t *cur, *next; |
190 | 208 | ||
191 | /* |
209 | /* |
192 | * Iteratively descend to the leaf that can contain the searched key. |
210 | * Iteratively descend to the leaf that can contain the searched key. |
193 | */ |
211 | */ |
194 | for (cur = t->root; cur; cur = next) { |
212 | for (cur = t->root; cur; cur = next) { |
195 | 213 | ||
196 | /* Last iteration will set this with proper leaf node address. */ |
214 | /* Last iteration will set this with proper leaf node address. */ |
197 | *leaf_node = cur; |
215 | *leaf_node = cur; |
198 | 216 | ||
199 | /* |
217 | /* |
200 | * The key can be in the leftmost subtree. |
218 | * The key can be in the leftmost subtree. |
201 | * Test it separately. |
219 | * Test it separately. |
202 | */ |
220 | */ |
203 | if (key < cur->key[0]) { |
221 | if (key < cur->key[0]) { |
204 | next = cur->subtree[0]; |
222 | next = cur->subtree[0]; |
205 | continue; |
223 | continue; |
206 | } else { |
224 | } else { |
207 | void *val; |
225 | void *val; |
208 | int i; |
226 | int i; |
209 | 227 | ||
210 | /* |
228 | /* |
211 | * Now if the key is smaller than cur->key[i] |
229 | * Now if the key is smaller than cur->key[i] |
212 | * it can only mean that the value is in cur->subtree[i] |
230 | * it can only mean that the value is in cur->subtree[i] |
213 | * or it is not in the tree at all. |
231 | * or it is not in the tree at all. |
214 | */ |
232 | */ |
215 | for (i = 1; i < cur->keys; i++) { |
233 | for (i = 1; i < cur->keys; i++) { |
216 | if (key < cur->key[i]) { |
234 | if (key < cur->key[i]) { |
217 | next = cur->subtree[i]; |
235 | next = cur->subtree[i]; |
218 | val = cur->value[i - 1]; |
236 | val = cur->value[i - 1]; |
219 | 237 | ||
220 | if (LEAF_NODE(cur)) |
238 | if (LEAF_NODE(cur)) |
221 | return key == cur->key[i - 1] ? val : NULL; |
239 | return key == cur->key[i - 1] ? val : NULL; |
222 | 240 | ||
223 | goto descend; |
241 | goto descend; |
224 | } |
242 | } |
225 | } |
243 | } |
226 | 244 | ||
227 | /* |
245 | /* |
228 | * Last possibility is that the key is in the rightmost subtree. |
246 | * Last possibility is that the key is in the rightmost subtree. |
229 | */ |
247 | */ |
230 | next = cur->subtree[i]; |
248 | next = cur->subtree[i]; |
231 | val = cur->value[i - 1]; |
249 | val = cur->value[i - 1]; |
232 | if (LEAF_NODE(cur)) |
250 | if (LEAF_NODE(cur)) |
233 | return key == cur->key[i - 1] ? val : NULL; |
251 | return key == cur->key[i - 1] ? val : NULL; |
234 | } |
252 | } |
235 | descend: |
253 | descend: |
236 | ; |
254 | ; |
237 | } |
255 | } |
238 | 256 | ||
239 | /* |
257 | /* |
240 | * The key was not found in the *leaf_node and is smaller than any of its keys. |
258 | * The key was not found in the *leaf_node and is smaller than any of its keys. |
241 | */ |
259 | */ |
242 | return NULL; |
260 | return NULL; |
243 | } |
261 | } |
244 | 262 | ||
245 | /** Get pointer to value with the smallest key within the node. |
263 | /** Get pointer to value with the smallest key within the node. |
246 | * |
264 | * |
247 | * Can be only used on leaf-level nodes. |
265 | * Can be only used on leaf-level nodes. |
248 | * |
266 | * |
249 | * @param node B-tree node. |
267 | * @param node B-tree node. |
250 | * |
268 | * |
251 | * @return Pointer to value assiciated with the smallest key. |
269 | * @return Pointer to value assiciated with the smallest key. |
252 | */ |
270 | */ |
253 | void *btree_node_min(btree_node_t *node) |
271 | void *btree_node_min(btree_node_t *node) |
254 | { |
272 | { |
255 | ASSERT(LEAF_NODE(node)); |
273 | ASSERT(LEAF_NODE(node)); |
256 | ASSERT(node->keys); |
274 | ASSERT(node->keys); |
257 | return node->value[0]; |
275 | return node->value[0]; |
258 | } |
276 | } |
259 | 277 | ||
260 | /** Get pointer to value with the biggest key within the node. |
278 | /** Get pointer to value with the biggest key within the node. |
261 | * |
279 | * |
262 | * Can be only used on leaf-level nodes. |
280 | * Can be only used on leaf-level nodes. |
263 | * |
281 | * |
264 | * @param node B-tree node. |
282 | * @param node B-tree node. |
265 | * |
283 | * |
266 | * @return Pointer to value assiciated with the biggest key. |
284 | * @return Pointer to value assiciated with the biggest key. |
267 | */ |
285 | */ |
268 | void *btree_node_max(btree_node_t *node) |
286 | void *btree_node_max(btree_node_t *node) |
269 | { |
287 | { |
270 | ASSERT(LEAF_NODE(node)); |
288 | ASSERT(LEAF_NODE(node)); |
271 | ASSERT(node->keys); |
289 | ASSERT(node->keys); |
272 | return node->value[node->keys - 1]; |
290 | return node->value[node->keys - 1]; |
273 | } |
291 | } |
274 | 292 | ||
275 | /** Initialize B-tree node. |
293 | /** Initialize B-tree node. |
276 | * |
294 | * |
277 | * @param node B-tree node. |
295 | * @param node B-tree node. |
278 | */ |
296 | */ |
279 | void node_initialize(btree_node_t *node) |
297 | void node_initialize(btree_node_t *node) |
280 | { |
298 | { |
281 | int i; |
299 | int i; |
282 | 300 | ||
283 | node->keys = 0; |
301 | node->keys = 0; |
284 | 302 | ||
285 | /* Clean also space for the extra key. */ |
303 | /* Clean also space for the extra key. */ |
286 | for (i = 0; i < BTREE_MAX_KEYS + 1; i++) { |
304 | for (i = 0; i < BTREE_MAX_KEYS + 1; i++) { |
287 | node->key[i] = 0; |
305 | node->key[i] = 0; |
288 | node->value[i] = NULL; |
306 | node->value[i] = NULL; |
289 | node->subtree[i] = NULL; |
307 | node->subtree[i] = NULL; |
290 | } |
308 | } |
291 | node->subtree[i] = NULL; |
309 | node->subtree[i] = NULL; |
292 | 310 | ||
293 | node->parent = NULL; |
311 | node->parent = NULL; |
294 | 312 | ||
295 | link_initialize(&node->leaf_link); |
313 | link_initialize(&node->leaf_link); |
296 | 314 | ||
297 | link_initialize(&node->bfs_link); |
315 | link_initialize(&node->bfs_link); |
298 | node->depth = 0; |
316 | node->depth = 0; |
299 | } |
317 | } |
300 | 318 | ||
301 | /** Insert key-value-lsubtree triplet into B-tree node. |
319 | /** Insert key-value-lsubtree triplet into B-tree node. |
302 | * |
320 | * |
303 | * It is actually possible to have more keys than BTREE_MAX_KEYS. |
321 | * It is actually possible to have more keys than BTREE_MAX_KEYS. |
304 | * This feature is used during insert by right rotation. |
322 | * This feature is used during insert by right rotation. |
305 | * |
323 | * |
306 | * @param node B-tree node into wich the new key is to be inserted. |
324 | * @param node B-tree node into wich the new key is to be inserted. |
307 | * @param key The key to be inserted. |
325 | * @param key The key to be inserted. |
308 | * @param value Pointer to value to be inserted. |
326 | * @param value Pointer to value to be inserted. |
309 | * @param lsubtree Pointer to the left subtree. |
327 | * @param lsubtree Pointer to the left subtree. |
310 | */ |
328 | */ |
311 | void node_insert_key_left(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree) |
329 | void node_insert_key_left(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree) |
312 | { |
330 | { |
313 | int i; |
331 | int i; |
314 | 332 | ||
315 | for (i = 0; i < node->keys; i++) { |
333 | for (i = 0; i < node->keys; i++) { |
316 | if (key < node->key[i]) { |
334 | if (key < node->key[i]) { |
317 | int j; |
335 | int j; |
318 | 336 | ||
319 | for (j = node->keys; j > i; j--) { |
337 | for (j = node->keys; j > i; j--) { |
320 | node->key[j] = node->key[j - 1]; |
338 | node->key[j] = node->key[j - 1]; |
321 | node->value[j] = node->value[j - 1]; |
339 | node->value[j] = node->value[j - 1]; |
322 | node->subtree[j + 1] = node->subtree[j]; |
340 | node->subtree[j + 1] = node->subtree[j]; |
323 | } |
341 | } |
324 | node->subtree[j + 1] = node->subtree[j]; |
342 | node->subtree[j + 1] = node->subtree[j]; |
325 | break; |
343 | break; |
326 | } |
344 | } |
327 | } |
345 | } |
328 | node->key[i] = key; |
346 | node->key[i] = key; |
329 | node->value[i] = value; |
347 | node->value[i] = value; |
330 | node->subtree[i] = lsubtree; |
348 | node->subtree[i] = lsubtree; |
331 | 349 | ||
332 | node->keys++; |
350 | node->keys++; |
333 | } |
351 | } |
334 | 352 | ||
335 | 353 | ||
336 | /** Insert key-value-rsubtree triplet into B-tree node. |
354 | /** Insert key-value-rsubtree triplet into B-tree node. |
337 | * |
355 | * |
338 | * It is actually possible to have more keys than BTREE_MAX_KEYS. |
356 | * It is actually possible to have more keys than BTREE_MAX_KEYS. |
339 | * This feature is used during splitting the node when the |
357 | * This feature is used during splitting the node when the |
340 | * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation |
358 | * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation |
341 | * also makes use of this feature. |
359 | * also makes use of this feature. |
342 | * |
360 | * |
343 | * @param node B-tree node into wich the new key is to be inserted. |
361 | * @param node B-tree node into wich the new key is to be inserted. |
344 | * @param key The key to be inserted. |
362 | * @param key The key to be inserted. |
345 | * @param value Pointer to value to be inserted. |
363 | * @param value Pointer to value to be inserted. |
346 | * @param rsubtree Pointer to the right subtree. |
364 | * @param rsubtree Pointer to the right subtree. |
347 | */ |
365 | */ |
348 | void node_insert_key_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree) |
366 | void node_insert_key_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree) |
349 | { |
367 | { |
350 | int i; |
368 | int i; |
351 | 369 | ||
352 | for (i = 0; i < node->keys; i++) { |
370 | for (i = 0; i < node->keys; i++) { |
353 | if (key < node->key[i]) { |
371 | if (key < node->key[i]) { |
354 | int j; |
372 | int j; |
355 | 373 | ||
356 | for (j = node->keys; j > i; j--) { |
374 | for (j = node->keys; j > i; j--) { |
357 | node->key[j] = node->key[j - 1]; |
375 | node->key[j] = node->key[j - 1]; |
358 | node->value[j] = node->value[j - 1]; |
376 | node->value[j] = node->value[j - 1]; |
359 | node->subtree[j + 1] = node->subtree[j]; |
377 | node->subtree[j + 1] = node->subtree[j]; |
360 | } |
378 | } |
361 | break; |
379 | break; |
362 | } |
380 | } |
363 | } |
381 | } |
364 | node->key[i] = key; |
382 | node->key[i] = key; |
365 | node->value[i] = value; |
383 | node->value[i] = value; |
366 | node->subtree[i + 1] = rsubtree; |
384 | node->subtree[i + 1] = rsubtree; |
367 | 385 | ||
368 | node->keys++; |
386 | node->keys++; |
369 | } |
387 | } |
370 | 388 | ||
371 | /** Split full B-tree node and insert new key-value-right-subtree triplet. |
389 | /** Split full B-tree node and insert new key-value-right-subtree triplet. |
372 | * |
390 | * |
373 | * This function will split a node and return pointer to a newly created |
391 | * This function will split a node and return pointer to a newly created |
374 | * node containing keys greater than or equal to the greater of medians |
392 | * node containing keys greater than or equal to the greater of medians |
375 | * (or median) of the old keys and the newly added key. It will also write |
393 | * (or median) of the old keys and the newly added key. It will also write |
376 | * the median key to a memory address supplied by the caller. |
394 | * the median key to a memory address supplied by the caller. |
377 | * |
395 | * |
378 | * If the node being split is an index node, the median will not be |
396 | * If the node being split is an index node, the median will not be |
379 | * included in the new node. If the node is a leaf node, |
397 | * included in the new node. If the node is a leaf node, |
380 | * the median will be copied there. |
398 | * the median will be copied there. |
381 | * |
399 | * |
382 | * @param node B-tree node wich is going to be split. |
400 | * @param node B-tree node wich is going to be split. |
383 | * @param key The key to be inserted. |
401 | * @param key The key to be inserted. |
384 | * @param value Pointer to the value to be inserted. |
402 | * @param value Pointer to the value to be inserted. |
385 | * @param rsubtree Pointer to the right subtree of the key being added. |
403 | * @param rsubtree Pointer to the right subtree of the key being added. |
386 | * @param median Address in memory, where the median key will be stored. |
404 | * @param median Address in memory, where the median key will be stored. |
387 | * |
405 | * |
388 | * @return Newly created right sibling of node. |
406 | * @return Newly created right sibling of node. |
389 | */ |
407 | */ |
390 | btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median) |
408 | btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median) |
391 | { |
409 | { |
392 | btree_node_t *rnode; |
410 | btree_node_t *rnode; |
393 | int i, j; |
411 | int i, j; |
394 | 412 | ||
395 | ASSERT(median); |
413 | ASSERT(median); |
396 | ASSERT(node->keys == BTREE_MAX_KEYS); |
414 | ASSERT(node->keys == BTREE_MAX_KEYS); |
397 | 415 | ||
398 | /* |
416 | /* |
399 | * Use the extra space to store the extra node. |
417 | * Use the extra space to store the extra node. |
400 | */ |
418 | */ |
401 | node_insert_key_right(node, key, value, rsubtree); |
419 | node_insert_key_right(node, key, value, rsubtree); |
402 | 420 | ||
403 | /* |
421 | /* |
404 | * Compute median of keys. |
422 | * Compute median of keys. |
405 | */ |
423 | */ |
406 | *median = MEDIAN_HIGH(node); |
424 | *median = MEDIAN_HIGH(node); |
407 | 425 | ||
408 | /* |
426 | /* |
409 | * Allocate and initialize new right sibling. |
427 | * Allocate and initialize new right sibling. |
410 | */ |
428 | */ |
411 | rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
429 | rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
412 | node_initialize(rnode); |
430 | node_initialize(rnode); |
413 | rnode->parent = node->parent; |
431 | rnode->parent = node->parent; |
414 | rnode->depth = node->depth; |
432 | rnode->depth = node->depth; |
415 | 433 | ||
416 | /* |
434 | /* |
417 | * Copy big keys, values and subtree pointers to the new right sibling. |
435 | * Copy big keys, values and subtree pointers to the new right sibling. |
418 | * If this is an index node, do not copy the median. |
436 | * If this is an index node, do not copy the median. |
419 | */ |
437 | */ |
420 | i = (int) INDEX_NODE(node); |
438 | i = (int) INDEX_NODE(node); |
421 | for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) { |
439 | for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) { |
422 | rnode->key[j] = node->key[i]; |
440 | rnode->key[j] = node->key[i]; |
423 | rnode->value[j] = node->value[i]; |
441 | rnode->value[j] = node->value[i]; |
424 | rnode->subtree[j] = node->subtree[i]; |
442 | rnode->subtree[j] = node->subtree[i]; |
425 | 443 | ||
426 | /* |
444 | /* |
427 | * Fix parent links in subtrees. |
445 | * Fix parent links in subtrees. |
428 | */ |
446 | */ |
429 | if (rnode->subtree[j]) |
447 | if (rnode->subtree[j]) |
430 | rnode->subtree[j]->parent = rnode; |
448 | rnode->subtree[j]->parent = rnode; |
431 | 449 | ||
432 | } |
450 | } |
433 | rnode->subtree[j] = node->subtree[i]; |
451 | rnode->subtree[j] = node->subtree[i]; |
434 | if (rnode->subtree[j]) |
452 | if (rnode->subtree[j]) |
435 | rnode->subtree[j]->parent = rnode; |
453 | rnode->subtree[j]->parent = rnode; |
436 | 454 | ||
437 | rnode->keys = j; /* Set number of keys of the new node. */ |
455 | rnode->keys = j; /* Set number of keys of the new node. */ |
438 | node->keys /= 2; /* Shrink the old node. */ |
456 | node->keys /= 2; /* Shrink the old node. */ |
439 | 457 | ||
440 | return rnode; |
458 | return rnode; |
441 | } |
459 | } |
442 | 460 | ||
443 | /** Remove key and its left subtree pointer from B-tree node. |
461 | /** Remove key and its left subtree pointer from B-tree node. |
444 | * |
462 | * |
445 | * Remove the key and eliminate gaps in node->key array. |
463 | * Remove the key and eliminate gaps in node->key array. |
446 | * Note that the value pointer and the left subtree pointer |
464 | * Note that the value pointer and the left subtree pointer |
447 | * is removed from the node as well. |
465 | * is removed from the node as well. |
448 | * |
466 | * |
449 | * @param node B-tree node. |
467 | * @param node B-tree node. |
450 | * @param key Key to be removed. |
468 | * @param key Key to be removed. |
451 | */ |
469 | */ |
452 | void node_remove_key_left(btree_node_t *node, __native key) |
470 | void node_remove_key_left(btree_node_t *node, __native key) |
453 | { |
471 | { |
454 | int i, j; |
472 | int i, j; |
455 | 473 | ||
456 | for (i = 0; i < node->keys; i++) { |
474 | for (i = 0; i < node->keys; i++) { |
457 | if (key == node->key[i]) { |
475 | if (key == node->key[i]) { |
458 | for (j = i + 1; j < node->keys; j++) { |
476 | for (j = i + 1; j < node->keys; j++) { |
459 | node->key[j - 1] = node->key[j]; |
477 | node->key[j - 1] = node->key[j]; |
460 | node->value[j - 1] = node->value[j]; |
478 | node->value[j - 1] = node->value[j]; |
461 | node->subtree[j - 1] = node->subtree[j]; |
479 | node->subtree[j - 1] = node->subtree[j]; |
462 | } |
480 | } |
463 | node->subtree[j - 1] = node->subtree[j]; |
481 | node->subtree[j - 1] = node->subtree[j]; |
464 | node->keys--; |
482 | node->keys--; |
465 | return; |
483 | return; |
466 | } |
484 | } |
467 | } |
485 | } |
468 | panic("node %P does not contain key %d\n", node, key); |
486 | panic("node %P does not contain key %d\n", node, key); |
469 | } |
487 | } |
470 | 488 | ||
471 | /** Remove key and its right subtree pointer from B-tree node. |
489 | /** Remove key and its right subtree pointer from B-tree node. |
472 | * |
490 | * |
473 | * Remove the key and eliminate gaps in node->key array. |
491 | * Remove the key and eliminate gaps in node->key array. |
474 | * Note that the value pointer and the right subtree pointer |
492 | * Note that the value pointer and the right subtree pointer |
475 | * is removed from the node as well. |
493 | * is removed from the node as well. |
476 | * |
494 | * |
477 | * @param node B-tree node. |
495 | * @param node B-tree node. |
478 | * @param key Key to be removed. |
496 | * @param key Key to be removed. |
479 | */ |
497 | */ |
480 | void node_remove_key_right(btree_node_t *node, __native key) |
498 | void node_remove_key_right(btree_node_t *node, __native key) |
481 | { |
499 | { |
482 | int i, j; |
500 | int i, j; |
483 | 501 | ||
484 | for (i = 0; i < node->keys; i++) { |
502 | for (i = 0; i < node->keys; i++) { |
485 | if (key == node->key[i]) { |
503 | if (key == node->key[i]) { |
486 | for (j = i + 1; j < node->keys; j++) { |
504 | for (j = i + 1; j < node->keys; j++) { |
487 | node->key[j - 1] = node->key[j]; |
505 | node->key[j - 1] = node->key[j]; |
488 | node->value[j - 1] = node->value[j]; |
506 | node->value[j - 1] = node->value[j]; |
489 | node->subtree[j] = node->subtree[j + 1]; |
507 | node->subtree[j] = node->subtree[j + 1]; |
490 | } |
508 | } |
491 | node->keys--; |
509 | node->keys--; |
492 | return; |
510 | return; |
493 | } |
511 | } |
494 | } |
512 | } |
495 | panic("node %P does not contain key %d\n", node, key); |
513 | panic("node %P does not contain key %d\n", node, key); |
496 | } |
514 | } |
497 | 515 | ||
498 | /** Find key by its left or right subtree. |
516 | /** Find key by its left or right subtree. |
499 | * |
517 | * |
500 | * @param node B-tree node. |
518 | * @param node B-tree node. |
501 | * @param subtree Left or right subtree of a key found in node. |
519 | * @param subtree Left or right subtree of a key found in node. |
502 | * @param right If true, subtree is a right subtree. If false, subtree is a left subtree. |
520 | * @param right If true, subtree is a right subtree. If false, subtree is a left subtree. |
503 | * |
521 | * |
504 | * @return Index of the key associated with the subtree. |
522 | * @return Index of the key associated with the subtree. |
505 | */ |
523 | */ |
506 | index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right) |
524 | index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right) |
507 | { |
525 | { |
508 | int i; |
526 | int i; |
509 | 527 | ||
510 | for (i = 0; i < node->keys + 1; i++) { |
528 | for (i = 0; i < node->keys + 1; i++) { |
511 | if (subtree == node->subtree[i]) |
529 | if (subtree == node->subtree[i]) |
512 | return i - (int) (right != false); |
530 | return i - (int) (right != false); |
513 | } |
531 | } |
514 | panic("node %P does not contain subtree %P\n", node, subtree); |
532 | panic("node %P does not contain subtree %P\n", node, subtree); |
515 | } |
533 | } |
516 | 534 | ||
517 | /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done. |
535 | /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done. |
518 | * |
536 | * |
519 | * Left sibling of the node (if it exists) is checked for free space. |
537 | * Left sibling of the node (if it exists) is checked for free space. |
520 | * If there is free space, the key is inserted and the smallest key of |
538 | * If there is free space, the key is inserted and the smallest key of |
521 | * the node is moved there. The index node which is the parent of both |
539 | * the node is moved there. The index node which is the parent of both |
522 | * nodes is fixed. |
540 | * nodes is fixed. |
523 | * |
541 | * |
524 | * @param node B-tree node. |
542 | * @param node B-tree node. |
525 | * @param inskey Key to be inserted. |
543 | * @param inskey Key to be inserted. |
526 | * @param insvalue Value to be inserted. |
544 | * @param insvalue Value to be inserted. |
527 | * @param rsubtree Right subtree of inskey. |
545 | * @param rsubtree Right subtree of inskey. |
528 | * |
546 | * |
529 | * @return True if the rotation was performed, false otherwise. |
547 | * @return True if the rotation was performed, false otherwise. |
530 | */ |
548 | */ |
531 | bool try_insert_by_left_rotation(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree) |
549 | bool try_insert_by_left_rotation(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree) |
532 | { |
550 | { |
533 | index_t idx; |
551 | index_t idx; |
534 | btree_node_t *lnode; |
552 | btree_node_t *lnode; |
535 | 553 | ||
536 | /* |
554 | /* |
537 | * If this is root node, the rotation can not be done. |
555 | * If this is root node, the rotation can not be done. |
538 | */ |
556 | */ |
539 | if (ROOT_NODE(node)) |
557 | if (ROOT_NODE(node)) |
540 | return false; |
558 | return false; |
541 | 559 | ||
542 | idx = find_key_by_subtree(node->parent, node, true); |
560 | idx = find_key_by_subtree(node->parent, node, true); |
543 | if ((int) idx == -1) { |
561 | if ((int) idx == -1) { |
544 | /* |
562 | /* |
545 | * If this node is the leftmost subtree of its parent, |
563 | * If this node is the leftmost subtree of its parent, |
546 | * the rotation can not be done. |
564 | * the rotation can not be done. |
547 | */ |
565 | */ |
548 | return false; |
566 | return false; |
549 | } |
567 | } |
550 | 568 | ||
551 | lnode = node->parent->subtree[idx]; |
569 | lnode = node->parent->subtree[idx]; |
552 | 570 | ||
553 | if (lnode->keys < BTREE_MAX_KEYS) { |
571 | if (lnode->keys < BTREE_MAX_KEYS) { |
554 | __native key; |
572 | __native key; |
555 | 573 | ||
556 | /* |
574 | /* |
557 | * The rotaion can be done. The left sibling has free space. |
575 | * The rotaion can be done. The left sibling has free space. |
558 | */ |
576 | */ |
559 | 577 | ||
560 | node_insert_key_right(node, inskey, insvalue, rsubtree); |
578 | node_insert_key_right(node, inskey, insvalue, rsubtree); |
561 | key = node->key[0]; |
579 | key = node->key[0]; |
562 | 580 | ||
563 | if (LEAF_NODE(node)) { |
581 | if (LEAF_NODE(node)) { |
564 | void *value; |
582 | void *value; |
565 | 583 | ||
566 | value = node->value[0]; |
584 | value = node->value[0]; |
567 | node_remove_key_left(node, key); |
585 | node_remove_key_left(node, key); |
568 | node_insert_key_right(lnode, key, value, NULL); |
586 | node_insert_key_right(lnode, key, value, NULL); |
569 | node->parent->key[idx] = node->key[0]; |
587 | node->parent->key[idx] = node->key[0]; |
570 | } else { |
588 | } else { |
571 | btree_node_t *lsubtree; |
589 | btree_node_t *lsubtree; |
572 | 590 | ||
573 | lsubtree = node->subtree[0]; |
591 | lsubtree = node->subtree[0]; |
574 | node_remove_key_left(node, key); |
592 | node_remove_key_left(node, key); |
575 | node_insert_key_right(lnode, node->parent->key[idx], NULL, lsubtree); |
593 | node_insert_key_right(lnode, node->parent->key[idx], NULL, lsubtree); |
576 | node->parent->key[idx] = key; |
594 | node->parent->key[idx] = key; |
577 | 595 | ||
578 | /* Fix parent link of the reconnected left subtree. */ |
596 | /* Fix parent link of the reconnected left subtree. */ |
579 | lsubtree->parent = lnode; |
597 | lsubtree->parent = lnode; |
580 | } |
598 | } |
581 | return true; |
599 | return true; |
582 | } |
600 | } |
583 | 601 | ||
584 | return false; |
602 | return false; |
585 | } |
603 | } |
586 | 604 | ||
587 | /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done. |
605 | /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done. |
588 | * |
606 | * |
589 | * Right sibling of the node (if it exists) is checked for free space. |
607 | * Right sibling of the node (if it exists) is checked for free space. |
590 | * If there is free space, the key is inserted and the biggest key of |
608 | * If there is free space, the key is inserted and the biggest key of |
591 | * the node is moved there. The index node which is the parent of both |
609 | * the node is moved there. The index node which is the parent of both |
592 | * nodes is fixed. |
610 | * nodes is fixed. |
593 | * |
611 | * |
594 | * @param node B-tree node. |
612 | * @param node B-tree node. |
595 | * @param inskey Key to be inserted. |
613 | * @param inskey Key to be inserted. |
596 | * @param insvalue Value to be inserted. |
614 | * @param insvalue Value to be inserted. |
597 | * @param rsubtree Right subtree of inskey. |
615 | * @param rsubtree Right subtree of inskey. |
598 | * |
616 | * |
599 | * @return True if the rotation was performed, false otherwise. |
617 | * @return True if the rotation was performed, false otherwise. |
600 | */ |
618 | */ |
601 | bool try_insert_by_right_rotation(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree) |
619 | bool try_insert_by_right_rotation(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree) |
602 | { |
620 | { |
603 | index_t idx; |
621 | index_t idx; |
604 | btree_node_t *rnode; |
622 | btree_node_t *rnode; |
605 | 623 | ||
606 | /* |
624 | /* |
607 | * If this is root node, the rotation can not be done. |
625 | * If this is root node, the rotation can not be done. |
608 | */ |
626 | */ |
609 | if (ROOT_NODE(node)) |
627 | if (ROOT_NODE(node)) |
610 | return false; |
628 | return false; |
611 | 629 | ||
612 | idx = find_key_by_subtree(node->parent, node, false); |
630 | idx = find_key_by_subtree(node->parent, node, false); |
613 | if (idx == node->parent->keys) { |
631 | if (idx == node->parent->keys) { |
614 | /* |
632 | /* |
615 | * If this node is the rightmost subtree of its parent, |
633 | * If this node is the rightmost subtree of its parent, |
616 | * the rotation can not be done. |
634 | * the rotation can not be done. |
617 | */ |
635 | */ |
618 | return false; |
636 | return false; |
619 | } |
637 | } |
620 | 638 | ||
621 | rnode = node->parent->subtree[idx + 1]; |
639 | rnode = node->parent->subtree[idx + 1]; |
622 | 640 | ||
623 | if (rnode->keys < BTREE_MAX_KEYS) { |
641 | if (rnode->keys < BTREE_MAX_KEYS) { |
624 | __native key; |
642 | __native key; |
625 | 643 | ||
626 | /* |
644 | /* |
627 | * The rotaion can be done. The right sibling has free space. |
645 | * The rotaion can be done. The right sibling has free space. |
628 | */ |
646 | */ |
629 | 647 | ||
630 | node_insert_key_right(node, inskey, insvalue, rsubtree); |
648 | node_insert_key_right(node, inskey, insvalue, rsubtree); |
631 | key = node->key[node->keys - 1]; |
649 | key = node->key[node->keys - 1]; |
632 | 650 | ||
633 | if (LEAF_NODE(node)) { |
651 | if (LEAF_NODE(node)) { |
634 | void *value; |
652 | void *value; |
635 | 653 | ||
636 | value = node->value[node->keys - 1]; |
654 | value = node->value[node->keys - 1]; |
637 | node_remove_key_right(node, key); |
655 | node_remove_key_right(node, key); |
638 | node_insert_key_left(rnode, key, value, NULL); |
656 | node_insert_key_left(rnode, key, value, NULL); |
639 | node->parent->key[idx] = key; |
657 | node->parent->key[idx] = key; |
640 | } else { |
658 | } else { |
641 | btree_node_t *rsubt; |
659 | btree_node_t *rsubt; |
642 | 660 | ||
643 | rsubt = node->subtree[node->keys]; |
661 | rsubt = node->subtree[node->keys]; |
644 | node_remove_key_right(node, key); |
662 | node_remove_key_right(node, key); |
645 | node_insert_key_left(rnode, node->parent->key[idx], NULL, rsubt); |
663 | node_insert_key_left(rnode, node->parent->key[idx], NULL, rsubt); |
646 | node->parent->key[idx] = key; |
664 | node->parent->key[idx] = key; |
647 | 665 | ||
648 | /* Fix parent link of the reconnected right subtree. */ |
666 | /* Fix parent link of the reconnected right subtree. */ |
649 | rsubt->parent = rnode; |
667 | rsubt->parent = rnode; |
650 | } |
668 | } |
651 | return true; |
669 | return true; |
652 | } |
670 | } |
653 | 671 | ||
654 | return false; |
672 | return false; |
655 | } |
673 | } |
656 | 674 | ||
657 | /** Print B-tree. |
675 | /** Print B-tree. |
658 | * |
676 | * |
659 | * @param t Print out B-tree. |
677 | * @param t Print out B-tree. |
660 | */ |
678 | */ |
661 | void btree_print(btree_t *t) |
679 | void btree_print(btree_t *t) |
662 | { |
680 | { |
663 | int i, depth = t->root->depth; |
681 | int i, depth = t->root->depth; |
664 | link_t head; |
682 | link_t head; |
665 | 683 | ||
666 | list_initialize(&head); |
684 | list_initialize(&head); |
667 | list_append(&t->root->bfs_link, &head); |
685 | list_append(&t->root->bfs_link, &head); |
668 | 686 | ||
669 | /* |
687 | /* |
670 | * Use BFS search to print out the tree. |
688 | * Use BFS search to print out the tree. |
671 | * Levels are distinguished from one another by node->depth. |
689 | * Levels are distinguished from one another by node->depth. |
672 | */ |
690 | */ |
673 | while (!list_empty(&head)) { |
691 | while (!list_empty(&head)) { |
674 | link_t *hlp; |
692 | link_t *hlp; |
675 | btree_node_t *node; |
693 | btree_node_t *node; |
676 | 694 | ||
677 | hlp = head.next; |
695 | hlp = head.next; |
678 | ASSERT(hlp != &head); |
696 | ASSERT(hlp != &head); |
679 | node = list_get_instance(hlp, btree_node_t, bfs_link); |
697 | node = list_get_instance(hlp, btree_node_t, bfs_link); |
680 | list_remove(hlp); |
698 | list_remove(hlp); |
681 | 699 | ||
682 | ASSERT(node); |
700 | ASSERT(node); |
683 | 701 | ||
684 | if (node->depth != depth) { |
702 | if (node->depth != depth) { |
685 | printf("\n"); |
703 | printf("\n"); |
686 | depth = node->depth; |
704 | depth = node->depth; |
687 | } |
705 | } |
688 | 706 | ||
689 | printf("("); |
707 | printf("("); |
690 | for (i = 0; i < node->keys; i++) { |
708 | for (i = 0; i < node->keys; i++) { |
691 | printf("%d,", node->key[i]); |
709 | printf("%d,", node->key[i]); |
692 | if (node->depth && node->subtree[i]) { |
710 | if (node->depth && node->subtree[i]) { |
693 | list_append(&node->subtree[i]->bfs_link, &head); |
711 | list_append(&node->subtree[i]->bfs_link, &head); |
694 | } |
712 | } |
695 | } |
713 | } |
696 | if (node->depth && node->subtree[i]) { |
714 | if (node->depth && node->subtree[i]) { |
697 | list_append(&node->subtree[i]->bfs_link, &head); |
715 | list_append(&node->subtree[i]->bfs_link, &head); |
698 | } |
716 | } |
699 | printf(")"); |
717 | printf(")"); |
700 | } |
718 | } |
701 | printf("\n"); |
719 | printf("\n"); |
702 | } |
720 | } |
703 | 721 |