Ignore:
File:
1 edited

Legend:

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

    re3ee9b9 r98000fb  
    3333/**
    3434 * @file
    35  * @brief B+tree implementation.
     35 * @brief       B+tree implementation.
    3636 *
    3737 * This file implements B+tree type and operations.
     
    5454#include <print.h>
    5555
     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))]);
     84
    5685static slab_cache_t *btree_node_slab;
    57 
    58 #define ROOT_NODE(n)   (!(n)->parent)
    59 #define INDEX_NODE(n)  ((n)->subtree[0] != NULL)
    60 #define LEAF_NODE(n)   ((n)->subtree[0] == NULL)
    61 
    62 #define FILL_FACTOR  ((BTREE_M - 1) / 2)
    63 
    64 #define MEDIAN_LOW_INDEX(n)   (((n)->keys-1) / 2)
    65 #define MEDIAN_HIGH_INDEX(n)  ((n)->keys / 2)
    66 #define MEDIAN_LOW(n)         ((n)->key[MEDIAN_LOW_INDEX((n))]);
    67 #define MEDIAN_HIGH(n)        ((n)->key[MEDIAN_HIGH_INDEX((n))]);
    6886
    6987/** Initialize B-trees. */
    7088void btree_init(void)
    7189{
    72         btree_node_slab = slab_cache_create("btree_node_slab",
    73             sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    74 }
    75 
    76 /** Initialize B-tree node.
    77  *
    78  * @param node B-tree node.
    79  *
    80  */
    81 static void node_initialize(btree_node_t *node)
    82 {
    83         unsigned int i;
    84        
    85         node->keys = 0;
    86        
    87         /* Clean also space for the extra key. */
    88         for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
    89                 node->key[i] = 0;
    90                 node->value[i] = NULL;
    91                 node->subtree[i] = NULL;
    92         }
    93        
    94         node->subtree[i] = NULL;
    95         node->parent = NULL;
    96        
    97         link_initialize(&node->leaf_link);
    98         link_initialize(&node->bfs_link);
    99         node->depth = 0;
     90        btree_node_slab = slab_cache_create("btree_node_slab", sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    10091}
    10192
     
    10394 *
    10495 * @param t B-tree.
    105  *
    10696 */
    10797void btree_create(btree_t *t)
     
    113103}
    114104
     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
    115134/** Destroy subtree rooted in a node.
    116135 *
    117136 * @param root Root of the subtree.
    118  *
    119  */
    120 static void btree_destroy_subtree(btree_node_t *root)
     137 */
     138void btree_destroy_subtree(btree_node_t *root)
    121139{
    122140        size_t i;
    123        
     141
    124142        if (root->keys) {
    125143                for (i = 0; i < root->keys + 1; i++) {
     
    128146                }
    129147        }
    130        
    131148        slab_free(btree_node_slab, root);
    132149}
    133150
    134 /** Destroy empty B-tree. */
    135 void btree_destroy(btree_t *t)
    136 {
    137         btree_destroy_subtree(t->root);
    138 }
    139 
    140 /** Insert key-value-rsubtree triplet into B-tree node.
    141  *
    142  * It is actually possible to have more keys than BTREE_MAX_KEYS.
    143  * This feature is used during splitting the node when the
    144  * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation
    145  * also makes use of this feature.
    146  *
    147  * @param node     B-tree node into wich the new key is to be inserted.
    148  * @param key      The key to be inserted.
    149  * @param value    Pointer to value to be inserted.
    150  * @param rsubtree Pointer to the right subtree.
    151  *
    152  */
    153 static void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key,
    154     void *value, btree_node_t *rsubtree)
    155 {
    156         size_t i;
    157        
    158         for (i = 0; i < node->keys; i++) {
    159                 if (key < node->key[i]) {
    160                         size_t j;
    161                        
    162                         for (j = node->keys; j > i; j--) {
    163                                 node->key[j] = node->key[j - 1];
    164                                 node->value[j] = node->value[j - 1];
    165                                 node->subtree[j + 1] = node->subtree[j];
    166                         }
    167                        
    168                         break;
    169                 }
    170         }
    171        
    172         node->key[i] = key;
    173         node->value[i] = value;
    174         node->subtree[i + 1] = rsubtree;
    175         node->keys++;
    176 }
    177 
    178 /** Find key by its left or right subtree.
    179  *
    180  * @param node    B-tree node.
    181  * @param subtree Left or right subtree of a key found in node.
    182  * @param right   If true, subtree is a right subtree. If false,
    183  *                subtree is a left subtree.
    184  *
    185  * @return Index of the key associated with the subtree.
    186  *
    187  */
    188 static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree,
    189     bool right)
    190 {
    191         size_t i;
    192        
    193         for (i = 0; i < node->keys + 1; i++) {
    194                 if (subtree == node->subtree[i])
    195                         return i - (int) (right != false);
    196         }
    197        
    198         panic("Node %p does not contain subtree %p.", node, subtree);
    199 }
    200 
    201 /** Remove key and its left subtree pointer from B-tree node.
    202  *
    203  * Remove the key and eliminate gaps in node->key array.
    204  * Note that the value pointer and the left subtree pointer
    205  * is removed from the node as well.
    206  *
    207  * @param node B-tree node.
    208  * @param key  Key to be removed.
    209  *
    210  */
    211 static void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key)
    212 {
    213         size_t i;
    214         size_t j;
    215        
    216         for (i = 0; i < node->keys; i++) {
    217                 if (key == node->key[i]) {
    218                         for (j = i + 1; j < node->keys; j++) {
    219                                 node->key[j - 1] = node->key[j];
    220                                 node->value[j - 1] = node->value[j];
    221                                 node->subtree[j - 1] = node->subtree[j];
    222                         }
    223                        
    224                         node->subtree[j - 1] = node->subtree[j];
    225                         node->keys--;
    226                        
    227                         return;
    228                 }
    229         }
    230        
    231         panic("Node %p does not contain key %" PRIu64 ".", node, key);
    232 }
    233 
    234 /** Remove key and its right subtree pointer from B-tree node.
    235  *
    236  * Remove the key and eliminate gaps in node->key array.
    237  * Note that the value pointer and the right subtree pointer
    238  * is removed from the node as well.
    239  *
    240  * @param node B-tree node.
    241  * @param key  Key to be removed.
    242  *
    243  */
    244 static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key)
    245 {
    246         size_t i, j;
    247        
    248         for (i = 0; i < node->keys; i++) {
    249                 if (key == node->key[i]) {
    250                         for (j = i + 1; j < node->keys; j++) {
    251                                 node->key[j - 1] = node->key[j];
    252                                 node->value[j - 1] = node->value[j];
    253                                 node->subtree[j] = node->subtree[j + 1];
    254                         }
    255                        
    256                         node->keys--;
    257                         return;
    258                 }
    259         }
    260        
    261         panic("Node %p does not contain key %" PRIu64 ".", node, key);
    262 }
    263 
    264 /** Insert key-value-lsubtree triplet into B-tree node.
    265  *
    266  * It is actually possible to have more keys than BTREE_MAX_KEYS.
    267  * This feature is used during insert by right rotation.
    268  *
    269  * @param node     B-tree node into wich the new key is to be inserted.
    270  * @param key      The key to be inserted.
    271  * @param value    Pointer to value to be inserted.
    272  * @param lsubtree Pointer to the left subtree.
    273  *
    274  */
    275 static void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key,
    276     void *value, btree_node_t *lsubtree)
    277 {
    278         size_t i;
    279        
    280         for (i = 0; i < node->keys; i++) {
    281                 if (key < node->key[i]) {
    282                         size_t j;
    283                        
    284                         for (j = node->keys; j > i; j--) {
    285                                 node->key[j] = node->key[j - 1];
    286                                 node->value[j] = node->value[j - 1];
    287                                 node->subtree[j + 1] = node->subtree[j];
    288                         }
    289                        
    290                         node->subtree[j + 1] = node->subtree[j];
    291                         break;
    292                 }
    293         }
    294        
    295         node->key[i] = key;
    296         node->value[i] = value;
    297         node->subtree[i] = lsubtree;
    298        
    299         node->keys++;
    300 }
    301 
    302 /** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
    303  *
    304  * The biggest key and its value and right subtree is rotated
    305  * from the left node to the right. If the node is an index node,
    306  * than the parent node key belonging to the left node takes part
    307  * in the rotation.
    308  *
    309  * @param lnode Left sibling.
    310  * @param rnode Right sibling.
    311  * @param idx   Index of the parent node key that is taking part
    312  *              in the rotation.
    313  *
    314  */
    315 static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
    316 {
    317         btree_key_t key = lnode->key[lnode->keys - 1];
    318        
    319         if (LEAF_NODE(lnode)) {
    320                 void *value = lnode->value[lnode->keys - 1];
    321                
    322                 node_remove_key_and_rsubtree(lnode, key);
    323                 node_insert_key_and_lsubtree(rnode, key, value, NULL);
    324                 lnode->parent->key[idx] = key;
    325         } else {
    326                 btree_node_t *rsubtree = lnode->subtree[lnode->keys];
    327                
    328                 node_remove_key_and_rsubtree(lnode, key);
    329                 node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);
    330                 lnode->parent->key[idx] = key;
    331                
    332                 /* Fix parent link of the reconnected right subtree. */
    333                 rsubtree->parent = rnode;
    334         }
    335 }
    336 
    337 /** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.
    338  *
    339  * The smallest key and its value and left subtree is rotated
    340  * from the right node to the left. If the node is an index node,
    341  * than the parent node key belonging to the right node takes part
    342  * in the rotation.
    343  *
    344  * @param lnode Left sibling.
    345  * @param rnode Right sibling.
    346  * @param idx   Index of the parent node key that is taking part
    347  *              in the rotation.
    348  *
    349  */
    350 static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
    351 {
    352         btree_key_t key = rnode->key[0];
    353        
    354         if (LEAF_NODE(rnode)) {
    355                 void *value = rnode->value[0];
    356                
    357                 node_remove_key_and_lsubtree(rnode, key);
    358                 node_insert_key_and_rsubtree(lnode, key, value, NULL);
    359                 rnode->parent->key[idx] = rnode->key[0];
    360         } else {
    361                 btree_node_t *lsubtree = rnode->subtree[0];
    362                
    363                 node_remove_key_and_lsubtree(rnode, key);
    364                 node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);
    365                 rnode->parent->key[idx] = key;
    366                
    367                 /* Fix parent link of the reconnected left subtree. */
    368                 lsubtree->parent = lnode;
    369         }
    370 }
    371 
    372 /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.
    373  *
    374  * Left sibling of the node (if it exists) is checked for free space.
    375  * If there is free space, the key is inserted and the smallest key of
    376  * the node is moved there. The index node which is the parent of both
    377  * nodes is fixed.
    378  *
    379  * @param node     B-tree node.
    380  * @param inskey   Key to be inserted.
    381  * @param insvalue Value to be inserted.
    382  * @param rsubtree Right subtree of inskey.
    383  *
    384  * @return True if the rotation was performed, false otherwise.
    385  *
    386  */
    387 static bool try_insert_by_rotation_to_left(btree_node_t *node,
    388     btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
    389 {
    390         size_t idx;
    391         btree_node_t *lnode;
    392        
    393         /*
    394          * If this is root node, the rotation can not be done.
    395          */
    396         if (ROOT_NODE(node))
    397                 return false;
    398        
    399         idx = find_key_by_subtree(node->parent, node, true);
    400         if ((int) idx == -1) {
    401                 /*
    402                  * If this node is the leftmost subtree of its parent,
    403                  * the rotation can not be done.
    404                  */
    405                 return false;
    406         }
    407        
    408         lnode = node->parent->subtree[idx];
    409         if (lnode->keys < BTREE_MAX_KEYS) {
    410                 /*
    411                  * The rotaion can be done. The left sibling has free space.
    412                  */
    413                 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
    414                 rotate_from_right(lnode, node, idx);
    415                 return true;
    416         }
    417        
    418         return false;
    419 }
    420 
    421 /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.
    422  *
    423  * Right sibling of the node (if it exists) is checked for free space.
    424  * If there is free space, the key is inserted and the biggest key of
    425  * the node is moved there. The index node which is the parent of both
    426  * nodes is fixed.
    427  *
    428  * @param node     B-tree node.
    429  * @param inskey   Key to be inserted.
    430  * @param insvalue Value to be inserted.
    431  * @param rsubtree Right subtree of inskey.
    432  *
    433  * @return True if the rotation was performed, false otherwise.
    434  *
    435  */
    436 static bool try_insert_by_rotation_to_right(btree_node_t *node,
    437     btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
    438 {
    439         size_t idx;
    440         btree_node_t *rnode;
    441        
    442         /*
    443          * If this is root node, the rotation can not be done.
    444          */
    445         if (ROOT_NODE(node))
    446                 return false;
    447        
    448         idx = find_key_by_subtree(node->parent, node, false);
    449         if (idx == node->parent->keys) {
    450                 /*
    451                  * If this node is the rightmost subtree of its parent,
    452                  * the rotation can not be done.
    453                  */
    454                 return false;
    455         }
    456        
    457         rnode = node->parent->subtree[idx + 1];
    458         if (rnode->keys < BTREE_MAX_KEYS) {
    459                 /*
    460                  * The rotaion can be done. The right sibling has free space.
    461                  */
    462                 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
    463                 rotate_from_left(node, rnode, idx);
    464                 return true;
    465         }
    466        
    467         return false;
    468 }
    469 
    470 /** Split full B-tree node and insert new key-value-right-subtree triplet.
    471  *
    472  * This function will split a node and return a pointer to a newly created
    473  * node containing keys greater than or equal to the greater of medians
    474  * (or median) of the old keys and the newly added key. It will also write
    475  * the median key to a memory address supplied by the caller.
    476  *
    477  * If the node being split is an index node, the median will not be
    478  * included in the new node. If the node is a leaf node,
    479  * the median will be copied there.
    480  *
    481  * @param node     B-tree node wich is going to be split.
    482  * @param key      The key to be inserted.
    483  * @param value    Pointer to the value to be inserted.
    484  * @param rsubtree Pointer to the right subtree of the key being added.
    485  * @param median   Address in memory, where the median key will be stored.
    486  *
    487  * @return Newly created right sibling of node.
    488  *
    489  */
    490 static btree_node_t *node_split(btree_node_t *node, btree_key_t key,
    491     void *value, btree_node_t *rsubtree, btree_key_t *median)
    492 {
    493         btree_node_t *rnode;
    494         size_t i;
    495         size_t j;
    496        
    497         ASSERT(median);
    498         ASSERT(node->keys == BTREE_MAX_KEYS);
    499        
    500         /*
    501          * Use the extra space to store the extra node.
    502          */
    503         node_insert_key_and_rsubtree(node, key, value, rsubtree);
    504        
    505         /*
    506          * Compute median of keys.
    507          */
    508         *median = MEDIAN_HIGH(node);
    509        
    510         /*
    511          * Allocate and initialize new right sibling.
    512          */
    513         rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0);
    514         node_initialize(rnode);
    515         rnode->parent = node->parent;
    516         rnode->depth = node->depth;
    517        
    518         /*
    519          * Copy big keys, values and subtree pointers to the new right sibling.
    520          * If this is an index node, do not copy the median.
    521          */
    522         i = (size_t) INDEX_NODE(node);
    523         for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
    524                 rnode->key[j] = node->key[i];
    525                 rnode->value[j] = node->value[i];
    526                 rnode->subtree[j] = node->subtree[i];
    527                
    528                 /*
    529                  * Fix parent links in subtrees.
    530                  */
    531                 if (rnode->subtree[j])
    532                         rnode->subtree[j]->parent = rnode;
    533         }
    534        
    535         rnode->subtree[j] = node->subtree[i];
    536         if (rnode->subtree[j])
    537                 rnode->subtree[j]->parent = rnode;
    538        
    539         rnode->keys = j;  /* Set number of keys of the new node. */
    540         node->keys /= 2;  /* Shrink the old node. */
    541        
    542         return rnode;
    543 }
    544 
    545151/** Recursively insert into B-tree.
    546152 *
    547  * @param t        B-tree.
    548  * @param key      Key to be inserted.
    549  * @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.
    550156 * @param rsubtree Right subtree of the inserted key.
    551  * @param node     Start inserting into this node.
    552  *
    553  */
    554 static void _btree_insert(btree_t *t, btree_key_t key, void *value,
    555     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)
    556160{
    557161        if (node->keys < BTREE_MAX_KEYS) {
     
    579183                 * bigger keys (i.e. the new node) into its parent.
    580184                 */
    581                
     185
    582186                rnode = node_split(node, key, value, rsubtree, &median);
    583                
     187
    584188                if (LEAF_NODE(node)) {
    585189                        list_prepend(&rnode->leaf_link, &node->leaf_link);
     
    598202                         * Left-hand side subtree will be the old root (i.e. node).
    599203                         * Right-hand side subtree will be rnode.
    600                          */
     204                         */                     
    601205                        t->root->subtree[0] = node;
    602                        
     206
    603207                        t->root->depth = node->depth + 1;
    604208                }
    605209                _btree_insert(t, median, NULL, rnode, node->parent);
    606         }
    607 }
    608 
    609 /** Insert key-value pair into B-tree.
    610  *
    611  * @param t         B-tree.
    612  * @param key       Key to be inserted.
    613  * @param value     Value to be inserted.
    614  * @param leaf_node Leaf node where the insertion should begin.
    615  *
    616  */
    617 void btree_insert(btree_t *t, btree_key_t key, void *value,
    618     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)
    619221{
    620222        btree_node_t *lnode;
    621        
    622         ASSERT(value);
    623223       
    624224        lnode = leaf_node;
    625225        if (!lnode) {
    626                 if (btree_search(t, key, &lnode))
    627                         panic("B-tree %p already contains key %" PRIu64 ".", t, key);
    628         }
    629        
    630         _btree_insert(t, key, value, NULL, lnode);
    631 }
    632 
    633 /** Rotate in a key from the left sibling or from the index node, if this operation can be done.
    634  *
    635  * @param rnode Node into which to add key from its left sibling
    636  *              or from the index node.
    637  *
    638  * @return True if the rotation was performed, false otherwise.
    639  *
    640  */
    641 static bool try_rotation_from_left(btree_node_t *rnode)
    642 {
    643         size_t idx;
    644         btree_node_t *lnode;
    645        
    646         /*
    647          * If this is root node, the rotation can not be done.
    648          */
    649         if (ROOT_NODE(rnode))
    650                 return false;
    651        
    652         idx = find_key_by_subtree(rnode->parent, rnode, true);
    653         if ((int) idx == -1) {
    654                 /*
    655                  * If this node is the leftmost subtree of its parent,
    656                  * the rotation can not be done.
    657                  */
    658                 return false;
    659         }
    660        
    661         lnode = rnode->parent->subtree[idx];
    662         if (lnode->keys > FILL_FACTOR) {
    663                 rotate_from_left(lnode, rnode, idx);
    664                 return true;
    665         }
    666        
    667         return false;
    668 }
    669 
    670 /** Rotate in a key from the right sibling or from the index node, if this operation can be done.
    671  *
    672  * @param lnode Node into which to add key from its right sibling
    673  *              or from the index node.
    674  *
    675  * @return True if the rotation was performed, false otherwise.
    676  *
    677  */
    678 static bool try_rotation_from_right(btree_node_t *lnode)
    679 {
    680         size_t idx;
    681         btree_node_t *rnode;
    682        
    683         /*
    684          * If this is root node, the rotation can not be done.
    685          */
    686         if (ROOT_NODE(lnode))
    687                 return false;
    688        
    689         idx = find_key_by_subtree(lnode->parent, lnode, false);
    690         if (idx == lnode->parent->keys) {
    691                 /*
    692                  * If this node is the rightmost subtree of its parent,
    693                  * the rotation can not be done.
    694                  */
    695                 return false;
    696         }
    697        
    698         rnode = lnode->parent->subtree[idx + 1];
    699         if (rnode->keys > FILL_FACTOR) {
    700                 rotate_from_right(lnode, rnode, idx);
    701                 return true;
    702         }
    703        
    704         return false;
    705 }
    706 
    707 /** Combine node with any of its siblings.
    708  *
    709  * The siblings are required to be below the fill factor.
    710  *
    711  * @param node Node to combine with one of its siblings.
    712  *
    713  * @return Pointer to the rightmost of the two nodes.
    714  *
    715  */
    716 static btree_node_t *node_combine(btree_node_t *node)
    717 {
    718         size_t idx;
    719         btree_node_t *rnode;
    720         size_t i;
    721        
    722         ASSERT(!ROOT_NODE(node));
    723        
    724         idx = find_key_by_subtree(node->parent, node, false);
    725         if (idx == node->parent->keys) {
    726                 /*
    727                  * Rightmost subtree of its parent, combine with the left sibling.
    728                  */
    729                 idx--;
    730                 rnode = node;
    731                 node = node->parent->subtree[idx];
    732         } else
    733                 rnode = node->parent->subtree[idx + 1];
    734        
    735         /* Index nodes need to insert parent node key in between left and right node. */
    736         if (INDEX_NODE(node))
    737                 node->key[node->keys++] = node->parent->key[idx];
    738        
    739         /* Copy the key-value-subtree triplets from the right node. */
    740         for (i = 0; i < rnode->keys; i++) {
    741                 node->key[node->keys + i] = rnode->key[i];
    742                 node->value[node->keys + i] = rnode->value[i];
    743                
    744                 if (INDEX_NODE(node)) {
    745                         node->subtree[node->keys + i] = rnode->subtree[i];
    746                         rnode->subtree[i]->parent = node;
    747                 }
    748         }
    749        
    750         if (INDEX_NODE(node)) {
    751                 node->subtree[node->keys + i] = rnode->subtree[i];
    752                 rnode->subtree[i]->parent = node;
    753         }
    754        
    755         node->keys += rnode->keys;
    756         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);
    757232}
    758233
    759234/** Recursively remove B-tree node.
    760235 *
    761  * @param t    B-tree.
    762  * @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.
    763238 * @param node Node where the key being removed resides.
    764  *
    765  */
    766 static void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node)
     239 */
     240void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node)
    767241{
    768242        if (ROOT_NODE(node)) {
    769                 if ((node->keys == 1) && (node->subtree[0])) {
     243                if (node->keys == 1 && node->subtree[0]) {
    770244                        /*
    771245                         * Free the current root and set new root.
     
    783257                        node_remove_key_and_rsubtree(node, key);
    784258                }
    785                
    786259                return;
    787260        }
     
    798271        if (node->keys > FILL_FACTOR) {
    799272                size_t i;
    800                
     273
    801274                /*
    802275                 * The key can be immediatelly removed.
     
    807280                 */
    808281                node_remove_key_and_rsubtree(node, key);
    809                
    810282                for (i = 0; i < node->parent->keys; i++) {
    811283                        if (node->parent->key[i] == key)
    812284                                node->parent->key[i] = node->key[0];
    813285                }
     286               
    814287        } else {
    815288                size_t idx;
    816                 btree_node_t *rnode;
    817                 btree_node_t *parent;
    818                
     289                btree_node_t *rnode, *parent;
     290
    819291                /*
    820292                 * The node is below the fill factor as well as its left and right sibling.
     
    826298                node_remove_key_and_rsubtree(node, key);
    827299                rnode = node_combine(node);
    828                
    829300                if (LEAF_NODE(rnode))
    830301                        list_remove(&rnode->leaf_link);
    831                
    832302                idx = find_key_by_subtree(parent, rnode, true);
    833303                ASSERT((int) idx != -1);
     
    837307}
    838308
    839 /** Remove B-tree node.
    840  *
    841  * @param t         B-tree.
    842  * @param key       Key to be removed from the B-tree along
    843  *                  with its associated value.
    844  * @param leaf_node If not NULL, pointer to the leaf node where
    845  *                  the key is found.
    846  *
    847  */
    848 void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node)
    849 {
    850         btree_node_t *lnode;
    851        
    852         lnode = leaf_node;
    853         if (!lnode) {
    854                 if (!btree_search(t, key, &lnode))
    855                         panic("B-tree %p does not contain key %" PRIu64 ".", t, key);
    856         }
    857        
    858         _btree_remove(t, key, lnode);
    859 }
    860 
    861309/** Search key in a B-tree.
    862310 *
    863  * @param t         B-tree.
    864  * @param key       Key to be searched.
     311 * @param t B-tree.
     312 * @param key Key to be searched.
    865313 * @param leaf_node Address where to put pointer to visited leaf node.
    866314 *
    867315 * @return Pointer to value or NULL if there is no such key.
    868  *
    869316 */
    870317void *btree_search(btree_t *t, btree_key_t key, btree_node_t **leaf_node)
     
    876323         */
    877324        for (cur = t->root; cur; cur = next) {
    878                 /*
    879                  * Last iteration will set this with proper
    880                  * leaf node address.
    881                  */
     325
     326                /* Last iteration will set this with proper leaf node address. */
    882327                *leaf_node = cur;
    883328               
     
    892337                        void *val;
    893338                        size_t i;
    894                        
     339               
    895340                        /*
    896341                         * Now if the key is smaller than cur->key[i]
     
    902347                                        next = cur->subtree[i];
    903348                                        val = cur->value[i - 1];
    904                                        
     349
    905350                                        if (LEAF_NODE(cur))
    906351                                                return key == cur->key[i - 1] ? val : NULL;
    907                                        
     352
    908353                                        goto descend;
    909                                 }
     354                                } 
    910355                        }
    911356                       
    912357                        /*
    913                          * Last possibility is that the key is
    914                          * in the rightmost subtree.
     358                         * Last possibility is that the key is in the rightmost subtree.
    915359                         */
    916360                        next = cur->subtree[i];
    917361                        val = cur->value[i - 1];
    918                        
    919362                        if (LEAF_NODE(cur))
    920363                                return key == cur->key[i - 1] ? val : NULL;
    921364                }
    922365                descend:
    923                 ;
    924         }
    925        
     366                        ;
     367        }
     368
    926369        /*
    927          * The key was not found in the *leaf_node and
    928          * 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.
    929371         */
    930372        return NULL;
     
    933375/** Return pointer to B-tree leaf node's left neighbour.
    934376 *
    935  * @param t    B-tree.
     377 * @param t B-tree.
    936378 * @param node Node whose left neighbour will be returned.
    937379 *
    938  * @return Left neighbour of the node or NULL if the node
    939  *         does not have the left neighbour.
    940  *
     380 * @return Left neighbour of the node or NULL if the node does not have the left neighbour.
    941381 */
    942382btree_node_t *btree_leaf_node_left_neighbour(btree_t *t, btree_node_t *node)
    943383{
    944384        ASSERT(LEAF_NODE(node));
    945        
    946385        if (node->leaf_link.prev != &t->leaf_head)
    947386                return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
     
    952391/** Return pointer to B-tree leaf node's right neighbour.
    953392 *
    954  * @param t    B-tree.
     393 * @param t B-tree.
    955394 * @param node Node whose right neighbour will be returned.
    956395 *
    957  * @return Right neighbour of the node or NULL if the node
    958  *         does not have the right neighbour.
    959  *
     396 * @return Right neighbour of the node or NULL if the node does not have the right neighbour.
    960397 */
    961398btree_node_t *btree_leaf_node_right_neighbour(btree_t *t, btree_node_t *node)
    962399{
    963400        ASSERT(LEAF_NODE(node));
    964        
    965401        if (node->leaf_link.next != &t->leaf_head)
    966402                return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
     
    969405}
    970406
     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
    971937/** Print B-tree.
    972938 *
    973939 * @param t Print out B-tree.
    974  *
    975940 */
    976941void btree_print(btree_t *t)
     
    979944        int depth = t->root->depth;
    980945        link_t head, *cur;
    981        
     946
    982947        printf("Printing B-tree:\n");
    983948        list_initialize(&head);
    984949        list_append(&t->root->bfs_link, &head);
    985        
     950
    986951        /*
    987952         * Use BFS search to print out the tree.
    988953         * Levels are distinguished from one another by node->depth.
    989          */
     954         */     
    990955        while (!list_empty(&head)) {
    991956                link_t *hlp;
     
    1003968                        depth = node->depth;
    1004969                }
    1005                
     970
    1006971                printf("(");
    1007                
    1008972                for (i = 0; i < node->keys; i++) {
    1009973                        printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
     
    1012976                        }
    1013977                }
    1014                
    1015                 if (node->depth && node->subtree[i])
     978                if (node->depth && node->subtree[i]) {
    1016979                        list_append(&node->subtree[i]->bfs_link, &head);
    1017                
     980                }
    1018981                printf(")");
    1019982        }
    1020        
    1021983        printf("\n");
    1022984       
     
    1028990               
    1029991                ASSERT(node);
    1030                
     992
    1031993                printf("(");
    1032                
    1033994                for (i = 0; i < node->keys; i++)
    1034995                        printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
    1035                
    1036996                printf(")");
    1037997        }
    1038        
    1039998        printf("\n");
    1040999}
Note: See TracChangeset for help on using the changeset viewer.