~ubuntu-branches/ubuntu/lucid/mysql-dfsg-5.1/lucid-security

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/ut/ut0rbt.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 22:33:55 UTC
  • mto: (1.2.1) (37.1.1 lucid-security)
  • mto: This revision was merged to the branch mainline in revision 36.
  • Revision ID: package-import@ubuntu.com-20120222223355-ku1tb4r70osci6v2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
5
This program is free software; you can redistribute it and/or modify it under
 
6
the terms of the GNU General Public License as published by the Free Software
 
7
Foundation; version 2 of the License.
 
8
 
 
9
This program is distributed in the hope that it will be useful, but WITHOUT
 
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
12
 
 
13
You should have received a copy of the GNU General Public License along with
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
/*******************************************************************//**
 
20
@file ut/ut0rbt.c
 
21
Red-Black tree implementation
 
22
 
 
23
Created 2007-03-20 Sunny Bains
 
24
***********************************************************************/
 
25
 
 
26
#include "ut0rbt.h"
 
27
 
 
28
/************************************************************************
 
29
Definition of a red-black tree
 
30
==============================
 
31
 
 
32
A red-black tree is a binary search tree which has the following
 
33
red-black properties:
 
34
 
 
35
   1. Every node is either red or black.
 
36
   2. Every leaf (NULL - in our case tree->nil) is black.
 
37
   3. If a node is red, then both its children are black.
 
38
   4. Every simple path from a node to a descendant leaf contains the
 
39
      same number of black nodes.
 
40
 
 
41
   from (3) above, the implication is that on any path from the root
 
42
   to a leaf, red nodes must not be adjacent.
 
43
 
 
44
   However, any number of black nodes may appear in a sequence. */
 
45
 
 
46
#if     defined(IB_RBT_TESTING)
 
47
#warning "Testing enabled!"
 
48
#endif
 
49
 
 
50
#define ROOT(t)         (t->root->left)
 
51
#define SIZEOF_NODE(t)  ((sizeof(ib_rbt_node_t) + t->sizeof_value) - 1)
 
52
 
 
53
/****************************************************************//**
 
54
Print out the sub-tree recursively. */
 
55
static
 
56
void
 
57
rbt_print_subtree(
 
58
/*==============*/
 
59
        const ib_rbt_t*         tree,   /*!< in: tree to traverse */
 
60
        const ib_rbt_node_t*    node,   /*!< in: node to print */
 
61
        ib_rbt_print_node       print)  /*!< in: print key function */
 
62
{
 
63
        /* FIXME: Doesn't do anything yet */
 
64
        if (node != tree->nil) {
 
65
                print(node);
 
66
                rbt_print_subtree(tree, node->left, print);
 
67
                rbt_print_subtree(tree, node->right, print);
 
68
        }
 
69
}
 
70
 
 
71
/****************************************************************//**
 
72
Verify that the keys are in order.
 
73
@return TRUE of OK. FALSE if not ordered */
 
74
static
 
75
ibool
 
76
rbt_check_ordering(
 
77
/*===============*/
 
78
        const ib_rbt_t*         tree)   /*!< in: tree to verfify */
 
79
{
 
80
        const ib_rbt_node_t*    node;
 
81
        const ib_rbt_node_t*    prev = NULL;
 
82
 
 
83
        /* Iterate over all the nodes, comparing each node with the prev */
 
84
        for (node = rbt_first(tree); node; node = rbt_next(tree, prev)) {
 
85
 
 
86
                if (prev && tree->compare(prev->value, node->value) >= 0) {
 
87
                        return(FALSE);
 
88
                }
 
89
 
 
90
                prev = node;
 
91
        }
 
92
 
 
93
        return(TRUE);
 
94
}
 
95
 
 
96
/****************************************************************//**
 
97
Check that every path from the root to the leaves has the same count.
 
98
Count is expressed in the number of black nodes.
 
99
@return 0 on failure else black height of the subtree */
 
100
static
 
101
ibool
 
102
rbt_count_black_nodes(
 
103
/*==================*/
 
104
        const ib_rbt_t*         tree,   /*!< in: tree to verify */
 
105
        const ib_rbt_node_t*    node)   /*!< in: start of sub-tree */
 
106
{
 
107
        ulint   result;
 
108
 
 
109
        if (node != tree->nil) {
 
110
                ulint   left_height = rbt_count_black_nodes(tree, node->left);
 
111
 
 
112
                ulint   right_height = rbt_count_black_nodes(tree, node->right);
 
113
 
 
114
                if (left_height == 0
 
115
                    || right_height == 0
 
116
                    || left_height != right_height) {
 
117
 
 
118
                        result = 0;
 
119
                } else if (node->color == IB_RBT_RED) {
 
120
 
 
121
                        /* Case 3 */
 
122
                        if (node->left->color != IB_RBT_BLACK
 
123
                            || node->right->color != IB_RBT_BLACK) {
 
124
 
 
125
                                result = 0;
 
126
                        } else {
 
127
                                result = left_height;
 
128
                        }
 
129
                /* Check if it's anything other than RED or BLACK. */
 
130
                } else if (node->color != IB_RBT_BLACK) {
 
131
 
 
132
                        result = 0;
 
133
                } else {
 
134
 
 
135
                        result = right_height + 1;
 
136
                }
 
137
        } else {
 
138
                result = 1;
 
139
        }
 
140
 
 
141
        return(result);
 
142
}
 
143
 
 
144
/****************************************************************//**
 
145
Turn the node's right child's left sub-tree into node's right sub-tree.
 
146
This will also make node's right child it's parent. */
 
147
static
 
148
void
 
149
rbt_rotate_left(
 
150
/*============*/
 
151
        const ib_rbt_node_t*    nil,    /*!< in: nil node of the tree */
 
152
        ib_rbt_node_t*          node)   /*!< in: node to rotate */
 
