Subversion Repositories HelenOS-historic

Rev

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

Rev 1144 Rev 1147
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.
-
 
344
 *
-
 
345
 * @param t B-tree.
-
 
346
 * @param node Node whose left sibling will be returned.
-
 
347
 *
-
 
348
 * @return Left sibling of the node or NULL if the node does not have the left sibling.
-
 
349
 */
-
 
350
btree_node_t *btree_node_left_sibling(btree_t *t, btree_node_t *node)
-
 
351
{
-
 
352
    ASSERT(LEAF_NODE(node));
-
 
353
    if (node->leaf_link.prev != &t->leaf_head)
-
 
354
        return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
-
 
355
    else
-
 
356
        return NULL;
-
 
357
}
-
 
358
 
-
 
359
/** Return pointer to B-tree node's right sibling.
-
 
360
 *
-
 
361
 * @param t B-tree.
-
 
362
 * @param node Node whose right sibling will be returned.
-
 
363
 *
-
 
364
 * @return Right sibling of the node or NULL if the node does not have the right sibling.
-
 
365
 */
-
 
366
btree_node_t *btree_node_right_sibling(btree_t *t, btree_node_t *node)
-
 
367
{
-
 
368
    ASSERT(LEAF_NODE(node));
-
 
369
    if (node->leaf_link.next != &t->leaf_head)
-
 
370
        return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
-
 
371
    else
-
 
372
        return NULL;
-
 
373
}
-
 
374
 
343
/** Initialize B-tree node.
375
/** Initialize B-tree node.
344
 *
376
 *
345
 * @param node B-tree node.
377
 * @param node B-tree node.
346
 */
378
 */
347
void node_initialize(btree_node_t *node)
379
void node_initialize(btree_node_t *node)
348
{
380
{
349
    int i;
381
    int i;
350
 
382
 
351
    node->keys = 0;
383
    node->keys = 0;
352
   
384
   
353
    /* Clean also space for the extra key. */
385
    /* Clean also space for the extra key. */
354
    for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
386
    for (i = 0; i < BTREE_MAX_KEYS + 1; i++) {
355
        node->key[i] = 0;
387
        node->key[i] = 0;
356
        node->value[i] = NULL;
388
        node->value[i] = NULL;
357
        node->subtree[i] = NULL;
389
        node->subtree[i] = NULL;
358
    }
390
    }
359
    node->subtree[i] = NULL;
391
    node->subtree[i] = NULL;
360
   
392
   
361
    node->parent = NULL;
393
    node->parent = NULL;
362
   
394
   
363
    link_initialize(&node->leaf_link);
395
    link_initialize(&node->leaf_link);
364
 
396
 
365
    link_initialize(&node->bfs_link);
397
    link_initialize(&node->bfs_link);
366
    node->depth = 0;
398
    node->depth = 0;
367
}
399
}
368
 
400
 
369
/** Insert key-value-lsubtree triplet into B-tree node.
401
/** Insert key-value-lsubtree triplet into B-tree node.
370
 *
402
 *
371
 * 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.
372
 * This feature is used during insert by right rotation.
404
 * This feature is used during insert by right rotation.
373
 *
405
 *
374
 * @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.
375
 * @param key The key to be inserted.
407
 * @param key The key to be inserted.
376
 * @param value Pointer to value to be inserted.
408
 * @param value Pointer to value to be inserted.
377
 * @param lsubtree Pointer to the left subtree.
409
 * @param lsubtree Pointer to the left subtree.
378
 */
410
 */
379
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)
380
{
412
{
381
    int i;
413
    int i;
382
 
414
 
383
    for (i = 0; i < node->keys; i++) {
415
    for (i = 0; i < node->keys; i++) {
384
        if (key < node->key[i]) {
416
        if (key < node->key[i]) {
385
            int j;
417
            int j;
386
       
418
       
387
            for (j = node->keys; j > i; j--) {
419
            for (j = node->keys; j > i; j--) {
388
                node->key[j] = node->key[j - 1];
420
                node->key[j] = node->key[j - 1];
389
                node->value[j] = node->value[j - 1];
421
                node->value[j] = node->value[j - 1];
390
                node->subtree[j + 1] = node->subtree[j];
422
                node->subtree[j + 1] = node->subtree[j];
391
            }
423
            }
392
            node->subtree[j + 1] = node->subtree[j];
424
            node->subtree[j + 1] = node->subtree[j];
393
            break; 
425
            break; 
394
        }
426
        }
395
    }
427
    }
396
    node->key[i] = key;
428
    node->key[i] = key;
397
    node->value[i] = value;
429
    node->value[i] = value;
398
    node->subtree[i] = lsubtree;
430
    node->subtree[i] = lsubtree;
399
           
431
           
400
    node->keys++;
432
    node->keys++;
401
}
433
}
402
 
