Subversion Repositories HelenOS-historic

Rev

Rev 1148 | Rev 1164 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1148 Rev 1150
1
/*
1
/*
2
 * Copyright (C) 2006 Jakub Jermar
2
 * Copyright (C) 2006 Jakub Jermar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/*
29
/*
30
 * This B-tree has the following properties:
30
 * This B-tree has the following properties:
31
 * - it is a ballanced 2-3-4-5 tree (i.e. BTREE_M = 5)
31
 * - it is a ballanced 2-3-4-5 tree (i.e. BTREE_M = 5)
32
 * - values (i.e. pointers to values) are stored only in leaves
32
 * - values (i.e. pointers to values) are stored only in leaves
33
 * - leaves are linked in a list
33
 * - leaves are linked in a list
34
 * - technically, it is a B+tree (because of the previous properties)
34
 * - technically, it is a B+tree (because of the previous properties)
35
 *
35
 *
36
 * Be carefull when using these trees. They need to allocate
36
 * Be carefull when using these trees. They need to allocate
37
 * and deallocate memory for their index nodes and as such
37
 * and deallocate memory for their index nodes and as such
38
 * can sleep.
38
 * can sleep.
39
 */
39
 */
40
 
40
 
41
#include <adt/btree.h>
41
#include <adt/btree.h>
42
#include <adt/list.h>
42
#include <adt/list.h>
43
#include <mm/slab.h>
43
#include <mm/slab.h>
44
#include <debug.h>
44
#include <debug.h>
45
#include <panic.h>
45
#include <panic.h>
46
#include <typedefs.h>
46
#include <typedefs.h>
47
#include <print.h>
47
#include <print.h>
48
 
48
 
49
static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node);
49
static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node);
50
static void _btree_remove(btree_t *t, __native key, btree_node_t *node);
50
static void _btree_remove(btree_t *t, __native key, btree_node_t *node);
51
static void node_initialize(btree_node_t *node);
51
static void node_initialize(btree_node_t *node);
52
static void node_insert_key_and_lsubtree(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree);
52
static void node_insert_key_and_lsubtree(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree);
53
static void node_insert_key_and_rsubtree(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);
53
static void node_insert_key_and_rsubtree(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);
54
static void node_remove_key_and_lsubtree(btree_node_t *node, __native key);
54
static void node_remove_key_and_lsubtree(btree_node_t *node, __native key);
55
static void node_remove_key_and_rsubtree(btree_node_t *node, __native key);
55
static void node_remove_key_and_rsubtree(btree_node_t *node, __native key);
56
static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median);
56
static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median);
57
static btree_node_t *node_combine(btree_node_t *node);
57
static btree_node_t *node_combine(btree_node_t *node);
58
static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
58
static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
59
static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
59
static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
60
static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
60
static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
61
static bool try_insert_by_rotation_to_left(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);
61
static bool try_insert_by_rotation_to_left(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);
62
static bool try_insert_by_rotation_to_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);
62
static bool try_insert_by_rotation_to_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);
63
static bool try_rotation_from_left(btree_node_t *rnode);
63
static bool try_rotation_from_left(btree_node_t *rnode);
64
static bool try_rotation_from_right(btree_node_t *lnode);
64
static bool try_rotation_from_right(btree_node_t *lnode);
65
 
65
 
66
#define ROOT_NODE(n)        (!(n)->parent)
66
#define ROOT_NODE(n)        (!(n)->parent)
67
#define INDEX_NODE(n)       ((n)->subtree[0] != NULL)
67
#define INDEX_NODE(n)       ((n)->subtree[0] != NULL)
68
#define LEAF_NODE(n)        ((n)->subtree[0] == NULL)
68
#define LEAF_NODE(n)        ((n)->subtree[0] == NULL)
69
 
69
 
70
#define FILL_FACTOR     ((BTREE_M-1)/2)
70
#define FILL_FACTOR     ((BTREE_M-1)/2)
71
 
71
 
72
#define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2)
72
#define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2)
73
#define MEDIAN_HIGH_INDEX(n)    ((n)->keys/2)
73
#define MEDIAN_HIGH_INDEX(n)    ((n)->keys/2)
74
#define MEDIAN_LOW(n)       ((n)->key[MEDIAN_LOW_INDEX((n))]);
74
#define MEDIAN_LOW(n)       ((n)->key[MEDIAN_LOW_INDEX((n))]);
75
#define MEDIAN_HIGH(n)      ((n)->key[MEDIAN_HIGH_INDEX((n))]);
75
#define MEDIAN_HIGH(n)      ((n)->key[MEDIAN_HIGH_INDEX((n))]);
76
 
76
 
77
/** Create empty B-tree.
77
/** Create empty B-tree.
78
 *
78
 *
79
 * @param t B-tree.
79
 * @param t B-tree.
80
 */
80
 */
81
void btree_create(btree_t *t)
81
void btree_create(btree_t *t)
82
{
82
{
83
    list_initialize(&t->leaf_head);
83
    list_initialize(&t->leaf_head);
84
    t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
84
    t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
85
    node_initialize(t->root);
85
    node_initialize(t->root);
86
    list_append(&t->root->leaf_link, &t->leaf_head);
86
    list_append(&t->root->leaf_link, &t->leaf_head);
87
}
87
}
88
 
88
 
89
/** Destroy empty B-tree. */
89
/** Destroy empty B-tree. */
90
void btree_destroy(btree_t *t)
90
void btree_destroy(btree_t *t)
91
{
91
{
92
    ASSERT(!t->root->keys);
92
    ASSERT(!t->root->keys);
93
    free(t->root);
93
    free(t->root);
94
}
94
}
95
 
95
 
96
/** Insert key-value pair into B-tree.
96
/** Insert key-value pair into B-tree.
97
 *
97
 *
98
 * @param t B-tree.
98
 * @param t B-tree.
99
 * @param key Key to be inserted.
99
 * @param key Key to be inserted.
100
 * @param value Value to be inserted.
100
 * @param value Value to be inserted.
101
 * @param leaf_node Leaf node where the insertion should begin.
101
 * @param leaf_node Leaf node where the insertion should begin.
102
 */
102
 */
103
void btree_insert(btree_t *t, __native key, void *value, btree_node_t *leaf_node)
103
void btree_insert(btree_t *t, __native key, void *value, btree_node_t *leaf_node)
104
{
104
{
105
    btree_node_t *lnode;
105
    btree_node_t *lnode;
106
   
106
   
107
    ASSERT(value);
107
    ASSERT(value);
108
   
108
   
109
    lnode = leaf_node;
109
    lnode = leaf_node;
110
    if (!lnode) {
110
    if (!lnode) {
111
        if (btree_search(t, key, &lnode)) {
111
        if (btree_search(t, key, &lnode)) {
112
            panic("B-tree %P already contains key %d\n", t, key);
112
            panic("B-tree %P already contains key %d\n", t, key);
113
        }
113
        }
114
    }
114
    }
115
   
115
   
116
    _btree_insert(t, key, value, NULL, lnode);
116
    _btree_insert(t, key, value, NULL, lnode);
117
}
117
}
118
 
118
 
119
/** Recursively insert into B-tree.
119
/** Recursively insert into B-tree.
120
 *
120
 *
121
 * @param t B-tree.
121
 * @param t B-tree.
122
 * @param key Key to be inserted.
122
 * @param key Key to be inserted.
123
 * @param value Value to be inserted.
123
 * @param value Value to be inserted.
124
 * @param rsubtree Right subtree of the inserted key.
124
 * @param rsubtree Right subtree of the inserted key.
125
 * @param node Start inserting into this node.
125
 * @param node Start inserting into this node.
126
 */
126
 */