153
{
 
154
        ib_rbt_node_t*  right = node->right;
 
155
 
 
156
        node->right = right->left;
 
157
 
 
158
        if (right->left != nil) {
 
159
                right->left->parent = node;
 
160
        }
 
161
 
 
162
        /* Right's new parent was node's parent. */
 
163
        right->parent = node->parent;
 
164
 
 
165
        /* Since root's parent is tree->nil and root->parent->left points
 
166
        back to root, we can avoid the check. */
 
167
        if (node == node->parent->left) {
 
168
                /* Node was on the left of its parent. */
 
169
                node->parent->left = right;
 
170
        } else {
 
171
                /* Node must have been on the right. */
 
172
                node->parent->right = right;
 
173
        }
 
174
 
 
175
        /* Finally, put node on right's left. */
 
176
        right->left = node;
 
177
        node->parent = right;
 
178
}
 
179
 
 
180
/****************************************************************//**
 
181
Turn the node's left child's right sub-tree into node's left sub-tree.
 
182
This also make node's left child it's parent. */
 
183
static
 
184
void
 
185
rbt_rotate_right(
 
186
/*=============*/
 
187
        const ib_rbt_node_t*    nil,    /*!< in: nil node of tree */
 
188
        ib_rbt_node_t*          node)   /*!< in: node to rotate */
 
189
{
 
190
        ib_rbt_node_t*  left = node->left;
 
191
 
 
192
        node->left = left->right;
 
193
 
 
194
        if (left->right != nil) {
 
195
                left->right->parent = node;
 
196
        }
 
197
 
 
198
        /* Left's new parent was node's parent. */
 
199
        left->parent = node->parent;
 
200
 
 
201
        /* Since root's parent is tree->nil and root->parent->left points
 
202
        back to root, we can avoid the check. */
 
203
        if (node == node->parent->right) {
 
204
            /* Node was on the left of its parent. */
 
205
            node->parent->right = left;
 
206
        } else {
 
207
            /* Node must have been on the left. */
 
208
            node->parent->left = left;
 
209
        }
 
210
 
 
211
        /* Finally, put node on left's right. */
 
212
        left->right = node;
 
213
        node->parent = left;
 
214
}
 
215
 
 
216
/****************************************************************//**
 
217
Append a node to the tree.
 
218
@return inserted node */
 
219
static
 
220
ib_rbt_node_t*
 
221
rbt_tree_add_child(
 
222
/*===============*/
 
223
        const ib_rbt_t* tree,           /*!< in: rbt tree */
 
224
        ib_rbt_bound_t* parent,         /*!< in: node's parent */
 
225
        ib_rbt_node_t*  node)           /*!< in: node to add */
 
226
{
 
227
        /* Cast away the const. */
 
228
        ib_rbt_node_t*  last = (ib_rbt_node_t*) parent->last;
 
229
 
 
230
        if (last == tree->root || parent->result < 0) {
 
231
                last->left = node;
 
232
        } else {
 
233
                /* FIXME: We don't handle duplicates (yet)! */
 
234
                ut_a(parent->result != 0);
 
235
 
 
236
                last->right = node;
 
237
        }
 
238
 
 
239
        node->parent = last;
 
240
 
 
241
        return(node);
 
242
}
 
243
 
 
244
/****************************************************************//**
 
245
Generic binary tree insert
 
246
@return inserted node */
 
247
static
 
248
ib_rbt_node_t*
 
249
rbt_tree_insert(
 
250
/*============*/
 
251
        ib_rbt_t*       tree,           /*!< in: rb tree */
 
252
        const void*     key,            /*!< in: key for ordering */
 
253
        ib_rbt_node_t*  node)           /*!< in: node hold the insert value */
 
254
{
 
255
        ib_rbt_bound_t  parent;
 
256
        ib_rbt_node_t*  current = ROOT(tree);
 
257
 
 
258
        parent.result = 0;
 
259
        parent.last = tree->root;
 
260
 
 
261
        /* Regular binary search. */
 
262
        while (current != tree->nil) {
 
263
 
 
264
                parent.last = current;
 
265
                parent.result = tree->compare(key, current->value);
 
266
 
 
267
                if (parent.result < 0) {
 
268
                        current = current->left;
 
269
                } else {
 
270
                        current = current->right;
 
271
                }
 
272
        }
 
273
 
 
274
        ut_a(current == tree->nil);
 
275
 
 
276
        rbt_tree_add_child(tree, &parent, node);
 
277
 
 
278
        return(node);
 
279
}
 
280
 
 
281
/****************************************************************//**
 
282
Balance a tree after inserting a node. */
 
283
static
 
284
void
 
285
rbt_balance_tree(
 
286
/*=============*/
 
287
        const ib_rbt_t* tree,           /*!< in: tree to balance */
 
288
        ib_rbt_node_t*  node)           /*!< in: node that was inserted */
 
