btree.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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                  * Node conatins enough space, the key can be stored immediately.
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                  * The key-value-rsubtree triplet has been inserted because
00170                  * some keys could have been moved to the left sibling.
00171                  */
00172         } else if (try_insert_by_rotation_to_right(node, key, value, rsubtree)) {
00173                 /*
00174                  * The key-value-rsubtree triplet has been inserted because
00175                  * some keys could have been moved to the right sibling.
00176                  */
00177         } else {
00178                 btree_node_t *rnode;
00179                 btree_key_t median;
00180                 
00181                 /*
00182                  * Node is full and both siblings (if both exist) are full too.
00183                  * Split the node and insert the smallest key from the node containing
00184                  * bigger keys (i.e. the new node) into its parent.
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                          * We split the root node. Create new root.
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                          * Left-hand side subtree will be the old root (i.e. node).
00204                          * Right-hand side subtree will be rnode.
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                          * Free the current root and set new root.
00247                          */
00248                         t->root = node->subtree[0];
00249                         t->root->parent = NULL;
00250                         slab_free(btree_node_slab, node);
00251                 } else {
00252                         /*
00253                          * Remove the key from the root node.
00254                          * Note that the right subtree is removed because when
00255                          * combining two nodes, the left-side sibling is preserved
00256                          * and the right-side sibling is freed.
00257                          */
00258                         node_remove_key_and_rsubtree(node, key);
00259                 }
00260                 return;
00261         }
00262         
00263         if (node->keys <= FILL_FACTOR) {
00264                 /*
00265                  * If the node is below the fill factor,
00266                  * try to borrow keys from left or right sibling.
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                  * The key can be immediatelly removed.
00277                  *
00278                  * Note that the right subtree is removed because when
00279                  * combining two nodes, the left-side sibling is preserved
00280                  * and the right-side sibling is freed.
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                  * The node is below the fill factor as well as its left and right sibling.
00294                  * Resort to combining the node with one of its siblings.
00295                  * The node which is on the left is preserved and the node on the right is
00296                  * freed.
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          * Iteratively descend to the leaf that can contain the searched key.
00324          */
00325         for (cur = t->root; cur; cur = next) {
00326 
00327                 /* Last iteration will set this with proper leaf node address. */
00328                 *leaf_node = cur;
00329                 
00330                 /*
00331                  * The key can be in the leftmost subtree.
00332                  * Test it separately.
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                          * Now if the key is smaller than cur->key[i]
00343                          * it can only mean that the value is in cur->subtree[i]
00344                          * or it is not in the tree at all.
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                          * Last possibility is that the key is in the rightmost subtree.
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          * The key was not found in the *leaf_node and is smaller than any of its keys.
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         /* Clean also space for the extra key. */
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          * Use the extra space to store the extra node.
00587          */
00588         node_insert_key_and_rsubtree(node, key, value, rsubtree);
00589 
00590         /*
00591          * Compute median of keys.
00592          */
00593         *median = MEDIAN_HIGH(node);
00594                 
00595         /*
00596          * Allocate and initialize new right sibling.
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          * Copy big keys, values and subtree pointers to the new right sibling.
00605          * If this is an index node, do not copy the median.
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                  * Fix parent links in subtrees.
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;        /* Set number of keys of the new node. */
00625         node->keys /= 2;        /* Shrink the old node. */
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                  * Rightmost subtree of its parent, combine with the left sibling.
00650                  */
00651                 idx--;
00652                 rnode = node;
00653                 node = node->parent->subtree[idx];
00654         } else {
00655                 rnode = node->parent->subtree[idx + 1];
00656         }
00657 
00658         /* Index nodes need to insert parent node key in between left and right node. */
00659         if (INDEX_NODE(node))
00660                 node->key[node->keys++] = node->parent->key[idx];
00661         
00662         /* Copy the key-value-subtree triplets from the right node. */
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                 /* Fix parent link of the reconnected right subtree. */
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                 /* Fix parent link of the reconnected left subtree. */
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          * If this is root node, the rotation can not be done.
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                  * If this node is the leftmost subtree of its parent,
00803                  * the rotation can not be done.
00804                  */
00805                 return false;
00806         }
00807                 
00808         lnode = node->parent->subtree[idx];
00809         if (lnode->keys < BTREE_MAX_KEYS) {
00810                 /*
00811                  * The rotaion can be done. The left sibling has free space.
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          * If this is root node, the rotation can not be done.
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                  * If this node is the rightmost subtree of its parent,
00850                  * the rotation can not be done.
00851                  */
00852                 return false;
00853         }
00854                 
00855         rnode = node->parent->subtree[idx + 1];
00856         if (rnode->keys < BTREE_MAX_KEYS) {
00857                 /*
00858                  * The rotaion can be done. The right sibling has free space.
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          * If this is root node, the rotation can not be done.
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                  * If this node is the leftmost subtree of its parent,
00889                  * the rotation can not be done.
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          * If this is root node, the rotation can not be done.
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                  * If this node is the rightmost subtree of its parent,
00924                  * the rotation can not be done.
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          * Use BFS search to print out the tree.
00953          * Levels are distinguished from one another by node->depth.
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 

Generated on Sun Jun 18 17:01:58 2006 for HelenOS Kernel (mips32) by  doxygen 1.4.6