127
void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node)
127
void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node)
128
{
128
{
129
    if (node->keys < BTREE_MAX_KEYS) {
129
    if (node->keys < BTREE_MAX_KEYS) {
130
        /*
130
        /*
131
         * Node conatins enough space, the key can be stored immediately.
131
         * Node conatins enough space, the key can be stored immediately.
132
         */
132
         */
133
        node_insert_key_and_rsubtree(node, key, value, rsubtree);
133
        node_insert_key_and_rsubtree(node, key, value, rsubtree);
134
    } else if (try_insert_by_rotation_to_left(node, key, value, rsubtree)) {
134
    } else if (try_insert_by_rotation_to_left(node, key, value, rsubtree)) {
135
        /*
135
        /*
136
         * The key-value-rsubtree triplet has been inserted because
136
         * The key-value-rsubtree triplet has been inserted because
137
         * some keys could have been moved to the left sibling.
137
         * some keys could have been moved to the left sibling.
138
         */
138
         */
139
    } else if (try_insert_by_rotation_to_right(node, key, value, rsubtree)) {
139
    } else if (try_insert_by_rotation_to_right(node, key, value, rsubtree)) {
140
        /*
140
        /*
141
         * The key-value-rsubtree triplet has been inserted because
141
         * The key-value-rsubtree triplet has been inserted because
142
         * some keys could have been moved to the right sibling.
142
         * some keys could have been moved to the right sibling.
143
         */
143
         */
144
    } else {
144
    } else {
145
        btree_node_t *rnode;
145
        btree_node_t *rnode;
146
        __native median;
146
        __native median;
147
       
147
       
148
        /*
148
        /*
149
         * Node is full and both siblings (if both exist) are full too.
149
         * Node is full and both siblings (if both exist) are full too.
150
         * Split the node and insert the smallest key from the node containing
150
         * Split the node and insert the smallest key from the node containing
151
         * bigger keys (i.e. the new node) into its parent.
151
         * bigger keys (i.e. the new node) into its parent.
152
         */
152
         */
153
 
153
 
154
        rnode = node_split(node, key, value, rsubtree, &median);
154
        rnode = node_split(node, key, value, rsubtree, &median);
155
 
155
 
156
        if (LEAF_NODE(node)) {
156
        if (LEAF_NODE(node)) {
157
            list_prepend(&rnode->leaf_link, &node->leaf_link);
157
            list_prepend(&rnode->leaf_link, &node->leaf_link);
158
        }
158
        }
159
       
159
       
160
        if (ROOT_NODE(node)) {
160
        if (ROOT_NODE(node)) {
161
            /*
161
            /*
162
             * We split the root node. Create new root.
162
             * We split the root node. Create new root.
163
             */
163
             */
164
            t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
164
            t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
165
            node->parent = t->root;
165
            node->parent = t->root;
166
            rnode->parent = t->root;
166
            rnode->parent = t->root;
167
            node_initialize(t->root);
167
            node_initialize(t->root);
168
           
168
           
169
            /*
169
            /*
170
             * Left-hand side subtree will be the old root (i.e. node).
170
             * Left-hand side subtree will be the old root (i.e. node).
171
             * Right-hand side subtree will be rnode.
171
             * Right-hand side subtree will be rnode.
172
             */        
172
             */        
173
            t->root->subtree[0] = node;
173
            t->root->subtree[0] = node;
174
 
174
 
175
            t->root->depth = node->depth + 1;
175
            t->root->depth = node->depth + 1;
176
        }
176
        }
177
        _btree_insert(t, median, NULL, rnode, node->parent);
177
        _btree_insert(t, median, NULL, rnode, node->parent);
178
    }  
178
    }  
179
       
179
       
180
}
180
}
181
 
181
 
182
/** Remove B-tree node.
182
/** Remove B-tree node.
183
 *
183
 *
184
 * @param B-tree.
184
 * @param B-tree.
185
 * @param key Key to be removed from the B-tree along with its associated value.
185
 * @param key Key to be removed from the B-tree along with its associated value.
186
 * @param leaf_node If not NULL, pointer to the leaf node where the key is found.
186
 * @param leaf_node If not NULL, pointer to the leaf node where the key is found.
187
 */
187
 */
188
void btree_remove(btree_t *t, __native key, btree_node_t *leaf_node)
188
void btree_remove(btree_t *t, __native key, btree_node_t *leaf_node)
189
{
189
{
190
    btree_node_t *lnode;
190
    btree_node_t *lnode;
191
   
191
   
192
    lnode = leaf_node;
192
    lnode = leaf_node;
193
    if (!lnode) {
193
    if (!lnode) {
194
        if (!btree_search(t, key, &lnode)) {
194
        if (!btree_search(t, key, &lnode)) {
195
            panic("B-tree %P does not contain key %d\n", t, key);
195
            panic("B-tree %P does not contain key %d\n", t, key);
196
        }
196
        }
197
    }
197
    }
198
   
198
   
199
    _btree_remove(t, key, lnode);
199
    _btree_remove(t, key, lnode);
200
}
200
}
201
 
201
 
202
/** Recursively remove B-tree node.
202
/** Recursively remove B-tree node.
203
 *
203
 *
204
 * @param B-tree.
204
 * @param B-tree.
205
 * @param key Key to be removed from the B-tree along with its associated value.
205
 * @param key Key to be removed from the B-tree along with its associated value.
206
 * @param node Node where the key being removed resides.
206
 * @param node Node where the key being removed resides.
207
 */
207
 */