289
{
 
290
        const ib_rbt_node_t*    nil = tree->nil;
 
291
        ib_rbt_node_t*          parent = node->parent;
 
292
 
 
293
        /* Restore the red-black property. */
 
294
        node->color = IB_RBT_RED;
 
295
 
 
296
        while (node != ROOT(tree) && parent->color == IB_RBT_RED) {
 
297
                ib_rbt_node_t*  grand_parent = parent->parent;
 
298
 
 
299
                if (parent == grand_parent->left) {
 
300
                        ib_rbt_node_t*  uncle = grand_parent->right;
 
301
 
 
302
                        if (uncle->color == IB_RBT_RED) {
 
303
 
 
304
                                /* Case 1 - change the colors. */
 
305
                                uncle->color = IB_RBT_BLACK;
 
306
                                parent->color = IB_RBT_BLACK;
 
307
                                grand_parent->color = IB_RBT_RED;
 
308
 
 
309
                                /* Move node up the tree. */
 
310
                                node = grand_parent;
 
311
 
 
312
                        } else {
 
313
 
 
314
                                if (node == parent->right) {
 
315
                                        /* Right is a black node and node is
 
316
                                        to the right, case 2 - move node
 
317
                                        up and rotate. */
 
318
                                        node = parent;
 
319
                                        rbt_rotate_left(nil, node);
 
320
                                }
 
321
 
 
322
                                grand_parent = node->parent->parent;
 
323
 
 
324
                                /* Case 3. */
 
325
                                node->parent->color = IB_RBT_BLACK;
 
326
                                grand_parent->color = IB_RBT_RED;
 
327
 
 
328
                                rbt_rotate_right(nil, grand_parent);
 
329
                        }
 
330
 
 
331
                } else {
 
332
                        ib_rbt_node_t*  uncle = grand_parent->left;
 
333
 
 
334
                        if (uncle->color == IB_RBT_RED) {
 
335
 
 
336
                                /* Case 1 - change the colors. */
 
337
                                uncle->color = IB_RBT_BLACK;
 
338
                                parent->color = IB_RBT_BLACK;
 
339
                                grand_parent->color = IB_RBT_RED;
 
340
 
 
341
                                /* Move node up the tree. */
 
342
                                node = grand_parent;
 
343
 
 
344
                        } else {
 
345
 
 
346
                                if (node == parent->left) {
 
347
                                        /* Left is a black node and node is to
 
348
                                        the right, case 2 - move node up and
 
349
                                        rotate. */
 
350
                                        node = parent;
 
351
                                        rbt_rotate_right(nil, node);
 
352
                                }
 
353
 
 
354
                                grand_parent = node->parent->parent;
 
355
 
 
356
                                /* Case 3. */
 
357
                                node->parent->color = IB_RBT_BLACK;
 
358
                                grand_parent->color = IB_RBT_RED;
 
359
 
 
360
                                rbt_rotate_left(nil, grand_parent);
 
361
                        }
 
362
                }
 
363
 
 
364
                parent = node->parent;
 
365
        }
 
366
 
 
367
        /* Color the root black. */
 
368
        ROOT(tree)->color = IB_RBT_BLACK;
 
369
}
 
370
 
 
371
/****************************************************************//**
 
372
Find the given node's successor.
 
373
@return successor node or NULL if no successor */
 
374
static
 
375
ib_rbt_node_t*
 
376
rbt_find_successor(
 
377
/*===============*/
 
378
        const ib_rbt_t*         tree,   /*!< in: rb tree */
 
379
        const ib_rbt_node_t*    current)/*!< in: this is declared const
 
380
                                        because it can be called via
 
381
                                        rbt_next() */
 
382
{
 
383
        const ib_rbt_node_t*    nil = tree->nil;
 
384
        ib_rbt_node_t*          next = current->right;
 
385
 
 
386
        /* Is there a sub-tree to the right that we can follow. */
 
387
        if (next != nil) {
 
388
 
 
389
                /* Follow the left most links of the current right child. */
 
390
                while (next->left != nil) {
 
391
                        next = next->left;
 
392
                }
 
393
 
 
394
        } else { /* We will have to go up the tree to find the successor. */
 
395
                ib_rbt_node_t*  parent = current->parent;
 
396
 
 
397
                /* Cast away the const. */
 
398
                next = (ib_rbt_node_t*) current;
 
399
 
 
400
                while (parent != tree->root && next == parent->right) {
 
401
                        next = parent;
 
402
                        parent = next->parent;
 
403
                }
 
404
 
 
405
                next = (parent == tree->root) ? NULL : parent;
 
406
        }
 
407
 
 
408
        return(next);
 
409
}
 
410
 
 
411
/****************************************************************//**
 
412
Find the given node's precedecessor.
 
413
@return predecessor node or NULL if no predecesor */
 
414
static
 
415
ib_rbt_node_t*
 
416
rbt_find_predecessor(
 
417
/*=================*/
 
418
        const ib_rbt_t*         tree,           /*!< in: rb tree */
 
419
        const ib_rbt_node_t*    current)        /*!< in: this is declared const
 
420
                                                because it can be called via
 
421
                                                rbt_prev() */
 
422
{
 
423
        const ib_rbt_node_t*    nil = tree->nil;
 
424
        ib_rbt_node_t*          prev = current->left;
 
425
 
 
426
        /* Is there a sub-tree to the left that we can follow. */
 
427
        if (prev != nil) {
 
428
 
 
429
                /* Follow the right most links of the current left child. */
 
430
                while (prev->right != nil) {
 
431
                        prev = prev->right;
 
432
                }
 
433
 
 
434
        } else { /* We will have to go up the tree to find the precedecessor. */
 
435
                ib_rbt_node_t*  parent = current->parent;
 
436
 
 
437
                /* Cast away the const. */
 
438
                prev = (ib_rbt_node_t*)current;
 
439
 
 
440
                while (parent != tree->root && prev == parent->left) {
 
441
                        prev = parent;
 
442
                        parent = prev->parent;
 
443
                }
 
444
 
 
445
                prev = (parent == tree->root) ? NULL : parent;
 
446
        }
 
447
 
 
448
        return(prev);
 
449
}
 
450
 
 
451
/****************************************************************//**
 
452
Replace node with child. After applying transformations eject becomes
 
453
an orphan. */
 
454
static
 
455
void
 
456
rbt_eject_node(
 
457
/*===========*/
 
458
        ib_rbt_node_t*  eject,          /*!< in: node to eject */
 
459
        ib_rbt_node_t*  node)           /*!< in: node to replace with */
 
460
{
 
461
        /* Update the to be ejected node's parent's child pointers. */
 
462
        if (eject->parent->left == eject) {
 
463
                eject->parent->left = node;
 
464
        } else if (eject->parent->right == eject) {
 
465
                eject->parent->right = node;
 
466
        } else {
 
467
                ut_a(0);
 
468
        }
 
469
        /* eject is now an orphan but otherwise its pointers
 
470
        and color are left intact. */
 
471
 
 
472
        node->parent = eject->parent;
 
473
}
 
474
 
 
475
/****************************************************************//**
 
476
Replace a node with another node. */
 
