Rev 1121 | Rev 1136 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1121 | Rev 1134 | ||
---|---|---|---|
Line 40... | Line 40... | ||
40 | * directly. |
40 | * directly. |
41 | * - node_split() always creates the right sibling and preserves |
41 | * - node_split() always creates the right sibling and preserves |
42 | * the original node (which becomes the left sibling). |
42 | * the original node (which becomes the left sibling). |
43 | * There is always pointer to the left-hand side subtree |
43 | * There is always pointer to the left-hand side subtree |
44 | * (i.e. left sibling) in the parent node. |
44 | * (i.e. left sibling) in the parent node. |
- | 45 | * |
|
- | 46 | * Be carefull when using these trees. They need to allocate |
|
- | 47 | * and deallocate memory for their index nodes and as such |
|
- | 48 | * can sleep. |
|
45 | */ |
49 | */ |
46 | 50 | ||
47 | #include <adt/btree.h> |
51 | #include <adt/btree.h> |
48 | #include <adt/list.h> |
52 | #include <adt/list.h> |
49 | #include <mm/slab.h> |
53 | #include <mm/slab.h> |
Line 53... | Line 57... | ||
53 | #include <print.h> |
57 | #include <print.h> |
54 | 58 | ||
55 | static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node); |
59 | static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node); |
56 | static void node_initialize(btree_node_t *node); |
60 | static void node_initialize(btree_node_t *node); |
57 | static void node_insert_key(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
61 | static void node_insert_key(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); |
- | 62 | void node_remove_key(btree_node_t *node, __native key); |
|
58 | static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median); |
63 | static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median); |
59 | 64 | ||
60 | #define ROOT_NODE(n) (!(n)->parent) |
65 | #define ROOT_NODE(n) (!(n)->parent) |
61 | #define INDEX_NODE(n) ((n)->subtree[0] != NULL) |
66 | #define INDEX_NODE(n) ((n)->subtree[0] != NULL) |
62 | #define LEAF_NODE(n) ((n)->subtree[0] == NULL) |
67 | #define LEAF_NODE(n) ((n)->subtree[0] == NULL) |
Line 176... | Line 181... | ||
176 | * @return Pointer to value or NULL if there is no such key. |
181 | * @return Pointer to value or NULL if there is no such key. |
177 | */ |
182 | */ |
178 | void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node) |
183 | void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node) |
179 | { |
184 | { |
180 | btree_node_t *cur, *next; |
185 | btree_node_t *cur, *next; |
181 | void *val = NULL; |
- | |
182 | 186 | ||
183 | /* |
187 | /* |
184 | * Iteratively descend to the leaf that can contain searched key. |
188 | * Iteratively descend to the leaf that can contain the searched key. |
185 | */ |
189 | */ |
186 | for (cur = t->root; cur; cur = next) { |
190 | for (cur = t->root; cur; cur = next) { |
187 | int i; |
- | |
188 | 191 | ||
189 | /* Last iteration will set this with proper leaf node address. */ |
192 | /* Last iteration will set this with proper leaf node address. */ |
190 | *leaf_node = cur; |
193 | *leaf_node = cur; |
- | 194 | ||
- | 195 | /* |
|
191 | for (i = 0; i < cur->keys; i++) { |
196 | * The key can be in the leftmost subtree. |
- | 197 | * Test it separately. |
|
- | 198 | */ |
|
192 | if (key <= cur->key[i]) { |
199 | if (key < cur->key[0]) { |
193 | val = cur->value[i]; |
200 | next = cur->subtree[0]; |
194 | next = cur->subtree[i]; |
201 | continue; |
- | 202 | } else { |
|
- | 203 | void *val; |
|
- | 204 | int i; |
|
195 | 205 | ||
196 | /* |
206 | /* |
197 | * Check if there is anywhere to descend. |
207 | * Now if the key is smaller than cur->key[i] |
- | 208 | * it can only mean that the value is in cur->subtree[i] |
|
- | 209 | * or it is not in the tree at all. |
|
198 | */ |
210 | */ |
- | 211 | for (i = 1; i < cur->keys; i++) { |
|
199 | if (!next) { |
212 | if (key < cur->key[i]) { |
200 | /* |
213 | next = cur->subtree[i]; |
201 | * Leaf-level. |
214 | val = cur->value[i - 1]; |
- | 215 | ||
202 | */ |
216 | if (LEAF_NODE(cur)) |
203 | return (key == cur->key[i]) ? val : NULL; |
217 | return key == cur->key[i - 1] ? val : NULL; |
204 | } |
218 | |
205 | goto descend; |
219 | goto descend; |
- | 220 | } |
|
206 | } |
221 | } |
- | 222 | ||
- | 223 | /* |
|
- | 224 | * Last possibility is that the key is in the rightmost subtree. |
|
- | 225 | */ |
|
- | 226 | next = cur->subtree[i]; |
|
- | 227 | val = cur->value[i - 1]; |
|
- | 228 | if (LEAF_NODE(cur)) |
|
- | 229 | return key == cur->key[i - 1] ? val : NULL; |
|
207 | } |
230 | } |
208 | next = cur->subtree[i]; |
- | |
209 | descend: |
231 | descend: |
210 | ; |
232 | ; |
211 | } |
233 | } |
212 | 234 | ||
213 | /* |
235 | /* |
214 | * The key was not found in the *leaf_node and is greater than any of its keys. |
236 | * The key was not found in the *leaf_node and is smaller than any of its keys. |
215 | */ |
237 | */ |
216 | return NULL; |
238 | return NULL; |
217 | } |
239 | } |
218 | 240 | ||
219 | /** Get pointer to value with the smallest key within the node. |
241 | /** Get pointer to value with the smallest key within the node. |
Line 270... | Line 292... | ||
270 | 292 | ||
271 | link_initialize(&node->bfs_link); |
293 | link_initialize(&node->bfs_link); |
272 | node->depth = 0; |
294 | node->depth = 0; |
273 | } |
295 | } |
274 | 296 | ||
275 | /** Insert key-value-left-subtree triplet into B-tree non-full node. |
297 | /** Insert key-value-right-subtree triplet into B-tree non-full node. |
276 | * |
298 | * |
277 | * It is actually possible to have more keys than BTREE_MAX_KEYS. |
299 | * It is actually possible to have more keys than BTREE_MAX_KEYS. |
278 | * This feature is used during splitting the node when the |
300 | * This feature is used during splitting the node when the |
279 | * number of keys is BTREE_MAX_KEYS + 1. |
301 | * number of keys is BTREE_MAX_KEYS + 1. |
280 | * |
302 | * |
Line 305... | Line 327... | ||
305 | node->subtree[i + 1] = rsubtree; |
327 | node->subtree[i + 1] = rsubtree; |
306 | 328 | ||
307 | node->keys++; |
329 | node->keys++; |
308 | } |
330 | } |
309 | 331 | ||
310 | /** Split full B-tree node and insert new key-value-left-subtree triplet. |
332 | /** Split full B-tree node and insert new key-value-right-subtree triplet. |
311 | * |
333 | * |
312 | * This function will split a node and return pointer to a newly created |
334 | * This function will split a node and return pointer to a newly created |
313 | * node containing keys greater than the lesser of medians (or median) |
335 | * node containing keys greater than or equal to the greater of medians |
314 | * of the old keys and the newly added key. It will also write the |
336 | * (or median) of the old keys and the newly added key. It will also write |
315 | * median key to a memory address supplied by the caller. |
337 | * the median key to a memory address supplied by the caller. |
316 | * |
338 | * |
317 | * If the node being split is an index node, the median will be |
339 | * If the node being split is an index node, the median will not be |
318 | * removed from the original node. If the node is a leaf node, |
340 | * included in the new node. If the node is a leaf node, |
319 | * the median will be preserved. |
341 | * the median will be copied there. |
320 | * |
342 | * |
321 | * @param node B-tree node wich is going to be split. |
343 | * @param node B-tree node wich is going to be split. |
322 | * @param key The key to be inserted. |
344 | * @param key The key to be inserted. |
323 | * @param value Pointer to the value to be inserted. |
345 | * @param value Pointer to the value to be inserted. |
324 | * @param rsubtree Pointer to the right subtree of the key being added. |
346 | * @param rsubtree Pointer to the right subtree of the key being added. |
Line 340... | Line 362... | ||
340 | node_insert_key(node, key, value, rsubtree); |
362 | node_insert_key(node, key, value, rsubtree); |
341 | 363 | ||
342 | /* |
364 | /* |
343 | * Compute median of keys. |
365 | * Compute median of keys. |
344 | */ |
366 | */ |
345 | *median = MEDIAN_LOW(node); |
367 | *median = MEDIAN_HIGH(node); |
346 | 368 | ||
- | 369 | /* |
|
- | 370 | * Allocate and initialize new right sibling. |
|
- | 371 | */ |
|
347 | rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
372 | rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0); |
348 | node_initialize(rnode); |
373 | node_initialize(rnode); |
349 | rnode->parent = node->parent; |
374 | rnode->parent = node->parent; |
350 | rnode->depth = node->depth; |
375 | rnode->depth = node->depth; |
351 | 376 | ||
352 | /* |
377 | /* |
353 | * Copy big keys, values and subtree pointers to the new right sibling. |
378 | * Copy big keys, values and subtree pointers to the new right sibling. |
- | 379 | * If this is an index node, do not copy the median. |
|
354 | */ |
380 | */ |
- | 381 | i = (int) INDEX_NODE(node); |
|
355 | for (i = MEDIAN_LOW_INDEX(node) + 1, j = 0; i < node->keys; i++, j++) { |
382 | for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) { |
356 | rnode->key[j] = node->key[i]; |
383 | rnode->key[j] = node->key[i]; |
357 | rnode->value[j] = node->value[i]; |
384 | rnode->value[j] = node->value[i]; |
358 | rnode->subtree[j] = node->subtree[i]; |
385 | rnode->subtree[j] = node->subtree[i]; |
359 | 386 | ||
360 | /* |
387 | /* |
Line 365... | Line 392... | ||
365 | 392 | ||
366 | } |
393 | } |
367 | rnode->subtree[j] = node->subtree[i]; |
394 | rnode->subtree[j] = node->subtree[i]; |
368 | if (rnode->subtree[j]) |
395 | if (rnode->subtree[j]) |
369 | rnode->subtree[j]->parent = rnode; |
396 | rnode->subtree[j]->parent = rnode; |
370 | rnode->keys = j; |
- | |
371 | 397 | ||
372 | /* |
- | |
373 | * Shrink the old node. |
- | |
374 | * If this is an index node, remove the median. |
398 | rnode->keys = j; /* Set number of keys of the new node. */ |
375 | */ |
- | |
376 | node->keys = MEDIAN_LOW_INDEX(node) + 1; |
399 | node->keys /= 2; /* Shrink the old node. */ |
377 | if (INDEX_NODE(node)) |
- | |
378 | node->keys--; |
- | |
379 | 400 | ||
380 | return rnode; |
401 | return rnode; |
381 | } |
402 | } |
382 | 403 | ||
- | 404 | /** Remove key from B-tree node. |
|
- | 405 | * |
|
- | 406 | * @param node B-tree node. |
|
- | 407 | * @param key Key to be removed. |
|
- | 408 | */ |
|
- | 409 | void node_remove_key(btree_node_t *node, __native key) |
|
- | 410 | { |
|
- | 411 | } |
|
- | 412 | ||
383 | /** Print B-tree. |
413 | /** Print B-tree. |
384 | * |
414 | * |
385 | * @param t Print out B-tree. |
415 | * @param t Print out B-tree. |
386 | */ |
416 | */ |
387 | void btree_print(btree_t *t) |
417 | void btree_print(btree_t *t) |