208
void _btree_remove(btree_t *t, __native key, btree_node_t *node)
208
void _btree_remove(btree_t *t, __native key, btree_node_t *node)
209
{
209
{
210
    if (ROOT_NODE(node)) {
210
    if (ROOT_NODE(node)) {
211
        if (node->keys == 1 && node->subtree[0]) {
211
        if (node->keys == 1 && node->subtree[0]) {
212
            /*
212
            /*
213
             * Free the current root and set new root.
213
             * Free the current root and set new root.
214
             */
214
             */
215
            t->root = node->subtree[0];
215
            t->root = node->subtree[0];
216
            t->root->parent = NULL;
216
            t->root->parent = NULL;
217
            free(node);
217
            free(node);
218
        } else {
218
        } else {
219
            /*
219
            /*
220
             * Remove the key from the root node.
220
             * Remove the key from the root node.
221
             * Note that the right subtree is removed because when
221
             * Note that the right subtree is removed because when
222
             * combining two nodes, the left-side sibling is preserved
222
             * combining two nodes, the left-side sibling is preserved
223
             * and the right-side sibling is freed.
223
             * and the right-side sibling is freed.
224
             */
224
             */
225
            node_remove_key_and_rsubtree(node, key);
225
            node_remove_key_and_rsubtree(node, key);
226
        }
226
        }
227
        return;
227
        return;
228
    }
228
    }
229
   
229
   
230
    if (node->keys <= FILL_FACTOR) {
230
    if (node->keys <= FILL_FACTOR) {
231
        /*
231
        /*
232
         * If the node is below the fill factor,
232
         * If the node is below the fill factor,
233
         * try to borrow keys from left or right sibling.
233
         * try to borrow keys from left or right sibling.
234
         */
234
         */
235
        if (!try_rotation_from_left(node))
235
        if (!try_rotation_from_left(node))
236
            try_rotation_from_right(node);
236
            try_rotation_from_right(node);
237
    }
237
    }
238
   
238
   
239
    if (node->keys > FILL_FACTOR) {
239
    if (node->keys > FILL_FACTOR) {
240
        int i;
240
        int i;
241
 
241
 
242
        /*
242
        /*
243
         * The key can be immediatelly removed.
243
         * The key can be immediatelly removed.
244
         *
244
         *
245
         * Note that the right subtree is removed because when
245
         * Note that the right subtree is removed because when
246
         * combining two nodes, the left-side sibling is preserved
246
         * combining two nodes, the left-side sibling is preserved
247
         * and the right-side sibling is freed.
247
         * and the right-side sibling is freed.
248
         */
248
         */
249
        node_remove_key_and_rsubtree(node, key);
249
        node_remove_key_and_rsubtree(node, key);
250
        for (i = 0; i < node->parent->keys; i++) {
250
        for (i = 0; i < node->parent->keys; i++) {
251
            if (node->parent->key[i] == key)
251
            if (node->parent->key[i] == key)
252
                node->parent->key[i] = node->key[0];
252
                node->parent->key[i] = node->key[0];
253
        }
253
        }
254
       
254
       
255
    } else {
255
    } else {
256
        index_t idx;
256
        index_t idx;
257
        btree_node_t *rnode, *parent;
257
        btree_node_t *rnode, *parent;
258
 
258
 
259
        /*
259
        /*
260
         * The node is below the fill factor as well as its left and right sibling.
260
         * The node is below the fill factor as well as its left and right sibling.
261
         * Resort to combining the node with one of its siblings.
261
         * Resort to combining the node with one of its siblings.
262
         * The node which is on the left is preserved and the node on the right is
262
         * The node which is on the left is preserved and the node on the right is
263
         * freed.
263
         * freed.
264
         */
264
         */
265
        parent = node->parent;
265
        parent = node->parent;
266
        node_remove_key_and_rsubtree(node, key);
266
        node_remove_key_and_rsubtree(node, key);
267
        rnode = node_combine(node);
267
        rnode = node_combine(node);
268
        if (LEAF_NODE(rnode))
268
        if (LEAF_NODE(rnode))
269
            list_remove(&rnode->leaf_link);
269
            list_remove(&rnode->leaf_link);
270
        idx = find_key_by_subtree(parent, rnode, true);
270
        idx = find_key_by_subtree(parent, rnode, true);
271
        ASSERT((int) idx != -1);
271
        ASSERT((int) idx != -1);
272
        free(rnode);
272
        free(rnode);
273
        _btree_remove(t, parent->key[idx], parent);
273
        _btree_remove(t, parent->key[idx], parent);
274
    }
274
    }
275
}
275
}
276
 
276
 
277
/** Search key in a B-tree.
277
/** Search key in a B-tree.
278
 *
278
 *
279
 * @param t B-tree.
279
 * @param t B-tree.
280
 * @param key Key to be searched.
280
 * @param key Key to be searched.
281
 * @param leaf_node Address where to put pointer to visited leaf node.
281
 * @param leaf_node Address where to put pointer to visited leaf node.
282
 *
282
 *
283
 * @return Pointer to value or NULL if there is no such key.
283
 * @return Pointer to value or NULL if there is no such key.
284
 */
284
 */
285
void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node)
285
void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node)
286
{
286
{
287
    btree_node_t *cur, *next;
287
    btree_node_t *cur, *next;
288
   
288
   
289
    /*
289
    /*
290
     * Iteratively descend to the leaf that can contain the searched key.
290
     * Iteratively descend to the leaf that can contain the searched key.
291
     */
291
     */
292
    for (cur = t->root; cur; cur = next) {
292
    for (cur = t->root; cur; cur = next) {
293
 
293
 
294
        /* Last iteration will set this with proper leaf node address. */
294
        /* Last iteration will set this with proper leaf node address. */
295
        *leaf_node = cur;
295
        *leaf_node = cur;
296
       
296
       
297
        /*
297
        /*
298
         * The key can be in the leftmost subtree.
298
         * The key can be in the leftmost subtree.
299
         * Test it separately.
299
         * Test it separately.
300
         */
300
         */
301
        if (key < cur->key[0]) {
301
        if (key < cur->key[0]) {
302
            next = cur->subtree[0];
302
            next = cur->subtree[0];
303
            continue;
303
            continue;
304
        } else {
304
        } else {
305
            void *val;
305
            void *val;
306
            int i;
306
            int i;
307
       
307
       
308
            /*
308
            /*
309
             * Now if the key is smaller than cur->key[i]
309
             * Now if the key is smaller than cur->key[i]
310
             * it can only mean that the value is in cur->subtree[i]
310
             * it can only mean that the value is in cur->subtree[i]
311
             * or it is not in the tree at all.
311
             * or it is not in the tree at all.
312
             */
312
             */
313
            for (i = 1; i < cur->keys; i++) {
313
            for (i = 1; i < cur->keys; i++) {
314
                if (key < cur->key[i]) {
314
                if (key < cur->key[i]) {
315
                    next = cur->subtree[i];
315
                    next = cur->subtree[i];
316
                    val = cur->value[i - 1];
316
                    val = cur->value[i - 1];
317
 
317
 
318
                    if (LEAF_NODE(cur))
318
                    if (LEAF_NODE(cur))
319
                        return key == cur->key[i - 1] ? val : NULL;
319
                        return key == cur->key[i - 1] ? val : NULL;
320
 
320
 
321
                    goto descend;
321
                    goto descend;
322
                }
322
                }
323
            }
323
            }
324
           
324
           
325
            /*
325
            /*
326
             * Last possibility is that the key is in the rightmost subtree.
326
             * Last possibility is that the key is in the rightmost subtree.
327
             */
327
             */
328
            next = cur->subtree[i];
328
            next = cur->subtree[i];
329
            val = cur->value[i - 1];
329
            val = cur->value[i - 1];
330
            if (LEAF_NODE(cur))
330
            if (LEAF_NODE(cur))
331
                return key == cur->key[i - 1] ? val : NULL;
331
                return key == cur->key[i - 1] ? val : NULL;
332
        }
332
        }
333
        descend:
333
        descend:
334
            ;
334
            ;
335
    }
335
    }
336
 
336
 
337
    /*
337
    /*
338
     * The key was not found in the *leaf_node and is smaller than any of its keys.
338
     * The key was not found in the *leaf_node and is smaller than any of its keys.
339
     */
339
     */
340
    return NULL;
340
    return NULL;
341
}
341
}
342
 
342
 
343
/** Return pointer to B-tree node's left sibling.
343
/** Return pointer to B-tree leaf node's left neighbour.
344
 *
344
 *
345
 * @param t B-tree.
345
 * @param t B-tree.
346
 * @param node Node whose left sibling will be returned.
346
 * @param node Node whose left neighbour will be returned.
347
 *
347
 *
348
 * @return Left sibling of the node or NULL if the node does not have the left sibling.
348
 * @return Left neighbour of the node or NULL if the node does not have the left neighbour.
349
 */
349
 */
350
btree_node_t *btree_node_left_sibling(btree_t *t, btree_node_t *node)
350
btree_node_t *btree_leaf_node_left_neighbour(btree_t *t, btree_node_t *node)
351
{
351
{
352
    ASSERT(LEAF_NODE(node));
352
    ASSERT(LEAF_NODE(node));
353
    if (node->leaf_link.prev != &t->leaf_head)
353
    if (node->leaf_link.prev != &t->leaf_head)
354
        return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
354
        return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
355
    else
355
    else
356
        return NULL;
356
        return NULL;
357
}
357
}
358
 
358
 
359
/** Return pointer to B-tree node's right sibling.
359
/** Return pointer to B-tree leaf node's right neighbour.
360
 *
360
 *
361
 * @param t B-tree.
361
 * @param t B-tree.
362
 * @param node Node whose right sibling will be returned.
362
 * @param node Node whose right neighbour will be returned.
363
 *
363
 *
364
 * @return Right sibling of the node or NULL if the node does not have the right sibling.
364
 * @return Right neighbour of the node or NULL if the node does not have the right neighbour.
365
 */