477
static
 
478
void
 
479
rbt_replace_node(
 
480
/*=============*/
 
481
        ib_rbt_node_t*  replace,        /*!< in: node to replace */
 
482
        ib_rbt_node_t*  node)           /*!< in: node to replace with */
 
483
{
 
484
        ib_rbt_color_t  color = node->color;
 
485
 
 
486
        /* Update the node pointers. */
 
487
        node->left = replace->left;
 
488
        node->right = replace->right;
 
489
 
 
490
        /* Update the child node pointers. */
 
491
        node->left->parent = node;
 
492
        node->right->parent = node;
 
493
 
 
494
        /* Make the parent of replace point to node. */
 
495
        rbt_eject_node(replace, node);
 
496
 
 
497
        /* Swap the colors. */
 
498
        node->color = replace->color;
 
499
        replace->color = color;
 
500
}
 
501
 
 
502
/****************************************************************//**
 
503
Detach node from the tree replacing it with one of it's children.
 
504
@return the child node that now occupies the position of the detached node */
 
505
static
 
506
ib_rbt_node_t*
 
507
rbt_detach_node(
 
508
/*============*/
 
509
        const ib_rbt_t* tree,           /*!< in: rb tree */
 
510
        ib_rbt_node_t*  node)           /*!< in: node to detach */
 
511
{
 
512
        ib_rbt_node_t*          child;
 
513
        const ib_rbt_node_t*    nil = tree->nil;
 
514
 
 
515
        if (node->left != nil && node->right != nil) {
 
516
                /* Case where the node to be deleted has two children. */
 
517
                ib_rbt_node_t*  successor = rbt_find_successor(tree, node);
 
518
 
 
519
                ut_a(successor != nil);
 
520
                ut_a(successor->parent != nil);
 
521
                ut_a(successor->left == nil);
 
522
 
 
523
                child = successor->right;
 
524
 
 
525
                /* Remove the successor node and replace with its child. */
 
526
                rbt_eject_node(successor, child);
 
527
 
 
528
                /* Replace the node to delete with its successor node. */
 
529
                rbt_replace_node(node, successor);
 
530
        } else {
 
531
                ut_a(node->left == nil || node->right == nil);
 
532
 
 
533
                child = (node->left != nil) ? node->left : node->right;
 
534
 
 
535
                /* Replace the node to delete with one of it's children. */
 
536
                rbt_eject_node(node, child);
 
537
        }
 
538
 
 
539
        /* Reset the node links. */
 
540
        node->parent = node->right = node->left = tree->nil;
 
541
 
 
542
        return(child);
 
543
}
 
544
 
 
545
/****************************************************************//**
 
546
Rebalance the right sub-tree after deletion.
 
547
@return node to rebalance if more rebalancing required else NULL */
 
548
static
 
549
ib_rbt_node_t*
 
550
rbt_balance_right(
 
551
/*==============*/
 
552
        const ib_rbt_node_t*    nil,    /*!< in: rb tree nil node */
 
553
        ib_rbt_node_t*          parent, /*!< in: parent node */
 
554
        ib_rbt_node_t*          sibling)/*!< in: sibling node */
 
555
{
 
556
        ib_rbt_node_t*          node = NULL;
 
557
 
 
558
        ut_a(sibling != nil);
 
559
 
 
560
        /* Case 3. */
 
561
        if (sibling->color == IB_RBT_RED) {
 
562
 
 
563
                parent->color = IB_RBT_RED;
 
564
                sibling->color = IB_RBT_BLACK;
 
565
 
 
566
                rbt_rotate_left(nil, parent);
 
567
 
 
568
                sibling = parent->right;
 
569
 
 
570
                ut_a(sibling != nil);
 
571
        }
 
572
 
 
573
        /* Since this will violate case 3 because of the change above. */
 
574
        if (sibling->left->color == IB_RBT_BLACK
 
575
            && sibling->right->color == IB_RBT_BLACK) {
 
576
 
 
577
                node = parent; /* Parent needs to be rebalanced too. */
 
578
                sibling->color = IB_RBT_RED;
 
579
 
 
580
        } else {
 
581
                if (sibling->right->color == IB_RBT_BLACK) {
 
582
 
 
583
                        ut_a(sibling->left->color == IB_RBT_RED);
 
584
 
 
585
                        sibling->color = IB_RBT_RED;
 
586
                        sibling->left->color = IB_RBT_BLACK;
 
587
 
 
588
                        rbt_rotate_right(nil, sibling);
 
589
 
 
590
                        sibling = parent->right;
 
591
                        ut_a(sibling != nil);
 
592
                }
 
593
 
 
594
                sibling->color = parent->color;
 
595
                sibling->right->color = IB_RBT_BLACK;
 
596
 
 
597
                parent->color = IB_RBT_BLACK;
 
598
 
 
599
                rbt_rotate_left(nil, parent);
 
600
        }
 
601
 
 
602
        return(node);
 
603
}
 
604
 
 
605
/****************************************************************//**
 
606
Rebalance the left sub-tree after deletion.
 
607
@return node to rebalance if more rebalancing required else NULL */
 
608
static
 
609
ib_rbt_node_t*
 
610
rbt_balance_left(
 
611
/*=============*/
 
612
        const ib_rbt_node_t*    nil,    /*!< in: rb tree nil node */
 
613
        ib_rbt_node_t*          parent, /*!< in: parent node */
 
614
        ib_rbt_node_t*          sibling)/*!< in: sibling node */
 