434
 
403
/** Insert key-value-rsubtree triplet into B-tree node.
435
/** Insert key-value-rsubtree triplet into B-tree node.
404
 *
436
 *
405
 * 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.
406
 * This feature is used during splitting the node when the
438
 * This feature is used during splitting the node when the
407
 * 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
408
 * also makes use of this feature.
440
 * also makes use of this feature.
409
 *
441
 *
410
 * @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.
411
 * @param key The key to be inserted.
443
 * @param key The key to be inserted.
412
 * @param value Pointer to value to be inserted.
444
 * @param value Pointer to value to be inserted.
413
 * @param rsubtree Pointer to the right subtree.
445
 * @param rsubtree Pointer to the right subtree.
414
 */
446
 */
415
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)
416
{
448
{
417
    int i;
449
    int i;
418
 
450
 
419
    for (i = 0; i < node->keys; i++) {
451
    for (i = 0; i < node->keys; i++) {
420
        if (key < node->key[i]) {
452
        if (key < node->key[i]) {
421
            int j;
453
            int j;
422
       
454
       
423
            for (j = node->keys; j > i; j--) {
455
            for (j = node->keys; j > i; j--) {
424
                node->key[j] = node->key[j - 1];
456
                node->key[j] = node->key[j - 1];
425
                node->value[j] = node->value[j - 1];
457
                node->value[j] = node->value[j - 1];
426
                node->subtree[j + 1] = node->subtree[j];
458
                node->subtree[j + 1] = node->subtree[j];
427
            }
459
            }
428
            break; 
460
            break; 
429
        }
461
        }
430
    }
462
    }
431
    node->key[i] = key;
463
    node->key[i] = key;
432
    node->value[i] = value;
464
    node->value[i] = value;
433
    node->subtree[i + 1] = rsubtree;
465
    node->subtree[i + 1] = rsubtree;
434
           
466
           
435
    node->keys++;
467
    node->keys++;
436
}
468
}
437
 
469
 
438
/** Remove key and its left subtree pointer from B-tree node.
470
/** Remove key and its left subtree pointer from B-tree node.
439
 *
471
 *
440
 * Remove the key and eliminate gaps in node->key array.
472
 * Remove the key and eliminate gaps in node->key array.
441
 * Note that the value pointer and the left subtree pointer
473
 * Note that the value pointer and the left subtree pointer
442
 * is removed from the node as well.
474
 * is removed from the node as well.
443
 *
475
 *
444
 * @param node B-tree node.
476
 * @param node B-tree node.
445
 * @param key Key to be removed.
477
 * @param key Key to be removed.
446
 */
478
 */
447
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)
448
{
480
{
449
    int i, j;
481
    int i, j;
450
   
482
   
451
    for (i = 0; i < node->keys; i++) {
483
    for (i = 0; i < node->keys; i++) {
452
        if (key == node->key[i]) {
484
        if (key == node->key[i]) {
453
            for (j = i + 1; j < node->keys; j++) {
485
            for (j = i + 1; j < node->keys; j++) {
454
                node->key[j - 1] = node->key[j];
486
                node->key[j - 1] = node->key[j];
455
                node->value[j - 1] = node->value[j];
487
                node->value[j - 1] = node->value[j];
456
                node->subtree[j - 1] = node->subtree[j];
488
                node->subtree[j - 1] = node->subtree[j];
457
            }
489
            }
458
            node->subtree[j - 1] = node->subtree[j];
490
            node->subtree[j - 1] = node->subtree[j];
459
            node->keys--;
491
            node->keys--;
460
            return;
492
            return;
461
        }
493
        }
462
    }
494
    }
463
    panic("node %P does not contain key %d\n", node, key);
495
    panic("node %P does not contain key %d\n", node, key);
464
}
496
}
465
 
497
 