365
 */
366
btree_node_t *btree_node_right_sibling(btree_t *t, btree_node_t *node)
366
btree_node_t *btree_leaf_node_right_neighbour(btree_t *t, btree_node_t *node)
367
{
367
{
368
    ASSERT(LEAF_NODE(node));
368
    ASSERT(LEAF_NODE(node));
369
    if (node->leaf_link.next != &t->leaf_head)
369
    if (node->leaf_link.next != &t->leaf_head)
370
        return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
370
        return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
371
    else
371
    else
372
        return NULL;
372
        return NULL;
373
}
373
}
374
 
374
 
375
/** Initialize B-tree node.
375
/** Initialize B-tree node.
376
 *
376
 *
377
 * @param node B-tree node.
377
 * @param node B-tree node.
378
 */
378
 */
379
void node_initialize(btree_node_t *node)
379
void node_initialize(btree_node_t *node)
380
{
380
{
381
    int i;
381
    int i;
382
 
382
 
383
    node->keys = 0;
383
    node->keys = 0;
384
   
384
   
385
    /* Clean also space for the extra key. */
385
    /* Clean also space for the extra key. */
386
    for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
386
    for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
387
        node->key[i] = 0;
387
        node->key[i] = 0;
388
        node->value[i] = NULL;
388
        node->value[i] = NULL;
389
        node->subtree[i] = NULL;
389
        node->subtree[i] = NULL;
390
    }
390
    }
391
    node->subtree[i] = NULL;
391
    node->subtree[i] = NULL;
392
   
392
   
393
    node->parent = NULL;
393
    node->parent = NULL;
394
   
394
   
395
    link_initialize(&node->leaf_link);
395
    link_initialize(&node->leaf_link);
396
 
396
 
397
    link_initialize(&node->bfs_link);
397
    link_initialize(&node->bfs_link);
398
    node->depth = 0;
398
    node->depth = 0;
399
}
399
}
400
 
400
 
401
/** Insert key-value-lsubtree triplet into B-tree node.
401
/** Insert key-value-lsubtree triplet into B-tree node.
402
 *
402
 *
403
 * It is actually possible to have more keys than BTREE_MAX_KEYS.
403
 * It is actually possible to have more keys than BTREE_MAX_KEYS.
404
 * This feature is used during insert by right rotation.
404
 * This feature is used during insert by right rotation.
405
 *
405
 *
406
 * @param node B-tree node into wich the new key is to be inserted.
406
 * @param node B-tree node into wich the new key is to be inserted.
407
 * @param key The key to be inserted.
407
 * @param key The key to be inserted.
408
 * @param value Pointer to value to be inserted.
408
 * @param value Pointer to value to be inserted.
409
 * @param lsubtree Pointer to the left subtree.
409
 * @param lsubtree Pointer to the left subtree.
410
 */
410
 */
411
void node_insert_key_and_lsubtree(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree)
411
void node_insert_key_and_lsubtree(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree)
412
{
412
{
413
    int i;
413
    int i;
414
 
414
 
415
    for (i = 0; i < node->keys; i++) {
415
    for (i = 0; i < node->keys; i++) {
416
        if (key < node->key[i]) {
416
        if (key < node->key[i]) {
417
            int j;
417
            int j;
418
       
418
       
419
            for (j = node->keys; j > i; j--) {
419
            for (j = node->keys; j > i; j--) {
420
                node->key[j] = node->key[j - 1];
420
                node->key[j] = node->key[j - 1];
421
                node->value[j] = node->value[j - 1];
421
                node->value[j] = node->value[j - 1];
422
                node->subtree[j + 1] = node->subtree[j];
422
                node->subtree[j + 1] = node->subtree[j];
423
            }
423
            }
424
            node->subtree[j + 1] = node->subtree[j];
424
            node->subtree[j + 1] = node->subtree[j];
425
            break; 
425
            break; 
426
        }
426
        }
427
    }
427
    }
428
    node->key[i] = key;
428
    node->key[i] = key;
429
    node->value[i] = value;
429
    node->value[i] = value;
430
    node->subtree[i] = lsubtree;
430
    node->subtree[i] = lsubtree;
431
           
431
           
432
    node->keys++;
432
    node->keys++;
433
}
433
}
434
 
434
 
435
/** Insert key-value-rsubtree triplet into B-tree node.
435
/** Insert key-value-rsubtree triplet into B-tree node.
436
 *
436
 *
437
 * It is actually possible to have more keys than BTREE_MAX_KEYS.
437
 * It is actually possible to have more keys than BTREE_MAX_KEYS.
438
 * This feature is used during splitting the node when the
438
 * This feature is used during splitting the node when the
439
 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation
439
 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation
440
 * also makes use of this feature.
440
 * also makes use of this feature.
441
 *
441
 *
442
 * @param node B-tree node into wich the new key is to be inserted.
442
 * @param node B-tree node into wich the new key is to be inserted.
443
 * @param key The key to be inserted.
443
 * @param key The key to be inserted.
444
 * @param value Pointer to value to be inserted.
444
 * @param value Pointer to value to be inserted.
445
 * @param rsubtree Pointer to the right subtree.
445
 * @param rsubtree Pointer to the right subtree.
446
 */
446
 */
447
void node_insert_key_and_rsubtree(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree)
447
void node_insert_key_and_rsubtree(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree)
448
{
448
{
449
    int i;
449
    int i;
450
 
450
 
451
    for (i = 0; i < node->keys; i++) {
451
    for (i = 0; i < node->keys; i++) {
452
        if (key < node->key[i]) {
452
        if (key < node->key[i]) {
453
            int j;
453
            int j;
454
       
454
       
455
            for (j = node->keys; j > i; j--) {
455
            for (j = node->keys; j > i; j--) {
456
                node->key[j] = node->key[j - 1];
456
                node->key[j] = node->key[j - 1];
457
                node->value[j] = node->value[j - 1];
457
                node->value[j] = node->value[j - 1];
458
                node->subtree[j + 1] = node->subtree[j];
458
                node->subtree[j + 1] = node->subtree[j];
459
            }
459
            }
460
            break; 
460
            break; 
461
        }
461
        }
462
    }
462
    }
463
    node->key[i] = key;
463
    node->key[i] = key;
464
    node->value[i] = value;
464
    node->value[i] = value;
465
    node->subtree[i + 1] = rsubtree;
465
    node->subtree[i + 1] = rsubtree;
466
           
466
           
467
    node->keys++;
467
    node->keys++;
468
}
468
}
469
 
469
 
470
/** Remove key and its left subtree pointer from B-tree node.
470
/** Remove key and its left subtree pointer from B-tree node.
471
 *
471
 *
472
 * Remove the key and eliminate gaps in node->key array.
472
 * Remove the key and eliminate gaps in node->key array.
473
 * Note that the value pointer and the left subtree pointer
473
 * Note that the value pointer and the left subtree pointer
474
 * is removed from the node as well.
474
 * is removed from the node as well.
475
 *
475
 *
476
 * @param node B-tree node.
476
 * @param node B-tree node.
477
 * @param key Key to be removed.
477
 * @param key Key to be removed.
478
 */
478
 */
