Move routines to manipulate WAL into PostgreSQL::Test::Cluster
[pgsql.git] / src / backend / lib / rbtree.c
blob3b5e5faa9bf5f1bfe6562fc01e6ab296829f91e9
1 /*-------------------------------------------------------------------------
3 * rbtree.c
4 * implementation for PostgreSQL generic Red-Black binary tree package
5 * Adopted from http://algolist.manual.ru/ds/rbtree.php
7 * This code comes from Thomas Niemann's "Sorting and Searching Algorithms:
8 * a Cookbook".
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."
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.
20 * Copyright (c) 2009-2025, PostgreSQL Global Development Group
22 * IDENTIFICATION
23 * src/backend/lib/rbtree.c
25 *-------------------------------------------------------------------------
27 #include "postgres.h"
29 #include "lib/rbtree.h"
33 * Colors of nodes (values of RBTNode.color)
35 #define RBTBLACK (0)
36 #define RBTRED (1)
39 * RBTree control structure
41 struct RBTree
43 RBTNode *root; /* root node, or RBTNIL if tree is empty */
45 /* Remaining fields are constant after rbt_create */
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;
58 * all leafs are sentinels, use customized NIL name to prevent
59 * collision with system-wide constant NIL which is actually NULL
61 #define RBTNIL (&sentinel)
63 static RBTNode sentinel =
65 .color = RBTBLACK,.left = RBTNIL,.right = RBTNIL,.parent = NULL
70 * rbt_create: create an empty RBTree
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
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.
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.
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.
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.
101 RBTree *
102 rbt_create(Size node_size,
103 rbt_comparator comparator,
104 rbt_combiner combiner,
105 rbt_allocfunc allocfunc,
106 rbt_freefunc freefunc,
107 void *arg)
109 RBTree *tree = (RBTree *) palloc(sizeof(RBTree));
111 Assert(node_size > sizeof(RBTNode));
113 tree->root = RBTNIL;
114 tree->node_size = node_size;
115 tree->comparator = comparator;
116 tree->combiner = combiner;
117 tree->allocfunc = allocfunc;
118 tree->freefunc = freefunc;
120 tree->arg = arg;
122 return tree;
125 /* Copy the additional data fields from one RBTNode to another */
126 static inline void
127 rbt_copy_data(RBTree *rbt, RBTNode *dest, const RBTNode *src)
129 memcpy(dest + 1, src + 1, rbt->node_size - sizeof(RBTNode));
132 /**********************************************************************
133 * Search *
134 **********************************************************************/
137 * rbt_find: search for a value in an RBTree
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.
142 * Returns the matching tree entry, or NULL if no match is found.
144 RBTNode *
145 rbt_find(RBTree *rbt, const RBTNode *data)
147 RBTNode *node = rbt->root;
149 while (node != RBTNIL)
151 int cmp = rbt->comparator(data, node, rbt->arg);
153 if (cmp == 0)
154 return node;
155 else if (cmp < 0)
156 node = node->left;
157 else
158 node = node->right;
161 return NULL;
165 * rbt_find_great: search for a greater value in an RBTree
167 * If equal_match is true, this will be a great or equal search.
169 * Returns the matching tree entry, or NULL if no match is found.
171 RBTNode *
172 rbt_find_great(RBTree *rbt, const RBTNode *data, bool equal_match)
174 RBTNode *node = rbt->root;
175 RBTNode *greater = NULL;
177 while (node != RBTNIL)
179 int cmp = rbt->comparator(data, node, rbt->arg);
181 if (equal_match && cmp == 0)
182 return node;
183 else if (cmp < 0)
185 greater = node;
186 node = node->left;
188 else
189 node = node->right;
192 return greater;
196 * rbt_find_less: search for a lesser value in an RBTree
198 * If equal_match is true, this will be a less or equal search.
200 * Returns the matching tree entry, or NULL if no match is found.
202 RBTNode *
203 rbt_find_less(RBTree *rbt, const RBTNode *data, bool equal_match)
205 RBTNode *node = rbt->root;
206 RBTNode *lesser = NULL;
208 while (node != RBTNIL)
210 int cmp = rbt->comparator(data, node, rbt->arg);
212 if (equal_match && cmp == 0)
213 return node;
214 else if (cmp > 0)
216 lesser = node;
217 node = node->right;
219 else
220 node = node->left;
223 return lesser;
227 * rbt_leftmost: fetch the leftmost (smallest-valued) tree node.
228 * Returns NULL if tree is empty.
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.
234 RBTNode *
235 rbt_leftmost(RBTree *rbt)
237 RBTNode *node = rbt->root;
238 RBTNode *leftmost = rbt->root;
240 while (node != RBTNIL)
242 leftmost = node;
243 node = node->left;
246 if (leftmost != RBTNIL)
247 return leftmost;
249 return NULL;
252 /**********************************************************************
253 * Insertion *
254 **********************************************************************/
257 * Rotate node x to left.
259 * x's right child takes its place in the tree, and x becomes the left
260 * child of that node.
262 static void
263 rbt_rotate_left(RBTree *rbt, RBTNode *x)
265 RBTNode *y = x->right;
267 /* establish x->right link */
268 x->right = y->left;
269 if (y->left != RBTNIL)
270 y->left->parent = x;
272 /* establish y->parent link */
273 if (y != RBTNIL)
274 y->parent = x->parent;
275 if (x->parent)
277 if (x == x->parent->left)
278 x->parent->left = y;
279 else
280 x->parent->right = y;
282 else
284 rbt->root = y;
287 /* link x and y */
288 y->left = x;
289 if (x != RBTNIL)
290 x->parent = y;
294 * Rotate node x to right.
296 * x's left right child takes its place in the tree, and x becomes the right
297 * child of that node.
299 static void
300 rbt_rotate_right(RBTree *rbt, RBTNode *x)
302 RBTNode *y = x->left;
304 /* establish x->left link */
305 x->left = y->right;
306 if (y->right != RBTNIL)
307 y->right->parent = x;
309 /* establish y->parent link */
310 if (y != RBTNIL)
311 y->parent = x->parent;
312 if (x->parent)
314 if (x == x->parent->right)
315 x->parent->right = y;
316 else
317 x->parent->left = y;
319 else
321 rbt->root = y;
324 /* link x and y */
325 y->right = x;
326 if (x != RBTNIL)
327 x->parent = y;
331 * Maintain Red-Black tree balance after inserting node x.
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",
336 * which move the problem progressively higher up in the tree. If one of the
337 * two red nodes is the root, we can always fix the problem by changing the
338 * root from red to black.
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.)
343 static void
344 rbt_insert_fixup(RBTree *rbt, RBTNode *x)
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.
350 while (x != rbt->root && x->parent->color == RBTRED)
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.
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.
361 * If the uncle is black, we will perform one or two "rotations" to
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.
368 if (x->parent == x->parent->parent->left)
370 RBTNode *y = x->parent->parent->right;
372 if (y->color == RBTRED)
374 /* uncle is RBTRED */
375 x->parent->color = RBTBLACK;
376 y->color = RBTBLACK;
377 x->parent->parent->color = RBTRED;
379 x = x->parent->parent;
381 else
383 /* uncle is RBTBLACK */
384 if (x == x->parent->right)
386 /* make x a left child */
387 x = x->parent;
388 rbt_rotate_left(rbt, x);
391 /* recolor and rotate */
392 x->parent->color = RBTBLACK;
393 x->parent->parent->color = RBTRED;
395 rbt_rotate_right(rbt, x->parent->parent);
398 else
400 /* mirror image of above code */
401 RBTNode *y = x->parent->parent->left;
403 if (y->color == RBTRED)
405 /* uncle is RBTRED */
406 x->parent->color = RBTBLACK;
407 y->color = RBTBLACK;
408 x->parent->parent->color = RBTRED;
410 x = x->parent->parent;
412 else
414 /* uncle is RBTBLACK */
415 if (x == x->parent->left)
417 x = x->parent;
418 rbt_rotate_right(rbt, x);
420 x->parent->color = RBTBLACK;
421 x->parent->parent->color = RBTRED;
423 rbt_rotate_left(rbt, x->parent->parent);
429 * The root may already have been black; if not, the black-height of every
430 * node in the tree increases by one.
432 rbt->root->color = RBTBLACK;
436 * rbt_insert: insert a new value into the tree.
438 * data represents the value to insert. Its RBTNode fields need not
439 * be valid, it's the extra data in the larger struct that is of interest.
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.
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.
449 * "data" is unmodified in either case; it's typically just a local
450 * variable in the caller.
452 RBTNode *
453 rbt_insert(RBTree *rbt, const RBTNode *data, bool *isNew)
455 RBTNode *current,
456 *parent,
458 int cmp;
460 /* find where node belongs */
461 current = rbt->root;
462 parent = NULL;
463 cmp = 0; /* just to prevent compiler warning */
465 while (current != RBTNIL)
467 cmp = rbt->comparator(data, current, rbt->arg);
468 if (cmp == 0)
471 * Found node with given key. Apply combiner.
473 rbt->combiner(current, data, rbt->arg);
474 *isNew = false;
475 return current;
477 parent = current;
478 current = (cmp < 0) ? current->left : current->right;
482 * Value is not present, so create a new node containing data.
484 *isNew = true;
486 x = rbt->allocfunc(rbt->arg);
488 x->color = RBTRED;
490 x->left = RBTNIL;
491 x->right = RBTNIL;
492 x->parent = parent;
493 rbt_copy_data(rbt, x, data);
495 /* insert node in tree */
496 if (parent)
498 if (cmp < 0)
499 parent->left = x;
500 else
501 parent->right = x;
503 else
505 rbt->root = x;
508 rbt_insert_fixup(rbt, x);
510 return x;
513 /**********************************************************************
514 * Deletion *
515 **********************************************************************/
518 * Maintain Red-Black tree balance after deleting a black node.
520 static void
521 rbt_delete_fixup(RBTree *rbt, RBTNode *x)
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.
528 while (x != rbt->root && x->color == RBTBLACK)
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
535 * (where the black-height is allowed to decrease).
537 if (x == x->parent->left)
539 RBTNode *w = x->parent->right;
541 if (w->color == RBTRED)
543 w->color = RBTBLACK;
544 x->parent->color = RBTRED;
546 rbt_rotate_left(rbt, x->parent);
547 w = x->parent->right;
550 if (w->left->color == RBTBLACK && w->right->color == RBTBLACK)
552 w->color = RBTRED;
554 x = x->parent;
556 else
558 if (w->right->color == RBTBLACK)
560 w->left->color = RBTBLACK;
561 w->color = RBTRED;
563 rbt_rotate_right(rbt, w);
564 w = x->parent->right;
566 w->color = x->parent->color;
567 x->parent->color = RBTBLACK;
568 w->right->color = RBTBLACK;
570 rbt_rotate_left(rbt, x->parent);
571 x = rbt->root; /* Arrange for loop to terminate. */
574 else
576 RBTNode *w = x->parent->left;
578 if (w->color == RBTRED)
580 w->color = RBTBLACK;
581 x->parent->color = RBTRED;
583 rbt_rotate_right(rbt, x->parent);
584 w = x->parent->left;
587 if (w->right->color == RBTBLACK && w->left->color == RBTBLACK)
589 w->color = RBTRED;
591 x = x->parent;
593 else
595 if (w->left->color == RBTBLACK)
597 w->right->color = RBTBLACK;
598 w->color = RBTRED;
600 rbt_rotate_left(rbt, w);
601 w = x->parent->left;
603 w->color = x->parent->color;
604 x->parent->color = RBTBLACK;
605 w->left->color = RBTBLACK;
607 rbt_rotate_right(rbt, x->parent);
608 x = rbt->root; /* Arrange for loop to terminate. */
612 x->color = RBTBLACK;
616 * Delete node z from tree.
618 static void
619 rbt_delete_node(RBTree *rbt, RBTNode *z)
621 RBTNode *x,
624 /* This is just paranoia: we should only get called on a valid node */
625 if (!z || z == RBTNIL)
626 return;
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.
633 if (z->left == RBTNIL || z->right == RBTNIL)
635 /* y has a RBTNIL node as a child */
636 y = z;
638 else
640 /* find tree successor */
641 y = z->right;
642 while (y->left != RBTNIL)
643 y = y->left;
646 /* x is y's only child */
647 if (y->left != RBTNIL)
648 x = y->left;
649 else
650 x = y->right;
652 /* Remove y from the tree. */
653 x->parent = y->parent;
654 if (y->parent)
656 if (y == y->parent->left)
657 y->parent->left = x;
658 else
659 y->parent->right = x;
661 else
663 rbt->root = x;
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.
670 if (y != z)
671 rbt_copy_data(rbt, z, y);
674 * 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.
677 if (y->color == RBTBLACK)
678 rbt_delete_fixup(rbt, x);
680 /* Now we can recycle the y node */
681 if (rbt->freefunc)
682 rbt->freefunc(y, rbt->arg);
686 * rbt_delete: remove the given tree entry
688 * "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!)
694 void
695 rbt_delete(RBTree *rbt, RBTNode *node)
697 rbt_delete_node(rbt, node);
700 /**********************************************************************
701 * Traverse *
702 **********************************************************************/
704 static RBTNode *
705 rbt_left_right_iterator(RBTreeIterator *iter)
707 if (iter->last_visited == NULL)
709 iter->last_visited = iter->rbt->root;
710 while (iter->last_visited->left != RBTNIL)
711 iter->last_visited = iter->last_visited->left;
713 return iter->last_visited;
716 if (iter->last_visited->right != RBTNIL)
718 iter->last_visited = iter->last_visited->right;
719 while (iter->last_visited->left != RBTNIL)
720 iter->last_visited = iter->last_visited->left;
722 return iter->last_visited;
725 for (;;)
727 RBTNode *came_from = iter->last_visited;
729 iter->last_visited = iter->last_visited->parent;
730 if (iter->last_visited == NULL)
732 iter->is_over = true;
733 break;
736 if (iter->last_visited->left == came_from)
737 break; /* came from left sub-tree, return current
738 * node */
740 /* else - came from right sub-tree, continue to move up */
743 return iter->last_visited;
746 static RBTNode *
747 rbt_right_left_iterator(RBTreeIterator *iter)
749 if (iter->last_visited == NULL)
751 iter->last_visited = iter->rbt->root;
752 while (iter->last_visited->right != RBTNIL)
753 iter->last_visited = iter->last_visited->right;
755 return iter->last_visited;
758 if (iter->last_visited->left != RBTNIL)
760 iter->last_visited = iter->last_visited->left;
761 while (iter->last_visited->right != RBTNIL)
762 iter->last_visited = iter->last_visited->right;
764 return iter->last_visited;
767 for (;;)
769 RBTNode *came_from = iter->last_visited;
771 iter->last_visited = iter->last_visited->parent;
772 if (iter->last_visited == NULL)
774 iter->is_over = true;
775 break;
778 if (iter->last_visited->right == came_from)
779 break; /* came from right sub-tree, return current
780 * node */
782 /* else - came from left sub-tree, continue to move up */
785 return iter->last_visited;
789 * rbt_begin_iterate: prepare to traverse the tree in any of several orders
791 * After calling rbt_begin_iterate, call rbt_iterate repeatedly until it
792 * returns NULL or the traversal stops being of interest.
794 * If the tree is changed during traversal, results of further calls to
795 * rbt_iterate are unspecified. Multiple concurrent iterators on the same
796 * tree are allowed.
798 * The iterator state is stored in the 'iter' struct. The caller should
799 * treat it as an opaque struct.
801 void
802 rbt_begin_iterate(RBTree *rbt, RBTOrderControl ctrl, RBTreeIterator *iter)
804 /* Common initialization for all traversal orders */
805 iter->rbt = rbt;
806 iter->last_visited = NULL;
807 iter->is_over = (rbt->root == RBTNIL);
809 switch (ctrl)
811 case LeftRightWalk: /* visit left, then self, then right */
812 iter->iterate = rbt_left_right_iterator;
813 break;
814 case RightLeftWalk: /* visit right, then self, then left */
815 iter->iterate = rbt_right_left_iterator;
816 break;
817 default:
818 elog(ERROR, "unrecognized rbtree iteration order: %d", ctrl);
823 * rbt_iterate: return the next node in traversal order, or NULL if no more
825 RBTNode *
826 rbt_iterate(RBTreeIterator *iter)
828 if (iter->is_over)
829 return NULL;
831 return iter->iterate(iter);