00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00049 #include <adt/btree.h>
00050 #include <adt/list.h>
00051 #include <mm/slab.h>
00052 #include <debug.h>
00053 #include <panic.h>
00054 #include <typedefs.h>
00055 #include <print.h>
00056
00057 static void btree_destroy_subtree(btree_node_t *root);
00058 static void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node);
00059 static void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node);
00060 static void node_initialize(btree_node_t *node);
00061 static void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree);
00062 static void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
00063 static void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key);
00064 static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key);
00065 static btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median);
00066 static btree_node_t *node_combine(btree_node_t *node);
00067 static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
00068 static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
00069 static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
00070 static bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
00071 static bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
00072 static bool try_rotation_from_left(btree_node_t *rnode);
00073 static bool try_rotation_from_right(btree_node_t *lnode);
00074
00075 #define ROOT_NODE(n) (!(n)->parent)
00076 #define INDEX_NODE(n) ((n)->subtree[0] != NULL)
00077 #define LEAF_NODE(n) ((n)->subtree[0] == NULL)
00078
00079 #define FILL_FACTOR ((BTREE_M-1)/2)
00080
00081 #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2)
00082 #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2)
00083 #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]);
00084 #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]);
00085
00086 static slab_cache_t *btree_node_slab;
00087
00089 void btree_init(void)
00090 {
00091 btree_node_slab = slab_cache_create("btree_node_slab", sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
00092 }
00093
00098 void btree_create(btree_t *t)
00099 {
00100 list_initialize(&t->leaf_head);
00101 t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0);
00102 node_initialize(t->root);
00103 list_append(&t->root->leaf_link, &t->leaf_head);
00104 }
00105
00107 void btree_destroy(btree_t *t)
00108 {
00109 btree_destroy_subtree(t->root);
00110 }
00111
00119 void btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *leaf_node)
00120 {
00121 btree_node_t *lnode;
00122
00123 ASSERT(value);
00124
00125 lnode = leaf_node;
00126 if (!lnode) {
00127 if (btree_search(t, key, &lnode)) {
00128 panic("B-tree %p already contains key %d\n", t, key);
00129 }
00130 }
00131
00132 _btree_insert(t, key, value, NULL, lnode);
00133 }
00134
00139 void btree_destroy_subtree(btree_node_t *root)
00140 {
00141 int i;
00142
00143 if (root->keys) {
00144 for (i = 0; i < root->keys + 1; i++) {
00145 if (root->subtree[i])
00146 btree_destroy_subtree(root->subtree[i]);
00147 }
00148 }
00149 slab_free(btree_node_slab, root);
00150 }
00151
00160 void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node)
00161 {
00162 if (node->keys < BTREE_MAX_KEYS) {
00163
00164
00165
00166 node_insert_key_and_rsubtree(node, key, value, rsubtree);
00167 } else if (try_insert_by_rotation_to_left(node, key, value, rsubtree)) {
00168
00169
00170
00171
00172 } else if (try_insert_by_rotation_to_right(node, key, value, rsubtree)) {
00173
00174
00175
00176
00177 } else {
00178 btree_node_t *rnode;
00179 btree_key_t median;
00180
00181
00182
00183
00184
00185
00186
00187 rnode = node_split(node, key, value, rsubtree, &median);
00188
00189 if (LEAF_NODE(node)) {
00190 list_prepend(&rnode->leaf_link, &node->leaf_link);
00191 }
00192
00193 if (ROOT_NODE(node)) {
00194
00195
00196
00197 t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0);
00198 node->parent = t->root;
00199 rnode->parent = t->root;
00200 node_initialize(t->root);
00201
00202
00203
00204
00205
00206 t->root->subtree[0] = node;
00207
00208 t->root->depth = node->depth + 1;
00209 }
00210 _btree_insert(t, median, NULL, rnode, node->parent);
00211 }
00212
00213 }
00214
00221 void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node)
00222 {
00223 btree_node_t *lnode;
00224
00225 lnode = leaf_node;
00226 if (!lnode) {
00227 if (!btree_search(t, key, &lnode)) {
00228 panic("B-tree %p does not contain key %d\n", t, key);
00229 }
00230 }
00231
00232 _btree_remove(t, key, lnode);
00233 }
00234
00241 void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node)
00242 {
00243 if (ROOT_NODE(node)) {
00244 if (node->keys == 1 && node->subtree[0]) {
00245
00246
00247
00248 t->root = node->subtree[0];
00249 t->root->parent = NULL;
00250 slab_free(btree_node_slab, node);
00251 } else {
00252
00253
00254
00255
00256
00257
00258 node_remove_key_and_rsubtree(node, key);
00259 }
00260 return;
00261 }
00262
00263 if (node->keys <= FILL_FACTOR) {
00264
00265
00266
00267
00268 if (!try_rotation_from_left(node))
00269 try_rotation_from_right(node);
00270 }
00271
00272 if (node->keys > FILL_FACTOR) {
00273 int i;
00274
00275
00276
00277
00278
00279
00280
00281
00282 node_remove_key_and_rsubtree(node, key);
00283 for (i = 0; i < node->parent->keys; i++) {
00284 if (node->parent->key[i] == key)
00285 node->parent->key[i] = node->key[0];
00286 }
00287
00288 } else {
00289 index_t idx;
00290 btree_node_t *rnode, *parent;
00291
00292
00293
00294
00295
00296
00297
00298 parent = node->parent;
00299 node_remove_key_and_rsubtree(node, key);
00300 rnode = node_combine(node);
00301 if (LEAF_NODE(rnode))
00302 list_remove(&rnode->leaf_link);
00303 idx = find_key_by_subtree(parent, rnode, true);
00304 ASSERT((int) idx != -1);
00305 slab_free(btree_node_slab, rnode);
00306 _btree_remove(t, parent->key[idx], parent);
00307 }
00308 }
00309
00318 void *btree_search(btree_t *t, btree_key_t key, btree_node_t **leaf_node)
00319 {
00320 btree_node_t *cur, *next;
00321
00322
00323
00324
00325 for (cur = t->root; cur; cur = next) {
00326
00327
00328 *leaf_node = cur;
00329
00330
00331
00332
00333
00334 if (key < cur->key[0]) {
00335 next = cur->subtree[0];
00336 continue;
00337 } else {
00338 void *val;
00339 int i;
00340
00341
00342
00343
00344
00345
00346 for (i = 1; i < cur->keys; i++) {
00347 if (key < cur->key[i]) {
00348 next = cur->subtree[i];
00349 val = cur->value[i - 1];
00350
00351 if (LEAF_NODE(cur))
00352 return key == cur->key[i - 1] ? val : NULL;
00353
00354 goto descend;
00355 }
00356 }
00357
00358
00359
00360
00361 next = cur->subtree[i];
00362 val = cur->value[i - 1];
00363 if (LEAF_NODE(cur))
00364 return key == cur->key[i - 1] ? val : NULL;
00365 }
00366 descend:
00367 ;
00368 }
00369
00370
00371
00372
00373 return NULL;
00374 }
00375
00383 btree_node_t *btree_leaf_node_left_neighbour(btree_t *t, btree_node_t *node)
00384 {
00385 ASSERT(LEAF_NODE(node));
00386 if (node->leaf_link.prev != &t->leaf_head)
00387 return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
00388 else
00389 return NULL;
00390 }
00391
00399 btree_node_t *btree_leaf_node_right_neighbour(btree_t *t, btree_node_t *node)
00400 {
00401 ASSERT(LEAF_NODE(node));
00402 if (node->leaf_link.next != &t->leaf_head)
00403 return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
00404 else
00405 return NULL;
00406 }
00407
00412 void node_initialize(btree_node_t *node)
00413 {
00414 int i;
00415
00416 node->keys = 0;
00417
00418
00419 for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
00420 node->key[i] = 0;
00421 node->value[i] = NULL;
00422 node->subtree[i] = NULL;
00423 }
00424 node->subtree[i] = NULL;
00425
00426 node->parent = NULL;
00427
00428 link_initialize(&node->leaf_link);
00429
00430 link_initialize(&node->bfs_link);
00431 node->depth = 0;
00432 }
00433
00444 void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree)
00445 {
00446 int i;
00447
00448 for (i = 0; i < node->keys; i++) {
00449 if (key < node->key[i]) {
00450 int j;
00451
00452 for (j = node->keys; j > i; j--) {
00453 node->key[j] = node->key[j - 1];
00454 node->value[j] = node->value[j - 1];
00455 node->subtree[j + 1] = node->subtree[j];
00456 }
00457 node->subtree[j + 1] = node->subtree[j];
00458 break;
00459 }
00460 }
00461 node->key[i] = key;
00462 node->value[i] = value;
00463 node->subtree[i] = lsubtree;
00464
00465 node->keys++;
00466 }
00467
00480 void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree)
00481 {
00482 int i;
00483
00484 for (i = 0; i < node->keys; i++) {
00485 if (key < node->key[i]) {
00486 int j;
00487
00488 for (j = node->keys; j > i; j--) {
00489 node->key[j] = node->key[j - 1];
00490 node->value[j] = node->value[j - 1];
00491 node->subtree[j + 1] = node->subtree[j];
00492 }
00493 break;
00494 }
00495 }
00496 node->key[i] = key;
00497 node->value[i] = value;
00498 node->subtree[i + 1] = rsubtree;
00499
00500 node->keys++;
00501 }
00502
00512 void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key)
00513 {
00514 int i, j;
00515
00516 for (i = 0; i < node->keys; i++) {
00517 if (key == node->key[i]) {
00518 for (j = i + 1; j < node->keys; j++) {
00519 node->key[j - 1] = node->key[j];
00520 node->value[j - 1] = node->value[j];
00521 node->subtree[j - 1] = node->subtree[j];
00522 }
00523 node->subtree[j - 1] = node->subtree[j];
00524 node->keys--;
00525 return;
00526 }
00527 }
00528 panic("node %p does not contain key %d\n", node, key);
00529 }
00530
00540 void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key)
00541 {
00542 int i, j;
00543
00544 for (i = 0; i < node->keys; i++) {
00545 if (key == node->key[i]) {
00546 for (j = i + 1; j < node->keys; j++) {
00547 node->key[j - 1] = node->key[j];
00548 node->value[j - 1] = node->value[j];
00549 node->subtree[j] = node->subtree[j + 1];
00550 }
00551 node->keys--;
00552 return;
00553 }
00554 }
00555 panic("node %p does not contain key %d\n", node, key);
00556 }
00557
00577 btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median)
00578 {
00579 btree_node_t *rnode;
00580 int i, j;
00581
00582 ASSERT(median);
00583 ASSERT(node->keys == BTREE_MAX_KEYS);
00584
00585
00586
00587
00588 node_insert_key_and_rsubtree(node, key, value, rsubtree);
00589
00590
00591
00592
00593 *median = MEDIAN_HIGH(node);
00594
00595
00596
00597
00598 rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0);
00599 node_initialize(rnode);
00600 rnode->parent = node->parent;
00601 rnode->depth = node->depth;
00602
00603
00604
00605
00606
00607 i = (int) INDEX_NODE(node);
00608 for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
00609 rnode->key[j] = node->key[i];
00610 rnode->value[j] = node->value[i];
00611 rnode->subtree[j] = node->subtree[i];
00612
00613
00614
00615
00616 if (rnode->subtree[j])
00617 rnode->subtree[j]->parent = rnode;
00618
00619 }
00620 rnode->subtree[j] = node->subtree[i];
00621 if (rnode->subtree[j])
00622 rnode->subtree[j]->parent = rnode;
00623
00624 rnode->keys = j;
00625 node->keys /= 2;
00626
00627 return rnode;
00628 }
00629
00638 btree_node_t *node_combine(btree_node_t *node)
00639 {
00640 index_t idx;
00641 btree_node_t *rnode;
00642 int i;
00643
00644 ASSERT(!ROOT_NODE(node));
00645
00646 idx = find_key_by_subtree(node->parent, node, false);
00647 if (idx == node->parent->keys) {
00648
00649
00650
00651 idx--;
00652 rnode = node;
00653 node = node->parent->subtree[idx];
00654 } else {
00655 rnode = node->parent->subtree[idx + 1];
00656 }
00657
00658
00659 if (INDEX_NODE(node))
00660 node->key[node->keys++] = node->parent->key[idx];
00661
00662
00663 for (i = 0; i < rnode->keys; i++) {
00664 node->key[node->keys + i] = rnode->key[i];
00665 node->value[node->keys + i] = rnode->value[i];
00666 if (INDEX_NODE(node)) {
00667 node->subtree[node->keys + i] = rnode->subtree[i];
00668 rnode->subtree[i]->parent = node;
00669 }
00670 }
00671 if (INDEX_NODE(node)) {
00672 node->subtree[node->keys + i] = rnode->subtree[i];
00673 rnode->subtree[i]->parent = node;
00674 }
00675
00676 node->keys += rnode->keys;
00677
00678 return rnode;
00679 }
00680
00689 index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
00690 {
00691 int i;
00692
00693 for (i = 0; i < node->keys + 1; i++) {
00694 if (subtree == node->subtree[i])
00695 return i - (int) (right != false);
00696 }
00697 panic("node %p does not contain subtree %p\n", node, subtree);
00698 }
00699
00710 void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
00711 {
00712 btree_key_t key;
00713
00714 key = lnode->key[lnode->keys - 1];
00715
00716 if (LEAF_NODE(lnode)) {
00717 void *value;
00718
00719 value = lnode->value[lnode->keys - 1];
00720 node_remove_key_and_rsubtree(lnode, key);
00721 node_insert_key_and_lsubtree(rnode, key, value, NULL);
00722 lnode->parent->key[idx] = key;
00723 } else {
00724 btree_node_t *rsubtree;
00725
00726 rsubtree = lnode->subtree[lnode->keys];
00727 node_remove_key_and_rsubtree(lnode, key);
00728 node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);
00729 lnode->parent->key[idx] = key;
00730
00731
00732 rsubtree->parent = rnode;
00733 }
00734
00735 }
00736
00747 void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
00748 {
00749 btree_key_t key;
00750
00751 key = rnode->key[0];
00752
00753 if (LEAF_NODE(rnode)) {
00754 void *value;
00755
00756 value = rnode->value[0];
00757 node_remove_key_and_lsubtree(rnode, key);
00758 node_insert_key_and_rsubtree(lnode, key, value, NULL);
00759 rnode->parent->key[idx] = rnode->key[0];
00760 } else {
00761 btree_node_t *lsubtree;
00762
00763 lsubtree = rnode->subtree[0];
00764 node_remove_key_and_lsubtree(rnode, key);
00765 node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);
00766 rnode->parent->key[idx] = key;
00767
00768
00769 lsubtree->parent = lnode;
00770 }
00771
00772 }
00773
00788 bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
00789 {
00790 index_t idx;
00791 btree_node_t *lnode;
00792
00793
00794
00795
00796 if (ROOT_NODE(node))
00797 return false;
00798
00799 idx = find_key_by_subtree(node->parent, node, true);
00800 if ((int) idx == -1) {
00801
00802
00803
00804
00805 return false;
00806 }
00807
00808 lnode = node->parent->subtree[idx];
00809 if (lnode->keys < BTREE_MAX_KEYS) {
00810
00811
00812
00813 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
00814 rotate_from_right(lnode, node, idx);
00815 return true;
00816 }
00817
00818 return false;
00819 }
00820
00835 bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
00836 {
00837 index_t idx;
00838 btree_node_t *rnode;
00839
00840
00841
00842
00843 if (ROOT_NODE(node))
00844 return false;
00845
00846 idx = find_key_by_subtree(node->parent, node, false);
00847 if (idx == node->parent->keys) {
00848
00849
00850
00851
00852 return false;
00853 }
00854
00855 rnode = node->parent->subtree[idx + 1];
00856 if (rnode->keys < BTREE_MAX_KEYS) {
00857
00858
00859
00860 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
00861 rotate_from_left(node, rnode, idx);
00862 return true;
00863 }
00864
00865 return false;
00866 }
00867
00874 bool try_rotation_from_left(btree_node_t *rnode)
00875 {
00876 index_t idx;
00877 btree_node_t *lnode;
00878
00879
00880
00881
00882 if (ROOT_NODE(rnode))
00883 return false;
00884
00885 idx = find_key_by_subtree(rnode->parent, rnode, true);
00886 if ((int) idx == -1) {
00887
00888
00889
00890
00891 return false;
00892 }
00893
00894 lnode = rnode->parent->subtree[idx];
00895 if (lnode->keys > FILL_FACTOR) {
00896 rotate_from_left(lnode, rnode, idx);
00897 return true;
00898 }
00899
00900 return false;
00901 }
00902
00909 bool try_rotation_from_right(btree_node_t *lnode)
00910 {
00911 index_t idx;
00912 btree_node_t *rnode;
00913
00914
00915
00916
00917 if (ROOT_NODE(lnode))
00918 return false;
00919
00920 idx = find_key_by_subtree(lnode->parent, lnode, false);
00921 if (idx == lnode->parent->keys) {
00922
00923
00924
00925
00926 return false;
00927 }
00928
00929 rnode = lnode->parent->subtree[idx + 1];
00930 if (rnode->keys > FILL_FACTOR) {
00931 rotate_from_right(lnode, rnode, idx);
00932 return true;
00933 }
00934
00935 return false;
00936 }
00937
00942 void btree_print(btree_t *t)
00943 {
00944 int i, depth = t->root->depth;
00945 link_t head, *cur;
00946
00947 printf("Printing B-tree:\n");
00948 list_initialize(&head);
00949 list_append(&t->root->bfs_link, &head);
00950
00951
00952
00953
00954
00955 while (!list_empty(&head)) {
00956 link_t *hlp;
00957 btree_node_t *node;
00958
00959 hlp = head.next;
00960 ASSERT(hlp != &head);
00961 node = list_get_instance(hlp, btree_node_t, bfs_link);
00962 list_remove(hlp);
00963
00964 ASSERT(node);
00965
00966 if (node->depth != depth) {
00967 printf("\n");
00968 depth = node->depth;
00969 }
00970
00971 printf("(");
00972 for (i = 0; i < node->keys; i++) {
00973 printf("%lld%s", node->key[i], i < node->keys - 1 ? "," : "");
00974 if (node->depth && node->subtree[i]) {
00975 list_append(&node->subtree[i]->bfs_link, &head);
00976 }
00977 }
00978 if (node->depth && node->subtree[i]) {
00979 list_append(&node->subtree[i]->bfs_link, &head);
00980 }
00981 printf(")");
00982 }
00983 printf("\n");
00984
00985 printf("Printing list of leaves:\n");
00986 for (cur = t->leaf_head.next; cur != &t->leaf_head; cur = cur->next) {
00987 btree_node_t *node;
00988
00989 node = list_get_instance(cur, btree_node_t, leaf_link);
00990
00991 ASSERT(node);
00992
00993 printf("(");
00994 for (i = 0; i < node->keys; i++)
00995 printf("%lld%s", node->key[i], i < node->keys - 1 ? "," : "");
00996 printf(")");
00997 }
00998 printf("\n");
00999 }
01000