479
void node_remove_key_and_lsubtree(btree_node_t *node, __native key)
479
void node_remove_key_and_lsubtree(btree_node_t *node, __native key)
480
{
480
{
481
    int i, j;
481
    int i, j;
482
   
482
   
483
    for (i = 0; i < node->keys; i++) {
483
    for (i = 0; i < node->keys; i++) {
484
        if (key == node->key[i]) {
484
        if (key == node->key[i]) {
485
            for (j = i + 1; j < node->keys; j++) {
485
            for (j = i + 1; j < node->keys; j++) {
486
                node->key[j - 1] = node->key[j];
486
                node->key[j - 1] = node->key[j];
487
                node->value[j - 1] = node->value[j];
487
                node->value[j - 1] = node->value[j];
488
                node->subtree[j - 1] = node->subtree[j];
488
                node->subtree[j - 1] = node->subtree[j];
489
            }
489
            }
490
            node->subtree[j - 1] = node->subtree[j];
490
            node->subtree[j - 1] = node->subtree[j];
491
            node->keys--;
491
            node->keys--;
492
            return;
492
            return;
493
        }
493
        }
494
    }
494
    }
495
    panic("node %P does not contain key %d\n", node, key);
495
    panic("node %P does not contain key %d\n", node, key);
496
}
496
}
497
 
497
 
498
/** Remove key and its right subtree pointer from B-tree node.
498
/** Remove key and its right subtree pointer from B-tree node.
499
 *
499
 *
500
 * Remove the key and eliminate gaps in node->key array.
500
 * Remove the key and eliminate gaps in node->key array.
501
 * Note that the value pointer and the right subtree pointer
501
 * Note that the value pointer and the right subtree pointer
502
 * is removed from the node as well.
502
 * is removed from the node as well.
503
 *
503
 *
504
 * @param node B-tree node.
504
 * @param node B-tree node.
505
 * @param key Key to be removed.
505
 * @param key Key to be removed.
506
 */
506
 */
507
void node_remove_key_and_rsubtree(btree_node_t *node, __native key)
507
void node_remove_key_and_rsubtree(btree_node_t *node, __native key)
508
{
508
{
509
    int i, j;
509
    int i, j;
510
   
510
   
511
    for (i = 0; i < node->keys; i++) {
511
    for (i = 0; i < node->keys; i++) {
512
        if (key == node->key[i]) {
512
        if (key == node->key[i]) {
513
            for (j = i + 1; j < node->keys; j++) {
513
            for (j = i + 1; j < node->keys; j++) {
514
                node->key[j - 1] = node->key[j];
514
                node->key[j - 1] = node->key[j];
515
                node->value[j - 1] = node->value[j];
515
                node->value[j - 1] = node->value[j];
516
                node->subtree[j] = node->subtree[j + 1];
516
                node->subtree[j] = node->subtree[j + 1];
517
            }
517
            }
518
            node->keys--;
518
            node->keys--;
519
            return;
519
            return;
520
        }
520
        }
521
    }
521
    }
522
    panic("node %P does not contain key %d\n", node, key);
522
    panic("node %P does not contain key %d\n", node, key);
523
}
523
}
524
 
524
 
525
/** Split full B-tree node and insert new key-value-right-subtree triplet.
525
/** Split full B-tree node and insert new key-value-right-subtree triplet.
526
 *
526
 *
527
 * This function will split a node and return pointer to a newly created
527
 * This function will split a node and return pointer to a newly created
528
 * node containing keys greater than or equal to the greater of medians
528
 * node containing keys greater than or equal to the greater of medians
529
 * (or median) of the old keys and the newly added key. It will also write
529
 * (or median) of the old keys and the newly added key. It will also write
530
 * the median key to a memory address supplied by the caller.
530
 * the median key to a memory address supplied by the caller.
531
 *
531
 *
532
 * If the node being split is an index node, the median will not be
532
 * If the node being split is an index node, the median will not be
533
 * included in the new node. If the node is a leaf node,
533
 * included in the new node. If the node is a leaf node,
534
 * the median will be copied there.
534
 * the median will be copied there.
535
 *
535
 *
536
 * @param node B-tree node wich is going to be split.
536
 * @param node B-tree node wich is going to be split.
537
 * @param key The key to be inserted.
537
 * @param key The key to be inserted.
538
 * @param value Pointer to the value to be inserted.
538
 * @param value Pointer to the value to be inserted.
539
 * @param rsubtree Pointer to the right subtree of the key being added.
539
 * @param rsubtree Pointer to the right subtree of the key being added.
540
 * @param median Address in memory, where the median key will be stored.
540
 * @param median Address in memory, where the median key will be stored.
541
 *
541
 *
542
 * @return Newly created right sibling of node.
542
 * @return Newly created right sibling of node.
543
 */
543
 */
544
btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median)
544
btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median)
545
{
545
{
546
    btree_node_t *rnode;
546
    btree_node_t *rnode;
547
    int i, j;
547
    int i, j;
548
 
548
 
549
    ASSERT(median);
549
    ASSERT(median);
550
    ASSERT(node->keys == BTREE_MAX_KEYS);
550
    ASSERT(node->keys == BTREE_MAX_KEYS);
551
 
551
 
552
    /*
552
    /*
553
     * Use the extra space to store the extra node.
553
     * Use the extra space to store the extra node.
554
     */
554
     */
555
    node_insert_key_and_rsubtree(node, key, value, rsubtree);
555
    node_insert_key_and_rsubtree(node, key, value, rsubtree);
556
 
556
 
557
    /*
557
    /*
558
     * Compute median of keys.
558
     * Compute median of keys.
559
     */
559
     */
560
    *median = MEDIAN_HIGH(node);
560
    *median = MEDIAN_HIGH(node);
561
       
561
       
562
    /*
562
    /*
563
     * Allocate and initialize new right sibling.
563
     * Allocate and initialize new right sibling.
564
     */
564
     */
565
    rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
565
    rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
566
    node_initialize(rnode);
566
    node_initialize(rnode);
567
    rnode->parent = node->parent;
567
    rnode->parent = node->parent;
568
    rnode->depth = node->depth;
568
    rnode->depth = node->depth;
569
   
569
   
570
    /*
570
    /*
571
     * Copy big keys, values and subtree pointers to the new right sibling.
571
     * Copy big keys, values and subtree pointers to the new right sibling.
572
     * If this is an index node, do not copy the median.
572
     * If this is an index node, do not copy the median.
573
     */
573
     */
574
    i = (int) INDEX_NODE(node);
574
    i = (int) INDEX_NODE(node);
575
    for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
575
    for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
576
        rnode->key[j] = node->key[i];
576
        rnode->key[j] = node->key[i];
577
        rnode->value[j] = node->value[i];
577
        rnode->value[j] = node->value[i];
578
        rnode->subtree[j] = node->subtree[i];
578
        rnode->subtree[j] = node->subtree[i];
579
       
579
       
580
        /*
580
        /*
581
         * Fix parent links in subtrees.
581
         * Fix parent links in subtrees.
582
         */
582
         */
583
        if (rnode->subtree[j])
583
        if (rnode->subtree[j])
584
            rnode->subtree[j]->parent = rnode;
584
            rnode->subtree[j]->parent = rnode;
585
           
585
           
586
    }
586
    }
587
    rnode->subtree[j] = node->subtree[i];
587
    rnode->subtree[j] = node->subtree[i];
588
    if (rnode->subtree[j])
588
    if (rnode->subtree[j])
589
        rnode->subtree[j]->parent = rnode;
589
        rnode->subtree[j]->parent = rnode;
590
 
590
 
591
    rnode->keys = j;    /* Set number of keys of the new node. */
591
    rnode->keys = j;    /* Set number of keys of the new node. */
592
    node->keys /= 2;    /* Shrink the old node. */
592
    node->keys /= 2;    /* Shrink the old node. */
593
       
593
       
594
    return rnode;
594
    return rnode;
595
}
595
}
596
 
596
 
