LCOV - differential code coverage report
Current view: top level - src/backend/lib - rbtree.c (source / functions) Coverage Total Hit LBC UIC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 98.9 % 271 268 2 1 137 24 107 3 159
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 17 17 12 2 3 14
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 98.9 % 271 268 2 1 137 24 107 1 136
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 58.6 % 29 17 12 2 3 12

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * rbtree.c
                                  4                 :  *    implementation for PostgreSQL generic Red-Black binary tree package
                                  5                 :  *    Adopted from http://algolist.manual.ru/ds/rbtree.php
                                  6                 :  *
                                  7                 :  * This code comes from Thomas Niemann's "Sorting and Searching Algorithms:
                                  8                 :  * a Cookbook".
                                  9                 :  *
                                 10                 :  * See http://www.cs.auckland.ac.nz/software/AlgAnim/niemann/s_man.htm for
                                 11                 :  * license terms: "Source code, when part of a software project, may be used
                                 12                 :  * freely without reference to the author."
                                 13                 :  *
                                 14                 :  * Red-black trees are a type of balanced binary tree wherein (1) any child of
                                 15                 :  * a red node is always black, and (2) every path from root to leaf traverses
                                 16                 :  * an equal number of black nodes.  From these properties, it follows that the
                                 17                 :  * longest path from root to leaf is only about twice as long as the shortest,
                                 18                 :  * so lookups are guaranteed to run in O(lg n) time.
                                 19                 :  *
                                 20                 :  * Copyright (c) 2009-2023, PostgreSQL Global Development Group
                                 21                 :  *
                                 22                 :  * IDENTIFICATION
                                 23                 :  *    src/backend/lib/rbtree.c
                                 24                 :  *
                                 25                 :  *-------------------------------------------------------------------------
                                 26                 :  */
                                 27                 : #include "postgres.h"
                                 28                 : 
                                 29                 : #include "lib/rbtree.h"
                                 30                 : 
                                 31                 : 
                                 32                 : /*
                                 33                 :  * Colors of nodes (values of RBTNode.color)
                                 34                 :  */
                                 35                 : #define RBTBLACK    (0)
                                 36                 : #define RBTRED      (1)
                                 37                 : 
                                 38                 : /*
                                 39                 :  * RBTree control structure
                                 40                 :  */
                                 41                 : struct RBTree
                                 42                 : {
                                 43                 :     RBTNode    *root;           /* root node, or RBTNIL if tree is empty */
                                 44                 : 
                                 45                 :     /* Remaining fields are constant after rbt_create */
                                 46                 : 
                                 47                 :     Size        node_size;      /* actual size of tree nodes */
                                 48                 :     /* The caller-supplied manipulation functions */
                                 49                 :     rbt_comparator comparator;
                                 50                 :     rbt_combiner combiner;
                                 51                 :     rbt_allocfunc allocfunc;
                                 52                 :     rbt_freefunc freefunc;
                                 53                 :     /* Passthrough arg passed to all manipulation functions */
                                 54                 :     void       *arg;
                                 55                 : };
                                 56                 : 
                                 57                 : /*
                                 58                 :  * all leafs are sentinels, use customized NIL name to prevent
                                 59                 :  * collision with system-wide constant NIL which is actually NULL
                                 60                 :  */
                                 61                 : #define RBTNIL (&sentinel)
                                 62                 : 
                                 63                 : static RBTNode sentinel =
                                 64                 : {
                                 65                 :     .color = RBTBLACK,.left = RBTNIL,.right = RBTNIL,.parent = NULL
                                 66                 : };
                                 67                 : 
                                 68                 : 
                                 69                 : /*
                                 70                 :  * rbt_create: create an empty RBTree
                                 71                 :  *
                                 72                 :  * Arguments are:
                                 73                 :  *  node_size: actual size of tree nodes (> sizeof(RBTNode))
                                 74                 :  *  The manipulation functions:
                                 75                 :  *  comparator: compare two RBTNodes for less/equal/greater
                                 76                 :  *  combiner: merge an existing tree entry with a new one
                                 77                 :  *  allocfunc: allocate a new RBTNode
                                 78                 :  *  freefunc: free an old RBTNode
                                 79                 :  *  arg: passthrough pointer that will be passed to the manipulation functions
                                 80                 :  *
                                 81                 :  * Note that the combiner's righthand argument will be a "proposed" tree node,
                                 82                 :  * ie the input to rbt_insert, in which the RBTNode fields themselves aren't
                                 83                 :  * valid.  Similarly, either input to the comparator may be a "proposed" node.
                                 84                 :  * This shouldn't matter since the functions aren't supposed to look at the
                                 85                 :  * RBTNode fields, only the extra fields of the struct the RBTNode is embedded
                                 86                 :  * in.
                                 87                 :  *
                                 88                 :  * The freefunc should just be pfree or equivalent; it should NOT attempt
                                 89                 :  * to free any subsidiary data, because the node passed to it may not contain
                                 90                 :  * valid data!  freefunc can be NULL if caller doesn't require retail
                                 91                 :  * space reclamation.
                                 92                 :  *
                                 93                 :  * The RBTree node is palloc'd in the caller's memory context.  Note that
                                 94                 :  * all contents of the tree are actually allocated by the caller, not here.
                                 95                 :  *
                                 96                 :  * Since tree contents are managed by the caller, there is currently not
                                 97                 :  * an explicit "destroy" operation; typically a tree would be freed by
                                 98                 :  * resetting or deleting the memory context it's stored in.  You can pfree
                                 99                 :  * the RBTree node if you feel the urge.
                                100                 :  */
                                101                 : RBTree *
 1615 tgl                       102 CBC         173 : rbt_create(Size node_size,
                                103                 :            rbt_comparator comparator,
                                104                 :            rbt_combiner combiner,
                                105                 :            rbt_allocfunc allocfunc,
                                106                 :            rbt_freefunc freefunc,
                                107                 :            void *arg)
                                108                 : {
 4634                           109             173 :     RBTree     *tree = (RBTree *) palloc(sizeof(RBTree));
                                110                 : 
 1615                           111             173 :     Assert(node_size > sizeof(RBTNode));
                                112                 : 
                                113             173 :     tree->root = RBTNIL;
 4634                           114             173 :     tree->node_size = node_size;
 4805 teodor                    115             173 :     tree->comparator = comparator;
 4634 tgl                       116             173 :     tree->combiner = combiner;
                                117             173 :     tree->allocfunc = allocfunc;
 4805 teodor                    118             173 :     tree->freefunc = freefunc;
                                119                 : 
                                120             173 :     tree->arg = arg;
                                121                 : 
                                122             173 :     return tree;
                                123                 : }
                                124                 : 
                                125                 : /* Copy the additional data fields from one RBTNode to another */
                                126                 : static inline void
 1615 tgl                       127          320118 : rbt_copy_data(RBTree *rbt, RBTNode *dest, const RBTNode *src)
                                128                 : {
                                129          320118 :     memcpy(dest + 1, src + 1, rbt->node_size - sizeof(RBTNode));
 4634                           130          320118 : }
                                131                 : 
                                132                 : /**********************************************************************
                                133                 :  *                        Search                                      *
                                134                 :  **********************************************************************/
                                135                 : 
                                136                 : /*
                                137                 :  * rbt_find: search for a value in an RBTree
                                138                 :  *
                                139                 :  * data represents the value to try to find.  Its RBTNode fields need not
                                140                 :  * be valid, it's the extra data in the larger struct that is of interest.
                                141                 :  *
                                142                 :  * Returns the matching tree entry, or NULL if no match is found.
                                143                 :  */
                                144                 : RBTNode *
 1615                           145           40001 : rbt_find(RBTree *rbt, const RBTNode *data)
                                146                 : {
                                147           40001 :     RBTNode    *node = rbt->root;
                                148                 : 
                                149          489818 :     while (node != RBTNIL)
                                150                 :     {
                                151          478817 :         int         cmp = rbt->comparator(data, node, rbt->arg);
                                152                 : 
 4805 teodor                    153          478817 :         if (cmp == 0)
 4634 tgl                       154           29000 :             return node;
 4805 teodor                    155          449817 :         else if (cmp < 0)
                                156          254351 :             node = node->left;
                                157                 :         else
                                158          195466 :             node = node->right;
                                159                 :     }
                                160                 : 
                                161           11001 :     return NULL;
                                162                 : }
                                163                 : 
                                164                 : /*
                                165                 :  * rbt_find_great: search for a greater value in an RBTree
                                166                 :  *
                                167                 :  * If equal_match is true, this will be a great or equal search.
                                168                 :  *
                                169                 :  * Returns the matching tree entry, or NULL if no match is found.
                                170                 :  */
                                171                 : RBTNode *
  275 akorotkov                 172 GNC        3538 : rbt_find_great(RBTree *rbt, const RBTNode *data, bool equal_match)
                                173                 : {
                                174            3538 :     RBTNode    *node = rbt->root;
                                175            3538 :     RBTNode    *greater = NULL;
                                176                 : 
                                177           48495 :     while (node != RBTNIL)
                                178                 :     {
                                179           44958 :         int         cmp = rbt->comparator(data, node, rbt->arg);
                                180                 : 
                                181           44958 :         if (equal_match && cmp == 0)
                                182               1 :             return node;
                                183           44957 :         else if (cmp < 0)
                                184                 :         {
                                185           19524 :             greater = node;
                                186           19524 :             node = node->left;
                                187                 :         }
                                188                 :         else
                                189           25433 :             node = node->right;
                                190                 :     }
                                191                 : 
                                192            3537 :     return greater;
                                193                 : }
                                194                 : 
                                195                 : /*
                                196                 :  * rbt_find_less: search for a lesser value in an RBTree
                                197                 :  *
                                198                 :  * If equal_match is true, this will be a less or equal search.
                                199                 :  *
                                200                 :  * Returns the matching tree entry, or NULL if no match is found.
                                201                 :  */
                                202                 : RBTNode *
                                203            6467 : rbt_find_less(RBTree *rbt, const RBTNode *data, bool equal_match)
                                204                 : {
                                205            6467 :     RBTNode    *node = rbt->root;
                                206            6467 :     RBTNode    *lesser = NULL;
                                207                 : 
                                208           90941 :     while (node != RBTNIL)
                                209                 :     {
                                210           84475 :         int         cmp = rbt->comparator(data, node, rbt->arg);
                                211                 : 
                                212           84475 :         if (equal_match && cmp == 0)
                                213               1 :             return node;
                                214           84474 :         else if (cmp > 0)
                                215                 :         {
                                216           40566 :             lesser = node;
                                217           40566 :             node = node->right;
                                218                 :         }
                                219                 :         else
                                220           43908 :             node = node->left;
                                221                 :     }
                                222                 : 
                                223            6466 :     return lesser;
                                224                 : }
                                225                 : 
                                226                 : /*
                                227                 :  * rbt_leftmost: fetch the leftmost (smallest-valued) tree node.
                                228                 :  * Returns NULL if tree is empty.
                                229                 :  *
                                230                 :  * Note: in the original implementation this included an unlink step, but
                                231                 :  * that's a bit awkward.  Just call rbt_delete on the result if that's what
                                232                 :  * you want.
                                233                 :  */
 1615 tgl                       234 ECB             : RBTNode *
 1615 tgl                       235 GIC           3 : rbt_leftmost(RBTree *rbt)
 4634 tgl                       236 ECB             : {
 1615 tgl                       237 CBC           3 :     RBTNode    *node = rbt->root;
 1615 tgl                       238 GIC           3 :     RBTNode    *leftmost = rbt->root;
 4634 tgl                       239 ECB             : 
 1615 tgl                       240 GIC          17 :     while (node != RBTNIL)
 4634 tgl                       241 ECB             :     {
 4634 tgl                       242 GIC          14 :         leftmost = node;
 4634 tgl                       243 CBC          14 :         node = node->left;
 4634 tgl                       244 ECB             :     }
                                245                 : 
 1615 tgl                       246 GIC           3 :     if (leftmost != RBTNIL)
 4634 tgl                       247 CBC           1 :         return leftmost;
 4634 tgl                       248 ECB             : 
 4634 tgl                       249 GIC           2 :     return NULL;
                                250                 : }
 4634 tgl                       251 ECB             : 
                                252                 : /**********************************************************************
                                253                 :  *                            Insertion                               *
 4805 teodor                    254                 :  **********************************************************************/
                                255                 : 
                                256                 : /*
                                257                 :  * Rotate node x to left.
                                258                 :  *
                                259                 :  * x's right child takes its place in the tree, and x becomes the left
                                260                 :  * child of that node.
                                261                 :  */
                                262                 : static void
 1615 tgl                       263 GIC      268631 : rbt_rotate_left(RBTree *rbt, RBTNode *x)
                                264                 : {
 1615 tgl                       265 CBC      268631 :     RBTNode    *y = x->right;
                                266                 : 
 4805 teodor                    267 ECB             :     /* establish x->right link */
 4805 teodor                    268 CBC      268631 :     x->right = y->left;
 1615 tgl                       269 GIC      268631 :     if (y->left != RBTNIL)
 4805 teodor                    270 CBC      129812 :         y->left->parent = x;
                                271                 : 
 4805 teodor                    272 ECB             :     /* establish y->parent link */
 1615 tgl                       273 GIC      268631 :     if (y != RBTNIL)
 4805 teodor                    274 CBC      268631 :         y->parent = x->parent;
                                275          268631 :     if (x->parent)
 4805 teodor                    276 ECB             :     {
 4805 teodor                    277 GIC      268181 :         if (x == x->parent->left)
 4805 teodor                    278 CBC       82317 :             x->parent->left = y;
 4805 teodor                    279 ECB             :         else
 4805 teodor                    280 GIC      185864 :             x->parent->right = y;
                                281                 :     }
 4805 teodor                    282 ECB             :     else
                                283                 :     {
 1615 tgl                       284 GIC         450 :         rbt->root = y;
 4805 teodor                    285 ECB             :     }
                                286                 : 
                                287                 :     /* link x and y */
 4805 teodor                    288 GIC      268631 :     y->left = x;
 1615 tgl                       289          268631 :     if (x != RBTNIL)
 4805 teodor                    290          268631 :         x->parent = y;
                                291          268631 : }
                                292                 : 
                                293                 : /*
                                294                 :  * Rotate node x to right.
                                295                 :  *
                                296                 :  * x's left right child takes its place in the tree, and x becomes the right
 4805 teodor                    297 ECB             :  * child of that node.
                                298                 :  */
                                299                 : static void
 1615 tgl                       300 CBC       70783 : rbt_rotate_right(RBTree *rbt, RBTNode *x)
                                301                 : {
                                302           70783 :     RBTNode    *y = x->left;
                                303                 : 
 4805 teodor                    304 ECB             :     /* establish x->left link */
 4805 teodor                    305 CBC       70783 :     x->left = y->right;
 1615 tgl                       306 GIC       70783 :     if (y->right != RBTNIL)
 4805 teodor                    307           22661 :         y->right->parent = x;
 4805 teodor                    308 ECB             : 
                                309                 :     /* establish y->parent link */
 1615 tgl                       310 GIC       70783 :     if (y != RBTNIL)
 4805 teodor                    311 CBC       70783 :         y->parent = x->parent;
 4805 teodor                    312 GIC       70783 :     if (x->parent)
                                313                 :     {
                                314           70729 :         if (x == x->parent->right)
                                315           62402 :             x->parent->right = y;
                                316                 :         else
                                317            8327 :             x->parent->left = y;
                                318                 :     }
                                319                 :     else
                                320                 :     {
 1615 tgl                       321              54 :         rbt->root = y;
                                322                 :     }
                                323                 : 
                                324                 :     /* link x and y */
 4805 teodor                    325 CBC       70783 :     y->right = x;
 1615 tgl                       326 GIC       70783 :     if (x != RBTNIL)
 4805 teodor                    327 CBC       70783 :         x->parent = y;
 4805 teodor                    328 GIC       70783 : }
                                329                 : 
 4805 teodor                    330 ECB             : /*
                                331                 :  * Maintain Red-Black tree balance after inserting node x.
                                332                 :  *
                                333                 :  * The newly inserted node is always initially marked red.  That may lead to
                                334                 :  * a situation where a red node has a red child, which is prohibited.  We can
                                335                 :  * always fix the problem by a series of color changes and/or "rotations",
 3260 bruce                     336                 :  * which move the problem progressively higher up in the tree.  If one of the
 4805 teodor                    337                 :  * two red nodes is the root, we can always fix the problem by changing the
                                338                 :  * root from red to black.
                                339                 :  *
                                340                 :  * (This does not work lower down in the tree because we must also maintain
                                341                 :  * the invariant that every leaf has equal black-height.)
                                342                 :  */
                                343                 : static void
 1615 tgl                       344 GIC      317606 : rbt_insert_fixup(RBTree *rbt, RBTNode *x)
                                345                 : {
 4805 teodor                    346 ECB             :     /*
                                347                 :      * x is always a red node.  Initially, it is the newly inserted node. Each
                                348                 :      * iteration of this loop moves it higher up in the tree.
                                349                 :      */
 1615 tgl                       350 CBC      866466 :     while (x != rbt->root && x->parent->color == RBTRED)
 4805 teodor                    351 ECB             :     {
                                352                 :         /*
                                353                 :          * x and x->parent are both red.  Fix depends on whether x->parent is
                                354                 :          * a left or right child.  In either case, we define y to be the
                                355                 :          * "uncle" of x, that is, the other child of x's grandparent.
                                356                 :          *
                                357                 :          * If the uncle is red, we flip the grandparent to red and its two
                                358                 :          * children to black.  Then we loop around again to check whether the
                                359                 :          * grandparent still has a problem.
                                360                 :          *
                                361                 :          * If the uncle is black, we will perform one or two "rotations" to
 4790 bruce                     362                 :          * balance the tree.  Either x or x->parent will take the
                                363                 :          * grandparent's position in the tree and recolored black, and the
                                364                 :          * original grandparent will be recolored red and become a child of
                                365                 :          * that node. This always leaves us with a valid red-black tree, so
                                366                 :          * the loop will terminate.
 4805 teodor                    367                 :          */
 4805 teodor                    368 CBC      548860 :         if (x->parent == x->parent->parent->left)
 4805 teodor                    369 ECB             :         {
 1615 tgl                       370 GIC       80539 :             RBTNode    *y = x->parent->parent->right;
                                371                 : 
 1615 tgl                       372 CBC       80539 :             if (y->color == RBTRED)
 4805 teodor                    373 ECB             :             {
 1615 tgl                       374                 :                 /* uncle is RBTRED */
 1615 tgl                       375 GIC       19350 :                 x->parent->color = RBTBLACK;
 1615 tgl                       376 CBC       19350 :                 y->color = RBTBLACK;
                                377           19350 :                 x->parent->parent->color = RBTRED;
                                378                 : 
 4805 teodor                    379           19350 :                 x = x->parent->parent;
                                380                 :             }
                                381                 :             else
                                382                 :             {
 1615 tgl                       383 ECB             :                 /* uncle is RBTBLACK */
 4805 teodor                    384 GIC       61189 :                 if (x == x->parent->right)
                                385                 :                 {
                                386                 :                     /* make x a left child */
 4805 teodor                    387 CBC       53860 :                     x = x->parent;
 1615 tgl                       388           53860 :                     rbt_rotate_left(rbt, x);
 4805 teodor                    389 ECB             :                 }
                                390                 : 
                                391                 :                 /* recolor and rotate */
 1615 tgl                       392 GIC       61189 :                 x->parent->color = RBTBLACK;
                                393           61189 :                 x->parent->parent->color = RBTRED;
                                394                 : 
                                395           61189 :                 rbt_rotate_right(rbt, x->parent->parent);
                                396                 :             }
                                397                 :         }
                                398                 :         else
                                399                 :         {
                                400                 :             /* mirror image of above code */
                                401          468321 :             RBTNode    *y = x->parent->parent->left;
                                402                 : 
                                403          468321 :             if (y->color == RBTRED)
                                404                 :             {
                                405                 :                 /* uncle is RBTRED */
 1615 tgl                       406 CBC      259682 :                 x->parent->color = RBTBLACK;
 1615 tgl                       407 GIC      259682 :                 y->color = RBTBLACK;
                                408          259682 :                 x->parent->parent->color = RBTRED;
                                409                 : 
 4805 teodor                    410          259682 :                 x = x->parent->parent;
                                411                 :             }
 4805 teodor                    412 ECB             :             else
                                413                 :             {
                                414                 :                 /* uncle is RBTBLACK */
 4805 teodor                    415 GIC      208639 :                 if (x == x->parent->left)
                                416                 :                 {
                                417            7436 :                     x = x->parent;
 1615 tgl                       418            7436 :                     rbt_rotate_right(rbt, x);
                                419                 :                 }
                                420          208639 :                 x->parent->color = RBTBLACK;
                                421          208639 :                 x->parent->parent->color = RBTRED;
                                422                 : 
                                423          208639 :                 rbt_rotate_left(rbt, x->parent->parent);
                                424                 :             }
                                425                 :         }
                                426                 :     }
                                427                 : 
                                428                 :     /*
                                429                 :      * The root may already have been black; if not, the black-height of every
 4805 teodor                    430 ECB             :      * node in the tree increases by one.
                                431                 :      */
 1615 tgl                       432 CBC      317606 :     rbt->root->color = RBTBLACK;
 4805 teodor                    433 GIC      317606 : }
 4805 teodor                    434 ECB             : 
                                435                 : /*
                                436                 :  * rbt_insert: insert a new value into the tree.
                                437                 :  *
 1615 tgl                       438                 :  * data represents the value to insert.  Its RBTNode fields need not
 4634                           439                 :  * be valid, it's the extra data in the larger struct that is of interest.
                                440                 :  *
                                441                 :  * If the value represented by "data" is not present in the tree, then
                                442                 :  * we copy "data" into a new tree entry and return that node, setting *isNew
                                443                 :  * to true.
                                444                 :  *
                                445                 :  * If the value represented by "data" is already present, then we call the
                                446                 :  * combiner function to merge data into the existing node, and return the
                                447                 :  * existing node, setting *isNew to false.
                                448                 :  *
                                449                 :  * "data" is unmodified in either case; it's typically just a local
                                450                 :  * variable in the caller.
                                451                 :  */
                                452                 : RBTNode *
 1615 tgl                       453 GIC     1317870 : rbt_insert(RBTree *rbt, const RBTNode *data, bool *isNew)
 4805 teodor                    454 ECB             : {
 1615 tgl                       455                 :     RBTNode    *current,
                                456                 :                *parent,
 4805 teodor                    457                 :                *x;
                                458                 :     int         cmp;
                                459                 : 
                                460                 :     /* find where node belongs */
 1615 tgl                       461 GIC     1317870 :     current = rbt->root;
 4805 teodor                    462         1317870 :     parent = NULL;
 4634 tgl                       463 CBC     1317870 :     cmp = 0;                    /* just to prevent compiler warning */
                                464                 : 
 1615                           465        13759374 :     while (current != RBTNIL)
                                466                 :     {
 1615 tgl                       467 GIC    13441768 :         cmp = rbt->comparator(data, current, rbt->arg);
 4805 teodor                    468 CBC    13441768 :         if (cmp == 0)
 4805 teodor                    469 ECB             :         {
                                470                 :             /*
                                471                 :              * Found node with given key.  Apply combiner.
                                472                 :              */
 1615 tgl                       473 GIC     1000264 :             rbt->combiner(current, data, rbt->arg);
 4634                           474         1000264 :             *isNew = false;
                                475         1000264 :             return current;
                                476                 :         }
 4805 teodor                    477 CBC    12441504 :         parent = current;
 4805 teodor                    478 GIC    12441504 :         current = (cmp < 0) ? current->left : current->right;
 4805 teodor                    479 ECB             :     }
                                480                 : 
                                481                 :     /*
 4634 tgl                       482                 :      * Value is not present, so create a new node containing data.
                                483                 :      */
 4634 tgl                       484 GIC      317606 :     *isNew = true;
 4634 tgl                       485 ECB             : 
 1615 tgl                       486 GIC      317606 :     x = rbt->allocfunc(rbt->arg);
                                487                 : 
                                488          317606 :     x->color = RBTRED;
                                489                 : 
                                490          317606 :     x->left = RBTNIL;
                                491          317606 :     x->right = RBTNIL;
 4634                           492          317606 :     x->parent = parent;
 1615                           493          317606 :     rbt_copy_data(rbt, x, data);
 4805 teodor                    494 ECB             : 
                                495                 :     /* insert node in tree */
 4805 teodor                    496 GIC      317606 :     if (parent)
                                497                 :     {
                                498          317451 :         if (cmp < 0)
                                499           68528 :             parent->left = x;
                                500                 :         else
                                501          248923 :             parent->right = x;
                                502                 :     }
                                503                 :     else
                                504                 :     {
 1615 tgl                       505             155 :         rbt->root = x;
                                506                 :     }
                                507                 : 
                                508          317606 :     rbt_insert_fixup(rbt, x);
                                509                 : 
 4634                           510          317606 :     return x;
                                511                 : }
                                512                 : 
                                513                 : /**********************************************************************
                                514                 :  *                          Deletion                                  *
 4805 teodor                    515 ECB             :  **********************************************************************/
                                516                 : 
                                517                 : /*
                                518                 :  * Maintain Red-Black tree balance after deleting a black node.
                                519                 :  */
                                520                 : static void
 1615 tgl                       521 GIC       12875 : rbt_delete_fixup(RBTree *rbt, RBTNode *x)
                                522                 : {
 4805 teodor                    523 ECB             :     /*
                                524                 :      * x is always a black node.  Initially, it is the former child of the
                                525                 :      * deleted node.  Each iteration of this loop moves it higher up in the
                                526                 :      * tree.
                                527                 :      */
 1615 tgl                       528 GIC       23962 :     while (x != rbt->root && x->color == RBTBLACK)
 4805 teodor                    529 ECB             :     {
                                530                 :         /*
                                531                 :          * Left and right cases are symmetric.  Any nodes that are children of
                                532                 :          * x have a black-height one less than the remainder of the nodes in
                                533                 :          * the tree.  We rotate and recolor nodes to move the problem up the
                                534                 :          * tree: at some stage we'll either fix the problem, or reach the root
 4790 bruce                     535                 :          * (where the black-height is allowed to decrease).
 4805 teodor                    536                 :          */
 4805 teodor                    537 CBC       11087 :         if (x == x->parent->left)
                                538                 :         {
 1615 tgl                       539            9501 :             RBTNode    *w = x->parent->right;
 4805 teodor                    540 ECB             : 
 1615 tgl                       541 GIC        9501 :             if (w->color == RBTRED)
                                542                 :             {
                                543            2274 :                 w->color = RBTBLACK;
                                544            2274 :                 x->parent->color = RBTRED;
                                545                 : 
 1615 tgl                       546 CBC        2274 :                 rbt_rotate_left(rbt, x->parent);
 4805 teodor                    547 GIC        2274 :                 w = x->parent->right;
 4805 teodor                    548 ECB             :             }
                                549                 : 
 1615 tgl                       550 CBC        9501 :             if (w->left->color == RBTBLACK && w->right->color == RBTBLACK)
                                551                 :             {
                                552            5898 :                 w->color = RBTRED;
 4790 bruce                     553 ECB             : 
 4805 teodor                    554 CBC        5898 :                 x = x->parent;
 4805 teodor                    555 ECB             :             }
                                556                 :             else
                                557                 :             {
 1615 tgl                       558 CBC        3603 :                 if (w->right->color == RBTBLACK)
                                559                 :                 {
                                560            1257 :                     w->left->color = RBTBLACK;
                                561            1257 :                     w->color = RBTRED;
                                562                 : 
                                563            1257 :                     rbt_rotate_right(rbt, w);
 4805 teodor                    564 GIC        1257 :                     w = x->parent->right;
                                565                 :                 }
                                566            3603 :                 w->color = x->parent->color;
 1615 tgl                       567 CBC        3603 :                 x->parent->color = RBTBLACK;
 1615 tgl                       568 GIC        3603 :                 w->right->color = RBTBLACK;
                                569                 : 
 1615 tgl                       570 CBC        3603 :                 rbt_rotate_left(rbt, x->parent);
 1615 tgl                       571 GIC        3603 :                 x = rbt->root;   /* Arrange for loop to terminate. */
 4805 teodor                    572 ECB             :             }
                                573                 :         }
                                574                 :         else
                                575                 :         {
 1615 tgl                       576 GIC        1586 :             RBTNode    *w = x->parent->left;
                                577                 : 
                                578            1586 :             if (w->color == RBTRED)
                                579                 :             {
                                580             157 :                 w->color = RBTBLACK;
                                581             157 :                 x->parent->color = RBTRED;
                                582                 : 
 1615 tgl                       583 CBC         157 :                 rbt_rotate_right(rbt, x->parent);
 4805 teodor                    584 GIC         157 :                 w = x->parent->left;
                                585                 :             }
                                586                 : 
 1615 tgl                       587            1586 :             if (w->right->color == RBTBLACK && w->left->color == RBTBLACK)
                                588                 :             {
                                589             842 :                 w->color = RBTRED;
 4790 bruce                     590 ECB             : 
 4805 teodor                    591 GIC         842 :                 x = x->parent;
                                592                 :             }
                                593                 :             else
                                594                 :             {
 1615 tgl                       595             744 :                 if (w->left->color == RBTBLACK)
                                596                 :                 {
                                597             255 :                     w->right->color = RBTBLACK;
                                598             255 :                     w->color = RBTRED;
 4790 bruce                     599 ECB             : 
 1615 tgl                       600 GIC         255 :                     rbt_rotate_left(rbt, w);
 4805 teodor                    601 CBC         255 :                     w = x->parent->left;
                                602                 :                 }
                                603             744 :                 w->color = x->parent->color;
 1615 tgl                       604 GIC         744 :                 x->parent->color = RBTBLACK;
 1615 tgl                       605 CBC         744 :                 w->left->color = RBTBLACK;
 4790 bruce                     606 ECB             : 
 1615 tgl                       607 GIC         744 :                 rbt_rotate_right(rbt, x->parent);
 1615 tgl                       608 CBC         744 :                 x = rbt->root;   /* Arrange for loop to terminate. */
 4805 teodor                    609 ECB             :             }
                                610                 :         }
                                611                 :     }
 1615 tgl                       612 CBC       12875 :     x->color = RBTBLACK;
 4805 teodor                    613 GIC       12875 : }
 4805 teodor                    614 ECB             : 
                                615                 : /*
                                616                 :  * Delete node z from tree.
                                617                 :  */
                                618                 : static void
 1615 tgl                       619 GIC       14989 : rbt_delete_node(RBTree *rbt, RBTNode *z)
 4805 teodor                    620 ECB             : {
                                621                 :     RBTNode    *x,
                                622                 :                *y;
                                623                 : 
                                624                 :     /* This is just paranoia: we should only get called on a valid node */
 1615 tgl                       625 CBC       14989 :     if (!z || z == RBTNIL)
 4805 teodor                    626 LBC           0 :         return;
                                627                 : 
 4805 teodor                    628 ECB             :     /*
                                629                 :      * y is the node that will actually be removed from the tree.  This will
                                630                 :      * be z if z has fewer than two children, or the tree successor of z
                                631                 :      * otherwise.
                                632                 :      */
 1615 tgl                       633 CBC       14989 :     if (z->left == RBTNIL || z->right == RBTNIL)
                                634                 :     {
                                635                 :         /* y has a RBTNIL node as a child */
 4805 teodor                    636 GIC       12477 :         y = z;
                                637                 :     }
 4805 teodor                    638 ECB             :     else
                                639                 :     {
                                640                 :         /* find tree successor */
 4805 teodor                    641 GIC        2512 :         y = z->right;
 1615 tgl                       642 CBC        5302 :         while (y->left != RBTNIL)
 4805 teodor                    643            2790 :             y = y->left;
                                644                 :     }
 4805 teodor                    645 ECB             : 
                                646                 :     /* x is y's only child */
 1615 tgl                       647 GIC       14989 :     if (y->left != RBTNIL)
 4805 teodor                    648             539 :         x = y->left;
 4805 teodor                    649 ECB             :     else
 4805 teodor                    650 GIC       14450 :         x = y->right;
 4805 teodor                    651 ECB             : 
                                652                 :     /* Remove y from the tree. */
 4805 teodor                    653 CBC       14989 :     x->parent = y->parent;
 4805 teodor                    654 GIC       14989 :     if (y->parent)
                                655                 :     {
                                656           14987 :         if (y == y->parent->left)
 4805 teodor                    657 CBC       12137 :             y->parent->left = x;
                                658                 :         else
                                659            2850 :             y->parent->right = x;
 4805 teodor                    660 ECB             :     }
                                661                 :     else
                                662                 :     {
 1615 tgl                       663 CBC           2 :         rbt->root = x;
                                664                 :     }
 4805 teodor                    665 ECB             : 
                                666                 :     /*
 4634 tgl                       667                 :      * If we removed the tree successor of z rather than z itself, then move
                                668                 :      * the data for the removed node to the one we were supposed to remove.
 4805 teodor                    669                 :      */
 4805 teodor                    670 CBC       14989 :     if (y != z)
 1615 tgl                       671 GIC        2512 :         rbt_copy_data(rbt, z, y);
                                672                 : 
                                673                 :     /*
 4805 teodor                    674 ECB             :      * Removing a black node might make some paths from root to leaf contain
                                675                 :      * fewer black nodes than others, or it might make two red nodes adjacent.
                                676                 :      */
 1615 tgl                       677 GIC       14989 :     if (y->color == RBTBLACK)
                                678           12875 :         rbt_delete_fixup(rbt, x);
                                679                 : 
                                680                 :     /* Now we can recycle the y node */
 1615 tgl                       681 CBC       14989 :     if (rbt->freefunc)
 1615 tgl                       682 GIC       14989 :         rbt->freefunc(y, rbt->arg);
                                683                 : }
                                684                 : 
                                685                 : /*
                                686                 :  * rbt_delete: remove the given tree entry
 4634 tgl                       687 ECB             :  *
 1615 tgl                       688 EUB             :  * "node" must have previously been found via rbt_find or rbt_leftmost.
                                689                 :  * It is caller's responsibility to free any subsidiary data attached
                                690                 :  * to the node before calling rbt_delete.  (Do *not* try to push that
                                691                 :  * responsibility off to the freefunc, as some other physical node
                                692                 :  * may be the one actually freed!)
                                693                 :  */
                                694                 : void
 1615 tgl                       695 CBC       14989 : rbt_delete(RBTree *rbt, RBTNode *node)
                                696                 : {
 1615 tgl                       697 GIC       14989 :     rbt_delete_node(rbt, node);
 4805 teodor                    698 CBC       14989 : }
                                699                 : 
                                700                 : /**********************************************************************
                                701                 :  *                        Traverse                                    *
                                702                 :  **********************************************************************/
 4805 teodor                    703 ECB             : 
 1615 tgl                       704                 : static RBTNode *
 1615 tgl                       705 CBC      267756 : rbt_left_right_iterator(RBTreeIterator *iter)
                                706                 : {
 2410 heikki.linnakangas        707 GIC      267756 :     if (iter->last_visited == NULL)
                                708                 :     {
 1615 tgl                       709 CBC         150 :         iter->last_visited = iter->rbt->root;
                                710             878 :         while (iter->last_visited->left != RBTNIL)
 2410 heikki.linnakangas        711 GIC         728 :             iter->last_visited = iter->last_visited->left;
 4634 tgl                       712 ECB             : 
 2410 heikki.linnakangas        713 GIC         150 :         return iter->last_visited;
                                714                 :     }
 4634 tgl                       715 ECB             : 
 1615 tgl                       716 CBC      267606 :     if (iter->last_visited->right != RBTNIL)
                                717                 :     {
 2410 heikki.linnakangas        718          133805 :         iter->last_visited = iter->last_visited->right;
 1615 tgl                       719          266728 :         while (iter->last_visited->left != RBTNIL)
 2410 heikki.linnakangas        720 GIC      132923 :             iter->last_visited = iter->last_visited->left;
 4634 tgl                       721 ECB             : 
 2410 heikki.linnakangas        722 GIC      133805 :         return iter->last_visited;
                                723                 :     }
                                724                 : 
 2410 heikki.linnakangas        725 ECB             :     for (;;)
 4805 teodor                    726 GIC      133805 :     {
 1615 tgl                       727          267606 :         RBTNode    *came_from = iter->last_visited;
                                728                 : 
 2410 heikki.linnakangas        729          267606 :         iter->last_visited = iter->last_visited->parent;
                                730          267606 :         if (iter->last_visited == NULL)
                                731                 :         {
 2410 heikki.linnakangas        732 CBC         150 :             iter->is_over = true;
 4805 teodor                    733             150 :             break;
                                734                 :         }
                                735                 : 
 2410 heikki.linnakangas        736 GIC      267456 :         if (iter->last_visited->left == came_from)
                                737          133651 :             break;              /* came from left sub-tree, return current
                                738                 :                                  * node */
 2410 heikki.linnakangas        739 ECB             : 
                                740                 :         /* else - came from right sub-tree, continue to move up */
                                741                 :     }
                                742                 : 
 2410 heikki.linnakangas        743 CBC      133801 :     return iter->last_visited;
 4805 teodor                    744 ECB             : }
                                745                 : 
                                746                 : static RBTNode *
 1615 tgl                       747 GIC       10001 : rbt_right_left_iterator(RBTreeIterator *iter)
                                748                 : {
 2410 heikki.linnakangas        749           10001 :     if (iter->last_visited == NULL)
                                750                 :     {
 1615 tgl                       751               1 :         iter->last_visited = iter->rbt->root;
                                752              14 :         while (iter->last_visited->right != RBTNIL)
 2410 heikki.linnakangas        753              13 :             iter->last_visited = iter->last_visited->right;
                                754                 : 
                                755               1 :         return iter->last_visited;
                                756                 :     }
 4805 teodor                    757 ECB             : 
 1615 tgl                       758 GIC       10000 :     if (iter->last_visited->left != RBTNIL)
 4805 teodor                    759 ECB             :     {
 2410 heikki.linnakangas        760 CBC        5000 :         iter->last_visited = iter->last_visited->left;
 1615 tgl                       761 GIC        9986 :         while (iter->last_visited->right != RBTNIL)
 2410 heikki.linnakangas        762            4986 :             iter->last_visited = iter->last_visited->right;
                                763                 : 
                                764            5000 :         return iter->last_visited;
                                765                 :     }
                                766                 : 
 2410 heikki.linnakangas        767 ECB             :     for (;;)
 2410 heikki.linnakangas        768 GIC        5000 :     {
 1615 tgl                       769 CBC       10000 :         RBTNode    *came_from = iter->last_visited;
                                770                 : 
 2410 heikki.linnakangas        771           10000 :         iter->last_visited = iter->last_visited->parent;
                                772           10000 :         if (iter->last_visited == NULL)
 2410 heikki.linnakangas        773 ECB             :         {
 2410 heikki.linnakangas        774 GIC           1 :             iter->is_over = true;
 4805 teodor                    775 CBC           1 :             break;
                                776                 :         }
                                777                 : 
 2410 heikki.linnakangas        778            9999 :         if (iter->last_visited->right == came_from)
 2410 heikki.linnakangas        779 GIC        4999 :             break;              /* came from right sub-tree, return current
 2410 heikki.linnakangas        780 ECB             :                                  * node */
                                781                 : 
                                782                 :         /* else - came from left sub-tree, continue to move up */
                                783                 :     }
 4805 teodor                    784                 : 
 2410 heikki.linnakangas        785 GIC        5000 :     return iter->last_visited;
                                786                 : }
                                787                 : 
 4634 tgl                       788 ECB             : /*
 1615                           789                 :  * rbt_begin_iterate: prepare to traverse the tree in any of several orders
                                790                 :  *
                                791                 :  * After calling rbt_begin_iterate, call rbt_iterate repeatedly until it
 4634                           792                 :  * returns NULL or the traversal stops being of interest.
                                793                 :  *
                                794                 :  * If the tree is changed during traversal, results of further calls to
 1615                           795                 :  * rbt_iterate are unspecified.  Multiple concurrent iterators on the same
                                796                 :  * tree are allowed.
                                797                 :  *
 2410 heikki.linnakangas        798                 :  * The iterator state is stored in the 'iter' struct.  The caller should
 2037 tgl                       799                 :  * treat it as an opaque struct.
                                800                 :  */
                                801                 : void
 1615 tgl                       802 GIC         171 : rbt_begin_iterate(RBTree *rbt, RBTOrderControl ctrl, RBTreeIterator *iter)
                                803                 : {
                                804                 :     /* Common initialization for all traversal orders */
 1615 tgl                       805 CBC         171 :     iter->rbt = rbt;
 2410 heikki.linnakangas        806 GIC         171 :     iter->last_visited = NULL;
 1615 tgl                       807             171 :     iter->is_over = (rbt->root == RBTNIL);
                                808                 : 
 4805 teodor                    809 CBC         171 :     switch (ctrl)
                                810                 :     {
 4790 bruce                     811             169 :         case LeftRightWalk:     /* visit left, then self, then right */
 1615 tgl                       812 GIC         169 :             iter->iterate = rbt_left_right_iterator;
 4805 teodor                    813 CBC         169 :             break;
 4790 bruce                     814               2 :         case RightLeftWalk:     /* visit right, then self, then left */
 1615 tgl                       815               2 :             iter->iterate = rbt_right_left_iterator;
 4805 teodor                    816 GIC           2 :             break;
 4805 teodor                    817 LBC           0 :         default:
 4634 tgl                       818 UIC           0 :             elog(ERROR, "unrecognized rbtree iteration order: %d", ctrl);
                                819                 :     }
 4805 teodor                    820 CBC         171 : }
                                821                 : 
 4634 tgl                       822 ECB             : /*
 1615                           823                 :  * rbt_iterate: return the next node in traversal order, or NULL if no more
 4634                           824                 :  */
                                825                 : RBTNode *
 1615 tgl                       826 CBC      277777 : rbt_iterate(RBTreeIterator *iter)
                                827                 : {
 2410 heikki.linnakangas        828 GIC      277777 :     if (iter->is_over)
 4805 teodor                    829              20 :         return NULL;
 4805 teodor                    830 ECB             : 
 2410 heikki.linnakangas        831 CBC      277757 :     return iter->iterate(iter);
                                832                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a