615
{
 
616
        ib_rbt_node_t*  node = NULL;
 
617
 
 
618
        ut_a(sibling != nil);
 
619
 
 
620
        /* Case 3. */
 
621
        if (sibling->color == IB_RBT_RED) {
 
622
 
 
623
                parent->color = IB_RBT_RED;
 
624
                sibling->color = IB_RBT_BLACK;
 
625
 
 
626
                rbt_rotate_right(nil, parent);
 
627
                sibling = parent->left;
 
628
 
 
629
                ut_a(sibling != nil);
 
630
        }
 
631
 
 
632
        /* Since this will violate case 3 because of the change above. */
 
633
        if (sibling->right->color == IB_RBT_BLACK
 
634
            && sibling->left->color == IB_RBT_BLACK) {
 
635
 
 
636
                node = parent; /* Parent needs to be rebalanced too. */
 
637
                sibling->color = IB_RBT_RED;
 
638
 
 
639
        } else {
 
640
                if (sibling->left->color == IB_RBT_BLACK) {
 
641
 
 
642
                        ut_a(sibling->right->color == IB_RBT_RED);
 
643
 
 
644
                        sibling->color = IB_RBT_RED;
 
645
                        sibling->right->color = IB_RBT_BLACK;
 
646
 
 
647
                        rbt_rotate_left(nil, sibling);
 
648
 
 
649
                        sibling = parent->left;
 
650
 
 
651
                        ut_a(sibling != nil);
 
652
                }
 
653
 
 
654
                sibling->color = parent->color;
 
655
                sibling->left->color = IB_RBT_BLACK;
 
656
 
 
657
                parent->color = IB_RBT_BLACK;
 
658
 
 
659
                rbt_rotate_right(nil, parent);
 
660
        }
 
661
 
 
662
        return(node);
 
663
}
 
664
 
 
665
/****************************************************************//**
 
666
Delete the node and rebalance the tree if necessary */
 
667
static
 
668
void
 
669
rbt_remove_node_and_rebalance(
 
670
/*==========================*/
 
671
        ib_rbt_t*       tree,           /*!< in: rb tree */
 
672
        ib_rbt_node_t*  node)           /*!< in: node to remove */
 
673
{
 
674
        /* Detach node and get the node that will be used
 
675
        as rebalance start. */
 
676
        ib_rbt_node_t*  child = rbt_detach_node(tree, node);
 
677
 
 
678
        if (node->color == IB_RBT_BLACK) {
 
679
                ib_rbt_node_t*  last = child;
 
680
 
 
681
                ROOT(tree)->color = IB_RBT_RED;
 
682
 
 
683
                while (child && child->color == IB_RBT_BLACK) {
 
684
                        ib_rbt_node_t*  parent = child->parent;
 
685
 
 
686
                        /* Did the deletion cause an imbalance in the
 
687
                        parents left sub-tree. */
 
688
                        if (parent->left == child) {
 
689
 
 
690
                                child = rbt_balance_right(
 
691
                                        tree->nil, parent, parent->right);
 
692
 
 
693
                        } else if (parent->right == child) {
 
694
 
 
695
                                child = rbt_balance_left(
 
696
                                        tree->nil, parent, parent->left);
 
697
 
 
698
                        } else {
 
699
                                ut_error;
 
700
                        }
 
701
 
 
702
                        if (child) {
 
703
                                last = child;
 
704
                        }
 
705
                }
 
706
 
 
707
                ut_a(last);
 
708
 
 
709
                last->color = IB_RBT_BLACK;
 
710
                ROOT(tree)->color = IB_RBT_BLACK;
 
711
        }
 
712
 
 
713
        /* Note that we have removed a node from the tree. */
 
714
        --tree->n_nodes;
 
715
}
 
716
 
 
717
/****************************************************************//**
 
718
Recursively free the nodes. */
 
719
static
 
720
void
 
721
rbt_free_node(
 
722
/*==========*/
 
723
        ib_rbt_node_t*  node,           /*!< in: node to free */
 
724
        ib_rbt_node_t*  nil)            /*!< in: rb tree nil node */
 
725
{
 
726
        if (node != nil) {
 
727
                rbt_free_node(node->left, nil);
 
728
                rbt_free_node(node->right, nil);
 
729
 
 
730
                ut_free(node);
 
731
        }
 
732
}
 
733
 
 
734
/****************************************************************//**
 
735
Free all the nodes and free the tree. */
 
736
UNIV_INTERN
 
737
void
 
738
rbt_free(
 
739
/*=====*/
 
740
        ib_rbt_t*       tree)           /*!< in: rb tree to free */
 
741
{
 
742
        rbt_free_node(tree->root, tree->nil);
 
743
        ut_free(tree->nil);
 
744
        ut_free(tree);
 
745
}
 
746
 
 
747
/****************************************************************//**
 
748
Create an instance of a red black tree.
 
749
@return an empty rb tree */
 
750
UNIV_INTERN
 
751
ib_rbt_t*
 
752
rbt_create(
 
753
/*=======*/
 
754
        size_t          sizeof_value,   /*!< in: sizeof data item */
 
755
        ib_rbt_compare  compare)        /*!< in: fn to compare items */
 
756
{
 
757
        ib_rbt_t*       tree;
 
758
        ib_rbt_node_t*  node;
 
759
 
 
760
        tree = (ib_rbt_t*) ut_malloc(sizeof(*tree));
 
761
        memset(tree, 0, sizeof(*tree));
 
762
 
 
763
        tree->sizeof_value = sizeof_value;
 
764
 
 
765
        /* Create the sentinel (NIL) node. */
 
766
        node = tree->nil = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
 
767
        memset(node, 0, sizeof(*node));
 
768
 
 
769
        node->color = IB_RBT_BLACK;
 
770
        node->parent = node->left = node->right = node;
 
771
 
 
772
        /* Create the "fake" root, the real root node will be the
 
773
        left child of this node. */
 
774
        node = tree->root = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
 
775
        memset(node, 0, sizeof(*node));
 
776
 
 
777
        node->color = IB_RBT_BLACK;
 
778
        node->parent = node->left = node->right = tree->nil;
 
779
 
 
780
        tree->compare = compare;
 
781
 
 
782
        return(tree);
 
783
}
 
784
 
 
785
/****************************************************************//**
 
786
Generic insert of a value in the rb tree.
 
787
@return inserted node */
 