597
/** Combine node with any of its siblings.
597
/** Combine node with any of its siblings.
598
 *
598
 *
599
 * The siblings are required to be below the fill factor.
599
 * The siblings are required to be below the fill factor.
600
 *
600
 *
601
 * @param node Node to combine with one of its siblings.
601
 * @param node Node to combine with one of its siblings.
602
 *
602
 *
603
 * @return Pointer to the rightmost of the two nodes.
603
 * @return Pointer to the rightmost of the two nodes.
604
 */
604
 */
605
btree_node_t *node_combine(btree_node_t *node)
605
btree_node_t *node_combine(btree_node_t *node)
606
{
606
{
607
    index_t idx;
607
    index_t idx;
608
    btree_node_t *rnode;
608
    btree_node_t *rnode;
609
    int i;
609
    int i;
610
 
610
 
611
    ASSERT(!ROOT_NODE(node));
611
    ASSERT(!ROOT_NODE(node));
612
   
612
   
613
    idx = find_key_by_subtree(node->parent, node, false);
613
    idx = find_key_by_subtree(node->parent, node, false);
614
    if (idx == node->parent->keys) {
614
    if (idx == node->parent->keys) {
615
        /*
615
        /*
616
         * Rightmost subtree of its parent, combine with the left sibling.
616
         * Rightmost subtree of its parent, combine with the left sibling.
617
         */
617
         */
618
        idx--;
618
        idx--;
619
        rnode = node;
619
        rnode = node;
620
        node = node->parent->subtree[idx];
620
        node = node->parent->subtree[idx];
621
    } else {
621
    } else {
622
        rnode = node->parent->subtree[idx + 1];
622
        rnode = node->parent->subtree[idx + 1];
623
    }
623
    }
624
 
624
 
625
    /* Index nodes need to insert parent node key in between left and right node. */
625
    /* Index nodes need to insert parent node key in between left and right node. */
626
    if (INDEX_NODE(node))
626
    if (INDEX_NODE(node))
627
        node->key[node->keys++] = node->parent->key[idx];
627
        node->key[node->keys++] = node->parent->key[idx];
628
   
628
   
629
    /* Copy the key-value-subtree triplets from the right node. */
629
    /* Copy the key-value-subtree triplets from the right node. */
630
    for (i = 0; i < rnode->keys; i++) {
630
    for (i = 0; i < rnode->keys; i++) {
631
        node->key[node->keys + i] = rnode->key[i];
631
        node->key[node->keys + i] = rnode->key[i];
632
        node->value[node->keys + i] = rnode->value[i];
632
        node->value[node->keys + i] = rnode->value[i];
633
        if (INDEX_NODE(node)) {
633
        if (INDEX_NODE(node)) {
634
            node->subtree[node->keys + i] = rnode->subtree[i];
634
            node->subtree[node->keys + i] = rnode->subtree[i];
635
            rnode->subtree[i]->parent = node;
635
            rnode->subtree[i]->parent = node;
636
        }
636
        }
637
    }
637
    }
638
    if (INDEX_NODE(node)) {
638
    if (INDEX_NODE(node)) {
639
        node->subtree[node->keys + i] = rnode->subtree[i];
639
        node->subtree[node->keys + i] = rnode->subtree[i];
640
        rnode->subtree[i]->parent = node;
640
        rnode->subtree[i]->parent = node;
641
    }
641
    }
642
 
642
 
643
    node->keys += rnode->keys;
643
    node->keys += rnode->keys;
644
 
644
 
645
    return rnode;
645
    return rnode;
646
}
646
}
647
 
647
 
648
/** Find key by its left or right subtree.
648
/** Find key by its left or right subtree.
649
 *
649
 *
650
 * @param node B-tree node.
650
 * @param node B-tree node.
651
 * @param subtree Left or right subtree of a key found in node.
651
 * @param subtree Left or right subtree of a key found in node.
652
 * @param right If true, subtree is a right subtree. If false, subtree is a left subtree.
652
 * @param right If true, subtree is a right subtree. If false, subtree is a left subtree.
653
 *
653
 *
654
 * @return Index of the key associated with the subtree.
654
 * @return Index of the key associated with the subtree.
655
 */
655
 */
656
index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
656
index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
657
{
657
{
658
    int i;
658
    int i;
659
   
659
   
660
    for (i = 0; i < node->keys + 1; i++) {
660
    for (i = 0; i < node->keys + 1; i++) {
661
        if (subtree == node->subtree[i])
661
        if (subtree == node->subtree[i])
662
            return i - (int) (right != false);
662
            return i - (int) (right != false);
663
    }
663
    }
664
    panic("node %P does not contain subtree %P\n", node, subtree);
664
    panic("node %P does not contain subtree %P\n", node, subtree);
665
}
665
}
666
 
666
 
667
/** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
667
/** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
668
 *
668
 *
669
 * The biggest key and its value and right subtree is rotated from the left node
669
 * The biggest key and its value and right subtree is rotated from the left node
670
 * to the right. If the node is an index node, than the parent node key belonging to
670
 * to the right. If the node is an index node, than the parent node key belonging to
671
 * the left node takes part in the rotation.
671
 * the left node takes part in the rotation.
672
 *
672
 *
673
 * @param lnode Left sibling.
673
 * @param lnode Left sibling.
674
 * @param rnode Right sibling.
674
 * @param rnode Right sibling.
675
 * @param idx Index of the parent node key that is taking part in the rotation.
675
 * @param idx Index of the parent node key that is taking part in the rotation.
676
 */
676
 */
677
void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
677
void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
678
{
678
{
679
    __native key;
679
    __native key;
680
 
680
 
681
    key = lnode->key[lnode->keys - 1];
681
    key = lnode->key[lnode->keys - 1];
682
       
682
       
683
    if (LEAF_NODE(lnode)) {
683
    if (LEAF_NODE(lnode)) {
684
        void *value;
684
        void *value;
685
 
685
 
686
        value = lnode->value[lnode->keys - 1];
686
        value = lnode->value[lnode->keys - 1];
687
        node_remove_key_and_rsubtree(lnode, key);
687
        node_remove_key_and_rsubtree(lnode, key);
688
        node_insert_key_and_lsubtree(rnode, key, value, NULL);
688
        node_insert_key_and_lsubtree(rnode, key, value, NULL);
689
        lnode->parent->key[idx] = key;
689
        lnode->parent->key[idx] = key;
690
    } else {
690
    } else {
691
        btree_node_t *rsubtree;
691
        btree_node_t *rsubtree;
692
 
692
 
693
        rsubtree = lnode->subtree[lnode->keys];
693
        rsubtree = lnode->subtree[lnode->keys];
694
        node_remove_key_and_rsubtree(lnode, key);
694
        node_remove_key_and_rsubtree(lnode, key);
695
        node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);
695
        node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);
696
        lnode->parent->key[idx] = key;
696
        lnode->parent->key[idx] = key;
697
 
697
 
698
        /* Fix parent link of the reconnected right subtree. */
698
        /* Fix parent link of the reconnected right subtree. */
699
        rsubtree->parent = rnode;
699
        rsubtree->parent = rnode;
700
    }
700
    }
701
 
701
 
702
}
702
}
703
 
703
 
704
/** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.
704
/** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.
705
 *
705
 *
706
 * The smallest key and its value and left subtree is rotated from the right node
706
 * The smallest key and its value and left subtree is rotated from the right node
707
 * to the left. If the node is an index node, than the parent node key belonging to
707
 * to the left. If the node is an index node, than the parent node key belonging to
708
 * the right node takes part in the rotation.
708
 * the right node takes part in the rotation.
709
 *
709
 *
710
 * @param lnode Left sibling.
710
 * @param lnode Left sibling.
711
 * @param rnode Right sibling.
711
 * @param rnode Right sibling.
712
 * @param idx Index of the parent node key that is taking part in the rotation.
712
 * @param idx Index of the parent node key that is taking part in the rotation.
713
 */
