[MEDIUM] upgrade to ebtree v4.0

New ebtree also supports unique keys. This is useful for counters.
This commit is contained in:
Willy Tarreau 2008-05-16 19:48:20 +02:00
parent 9c30fc161f
commit 1fb6c87cce
4 changed files with 80 additions and 11 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;