466
/** Remove key and its right subtree pointer from B-tree node.
498
/** Remove key and its right subtree pointer from B-tree node.
467
 *
499
 *
468
 * Remove the key and eliminate gaps in node->key array.
500
 * Remove the key and eliminate gaps in node->key array.
469
 * Note that the value pointer and the right subtree pointer
501
 * Note that the value pointer and the right subtree pointer
470
 * is removed from the node as well.
502
 * is removed from the node as well.
471
 *
503
 *
472
 * @param node B-tree node.
504
 * @param node B-tree node.
473
 * @param key Key to be removed.
505
 * @param key Key to be removed.
474
 */
506
 */
475
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)
476
{
508
{
477
    int i, j;
509
    int i, j;
478
   
510
   
479
    for (i = 0; i < node->keys; i++) {
511
    for (i = 0; i < node->keys; i++) {
480
        if (key == node->key[i]) {
512
        if (key == node->key[i]) {
481
            for (j = i + 1; j < node->keys; j++) {
513
            for (j = i + 1; j < node->keys; j++) {
482
                node->key[j - 1] = node->key[j];
514
                node->key[j - 1] = node->key[j];
483
                node->value[j - 1] = node->value[j];
515
                node->value[j - 1] = node->value[j];
484
                node->subtree[j] = node->subtree[j + 1];
516
                node->subtree[j] = node->subtree[j + 1];
485
            }
517
            }
486
            node->keys--;
518
            node->keys--;
487
            return;
519
            return;
488
        }
520
        }
489
    }
521
    }
490
    panic("node %P does not contain key %d\n", node, key);
522
    panic("node %P does not contain key %d\n", node, key);
491
}
523
}
492
 
524
 
493
/** 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.
494
 *
526
 *
495
 * 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
496
 * 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
497
 * (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
498
 * the median key to a memory address supplied by the caller.
530
 * the median key to a memory address supplied by the caller.
499
 *
531
 *
500
 * 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
501
 * 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,
502
 * the median will be copied there.
534
 * the median will be copied there.
503
 *
535
 *
504
 * @param node B-tree node wich is going to be split.
536
 * @param node B-tree node wich is going to be split.
505
 * @param key The key to be inserted.
537
 * @param key The key to be inserted.
506
 * @param value Pointer to the value to be inserted.
538
 * @param value Pointer to the value to be inserted.
507
 * @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.
508
 * @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.
509
 *
541
 *
510
 * @return Newly created right sibling of node.
542
 * @return Newly created right sibling of node.
511
 */
543
 */
512
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)
513
{
545
{
514
    btree_node_t *rnode;
546
    btree_node_t *rnode;
515
    int i, j;
547
    int i, j;
516
 
548
 
517
    ASSERT(median);
549
    ASSERT(median);
518
    ASSERT(node->keys == BTREE_MAX_KEYS);
550
    ASSERT(node->keys == BTREE_MAX_KEYS);
519
 
551
 
520
    /*
552
    /*
521
     * Use the extra space to store the extra node.
553
     * Use the extra space to store the extra node.
522
     */
554
     */
523
    node_insert_key_and_rsubtree(node, key, value, rsubtree);
555
    node_insert_key_and_rsubtree(node, key, value, rsubtree);
524
 
556
 
525
    /*
557
    /*
526
     * Compute median of keys.
558
     * Compute median of keys.
527
     */
559
     */
528
    *median = MEDIAN_HIGH(node);
560
    *median = MEDIAN_HIGH(node);
529
       
561
       
530
    /*
562
    /*
531
     * Allocate and initialize new right sibling.
563
     * Allocate and initialize new right sibling.
532
     */
564
     */
533
    rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
565
    rnode = (btree_node_t *) malloc(sizeof(btree_node_t), 0);
534
    node_initialize(rnode);
566
    node_initialize(rnode);
535
    rnode->parent = node->parent;
567
    rnode->parent = node->parent;
536
    rnode->depth = node->depth;
568
    rnode->depth = node->depth;
537
   
569
   
538
    /*
570
    /*
539
     * 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.
540
     * If this is an index node, do not copy the median.
572
     * If this is an index node, do not copy the median.
541
     */
573
     */
542
    i = (int) INDEX_NODE(node);
574
    i = (int) INDEX_NODE(node);
543
    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++) {
544
        rnode->key[j] = node->key[i];
576
        rnode->key[j] = node->key[i];
545
        rnode->value[j] = node->value[i];
577
        rnode->value[j] = node->value[i];
546
        rnode->subtree[j] = node->subtree[i];
578
        rnode->subtree[j] = node->subtree[i];
547
       
579
       
548
        /*
580
        /*
549
         * Fix parent links in subtrees.
581
         * Fix parent links in subtrees.
550
         */
582
         */
551
        if (rnode->subtree[j])
583
        if (rnode->subtree[j])
552
            rnode->subtree[j]->parent = rnode;
584
            rnode->subtree[j]->parent = rnode;
553
           
585
           
554
    }
586
    }
