mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-01 22:48:25 +00:00
[MEDIUM] upgrade to ebtree v4.0
New ebtree also supports unique keys. This is useful for counters.
This commit is contained in:
parent
9c30fc161f
commit
1fb6c87cce
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Elastic Binary Trees - macros and structures for operations on 32bit nodes.
|
||||
* (C) 2002-2007 - Willy Tarreau <w@1wt.eu>
|
||||
* Version 4.0
|
||||
* (C) 2002-2008 - Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -204,6 +205,7 @@ static inline struct eb32_node *__eb32i_lookup(struct eb_root *root, s32 x)
|
||||
|
||||
/* Insert eb32_node <new> into subtree starting at node root <root>.
|
||||
* Only new->key needs be set with the key. The eb32_node is returned.
|
||||
* If root->b[EB_RGHT]==1, the tree may only contain unique keys.
|
||||
*/
|
||||
static inline struct eb32_node *
|
||||
__eb32_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
@ -211,9 +213,11 @@ __eb32_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
unsigned int side;
|
||||
eb_troot_t *troot;
|
||||
u32 newkey; /* caching the key saves approximately one cycle */
|
||||
eb_troot_t *root_right = root;
|
||||
|
||||
side = EB_LEFT;
|
||||
troot = root->b[EB_LEFT];
|
||||
root_right = root->b[EB_RGHT];
|
||||
if (unlikely(troot == NULL)) {
|
||||
/* Tree is empty, insert the leaf part below the left branch */
|
||||
root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
|
||||
@ -272,6 +276,12 @@ __eb32_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
new->node.branches.b[EB_LEFT] = new_leaf;
|
||||
new->node.branches.b[EB_RGHT] = old_leaf;
|
||||
} else {
|
||||
/* we may refuse to duplicate this key if the tree is
|
||||
* tagged as containing only unique keys.
|
||||
*/
|
||||
if ((new->key == old->key) && eb_gettag(root_right))
|
||||
return old;
|
||||
|
||||
/* new->key >= old->key, new goes the right */
|
||||
old->node.leaf_p = new_left;
|
||||
new->node.leaf_p = new_rght;
|
||||
@ -359,7 +369,7 @@ __eb32_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
|
||||
/* Insert eb32_node <new> into subtree starting at node root <root>, using
|
||||
* signed keys. Only new->key needs be set with the key. The eb32_node
|
||||
* is returned
|
||||
* is returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys.
|
||||
*/
|
||||
static inline struct eb32_node *
|
||||
__eb32i_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
@ -367,9 +377,11 @@ __eb32i_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
unsigned int side;
|
||||
eb_troot_t *troot;
|
||||
int newkey; /* caching the key saves approximately one cycle */
|
||||
eb_troot_t *root_right = root;
|
||||
|
||||
side = EB_LEFT;
|
||||
troot = root->b[EB_LEFT];
|
||||
root_right = root->b[EB_RGHT];
|
||||
if (unlikely(troot == NULL)) {
|
||||
/* Tree is empty, insert the leaf part below the left branch */
|
||||
root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
|
||||
@ -430,6 +442,12 @@ __eb32i_insert(struct eb_root *root, struct eb32_node *new) {
|
||||
new->node.branches.b[EB_LEFT] = new_leaf;
|
||||
new->node.branches.b[EB_RGHT] = old_leaf;
|
||||
} else {
|
||||
/* we may refuse to duplicate this key if the tree is
|
||||
* tagged as containing only unique keys.
|
||||
*/
|
||||
if ((new->key == old->key) && eb_gettag(root_right))
|
||||
return old;
|
||||
|
||||
/* new->key >= old->key, new goes the right */
|
||||
old->node.leaf_p = new_left;
|
||||
new->node.leaf_p = new_rght;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Elastic Binary Trees - macros and structures for operations on 64bit nodes.
|
||||
* (C) 2002-2007 - Willy Tarreau <w@1wt.eu>
|
||||
* Version 4.0
|
||||
* (C) 2002-2008 - Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -204,6 +205,7 @@ static inline struct eb64_node *__eb64i_lookup(struct eb_root *root, s64 x)
|
||||
|
||||
/* Insert eb64_node <new> into subtree starting at node root <root>.
|
||||
* Only new->key needs be set with the key. The eb64_node is returned.
|
||||
* If root->b[EB_RGHT]==1, the tree may only contain unique keys.
|
||||
*/
|
||||
static inline struct eb64_node *
|
||||
__eb64_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
@ -211,9 +213,11 @@ __eb64_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
unsigned int side;
|
||||
eb_troot_t *troot;
|
||||
u64 newkey; /* caching the key saves approximately one cycle */
|
||||
eb_troot_t *root_right = root;
|
||||
|
||||
side = EB_LEFT;
|
||||
troot = root->b[EB_LEFT];
|
||||
root_right = root->b[EB_RGHT];
|
||||
if (unlikely(troot == NULL)) {
|
||||
/* Tree is empty, insert the leaf part below the left branch */
|
||||
root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
|
||||
@ -272,6 +276,12 @@ __eb64_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
new->node.branches.b[EB_LEFT] = new_leaf;
|
||||
new->node.branches.b[EB_RGHT] = old_leaf;
|
||||
} else {
|
||||
/* we may refuse to duplicate this key if the tree is
|
||||
* tagged as containing only unique keys.
|
||||
*/
|
||||
if ((new->key == old->key) && eb_gettag(root_right))
|
||||
return old;
|
||||
|
||||
/* new->key >= old->key, new goes the right */
|
||||
old->node.leaf_p = new_left;
|
||||
new->node.leaf_p = new_rght;
|
||||
@ -369,7 +379,7 @@ __eb64_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
|
||||
/* Insert eb64_node <new> into subtree starting at node root <root>, using
|
||||
* signed keys. Only new->key needs be set with the key. The eb64_node
|
||||
* is returned.
|
||||
* is returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys.
|
||||
*/
|
||||
static inline struct eb64_node *
|
||||
__eb64i_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
@ -377,9 +387,11 @@ __eb64i_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
unsigned int side;
|
||||
eb_troot_t *troot;
|
||||
u64 newkey; /* caching the key saves approximately one cycle */
|
||||
eb_troot_t *root_right = root;
|
||||
|
||||
side = EB_LEFT;
|
||||
troot = root->b[EB_LEFT];
|
||||
root_right = root->b[EB_RGHT];
|
||||
if (unlikely(troot == NULL)) {
|
||||
/* Tree is empty, insert the leaf part below the left branch */
|
||||
root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
|
||||
@ -440,6 +452,12 @@ __eb64i_insert(struct eb_root *root, struct eb64_node *new) {
|
||||
new->node.branches.b[EB_LEFT] = new_leaf;
|
||||
new->node.branches.b[EB_RGHT] = old_leaf;
|
||||
} else {
|
||||
/* we may refuse to duplicate this key if the tree is
|
||||
* tagged as containing only unique keys.
|
||||
*/
|
||||
if ((new->key == old->key) && eb_gettag(root_right))
|
||||
return old;
|
||||
|
||||
/* new->key >= old->key, new goes the right */
|
||||
old->node.leaf_p = new_left;
|
||||
new->node.leaf_p = new_rght;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Elastic Binary Trees - macros and structures for operations on pointer nodes.
|
||||
* (C) 2002-2007 - Willy Tarreau <w@1wt.eu>
|
||||
* Version 4.0
|
||||
* (C) 2002-2008 - Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -160,6 +161,7 @@ static inline struct ebpt_node *__ebpt_lookup(struct eb_root *root, void *x)
|
||||
|
||||
/* Insert ebpt_node <new> into subtree starting at node root <root>.
|
||||
* Only new->key needs be set with the key. The ebpt_node is returned.
|
||||
* If root->b[EB_RGHT]==1, the tree may only contain unique keys.
|
||||
*/
|
||||
static inline struct ebpt_node *
|
||||
__ebpt_insert(struct eb_root *root, struct ebpt_node *new) {
|
||||
@ -167,9 +169,11 @@ __ebpt_insert(struct eb_root *root, struct ebpt_node *new) {
|
||||
unsigned int side;
|
||||
eb_troot_t *troot;
|
||||
void *newkey; /* caching the key saves approximately one cycle */
|
||||
eb_troot_t *root_right = root;
|
||||
|
||||
side = EB_LEFT;
|
||||
troot = root->b[EB_LEFT];
|
||||
root_right = root->b[EB_RGHT];
|
||||
if (unlikely(troot == NULL)) {
|
||||
/* Tree is empty, insert the leaf part below the left branch */
|
||||
root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
|
||||
@ -228,6 +232,12 @@ __ebpt_insert(struct eb_root *root, struct ebpt_node *new) {
|
||||
new->node.branches.b[EB_LEFT] = new_leaf;
|
||||
new->node.branches.b[EB_RGHT] = old_leaf;
|
||||
} else {
|
||||
/* we may refuse to duplicate this key if the tree is
|
||||
* tagged as containing only unique keys.
|
||||
*/
|
||||
if ((new->key == old->key) && eb_gettag(root_right))
|
||||
return old;
|
||||
|
||||
/* new->key >= old->key, new goes the right */
|
||||
old->node.leaf_p = new_left;
|
||||
new->node.leaf_p = new_rght;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Elastic Binary Trees - generic macros and structures.
|
||||
* Version 4.0
|
||||
* (C) 2002-2008 - Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -205,7 +206,8 @@
|
||||
root, it is not possible to see a NULL left branch when walking up a
|
||||
tree. Thus, an empty tree is immediately identified by a NULL left
|
||||
branch at the root. Conversely, the one and only way to identify the
|
||||
root node is to check that it right branch is NULL.
|
||||
root node is to check that it right branch is NULL. Note that the
|
||||
NULL pointer may have a few low-order bits set.
|
||||
|
||||
- a node connected to its own leaf will have branch[0|1] pointing to
|
||||
itself, and leaf_p pointing to itself.
|
||||
@ -244,6 +246,11 @@
|
||||
higher to lower keys. It returns duplicates in the opposite order they
|
||||
were inserted. The "eb_last" primitive returns the right-most entry.
|
||||
|
||||
- a tree which has 1 in the lower bit of its root's right branch is a
|
||||
tree with unique nodes. This means that when a node is inserted with
|
||||
a key which already exists will not be inserted, and the previous
|
||||
entry will be returned.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_EBTREE_H
|
||||
@ -369,6 +376,13 @@ static inline int fls64(unsigned long long x)
|
||||
#define EB_LEAF 0
|
||||
#define EB_NODE 1
|
||||
|
||||
/* Tags to set in root->b[EB_RGHT] :
|
||||
* - EB_NORMAL is a normal tree which stores duplicate keys.
|
||||
* - EB_UNIQUE is a tree which stores unique keys.
|
||||
*/
|
||||
#define EB_NORMAL 0
|
||||
#define EB_UNIQUE 1
|
||||
|
||||
/* This is the same as an eb_node pointer, except that the lower bit embeds
|
||||
* a tag. See eb_dotag()/eb_untag()/eb_gettag(). This tag has two meanings :
|
||||
* - 0=left, 1=right to designate the parent's branch for leaf_p/node_p
|
||||
@ -378,7 +392,7 @@ typedef void eb_troot_t;
|
||||
|
||||
/* The eb_root connects the node which contains it, to two nodes below it, one
|
||||
* of which may be the same node. At the top of the tree, we use an eb_root
|
||||
* too, which always has its right branch NULL.
|
||||
* too, which always has its right branch NULL (+/1 low-order bits).
|
||||
*/
|
||||
struct eb_root {
|
||||
eb_troot_t *b[EB_NODE_BRANCHES]; /* left and right branches */
|
||||
@ -408,6 +422,11 @@ struct eb_node {
|
||||
.b = {[0] = NULL, [1] = NULL }, \
|
||||
}
|
||||
|
||||
#define EB_ROOT_UNIQUE \
|
||||
(struct eb_root) { \
|
||||
.b = {[0] = NULL, [1] = (void *)1 }, \
|
||||
}
|
||||
|
||||
#define EB_TREE_HEAD(name) \
|
||||
struct eb_root name = EB_ROOT
|
||||
|
||||
@ -552,7 +571,7 @@ static inline struct eb_node *eb_prev(struct eb_node *node)
|
||||
/* Walking up from left branch. We must ensure that we never
|
||||
* walk beyond root.
|
||||
*/
|
||||
if (unlikely((eb_untag(t, EB_LEFT))->b[EB_RGHT] == NULL))
|
||||
if (unlikely(eb_clrtag((eb_untag(t, EB_LEFT))->b[EB_RGHT]) == NULL))
|
||||
return NULL;
|
||||
t = (eb_root_to_node(eb_untag(t, EB_LEFT)))->node_p;
|
||||
}
|
||||
@ -572,6 +591,8 @@ static inline struct eb_node *eb_next(struct eb_node *node)
|
||||
|
||||
/* Note that <t> cannot be NULL at this stage */
|
||||
t = (eb_untag(t, EB_LEFT))->b[EB_RGHT];
|
||||
if (eb_clrtag(t) == NULL)
|
||||
return NULL;
|
||||
return eb_walk_down(t, EB_LEFT);
|
||||
}
|
||||
|
||||
@ -593,7 +614,7 @@ static inline struct eb_node *eb_prev_unique(struct eb_node *node)
|
||||
/* Walking up from left branch. We must ensure that we never
|
||||
* walk beyond root.
|
||||
*/
|
||||
if (unlikely((eb_untag(t, EB_LEFT))->b[EB_RGHT] == NULL))
|
||||
if (unlikely(eb_clrtag((eb_untag(t, EB_LEFT))->b[EB_RGHT]) == NULL))
|
||||
return NULL;
|
||||
t = (eb_root_to_node(eb_untag(t, EB_LEFT)))->node_p;
|
||||
}
|
||||
@ -612,7 +633,7 @@ static inline struct eb_node *eb_next_unique(struct eb_node *node)
|
||||
|
||||
while (1) {
|
||||
if (eb_gettag(t) == EB_LEFT) {
|
||||
if (unlikely((eb_untag(t, EB_LEFT))->b[EB_RGHT] == NULL))
|
||||
if (unlikely(eb_clrtag((eb_untag(t, EB_LEFT))->b[EB_RGHT]) == NULL))
|
||||
return NULL; /* we reached root */
|
||||
node = eb_root_to_node(eb_untag(t, EB_LEFT));
|
||||
/* if we're left and not in duplicates, stop here */
|
||||
@ -628,6 +649,8 @@ static inline struct eb_node *eb_next_unique(struct eb_node *node)
|
||||
|
||||
/* Note that <t> cannot be NULL at this stage */
|
||||
t = (eb_untag(t, EB_LEFT))->b[EB_RGHT];
|
||||
if (eb_clrtag(t) == NULL)
|
||||
return NULL;
|
||||
return eb_walk_down(t, EB_LEFT);
|
||||
}
|
||||
|
||||
@ -654,7 +677,7 @@ static inline void __eb_delete(struct eb_node *node)
|
||||
* only be attached to the root by its left branch.
|
||||
*/
|
||||
|
||||
if (parent->branches.b[EB_RGHT] == NULL) {
|
||||
if (eb_clrtag(parent->branches.b[EB_RGHT]) == NULL) {
|
||||
/* we're just below the root, it's trivial. */
|
||||
parent->branches.b[EB_LEFT] = NULL;
|
||||
goto delete_unlink;
|
||||
|
Loading…
Reference in New Issue
Block a user