Changeset bd48f4c in mainline for kernel/generic/src/adt/btree.c


Ignore:
Timestamp:
2010-07-12T10:53:30Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bd11d3e
Parents:
c40e6ef (diff), bee2d4c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    rc40e6ef rbd48f4c  
    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 
    56 static void btree_destroy_subtree(btree_node_t *root);
    57 static void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node);
    58 static void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node);
    59 static void node_initialize(btree_node_t *node);
    60 static void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree);
    61 static void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
    62 static void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key);
    63 static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key);
    64 static btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median);
    65 static btree_node_t *node_combine(btree_node_t *node);
    66 static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
    67 static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
    68 static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
    69 static bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
    70 static bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
    71 static bool try_rotation_from_left(btree_node_t *rnode);
    72 static 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))]);
     55#include <trace.h>
    8456
    8557static 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))]);
    8669
    8770/** Initialize B-trees. */
    8871void btree_init(void)
    8972{
    90         btree_node_slab = slab_cache_create("btree_node_slab", sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
     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 */
     82NO_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;
    91101}
    92102
     
    94104 *
    95105 * @param t B-tree.
     106 *
    96107 */
    97108void btree_create(btree_t *t)
     
    103114}
    104115
    105 /** Destroy empty B-tree. */
    106 void 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  */
    118 void 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 
    134116/** Destroy subtree rooted in a node.
    135117 *
    136118 * @param root Root of the subtree.
    137  */
    138 void btree_destroy_subtree(btree_node_t *root)
     119 *
     120 */
     121NO_TRACE static void btree_destroy_subtree(btree_node_t *root)
    139122{
    140123        size_t i;
    141 
     124       
    142125        if (root->keys) {
    143126                for (i = 0; i < root->keys + 1; i++) {
     
    146129                }
    147130        }
     131       
    148132        slab_free(btree_node_slab, root);
    149133}
    150134
     135/** Destroy empty B-tree. */
     136void 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 */
     154NO_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 */
     189NO_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 */
     212NO_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 */
     246NO_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 */
     278NO_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 */
     318NO_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 */
     354NO_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 */
     392NO_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 */
     441NO_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 */
     495NO_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
    151550/** Recursively insert into B-tree.
    152551 *
    153  * @param t B-tree.
    154  * @param key Key to be inserted.
    155  * @param value Value to be inserted.
     552 * @param t        B-tree.
     553 * @param key      Key to be inserted.
     554 * @param value    Value to be inserted.
    156555 * @param rsubtree Right subtree of the inserted key.
    157  * @param node Start inserting into this node.
    158  */
    159 void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node)
     556 * @param node     Start inserting into this node.
     557 *
     558 */
     559NO_TRACE static void _btree_insert(btree_t *t, btree_key_t key, void *value,
     560    btree_node_t *rsubtree, btree_node_t *node)
    160561{
    161562        if (node->keys < BTREE_MAX_KEYS) {
     
    183584                 * bigger keys (i.e. the new node) into its parent.
    184585                 */
    185 
     586               
    186587                rnode = node_split(node, key, value, rsubtree, &median);
    187 
     588               
    188589                if (LEAF_NODE(node)) {
    189590                        list_prepend(&rnode->leaf_link, &node->leaf_link);
     
    202603                         * Left-hand side subtree will be the old root (i.e. node).
    203604                         * Right-hand side subtree will be rnode.
    204                          */                     
     605                         */
    205606                        t->root->subtree[0] = node;
    206 
     607                       
    207608                        t->root->depth = node->depth + 1;
    208609                }
    209610                _btree_insert(t, median, NULL, rnode, node->parent);
    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  */
    220 void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node)
     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 */
     622void btree_insert(btree_t *t, btree_key_t key, void *value,
     623    btree_node_t *leaf_node)
    221624{
    222625        btree_node_t *lnode;
     626       
     627        ASSERT(value);
    223628       
    224629        lnode = leaf_node;
    225630        if (!lnode) {
    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);
     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 */
     646NO_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 */
     683NO_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 */
     721NO_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;
    232762}
    233763
    234764/** Recursively remove B-tree node.
    235765 *
    236  * @param t B-tree.
    237  * @param key Key to be removed from the B-tree along with its associated value.
     766 * @param t    B-tree.
     767 * @param key  Key to be removed from the B-tree along with its associated value.
    238768 * @param node Node where the key being removed resides.
    239  */
    240 void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node)
     769 *
     770 */
     771NO_TRACE static void _btree_remove(btree_t *t, btree_key_t key,
     772    btree_node_t *node)
    241773{
    242774        if (ROOT_NODE(node)) {
    243                 if (node->keys == 1 && node->subtree[0]) {
     775                if ((node->keys == 1) && (node->subtree[0])) {
    244776                        /*
    245777                         * Free the current root and set new root.
     
    257789                        node_remove_key_and_rsubtree(node, key);
    258790                }
     791               
    259792                return;
    260793        }
     
    271804        if (node->keys > FILL_FACTOR) {
    272805                size_t i;
    273 
     806               
    274807                /*
    275808                 * The key can be immediatelly removed.
     
    280813                 */
    281814                node_remove_key_and_rsubtree(node, key);
     815               
    282816                for (i = 0; i < node->parent->keys; i++) {
    283817                        if (node->parent->key[i] == key)
    284818                                node->parent->key[i] = node->key[0];
    285819                }
    286                
    287820        } else {
    288821                size_t idx;
    289                 btree_node_t *rnode, *parent;
    290 
     822                btree_node_t *rnode;
     823                btree_node_t *parent;
     824               
    291825                /*
    292826                 * The node is below the fill factor as well as its left and right sibling.
     
    298832                node_remove_key_and_rsubtree(node, key);
    299833                rnode = node_combine(node);
     834               
    300835                if (LEAF_NODE(rnode))
    301836                        list_remove(&rnode->leaf_link);
     837               
    302838                idx = find_key_by_subtree(parent, rnode, true);
    303839                ASSERT((int) idx != -1);
     
    307843}
    308844
     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 */
     854void 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
    309867/** Search key in a B-tree.
    310868 *
    311  * @param t B-tree.
    312  * @param key Key to be searched.
     869 * @param t         B-tree.
     870 * @param key       Key to be searched.
    313871 * @param leaf_node Address where to put pointer to visited leaf node.
    314872 *
    315873 * @return Pointer to value or NULL if there is no such key.
     874 *
    316875 */
    317876void *btree_search(btree_t *t, btree_key_t key, btree_node_t **leaf_node)
     
    323882         */
    324883        for (cur = t->root; cur; cur = next) {
    325 
    326                 /* Last iteration will set this with proper leaf node address. */
     884                /*
     885                 * Last iteration will set this with proper
     886                 * leaf node address.
     887                 */
    327888                *leaf_node = cur;
    328889               
     
    337898                        void *val;
    338899                        size_t i;
    339                
     900                       
    340901                        /*
    341902                         * Now if the key is smaller than cur->key[i]
     
    347908                                        next = cur->subtree[i];
    348909                                        val = cur->value[i - 1];
    349 
     910                                       
    350911                                        if (LEAF_NODE(cur))
    351912                                                return key == cur->key[i - 1] ? val : NULL;
    352 
     913                                       
    353914                                        goto descend;
    354                                 } 
     915                                }
    355916                        }
    356917                       
    357918                        /*
    358                          * Last possibility is that the key is in the rightmost subtree.
     919                         * Last possibility is that the key is
     920                         * in the rightmost subtree.
    359921                         */
    360922                        next = cur->subtree[i];
    361923                        val = cur->value[i - 1];
     924                       
    362925                        if (LEAF_NODE(cur))
    363926                                return key == cur->key[i - 1] ? val : NULL;
    364927                }
    365928                descend:
    366                         ;
    367         }
    368 
     929                ;
     930        }
     931       
    369932        /*
    370          * The key was not found in the *leaf_node and is smaller than any of its keys.
     933         * The key was not found in the *leaf_node and
     934         * is smaller than any of its keys.
    371935         */
    372936        return NULL;
     
    375939/** Return pointer to B-tree leaf node's left neighbour.
    376940 *
    377  * @param t B-tree.
     941 * @param t    B-tree.
    378942 * @param node Node whose left neighbour will be returned.
    379943 *
    380  * @return Left neighbour of the node or NULL if the node does not have the left neighbour.
     944 * @return Left neighbour of the node or NULL if the node
     945 *         does not have the left neighbour.
     946 *
    381947 */
    382948btree_node_t *btree_leaf_node_left_neighbour(btree_t *t, btree_node_t *node)
    383949{
    384950        ASSERT(LEAF_NODE(node));
     951       
    385952        if (node->leaf_link.prev != &t->leaf_head)
    386953                return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
     
    391958/** Return pointer to B-tree leaf node's right neighbour.
    392959 *
    393  * @param t B-tree.
     960 * @param t    B-tree.
    394961 * @param node Node whose right neighbour will be returned.
    395962 *
    396  * @return Right neighbour of the node or NULL if the node does not have the right neighbour.
     963 * @return Right neighbour of the node or NULL if the node
     964 *         does not have the right neighbour.
     965 *
    397966 */
    398967btree_node_t *btree_leaf_node_right_neighbour(btree_t *t, btree_node_t *node)
    399968{
    400969        ASSERT(LEAF_NODE(node));
     970       
    401971        if (node->leaf_link.next != &t->leaf_head)
    402972                return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
     
    405975}
    406976
    407 /** Initialize B-tree node.
    408  *
    409  * @param node B-tree node.
    410  */
    411 void 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  */
    443 void 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  */
    479 void 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  */
    511 void 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  */
    539 void 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  */
    576 btree_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  */
    637 btree_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  */
    688 size_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  */
    709 void 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  */
    746 void 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  */
    787 bool 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  */
    834 bool 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  */
    873 bool 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  */
    908 bool 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 
    937977/** Print B-tree.
    938978 *
    939979 * @param t Print out B-tree.
     980 *
    940981 */
    941982void btree_print(btree_t *t)
     
    944985        int depth = t->root->depth;
    945986        link_t head, *cur;
    946 
     987       
    947988        printf("Printing B-tree:\n");
    948989        list_initialize(&head);
    949990        list_append(&t->root->bfs_link, &head);
    950 
     991       
    951992        /*
    952993         * Use BFS search to print out the tree.
    953994         * Levels are distinguished from one another by node->depth.
    954          */     
     995         */
    955996        while (!list_empty(&head)) {
    956997                link_t *hlp;
     
    9681009                        depth = node->depth;
    9691010                }
    970 
     1011               
    9711012                printf("(");
     1013               
    9721014                for (i = 0; i < node->keys; i++) {
    9731015                        printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
     
    9761018                        }
    9771019                }
    978                 if (node->depth && node->subtree[i]) {
     1020               
     1021                if (node->depth && node->subtree[i])
    9791022                        list_append(&node->subtree[i]->bfs_link, &head);
    980                 }
     1023               
    9811024                printf(")");
    9821025        }
     1026       
    9831027        printf("\n");
    9841028       
     
    9901034               
    9911035                ASSERT(node);
    992 
     1036               
    9931037                printf("(");
     1038               
    9941039                for (i = 0; i < node->keys; i++)
    9951040                        printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
     1041               
    9961042                printf(")");
    9971043        }
     1044       
    9981045        printf("\n");
    9991046}
Note: See TracChangeset for help on using the changeset viewer.