555
    rnode->subtree[j] = node->subtree[i];
587
    rnode->subtree[j] = node->subtree[i];
556
    if (rnode->subtree[j])
588
    if (rnode->subtree[j])
557
        rnode->subtree[j]->parent = rnode;
589
        rnode->subtree[j]->parent = rnode;
558
 
590
 
559
    rnode->keys = j;    /* Set number of keys of the new node. */
591
    rnode->keys = j;    /* Set number of keys of the new node. */
560
    node->keys /= 2;    /* Shrink the old node. */
592
    node->keys /= 2;    /* Shrink the old node. */
561
       
593
       
562
    return rnode;
594
    return rnode;
563
}
595
}
564
 
596
 
565
/** Combine node with any of its siblings.
597
/** Combine node with any of its siblings.
566
 *
598
 *
567
 * The siblings are required to be below the fill factor.
599
 * The siblings are required to be below the fill factor.
568
 *
600
 *
569
 * @param node Node to combine with one of its siblings.
601
 * @param node Node to combine with one of its siblings.
570
 *
602
 *
571
 * @return Pointer to the rightmost of the two nodes.
603
 * @return Pointer to the rightmost of the two nodes.
572
 */
604
 */
573
btree_node_t *node_combine(btree_node_t *node)
605
btree_node_t *node_combine(btree_node_t *node)
574
{
606
{
575
    index_t idx;
607
    index_t idx;
576
    btree_node_t *rnode;
608
    btree_node_t *rnode;
577
    int i;
609
    int i;
578
 
610
 
579
    ASSERT(!ROOT_NODE(node));
611
    ASSERT(!ROOT_NODE(node));
580
   
612
   
581
    idx = find_key_by_subtree(node->parent, node, false);
613
    idx = find_key_by_subtree(node->parent, node, false);
582
    if (idx == node->parent->keys) {
614
    if (idx == node->parent->keys) {
583
        /*
615
        /*
584
         * Rightmost subtree of its parent, combine with the left sibling.
616
         * Rightmost subtree of its parent, combine with the left sibling.
585
         */
617
         */
586
        idx--;
618
        idx--;
587
        rnode = node;
619
        rnode = node;
588
        node = node->parent->subtree[idx];
620
        node = node->parent->subtree[idx];
589
    } else {
621
    } else {
590
        rnode = node->parent->subtree[idx + 1];
622
        rnode = node->parent->subtree[idx + 1];
591
    }
623
    }
592
 
624
 
593
    /* 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. */
594
    if (INDEX_NODE(node))
626
    if (INDEX_NODE(node))
595
        node->key[node->keys++] = node->parent->key[idx];
627
        node->key[node->keys++] = node->parent->key[idx];
596
   
628
   
597
    /* Copy the key-value-subtree triplets from the right node. */
629
    /* Copy the key-value-subtree triplets from the right node. */
598
    for (i = 0; i < rnode->keys; i++) {
630
    for (i = 0; i < rnode->keys; i++) {
599
        node->key[node->keys + i] = rnode->key[i];
631
        node->key[node->keys + i] = rnode->key[i];
600
        node->value[node->keys + i] = rnode->value[i];
632
        node->value[node->keys + i] = rnode->value[i];
601
        if (INDEX_NODE(node)) {
633
        if (INDEX_NODE(node)) {
602
            node->subtree[node->keys + i] = rnode->subtree[i];
634
            node->subtree[node->keys + i] = rnode->subtree[i];
603
            rnode->subtree[i]->parent = node;
635
            rnode->subtree[i]->parent = node;
604
        }
636
        }
605
    }
637
    }
606
    if (INDEX_NODE(node)) {
638
    if (INDEX_NODE(node)) {
607
        node->subtree[node->keys + i] = rnode->subtree[i];
639
        node->subtree[node->keys + i] = rnode->subtree[i];
608
        rnode->subtree[i]->parent = node;
640
        rnode->subtree[i]->parent = node;
609
    }
641
    }
610
 
642
 
611
    node->keys += rnode->keys;
643
    node->keys += rnode->keys;
612
 
644
 
613
    return rnode;
645
    return rnode;
614
}
646
}
615
 