713
 */
714
void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
714
void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
715
{
715
{
716
    __native key;
716
    __native key;
717
 
717
 
718
    key = rnode->key[0];
718
    key = rnode->key[0];
719
       
719
       
720
    if (LEAF_NODE(rnode)) {
720
    if (LEAF_NODE(rnode)) {
721
        void *value;
721
        void *value;
722
 
722
 
723
        value = rnode->value[0];
723
        value = rnode->value[0];
724
        node_remove_key_and_lsubtree(rnode, key);
724
        node_remove_key_and_lsubtree(rnode, key);
725
        node_insert_key_and_rsubtree(lnode, key, value, NULL);
725
        node_insert_key_and_rsubtree(lnode, key, value, NULL);
726
        rnode->parent->key[idx] = rnode->key[0];
726
        rnode->parent->key[idx] = rnode->key[0];
727
    } else {
727
    } else {
728
        btree_node_t *lsubtree;
728
        btree_node_t *lsubtree;
729
 
729
 
730
        lsubtree = rnode->subtree[0];
730
        lsubtree = rnode->subtree[0];
731
        node_remove_key_and_lsubtree(rnode, key);
731
        node_remove_key_and_lsubtree(rnode, key);
732
        node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);
732
        node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);
733
        rnode->parent->key[idx] = key;
733
        rnode->parent->key[idx] = key;
734
 
734
 
735
        /* Fix parent link of the reconnected left subtree. */
735
        /* Fix parent link of the reconnected left subtree. */
736
        lsubtree->parent = lnode;
736
        lsubtree->parent = lnode;
737
    }
737
    }
738
 
738
 
739
}
739
}
740
 
740
 
741
/** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.
741
/** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.
742
 *
742
 *
743
 * Left sibling of the node (if it exists) is checked for free space.
743
 * Left sibling of the node (if it exists) is checked for free space.
744
 * If there is free space, the key is inserted and the smallest key of
744
 * If there is free space, the key is inserted and the smallest key of
745
 * the node is moved there. The index node which is the parent of both
745
 * the node is moved there. The index node which is the parent of both
746
 * nodes is fixed.
746
 * nodes is fixed.
747
 *
747
 *
748
 * @param node B-tree node.
748
 * @param node B-tree node.
749
 * @param inskey Key to be inserted.
749
 * @param inskey Key to be inserted.
750
 * @param insvalue Value to be inserted.
750
 * @param insvalue Value to be inserted.
751
 * @param rsubtree Right subtree of inskey.
751
 * @param rsubtree Right subtree of inskey.
752
 *
752
 *
753
 * @return True if the rotation was performed, false otherwise.
753
 * @return True if the rotation was performed, false otherwise.
754
 */
754
 */
755
bool try_insert_by_rotation_to_left(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree)
755
bool try_insert_by_rotation_to_left(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree)
756
{
756
{
757
    index_t idx;
757
    index_t idx;
758
    btree_node_t *lnode;
758
    btree_node_t *lnode;
759
 
759
 
760
    /*
760
    /*
761
     * If this is root node, the rotation can not be done.
761
     * If this is root node, the rotation can not be done.
762
     */
762
     */
763
    if (ROOT_NODE(node))
763
    if (ROOT_NODE(node))
764
        return false;
764
        return false;
765
   
765
   
766
    idx = find_key_by_subtree(node->parent, node, true);
766
    idx = find_key_by_subtree(node->parent, node, true);
767
    if ((int) idx == -1) {
767
    if ((int) idx == -1) {
768
        /*
768
        /*
769
         * If this node is the leftmost subtree of its parent,
769
         * If this node is the leftmost subtree of its parent,
770
         * the rotation can not be done.
770
         * the rotation can not be done.
771
         */
771
         */
772
        return false;
772
        return false;
773
    }
773
    }
774
       
774
       
775
    lnode = node->parent->subtree[idx];
775
    lnode = node->parent->subtree[idx];
776
    if (lnode->keys < BTREE_MAX_KEYS) {
776
    if (lnode->keys < BTREE_MAX_KEYS) {
777
        /*
777
        /*
778
         * The rotaion can be done. The left sibling has free space.
778
         * The rotaion can be done. The left sibling has free space.
779
         */
779
         */
780
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
780
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
781
        rotate_from_right(lnode, node, idx);
781
        rotate_from_right(lnode, node, idx);
782
        return true;
782
        return true;
783
    }
783
    }
784
 
784
 
785
    return false;
785
    return false;
786
}
786
}
787
 
787
 
788
/** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.
788
/** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.
789
 *
789
 *
790
 * Right sibling of the node (if it exists) is checked for free space.
790
 * Right sibling of the node (if it exists) is checked for free space.
791
 * If there is free space, the key is inserted and the biggest key of
791
 * If there is free space, the key is inserted and the biggest key of
792
 * the node is moved there. The index node which is the parent of both
792
 * the node is moved there. The index node which is the parent of both
793
 * nodes is fixed.
793
 * nodes is fixed.
794
 *
794
 *
795
 * @param node B-tree node.
795
 * @param node B-tree node.
796
 * @param inskey Key to be inserted.
796
 * @param inskey Key to be inserted.
797
 * @param insvalue Value to be inserted.
797
 * @param insvalue Value to be inserted.
798
 * @param rsubtree Right subtree of inskey.
798
 * @param rsubtree Right subtree of inskey.
799
 *
799
 *
800
 * @return True if the rotation was performed, false otherwise.
800
 * @return True if the rotation was performed, false otherwise.
801
 */
801
 */
802
bool try_insert_by_rotation_to_right(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree)
802
bool try_insert_by_rotation_to_right(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree)
803
{
803
{
804
    index_t idx;
804
    index_t idx;
805
    btree_node_t *rnode;
805
    btree_node_t *rnode;
806
 
806
 
807
    /*
807
    /*
808
     * If this is root node, the rotation can not be done.
808
     * If this is root node, the rotation can not be done.
809
     */
809
     */
810
    if (ROOT_NODE(node))
810
    if (ROOT_NODE(node))
811
        return false;
811
        return false;
812
   
812
   
813
    idx = find_key_by_subtree(node->parent, node, false);
813
    idx = find_key_by_subtree(node->parent, node, false);
814
    if (idx == node->parent->keys) {
814
    if (idx == node->parent->keys) {
815
        /*
815
        /*
816
         * If this node is the rightmost subtree of its parent,
816
         * If this node is the rightmost subtree of its parent,
817
         * the rotation can not be done.
817
         * the rotation can not be done.
818
         */
818
         */
819
        return false;
819
        return false;
820
    }
820
    }
821
       
821
       
822
    rnode = node->parent->subtree[idx + 1];
822
    rnode = node->parent->subtree[idx + 1];
823
    if (rnode->keys < BTREE_MAX_KEYS) {
823
    if (rnode->keys < BTREE_MAX_KEYS) {
824
        /*
824
        /*
825
         * The rotaion can be done. The right sibling has free space.
825
         * The rotaion can be done. The right sibling has free space.
826
         */
826
         */
827
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
827
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
828
        rotate_from_left(node, rnode, idx);
828
        rotate_from_left(node, rnode, idx);
829
        return true;
829
        return true;
830
    }
830
    }
831
 
831
 
832
    return false;
832
    return false;
833
}
833
}
834
 
834
 
835
/** Rotate in a key from the left sibling or from the index node, if this operation can be done.
835
/** Rotate in a key from the left sibling or from the index node, if this operation can be done.
836
 *
836
 *
837
 * @param rnode Node into which to add key from its left sibling or from the index node.
837
 * @param rnode Node into which to add key from its left sibling or from the index node.
838
 *
838
 *
839
 * @return True if the rotation was performed, false otherwise.
839
 * @return True if the rotation was performed, false otherwise.
840
 */
