interval-tree: add augmentation fns to the tree

An interval tree uses red-black tree as its base data structure and
follows all the properties of a usual red-black tree. The additional
params are:
1. An interval such as [low, high] per node.
2. A max attribute per node. This attribute stores the maximum high
   value of any subtree rooted at this node.

At any point in time, an inorder traversal of an interval tree should
give the port ranges sorted by the low key in ascending order.

This commit modifies the IRB_AUGMENT macro and it's call sites to make
sure that on every insertion, the max attribute of the tree is properly
updated.

Ticket 6792
Bug 6414
pull/10569/head
Shivani Bhardwaj 2 years ago committed by Victor Julien
parent 30b6e4d368
commit d36d03a428

@ -511,6 +511,7 @@ noinst_HEADERS = \
tm-threads-common.h \ tm-threads-common.h \
tm-threads.h \ tm-threads.h \
tree.h \ tree.h \
interval-tree.h \
unix-manager.h \ unix-manager.h \
util-action.h \ util-action.h \
util-affinity.h \ util-affinity.h \

@ -2,7 +2,8 @@
/* $OpenBSD: interval-tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ /* $OpenBSD: interval-tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
/* $FreeBSD$ */ /* $FreeBSD$ */
/* This is a COPY of the in-tree tree.h */ /* This is a COPY of the in-tree tree.h modified to accomodate interval
* tree operations */
/*- /*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
@ -41,9 +42,10 @@
#endif #endif
/* /*
* This file defines data structures for red-black trees. * This file defines data structures for interval trees which are
* implemented using red-black trees.
* *
* A red-black tree is a binary search interval-tree with the node color as an * A red-black tree is a binary search tree with the node color as an
* extra attribute. It fulfills a set of conditions: * extra attribute. It fulfills a set of conditions:
* - every search path from the root to a leaf consists of the * - every search path from the root to a leaf consists of the
* same number of black nodes, * same number of black nodes,
@ -100,9 +102,23 @@
IRB_COLOR(red, field) = IRB_RED; \ IRB_COLOR(red, field) = IRB_RED; \
} while (/*CONSTCOND*/ 0) } while (/*CONSTCOND*/ 0)
/*
* The implementation of the following macro has been updated.
* In order to incorporte it properly, the call sites of this
* function have also been updated compared to the standard
* Red Black tree implementation in tree.h of BSD */
#ifndef IRB_AUGMENT #ifndef IRB_AUGMENT
#define IRB_AUGMENT(x) \ #define IRB_AUGMENT(x, field) \
do { \ do { \
if (x != NULL) { \
x->max = x->port2; \
if (IRB_LEFT(x, field) != NULL) { \
x->max = MAX(x->max, IRB_LEFT(x, field)->max); \
} \
if (IRB_RIGHT(x, field) != NULL) { \
x->max = MAX(x->max, IRB_RIGHT(x, field)->max); \
} \
} \
} while (0) } while (0)
#endif #endif
@ -112,7 +128,6 @@
if ((IRB_RIGHT(elm, field) = IRB_LEFT(tmp, field)) != NULL) { \ if ((IRB_RIGHT(elm, field) = IRB_LEFT(tmp, field)) != NULL) { \
IRB_PARENT(IRB_LEFT(tmp, field), field) = (elm); \ IRB_PARENT(IRB_LEFT(tmp, field), field) = (elm); \
} \ } \
IRB_AUGMENT(elm); \
if ((IRB_PARENT(tmp, field) = IRB_PARENT(elm, field)) != NULL) { \ if ((IRB_PARENT(tmp, field) = IRB_PARENT(elm, field)) != NULL) { \
if ((elm) == IRB_LEFT(IRB_PARENT(elm, field), field)) \ if ((elm) == IRB_LEFT(IRB_PARENT(elm, field), field)) \
IRB_LEFT(IRB_PARENT(elm, field), field) = (tmp); \ IRB_LEFT(IRB_PARENT(elm, field), field) = (tmp); \
@ -122,9 +137,10 @@
(head)->rbh_root = (tmp); \ (head)->rbh_root = (tmp); \
IRB_LEFT(tmp, field) = (elm); \ IRB_LEFT(tmp, field) = (elm); \
IRB_PARENT(elm, field) = (tmp); \ IRB_PARENT(elm, field) = (tmp); \
IRB_AUGMENT(tmp); \ IRB_AUGMENT(elm, field); \
IRB_AUGMENT(tmp, field); \
if ((IRB_PARENT(tmp, field))) \ if ((IRB_PARENT(tmp, field))) \
IRB_AUGMENT(IRB_PARENT(tmp, field)); \ IRB_AUGMENT(IRB_PARENT(tmp, field), field); \
} while (/*CONSTCOND*/ 0) } while (/*CONSTCOND*/ 0)
#define IRB_ROTATE_RIGHT(head, elm, tmp, field) \ #define IRB_ROTATE_RIGHT(head, elm, tmp, field) \
@ -133,7 +149,6 @@
if ((IRB_LEFT(elm, field) = IRB_RIGHT(tmp, field)) != NULL) { \ if ((IRB_LEFT(elm, field) = IRB_RIGHT(tmp, field)) != NULL) { \
IRB_PARENT(IRB_RIGHT(tmp, field), field) = (elm); \ IRB_PARENT(IRB_RIGHT(tmp, field), field) = (elm); \
} \ } \
IRB_AUGMENT(elm); \
if ((IRB_PARENT(tmp, field) = IRB_PARENT(elm, field)) != NULL) { \ if ((IRB_PARENT(tmp, field) = IRB_PARENT(elm, field)) != NULL) { \
if ((elm) == IRB_LEFT(IRB_PARENT(elm, field), field)) \ if ((elm) == IRB_LEFT(IRB_PARENT(elm, field), field)) \
IRB_LEFT(IRB_PARENT(elm, field), field) = (tmp); \ IRB_LEFT(IRB_PARENT(elm, field), field) = (tmp); \
@ -143,9 +158,10 @@
(head)->rbh_root = (tmp); \ (head)->rbh_root = (tmp); \
IRB_RIGHT(tmp, field) = (elm); \ IRB_RIGHT(tmp, field) = (elm); \
IRB_PARENT(elm, field) = (tmp); \ IRB_PARENT(elm, field) = (tmp); \
IRB_AUGMENT(tmp); \ IRB_AUGMENT(elm, field); \
IRB_AUGMENT(tmp, field); \
if ((IRB_PARENT(tmp, field))) \ if ((IRB_PARENT(tmp, field))) \
IRB_AUGMENT(IRB_PARENT(tmp, field)); \ IRB_AUGMENT(IRB_PARENT(tmp, field), field); \
} while (/*CONSTCOND*/ 0) } while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */ /* Generates prototypes and inline functions */
@ -341,7 +357,7 @@
IRB_LEFT(parent, field) = child; \ IRB_LEFT(parent, field) = child; \
else \ else \
IRB_RIGHT(parent, field) = child; \ IRB_RIGHT(parent, field) = child; \
IRB_AUGMENT(parent); \ IRB_AUGMENT(parent, field); \
} else \ } else \
IRB_ROOT(head) = child; \ IRB_ROOT(head) = child; \
if (IRB_PARENT(elm, field) == old) \ if (IRB_PARENT(elm, field) == old) \
@ -353,7 +369,7 @@
IRB_LEFT(IRB_PARENT(old, field), field) = elm; \ IRB_LEFT(IRB_PARENT(old, field), field) = elm; \
else \ else \
IRB_RIGHT(IRB_PARENT(old, field), field) = elm; \ IRB_RIGHT(IRB_PARENT(old, field), field) = elm; \
IRB_AUGMENT(IRB_PARENT(old, field)); \ IRB_AUGMENT(IRB_PARENT(old, field), field); \
} else \ } else \
IRB_ROOT(head) = elm; \ IRB_ROOT(head) = elm; \
_T_ASSERT(old); \ _T_ASSERT(old); \
@ -364,7 +380,7 @@
if (parent) { \ if (parent) { \
left = parent; \ left = parent; \
do { \ do { \
IRB_AUGMENT(left); \ IRB_AUGMENT(left, field); \
} while ((left = IRB_PARENT(left, field)) != NULL); \ } while ((left = IRB_PARENT(left, field)) != NULL); \
} \ } \
goto color; \ goto color; \
@ -378,7 +394,7 @@
IRB_LEFT(parent, field) = child; \ IRB_LEFT(parent, field) = child; \
else \ else \
IRB_RIGHT(parent, field) = child; \ IRB_RIGHT(parent, field) = child; \
IRB_AUGMENT(parent); \ IRB_AUGMENT(parent, field); \
} else \ } else \
IRB_ROOT(head) = child; \ IRB_ROOT(head) = child; \
color: \ color: \
@ -398,11 +414,11 @@
while (tmp) { \ while (tmp) { \
parent = tmp; \ parent = tmp; \
comp = (cmp)(elm, parent); \ comp = (cmp)(elm, parent); \
if (comp < 0) \ if (comp < 0) { \
tmp = IRB_LEFT(tmp, field); \ tmp = IRB_LEFT(tmp, field); \
else if (comp > 0) \ } else if (comp > 0) { \
tmp = IRB_RIGHT(tmp, field); \ tmp = IRB_RIGHT(tmp, field); \
else \ } else \
return (tmp); \ return (tmp); \
} \ } \
IRB_SET(elm, parent, field); \ IRB_SET(elm, parent, field); \
@ -411,9 +427,9 @@
IRB_LEFT(parent, field) = elm; \ IRB_LEFT(parent, field) = elm; \
else \ else \
IRB_RIGHT(parent, field) = elm; \ IRB_RIGHT(parent, field) = elm; \
IRB_AUGMENT(parent); \
} else \ } else \
IRB_ROOT(head) = elm; \ IRB_ROOT(head) = elm; \
IRB_AUGMENT(elm, field); \
name##_IRB_INSERT_COLOR(head, elm); \ name##_IRB_INSERT_COLOR(head, elm); \
return (NULL); \ return (NULL); \
} }

Loading…
Cancel
Save