647
 
616
/** Find key by its left or right subtree.
648
/** Find key by its left or right subtree.
617
 *
649
 *
618
 * @param node B-tree node.
650
 * @param node B-tree node.
619
 * @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.
620
 * @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.
621
 *
653
 *
622
 * @return Index of the key associated with the subtree.
654
 * @return Index of the key associated with the subtree.
623
 */
655
 */
624
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)
625
{
657
{
626
    int i;
658
    int i;
627
   
659
   
628
    for (i = 0; i < node->keys + 1; i++) {
660
    for (i = 0; i < node->keys + 1; i++) {
629
        if (subtree == node->subtree[i])
661
        if (subtree == node->subtree[i])
630
            return i - (int) (right != false);
662
            return i - (int) (right != false);
631
    }
663
    }
632
    panic("node %P does not contain subtree %P\n", node, subtree);
664
    panic("node %P does not contain subtree %P\n", node, subtree);
633
}
665
}
634
 
666
 
635
/** 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.
636
 *
668
 *
637
 * 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
638
 * 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
639
 * the left node takes part in the rotation.
671
 * the left node takes part in the rotation.
640
 *
672
 *
641
 * @param lnode Left sibling.
673
 * @param lnode Left sibling.
642
 * @param rnode Right sibling.
674
 * @param rnode Right sibling.
643
 * @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.
644
 */
676
 */
645
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)
646
{
678
{
647
    __native key;
679
    __native key;
648
 
680
 
649
    key = lnode->key[lnode->keys - 1];
681
    key = lnode->key[lnode->keys - 1];
650
       
682
       
651
    if (LEAF_NODE(lnode)) {
683
    if (LEAF_NODE(lnode)) {
652
        void *value;
684
        void *value;
653
 
685
 
654
        value = lnode->value[lnode->keys - 1];
686
        value = lnode->value[lnode->keys - 1];
655
        node_remove_key_and_rsubtree(lnode, key);
687
        node_remove_key_and_rsubtree(lnode, key);
656
        node_insert_key_and_lsubtree(rnode, key, value, NULL);
688
        node_insert_key_and_lsubtree(rnode, key, value, NULL);
657
        lnode->parent->key[idx] = key;
689
        lnode->parent->key[idx] = key;
658
    } else {
690
    } else {
659
        btree_node_t *rsubtree;
691
        btree_node_t *rsubtree;
660
 
692
 
661
        rsubtree = lnode->subtree[lnode->keys];
693
        rsubtree = lnode->subtree[lnode->keys];
662
        node_remove_key_and_rsubtree(lnode, key);
694
        node_remove_key_and_rsubtree(lnode, key);
663
        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);
664
        lnode->parent->key[idx] = key;
696
        lnode->parent->key[idx] = key;
665
 
697
 
666
        /* Fix parent link of the reconnected right subtree. */
698
        /* Fix parent link of the reconnected right subtree. */
667
        rsubtree->parent = rnode;
699
        rsubtree->parent = rnode;
668
    }
700
    }
669
 
701
 
670
}
702
}
671
 
703
 
672
/** 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.
673
 *
705
 *
674
 * 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
675
 * 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
676
 * the right node takes part in the rotation.
708
 * the right node takes part in the rotation.
677
 *
709
 *
678
 * @param lnode Left sibling.
710
 * @param lnode Left sibling.
679
 * @param rnode Right sibling.
711
 * @param rnode Right sibling.
680
 * @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.
681
 */
713
 */