788
UNIV_INTERN
 
789
const ib_rbt_node_t*
 
790
rbt_insert(
 
791
/*=======*/
 
792
        ib_rbt_t*       tree,           /*!< in: rb tree */
 
793
        const void*     key,            /*!< in: key for ordering */
 
794
        const void*     value)          /*!< in: value of key, this value
 
795
                                        is copied to the node */
 
796
{
 
797
        ib_rbt_node_t*  node;
 
798
 
 
799
        /* Create the node that will hold the value data. */
 
800
        node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));
 
801
 
 
802
        memcpy(node->value, value, tree->sizeof_value);
 
803
        node->parent = node->left = node->right = tree->nil;
 
804
 
 
805
        /* Insert in the tree in the usual way. */
 
806
        rbt_tree_insert(tree, key, node);
 
807
        rbt_balance_tree(tree, node);
 
808
 
 
809
        ++tree->n_nodes;
 
810
 
 
811
        return(node);
 
812
}
 
813
 
 
814
/****************************************************************//**
 
815
Add a new node to the tree, useful for data that is pre-sorted.
 
816
@return appended node */
 
817
UNIV_INTERN
 
818
const ib_rbt_node_t*
 
819
rbt_add_node(
 
820
/*=========*/
 
821
        ib_rbt_t*       tree,           /*!< in: rb tree */
 
822
        ib_rbt_bound_t* parent,         /*!< in: bounds */
 
823
        const void*     value)          /*!< in: this value is copied
 
824
                                        to the node */
 
825
{
 
826
        ib_rbt_node_t*  node;
 
827
 
 
828
        /* Create the node that will hold the value data */
 
829
        node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));
 
830
 
 
831
        memcpy(node->value, value, tree->sizeof_value);
 
832
        node->parent = node->left = node->right = tree->nil;
 
833
 
 
834
        /* If tree is empty */
 
835
        if (parent->last == NULL) {
 
836
                parent->last = tree->root;
 
837
        }
 
838
 
 
839
        /* Append the node, the hope here is that the caller knows
 
840
        what s/he is doing. */
 
841
        rbt_tree_add_child(tree, parent, node);
 
842
        rbt_balance_tree(tree, node);
 
843
 
 
844
        ++tree->n_nodes;
 
845
 
 
846
#if     defined(IB_RBT_TESTING)
 
847
        ut_a(rbt_validate(tree));
 
848
#endif
 
849
        return(node);
 
850
}
 
851
 
 
852
/****************************************************************//**
 
853
Find a matching node in the rb tree.
 
854
@return NULL if not found else the node where key was found */
 
855
UNIV_INTERN
 
856
const ib_rbt_node_t*
 
857
rbt_lookup(
 
858
/*=======*/
 
859
        const ib_rbt_t* tree,           /*!< in: rb tree */
 
860
        const void*     key)            /*!< in: key to use for search */
 
861
{
 
862
        const ib_rbt_node_t*    current = ROOT(tree);
 
863
 
 
864
        /* Regular binary search. */
 
865
        while (current != tree->nil) {
 
866
                int     result = tree->compare(key, current->value);
 
867
 
 
868
                if (result < 0) {
 
869
                        current = current->left;
 
870
                } else if (result > 0) {
 
871
                        current = current->right;
 
872
                } else {
 
873
                        break;
 
874
                }
 
875
        }
 
876
 
 
877
        return(current != tree->nil ? current : NULL);
 
878
}
 
879
 
 
880
/****************************************************************//**
 
881
Delete a node from the red black tree, identified by key.
 
882
@return TRUE if success FALSE if not found */
 
883
UNIV_INTERN
 
884
ibool
 
885
rbt_delete(
 
886
/*=======*/
 
887
        ib_rbt_t*       tree,           /*!< in: rb tree */
 
888
        const void*     key)            /*!< in: key to delete */
 
889
{
 
890
        ibool           deleted = FALSE;
 
891
        ib_rbt_node_t*  node = (ib_rbt_node_t*) rbt_lookup(tree, key);
 
892
 
 
893
        if (node) {
 
894
                rbt_remove_node_and_rebalance(tree, node);
 
895
 
 
896
                ut_free(node);
 
897
                deleted = TRUE;
 
898
        }
 
899
 
 
900
        return(deleted);
 
901
}
 
902
 
 
903
/****************************************************************//**
 
904
Remove a node from the rb tree, the node is not free'd, that is the
 
905
callers responsibility.
 
906
@return deleted node but without the const */
 
907
UNIV_INTERN
 
908
ib_rbt_node_t*
 
909
rbt_remove_node(
 
910
/*============*/
 
911
        ib_rbt_t*               tree,           /*!< in: rb tree */
 
912
        const ib_rbt_node_t*    const_node)     /*!< in: node to delete, this
 
913
                                                is a fudge and declared const
 
914
                                                because the caller can access
 
915
                                                only const nodes */
 
916
{
 
917
        /* Cast away the const. */
 
918
        rbt_remove_node_and_rebalance(tree, (ib_rbt_node_t*) const_node);
 
919
 
 
920
        /* This is to make it easier to do something like this:
 
921
                ut_free(rbt_remove_node(node));
 
922
        */
 
923
 
 
924
        return((ib_rbt_node_t*) const_node);
 
925
}
 
926
 
 
927
/****************************************************************//**
 
928
Find the node that has the lowest key that is >= key.
 
929
@return node satisfying the lower bound constraint or NULL */
 
930
UNIV_INTERN
 
931
const ib_rbt_node_t*
 
932
rbt_lower_bound(
 
933
/*============*/
 
934
        const ib_rbt_t* tree,           /*!< in: rb tree */
 
935
        const void*     key)            /*!< in: key to search */
 
