Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/adt/btree.c

    r7a0359b r98000fb  
    3333/**
    3434 * @file
    35  * @brief B+tree implementation.
     35 * @brief       B+tree implementation.
    3636 *
    3737 * This file implements B+tree type and operations.
     
    5353#include <panic.h>
    5454#include <print.h>
    55 #include <trace.h>
     55
     56static void btree_destroy_subtree(btree_node_t *root);
     57static void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node);
     58static void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node);
     59static void node_initialize(btree_node_t *node);
     60static void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree);
     61static void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
     62static void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key);
     63static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key);
     64static btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median);
     65static btree_node_t *node_combine(btree_node_t *node);
     66static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
     67static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
     68static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
     69static bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
     70static bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
     71static bool try_rotation_from_left(btree_node_t *rnode);
     72static bool try_rotation_from_right(btree_node_t *lnode);
     73
     74#define ROOT_NODE(n)            (!(n)->parent)
     75#define INDEX_NODE(n)           ((n)->subtree[0] != NULL)
     76#define LEAF_NODE(n)            ((n)->subtree[0] == NULL)
     77
     78#define FILL_FACTOR             ((BTREE_M-1)/2)
     79
     80#define MEDIAN_LOW_INDEX(n)     (((n)->keys-1)/2)
     81#define MEDIAN_HIGH_INDEX(n)    ((n)->keys/2)
     82#define MEDIAN_LOW(n)           ((n)->key[MEDIAN_LOW_INDEX((n))]);
     83#define MEDIAN_HIGH(n)          ((n)->key[MEDIAN_HIGH_INDEX((n))]);
    5684
    5785static slab_cache_t *btree_node_slab;
    58 
    59 #define ROOT_NODE(n)   (!(n)->parent)
    60 #define INDEX_NODE(n)  ((n)->subtree[0] != NULL)
    61 #define LEAF_NODE(n)   ((n)->subtree[0] == NULL)
    62 
    63 #define FILL_FACTOR  ((BTREE_M - 1) / 2)
    64 
    65 #define MEDIAN_LOW_INDEX(n)   (((n)->keys-1) / 2)
    66 #define MEDIAN_HIGH_INDEX(n)  ((n)->keys / 2)
    67 #define MEDIAN_LOW(n)         ((n)->key[MEDIAN_LOW_INDEX((n))]);
    68 #define MEDIAN_HIGH(n)        ((n)->key[MEDIAN_HIGH_INDEX((n))]);
    6986
    7087/** Initialize B-trees. */
    7188void btree_init(void)
    7289{
    73         btree_node_slab = slab_cache_create("btree_node_slab",
    74             sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    75 }
    76 
    77 /** Initialize B-tree node.
    78  *
    79  * @param node B-tree node.
    80  *
    81  */
    82 NO_TRACE static void node_initialize(btree_node_t *node)
    83 {
    84         unsigned int i;
    85        
    86         node->keys = 0;
    87        
    88         /* Clean also space for the extra key. */
    89         for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
    90                 node->key[i] = 0;
    91                 node->value[i] = NULL;
    92                 node->subtree[i] = NULL;
    93         }
    94        
    95         node->subtree[i] = NULL;
    96         node->parent = NULL;
    97        
    98         link_initialize(&node->leaf_link);
    99         link_initialize(&node->bfs_link);
    100         node->depth = 0;
     90        btree_node_slab = slab_cache_create("btree_node_slab", sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    10191}
    10292
     
    10494 *
    10595 * @param t B-tree.
    106  *
    10796 */
    10897void btree_create(btree_t *t)
     
    114103}
    115104
     105/** Destroy empty B-tree. */
     106void btree_destroy(btree_t *t)
     107{
     108        btree_destroy_subtree(t->root);
     109}
     110
     111/** Insert key-value pair into B-tree.
     112 *
     113 * @param t B-tree.
     114 * @param key Key to be inserted.
     115 * @param value Value to be inserted.
     116 * @param leaf_node Leaf node where the insertion should begin.
     117 */
     118void btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *leaf_node)
     119{
     120        btree_node_t *lnode;
     121       
     122        ASSERT(value);
     123       
     124        lnode = leaf_node;
     125        if (!lnode) {
     126                if (btree_search(t, key, &lnode)) {
     127                        panic("B-tree %p already contains key %" PRIu64 ".", t, key);
     128                }
     129        }
     130       
     131        _btree_insert(t, key, value, NULL, lnode);
     132}
     133
    116134/** Destroy subtree rooted in a node.
    117135 *
    118136 * @param root Root of the subtree.
    119  *
    120  */
    121 NO_TRACE static void btree_destroy_subtree(btree_node_t *root)
     137 */
     138void btree_destroy_subtree(btree_node_t *root)
    122139{
    123140        size_t i;
    124        
     141
    125142        if (root->keys) {
    126143                for (i = 0; i < root->keys + 1; i++) {
     
    129146                }
    130147        }
    131        
    132148        slab_free(btree_node_slab, root);
    133149}
    134150
    135 /** Destroy empty B-tree. */
    136 void btree_destroy(btree_t *t)
    137 {
    138         btree_destroy_subtree(t->root);
    139 }
    140 
    141 /** Insert key-value-rsubtree triplet into B-tree node.
    142  *
    143  * It is actually possible to have more keys than BTREE_MAX_KEYS.
    144  * This feature is used during splitting the node when the
    145  * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation
    146  * also makes use of this feature.
    147  *
    148  * @param node     B-tree node into wich the new key is to be inserted.
    149  * @param key      The key to be inserted.
    150  * @param value    Pointer to value to be inserted.
    151  * @param rsubtree Pointer to the right subtree.
    152  *
    153  */
    154 NO_TRACE static void node_insert_key_and_rsubtree(btree_node_t *node,
    155     btree_key_t key, void *value, btree_node_t *rsubtree)
    156 {
    157         size_t i;
    158        
    159         for (i = 0; i < node->keys; i++) {
    160                 if (key < node->key[i]) {
    161                         size_t j;
    162                        
    163                         for (j = node->keys; j > i; j--) {
    164                                 node->key[j] = node->key[j - 1];
    165                                 node->value[j] = node->value[j - 1];
    166                                 node->subtree[j + 1] = node->subtree[j];
    167                         }
    168                        
    169                         break;
    170                 }
    171         }
    172        
    173         node->key[i] = key;
    174         node->value[i] = value;
    175         node->subtree[i + 1] = rsubtree;
    176         node->keys++;
    177 }
    178 
    179 /** Find key by its left or right subtree.
    180  *
    181  * @param node    B-tree node.
    182  * @param subtree Left or right subtree of a key found in node.
    183  * @param right   If true, subtree is a right subtree. If false,
    184  *                subtree is a left subtree.
    185  *
    186  * @return Index of the key associated with the subtree.
    187  *
    188  */
    189 NO_TRACE static size_t find_key_by_subtree(btree_node_t *node,
    190     btree_node_t *subtree, bool right)
    191 {
    192         size_t i;
    193        
    194         for (i = 0; i < node->keys + 1; i++) {
    195                 if (subtree == node->subtree[i])
    196                         return i - (int) (right != false);
    197         }
    198        
    199         panic("Node %p does not contain subtree %p.", node, subtree);
    200 }
    201 
    202 /** Remove key and its left subtree pointer from B-tree node.
    203  *
    204  * Remove the key and eliminate gaps in node->key array.
    205  * Note that the value pointer and the left subtree pointer
    206  * is removed from the node as well.
    207  *
    208  * @param node B-tree node.
    209  * @param key  Key to be removed.
    210  *
    211  */
    212 NO_TRACE static void node_remove_key_and_lsubtree(btree_node_t *node,
    213     btree_key_t key)
    214 {
    215         size_t i;
    216         size_t j;
    217        
    218         for (i = 0; i < node->keys; i++) {
    219                 if (key == node->key[i]) {
    220                         for (j = i + 1; j < node->keys; j++) {
    221                                 node->key[j - 1] = node->key[j];
    222                                 node->value[j - 1] = node->value[j];
    223                                 node->subtree[j - 1] = node->subtree[j];
    224                         }
    225                        
    226                         node->subtree[j - 1] = node->subtree[j];
    227                         node->keys--;
    228                        
    229                         return;
    230                 }
    231         }
    232        
    233         panic("Node %p does not contain key %" PRIu64 ".", node, key);
    234 }
    235 
    236 /** Remove key and its right subtree pointer from B-tree node.
    237  *
    238  * Remove the key and eliminate gaps in node->key array.
    239  * Note that the value pointer and the right subtree pointer
    240  * is removed from the node as well.
    241  *
    242  * @param node B-tree node.
    243  * @param key  Key to be removed.
    244  *
    245  */
    246 NO_TRACE static void node_remove_key_and_rsubtree(btree_node_t *node,
    247     btree_key_t key)
    248 {
    249         size_t i, j;
    250        
    251         for (i = 0; i < node->keys; i++) {
    252                 if (key == node->key[i]) {
    253                         for (j = i + 1; j < node->keys; j++) {
    254                                 node->key[j - 1] = node->key[j];
    255                                 node->value[j - 1] = node->value[j];
    256                                 node->subtree[j] = node->subtree[j + 1];
    257                         }
    258                        
    259                         node->keys--;
    260                         return;
    261                 }
    262         }
    263        
    264         panic("Node %p does not contain key %" PRIu64 ".", node, key);
    265 }
    266 
    267 /** Insert key-value-lsubtree triplet into B-tree node.
    268  *
    269  * It is actually possible to have more keys than BTREE_MAX_KEYS.
    270  * This feature is used during insert by right rotation.
    271  *
    272  * @param node     B-tree node into wich the new key is to be inserted.
    273  * @param key      The key to be inserted.
    274  * @param value    Pointer to value to be inserted.
    275  * @param lsubtree Pointer to the left subtree.
    276  *
    277  */
    278 NO_TRACE static void node_insert_key_and_lsubtree(btree_node_t *node,
    279     btree_key_t key, void *value, btree_node_t *lsubtree)
    280 {
    281         size_t i;
    282        
    283         for (i = 0; i < node->keys; i++) {
    284                 if (key < node->key[i]) {
    285                         size_t j;
    286                        
    287                         for (j = node->keys; j > i; j--) {
    288                                 node->key[j] = node->key[j - 1];
    289                                 node->value[j] = node->value[j - 1];
    290                                 node->subtree[j + 1] = node->subtree[j];
    291                         }
    292                        
    293                         node->subtree[j + 1] = node->subtree[j];
    294                         break;
    295                 }
    296         }
    297        
    298         node->key[i] = key;
    299         node->value[i] = value;
    300         node->subtree[i] = lsubtree;
    301        
    302         node->keys++;
    303 }
    304 
    305 /** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
    306  *
    307  * The biggest key and its value and right subtree is rotated
    308  * from the left node to the right. If the node is an index node,
    309  * than the parent node key belonging to the left node takes part
    310  * in the rotation.
    311  *
    312  * @param lnode Left sibling.
    313  * @param rnode Right sibling.
    314  * @param idx   Index of the parent node key that is taking part
    315  *              in the rotation.
    316  *
    317  */
    318 NO_TRACE static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode,
    319     size_t idx)
    320 {
    321         btree_key_t key = lnode->key[lnode->keys - 1];
    322        
    323         if (LEAF_NODE(lnode)) {
    324                 void *value = lnode->value[lnode->keys - 1];
    325                
    326                 node_remove_key_and_rsubtree(lnode, key);
    327                 node_insert_key_and_lsubtree(rnode, key, value, NULL);
    328                 lnode->parent->key[idx] = key;
    329         } else {
    330                 btree_node_t *rsubtree = lnode->subtree[lnode->keys];
    331                
    332                 node_remove_key_and_rsubtree(lnode, key);
    333                 node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);
    334                 lnode->parent->key[idx] = key;
    335                
    336                 /* Fix parent link of the reconnected right subtree. */
    337                 rsubtree->parent = rnode;
    338         }
    339 }
    340 
    341 /** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.
    342  *
    343  * The smallest key and its value and left subtree is rotated
    344  * from the right node to the left. If the node is an index node,
    345  * than the parent node key belonging to the right node takes part
    346  * in the rotation.
    347  *
    348  * @param lnode Left sibling.
    349  * @param rnode Right sibling.
    350  * @param idx   Index of the parent node key that is taking part
    351  *              in the rotation.
    352  *
    353  */
    354 NO_TRACE static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode,
    355     size_t idx)
    356 {
    357         btree_key_t key = rnode->key[0];
    358        
    359         if (LEAF_NODE(rnode)) {
    360                 void *value = rnode->value[0];
    361                
    362                 node_remove_key_and_lsubtree(rnode, key);
    363                 node_insert_key_and_rsubtree(lnode, key, value, NULL);
    364                 rnode->parent->key[idx] = rnode->key[0];
    365         } else {
    366                 btree_node_t *lsubtree = rnode->subtree[0];
    367                
    368                 node_remove_key_and_lsubtree(rnode, key);
    369                 node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);
    370                 rnode->parent->key[idx] = key;
    371                
    372                 /* Fix parent link of the reconnected left subtree. */
    373                 lsubtree->parent = lnode;
    374         }
    375 }
    376 
    377 /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.
    378  *
    379  * Left sibling of the node (if it exists) is checked for free space.
    380  * If there is free space, the key is inserted and the smallest key of
    381  * the node is moved there. The index node which is the parent of both
    382  * nodes is fixed.
    383  *
    384  * @param node     B-tree node.
    385  * @param inskey   Key to be inserted.
    386  * @param insvalue Value to be inserted.
    387  * @param rsubtree Right subtree of inskey.
    388  *
    389  * @return True if the rotation was performed, false otherwise.
    390  *
    391  */
    392 NO_TRACE static bool try_insert_by_rotation_to_left(btree_node_t *node,
    393     btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
    394 {
    395         size_t idx;
    396         btree_node_t *lnode;
    397        
    398         /*
    399          * If this is root node, the rotation can not be done.
    400          */
    401         if (ROOT_NODE(node))
    402                 return false;
    403        
    404         idx = find_key_by_subtree(node->parent, node, true);
    405         if ((int) idx == -1) {
    406                 /*
    407                  * If this node is the leftmost subtree of its parent,
    408                  * the rotation can not be done.
    409                  */
    410                 return false;
    411         }
    412        
    413         lnode = node->parent->subtree[idx];
    414         if (lnode->keys < BTREE_MAX_KEYS) {
    415                 /*
    416                  * The rotaion can be done. The left sibling has free space.
    417                  */
    418                 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
    419                 rotate_from_right(lnode, node, idx);
    420                 return true;
    421         }
    422        
    423         return false;
    424 }
    425 
    426 /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.
    427  *
    428  * Right sibling of the node (if it exists) is checked for free space.
    429  * If there is free space, the key is inserted and the biggest key of
    430  * the node is moved there. The index node which is the parent of both
    431  * nodes is fixed.
    432  *
    433  * @param node     B-tree node.
    434  * @param inskey   Key to be inserted.
    435  * @param insvalue Value to be inserted.
    436  * @param rsubtree Right subtree of inskey.
    437  *
    438  * @return True if the rotation was performed, false otherwise.
    439  *
    440  */
    441 NO_TRACE static bool try_insert_by_rotation_to_right(btree_node_t *node,
    442     btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
    443 {
    444         size_t idx;
    445         btree_node_t *rnode;
    446        
    447         /*
    448          * If this is root node, the rotation can not be done.
    449          */
    450         if (ROOT_NODE(node))
    451                 return false;
    452        
    453         idx = find_key_by_subtree(node->parent, node, false);
    454         if (idx == node->parent->keys) {
    455                 /*
    456                  * If this node is the rightmost subtree of its parent,
    457                  * the rotation can not be done.
    458                  */
    459                 return false;
    460         }
    461        
    462         rnode = node->parent->subtree[idx + 1];
    463         if (rnode->keys < BTREE_MAX_KEYS) {
    464                 /*
    465                  * The rotaion can be done. The right sibling has free space.
    466                  */
    467                 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
    468                 rotate_from_left(node, rnode, idx);
    469                 return true;
    470         }
    471        
    472         return false;
    473 }
    474 
    475 /** Split full B-tree node and insert new key-value-right-subtree triplet.
    476  *
    477  * This function will split a node and return a pointer to a newly created
    478  * node containing keys greater than or equal to the greater of medians
    479  * (or median) of the old keys and the newly added key. It will also write
    480  * the median key to a memory address supplied by the caller.
    481  *
    482  * If the node being split is an index node, the median will not be
    483  * included in the new node. If the node is a leaf node,
    484  * the median will be copied there.
    485  *
    486  * @param node     B-tree node wich is going to be split.
    487  * @param key      The key to be inserted.
    488  * @param value    Pointer to the value to be inserted.
    489  * @param rsubtree Pointer to the right subtree of the key being added.
    490  * @param median   Address in memory, where the median key will be stored.
    491  *
    492  * @return Newly created right sibling of node.
    493  *
    494  */
    495 NO_TRACE static btree_node_t *node_split(btree_node_t *node, btree_key_t key,
    496     void *value, btree_node_t *rsubtree, btree_key_t *median)
    497 {
    498         btree_node_t *rnode;
    499         size_t i;
    500         size_t j;
    501        
    502         ASSERT(median);
    503         ASSERT(node->keys == BTREE_MAX_KEYS);
    504        
    505         /*
    506          * Use the extra space to store the extra node.
    507          */
    508         node_insert_key_and_rsubtree(node, key, value, rsubtree);
    509        
    510         /*
    511          * Compute median of keys.
    512          */
    513         *median = MEDIAN_HIGH(node);
    514        
    515         /*
    516          * Allocate and initialize new right sibling.
    517          */
    518         rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0);
    519         node_initialize(rnode);
    520         rnode->parent = node->parent;
    521         rnode->depth = node->depth;
    522        
    523         /*
    524          * Copy big keys, values and subtree pointers to the new right sibling.
    525          * If this is an index node, do not copy the median.
    526          */
    527         i = (size_t) INDEX_NODE(node);
    528         for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
    529                 rnode->key[j] = node->key[i];
    530                 rnode->value[j] = node->value[i];
    531                 rnode->subtree[j] = node->subtree[i];
    532                
    533                 /*
    534                  * Fix parent links in subtrees.
    535                  */
    536                 if (rnode->subtree[j])
    537                         rnode->subtree[j]->parent = rnode;
    538         }
    539        
    540         rnode->subtree[j] = node->subtree[i];
    541         if (rnode->subtree[j])
    542                 rnode->subtree[j]->parent = rnode;
    543        
    544         rnode->keys = j;  /* Set number of keys of the new node. */
    545         node->keys /= 2;  /* Shrink the old node. */
    546        
    547         return rnode;
    548 }
    549 
    550151/** Recursively insert into B-tree.
    551152 *
    552  * @param t        B-tree.
    553  * @param key      Key to be inserted.
    554  * @param value    Value to be inserted.
     153 * @param t B-tree.
     154 * @param key Key to be inserted.
     155 * @param value Value to be inserted.
    555156 * @param rsubtree Right subtree of the inserted key.
    556  * @param node     Start inserting into this node.
    557  *
    558  */
    559 NO_TRACE static void _btree_insert(btree_t *t, btree_key_t key, void *value,
    560     btree_node_t *rsubtree, btree_node_t *node)
     157 * @param node Start inserting into this node.
     158 */
     159void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node)
    561160{
    562161        if (node->keys < BTREE_MAX_KEYS) {
     
    584183                 * bigger keys (i.e. the new node) into its parent.
    585184                 */
    586                
     185
    587186                rnode = node_split(node, key, value, rsubtree, &median);
    588                
     187
    589188                if (LEAF_NODE(node)) {
    590189                        list_prepend(&rnode->leaf_link, &node->leaf_link);
     
    603202                         * Left-hand side subtree will be the old root (i.e. node).
    604203                         * Right-hand side subtree will be rnode.
    605                          */
     204                         */                     
    606205                        t->root->subtree[0] = node;
    607                        
     206
    608207                        t->root->depth = node->depth + 1;
    609208                }
    610209                _btree_insert(t, median, NULL, rnode, node->parent);
    611         }
    612 }
    613 
    614 /** Insert key-value pair into B-tree.
    615  *
    616  * @param t         B-tree.
    617  * @param key       Key to be inserted.
    618  * @param value     Value to be inserted.
    619  * @param leaf_node Leaf node where the insertion should begin.
    620  *
    621  */
    622 void btree_insert(btree_t *t, btree_key_t key, void *value,
    623     btree_node_t *leaf_node)
     210        }       
     211               
     212}
     213
     214/** Remove B-tree node.
     215 *
     216 * @param t B-tree.
     217 * @param key Key to be removed from the B-tree along with its associated value.
     218 * @param leaf_node If not NULL, pointer to the leaf node where the key is found.
     219 */
     220void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node)
    624221{
    625222        btree_node_t *lnode;
    626        
    627         ASSERT(value);
    628223       
    629224        lnode = leaf_node;
    630225        if (!lnode) {
    631                 if (btree_search(t, key, &lnode))
    632                         panic("B-tree %p already contains key %" PRIu64 ".", t, key);
    633         }
    634        
    635         _btree_insert(t, key, value, NULL, lnode);
    636 }
    637 
    638 /** Rotate in a key from the left sibling or from the index node, if this operation can be done.
    639  *
    640  * @param rnode Node into which to add key from its left sibling
    641  *              or from the index node.
    642  *
    643  * @return True if the rotation was performed, false otherwise.
    644  *
    645  */
    646 NO_TRACE static bool try_rotation_from_left(btree_node_t *rnode)
    647 {
    648         size_t idx;
    649         btree_node_t *lnode;
    650        
    651         /*
    652          * If this is root node, the rotation can not be done.
    653          */
    654         if (ROOT_NODE(rnode))
    655                 return false;
    656        
    657         idx = find_key_by_subtree(rnode->parent, rnode, true);
    658         if ((int) idx == -1) {
    659                 /*
    660                  * If this node is the leftmost subtree of its parent,
    661                  * the rotation can not be done.
    662                  */
    663                 return false;
    664         }
    665        
    666         lnode = rnode->parent->subtree[idx];
    667         if (lnode->keys > FILL_FACTOR) {
    668                 rotate_from_left(lnode, rnode, idx);
    669                 return true;
    670         }
    671        
    672         return false;
    673 }
    674 
    675 /** Rotate in a key from the right sibling or from the index node, if this operation can be done.
    676  *
    677  * @param lnode Node into which to add key from its right sibling
    678  *              or from the index node.
    679  *
    680  * @return True if the rotation was performed, false otherwise.
    681  *
    682  */
    683 NO_TRACE static bool try_rotation_from_right(btree_node_t *lnode)
    684 {
    685         size_t idx;
    686         btree_node_t *rnode;
    687        
    688         /*
    689          * If this is root node, the rotation can not be done.
    690          */
    691         if (ROOT_NODE(lnode))
    692                 return false;
    693        
    694         idx = find_key_by_subtree(lnode->parent, lnode, false);
    695         if (idx == lnode->parent->keys) {
    696                 /*
    697                  * If this node is the rightmost subtree of its parent,
    698                  * the rotation can not be done.
    699                  */
    700                 return false;
    701         }
    702        
    703         rnode = lnode->parent->subtree[idx + 1];
    704         if (rnode->keys > FILL_FACTOR) {
    705                 rotate_from_right(lnode, rnode, idx);
    706                 return true;
    707         }
    708        
    709         return false;
    710 }
    711 
    712 /** Combine node with any of its siblings.
    713  *
    714  * The siblings are required to be below the fill factor.
    715  *
    716  * @param node Node to combine with one of its siblings.
    717  *
    718  * @return Pointer to the rightmost of the two nodes.
    719  *
    720  */
    721 NO_TRACE static btree_node_t *node_combine(btree_node_t *node)
    722 {
    723         size_t idx;
    724         btree_node_t *rnode;
    725         size_t i;
    726        
    727         ASSERT(!ROOT_NODE(node));
    728        
    729         idx = find_key_by_subtree(node->parent, node, false);
    730         if (idx == node->parent->keys) {
    731                 /*
    732                  * Rightmost subtree of its parent, combine with the left sibling.
    733                  */
    734                 idx--;
    735                 rnode = node;
    736                 node = node->parent->subtree[idx];
    737         } else
    738                 rnode = node->parent->subtree[idx + 1];
    739        
    740         /* Index nodes need to insert parent node key in between left and right node. */
    741         if (INDEX_NODE(node))
    742                 node->key[node->keys++] = node->parent->key[idx];
    743        
    744         /* Copy the key-value-subtree triplets from the right node. */
    745         for (i = 0; i < rnode->keys; i++) {
    746                 node->key[node->keys + i] = rnode->key[i];
    747                 node->value[node->keys + i] = rnode->value[i];
    748                
    749                 if (INDEX_NODE(node)) {
    750                         node->subtree[node->keys + i] = rnode->subtree[i];
    751                         rnode->subtree[i]->parent = node;
    752                 }
    753         }
    754        
    755         if (INDEX_NODE(node)) {
    756                 node->subtree[node->keys + i] = rnode->subtree[i];
    757                 rnode->subtree[i]->parent = node;
    758         }
    759        
    760         node->keys += rnode->keys;
    761         return rnode;
     226                if (!btree_search(t, key, &lnode)) {
     227                        panic("B-tree %p does not contain key %" PRIu64 ".", t, key);
     228                }
     229        }
     230       
     231        _btree_remove(t, key, lnode);
    762232}
    763233
    764234/** Recursively remove B-tree node.
    765235 *
    766  * @param t    B-tree.
    767  * @param key  Key to be removed from the B-tree along with its associated value.
     236 * @param t B-tree.
     237 * @param key Key to be removed from the B-tree along with its associated value.
    768238 * @param node Node where the key being removed resides.
    769  *
    770  */
    771 NO_TRACE static void _btree_remove(btree_t *t, btree_key_t key,
    772     btree_node_t *node)
     239 */
     240void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node)
    773241{
    774242        if (ROOT_NODE(node)) {
    775                 if ((node->keys == 1) && (node->subtree[0])) {
     243                if (node->keys == 1 && node->subtree[0]) {
    776244                        /*
    777245                         * Free the current root and set new root.
     
    789257                        node_remove_key_and_rsubtree(node, key);
    790258                }
    791                
    792259                return;
    793260        }
     
    804271        if (node->keys > FILL_FACTOR) {
    805272                size_t i;
    806                
     273
    807274                /*
    808275                 * The key can be immediatelly removed.
     
    813280                 */
    814281                node_remove_key_and_rsubtree(node, key);
    815                
    816282                for (i = 0; i < node->parent->keys; i++) {
    817283                        if (node->parent->key[i] == key)
    818284                                node->parent->key[i] = node->key[0];
    819285                }
     286               
    820287        } else {
    821288                size_t idx;
    822                 btree_node_t *rnode;
    823                 btree_node_t *parent;
    824                
     289                btree_node_t *rnode, *parent;
     290
    825291                /*
    826292                 * The node is below the fill factor as well as its left and right sibling.
     
    832298                node_remove_key_and_rsubtree(node, key);
    833299                rnode = node_combine(node);
    834                
    835300                if (LEAF_NODE(rnode))
    836301                        list_remove(&rnode->leaf_link);
    837                
    838302                idx = find_key_by_subtree(parent, rnode, true);
    839303                ASSERT((int) idx != -1);
     
    843307}
    844308
    845 /** Remove B-tree node.
    846  *
    847  * @param t         B-tree.
    848  * @param key       Key to be removed from the B-tree along
    849  *                  with its associated value.
    850  * @param leaf_node If not NULL, pointer to the leaf node where
    851  *                  the key is found.
    852  *
    853  */
    854 void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node)
    855 {
    856         btree_node_t *lnode;
    857        
    858         lnode = leaf_node;
    859         if (!lnode) {
    860                 if (!btree_search(t, key, &lnode))
    861                         panic("B-tree %p does not contain key %" PRIu64 ".", t, key);
    862         }
    863        
    864         _btree_remove(t, key, lnode);
    865 }
    866 
    867309/** Search key in a B-tree.
    868310 *
    869  * @param t         B-tree.
    870  * @param key       Key to be searched.
     311 * @param t B-tree.
     312 * @param key Key to be searched.
    871313 * @param leaf_node Address where to put pointer to visited leaf node.
    872314 *
    873315 * @return Pointer to value or NULL if there is no such key.
    874  *
    875316 */
    876317void *btree_search(btree_t *t, btree_key_t key, btree_node_t **leaf_node)
     
    882323         */
    883324        for (cur = t->root; cur; cur = next) {
    884                 /*
    885                  * Last iteration will set this with proper
    886                  * leaf node address.
    887                  */
     325
     326                /* Last iteration will set this with proper leaf node address. */
    888327                *leaf_node = cur;
    889328               
     
    898337                        void *val;
    899338                        size_t i;
    900                        
     339               
    901340                        /*
    902341                         * Now if the key is smaller than cur->key[i]
     
    908347                                        next = cur->subtree[i];
    909348                                        val = cur->value[i - 1];
    910                                        
     349
    911350                                        if (LEAF_NODE(cur))
    912351                                                return key == cur->key[i - 1] ? val : NULL;
    913                                        
     352
    914353                                        goto descend;
    915                                 }
     354                                } 
    916355                        }
    917356                       
    918357                        /*
    919                          * Last possibility is that the key is
    920                          * in the rightmost subtree.
     358                         * Last possibility is that the key is in the rightmost subtree.
    921359                         */
    922360                        next = cur->subtree[i];
    923361                        val = cur->value[i - 1];
    924                        
    925362                        if (LEAF_NODE(cur))
    926363                                return key == cur->key[i - 1] ? val : NULL;
    927364                }
    928365                descend:
    929                 ;
    930         }
    931        
     366                        ;
     367        }
     368
    932369        /*
    933          * The key was not found in the *leaf_node and
    934          * is smaller than any of its keys.
     370         * The key was not found in the *leaf_node and is smaller than any of its keys.
    935371         */
    936372        return NULL;
     
    939375/** Return pointer to B-tree leaf node's left neighbour.
    940376 *
    941  * @param t    B-tree.
     377 * @param t B-tree.
    942378 * @param node Node whose left neighbour will be returned.
    943379 *
    944  * @return Left neighbour of the node or NULL if the node
    945  *         does not have the left neighbour.
    946  *
     380 * @return Left neighbour of the node or NULL if the node does not have the left neighbour.
    947381 */
    948382btree_node_t *btree_leaf_node_left_neighbour(btree_t *t, btree_node_t *node)
    949383{
    950384        ASSERT(LEAF_NODE(node));
    951        
    952385        if (node->leaf_link.prev != &t->leaf_head)
    953386                return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
     
    958391/** Return pointer to B-tree leaf node's right neighbour.
    959392 *
    960  * @param t    B-tree.
     393 * @param t B-tree.
    961394 * @param node Node whose right neighbour will be returned.
    962395 *
    963  * @return Right neighbour of the node or NULL if the node
    964  *         does not have the right neighbour.
    965  *
     396 * @return Right neighbour of the node or NULL if the node does not have the right neighbour.
    966397 */
    967398btree_node_t *btree_leaf_node_right_neighbour(btree_t *t, btree_node_t *node)
    968399{
    969400        ASSERT(LEAF_NODE(node));
    970        
    971401        if (node->leaf_link.next != &t->leaf_head)
    972402                return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
     
    975405}
    976406
     407/** Initialize B-tree node.
     408 *
     409 * @param node B-tree node.
     410 */
     411void node_initialize(btree_node_t *node)
     412{
     413        int i;
     414
     415        node->keys = 0;
     416       
     417        /* Clean also space for the extra key. */
     418        for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
     419                node->key[i] = 0;
     420                node->value[i] = NULL;
     421                node->subtree[i] = NULL;
     422        }
     423        node->subtree[i] = NULL;
     424       
     425        node->parent = NULL;
     426       
     427        link_initialize(&node->leaf_link);
     428
     429        link_initialize(&node->bfs_link);
     430        node->depth = 0;
     431}
     432
     433/** Insert key-value-lsubtree triplet into B-tree node.
     434 *
     435 * It is actually possible to have more keys than BTREE_MAX_KEYS.
     436 * This feature is used during insert by right rotation.
     437 *
     438 * @param node B-tree node into wich the new key is to be inserted.
     439 * @param key The key to be inserted.
     440 * @param value Pointer to value to be inserted.
     441 * @param lsubtree Pointer to the left subtree.
     442 */
     443void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree)
     444{
     445        size_t i;
     446
     447        for (i = 0; i < node->keys; i++) {
     448                if (key < node->key[i]) {
     449                        size_t j;
     450               
     451                        for (j = node->keys; j > i; j--) {
     452                                node->key[j] = node->key[j - 1];
     453                                node->value[j] = node->value[j - 1];
     454                                node->subtree[j + 1] = node->subtree[j];
     455                        }
     456                        node->subtree[j + 1] = node->subtree[j];
     457                        break; 
     458                }
     459        }
     460        node->key[i] = key;
     461        node->value[i] = value;
     462        node->subtree[i] = lsubtree;
     463                       
     464        node->keys++;
     465}
     466
     467/** Insert key-value-rsubtree triplet into B-tree node.
     468 *
     469 * It is actually possible to have more keys than BTREE_MAX_KEYS.
     470 * This feature is used during splitting the node when the
     471 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation
     472 * also makes use of this feature.
     473 *
     474 * @param node B-tree node into wich the new key is to be inserted.
     475 * @param key The key to be inserted.
     476 * @param value Pointer to value to be inserted.
     477 * @param rsubtree Pointer to the right subtree.
     478 */
     479void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree)
     480{
     481        size_t i;
     482
     483        for (i = 0; i < node->keys; i++) {
     484                if (key < node->key[i]) {
     485                        size_t j;
     486               
     487                        for (j = node->keys; j > i; j--) {
     488                                node->key[j] = node->key[j - 1];
     489                                node->value[j] = node->value[j - 1];
     490                                node->subtree[j + 1] = node->subtree[j];
     491                        }
     492                        break; 
     493                }
     494        }
     495        node->key[i] = key;
     496        node->value[i] = value;
     497        node->subtree[i + 1] = rsubtree;
     498                       
     499        node->keys++;
     500}
     501
     502/** Remove key and its left subtree pointer from B-tree node.
     503 *
     504 * Remove the key and eliminate gaps in node->key array.
     505 * Note that the value pointer and the left subtree pointer
     506 * is removed from the node as well.
     507 *
     508 * @param node B-tree node.
     509 * @param key Key to be removed.
     510 */
     511void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key)
     512{
     513        size_t i, j;
     514       
     515        for (i = 0; i < node->keys; i++) {
     516                if (key == node->key[i]) {
     517                        for (j = i + 1; j < node->keys; j++) {
     518                                node->key[j - 1] = node->key[j];
     519                                node->value[j - 1] = node->value[j];
     520                                node->subtree[j - 1] = node->subtree[j];
     521                        }
     522                        node->subtree[j - 1] = node->subtree[j];
     523                        node->keys--;
     524                        return;
     525                }
     526        }
     527        panic("Node %p does not contain key %" PRIu64 ".", node, key);
     528}
     529
     530/** Remove key and its right subtree pointer from B-tree node.
     531 *
     532 * Remove the key and eliminate gaps in node->key array.
     533 * Note that the value pointer and the right subtree pointer
     534 * is removed from the node as well.
     535 *
     536 * @param node B-tree node.
     537 * @param key Key to be removed.
     538 */
     539void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key)
     540{
     541        size_t i, j;
     542       
     543        for (i = 0; i < node->keys; i++) {
     544                if (key == node->key[i]) {
     545                        for (j = i + 1; j < node->keys; j++) {
     546                                node->key[j - 1] = node->key[j];
     547                                node->value[j - 1] = node->value[j];
     548                                node->subtree[j] = node->subtree[j + 1];
     549                        }
     550                        node->keys--;
     551                        return;
     552                }
     553        }
     554        panic("Node %p does not contain key %" PRIu64 ".", node, key);
     555}
     556
     557/** Split full B-tree node and insert new key-value-right-subtree triplet.
     558 *
     559 * This function will split a node and return a pointer to a newly created
     560 * node containing keys greater than or equal to the greater of medians
     561 * (or median) of the old keys and the newly added key. It will also write
     562 * the median key to a memory address supplied by the caller.
     563 *
     564 * If the node being split is an index node, the median will not be
     565 * included in the new node. If the node is a leaf node,
     566 * the median will be copied there.
     567 *
     568 * @param node B-tree node wich is going to be split.
     569 * @param key The key to be inserted.
     570 * @param value Pointer to the value to be inserted.
     571 * @param rsubtree Pointer to the right subtree of the key being added.
     572 * @param median Address in memory, where the median key will be stored.
     573 *
     574 * @return Newly created right sibling of node.
     575 */
     576btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median)
     577{
     578        btree_node_t *rnode;
     579        size_t i, j;
     580
     581        ASSERT(median);
     582        ASSERT(node->keys == BTREE_MAX_KEYS);
     583
     584        /*
     585         * Use the extra space to store the extra node.
     586         */
     587        node_insert_key_and_rsubtree(node, key, value, rsubtree);
     588
     589        /*
     590         * Compute median of keys.
     591         */
     592        *median = MEDIAN_HIGH(node);
     593               
     594        /*
     595         * Allocate and initialize new right sibling.
     596         */
     597        rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0);
     598        node_initialize(rnode);
     599        rnode->parent = node->parent;
     600        rnode->depth = node->depth;
     601       
     602        /*
     603         * Copy big keys, values and subtree pointers to the new right sibling.
     604         * If this is an index node, do not copy the median.
     605         */
     606        i = (size_t) INDEX_NODE(node);
     607        for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
     608                rnode->key[j] = node->key[i];
     609                rnode->value[j] = node->value[i];
     610                rnode->subtree[j] = node->subtree[i];
     611               
     612                /*
     613                 * Fix parent links in subtrees.
     614                 */
     615                if (rnode->subtree[j])
     616                        rnode->subtree[j]->parent = rnode;
     617                       
     618        }
     619        rnode->subtree[j] = node->subtree[i];
     620        if (rnode->subtree[j])
     621                rnode->subtree[j]->parent = rnode;
     622
     623        rnode->keys = j;        /* Set number of keys of the new node. */
     624        node->keys /= 2;        /* Shrink the old node. */
     625               
     626        return rnode;
     627}
     628
     629/** Combine node with any of its siblings.
     630 *
     631 * The siblings are required to be below the fill factor.
     632 *
     633 * @param node Node to combine with one of its siblings.
     634 *
     635 * @return Pointer to the rightmost of the two nodes.
     636 */
     637btree_node_t *node_combine(btree_node_t *node)
     638{
     639        size_t idx;
     640        btree_node_t *rnode;
     641        size_t i;
     642
     643        ASSERT(!ROOT_NODE(node));
     644       
     645        idx = find_key_by_subtree(node->parent, node, false);
     646        if (idx == node->parent->keys) {
     647                /*
     648                 * Rightmost subtree of its parent, combine with the left sibling.
     649                 */
     650                idx--;
     651                rnode = node;
     652                node = node->parent->subtree[idx];
     653        } else {
     654                rnode = node->parent->subtree[idx + 1];
     655        }
     656
     657        /* Index nodes need to insert parent node key in between left and right node. */
     658        if (INDEX_NODE(node))
     659                node->key[node->keys++] = node->parent->key[idx];
     660       
     661        /* Copy the key-value-subtree triplets from the right node. */
     662        for (i = 0; i < rnode->keys; i++) {
     663                node->key[node->keys + i] = rnode->key[i];
     664                node->value[node->keys + i] = rnode->value[i];
     665                if (INDEX_NODE(node)) {
     666                        node->subtree[node->keys + i] = rnode->subtree[i];
     667                        rnode->subtree[i]->parent = node;
     668                }
     669        }
     670        if (INDEX_NODE(node)) {
     671                node->subtree[node->keys + i] = rnode->subtree[i];
     672                rnode->subtree[i]->parent = node;
     673        }
     674
     675        node->keys += rnode->keys;
     676
     677        return rnode;
     678}
     679
     680/** Find key by its left or right subtree.
     681 *
     682 * @param node B-tree node.
     683 * @param subtree Left or right subtree of a key found in node.
     684 * @param right If true, subtree is a right subtree. If false, subtree is a left subtree.
     685 *
     686 * @return Index of the key associated with the subtree.
     687 */
     688size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
     689{
     690        size_t i;
     691       
     692        for (i = 0; i < node->keys + 1; i++) {
     693                if (subtree == node->subtree[i])
     694                        return i - (int) (right != false);
     695        }
     696        panic("Node %p does not contain subtree %p.", node, subtree);
     697}
     698
     699/** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
     700 *
     701 * The biggest key and its value and right subtree is rotated from the left node
     702 * to the right. If the node is an index node, than the parent node key belonging to
     703 * the left node takes part in the rotation.
     704 *
     705 * @param lnode Left sibling.
     706 * @param rnode Right sibling.
     707 * @param idx Index of the parent node key that is taking part in the rotation.
     708 */
     709void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
     710{
     711        btree_key_t key;
     712
     713        key = lnode->key[lnode->keys - 1];
     714               
     715        if (LEAF_NODE(lnode)) {
     716                void *value;
     717
     718                value = lnode->value[lnode->keys - 1];
     719                node_remove_key_and_rsubtree(lnode, key);
     720                node_insert_key_and_lsubtree(rnode, key, value, NULL);
     721                lnode->parent->key[idx] = key;
     722        } else {
     723                btree_node_t *rsubtree;
     724
     725                rsubtree = lnode->subtree[lnode->keys];
     726                node_remove_key_and_rsubtree(lnode, key);
     727                node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);
     728                lnode->parent->key[idx] = key;
     729
     730                /* Fix parent link of the reconnected right subtree. */
     731                rsubtree->parent = rnode;
     732        }
     733
     734}
     735
     736/** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.
     737 *
     738 * The smallest key and its value and left subtree is rotated from the right node
     739 * to the left. If the node is an index node, than the parent node key belonging to
     740 * the right node takes part in the rotation.
     741 *
     742 * @param lnode Left sibling.
     743 * @param rnode Right sibling.
     744 * @param idx Index of the parent node key that is taking part in the rotation.
     745 */
     746void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
     747{
     748        btree_key_t key;
     749
     750        key = rnode->key[0];
     751               
     752        if (LEAF_NODE(rnode)) {
     753                void *value;
     754
     755                value = rnode->value[0];
     756                node_remove_key_and_lsubtree(rnode, key);
     757                node_insert_key_and_rsubtree(lnode, key, value, NULL);
     758                rnode->parent->key[idx] = rnode->key[0];
     759        } else {
     760                btree_node_t *lsubtree;
     761
     762                lsubtree = rnode->subtree[0];
     763                node_remove_key_and_lsubtree(rnode, key);
     764                node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);
     765                rnode->parent->key[idx] = key;
     766
     767                /* Fix parent link of the reconnected left subtree. */
     768                lsubtree->parent = lnode;
     769        }
     770
     771}
     772
     773/** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.
     774 *
     775 * Left sibling of the node (if it exists) is checked for free space.
     776 * If there is free space, the key is inserted and the smallest key of
     777 * the node is moved there. The index node which is the parent of both
     778 * nodes is fixed.
     779 *
     780 * @param node B-tree node.
     781 * @param inskey Key to be inserted.
     782 * @param insvalue Value to be inserted.
     783 * @param rsubtree Right subtree of inskey.
     784 *
     785 * @return True if the rotation was performed, false otherwise.
     786 */
     787bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
     788{
     789        size_t idx;
     790        btree_node_t *lnode;
     791
     792        /*
     793         * If this is root node, the rotation can not be done.
     794         */
     795        if (ROOT_NODE(node))
     796                return false;
     797       
     798        idx = find_key_by_subtree(node->parent, node, true);
     799        if ((int) idx == -1) {
     800                /*
     801                 * If this node is the leftmost subtree of its parent,
     802                 * the rotation can not be done.
     803                 */
     804                return false;
     805        }
     806               
     807        lnode = node->parent->subtree[idx];
     808        if (lnode->keys < BTREE_MAX_KEYS) {
     809                /*
     810                 * The rotaion can be done. The left sibling has free space.
     811                 */
     812                node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
     813                rotate_from_right(lnode, node, idx);
     814                return true;
     815        }
     816
     817        return false;
     818}
     819
     820/** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.
     821 *
     822 * Right sibling of the node (if it exists) is checked for free space.
     823 * If there is free space, the key is inserted and the biggest key of
     824 * the node is moved there. The index node which is the parent of both
     825 * nodes is fixed.
     826 *
     827 * @param node B-tree node.
     828 * @param inskey Key to be inserted.
     829 * @param insvalue Value to be inserted.
     830 * @param rsubtree Right subtree of inskey.
     831 *
     832 * @return True if the rotation was performed, false otherwise.
     833 */
     834bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
     835{
     836        size_t idx;
     837        btree_node_t *rnode;
     838
     839        /*
     840         * If this is root node, the rotation can not be done.
     841         */
     842        if (ROOT_NODE(node))
     843                return false;
     844       
     845        idx = find_key_by_subtree(node->parent, node, false);
     846        if (idx == node->parent->keys) {
     847                /*
     848                 * If this node is the rightmost subtree of its parent,
     849                 * the rotation can not be done.
     850                 */
     851                return false;
     852        }
     853               
     854        rnode = node->parent->subtree[idx + 1];
     855        if (rnode->keys < BTREE_MAX_KEYS) {
     856                /*
     857                 * The rotaion can be done. The right sibling has free space.
     858                 */
     859                node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
     860                rotate_from_left(node, rnode, idx);
     861                return true;
     862        }
     863
     864        return false;
     865}
     866
     867/** Rotate in a key from the left sibling or from the index node, if this operation can be done.
     868 *
     869 * @param rnode Node into which to add key from its left sibling or from the index node.
     870 *
     871 * @return True if the rotation was performed, false otherwise.
     872 */
     873bool try_rotation_from_left(btree_node_t *rnode)
     874{
     875        size_t idx;
     876        btree_node_t *lnode;
     877
     878        /*
     879         * If this is root node, the rotation can not be done.
     880         */
     881        if (ROOT_NODE(rnode))
     882                return false;
     883       
     884        idx = find_key_by_subtree(rnode->parent, rnode, true);
     885        if ((int) idx == -1) {
     886                /*
     887                 * If this node is the leftmost subtree of its parent,
     888                 * the rotation can not be done.
     889                 */
     890                return false;
     891        }
     892               
     893        lnode = rnode->parent->subtree[idx];
     894        if (lnode->keys > FILL_FACTOR) {
     895                rotate_from_left(lnode, rnode, idx);
     896                return true;
     897        }
     898       
     899        return false;
     900}
     901
     902/** Rotate in a key from the right sibling or from the index node, if this operation can be done.
     903 *
     904 * @param lnode Node into which to add key from its right sibling or from the index node.
     905 *
     906 * @return True if the rotation was performed, false otherwise.
     907 */
     908bool try_rotation_from_right(btree_node_t *lnode)
     909{
     910        size_t idx;
     911        btree_node_t *rnode;
     912
     913        /*
     914         * If this is root node, the rotation can not be done.
     915         */
     916        if (ROOT_NODE(lnode))
     917                return false;
     918       
     919        idx = find_key_by_subtree(lnode->parent, lnode, false);
     920        if (idx == lnode->parent->keys) {
     921                /*
     922                 * If this node is the rightmost subtree of its parent,
     923                 * the rotation can not be done.
     924                 */
     925                return false;
     926        }
     927               
     928        rnode = lnode->parent->subtree[idx + 1];
     929        if (rnode->keys > FILL_FACTOR) {
     930                rotate_from_right(lnode, rnode, idx);
     931                return true;
     932        }       
     933
     934        return false;
     935}
     936
    977937/** Print B-tree.
    978938 *
    979939 * @param t Print out B-tree.
    980  *
    981940 */
    982941void btree_print(btree_t *t)
     
    985944        int depth = t->root->depth;
    986945        link_t head, *cur;
    987        
     946
    988947        printf("Printing B-tree:\n");
    989948        list_initialize(&head);
    990949        list_append(&t->root->bfs_link, &head);
    991        
     950
    992951        /*
    993952         * Use BFS search to print out the tree.
    994953         * Levels are distinguished from one another by node->depth.
    995          */
     954         */     
    996955        while (!list_empty(&head)) {
    997956                link_t *hlp;
     
    1009968                        depth = node->depth;
    1010969                }
    1011                
     970
    1012971                printf("(");
    1013                
    1014972                for (i = 0; i < node->keys; i++) {
    1015973                        printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
     
    1018976                        }
    1019977                }
    1020                
    1021                 if (node->depth && node->subtree[i])
     978                if (node->depth && node->subtree[i]) {
    1022979                        list_append(&node->subtree[i]->bfs_link, &head);
    1023                
     980                }
    1024981                printf(")");
    1025982        }
    1026        
    1027983        printf("\n");
    1028984       
     
    1034990               
    1035991                ASSERT(node);
    1036                
     992
    1037993                printf("(");
    1038                
    1039994                for (i = 0; i < node->keys; i++)
    1040995                        printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
    1041                
    1042996                printf(")");
    1043997        }
    1044        
    1045998        printf("\n");
    1046999}
Note: See TracChangeset for help on using the changeset viewer.