682
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)
683
{
715
{
684
    __native key;
716
    __native key;
685
 
717
 
686
    key = rnode->key[0];
718
    key = rnode->key[0];
687
       
719
       
688
    if (LEAF_NODE(rnode)) {
720
    if (LEAF_NODE(rnode)) {
689
        void *value;
721
        void *value;
690
 
722
 
691
        value = rnode->value[0];
723
        value = rnode->value[0];
692
        node_remove_key_and_lsubtree(rnode, key);
724
        node_remove_key_and_lsubtree(rnode, key);
693
        node_insert_key_and_rsubtree(lnode, key, value, NULL);
725
        node_insert_key_and_rsubtree(lnode, key, value, NULL);
694
        rnode->parent->key[idx] = rnode->key[0];
726
        rnode->parent->key[idx] = rnode->key[0];
695
    } else {
727
    } else {
696
        btree_node_t *lsubtree;
728
        btree_node_t *lsubtree;
697
 
729
 
698
        lsubtree = rnode->subtree[0];
730
        lsubtree = rnode->subtree[0];
699
        node_remove_key_and_lsubtree(rnode, key);
731
        node_remove_key_and_lsubtree(rnode, key);
700
        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);
701
        rnode->parent->key[idx] = key;
733
        rnode->parent->key[idx] = key;
702
 
734
 
703
        /* Fix parent link of the reconnected left subtree. */
735
        /* Fix parent link of the reconnected left subtree. */
704
        lsubtree->parent = lnode;
736
        lsubtree->parent = lnode;
705
    }
737
    }
706
 
738
 
707
}
739
}
708
 
740
 
709
/** 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.
710
 *
742
 *
711
 * 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.
712
 * 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
713
 * 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
714
 * nodes is fixed.
746
 * nodes is fixed.
715
 *
747
 *
716
 * @param node B-tree node.
748
 * @param node B-tree node.
717
 * @param inskey Key to be inserted.
749
 * @param inskey Key to be inserted.
718
 * @param insvalue Value to be inserted.
750
 * @param insvalue Value to be inserted.
719
 * @param rsubtree Right subtree of inskey.
751
 * @param rsubtree Right subtree of inskey.
720
 *
752
 *
721
 * @return True if the rotation was performed, false otherwise.
753
 * @return True if the rotation was performed, false otherwise.
722
 */
754
 */
723
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)
724
{
756
{
725
    index_t idx;
757
    index_t idx;
726
    btree_node_t *lnode;
758
    btree_node_t *lnode;
727
 
759
 
728
    /*
760
    /*
729
     * If this is root node, the rotation can not be done.
761
     * If this is root node, the rotation can not be done.
730
     */
762
     */
731
    if (ROOT_NODE(node))
763
    if (ROOT_NODE(node))
732
        return false;
764
        return false;
733
   
765
   
734
    idx = find_key_by_subtree(node->parent, node, true);
766
    idx = find_key_by_subtree(node->parent, node, true);
735
    if ((int) idx == -1) {
767
    if ((int) idx == -1) {
736
        /*
768
        /*
737
         * If this node is the leftmost subtree of its parent,
769
         * If this node is the leftmost subtree of its parent,
738
         * the rotation can not be done.
770
         * the rotation can not be done.
739
         */
771
         */
740
        return false;
772
        return false;
741
    }
773
    }
742
       
774
       
743
    lnode = node->parent->subtree[idx];
775
    lnode = node->parent->subtree[idx];
744
    if (lnode->keys < BTREE_MAX_KEYS) {
776
    if (lnode->keys < BTREE_MAX_KEYS) {
745
        /*
777
        /*
746
         * The rotaion can be done. The left sibling has free space.
778
         * The rotaion can be done. The left sibling has free space.
747
         */
779
         */
748
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
780
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
749
        rotate_from_right(lnode, node, idx);
781
        rotate_from_right(lnode, node, idx);
750
        return true;
782
        return true;
751
    }
783
    }
752
 
784
 
753
    return false;
785
    return false;
754
}
786
}
755
 
787
 
756
/** 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.
757
 *
789
 *
758
 * 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.
759
 * 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
760
 * 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
761
 * nodes is fixed.
793
 * nodes is fixed.
762
 *
794
 *
763
 * @param node B-tree node.
795
 * @param node B-tree node.
764
 * @param inskey Key to be inserted.
796
 * @param inskey Key to be inserted.
765
 * @param insvalue Value to be inserted.
797
 * @param insvalue Value to be inserted.
766
 * @param rsubtree Right subtree of inskey.
798
 * @param rsubtree Right subtree of inskey.
767
 *
799
 *
768
 * @return True if the rotation was performed, false otherwise.
800
 * @return True if the rotation was performed, false otherwise.
769
 */
801
 */