936
{
 
937
        ib_rbt_node_t*  lb_node = NULL;
 
938
        ib_rbt_node_t*  current = ROOT(tree);
 
939
 
 
940
        while (current != tree->nil) {
 
941
                int result = tree->compare(key, current->value);
 
942
 
 
943
                if (result > 0) {
 
944
 
 
945
                        current = current->right;
 
946
 
 
947
                } else if (result < 0) {
 
948
 
 
949
                        lb_node = current;
 
950
                        current = current->left;
 
951
 
 
952
                } else {
 
953
                        lb_node = current;
 
954
                        break;
 
955
                }
 
956
        }
 
957
 
 
958
        return(lb_node);
 
959
}
 
960
 
 
961
/****************************************************************//**
 
962
Find the node that has the greatest key that is <= key.
 
963
@return node satisfying the upper bound constraint or NULL */
 
964
UNIV_INTERN
 
965
const ib_rbt_node_t*
 
966
rbt_upper_bound(
 
967
/*============*/
 
968
        const ib_rbt_t* tree,           /*!< in: rb tree */
 
969
        const void*     key)            /*!< in: key to search */
 
970
{
 
971
        ib_rbt_node_t*  ub_node = NULL;
 
972
        ib_rbt_node_t*  current = ROOT(tree);
 
973
 
 
974
        while (current != tree->nil) {
 
975
                int result = tree->compare(key, current->value);
 
976
 
 
977
                if (result > 0) {
 
978
 
 
979
                        ub_node = current;
 
980
                        current = current->right;
 
981
 
 
982
                } else if (result < 0) {
 
983
 
 
984
                        current = current->left;
 
985
 
 
986
                } else {
 
987
                        ub_node = current;
 
988
                        break;
 
989
                }
 
990
        }
 
991
 
 
992
        return(ub_node);
 
993
}
 
994
 
 
995
/****************************************************************//**
 
996
Find the node that has the greatest key that is <= key.
 
997
@return value of result */
 
998
UNIV_INTERN
 
999
int
 
1000
rbt_search(
 
1001
/*=======*/
 
1002
        const ib_rbt_t* tree,           /*!< in: rb tree */
 
1003
        ib_rbt_bound_t* parent,         /*!< in: search bounds */
 
1004
        const void*     key)            /*!< in: key to search */
 
1005
{
 
1006
        ib_rbt_node_t*  current = ROOT(tree);
 
1007
 
 
1008
        /* Every thing is greater than the NULL root. */
 
1009
        parent->result = 1;
 
1010
        parent->last = NULL;
 
1011
 
 
1012
        while (current != tree->nil) {
 
1013
 
 
1014
                parent->last = current;
 
1015
                parent->result = tree->compare(key, current->value);
 
1016
 
 
1017
                if (parent->result > 0) {
 
1018
                        current = current->right;
 
1019
                } else if (parent->result < 0) {
 
1020
                        current = current->left;
 
1021
                } else {
 
1022
                        break;
 
1023
                }
 
1024
        }
 
1025
 
 
1026
        return(parent->result);
 
1027
}
 
1028
 
 
1029
/****************************************************************//**
 
1030
Find the node that has the greatest key that is <= key. But use the
 
1031
supplied comparison function.
 
1032
@return value of result */
 
1033
UNIV_INTERN
 
1034
int
 
1035
rbt_search_cmp(
 
1036
/*===========*/
 
1037
        const ib_rbt_t* tree,           /*!< in: rb tree */
 
1038
        ib_rbt_bound_t* parent,         /*!< in: search bounds */
 
1039
        const void*     key,            /*!< in: key to search */
 
1040
        ib_rbt_compare  compare)        /*!< in: fn to compare items */
 
1041
{
 
1042
        ib_rbt_node_t*  current = ROOT(tree);
 
1043
 
 
1044
        /* Every thing is greater than the NULL root. */
 
1045
        parent->result = 1;
 
1046
        parent->last = NULL;
 
1047
 
 
1048
        while (current != tree->nil) {
 
1049
 
 
1050
                parent->last = current;
 
1051
                parent->result = compare(key, current->value);
 
1052
 
 
1053
                if (parent->result > 0) {
 
1054
                        current = current->right;
 
1055
                } else if (parent->result < 0) {
 
1056
                        current = current->left;
 
1057
                } else {
 
1058
                        break;
 
1059
                }
 
1060
        }
 
1061
 
 
1062
        return(parent->result);
 
1063
}
 
1064
 
 
1065
/****************************************************************//**
 
1066
Get the leftmost node.
 
1067
Return the left most node in the tree. */
 
1068
UNIV_INTERN
 
1069
const ib_rbt_node_t*
 
1070
rbt_first(
 
1071
/*======*/
 
1072
        const ib_rbt_t* tree)           /* in: rb tree */
 
1073
{
 
1074
        ib_rbt_node_t*  first = NULL;
 
1075
        ib_rbt_node_t*  current = ROOT(tree);
 
1076
 
 
1077
        while (current != tree->nil) {
 
1078
                first = current;
 
1079
                current = current->left;
 
1080
        }
 
1081
 
 
1082
        return(first);
 
1083
}
 
1084
 
 
1085
/****************************************************************//**
 
1086
Return the right most node in the tree.
 
1087
@return the rightmost node or NULL */
 
1088
UNIV_INTERN
 
1089
const ib_rbt_node_t*
 
1090
rbt_last(
 
1091
/*=====*/
 
1092
        const ib_rbt_t* tree)           /*!< in: rb tree */
 
1093
{
 
1094
        ib_rbt_node_t*  last = NULL;
 
1095
        ib_rbt_node_t*  current = ROOT(tree);
 
1096
 
 
1097
        while (current != tree->nil) {
 
1098
                last = current;
 
1099
                current = current->right;
 
1100
        }
 
1101
 
 
1102
        return(last);
 
1103
}
 
1104
 
 
1105
/****************************************************************//**
 
1106
Return the next node.
 
1107
@return node next from current */
 
1108
UNIV_INTERN
 
1109
const ib_rbt_node_t*
 