840
 */
841
bool try_rotation_from_left(btree_node_t *rnode)
841
bool try_rotation_from_left(btree_node_t *rnode)
842
{
842
{
843
    index_t idx;
843
    index_t idx;
844
    btree_node_t *lnode;
844
    btree_node_t *lnode;
845
 
845
 
846
    /*
846
    /*
847
     * If this is root node, the rotation can not be done.
847
     * If this is root node, the rotation can not be done.
848
     */
848
     */
849
    if (ROOT_NODE(rnode))
849
    if (ROOT_NODE(rnode))
850
        return false;
850
        return false;
851
   
851
   
852
    idx = find_key_by_subtree(rnode->parent, rnode, true);
852
    idx = find_key_by_subtree(rnode->parent, rnode, true);
853
    if ((int) idx == -1) {
853
    if ((int) idx == -1) {
854
        /*
854
        /*
855
         * If this node is the leftmost subtree of its parent,
855
         * If this node is the leftmost subtree of its parent,
856
         * the rotation can not be done.
856
         * the rotation can not be done.
857
         */
857
         */
858
        return false;
858
        return false;
859
    }
859
    }
860
       
860
       
861
    lnode = rnode->parent->subtree[idx];
861
    lnode = rnode->parent->subtree[idx];
862
    if (lnode->keys > FILL_FACTOR) {
862
    if (lnode->keys > FILL_FACTOR) {
863
        rotate_from_left(lnode, rnode, idx);
863
        rotate_from_left(lnode, rnode, idx);
864
        return true;
864
        return true;
865
    }
865
    }
866
   
866
   
867
    return false;
867
    return false;
868
}
868
}
869
 
869
 
870
/** Rotate in a key from the right sibling or from the index node, if this operation can be done.
870
/** Rotate in a key from the right sibling or from the index node, if this operation can be done.
871
 *
871
 *
872
 * @param rnode Node into which to add key from its right sibling or from the index node.
872
 * @param rnode Node into which to add key from its right sibling or from the index node.
873
 *
873
 *
874
 * @return True if the rotation was performed, false otherwise.
874
 * @return True if the rotation was performed, false otherwise.
875
 */
875
 */
876
bool try_rotation_from_right(btree_node_t *lnode)
876
bool try_rotation_from_right(btree_node_t *lnode)
877
{
877
{
878
    index_t idx;
878
    index_t idx;
879
    btree_node_t *rnode;
879
    btree_node_t *rnode;
880
 
880
 
881
    /*
881
    /*
882
     * If this is root node, the rotation can not be done.
882
     * If this is root node, the rotation can not be done.
883
     */
883
     */
884
    if (ROOT_NODE(lnode))
884
    if (ROOT_NODE(lnode))
885
        return false;
885
        return false;
886
   
886
   
887
    idx = find_key_by_subtree(lnode->parent, lnode, false);
887
    idx = find_key_by_subtree(lnode->parent, lnode, false);
888
    if (idx == lnode->parent->keys) {
888
    if (idx == lnode->parent->keys) {
889
        /*
889
        /*
890
         * If this node is the rightmost subtree of its parent,
890
         * If this node is the rightmost subtree of its parent,
891
         * the rotation can not be done.
891
         * the rotation can not be done.
892
         */
892
         */
893
        return false;
893
        return false;
894
    }
894
    }
895
       
895
       
896
    rnode = lnode->parent->subtree[idx + 1];
896
    rnode = lnode->parent->subtree[idx + 1];
897
    if (rnode->keys > FILL_FACTOR) {
897
    if (rnode->keys > FILL_FACTOR) {
898
        rotate_from_right(lnode, rnode, idx);
898
        rotate_from_right(lnode, rnode, idx);
899
        return true;
899
        return true;
900
    }  
900
    }  
901
 
901
 
902
    return false;
902
    return false;
903
}
903
}
904
 
904
 
905
/** Print B-tree.
905
/** Print B-tree.
906
 *
906
 *
907
 * @param t Print out B-tree.
907
 * @param t Print out B-tree.
908
 */
908
 */
909
void btree_print(btree_t *t)
909
void btree_print(btree_t *t)
910
{
910
{
911
    int i, depth = t->root->depth;
911
    int i, depth = t->root->depth;
912
    link_t head, *cur;
912
    link_t head, *cur;
913
 
913
 
914
    printf("Printing B-tree:\n");
914
    printf("Printing B-tree:\n");
915
    list_initialize(&head);
915
    list_initialize(&head);
916
    list_append(&t->root->bfs_link, &head);
916
    list_append(&t->root->bfs_link, &head);
917
 
917
 
918
    /*
918
    /*
919
     * Use BFS search to print out the tree.
919
     * Use BFS search to print out the tree.
920
     * Levels are distinguished from one another by node->depth.
920
     * Levels are distinguished from one another by node->depth.
921
     */
921
     */
922
    while (!list_empty(&head)) {
922
    while (!list_empty(&head)) {
923
        link_t *hlp;
923
        link_t *hlp;
924
        btree_node_t *node;
924
        btree_node_t *node;
925
       
925
       
926
        hlp = head.next;
926
        hlp = head.next;
927
        ASSERT(hlp != &head);
927
        ASSERT(hlp != &head);
928
        node = list_get_instance(hlp, btree_node_t, bfs_link);
928
        node = list_get_instance(hlp, btree_node_t, bfs_link);
929
        list_remove(hlp);
929
        list_remove(hlp);
930
       
930
       
931
        ASSERT(node);
931
        ASSERT(node);
932
       
932
       
933
        if (node->depth != depth) {
933
        if (node->depth != depth) {
934
            printf("\n");
934
            printf("\n");
935
            depth = node->depth;
935
            depth = node->depth;
936
        }
936
        }
937
 
937
 
938
        printf("(");
938
        printf("(");
939
        for (i = 0; i < node->keys; i++) {
939
        for (i = 0; i < node->keys; i++) {
940
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
940
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
941
            if (node->depth && node->subtree[i]) {
941
            if (node->depth && node->subtree[i]) {
942
                list_append(&node->subtree[i]->bfs_link, &head);
942
                list_append(&node->subtree[i]->bfs_link, &head);
943
            }
943
            }
944
        }
944
        }
945
        if (node->depth && node->subtree[i]) {
945
        if (node->depth && node->subtree[i]) {
946
            list_append(&node->subtree[i]->bfs_link, &head);
946
            list_append(&node->subtree[i]->bfs_link, &head);
947
        }
947
        }
948
        printf(")");
948
        printf(")");
949
    }
949
    }
950
    printf("\n");
950
    printf("\n");
951
   
951
   
952
    printf("Printing list of leaves:\n");
952
    printf("Printing list of leaves:\n");
953
    for (cur = t->leaf_head.next; cur != &t->leaf_head; cur = cur->next) {
953
    for (cur = t->leaf_head.next; cur != &t->leaf_head; cur = cur->next) {
954
        btree_node_t *node;
954
        btree_node_t *node;
955
       
955
       
956
        node = list_get_instance(cur, btree_node_t, leaf_link);
956
        node = list_get_instance(cur, btree_node_t, leaf_link);
957
       
957
       
958
        ASSERT(node);
958
        ASSERT(node);
959
 
959
 
960
        printf("(");
960
        printf("(");
961
        for (i = 0; i < node->keys; i++)
961
        for (i = 0; i < node->keys; i++)
962
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
962
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
963
        printf(")");
963
        printf(")");
964
    }
964
    }
965
    printf("\n");
965
    printf("\n");
966
}
966
}
967
 
967