770
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)
771
{
803
{
772
    index_t idx;
804
    index_t idx;
773
    btree_node_t *rnode;
805
    btree_node_t *rnode;
774
 
806
 
775
    /*
807
    /*
776
     * If this is root node, the rotation can not be done.
808
     * If this is root node, the rotation can not be done.
777
     */
809
     */
778
    if (ROOT_NODE(node))
810
    if (ROOT_NODE(node))
779
        return false;
811
        return false;
780
   
812
   
781
    idx = find_key_by_subtree(node->parent, node, false);
813
    idx = find_key_by_subtree(node->parent, node, false);
782
    if (idx == node->parent->keys) {
814
    if (idx == node->parent->keys) {
783
        /*
815
        /*
784
         * If this node is the rightmost subtree of its parent,
816
         * If this node is the rightmost subtree of its parent,
785
         * the rotation can not be done.
817
         * the rotation can not be done.
786
         */
818
         */
787
        return false;
819
        return false;
788
    }
820
    }
789
       
821
       
790
    rnode = node->parent->subtree[idx + 1];
822
    rnode = node->parent->subtree[idx + 1];
791
    if (rnode->keys < BTREE_MAX_KEYS) {
823
    if (rnode->keys < BTREE_MAX_KEYS) {
792
        /*
824
        /*
793
         * The rotaion can be done. The right sibling has free space.
825
         * The rotaion can be done. The right sibling has free space.
794
         */
826
         */
795
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
827
        node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);
796
        rotate_from_left(node, rnode, idx);
828
        rotate_from_left(node, rnode, idx);
797
        return true;
829
        return true;
798
    }
830
    }
799
 
831
 
800
    return false;
832
    return false;
801
}
833
}
802
 
834
 
803
/** 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.
804
 *
836
 *
805
 * @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.
806
 *
838
 *
807
 * @return True if the rotation was performed, false otherwise.
839
 * @return True if the rotation was performed, false otherwise.
808
 */
840
 */
809
bool try_rotation_from_left(btree_node_t *rnode)
841
bool try_rotation_from_left(btree_node_t *rnode)
810
{
842
{
811
    index_t idx;
843
    index_t idx;
812
    btree_node_t *lnode;
844
    btree_node_t *lnode;
813
 
845
 
814
    /*
846
    /*
815
     * If this is root node, the rotation can not be done.
847
     * If this is root node, the rotation can not be done.
816
     */
848
     */
817
    if (ROOT_NODE(rnode))
849
    if (ROOT_NODE(rnode))
818
        return false;
850
        return false;
819
   
851
   
820
    idx = find_key_by_subtree(rnode->parent, rnode, true);
852
    idx = find_key_by_subtree(rnode->parent, rnode, true);
821
    if ((int) idx == -1) {
853
    if ((int) idx == -1) {
822
        /*
854
        /*
823
         * If this node is the leftmost subtree of its parent,
855
         * If this node is the leftmost subtree of its parent,
824
         * the rotation can not be done.
856
         * the rotation can not be done.
825
         */
857
         */
826
        return false;
858
        return false;
827
    }
859
    }
828
       
860
       
829
    lnode = rnode->parent->subtree[idx];
861
    lnode = rnode->parent->subtree[idx];
830
    if (lnode->keys > FILL_FACTOR) {
862
    if (lnode->keys > FILL_FACTOR) {
831
        rotate_from_left(lnode, rnode, idx);
863
        rotate_from_left(lnode, rnode, idx);
832
        return true;
864
        return true;
833
    }
865
    }
834
   
866
   
835
    return false;
867
    return false;
836
}
868
}
837
 
869
 
838
/** 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.
839
 *
871
 *
840
 * @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.
841
 *
873
 *
842
 * @return True if the rotation was performed, false otherwise.
874
 * @return True if the rotation was performed, false otherwise.
843
 */
875
 */
844
bool try_rotation_from_right(btree_node_t *lnode)
876
bool try_rotation_from_right(btree_node_t *lnode)
845
{
877
{
846
    index_t idx;
878
    index_t idx;
847
    btree_node_t *rnode;
879
    btree_node_t *rnode;
848
 
880
 
849
    /*
881
    /*
850
     * If this is root node, the rotation can not be done.
882
     * If this is root node, the rotation can not be done.
851
     */
883
     */
852
    if (ROOT_NODE(lnode))
884
    if (ROOT_NODE(lnode))
853
        return false;
885
        return false;
854
   
886
   
855
    idx = find_key_by_subtree(lnode->parent, lnode, false);
887
    idx = find_key_by_subtree(lnode->parent, lnode, false);
856
    if (idx == lnode->parent->keys) {
888
    if (idx == lnode->parent->keys) {
857
        /*
889
        /*
858
         * If this node is the rightmost subtree of its parent,
890
         * If this node is the rightmost subtree of its parent,
859
         * the rotation can not be done.
891
         * the rotation can not be done.
860
         */
892
         */
861
        return false;
893
        return false;
862
    }
894
    }
863
       
895
       
864
    rnode = lnode->parent->subtree[idx + 1];
896
    rnode = lnode->parent->subtree[idx + 1];
865
    if (rnode->keys > FILL_FACTOR) {
897
    if (rnode->keys > FILL_FACTOR) {
866
        rotate_from_right(lnode, rnode, idx);
898
        rotate_from_right(lnode, rnode, idx);
867
        return true;
899
        return true;
868
    }  
900
    }  
869
 
901
 
870
    return false;
902
    return false;
871
}
903
}
872
 