1110
rbt_next(
 
1111
/*=====*/
 
1112
        const ib_rbt_t*         tree,   /*!< in: rb tree */
 
1113
        const ib_rbt_node_t*    current)/*!< in: current node */
 
1114
{
 
1115
        return(current ? rbt_find_successor(tree, current) : NULL);
 
1116
}
 
1117
 
 
1118
/****************************************************************//**
 
1119
Return the previous node.
 
1120
@return node prev from current */
 
1121
UNIV_INTERN
 
1122
const ib_rbt_node_t*
 
1123
rbt_prev(
 
1124
/*=====*/
 
1125
        const ib_rbt_t*         tree,   /*!< in: rb tree */
 
1126
        const ib_rbt_node_t*    current)/*!< in: current node */
 
1127
{
 
1128
        return(current ? rbt_find_predecessor(tree, current) : NULL);
 
1129
}
 
1130
 
 
1131
/****************************************************************//**
 
1132
Reset the tree. Delete all the nodes. */
 
1133
UNIV_INTERN
 
1134
void
 
1135
rbt_clear(
 
1136
/*======*/
 
1137
        ib_rbt_t*       tree)           /*!< in: rb tree */
 
1138
{
 
1139
        rbt_free_node(ROOT(tree), tree->nil);
 
1140
 
 
1141
        tree->n_nodes = 0;
 
1142
        tree->root->left = tree->root->right = tree->nil;
 
1143
}
 
1144
 
 
1145
/****************************************************************//**
 
1146
Merge the node from dst into src. Return the number of nodes merged.
 
1147
@return no. of recs merged */
 
1148
UNIV_INTERN
 
1149
ulint
 
1150
rbt_merge_uniq(
 
1151
/*===========*/
 
1152
        ib_rbt_t*       dst,            /*!< in: dst rb tree */
 
1153
        const ib_rbt_t* src)            /*!< in: src rb tree */
 
1154
{
 
1155
        ib_rbt_bound_t          parent;
 
1156
        ulint                   n_merged = 0;
 
1157
        const   ib_rbt_node_t*  src_node = rbt_first(src);
 
1158
 
 
1159
        if (rbt_empty(src) || dst == src) {
 
1160
                return(0);
 
1161
        }
 
1162
 
 
1163
        for (/* No op */; src_node; src_node = rbt_next(src, src_node)) {
 
1164
 
 
1165
                if (rbt_search(dst, &parent, src_node->value) != 0) {
 
1166
                        rbt_add_node(dst, &parent, src_node->value);
 
1167
                        ++n_merged;
 
1168
                }
 
1169
        }
 
1170
 
 
1171
        return(n_merged);
 
1172
}
 
1173
 
 
1174
/****************************************************************//**
 
1175
Merge the node from dst into src. Return the number of nodes merged.
 
1176
Delete the nodes from src after copying node to dst. As a side effect
 
1177
the duplicates will be left untouched in the src.
 
1178
@return no. of recs merged */
 
1179
UNIV_INTERN
 
1180
ulint
 
1181
rbt_merge_uniq_destructive(
 
1182
/*=======================*/
 
1183
        ib_rbt_t*       dst,            /*!< in: dst rb tree */
 
1184
        ib_rbt_t*       src)            /*!< in: src rb tree */
 
1185
{
 
1186
        ib_rbt_bound_t  parent;
 
1187
        ib_rbt_node_t*  src_node;
 
1188
        ulint           old_size = rbt_size(dst);
 
1189
 
 
1190
        if (rbt_empty(src) || dst == src) {
 
1191
                return(0);
 
1192
        }
 
1193
 
 
1194
        for (src_node = (ib_rbt_node_t*) rbt_first(src); src_node; /* */) {
 
1195
                ib_rbt_node_t*  prev = src_node;
 
1196
 
 
1197
                src_node = (ib_rbt_node_t*)rbt_next(src, prev);
 
1198
 
 
1199
                /* Skip duplicates. */
 
1200
                if (rbt_search(dst, &parent, prev->value) != 0) {
 
1201
 
 
1202
                        /* Remove and reset the node but preserve
 
1203
                        the node (data) value. */
 
1204
                        rbt_remove_node_and_rebalance(src, prev);
 
1205
 
 
1206
                        /* The nil should be taken from the dst tree. */
 
1207
                        prev->parent = prev->left = prev->right = dst->nil;
 
1208
                        rbt_tree_add_child(dst, &parent, prev);
 
1209
                        rbt_balance_tree(dst, prev);
 
1210
 
 
1211
                        ++dst->n_nodes;
 
1212
                }
 
1213
        }
 
1214
 
 
1215
#if     defined(IB_RBT_TESTING)
 
1216
        ut_a(rbt_validate(dst));
 
1217
        ut_a(rbt_validate(src));
 
1218
#endif
 
1219
        return(rbt_size(dst) - old_size);
 
1220
}
 
1221
 
 
1222
/****************************************************************//**
 
1223
Check that every path from the root to the leaves has the same count and
 
1224
the tree nodes are in order.
 
1225
@return TRUE if OK FALSE otherwise */
 
1226
UNIV_INTERN
 
1227
ibool
 
1228
rbt_validate(
 
1229
/*=========*/
 
1230
        const ib_rbt_t* tree)           /*!< in: RB tree to validate */
 
1231
{
 
1232
        if (rbt_count_black_nodes(tree, ROOT(tree)) > 0) {
 
1233
                return(rbt_check_ordering(tree));
 
1234
        }
 
1235
 
 
1236
        return(FALSE);
 
1237
}
 
1238
 
 
1239
/****************************************************************//**
 
1240
Iterate over the tree in depth first order. */
 
1241
UNIV_INTERN
 
1242
void
 
1243
rbt_print(
 
1244
/*======*/
 
1245
        const ib_rbt_t*         tree,   /*!< in: tree to traverse */
 
1246
        ib_rbt_print_node       print)  /*!< in: print function */
 
1247
{
 
1248
        rbt_print_subtree(tree, ROOT(tree), print);
 
1249
}