904
 
873
/** Print B-tree.
905
/** Print B-tree.
874
 *
906
 *
875
 * @param t Print out B-tree.
907
 * @param t Print out B-tree.
876
 */
908
 */
877
void btree_print(btree_t *t)
909
void btree_print(btree_t *t)
878
{
910
{
879
    int i, depth = t->root->depth;
911
    int i, depth = t->root->depth;
880
    link_t head, *cur;
912
    link_t head, *cur;
881
 
913
 
882
    printf("Printing B-tree:\n");
914
    printf("Printing B-tree:\n");
883
    list_initialize(&head);
915
    list_initialize(&head);
884
    list_append(&t->root->bfs_link, &head);
916
    list_append(&t->root->bfs_link, &head);
885
 
917
 
886
    /*
918
    /*
887
     * Use BFS search to print out the tree.
919
     * Use BFS search to print out the tree.
888
     * Levels are distinguished from one another by node->depth.
920
     * Levels are distinguished from one another by node->depth.
889
     */
921
     */
890
    while (!list_empty(&head)) {
922
    while (!list_empty(&head)) {
891
        link_t *hlp;
923
        link_t *hlp;
892
        btree_node_t *node;
924
        btree_node_t *node;
893
       
925
       
894
        hlp = head.next;
926
        hlp = head.next;
895
        ASSERT(hlp != &head);
927
        ASSERT(hlp != &head);
896
        node = list_get_instance(hlp, btree_node_t, bfs_link);
928
        node = list_get_instance(hlp, btree_node_t, bfs_link);
897
        list_remove(hlp);
929
        list_remove(hlp);
898
       
930
       
899
        ASSERT(node);
931
        ASSERT(node);
900
       
932
       
901
        if (node->depth != depth) {
933
        if (node->depth != depth) {
902
            printf("\n");
934
            printf("\n");
903
            depth = node->depth;
935
            depth = node->depth;
904
        }
936
        }
905
 
937
 
906
        printf("(");
938
        printf("(");
907
        for (i = 0; i < node->keys; i++) {
939
        for (i = 0; i < node->keys; i++) {
908
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
940
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
909
            if (node->depth && node->subtree[i]) {
941
            if (node->depth && node->subtree[i]) {
910
                list_append(&node->subtree[i]->bfs_link, &head);
942
                list_append(&node->subtree[i]->bfs_link, &head);
911
            }
943
            }
912
        }
944
        }
913
        if (node->depth && node->subtree[i]) {
945
        if (node->depth && node->subtree[i]) {
914
            list_append(&node->subtree[i]->bfs_link, &head);
946
            list_append(&node->subtree[i]->bfs_link, &head);
915
        }
947
        }
916
        printf(")");
948
        printf(")");
917
    }
949
    }
918
    printf("\n");
950
    printf("\n");
919
   
951
   
920
    printf("Printing list of leaves:\n");
952
    printf("Printing list of leaves:\n");
921
    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) {
922
        btree_node_t *node;
954
        btree_node_t *node;
923
       
955
       
924
        node = list_get_instance(cur, btree_node_t, leaf_link);
956
        node = list_get_instance(cur, btree_node_t, leaf_link);
925
       
957
       
926
        ASSERT(node);
958
        ASSERT(node);
927
 
959
 
928
        printf("(");
960
        printf("(");
929
        for (i = 0; i < node->keys; i++)
961
        for (i = 0; i < node->keys; i++)
930
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
962
            printf("%d%s", node->key[i], i < node->keys - 1 ? "," : "");
931
        printf(")");
963
        printf(")");
932
    }
964
    }
933
    printf("\n");
965
    printf("\n");
934
}
966
}
935
 
967