ebtree/0000755000076400001440000000000011613243153011521 5ustar bernatusersebtree/ebmbtree.c0000644000076400001440000000544411613243153013461 0ustar bernatusers/* * Elastic Binary Trees - exported functions for Multi-Byte data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult ebmbtree.h for more details about those functions */ #include "ebmbtree.h" /* Find the first occurence of a key of bytes in the tree . * If none can be found, return NULL. */ REGPRM3 struct ebmb_node * ebmb_lookup(struct eb_root *root, const void *x, unsigned int len) { return __ebmb_lookup(root, x, len); } /* Insert ebmb_node into subtree starting at node root . * Only new->key needs be set with the key. The ebmb_node is returned. * If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * len is specified in bytes. */ REGPRM3 struct ebmb_node * ebmb_insert(struct eb_root *root, struct ebmb_node *new, unsigned int len) { return __ebmb_insert(root, new, len); } /* Find the first occurence of the longest prefix matching a key in the * tree . It's the caller's responsibility to ensure that key is at * least as long as the keys in the tree. If none can be found, return NULL. */ REGPRM2 struct ebmb_node * ebmb_lookup_longest(struct eb_root *root, const void *x) { return __ebmb_lookup_longest(root, x); } /* Find the first occurence of a prefix matching a key of BITS in the * tree . If none can be found, return NULL. */ REGPRM3 struct ebmb_node * ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx) { return __ebmb_lookup_prefix(root, x, pfx); } /* Insert ebmb_node into a prefix subtree starting at node root . * Only new->key and new->pfx need be set with the key and its prefix length. * Note that bits between and are theorically ignored and should be * zero, as it is not certain yet that they will always be ignored everywhere * (eg in bit compare functions). * The ebmb_node is returned. * If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * len is specified in bytes. */ REGPRM3 struct ebmb_node * ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len) { return __ebmb_insert_prefix(root, new, len); } ebtree/ebsttree.h0000644000076400001440000002435211613243153013515 0ustar bernatusers/* * Elastic Binary Trees - macros to manipulate String data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* These functions and macros rely on Multi-Byte nodes */ #ifndef _EBSTTREE_H #define _EBSTTREE_H #include "ebtree.h" #include "ebmbtree.h" /* The following functions are not inlined by default. They are declared * in ebsttree.c, which simply relies on their inline version. */ REGPRM2 struct ebmb_node *ebst_lookup(struct eb_root *root, const char *x); REGPRM2 struct ebmb_node *ebst_insert(struct eb_root *root, struct ebmb_node *new); /* Find the first occurence of a length string in the tree . * It's the caller's reponsibility to use this function only on trees which * only contain zero-terminated strings, and that no null character is present * in string in the first chars. If none can be found, return NULL. */ static forceinline struct ebmb_node * ebst_lookup_len(struct eb_root *root, const char *x, unsigned int len) { struct ebmb_node *node; node = ebmb_lookup(root, x, len); if (!node || node->key[len] != 0) return NULL; return node; } /* Find the first occurence of a zero-terminated string in the tree . * It's the caller's reponsibility to use this function only on trees which * only contain zero-terminated strings. If none can be found, return NULL. */ static forceinline struct ebmb_node *__ebst_lookup(struct eb_root *root, const void *x) { struct ebmb_node *node; eb_troot_t *troot; int bit; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; bit = 0; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); if (strcmp((char *)node->key, x) == 0) return node; else return NULL; } node = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); node_bit = node->node.bit; if (node_bit < 0) { /* We have a dup tree now. Either it's for the same * value, and we walk down left, or it's a different * one and we don't have our key. */ if (strcmp((char *)node->key, x) != 0) return NULL; troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); return node; } /* OK, normal data node, let's walk down but don't compare data * if we already reached the end of the key. */ if (likely(bit >= 0)) { bit = string_equal_bits(x, node->key, bit); if (likely(bit < node_bit)) { if (bit >= 0) return NULL; /* no more common bits */ /* bit < 0 : we reached the end of the key. If we * are in a tree with unique keys, we can return * this node. Otherwise we have to walk it down * and stop comparing bits. */ if (eb_gettag(root->b[EB_RGHT])) return node; } } troot = node->node.branches.b[(((unsigned char*)x)[node_bit >> 3] >> (~node_bit & 7)) & 1]; } } /* Insert ebmb_node into subtree starting at node root . Only * new->key needs be set with the zero-terminated string key. The ebmb_node is * returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * caller is responsible for properly terminating the key with a zero. */ static forceinline struct ebmb_node * __ebst_insert(struct eb_root *root, struct ebmb_node *new) { struct ebmb_node *old; unsigned int side; eb_troot_t *troot; eb_troot_t *root_right = root; int diff; int bit; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. */ bit = 0; while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_leaf; old = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_leaf = eb_dotag(&old->node.branches, EB_LEAF); new->node.node_p = old->node.leaf_p; /* Right here, we have 3 possibilities : * - the tree does not contain the key, and we have * new->key < old->key. We insert new above old, on * the left ; * * - the tree does not contain the key, and we have * new->key > old->key. We insert new above old, on * the right ; * * - the tree does contain the key, which implies it * is alone. We add the new key next to it as a * first duplicate. * * The last two cases can easily be partially merged. */ if (bit >= 0) bit = string_equal_bits(new->key, old->key, bit); if (bit < 0) { /* key was already there */ /* we may refuse to duplicate this key if the tree is * tagged as containing only unique keys. */ if (eb_gettag(root_right)) return old; /* new arbitrarily goes to the right and tops the dup tree */ old->node.leaf_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; new->node.bit = -1; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } diff = cmp_bits(new->key, old->key, bit); if (diff < 0) { /* new->key < old->key, new takes the left */ new->node.leaf_p = new_left; old->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_leaf; } else { /* new->key > old->key, new takes the right */ old->node.leaf_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; } break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. Note: we can compare more bits than * the current node's because as long as they are identical, we * know we descend along the correct side. */ if (bit >= 0 && (bit < old_node_bit || old_node_bit < 0)) bit = string_equal_bits(new->key, old->key, bit); if (unlikely(bit < 0)) { /* Perfect match, we must only stop on head of dup tree * or walk down to a leaf. */ if (old_node_bit < 0) { /* We know here that string_equal_bits matched all * bits and that we're on top of a dup tree, then * we can perform the dup insertion and return. */ struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct ebmb_node, node); } /* OK so let's walk down */ } else if (bit < old_node_bit || old_node_bit < 0) { /* The tree did not contain the key, or we stopped on top of a dup * tree, possibly containing the key. In the former case, we insert * before the node , and set ->bit to designate the lowest * bit position in which applies to ->branches.b[]. In the later * case, we add the key to the existing dup tree. Note that we cannot * enter here if we match an intermediate node's key that is not the * head of a dup tree. */ eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_node; new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_node = eb_dotag(&old->node.branches, EB_NODE); new->node.node_p = old->node.node_p; /* we can never match all bits here */ diff = cmp_bits(new->key, old->key, bit); if (diff < 0) { new->node.leaf_p = new_left; old->node.node_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_node; } else { old->node.node_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_node; new->node.branches.b[EB_RGHT] = new_leaf; } break; } /* walk down */ root = &old->node.branches; side = (new->key[old_node_bit >> 3] >> (~old_node_bit & 7)) & 1; troot = root->b[side]; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ /* We need the common higher bits between new->key and old->key. * This number of bits is already in . * NOTE: we can't get here whit bit < 0 since we found a dup ! */ new->node.bit = bit; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } #endif /* _EBSTTREE_H */ ebtree/ebimtree.c0000644000076400001440000000307011613243153013461 0ustar bernatusers/* * Elastic Binary Trees - exported functions for Indirect Multi-Byte data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult ebimtree.h for more details about those functions */ #include "ebpttree.h" #include "ebimtree.h" /* Find the first occurence of a key of bytes in the tree . * If none can be found, return NULL. */ REGPRM3 struct ebpt_node * ebim_lookup(struct eb_root *root, const void *x, unsigned int len) { return __ebim_lookup(root, x, len); } /* Insert ebpt_node into subtree starting at node 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. The * len is specified in bytes. */ REGPRM3 struct ebpt_node * ebim_insert(struct eb_root *root, struct ebpt_node *new, unsigned int len) { return __ebim_insert(root, new, len); } ebtree/eb64tree.c0000644000076400001440000001566211613243153013317 0ustar bernatusers/* * Elastic Binary Trees - exported functions for operations on 64bit nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult eb64tree.h for more details about those functions */ #include "eb64tree.h" REGPRM2 struct eb64_node *eb64_insert(struct eb_root *root, struct eb64_node *new) { return __eb64_insert(root, new); } REGPRM2 struct eb64_node *eb64i_insert(struct eb_root *root, struct eb64_node *new) { return __eb64i_insert(root, new); } REGPRM2 struct eb64_node *eb64_lookup(struct eb_root *root, u64 x) { return __eb64_lookup(root, x); } REGPRM2 struct eb64_node *eb64i_lookup(struct eb_root *root, s64 x) { return __eb64i_lookup(root, x); } /* * Find the last occurrence of the highest key in the tree , which is * equal to or less than . NULL is returned is no key matches. */ REGPRM2 struct eb64_node *eb64_lookup_le(struct eb_root *root, u64 x) { struct eb64_node *node; eb_troot_t *troot; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { /* We reached a leaf, which means that the whole upper * parts were common. We will return either the current * node or its next one if the former is too small. */ node = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); if (node->key <= x) return node; /* return prev */ troot = node->node.leaf_p; break; } node = container_of(eb_untag(troot, EB_NODE), struct eb64_node, node.branches); if (node->node.bit < 0) { /* We're at the top of a dup tree. Either we got a * matching value and we return the rightmost node, or * we don't and we skip the whole subtree to return the * prev node before the subtree. Note that since we're * at the top of the dup tree, we can simply return the * prev node without first trying to escape from the * tree. */ if (node->key <= x) { troot = node->node.branches.b[EB_RGHT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_RGHT]; return container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); } /* return prev */ troot = node->node.node_p; break; } if (((x ^ node->key) >> node->node.bit) >= EB_NODE_BRANCHES) { /* No more common bits at all. Either this node is too * small and we need to get its highest value, or it is * too large, and we need to get the prev value. */ if ((node->key >> node->node.bit) < (x >> node->node.bit)) { troot = node->node.branches.b[EB_RGHT]; return eb64_entry(eb_walk_down(troot, EB_RGHT), struct eb64_node, node); } /* Further values will be too high here, so return the prev * unique node (if it exists). */ troot = node->node.node_p; break; } troot = node->node.branches.b[(x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } /* If we get here, it means we want to report previous node before the * current one which is not above. is already initialised to * the parent's branches. */ while (eb_gettag(troot) == EB_LEFT) { /* Walking up from left branch. We must ensure that we never * walk beyond root. */ if (unlikely(eb_clrtag((eb_untag(troot, EB_LEFT))->b[EB_RGHT]) == NULL)) return NULL; troot = (eb_root_to_node(eb_untag(troot, EB_LEFT)))->node_p; } /* Note that cannot be NULL at this stage */ troot = (eb_untag(troot, EB_RGHT))->b[EB_LEFT]; node = eb64_entry(eb_walk_down(troot, EB_RGHT), struct eb64_node, node); return node; } /* * Find the first occurrence of the lowest key in the tree , which is * equal to or greater than . NULL is returned is no key matches. */ REGPRM2 struct eb64_node *eb64_lookup_ge(struct eb_root *root, u64 x) { struct eb64_node *node; eb_troot_t *troot; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { /* We reached a leaf, which means that the whole upper * parts were common. We will return either the current * node or its next one if the former is too small. */ node = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); if (node->key >= x) return node; /* return next */ troot = node->node.leaf_p; break; } node = container_of(eb_untag(troot, EB_NODE), struct eb64_node, node.branches); if (node->node.bit < 0) { /* We're at the top of a dup tree. Either we got a * matching value and we return the leftmost node, or * we don't and we skip the whole subtree to return the * next node after the subtree. Note that since we're * at the top of the dup tree, we can simply return the * next node without first trying to escape from the * tree. */ if (node->key >= x) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; return container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); } /* return next */ troot = node->node.node_p; break; } if (((x ^ node->key) >> node->node.bit) >= EB_NODE_BRANCHES) { /* No more common bits at all. Either this node is too * large and we need to get its lowest value, or it is too * small, and we need to get the next value. */ if ((node->key >> node->node.bit) > (x >> node->node.bit)) { troot = node->node.branches.b[EB_LEFT]; return eb64_entry(eb_walk_down(troot, EB_LEFT), struct eb64_node, node); } /* Further values will be too low here, so return the next * unique node (if it exists). */ troot = node->node.node_p; break; } troot = node->node.branches.b[(x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } /* If we get here, it means we want to report next node after the * current one which is not below. is already initialised * to the parent's branches. */ while (eb_gettag(troot) != EB_LEFT) /* Walking up from right branch, so we cannot be below root */ troot = (eb_root_to_node(eb_untag(troot, EB_RGHT)))->node_p; /* Note that cannot be NULL at this stage */ troot = (eb_untag(troot, EB_LEFT))->b[EB_RGHT]; if (eb_clrtag(troot) == NULL) return NULL; node = eb64_entry(eb_walk_down(troot, EB_LEFT), struct eb64_node, node); return node; } ebtree/Makefile0000644000076400001440000000170511613243153013164 0ustar bernatusersOBJS = ebtree.o eb32tree.o eb64tree.o ebmbtree.o ebsttree.o ebimtree.o ebistree.o CFLAGS = -O3 EXAMPLES = $(basename $(wildcard examples/*.c)) all: libebtree.a examples: ${EXAMPLES} libebtree.a: $(OBJS) $(AR) rv $@ $^ %.o: %.c $(CC) $(CFLAGS) -o $@ -c $^ examples/%: examples/%.c libebtree.a $(CC) $(CFLAGS) -I. -o $@ $< -L. -lebtree test: test32 test64 testst test%: test%.c libebtree.a $(CC) $(CFLAGS) -o $@ $< -L. -lebtree clean: -rm -fv libebtree.a $(OBJS) *~ *.rej core test32 test64 testst ${EXAMPLES} ifeq ($(wildcard .git),.git) VERSION := $(shell [ -d .git/. ] && ref=`(git describe --tags --match 'v*') 2>/dev/null` && ref=$${ref%-g*} && echo "$${ref\#v}") SUBVERS := $(shell comms=`git log --no-merges v$(VERSION).. 2>/dev/null |grep -c ^commit `; [ $$comms -gt 0 ] && echo "-$$comms" ) endif git-tar: .git git archive --format=tar --prefix="ebtree-$(VERSION)/" HEAD | gzip -9 > ebtree-$(VERSION)$(SUBVERS).tar.gz .PHONY: examples tests ebtree/eb32tree.h0000644000076400001440000003661611613243153013321 0ustar bernatusers/* * Elastic Binary Trees - macros and structures for operations on 32bit nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _EB32TREE_H #define _EB32TREE_H #include "ebtree.h" /* Return the structure of type whose member points to */ #define eb32_entry(ptr, type, member) container_of(ptr, type, member) #define EB32_ROOT EB_ROOT #define EB32_TREE_HEAD EB_TREE_HEAD /* These types may sometimes already be defined */ typedef unsigned int u32; typedef signed int s32; /* This structure carries a node, a leaf, and a key. It must start with the * eb_node so that it can be cast into an eb_node. We could also have put some * sort of transparent union here to reduce the indirection level, but the fact * is, the end user is not meant to manipulate internals, so this is pointless. */ struct eb32_node { struct eb_node node; /* the tree node, must be at the beginning */ u32 key; }; /* * Exported functions and macros. * Many of them are always inlined because they are extremely small, and * are generally called at most once or twice in a program. */ /* Return leftmost node in the tree, or NULL if none */ static inline struct eb32_node *eb32_first(struct eb_root *root) { return eb32_entry(eb_first(root), struct eb32_node, node); } /* Return rightmost node in the tree, or NULL if none */ static inline struct eb32_node *eb32_last(struct eb_root *root) { return eb32_entry(eb_last(root), struct eb32_node, node); } /* Return next node in the tree, or NULL if none */ static inline struct eb32_node *eb32_next(struct eb32_node *eb32) { return eb32_entry(eb_next(&eb32->node), struct eb32_node, node); } /* Return previous node in the tree, or NULL if none */ static inline struct eb32_node *eb32_prev(struct eb32_node *eb32) { return eb32_entry(eb_prev(&eb32->node), struct eb32_node, node); } /* Return next node in the tree, skipping duplicates, or NULL if none */ static inline struct eb32_node *eb32_next_unique(struct eb32_node *eb32) { return eb32_entry(eb_next_unique(&eb32->node), struct eb32_node, node); } /* Return previous node in the tree, skipping duplicates, or NULL if none */ static inline struct eb32_node *eb32_prev_unique(struct eb32_node *eb32) { return eb32_entry(eb_prev_unique(&eb32->node), struct eb32_node, node); } /* Delete node from the tree if it was linked in. Mark the node unused. Note * that this function relies on a non-inlined generic function: eb_delete. */ static inline void eb32_delete(struct eb32_node *eb32) { eb_delete(&eb32->node); } /* * The following functions are not inlined by default. They are declared * in eb32tree.c, which simply relies on their inline version. */ REGPRM2 struct eb32_node *eb32_lookup(struct eb_root *root, u32 x); REGPRM2 struct eb32_node *eb32i_lookup(struct eb_root *root, s32 x); REGPRM2 struct eb32_node *eb32_lookup_le(struct eb_root *root, u32 x); REGPRM2 struct eb32_node *eb32_lookup_ge(struct eb_root *root, u32 x); REGPRM2 struct eb32_node *eb32_insert(struct eb_root *root, struct eb32_node *new); REGPRM2 struct eb32_node *eb32i_insert(struct eb_root *root, struct eb32_node *new); /* * The following functions are less likely to be used directly, because their * code is larger. The non-inlined version is preferred. */ /* Delete node from the tree if it was linked in. Mark the node unused. */ static forceinline void __eb32_delete(struct eb32_node *eb32) { __eb_delete(&eb32->node); } /* * Find the first occurence of a key in the tree . If none can be * found, return NULL. */ static forceinline struct eb32_node *__eb32_lookup(struct eb_root *root, u32 x) { struct eb32_node *node; eb_troot_t *troot; u32 y; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); if (node->key == x) return node; else return NULL; } node = container_of(eb_untag(troot, EB_NODE), struct eb32_node, node.branches); node_bit = node->node.bit; y = node->key ^ x; if (!y) { /* Either we found the node which holds the key, or * we have a dup tree. In the later case, we have to * walk it down left to get the first entry. */ if (node_bit < 0) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); } return node; } if ((y >> node_bit) >= EB_NODE_BRANCHES) return NULL; /* no more common bits */ troot = node->node.branches.b[(x >> node_bit) & EB_NODE_BRANCH_MASK]; } } /* * Find the first occurence of a signed key in the tree . If none can * be found, return NULL. */ static forceinline struct eb32_node *__eb32i_lookup(struct eb_root *root, s32 x) { struct eb32_node *node; eb_troot_t *troot; u32 key = x ^ 0x80000000; u32 y; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); if (node->key == (u32)x) return node; else return NULL; } node = container_of(eb_untag(troot, EB_NODE), struct eb32_node, node.branches); node_bit = node->node.bit; y = node->key ^ x; if (!y) { /* Either we found the node which holds the key, or * we have a dup tree. In the later case, we have to * walk it down left to get the first entry. */ if (node_bit < 0) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); } return node; } if ((y >> node_bit) >= EB_NODE_BRANCHES) return NULL; /* no more common bits */ troot = node->node.branches.b[(key >> node_bit) & EB_NODE_BRANCH_MASK]; } } /* Insert eb32_node into subtree starting at node 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 forceinline struct eb32_node * __eb32_insert(struct eb_root *root, struct eb32_node *new) { struct eb32_node *old; unsigned int side; eb_troot_t *troot, **up_ptr; u32 newkey; /* caching the key saves approximately one cycle */ eb_troot_t *root_right = root; eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. carries the key being inserted. */ newkey = new->key; while (1) { if (eb_gettag(troot) == EB_LEAF) { /* insert above a leaf */ old = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); new->node.node_p = old->node.leaf_p; up_ptr = &old->node.leaf_p; break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct eb32_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. */ if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { /* The tree did not contain the key, so we insert before the node * , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; break; } /* walk down */ root = &old->node.branches; side = (newkey >> old_node_bit) & EB_NODE_BRANCH_MASK; troot = root->b[side]; } new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); /* We need the common higher bits between new->key and old->key. * What differences are there between new->key and the node here ? * NOTE that bit(new) is always < bit(root) because highest * bit of new->key and old->key are identical here (otherwise they * would sit on different branches). */ // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 new->node.bit = flsnz(new->key ^ old->key) - EB_NODE_BITS; if (new->key == old->key) { new->node.bit = -1; /* mark as new dup tree, just in case */ if (likely(eb_gettag(root_right))) { /* we refuse to duplicate this key if the tree is * tagged as containing only unique keys. */ return old; } if (eb_gettag(troot) != EB_LEAF) { /* there was already a dup tree below */ struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct eb32_node, node); } /* otherwise fall through */ } if (new->key >= old->key) { new->node.branches.b[EB_LEFT] = troot; new->node.branches.b[EB_RGHT] = new_leaf; new->node.leaf_p = new_rght; *up_ptr = new_left; } else { new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = troot; new->node.leaf_p = new_left; *up_ptr = new_rght; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } /* Insert eb32_node into subtree starting at node root , using * signed keys. 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 forceinline struct eb32_node * __eb32i_insert(struct eb_root *root, struct eb32_node *new) { struct eb32_node *old; unsigned int side; eb_troot_t *troot, **up_ptr; int newkey; /* caching the key saves approximately one cycle */ eb_troot_t *root_right = root; eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. carries a high bit shift of the key being * inserted in order to have negative keys stored before positive * ones. */ newkey = new->key + 0x80000000; while (1) { if (eb_gettag(troot) == EB_LEAF) { old = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); new->node.node_p = old->node.leaf_p; up_ptr = &old->node.leaf_p; break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct eb32_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. */ if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { /* The tree did not contain the key, so we insert before the node * , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; break; } /* walk down */ root = &old->node.branches; side = (newkey >> old_node_bit) & EB_NODE_BRANCH_MASK; troot = root->b[side]; } new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); /* We need the common higher bits between new->key and old->key. * What differences are there between new->key and the node here ? * NOTE that bit(new) is always < bit(root) because highest * bit of new->key and old->key are identical here (otherwise they * would sit on different branches). */ // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 new->node.bit = flsnz(new->key ^ old->key) - EB_NODE_BITS; if (new->key == old->key) { new->node.bit = -1; /* mark as new dup tree, just in case */ if (likely(eb_gettag(root_right))) { /* we refuse to duplicate this key if the tree is * tagged as containing only unique keys. */ return old; } if (eb_gettag(troot) != EB_LEAF) { /* there was already a dup tree below */ struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct eb32_node, node); } /* otherwise fall through */ } if ((s32)new->key >= (s32)old->key) { new->node.branches.b[EB_LEFT] = troot; new->node.branches.b[EB_RGHT] = new_leaf; new->node.leaf_p = new_rght; *up_ptr = new_left; } else { new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = troot; new->node.leaf_p = new_left; *up_ptr = new_rght; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } #endif /* _EB32_TREE_H */ ebtree/eb32tree.c0000644000076400001440000001566211613243153013312 0ustar bernatusers/* * Elastic Binary Trees - exported functions for operations on 32bit nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult eb32tree.h for more details about those functions */ #include "eb32tree.h" REGPRM2 struct eb32_node *eb32_insert(struct eb_root *root, struct eb32_node *new) { return __eb32_insert(root, new); } REGPRM2 struct eb32_node *eb32i_insert(struct eb_root *root, struct eb32_node *new) { return __eb32i_insert(root, new); } REGPRM2 struct eb32_node *eb32_lookup(struct eb_root *root, u32 x) { return __eb32_lookup(root, x); } REGPRM2 struct eb32_node *eb32i_lookup(struct eb_root *root, s32 x) { return __eb32i_lookup(root, x); } /* * Find the last occurrence of the highest key in the tree , which is * equal to or less than . NULL is returned is no key matches. */ REGPRM2 struct eb32_node *eb32_lookup_le(struct eb_root *root, u32 x) { struct eb32_node *node; eb_troot_t *troot; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { /* We reached a leaf, which means that the whole upper * parts were common. We will return either the current * node or its next one if the former is too small. */ node = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); if (node->key <= x) return node; /* return prev */ troot = node->node.leaf_p; break; } node = container_of(eb_untag(troot, EB_NODE), struct eb32_node, node.branches); if (node->node.bit < 0) { /* We're at the top of a dup tree. Either we got a * matching value and we return the rightmost node, or * we don't and we skip the whole subtree to return the * prev node before the subtree. Note that since we're * at the top of the dup tree, we can simply return the * prev node without first trying to escape from the * tree. */ if (node->key <= x) { troot = node->node.branches.b[EB_RGHT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_RGHT]; return container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); } /* return prev */ troot = node->node.node_p; break; } if (((x ^ node->key) >> node->node.bit) >= EB_NODE_BRANCHES) { /* No more common bits at all. Either this node is too * small and we need to get its highest value, or it is * too large, and we need to get the prev value. */ if ((node->key >> node->node.bit) < (x >> node->node.bit)) { troot = node->node.branches.b[EB_RGHT]; return eb32_entry(eb_walk_down(troot, EB_RGHT), struct eb32_node, node); } /* Further values will be too high here, so return the prev * unique node (if it exists). */ troot = node->node.node_p; break; } troot = node->node.branches.b[(x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } /* If we get here, it means we want to report previous node before the * current one which is not above. is already initialised to * the parent's branches. */ while (eb_gettag(troot) == EB_LEFT) { /* Walking up from left branch. We must ensure that we never * walk beyond root. */ if (unlikely(eb_clrtag((eb_untag(troot, EB_LEFT))->b[EB_RGHT]) == NULL)) return NULL; troot = (eb_root_to_node(eb_untag(troot, EB_LEFT)))->node_p; } /* Note that cannot be NULL at this stage */ troot = (eb_untag(troot, EB_RGHT))->b[EB_LEFT]; node = eb32_entry(eb_walk_down(troot, EB_RGHT), struct eb32_node, node); return node; } /* * Find the first occurrence of the lowest key in the tree , which is * equal to or greater than . NULL is returned is no key matches. */ REGPRM2 struct eb32_node *eb32_lookup_ge(struct eb_root *root, u32 x) { struct eb32_node *node; eb_troot_t *troot; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { /* We reached a leaf, which means that the whole upper * parts were common. We will return either the current * node or its next one if the former is too small. */ node = container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); if (node->key >= x) return node; /* return next */ troot = node->node.leaf_p; break; } node = container_of(eb_untag(troot, EB_NODE), struct eb32_node, node.branches); if (node->node.bit < 0) { /* We're at the top of a dup tree. Either we got a * matching value and we return the leftmost node, or * we don't and we skip the whole subtree to return the * next node after the subtree. Note that since we're * at the top of the dup tree, we can simply return the * next node without first trying to escape from the * tree. */ if (node->key >= x) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; return container_of(eb_untag(troot, EB_LEAF), struct eb32_node, node.branches); } /* return next */ troot = node->node.node_p; break; } if (((x ^ node->key) >> node->node.bit) >= EB_NODE_BRANCHES) { /* No more common bits at all. Either this node is too * large and we need to get its lowest value, or it is too * small, and we need to get the next value. */ if ((node->key >> node->node.bit) > (x >> node->node.bit)) { troot = node->node.branches.b[EB_LEFT]; return eb32_entry(eb_walk_down(troot, EB_LEFT), struct eb32_node, node); } /* Further values will be too low here, so return the next * unique node (if it exists). */ troot = node->node.node_p; break; } troot = node->node.branches.b[(x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } /* If we get here, it means we want to report next node after the * current one which is not below. is already initialised * to the parent's branches. */ while (eb_gettag(troot) != EB_LEFT) /* Walking up from right branch, so we cannot be below root */ troot = (eb_root_to_node(eb_untag(troot, EB_RGHT)))->node_p; /* Note that cannot be NULL at this stage */ troot = (eb_untag(troot, EB_LEFT))->b[EB_RGHT]; if (eb_clrtag(troot) == NULL) return NULL; node = eb32_entry(eb_walk_down(troot, EB_LEFT), struct eb32_node, node); return node; } ebtree/testebtree.c0000644000076400001440000001672611613243153014047 0ustar bernatusers#include #include #include #include #include "ebtree.h" #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) static inline struct timeval *tv_now(struct timeval *tv) { gettimeofday(tv, NULL); return tv; } static inline unsigned long tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2) { unsigned long ret; ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000; ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000; return ret; } static unsigned long long start, calibrate, end, cycles; EB32_TREE_HEAD(root); struct eb32_node *eb32_insert(struct eb32_node *root, struct eb32_node *new) { return __eb32_insert(root, new); } int eb32_delete(struct eb32_node *node) { return __eb_delete((struct eb_node *)node); } struct eb32_node *eb32_lookup(struct eb32_node *root, unsigned long x) { return __eb32_lookup(root, x); } unsigned long total_jumps = 0; static unsigned long rev32(unsigned long x) { x = ((x & 0xFFFF0000) >> 16) | ((x & 0x0000FFFF) << 16); x = ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8); x = ((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4); x = ((x & 0xCCCCCCCC) >> 2) | ((x & 0x33333333) << 2); x = ((x & 0xAAAAAAAA) >> 1) | ((x & 0x55555555) << 1); return x; } int main(int argc, char **argv) { char buffer[1024]; unsigned int total = 0; int i; unsigned long links_used = 0; unsigned long neighbours = 0; unsigned long long x; struct eb32_node *node, *lastnode; struct timeval t_start, t_random, t_insert, t_lookup, t_walk, t_move, t_delete; /* disable output buffering */ setbuf(stdout, NULL); if (argc < 2) { tv_now(&t_start); while (fgets(buffer, sizeof(buffer), stdin) != NULL) { char *ret = strchr(buffer, '\n'); if (ret) *ret = 0; //printf("read=%lld\n", x); x = atoll(buffer); total++; node = (struct eb32_node *)malloc(sizeof(*node)); node->val = x; eb32_insert(&root, node); } tv_now(&t_random); tv_now(&t_insert); } else { total = atol(argv[1]); /* preallocation */ tv_now(&t_start); printf("Timing %d random()+malloc... ", total); rdtscll(start); lastnode = NULL; for (i = 0; i < total; i++) { ////unsigned long long x = (i << 16) + ((random() & 63ULL) << 32) + (random() % 1000); //unsigned long l = (random() % 1000)*1000; // to emulate tv_usec based on milliseconds //unsigned long h = ((random() & 63ULL)<<8) + (i%100); // to emulate lots of close seconds ////unsigned long long x = ((unsigned long long)h << 32) + l; //unsigned long long x = ((unsigned long long)h << 16) + l; unsigned long x = random(); // triggers worst case cache patterns //x = i & 16383;// ^ (1 << (i&31));//(i < 32) ? (1 << i) : 1/*(i & 1023)*/; //x = 1UL << (i&31); //x = (i >> 10) << 20 | (i & 1023); x = ((i >> 10) << 20) + (i & 1023) * 3; //x = rev32(i); //x = (x >> 10) << 20 | (x & 1023); //x = (x >> 16) ^ (x << 16); //x = i; node = (struct eb32_node *)calloc(1,sizeof(*node)); node->val = x;//*x;//total-i-1;//*/(x>>10)&65535;//i&65535;//(x>>8)&65535;//rev32(i);//i&32767;//x;//i ^ (long)lastnode; node->node.leaf_p = (void *)lastnode; lastnode = node; } rdtscll(end); tv_now(&t_random); printf("%llu cycles/ent\n", (end - start)/total); printf("Timing %d insert... ", total); cycles = 0; for (i = 0; i < total; i++) { node = lastnode; lastnode = (void *)node->node.leaf_p; rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! eb32_insert(&root, node); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); if (!node->node.leaf_p) neighbours++; else if (node->node.bit) links_used++; } tv_now(&t_insert); printf("%llu cycles/ent\n", cycles/total); printf("%lu jumps during insertion = %llu jumps/1000 ins\n", total_jumps, (1000ULL*total_jumps)/total); } printf("Looking up %d entries... ", total); cycles = 0; for (i = 0; i < total; i++) { unsigned long long x = i;//random();//(random()>>10)&65535;//(i << 16) + ((random() & 63ULL) << 32) + (random() % 1000); rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! node = eb32_lookup(&root, x); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); if (node && (node->val != (int)x)) { printf("node = %p, wanted = %d, returned = %d\n", node, (int)x, node->val); } //if (!node) // printf("wanted = %d\n", (int)x); } tv_now(&t_lookup); printf("%llu cycles/ent\n", cycles/total); printf("Walking forwards %d entries... ", total); cycles = 0; node = eb_first(&root); while (node) { //printf("node = %p, node->val = 0x%08x, link_p=%p, leaf_p=%p, bit=%d, leaf_p->bit=%d\n", // node, node->val, node->node.link_p, node->node.leaf_p, node->node.bit, // node->node.leaf_p ? node->node.leaf_p->bit : -1); rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! node = eb_next(node); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); } printf("%llu cycles/ent\n", cycles/total); printf("Walking backwards %d entries... ", total); rdtscll(start); node = eb_last(&root); while (node) { //printf("node = %p, node->val = 0x%08x, link_p=%p, leaf_p=%p, bit=%d, leaf_p->bit=%d\n", // node, node->val, node->node.link_p, node->node.leaf_p, node->node.bit, // node->node.leaf_p ? node->node.leaf_p->bit : -1); node = eb_prev(node); } rdtscll(end); tv_now(&t_walk); printf("%llu cycles/ent\n", (end - start)/total); printf("Moving %d entries (2 times)... ", total); rdtscll(start); node = NULL; for (i=0; i<2 * total; i++) { struct eb32_node *next; if (!node) node = eb_first(&root); next = eb_next(node); //printf("moving node = %p, node->val = 0x%08x, link_p=%p, leaf_p=%p, bit=%d, leaf_p->bit=%d\n", // node, node->val, node->node.link_p, node->node.leaf_p, node->node.bit, // node->node.leaf_p ? node->node.leaf_p->bit : -1); eb32_delete(node); node->val += 1000000; // jump in the future eb32_insert(&root, node); node = next; } rdtscll(end); printf("%llu cycles/ent\n", (end - start)/i); tv_now(&t_move); printf("Deleting %d entries... ", total); node = eb_first(&root); rdtscll(start); while (node) { struct eb32_node *next; next = eb_next(node); //printf("deleting node = %p, node->val = 0x%08x, link_p=%p, leaf_p=%p, bit=%d, leaf_p->bit=%d\n", // node, node->val, node->node.link_p, node->node.leaf_p, node->node.bit, // node->node.leaf_p ? node->node.leaf_p->bit : -1); eb32_delete(node); node = next; } rdtscll(end); tv_now(&t_delete); printf("%llu cycles/ent\n", (end - start)/total); node = eb_first(&root); printf("eb_first now returns %p\n", node); printf("total=%u, links=%lu, neighbours=%lu entries, total_jumps=%lu\n", total, links_used, neighbours, total_jumps); printf("random+malloc =%lu ms\n", tv_ms_elapsed(&t_start, &t_random)); printf("insert =%lu ms\n", tv_ms_elapsed(&t_random, &t_insert)); printf("lookup =%lu ms\n", tv_ms_elapsed(&t_insert, &t_lookup)); printf("walk =%lu ms\n", tv_ms_elapsed(&t_lookup, &t_walk)); printf("move =%lu ms\n", tv_ms_elapsed(&t_walk, &t_move)); printf("delete =%lu ms\n", tv_ms_elapsed(&t_move, &t_delete)); return 0; } ebtree/ebsttree.c0000644000076400001440000000323711613243153013507 0ustar bernatusers/* * Elastic Binary Trees - exported functions for String data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult ebsttree.h for more details about those functions */ #include "ebsttree.h" /* Find the first occurence of a zero-terminated string in the tree . * It's the caller's reponsibility to use this function only on trees which * only contain zero-terminated strings. If none can be found, return NULL. */ REGPRM2 struct ebmb_node *ebst_lookup(struct eb_root *root, const char *x) { return __ebst_lookup(root, x); } /* Insert ebmb_node into subtree starting at node root . Only * new->key needs be set with the zero-terminated string key. The ebmb_node is * returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * caller is responsible for properly terminating the key with a zero. */ REGPRM2 struct ebmb_node *ebst_insert(struct eb_root *root, struct ebmb_node *new) { return __ebst_insert(root, new); } ebtree/eb64tree.h0000644000076400001440000004434111613243153013320 0ustar bernatusers/* * Elastic Binary Trees - macros and structures for operations on 64bit nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _EB64TREE_H #define _EB64TREE_H #include "ebtree.h" /* Return the structure of type whose member points to */ #define eb64_entry(ptr, type, member) container_of(ptr, type, member) #define EB64_ROOT EB_ROOT #define EB64_TREE_HEAD EB_TREE_HEAD /* These types may sometimes already be defined */ typedef unsigned long long u64; typedef signed long long s64; /* This structure carries a node, a leaf, and a key. It must start with the * eb_node so that it can be cast into an eb_node. We could also have put some * sort of transparent union here to reduce the indirection level, but the fact * is, the end user is not meant to manipulate internals, so this is pointless. */ struct eb64_node { struct eb_node node; /* the tree node, must be at the beginning */ u64 key; }; /* * Exported functions and macros. * Many of them are always inlined because they are extremely small, and * are generally called at most once or twice in a program. */ /* Return leftmost node in the tree, or NULL if none */ static inline struct eb64_node *eb64_first(struct eb_root *root) { return eb64_entry(eb_first(root), struct eb64_node, node); } /* Return rightmost node in the tree, or NULL if none */ static inline struct eb64_node *eb64_last(struct eb_root *root) { return eb64_entry(eb_last(root), struct eb64_node, node); } /* Return next node in the tree, or NULL if none */ static inline struct eb64_node *eb64_next(struct eb64_node *eb64) { return eb64_entry(eb_next(&eb64->node), struct eb64_node, node); } /* Return previous node in the tree, or NULL if none */ static inline struct eb64_node *eb64_prev(struct eb64_node *eb64) { return eb64_entry(eb_prev(&eb64->node), struct eb64_node, node); } /* Return next node in the tree, skipping duplicates, or NULL if none */ static inline struct eb64_node *eb64_next_unique(struct eb64_node *eb64) { return eb64_entry(eb_next_unique(&eb64->node), struct eb64_node, node); } /* Return previous node in the tree, skipping duplicates, or NULL if none */ static inline struct eb64_node *eb64_prev_unique(struct eb64_node *eb64) { return eb64_entry(eb_prev_unique(&eb64->node), struct eb64_node, node); } /* Delete node from the tree if it was linked in. Mark the node unused. Note * that this function relies on a non-inlined generic function: eb_delete. */ static inline void eb64_delete(struct eb64_node *eb64) { eb_delete(&eb64->node); } /* * The following functions are not inlined by default. They are declared * in eb64tree.c, which simply relies on their inline version. */ REGPRM2 struct eb64_node *eb64_lookup(struct eb_root *root, u64 x); REGPRM2 struct eb64_node *eb64i_lookup(struct eb_root *root, s64 x); REGPRM2 struct eb64_node *eb64_lookup_le(struct eb_root *root, u64 x); REGPRM2 struct eb64_node *eb64_lookup_ge(struct eb_root *root, u64 x); REGPRM2 struct eb64_node *eb64_insert(struct eb_root *root, struct eb64_node *new); REGPRM2 struct eb64_node *eb64i_insert(struct eb_root *root, struct eb64_node *new); /* * The following functions are less likely to be used directly, because their * code is larger. The non-inlined version is preferred. */ /* Delete node from the tree if it was linked in. Mark the node unused. */ static forceinline void __eb64_delete(struct eb64_node *eb64) { __eb_delete(&eb64->node); } /* * Find the first occurence of a key in the tree . If none can be * found, return NULL. */ static forceinline struct eb64_node *__eb64_lookup(struct eb_root *root, u64 x) { struct eb64_node *node; eb_troot_t *troot; u64 y; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); if (node->key == x) return node; else return NULL; } node = container_of(eb_untag(troot, EB_NODE), struct eb64_node, node.branches); y = node->key ^ x; if (!y) { /* Either we found the node which holds the key, or * we have a dup tree. In the later case, we have to * walk it down left to get the first entry. */ if (node->node.bit < 0) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); } return node; } if ((y >> node->node.bit) >= EB_NODE_BRANCHES) return NULL; /* no more common bits */ troot = node->node.branches.b[(x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } } /* * Find the first occurence of a signed key in the tree . If none can * be found, return NULL. */ static forceinline struct eb64_node *__eb64i_lookup(struct eb_root *root, s64 x) { struct eb64_node *node; eb_troot_t *troot; u64 key = x ^ (1ULL << 63); u64 y; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); if (node->key == (u64)x) return node; else return NULL; } node = container_of(eb_untag(troot, EB_NODE), struct eb64_node, node.branches); y = node->key ^ x; if (!y) { /* Either we found the node which holds the key, or * we have a dup tree. In the later case, we have to * walk it down left to get the first entry. */ if (node->node.bit < 0) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); } return node; } if ((y >> node->node.bit) >= EB_NODE_BRANCHES) return NULL; /* no more common bits */ troot = node->node.branches.b[(key >> node->node.bit) & EB_NODE_BRANCH_MASK]; } } /* Insert eb64_node into subtree starting at node 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 forceinline struct eb64_node * __eb64_insert(struct eb_root *root, struct eb64_node *new) { struct eb64_node *old; unsigned int side; eb_troot_t *troot; u64 newkey; /* caching the key saves approximately one cycle */ eb_troot_t *root_right = root; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. carries the key being inserted. */ newkey = new->key; while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_leaf; old = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_leaf = eb_dotag(&old->node.branches, EB_LEAF); new->node.node_p = old->node.leaf_p; /* Right here, we have 3 possibilities : - the tree does not contain the key, and we have new->key < old->key. We insert new above old, on the left ; - the tree does not contain the key, and we have new->key > old->key. We insert new above old, on the right ; - the tree does contain the key, which implies it is alone. We add the new key next to it as a first duplicate. The last two cases can easily be partially merged. */ if (new->key < old->key) { new->node.leaf_p = new_left; old->node.leaf_p = new_rght; 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; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; if (new->key == old->key) { new->node.bit = -1; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } } break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct eb64_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. */ if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { /* The tree did not contain the key, so we insert before the node * , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. */ eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_node; new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_node = eb_dotag(&old->node.branches, EB_NODE); new->node.node_p = old->node.node_p; if (new->key < old->key) { new->node.leaf_p = new_left; old->node.node_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_node; } else if (new->key > old->key) { old->node.node_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_node; new->node.branches.b[EB_RGHT] = new_leaf; } else { struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct eb64_node, node); } break; } /* walk down */ root = &old->node.branches; #if BITS_PER_LONG >= 64 side = (newkey >> old_node_bit) & EB_NODE_BRANCH_MASK; #else side = newkey; side >>= old_node_bit; if (old_node_bit >= 32) { side = newkey >> 32; side >>= old_node_bit & 0x1F; } side &= EB_NODE_BRANCH_MASK; #endif troot = root->b[side]; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ /* We need the common higher bits between new->key and old->key. * What differences are there between new->key and the node here ? * NOTE that bit(new) is always < bit(root) because highest * bit of new->key and old->key are identical here (otherwise they * would sit on different branches). */ // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 new->node.bit = fls64(new->key ^ old->key) - EB_NODE_BITS; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } /* Insert eb64_node into subtree starting at node root , using * signed keys. 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 forceinline struct eb64_node * __eb64i_insert(struct eb_root *root, struct eb64_node *new) { struct eb64_node *old; unsigned int side; eb_troot_t *troot; u64 newkey; /* caching the key saves approximately one cycle */ eb_troot_t *root_right = root; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. carries a high bit shift of the key being * inserted in order to have negative keys stored before positive * ones. */ newkey = new->key ^ (1ULL << 63); while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_leaf; old = container_of(eb_untag(troot, EB_LEAF), struct eb64_node, node.branches); new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_leaf = eb_dotag(&old->node.branches, EB_LEAF); new->node.node_p = old->node.leaf_p; /* Right here, we have 3 possibilities : - the tree does not contain the key, and we have new->key < old->key. We insert new above old, on the left ; - the tree does not contain the key, and we have new->key > old->key. We insert new above old, on the right ; - the tree does contain the key, which implies it is alone. We add the new key next to it as a first duplicate. The last two cases can easily be partially merged. */ if ((s64)new->key < (s64)old->key) { new->node.leaf_p = new_left; old->node.leaf_p = new_rght; 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; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; if (new->key == old->key) { new->node.bit = -1; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } } break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct eb64_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. */ if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { /* The tree did not contain the key, so we insert before the node * , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. */ eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_node; new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_node = eb_dotag(&old->node.branches, EB_NODE); new->node.node_p = old->node.node_p; if ((s64)new->key < (s64)old->key) { new->node.leaf_p = new_left; old->node.node_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_node; } else if ((s64)new->key > (s64)old->key) { old->node.node_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_node; new->node.branches.b[EB_RGHT] = new_leaf; } else { struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct eb64_node, node); } break; } /* walk down */ root = &old->node.branches; #if BITS_PER_LONG >= 64 side = (newkey >> old_node_bit) & EB_NODE_BRANCH_MASK; #else side = newkey; side >>= old_node_bit; if (old_node_bit >= 32) { side = newkey >> 32; side >>= old_node_bit & 0x1F; } side &= EB_NODE_BRANCH_MASK; #endif troot = root->b[side]; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ /* We need the common higher bits between new->key and old->key. * What differences are there between new->key and the node here ? * NOTE that bit(new) is always < bit(root) because highest * bit of new->key and old->key are identical here (otherwise they * would sit on different branches). */ // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 new->node.bit = fls64(new->key ^ old->key) - EB_NODE_BITS; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } #endif /* _EB64_TREE_H */ ebtree/LICENSE0000644000076400001440000006350411613243153012536 0ustar bernatusers GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ebtree/ebistree.c0000644000076400001440000000325011613243153013467 0ustar bernatusers/* * Elastic Binary Trees - exported functions for Indirect String data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult ebistree.h for more details about those functions */ #include "ebistree.h" /* Find the first occurence of a zero-terminated string in the tree . * It's the caller's reponsibility to use this function only on trees which * only contain zero-terminated strings. If none can be found, return NULL. */ REGPRM2 struct ebpt_node *ebis_lookup(struct eb_root *root, const char *x) { return __ebis_lookup(root, x); } /* Insert ebpt_node into subtree starting at node root . Only * new->key needs be set with the zero-terminated string key. The ebpt_node is * returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * caller is responsible for properly terminating the key with a zero. */ REGPRM2 struct ebpt_node *ebis_insert(struct eb_root *root, struct ebpt_node *new) { return __ebis_insert(root, new); } ebtree/VERSION0000644000076400001440000000000611613243153012565 0ustar bernatusers6.0.6 ebtree/ebpttree.c0000644000076400001440000001543211613243153013504 0ustar bernatusers/* * Elastic Binary Trees - exported functions for operations on pointer nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Consult ebpttree.h for more details about those functions */ #include "ebpttree.h" REGPRM2 struct ebpt_node *ebpt_insert(struct eb_root *root, struct ebpt_node *new) { return __ebpt_insert(root, new); } REGPRM2 struct ebpt_node *ebpt_lookup(struct eb_root *root, void *x) { return __ebpt_lookup(root, x); } /* * Find the last occurrence of the highest key in the tree , which is * equal to or less than . NULL is returned is no key matches. */ REGPRM2 struct ebpt_node *ebpt_lookup_le(struct eb_root *root, void *x) { struct ebpt_node *node; eb_troot_t *troot; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { /* We reached a leaf, which means that the whole upper * parts were common. We will return either the current * node or its next one if the former is too small. */ node = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); if (node->key <= x) return node; /* return prev */ troot = node->node.leaf_p; break; } node = container_of(eb_untag(troot, EB_NODE), struct ebpt_node, node.branches); if (node->node.bit < 0) { /* We're at the top of a dup tree. Either we got a * matching value and we return the rightmost node, or * we don't and we skip the whole subtree to return the * prev node before the subtree. Note that since we're * at the top of the dup tree, we can simply return the * prev node without first trying to escape from the * tree. */ if (node->key <= x) { troot = node->node.branches.b[EB_RGHT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_RGHT]; return container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); } /* return prev */ troot = node->node.node_p; break; } if ((((ptr_t)x ^ (ptr_t)node->key) >> node->node.bit) >= EB_NODE_BRANCHES) { /* No more common bits at all. Either this node is too * small and we need to get its highest value, or it is * too large, and we need to get the prev value. */ if (((ptr_t)node->key >> node->node.bit) < ((ptr_t)x >> node->node.bit)) { troot = node->node.branches.b[EB_RGHT]; return ebpt_entry(eb_walk_down(troot, EB_RGHT), struct ebpt_node, node); } /* Further values will be too high here, so return the prev * unique node (if it exists). */ troot = node->node.node_p; break; } troot = node->node.branches.b[((ptr_t)x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } /* If we get here, it means we want to report previous node before the * current one which is not above. is already initialised to * the parent's branches. */ while (eb_gettag(troot) == EB_LEFT) { /* Walking up from left branch. We must ensure that we never * walk beyond root. */ if (unlikely(eb_clrtag((eb_untag(troot, EB_LEFT))->b[EB_RGHT]) == NULL)) return NULL; troot = (eb_root_to_node(eb_untag(troot, EB_LEFT)))->node_p; } /* Note that cannot be NULL at this stage */ troot = (eb_untag(troot, EB_RGHT))->b[EB_LEFT]; node = ebpt_entry(eb_walk_down(troot, EB_RGHT), struct ebpt_node, node); return node; } /* * Find the first occurrence of the lowest key in the tree , which is * equal to or greater than . NULL is returned is no key matches. */ REGPRM2 struct ebpt_node *ebpt_lookup_ge(struct eb_root *root, void *x) { struct ebpt_node *node; eb_troot_t *troot; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { /* We reached a leaf, which means that the whole upper * parts were common. We will return either the current * node or its next one if the former is too small. */ node = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); if (node->key >= x) return node; /* return next */ troot = node->node.leaf_p; break; } node = container_of(eb_untag(troot, EB_NODE), struct ebpt_node, node.branches); if (node->node.bit < 0) { /* We're at the top of a dup tree. Either we got a * matching value and we return the leftmost node, or * we don't and we skip the whole subtree to return the * next node after the subtree. Note that since we're * at the top of the dup tree, we can simply return the * next node without first trying to escape from the * tree. */ if (node->key >= x) { troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; return container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); } /* return next */ troot = node->node.node_p; break; } if ((((ptr_t)x ^ (ptr_t)node->key) >> node->node.bit) >= EB_NODE_BRANCHES) { /* No more common bits at all. Either this node is too * large and we need to get its lowest value, or it is too * small, and we need to get the next value. */ if (((ptr_t)node->key >> node->node.bit) > ((ptr_t)x >> node->node.bit)) { troot = node->node.branches.b[EB_LEFT]; return ebpt_entry(eb_walk_down(troot, EB_LEFT), struct ebpt_node, node); } /* Further values will be too low here, so return the next * unique node (if it exists). */ troot = node->node.node_p; break; } troot = node->node.branches.b[((ptr_t)x >> node->node.bit) & EB_NODE_BRANCH_MASK]; } /* If we get here, it means we want to report next node after the * current one which is not below. is already initialised * to the parent's branches. */ while (eb_gettag(troot) != EB_LEFT) /* Walking up from right branch, so we cannot be below root */ troot = (eb_root_to_node(eb_untag(troot, EB_RGHT)))->node_p; /* Note that cannot be NULL at this stage */ troot = (eb_untag(troot, EB_LEFT))->b[EB_RGHT]; if (eb_clrtag(troot) == NULL) return NULL; node = ebpt_entry(eb_walk_down(troot, EB_LEFT), struct ebpt_node, node); return node; } ebtree/test32.c0000644000076400001440000000245311613243153013015 0ustar bernatusers#include #include #include #include "eb32tree.h" #ifdef DEBUG #define DPRINTF printf #else #define DPRINTF(a, ...) #endif int main(int argc, char **argv) { unsigned long long x; struct eb_root e32 = EB_ROOT; struct eb32_node *node; char buffer[1024]; /* disable output buffering */ setbuf(stdout, NULL); if (argc > 1 && strcmp(argv[1], "-h") == 0) { fprintf(stderr, "Usage: %s [val...]\n", argv[0]); exit(1); } argv++; argc--; while (argc >= 1) { char *ret = strchr(*argv, '\n'); if (ret) *ret = 0; x = atoll(*argv); node = calloc(1, sizeof(*node)); node->key = x; eb32_insert(&e32, node); argv++; argc--; } printf("Dump of command line values :\n"); node = eb32_first(&e32); while (node) { printf("node %p = %d\n", node, node->key); node = eb32_next(node); } printf("Now enter lookup values, one per line.\n"); while (fgets(buffer, sizeof(buffer), stdin) != NULL) { char *ret = strchr(buffer, '\n'); if (ret) *ret = 0; x = atoll(buffer); node = eb32_lookup(&e32, x); printf("eq: node=%p, val=%d\n", node, node?node->key:0); node = eb32_lookup_le(&e32, x); printf("le: node=%p, val=%d\n", node, node?node->key:0); node = eb32_lookup_ge(&e32, x); printf("ge: node=%p, val=%d\n", node, node?node->key:0); } return 0; } ebtree/testtree64.c0000644000076400001440000002127211613243153013702 0ustar bernatusers#include #include #include #include #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) static inline struct timeval *tv_now(struct timeval *tv) { gettimeofday(tv, NULL); return tv; } static inline unsigned long tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2) { unsigned long ret; ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000; ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000; return ret; } /****************************************************************************/ #ifdef USE_RBTREE #include "rbtree.h" struct task { struct rb_node rb_node; struct rb_root *wq; long long expire; void *data; char task_data[200]; }; struct rb_root wait_queue = RB_ROOT; static inline int time_compare(struct task *task1, struct task *task2) { return (task1->expire > task2->expire); } static inline void __rb_insert_task_queue(struct task *newtask) { struct rb_node **p = &newtask->wq->rb_node; struct rb_node *parent = NULL; struct task * task; while(*p) { parent = *p; task = rb_entry(parent, struct task, rb_node); if (time_compare(task, newtask)) p = &(*p)->rb_left; else p = &(*p)->rb_right; } rb_link_node(&newtask->rb_node, parent, p); } static inline void rb_insert_task_queue(struct task *newtask) { __rb_insert_task_queue(newtask); rb_insert_color(&newtask->rb_node, newtask->wq); } #define tree_node rb_node #define insert_task_queue(task) rb_insert_task_queue(task) #define tree_first(root) rb_first(root) #define tree_last(root) rb_last(root) #define tree_next(node) rb_next(node) #define tree_prev(node) rb_prev(node) #define tree_erase(node, root) rb_erase(node, root) #define tree_entry(node) rb_entry((node), struct task, rb_node) /****************************************************************************/ #else #include "eb64tree.h" struct task { struct eb64_node eb_node; struct eb_root *wq; void *data; char task_data[196]; }; #define expire eb_node.key struct eb_root wait_queue = EB_ROOT; #define tree_node eb64_node #define tree_first(root) eb64_first(root) #define tree_last(root) eb64_last(root) #define tree_next(node) eb64_next(node) #define tree_prev(node) eb64_prev(node) #define tree_entry(node) eb64_entry((node), struct task, eb_node) #define insert_task_queue(task) __eb64_insert((task)->wq, &task->eb_node) #define tree_lookup(root, x) __eb64_lookup(root, x) #define tree_erase(node, root) __eb64_delete(node); #endif /****************************************************************************/ unsigned long total_jumps = 0; int main(int argc, char **argv) { char buffer[1024]; unsigned int total = 0; long long i; unsigned long links_used = 0; unsigned long neighbours = 0; unsigned long long x; struct task *task, *lasttask; struct tree_node *node; struct timeval t_start, t_random, t_insert, t_lookup, t_walk, t_move, t_delete; static unsigned long long start, calibrate, end, cycles, cycles2, cycles3; /* disable output buffering */ setbuf(stdout, NULL); printf("Sizeof struct task=%d\n", sizeof(struct task)); cycles = 0; if (argc < 2) { tv_now(&t_start); while (fgets(buffer, sizeof(buffer), stdin) != NULL) { char *ret = strchr(buffer, '\n'); if (ret) *ret = 0; //printf("read=%lld\n", x); x = atoll(buffer); total++; task = (struct task *)calloc(1, sizeof(*task)); task->expire = x; task->wq = &wait_queue; insert_task_queue(task); } tv_now(&t_random); tv_now(&t_insert); } else { total = atol(argv[1]); /* preallocation */ tv_now(&t_start); //printf("Timing %d random()+malloc... ", total); rdtscll(start); lasttask = NULL; for (i = 0; i < total; i++) { ////unsigned long long x = (i << 16) + ((random() & 63ULL) << 32) + (random() % 1000); //unsigned long l = (random() % 1000)*1000; // to emulate tv_usec based on milliseconds //unsigned long h = ((random() & 63ULL)<<8) + (i%100); // to emulate lots of close seconds ////unsigned long long x = ((unsigned long long)h << 32) + l; //unsigned long long x = ((unsigned long long)h << 16) + l; unsigned long j, x; /* makes a worst case with high bits moving fast */ x = i; for (j = 0; j < 32; j++) x ^= (1UL << (32-j)) >> (i%(j+1)); //printf("x=%08x\n", x); //x=((1<<31) >> (i%32)) ^ ((1<<30) >> (i%31)) ^ ((1<<29) >> (i%30)) ^ ((1<<28) >> (i%29)) ^ //((1<<27) >> (i%28)) ^ ((1<<26) >> (i%27)) ^ ((1<<31) >> (i%26)) ^ ((1<<31) >> (i%25)) ^ //((1<<31) >> (i%24)) ^ ((1<<31) >> (i%23)) ^ ((1<<31) >> (i%22)) ^ ((1<<31) >> (i%21)) ^ //0; //x = i & 16383;// ^ (1 << (i&31));//(i < 32) ? (1 << i) : 1/*(i & 1023)*/; //x = 1UL << (i&31); //x = (i >> 10) << 20 | (i & 1023); //x = rev32(i); //x = (x >> 10) << 20 | (x & 1023); //x = (x >> 16) ^ (x << 16); //x = ((i >> 10) << 20) + (i & 1023) * 3; //x = random(); //x = i; //x = total-i; //x = rev32(i); //x = random() & 1023; // simulates some sparse groups of values like with a scheduler x = (i / 1000) * 50000 + (i % 1000) * 4 - 1500; //x = x + (1ULL << 63); x ^= (1ULL << i&0x3F); //x = i & -256; task = (struct task *)calloc(1,sizeof(*task)); task->expire = x;//*x;//total-i-1;//*/(x>>10)&65535;//i&65535;//(x>>8)&65535;//rev32(i);//i&32767;//x;//i ^ (long)lasttask; task->wq = &wait_queue; task->data = (void *)lasttask; lasttask = task; } rdtscll(end); tv_now(&t_random); //printf("%llu cycles/ent\n", (end - start)/total); printf("Timing %d insert... ", total); cycles = 0; task = lasttask; for (i = 0; i < total; i++) { rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! insert_task_queue(task); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); task = task->data; } tv_now(&t_insert); printf("%llu cycles/ent avg, last = %llu cycles\n", cycles/total, (end - calibrate) - (calibrate - start)); #if 0 && defined(tree_lookup) printf("Timing %d lookups... ", total); cycles3 = 0; task = lasttask; for (i = 0; i < total; i++) { rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! node = tree_lookup(&wait_queue, task->expire); rdtscll(end); cycles3 += (end - calibrate) - (calibrate - start); if (!node) *(int*)0=0; if (tree_entry(node)->expire != task->expire) *(int*)0 = 0; task = task->data; } tv_now(&t_lookup); printf("%llu cycles/ent avg, last = %llu cycles\n", cycles3/total, (end - calibrate) - (calibrate - start)); #else tv_now(&t_lookup); #endif } cycles2 = cycles; printf("Walking through %d entries... ", total); node = tree_first(&wait_queue); cycles = 0; rdtscll(start); while (node) { node = tree_next(node); } rdtscll(end); cycles = end - start; tv_now(&t_walk); printf("%llu cycles/ent\n", cycles/total); cycles2 += cycles; tv_now(&t_move); printf("Deleting %d entries... ", total); node = tree_first(&wait_queue); lasttask = tree_entry(node); cycles = 0; rdtscll(start); while (node) { struct tree_node *next; next = tree_next(node); task = tree_entry(node); //printf("deleting node = %p, node->val = 0x%08x, link_p=%p, leaf_p=%p, bit=%d, leaf_p->bit=%d\n", // node, node->val, node->node.link_p, node->node.leaf_p, node->node.bit, // node->node.leaf_p ? node->node.leaf_p->bit : -1); //if (task->expire < lasttask->expire) // printf("old=%p, new=%p, o_exp=%d, n_exp=%d\n", lasttask, task, lasttask->expire, task->expire); rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! tree_erase(node, task->wq); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); node = next; lasttask = task; } rdtscll(end); tv_now(&t_delete); printf("%llu cycles/ent\n", cycles/total); printf("Total for %d entries : %llu cycles/ent = %llu kilocycles\n", total, (cycles+cycles2)/total, (cycles+cycles2)/1000); node = tree_first(&wait_queue); if (node) printf("ERROR!! rb_first now returns %p\n", node); //printf("total=%u, links=%lu, neighbours=%lu entries, total_jumps=%lu\n", total, links_used, neighbours, total_jumps); //printf("random+malloc =%lu ms\n", tv_ms_elapsed(&t_start, &t_random)); //printf("insert =%lu ms\n", tv_ms_elapsed(&t_random, &t_insert)); //printf("delete =%lu ms\n", tv_ms_elapsed(&t_move, &t_delete)); return 0; } ebtree/ebistree.h0000644000076400001440000002461611613243153013505 0ustar bernatusers/* * Elastic Binary Trees - macros to manipulate Indirect String data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* These functions and macros rely on Multi-Byte nodes */ #include #include "ebtree.h" #include "ebpttree.h" #include "ebimtree.h" /* These functions and macros rely on Pointer nodes and use the entry as * a pointer to an indirect key. Most operations are performed using ebpt_*. */ /* The following functions are not inlined by default. They are declared * in ebistree.c, which simply relies on their inline version. */ REGPRM2 struct ebpt_node *ebis_lookup(struct eb_root *root, const char *x); REGPRM2 struct ebpt_node *ebis_insert(struct eb_root *root, struct ebpt_node *new); /* Find the first occurence of a length string in the tree . * It's the caller's reponsibility to use this function only on trees which * only contain zero-terminated strings, and that no null character is present * in string in the first chars. If none can be found, return NULL. */ static forceinline struct ebpt_node * ebis_lookup_len(struct eb_root *root, const char *x, unsigned int len) { struct ebpt_node *node; node = ebim_lookup(root, x, len); if (!node || ((const char *)node->key)[len] != 0) return NULL; return node; } /* Find the first occurence of a zero-terminated string in the tree . * It's the caller's reponsibility to use this function only on trees which * only contain zero-terminated strings. If none can be found, return NULL. */ static forceinline struct ebpt_node *__ebis_lookup(struct eb_root *root, const void *x) { struct ebpt_node *node; eb_troot_t *troot; int bit; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; bit = 0; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); if (strcmp(node->key, x) == 0) return node; else return NULL; } node = container_of(eb_untag(troot, EB_NODE), struct ebpt_node, node.branches); node_bit = node->node.bit; if (node_bit < 0) { /* We have a dup tree now. Either it's for the same * value, and we walk down left, or it's a different * one and we don't have our key. */ if (strcmp(node->key, x) != 0) return NULL; troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); return node; } /* OK, normal data node, let's walk down but don't compare data * if we already reached the end of the key. */ if (likely(bit >= 0)) { bit = string_equal_bits(x, node->key, bit); if (likely(bit < node_bit)) { if (bit >= 0) return NULL; /* no more common bits */ /* bit < 0 : we reached the end of the key. If we * are in a tree with unique keys, we can return * this node. Otherwise we have to walk it down * and stop comparing bits. */ if (eb_gettag(root->b[EB_RGHT])) return node; } } troot = node->node.branches.b[(((unsigned char*)x)[node_bit >> 3] >> (~node_bit & 7)) & 1]; } } /* Insert ebpt_node into subtree starting at node root . Only * new->key needs be set with the zero-terminated string key. The ebpt_node is * returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * caller is responsible for properly terminating the key with a zero. */ static forceinline struct ebpt_node * __ebis_insert(struct eb_root *root, struct ebpt_node *new) { struct ebpt_node *old; unsigned int side; eb_troot_t *troot; eb_troot_t *root_right = root; int diff; int bit; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. */ bit = 0; while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_leaf; old = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_leaf = eb_dotag(&old->node.branches, EB_LEAF); new->node.node_p = old->node.leaf_p; /* Right here, we have 3 possibilities : * - the tree does not contain the key, and we have * new->key < old->key. We insert new above old, on * the left ; * * - the tree does not contain the key, and we have * new->key > old->key. We insert new above old, on * the right ; * * - the tree does contain the key, which implies it * is alone. We add the new key next to it as a * first duplicate. * * The last two cases can easily be partially merged. */ if (bit >= 0) bit = string_equal_bits(new->key, old->key, bit); if (bit < 0) { /* key was already there */ /* we may refuse to duplicate this key if the tree is * tagged as containing only unique keys. */ if (eb_gettag(root_right)) return old; /* new arbitrarily goes to the right and tops the dup tree */ old->node.leaf_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; new->node.bit = -1; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } diff = cmp_bits(new->key, old->key, bit); if (diff < 0) { /* new->key < old->key, new takes the left */ new->node.leaf_p = new_left; old->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_leaf; } else { /* new->key > old->key, new takes the right */ old->node.leaf_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; } break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct ebpt_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. Note: we can compare more bits than * the current node's because as long as they are identical, we * know we descend along the correct side. */ if (bit >= 0 && (bit < old_node_bit || old_node_bit < 0)) bit = string_equal_bits(new->key, old->key, bit); if (unlikely(bit < 0)) { /* Perfect match, we must only stop on head of dup tree * or walk down to a leaf. */ if (old_node_bit < 0) { /* We know here that string_equal_bits matched all * bits and that we're on top of a dup tree, then * we can perform the dup insertion and return. */ struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct ebpt_node, node); } /* OK so let's walk down */ } else if (bit < old_node_bit || old_node_bit < 0) { /* The tree did not contain the key, or we stopped on top of a dup * tree, possibly containing the key. In the former case, we insert * before the node , and set ->bit to designate the lowest * bit position in which applies to ->branches.b[]. In the later * case, we add the key to the existing dup tree. Note that we cannot * enter here if we match an intermediate node's key that is not the * head of a dup tree. */ eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_node; new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_node = eb_dotag(&old->node.branches, EB_NODE); new->node.node_p = old->node.node_p; /* we can never match all bits here */ diff = cmp_bits(new->key, old->key, bit); if (diff < 0) { new->node.leaf_p = new_left; old->node.node_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_node; } else { old->node.node_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_node; new->node.branches.b[EB_RGHT] = new_leaf; } break; } /* walk down */ root = &old->node.branches; side = (((unsigned char *)new->key)[old_node_bit >> 3] >> (~old_node_bit & 7)) & 1; troot = root->b[side]; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ /* We need the common higher bits between new->key and old->key. * This number of bits is already in . * NOTE: we can't get here whit bit < 0 since we found a dup ! */ new->node.bit = bit; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } ebtree/test64.c0000644000076400001440000000246311613243153013023 0ustar bernatusers#include #include #include #include "eb64tree.h" #ifdef DEBUG #define DPRINTF printf #else #define DPRINTF(a, ...) #endif int main(int argc, char **argv) { unsigned long long x; struct eb_root e64 = EB_ROOT; struct eb64_node *node; char buffer[1024]; /* disable output buffering */ setbuf(stdout, NULL); if (argc > 1 && strcmp(argv[1], "-h") == 0) { fprintf(stderr, "Usage: %s [val...]\n", argv[0]); exit(1); } argv++; argc--; while (argc >= 1) { char *ret = strchr(*argv, '\n'); if (ret) *ret = 0; x = atoll(*argv); node = calloc(1, sizeof(*node)); node->key = x; eb64_insert(&e64, node); argv++; argc--; } printf("Dump of command line values :\n"); node = eb64_first(&e64); while (node) { printf("node %p = %lld\n", node, node->key); node = eb64_next(node); } printf("Now enter lookup values, one per line.\n"); while (fgets(buffer, sizeof(buffer), stdin) != NULL) { char *ret = strchr(buffer, '\n'); if (ret) *ret = 0; x = atoll(buffer); node = eb64_lookup(&e64, x); printf("eq: node=%p, val=%lld\n", node, node?node->key:0); node = eb64_lookup_le(&e64, x); printf("le: node=%p, val=%lld\n", node, node?node->key:0); node = eb64_lookup_ge(&e64, x); printf("ge: node=%p, val=%lld\n", node, node?node->key:0); } return 0; } ebtree/testtree.c0000644000076400001440000002505611613243153013534 0ustar bernatusers#include #include #include #include #ifdef DEBUG #define DPRINTF printf #else #define DPRINTF(a, ...) #endif #ifdef __i386__ #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) #elif __x86_64__ #define rdtscll(val) do { \ unsigned int __a,__d; \ asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \ (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \ } while(0) #else #define rdtscll(val) #endif static inline struct timeval *tv_now(struct timeval *tv) { gettimeofday(tv, NULL); return tv; } static inline unsigned long tv_ms_elapsed(const struct timeval *tv1, const struct timeval *tv2) { unsigned long ret; ret = ((signed long)(tv2->tv_sec - tv1->tv_sec)) * 1000; ret += ((signed long)(tv2->tv_usec - tv1->tv_usec)) / 1000; return ret; } /****************************************************************************/ #ifdef USE_RBTREE #include "rbtree.h" struct task { struct rb_node rb_node; struct rb_root *wq; long expire; void *data; char task_data[200]; }; struct rb_root wait_queue = RB_ROOT; static inline int time_compare(struct task *task1, struct task *task2) { return (task1->expire > task2->expire); } static inline void __rb_insert_task_queue(struct task *newtask) { struct rb_node **p = &newtask->wq->rb_node; struct rb_node *parent = NULL; struct task * task; while(*p) { parent = *p; task = rb_entry(parent, struct task, rb_node); if (time_compare(task, newtask)) p = &(*p)->rb_left; else p = &(*p)->rb_right; } rb_link_node(&newtask->rb_node, parent, p); } static inline void rb_insert_task_queue(struct task *newtask) { __rb_insert_task_queue(newtask); rb_insert_color(&newtask->rb_node, newtask->wq); } #define tree_node rb_node #define insert_task_queue(task) rb_insert_task_queue(task) #define tree_first(root) rb_first(root) #define tree_last(root) rb_last(root) #define tree_next(node) rb_next(node) #define tree_prev(node) rb_prev(node) #define tree_erase(node, root) rb_erase(node, root) #define tree_entry(node) rb_entry((node), struct task, rb_node) /****************************************************************************/ #else #include "eb32tree.h" struct task { struct eb32_node eb_node; struct eb_root *wq; void *data; char task_data[200]; }; #define expire eb_node.key struct eb_root wait_queue = EB_ROOT; /* EB_ROOT || EB_ROOT_UNIQUE */ #define tree_node eb32_node #define tree_first(root) eb32_first(root) #define tree_last(root) eb32_last(root) #define tree_next(node) eb32_next(node) #define tree_prev(node) eb32_prev(node) #define tree_entry(node) eb32_entry((node), struct task, eb_node) #define insert_task_queue(task) __eb32_insert((task)->wq, &task->eb_node) #define tree_lookup(root, x) __eb32_lookup(root, x) #define tree_erase(node, root) __eb32_delete(node); #endif /****************************************************************************/ unsigned long total_jumps = 0; static unsigned long rev32(unsigned long x) { x = ((x & 0xFFFF0000) >> 16) | ((x & 0x0000FFFF) << 16); x = ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8); x = ((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4); x = ((x & 0xCCCCCCCC) >> 2) | ((x & 0x33333333) << 2); x = ((x & 0xAAAAAAAA) >> 1) | ((x & 0x55555555) << 1); return x; } int main(int argc, char **argv) { char buffer[1024]; unsigned int total = 0; long i; unsigned long links_used = 0; unsigned long neighbours = 0; unsigned long long x; struct task *task, *lasttask, *firsttask; struct tree_node *node; struct timeval t_start, t_random, t_insert, t_lookup, t_walk, t_move, t_delete; static unsigned long long start, calibrate, end, cycles, cycles2, cycles3; static unsigned long long start1, stop1, count; /* disable output buffering */ setbuf(stdout, NULL); printf("Sizeof struct task=%d\n", sizeof(struct task)); cycles = 0; if (argc < 2) { tv_now(&t_start); while (fgets(buffer, sizeof(buffer), stdin) != NULL) { void *p; char *ret = strchr(buffer, '\n'); if (ret) *ret = 0; //printf("read=%lld\n", x); x = atoll(buffer); total++; task = (struct task *)calloc(1, sizeof(*task)); task->expire = x; task->wq = &wait_queue; p = insert_task_queue(task); if (p == task) printf("Inserted task %p\n", p); else printf("Reused task %p\n", p); } tv_now(&t_random); tv_now(&t_insert); } else { total = atol(argv[1]); /* preallocation */ tv_now(&t_start); //printf("Timing %d random()+malloc... ", total); rdtscll(start); firsttask = lasttask = NULL; for (i = 0; i < total; i++) { ////unsigned long long x = (i << 16) + ((random() & 63ULL) << 32) + (random() % 1000); //unsigned long l = (random() % 1000)*1000; // to emulate tv_usec based on milliseconds //unsigned long h = ((random() & 63ULL)<<8) + (i%100); // to emulate lots of close seconds ////unsigned long long x = ((unsigned long long)h << 32) + l; //unsigned long long x = ((unsigned long long)h << 16) + l; unsigned long j, x; /* makes a worst case with high bits moving fast */ x = i; for (j = 0; j < 32; j++) x ^= (1UL << (32-j)) >> (i%(j+1)); //printf("x=%08x\n", x); //x=((1<<31) >> (i%32)) ^ ((1<<30) >> (i%31)) ^ ((1<<29) >> (i%30)) ^ ((1<<28) >> (i%29)) ^ //((1<<27) >> (i%28)) ^ ((1<<26) >> (i%27)) ^ ((1<<31) >> (i%26)) ^ ((1<<31) >> (i%25)) ^ //((1<<31) >> (i%24)) ^ ((1<<31) >> (i%23)) ^ ((1<<31) >> (i%22)) ^ ((1<<31) >> (i%21)) ^ //0; //x = i & 16383;// ^ (1 << (i&31));//(i < 32) ? (1 << i) : 1/*(i & 1023)*/; //x = 1UL << (i&31); //x = (i >> 10) << 20 | (i & 1023); //x = rev32(i); //x = (x >> 10) << 20 | (x & 1023); //x = (x >> 16) ^ (x << 16); //x = ((i >> 10) << 20) + (i & 1023) * 3; //x = random(); //x = i; //x = total-i; //x = rev32(i); //x = random() & 1023; // simulates some sparse groups of values like with a scheduler x = (i / 1000) * 50000 + (i % 1000) * 4 - 1500; //x = i>>2; //x = i; //x = 1000; task = (struct task *)calloc(1,sizeof(*task)); task->expire = x;//*x;//total-i-1;//*/(x>>10)&65535;//i&65535;//(x>>8)&65535;//rev32(i);//i&32767;//x;//i ^ (long)lasttask; task->wq = &wait_queue; if (!firsttask) firsttask = task; if (lasttask) lasttask->data = (void *)task; lasttask = task; task->data = NULL; /* tasks will be queued backwards */ memcpy(task->task_data, &i, sizeof(i)); lasttask = task; DPRINTF("task %p = %ld (data=%ld)\n", task, x, i); } rdtscll(end); tv_now(&t_random); //printf("%llu cycles/ent\n", (end - start)/total); printf("Timing %d insert... ", total); cycles = 0; task = firsttask; for (i = 0; i < total; i++) { rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! insert_task_queue(task); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); task = task->data; } tv_now(&t_insert); printf("%llu cycles/ent avg, last = %llu cycles\n", cycles/total, (end - calibrate) - (calibrate - start)); #if defined(tree_lookup) printf("Timing %d lookups... ", total); cycles3 = 0; task = firsttask; for (i = 0; i < total; i++) { rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! node = tree_lookup(&wait_queue, task->expire); rdtscll(end); cycles3 += (end - calibrate) - (calibrate - start); //if (!node) // *(int*)0=0; //if (tree_entry(node)->expire != task->expire) // *(int*)0 = 0; task = task->data; } tv_now(&t_lookup); printf("%llu cycles/ent avg, last = %llu cycles\n", cycles3/total, (end - calibrate) - (calibrate - start)); #else tv_now(&t_lookup); #endif } cycles2 = cycles; printf("Walking right through %d entries... ", total); node = tree_first(&wait_queue); cycles = 0; DPRINTF("\n"); rdtscll(start); while (node) { #ifdef DEBUG task = tree_entry(node); memcpy(&i, task->task_data, sizeof(i)); DPRINTF("next: %p = %ld (data=%ld)\n", task, task->expire, i); #endif node = tree_next(node); } rdtscll(end); cycles = end - start; printf("%llu cycles/ent\n", cycles/total); cycles2 += cycles; printf("Walking left through %d entries... ", total); node = tree_last(&wait_queue); cycles = 0; DPRINTF("\n"); rdtscll(start); while (node) { #ifdef DEBUG task = tree_entry(node); memcpy(&i, task->task_data, sizeof(i)); DPRINTF("prev: %p = %ld (data=%ld)\n", task, task->expire, i); #endif node = tree_prev(node); } rdtscll(end); cycles = end - start; printf("%llu cycles/ent\n", cycles/total); cycles2 += cycles; printf("Deleting %d entries... ", total); node = tree_first(&wait_queue); lasttask = tree_entry(node); cycles = 0; count = 0; rdtscll(start); start1 = start; while (node) { struct tree_node *next; next = tree_next(node); task = tree_entry(node); //printf("deleting node = %p, node->val = 0x%08x, link_p=%p, leaf_p=%p, bit=%d, leaf_p->bit=%d\n", // node, node->val, node->node.link_p, node->node.leaf_p, node->node.bit, // node->node.leaf_p ? node->node.leaf_p->bit : -1); //if (task->expire < lasttask->expire) // printf("old=%p, new=%p, o_exp=%d, n_exp=%d\n", lasttask, task, lasttask->expire, task->expire); rdtscll(start); rdtscll(calibrate); // account for the time spent calling rdtsc too ! tree_erase(node, task->wq); rdtscll(end); cycles += (end - calibrate) - (calibrate - start); node = next; lasttask = task; count++; } rdtscll(end); stop1 = end; tv_now(&t_delete); printf("%llu cycles/ent, %llu ent, %llu cycles tot, %llu cycles/ent(avg)\n", cycles/total, count, stop1-start1, (stop1-start1)/count); printf("Total for %d entries : %llu cycles/ent = %llu kilocycles\n", total, (cycles+cycles2)/total, (cycles+cycles2)/1000); node = tree_first(&wait_queue); if (node) printf("ERROR!! rb_first now returns %p\n", node); //printf("total=%u, links=%lu, neighbours=%lu entries, total_jumps=%lu\n", total, links_used, neighbours, total_jumps); //printf("random+malloc =%lu ms\n", tv_ms_elapsed(&t_start, &t_random)); //printf("insert =%lu ms\n", tv_ms_elapsed(&t_random, &t_insert)); //printf("delete =%lu ms\n", tv_ms_elapsed(&t_move, &t_delete)); return 0; } ebtree/ebpttree.h0000644000076400001440000001262011613243153013505 0ustar bernatusers/* * Elastic Binary Trees - macros and structures for operations on pointer nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _EBPTTREE_H #define _EBPTTREE_H #include "ebtree.h" #include "eb32tree.h" #include "eb64tree.h" /* Return the structure of type whose member points to */ #define ebpt_entry(ptr, type, member) container_of(ptr, type, member) #define EBPT_ROOT EB_ROOT #define EBPT_TREE_HEAD EB_TREE_HEAD /* on *almost* all platforms, a pointer can be cast into a size_t which is unsigned */ #ifndef PTR_INT_TYPE #define PTR_INT_TYPE size_t #endif typedef PTR_INT_TYPE ptr_t; /* This structure carries a node, a leaf, and a key. It must start with the * eb_node so that it can be cast into an eb_node. We could also have put some * sort of transparent union here to reduce the indirection level, but the fact * is, the end user is not meant to manipulate internals, so this is pointless. * Internally, it is automatically cast as an eb32_node or eb64_node. */ struct ebpt_node { struct eb_node node; /* the tree node, must be at the beginning */ void *key; }; /* * Exported functions and macros. * Many of them are always inlined because they are extremely small, and * are generally called at most once or twice in a program. */ /* Return leftmost node in the tree, or NULL if none */ static forceinline struct ebpt_node *ebpt_first(struct eb_root *root) { return ebpt_entry(eb_first(root), struct ebpt_node, node); } /* Return rightmost node in the tree, or NULL if none */ static forceinline struct ebpt_node *ebpt_last(struct eb_root *root) { return ebpt_entry(eb_last(root), struct ebpt_node, node); } /* Return next node in the tree, or NULL if none */ static forceinline struct ebpt_node *ebpt_next(struct ebpt_node *ebpt) { return ebpt_entry(eb_next(&ebpt->node), struct ebpt_node, node); } /* Return previous node in the tree, or NULL if none */ static forceinline struct ebpt_node *ebpt_prev(struct ebpt_node *ebpt) { return ebpt_entry(eb_prev(&ebpt->node), struct ebpt_node, node); } /* Return next node in the tree, skipping duplicates, or NULL if none */ static forceinline struct ebpt_node *ebpt_next_unique(struct ebpt_node *ebpt) { return ebpt_entry(eb_next_unique(&ebpt->node), struct ebpt_node, node); } /* Return previous node in the tree, skipping duplicates, or NULL if none */ static forceinline struct ebpt_node *ebpt_prev_unique(struct ebpt_node *ebpt) { return ebpt_entry(eb_prev_unique(&ebpt->node), struct ebpt_node, node); } /* Delete node from the tree if it was linked in. Mark the node unused. Note * that this function relies on a non-inlined generic function: eb_delete. */ static forceinline void ebpt_delete(struct ebpt_node *ebpt) { eb_delete(&ebpt->node); } /* * The following functions are inlined but derived from the integer versions. */ static forceinline struct ebpt_node *ebpt_lookup(struct eb_root *root, void *x) { if (sizeof(void *) == 4) return (struct ebpt_node *)eb32_lookup(root, (u32)(PTR_INT_TYPE)x); else return (struct ebpt_node *)eb64_lookup(root, (u64)(PTR_INT_TYPE)x); } static forceinline struct ebpt_node *ebpt_lookup_le(struct eb_root *root, void *x) { if (sizeof(void *) == 4) return (struct ebpt_node *)eb32_lookup_le(root, (u32)(PTR_INT_TYPE)x); else return (struct ebpt_node *)eb64_lookup_le(root, (u64)(PTR_INT_TYPE)x); } static forceinline struct ebpt_node *ebpt_lookup_ge(struct eb_root *root, void *x) { if (sizeof(void *) == 4) return (struct ebpt_node *)eb32_lookup_ge(root, (u32)(PTR_INT_TYPE)x); else return (struct ebpt_node *)eb64_lookup_ge(root, (u64)(PTR_INT_TYPE)x); } static forceinline struct ebpt_node *ebpt_insert(struct eb_root *root, struct ebpt_node *new) { if (sizeof(void *) == 4) return (struct ebpt_node *)eb32_insert(root, (struct eb32_node *)new); else return (struct ebpt_node *)eb64_insert(root, (struct eb64_node *)new); } /* * The following functions are less likely to be used directly, because * their code is larger. The non-inlined version is preferred. */ /* Delete node from the tree if it was linked in. Mark the node unused. */ static forceinline void __ebpt_delete(struct ebpt_node *ebpt) { __eb_delete(&ebpt->node); } static forceinline struct ebpt_node *__ebpt_lookup(struct eb_root *root, void *x) { if (sizeof(void *) == 4) return (struct ebpt_node *)__eb32_lookup(root, (u32)(PTR_INT_TYPE)x); else return (struct ebpt_node *)__eb64_lookup(root, (u64)(PTR_INT_TYPE)x); } static forceinline struct ebpt_node *__ebpt_insert(struct eb_root *root, struct ebpt_node *new) { if (sizeof(void *) == 4) return (struct ebpt_node *)__eb32_insert(root, (struct eb32_node *)new); else return (struct ebpt_node *)__eb64_insert(root, (struct eb64_node *)new); } #endif /* _EBPT_TREE_H */ ebtree/compiler.h0000644000076400001440000000561211613243153013510 0ustar bernatusers/* * ebtree/compiler.h * This files contains some compiler-specific settings. * * Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _EBTREE_COMPILER_H #define _EBTREE_COMPILER_H /* * Gcc before 3.0 needs [0] to declare a variable-size array */ #ifndef VAR_ARRAY #if __GNUC__ < 3 #define VAR_ARRAY 0 #else #define VAR_ARRAY #endif #endif /* Support passing function parameters in registers. For this, the * CONFIG_REGPARM macro has to be set to the maximal number of registers * allowed. Some functions have intentionally received a regparm lower than * their parameter count, it is in order to avoid register clobbering where * they are called. */ #ifndef REGPRM1 #if CONFIG_REGPARM >= 1 && __GNUC__ >= 3 #define REGPRM1 __attribute__((regparm(1))) #else #define REGPRM1 #endif #endif #ifndef REGPRM2 #if CONFIG_REGPARM >= 2 && __GNUC__ >= 3 #define REGPRM2 __attribute__((regparm(2))) #else #define REGPRM2 REGPRM1 #endif #endif #ifndef REGPRM3 #if CONFIG_REGPARM >= 3 && __GNUC__ >= 3 #define REGPRM3 __attribute__((regparm(3))) #else #define REGPRM3 REGPRM2 #endif #endif /* By default, gcc does not inline large chunks of code, but we want it to * respect our choices. */ #if !defined(forceinline) #if __GNUC__ < 3 #define forceinline inline #else #define forceinline inline __attribute__((always_inline)) #endif #endif /* * Gcc >= 3 provides the ability for the programme to give hints to the * compiler about what branch of an if is most likely to be taken. This * helps the compiler produce the most compact critical paths, which is * generally better for the cache and to reduce the number of jumps. */ #if !defined(likely) #if __GNUC__ < 3 #define __builtin_expect(x,y) (x) #define likely(x) (x) #define unlikely(x) (x) #elif __GNUC__ < 4 /* gcc 3.x does the best job at this */ #define likely(x) (__builtin_expect((x) != 0, 1)) #define unlikely(x) (__builtin_expect((x) != 0, 0)) #else /* GCC 4.x is stupid, it performs the comparison then compares it to 1, * so we cheat in a dirty way to prevent it from doing this. This will * only work with ints and booleans though. */ #define likely(x) (x) #define unlikely(x) (__builtin_expect((unsigned long)(x), 0)) #endif #endif #endif /* _EBTREE_COMPILER_H */ ebtree/ebimtree.h0000644000076400001440000002360111613243153013470 0ustar bernatusers/* * Elastic Binary Trees - macros for Indirect Multi-Byte data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "ebtree.h" #include "ebpttree.h" /* These functions and macros rely on Pointer nodes and use the entry as * a pointer to an indirect key. Most operations are performed using ebpt_*. */ /* The following functions are not inlined by default. They are declared * in ebimtree.c, which simply relies on their inline version. */ REGPRM3 struct ebpt_node *ebim_lookup(struct eb_root *root, const void *x, unsigned int len); REGPRM3 struct ebpt_node *ebim_insert(struct eb_root *root, struct ebpt_node *new, unsigned int len); /* Find the first occurence of a key of a least bytes matching in the * tree . The caller is responsible for ensuring that will not exceed * the common parts between the tree's keys and . In case of multiple matches, * the leftmost node is returned. This means that this function can be used to * lookup string keys by prefix if all keys in the tree are zero-terminated. If * no match is found, NULL is returned. Returns first node if is zero. */ static forceinline struct ebpt_node * __ebim_lookup(struct eb_root *root, const void *x, unsigned int len) { struct ebpt_node *node; eb_troot_t *troot; int pos, side; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) goto ret_null; if (unlikely(len == 0)) goto walk_down; pos = 0; while (1) { if (eb_gettag(troot) == EB_LEAF) { node = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); if (memcmp(node->key + pos, x, len) != 0) goto ret_null; else goto ret_node; } node = container_of(eb_untag(troot, EB_NODE), struct ebpt_node, node.branches); node_bit = node->node.bit; if (node_bit < 0) { /* We have a dup tree now. Either it's for the same * value, and we walk down left, or it's a different * one and we don't have our key. */ if (memcmp(node->key + pos, x, len) != 0) goto ret_null; else goto walk_left; } /* OK, normal data node, let's walk down. We check if all full * bytes are equal, and we start from the last one we did not * completely check. We stop as soon as we reach the last byte, * because we must decide to go left/right or abort. */ node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit) if (node_bit < 0) { /* This surprizing construction gives better performance * because gcc does not try to reorder the loop. Tested to * be fine with 2.95 to 4.2. */ while (1) { if (*(unsigned char*)(node->key + pos++) ^ *(unsigned char*)(x++)) goto ret_null; /* more than one full byte is different */ if (--len == 0) goto walk_left; /* return first node if all bytes matched */ node_bit += 8; if (node_bit >= 0) break; } } /* here we know that only the last byte differs, so node_bit < 8. * We have 2 possibilities : * - more than the last bit differs => return NULL * - walk down on side = (x[pos] >> node_bit) & 1 */ side = *(unsigned char *)x >> node_bit; if (((*(unsigned char*)(node->key + pos) >> node_bit) ^ side) > 1) goto ret_null; side &= 1; troot = node->node.branches.b[side]; } walk_left: troot = node->node.branches.b[EB_LEFT]; walk_down: while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); ret_node: return node; ret_null: return NULL; } /* Insert ebpt_node into subtree starting at node 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. The * len is specified in bytes. */ static forceinline struct ebpt_node * __ebim_insert(struct eb_root *root, struct ebpt_node *new, unsigned int len) { struct ebpt_node *old; unsigned int side; eb_troot_t *troot; eb_troot_t *root_right = root; int diff; int bit; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } len <<= 3; /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. */ bit = 0; while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_leaf; old = container_of(eb_untag(troot, EB_LEAF), struct ebpt_node, node.branches); new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_leaf = eb_dotag(&old->node.branches, EB_LEAF); new->node.node_p = old->node.leaf_p; /* Right here, we have 3 possibilities : * - the tree does not contain the key, and we have * new->key < old->key. We insert new above old, on * the left ; * * - the tree does not contain the key, and we have * new->key > old->key. We insert new above old, on * the right ; * * - the tree does contain the key, which implies it * is alone. We add the new key next to it as a * first duplicate. * * The last two cases can easily be partially merged. */ bit = equal_bits(new->key, old->key, bit, len); diff = cmp_bits(new->key, old->key, bit); if (diff < 0) { new->node.leaf_p = new_left; old->node.leaf_p = new_rght; 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 (diff == 0 && 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; new->node.branches.b[EB_LEFT] = old_leaf; new->node.branches.b[EB_RGHT] = new_leaf; if (diff == 0) { new->node.bit = -1; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } } break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct ebpt_node, node.branches); old_node_bit = old->node.bit; /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. Note: we can compare more bits than * the current node's because as long as they are identical, we * know we descend along the correct side. */ if (old_node_bit < 0) { /* we're above a duplicate tree, we must compare till the end */ bit = equal_bits(new->key, old->key, bit, len); goto dup_tree; } else if (bit < old_node_bit) { bit = equal_bits(new->key, old->key, bit, old_node_bit); } if (bit < old_node_bit) { /* we don't have all bits in common */ /* The tree did not contain the key, so we insert before the node * , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. */ eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf, *old_node; dup_tree: new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); old_node = eb_dotag(&old->node.branches, EB_NODE); new->node.node_p = old->node.node_p; diff = cmp_bits(new->key, old->key, bit); if (diff < 0) { new->node.leaf_p = new_left; old->node.node_p = new_rght; new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = old_node; } else if (diff > 0) { old->node.node_p = new_left; new->node.leaf_p = new_rght; new->node.branches.b[EB_LEFT] = old_node; new->node.branches.b[EB_RGHT] = new_leaf; } else { struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct ebpt_node, node); } break; } /* walk down */ root = &old->node.branches; side = (((unsigned char *)new->key)[old_node_bit >> 3] >> (~old_node_bit & 7)) & 1; troot = root->b[side]; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ /* We need the common higher bits between new->key and old->key. * This number of bits is already in . */ new->node.bit = bit; root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } ebtree/testst.c0000644000076400001440000000324111613243153013213 0ustar bernatusersint loops = 0; #include #include #include #include "ebsttree.h" #ifdef DEBUG #define DPRINTF printf #else #define DPRINTF(a, ...) #endif int main(int argc, char **argv) { struct eb_root root = EB_ROOT; struct ebmb_node *node; struct ebmb_node *node_mb, *node_len, *node_len1; char buffer[1024]; /* disable output buffering */ setbuf(stdout, NULL); if (argc > 1 && strcmp(argv[1], "-h") == 0) { fprintf(stderr, "Usage: %s [val...]\n", argv[0]); exit(1); } argv++; argc--; while (argc >= 1) { int len; char *ret = strchr(*argv, '\n'); if (ret) *ret = 0; len = strlen(*argv); node = calloc(1, sizeof(*node) + len + 1); memcpy(node->key, *argv, len + 1); ebst_insert(&root, node); argv++; argc--; } printf("Dump of command line values :\n"); node = ebmb_first(&root); while (node) { printf("node %p = %s\n", node, (char *)node->key); node = ebmb_next(node); } printf("Now enter lookup values, one per line.\n"); while (fgets(buffer, sizeof(buffer), stdin) != NULL) { char *ret = strchr(buffer, '\n'); int len; if (ret) *ret = 0; len = strlen(buffer); node = ebst_lookup(&root, buffer); node_mb = ebmb_lookup(&root, buffer, len); node_len = ebst_lookup_len(&root, buffer, len); node_len1 = ebst_lookup_len(&root, buffer, len ? len - 1 : 0); printf("lookup: st:node=%p <%s>, mb:node=%p <%s>, len:node=%p <%s>, len-1:node=%p <%s>\n", node, node?(char *)node->key:"", node_mb, node_mb?(char *)node_mb->key:"", node_len, node_len?(char *)node_len->key:"", node_len1, node_len1?(char *)node_len1->key:""); } printf("loops=%d\n", loops); return 0; } ebtree/ebmbtree.h0000644000076400001440000006235711613243153013474 0ustar bernatusers/* * Elastic Binary Trees - macros and structures for Multi-Byte data nodes. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _EBMBTREE_H #define _EBMBTREE_H #include #include "ebtree.h" /* Return the structure of type whose member points to */ #define ebmb_entry(ptr, type, member) container_of(ptr, type, member) #define EBMB_ROOT EB_ROOT #define EBMB_TREE_HEAD EB_TREE_HEAD /* This structure carries a node, a leaf, and a key. It must start with the * eb_node so that it can be cast into an eb_node. We could also have put some * sort of transparent union here to reduce the indirection level, but the fact * is, the end user is not meant to manipulate internals, so this is pointless. * The 'node.bit' value here works differently from scalar types, as it contains * the number of identical bits between the two branches. */ struct ebmb_node { struct eb_node node; /* the tree node, must be at the beginning */ unsigned char key[0]; /* the key, its size depends on the application */ }; /* * Exported functions and macros. * Many of them are always inlined because they are extremely small, and * are generally called at most once or twice in a program. */ /* Return leftmost node in the tree, or NULL if none */ static forceinline struct ebmb_node *ebmb_first(struct eb_root *root) { return ebmb_entry(eb_first(root), struct ebmb_node, node); } /* Return rightmost node in the tree, or NULL if none */ static forceinline struct ebmb_node *ebmb_last(struct eb_root *root) { return ebmb_entry(eb_last(root), struct ebmb_node, node); } /* Return next node in the tree, or NULL if none */ static forceinline struct ebmb_node *ebmb_next(struct ebmb_node *ebmb) { return ebmb_entry(eb_next(&ebmb->node), struct ebmb_node, node); } /* Return previous node in the tree, or NULL if none */ static forceinline struct ebmb_node *ebmb_prev(struct ebmb_node *ebmb) { return ebmb_entry(eb_prev(&ebmb->node), struct ebmb_node, node); } /* Return next node in the tree, skipping duplicates, or NULL if none */ static forceinline struct ebmb_node *ebmb_next_unique(struct ebmb_node *ebmb) { return ebmb_entry(eb_next_unique(&ebmb->node), struct ebmb_node, node); } /* Return previous node in the tree, skipping duplicates, or NULL if none */ static forceinline struct ebmb_node *ebmb_prev_unique(struct ebmb_node *ebmb) { return ebmb_entry(eb_prev_unique(&ebmb->node), struct ebmb_node, node); } /* Delete node from the tree if it was linked in. Mark the node unused. Note * that this function relies on a non-inlined generic function: eb_delete. */ static forceinline void ebmb_delete(struct ebmb_node *ebmb) { eb_delete(&ebmb->node); } /* The following functions are not inlined by default. They are declared * in ebmbtree.c, which simply relies on their inline version. */ REGPRM3 struct ebmb_node *ebmb_lookup(struct eb_root *root, const void *x, unsigned int len); REGPRM3 struct ebmb_node *ebmb_insert(struct eb_root *root, struct ebmb_node *new, unsigned int len); REGPRM2 struct ebmb_node *ebmb_lookup_longest(struct eb_root *root, const void *x); REGPRM3 struct ebmb_node *ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx); REGPRM3 struct ebmb_node *ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len); /* The following functions are less likely to be used directly, because their * code is larger. The non-inlined version is preferred. */ /* Delete node from the tree if it was linked in. Mark the node unused. */ static forceinline void __ebmb_delete(struct ebmb_node *ebmb) { __eb_delete(&ebmb->node); } /* Find the first occurence of a key of a least bytes matching in the * tree . The caller is responsible for ensuring that will not exceed * the common parts between the tree's keys and . In case of multiple matches, * the leftmost node is returned. This means that this function can be used to * lookup string keys by prefix if all keys in the tree are zero-terminated. If * no match is found, NULL is returned. Returns first node if is zero. */ static forceinline struct ebmb_node *__ebmb_lookup(struct eb_root *root, const void *x, unsigned int len) { struct ebmb_node *node; eb_troot_t *troot; int pos, side; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) goto ret_null; if (unlikely(len == 0)) goto walk_down; pos = 0; while (1) { if (eb_gettag(troot) == EB_LEAF) { node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); if (memcmp(node->key + pos, x, len) != 0) goto ret_null; else goto ret_node; } node = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); node_bit = node->node.bit; if (node_bit < 0) { /* We have a dup tree now. Either it's for the same * value, and we walk down left, or it's a different * one and we don't have our key. */ if (memcmp(node->key + pos, x, len) != 0) goto ret_null; else goto walk_left; } /* OK, normal data node, let's walk down. We check if all full * bytes are equal, and we start from the last one we did not * completely check. We stop as soon as we reach the last byte, * because we must decide to go left/right or abort. */ node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit) if (node_bit < 0) { /* This surprizing construction gives better performance * because gcc does not try to reorder the loop. Tested to * be fine with 2.95 to 4.2. */ while (1) { if (node->key[pos++] ^ *(unsigned char*)(x++)) goto ret_null; /* more than one full byte is different */ if (--len == 0) goto walk_left; /* return first node if all bytes matched */ node_bit += 8; if (node_bit >= 0) break; } } /* here we know that only the last byte differs, so node_bit < 8. * We have 2 possibilities : * - more than the last bit differs => return NULL * - walk down on side = (x[pos] >> node_bit) & 1 */ side = *(unsigned char *)x >> node_bit; if (((node->key[pos] >> node_bit) ^ side) > 1) goto ret_null; side &= 1; troot = node->node.branches.b[side]; } walk_left: troot = node->node.branches.b[EB_LEFT]; walk_down: while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); ret_node: return node; ret_null: return NULL; } /* Insert ebmb_node into subtree starting at node root . * Only new->key needs be set with the key. The ebmb_node is returned. * If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * len is specified in bytes. It is absolutely mandatory that this length * is the same for all keys in the tree. This function cannot be used to * insert strings. */ static forceinline struct ebmb_node * __ebmb_insert(struct eb_root *root, struct ebmb_node *new, unsigned int len) { struct ebmb_node *old; unsigned int side; eb_troot_t *troot, **up_ptr; eb_troot_t *root_right = root; int diff; int bit; eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. */ bit = 0; while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { /* insert above a leaf */ old = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); new->node.node_p = old->node.leaf_p; up_ptr = &old->node.leaf_p; goto check_bit_and_break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); old_node_bit = old->node.bit; if (unlikely(old->node.bit < 0)) { /* We're above a duplicate tree, so we must compare the whole value */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; check_bit_and_break: bit = equal_bits(new->key, old->key, bit, len << 3); break; } /* Stop going down when we don't have common bits anymore. We * also stop in front of a duplicates tree because it means we * have to insert above. Note: we can compare more bits than * the current node's because as long as they are identical, we * know we descend along the correct side. */ bit = equal_bits(new->key, old->key, bit, old_node_bit); if (unlikely(bit < old_node_bit)) { /* The tree did not contain the key, so we insert before the * node , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; break; } /* we don't want to skip bits for further comparisons, so we must limit . * However, since we're going down around , we know it will be * properly matched, so we can skip this bit. */ bit = old_node_bit + 1; /* walk down */ root = &old->node.branches; side = old_node_bit & 7; side ^= 7; side = (new->key[old_node_bit >> 3] >> side) & 1; troot = root->b[side]; } new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); /* Note: we can compare more bits than * the current node's because as long as they are identical, we * know we descend along the correct side. */ new->node.bit = bit; diff = cmp_bits(new->key, old->key, bit); if (diff == 0) { new->node.bit = -1; /* mark as new dup tree, just in case */ if (likely(eb_gettag(root_right))) { /* we refuse to duplicate this key if the tree is * tagged as containing only unique keys. */ return old; } if (eb_gettag(troot) != EB_LEAF) { /* there was already a dup tree below */ struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct ebmb_node, node); } /* otherwise fall through */ } if (diff >= 0) { new->node.branches.b[EB_LEFT] = troot; new->node.branches.b[EB_RGHT] = new_leaf; new->node.leaf_p = new_rght; *up_ptr = new_left; } else if (diff < 0) { new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = troot; new->node.leaf_p = new_left; *up_ptr = new_rght; } /* Ok, now we are inserting between and . 's * parent is already set to , and the 's branch is still in * . Update the root's leaf till we have it. Note that we can also * find the side by checking the side of new->node.node_p. */ root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } /* Find the first occurence of the longest prefix matching a key in the * tree . It's the caller's responsibility to ensure that key is at * least as long as the keys in the tree. If none can be found, return NULL. */ static forceinline struct ebmb_node *__ebmb_lookup_longest(struct eb_root *root, const void *x) { struct ebmb_node *node; eb_troot_t *troot, *cover; int pos, side; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; cover = NULL; pos = 0; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); if (check_bits(x - pos, node->key, pos, node->node.pfx)) goto not_found; return node; } node = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); node_bit = node->node.bit; if (node_bit < 0) { /* We have a dup tree now. Either it's for the same * value, and we walk down left, or it's a different * one and we don't have our key. */ if (check_bits(x - pos, node->key, pos, node->node.pfx)) goto not_found; troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); return node; } node_bit >>= 1; /* strip cover bit */ node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit) if (node_bit < 0) { /* This uncommon construction gives better performance * because gcc does not try to reorder the loop. Tested to * be fine with 2.95 to 4.2. */ while (1) { x++; pos++; if (node->key[pos-1] ^ *(unsigned char*)(x-1)) goto not_found; /* more than one full byte is different */ node_bit += 8; if (node_bit >= 0) break; } } /* here we know that only the last byte differs, so 0 <= node_bit <= 7. * We have 2 possibilities : * - more than the last bit differs => data does not match * - walk down on side = (x[pos] >> node_bit) & 1 */ side = *(unsigned char *)x >> node_bit; if (((node->key[pos] >> node_bit) ^ side) > 1) goto not_found; if (!(node->node.bit & 1)) { /* This is a cover node, let's keep a reference to it * for later. The covering subtree is on the left, and * the covered subtree is on the right, so we have to * walk down right. */ cover = node->node.branches.b[EB_LEFT]; troot = node->node.branches.b[EB_RGHT]; continue; } side &= 1; troot = node->node.branches.b[side]; } not_found: /* Walk down last cover tre if it exists. It does not matter if cover is NULL */ return ebmb_entry(eb_walk_down(cover, EB_LEFT), struct ebmb_node, node); } /* Find the first occurence of a prefix matching a key of BITS in the * tree . It's the caller's responsibility to ensure that key is at * least as long as the keys in the tree. If none can be found, return NULL. */ static forceinline struct ebmb_node *__ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx) { struct ebmb_node *node; eb_troot_t *troot; int pos, side; int node_bit; troot = root->b[EB_LEFT]; if (unlikely(troot == NULL)) return NULL; pos = 0; while (1) { if ((eb_gettag(troot) == EB_LEAF)) { node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); if (node->node.pfx != pfx) return NULL; if (check_bits(x - pos, node->key, pos, node->node.pfx)) return NULL; return node; } node = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); node_bit = node->node.bit; if (node_bit < 0) { /* We have a dup tree now. Either it's for the same * value, and we walk down left, or it's a different * one and we don't have our key. */ if (node->node.pfx != pfx) return NULL; if (check_bits(x - pos, node->key, pos, node->node.pfx)) return NULL; troot = node->node.branches.b[EB_LEFT]; while (eb_gettag(troot) != EB_LEAF) troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; node = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); return node; } node_bit >>= 1; /* strip cover bit */ node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit) if (node_bit < 0) { /* This uncommon construction gives better performance * because gcc does not try to reorder the loop. Tested to * be fine with 2.95 to 4.2. */ while (1) { x++; pos++; if (node->key[pos-1] ^ *(unsigned char*)(x-1)) return NULL; /* more than one full byte is different */ node_bit += 8; if (node_bit >= 0) break; } } /* here we know that only the last byte differs, so 0 <= node_bit <= 7. * We have 2 possibilities : * - more than the last bit differs => data does not match * - walk down on side = (x[pos] >> node_bit) & 1 */ side = *(unsigned char *)x >> node_bit; if (((node->key[pos] >> node_bit) ^ side) > 1) return NULL; if (!(node->node.bit & 1)) { /* This is a cover node, it may be the entry we're * looking for. We already know that it matches all the * bits, let's compare prefixes and descend the cover * subtree if they match. */ if ((unsigned short)node->node.bit >> 1 == pfx) troot = node->node.branches.b[EB_LEFT]; else troot = node->node.branches.b[EB_RGHT]; continue; } side &= 1; troot = node->node.branches.b[side]; } } /* Insert ebmb_node into a prefix subtree starting at node root . * Only new->key and new->pfx need be set with the key and its prefix length. * Note that bits between and are theorically ignored and should be * zero, as it is not certain yet that they will always be ignored everywhere * (eg in bit compare functions). * The ebmb_node is returned. * If root->b[EB_RGHT]==1, the tree may only contain unique keys. The * len is specified in bytes. */ static forceinline struct ebmb_node * __ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len) { struct ebmb_node *old; unsigned int side; eb_troot_t *troot, **up_ptr; eb_troot_t *root_right = root; int diff; int bit; eb_troot_t *new_left, *new_rght; eb_troot_t *new_leaf; int old_node_bit; 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); new->node.leaf_p = eb_dotag(root, EB_LEFT); new->node.node_p = NULL; /* node part unused */ return new; } len <<= 3; if (len > new->node.pfx) len = new->node.pfx; /* The tree descent is fairly easy : * - first, check if we have reached a leaf node * - second, check if we have gone too far * - third, reiterate * Everywhere, we use for the node node we are inserting, * for the node we attach it to, and for the node we are * displacing below . will always point to the future node * (tagged with its type). carries the side the node is * attached to below its parent, which is also where previous node * was attached. */ bit = 0; while (1) { if (unlikely(eb_gettag(troot) == EB_LEAF)) { /* Insert above a leaf. Note that this leaf could very * well be part of a cover node. */ old = container_of(eb_untag(troot, EB_LEAF), struct ebmb_node, node.branches); new->node.node_p = old->node.leaf_p; up_ptr = &old->node.leaf_p; goto check_bit_and_break; } /* OK we're walking down this link */ old = container_of(eb_untag(troot, EB_NODE), struct ebmb_node, node.branches); old_node_bit = old->node.bit; /* Note that old_node_bit can be : * < 0 : dup tree * = 2N : cover node for N bits * = 2N+1 : normal node at N bits */ if (unlikely(old_node_bit < 0)) { /* We're above a duplicate tree, so we must compare the whole value */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; check_bit_and_break: /* No need to compare everything if the leaves are shorter than the new one. */ if (len > old->node.pfx) len = old->node.pfx; bit = equal_bits(new->key, old->key, bit, len); break; } /* WARNING: for the two blocks below, is counted in half-bits */ bit = equal_bits(new->key, old->key, bit, old_node_bit >> 1); bit = (bit << 1) + 1; // assume comparisons with normal nodes /* we must always check that our prefix is larger than the nodes * we visit, otherwise we have to stop going down. The following * test is able to stop before both normal and cover nodes. */ if (bit >= (new->node.pfx << 1) && (new->node.pfx << 1) < old_node_bit) { /* insert cover node here on the left */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; new->node.bit = new->node.pfx << 1; diff = -1; goto insert_above; } if (unlikely(bit < old_node_bit)) { /* The tree did not contain the key, so we insert before the * node , and set ->bit to designate the lowest bit position in * which applies to ->branches.b[]. We know that the bit is not * greater than the prefix length thanks to the test above. */ new->node.node_p = old->node.node_p; up_ptr = &old->node.node_p; new->node.bit = bit; diff = cmp_bits(new->key, old->key, bit >> 1); goto insert_above; } if (!(old_node_bit & 1)) { /* if we encounter a cover node with our exact prefix length, it's * necessarily the same value, so we insert there as a duplicate on * the left. For that, we go down on the left and the leaf detection * code will finish the job. */ if ((new->node.pfx << 1) == old_node_bit) { root = &old->node.branches; side = EB_LEFT; troot = root->b[side]; continue; } /* cover nodes are always walked through on the right */ side = EB_RGHT; bit = old_node_bit >> 1; /* recheck that bit */ root = &old->node.branches; troot = root->b[side]; continue; } /* we don't want to skip bits for further comparisons, so we must limit . * However, since we're going down around , we know it will be * properly matched, so we can skip this bit. */ old_node_bit >>= 1; bit = old_node_bit + 1; /* walk down */ root = &old->node.branches; side = old_node_bit & 7; side ^= 7; side = (new->key[old_node_bit >> 3] >> side) & 1; troot = root->b[side]; } /* Right here, we have 4 possibilities : * - the tree does not contain any leaf matching the * key, and we have new->key < old->key. We insert * new above old, on the left ; * * - the tree does not contain any leaf matching the * key, and we have new->key > old->key. We insert * new above old, on the right ; * * - the tree does contain the key with the same prefix * length. We add the new key next to it as a first * duplicate (since it was alone). * * The last two cases can easily be partially merged. * * - the tree contains a leaf matching the key, we have * to insert above it as a cover node. The leaf with * the shortest prefix becomes the left subtree and * the leaf with the longest prefix becomes the right * one. The cover node gets the min of both prefixes * as its new bit. */ /* first we want to ensure that we compare the correct bit, which means * the largest common to both nodes. */ if (bit > new->node.pfx) bit = new->node.pfx; if (bit > old->node.pfx) bit = old->node.pfx; new->node.bit = (bit << 1) + 1; /* assume normal node by default */ /* if one prefix is included in the second one, we don't compare bits * because they won't necessarily match, we just proceed with a cover * node insertion. */ diff = 0; if (bit < old->node.pfx && bit < new->node.pfx) diff = cmp_bits(new->key, old->key, bit); if (diff == 0) { /* Both keys match. Either it's a duplicate entry or we have to * put the shortest prefix left and the largest one right below * a new cover node. By default, diff==0 means we'll be inserted * on the right. */ new->node.bit--; /* anticipate cover node insertion */ if (new->node.pfx == old->node.pfx) { new->node.bit = -1; /* mark as new dup tree, just in case */ if (unlikely(eb_gettag(root_right))) { /* we refuse to duplicate this key if the tree is * tagged as containing only unique keys. */ return old; } if (eb_gettag(troot) != EB_LEAF) { /* there was already a dup tree below */ struct eb_node *ret; ret = eb_insert_dup(&old->node, &new->node); return container_of(ret, struct ebmb_node, node); } /* otherwise fall through to insert first duplicate */ } /* otherwise we just rely on the tests below to select the right side */ else if (new->node.pfx < old->node.pfx) diff = -1; /* force insertion to left side */ } insert_above: new_left = eb_dotag(&new->node.branches, EB_LEFT); new_rght = eb_dotag(&new->node.branches, EB_RGHT); new_leaf = eb_dotag(&new->node.branches, EB_LEAF); if (diff >= 0) { new->node.branches.b[EB_LEFT] = troot; new->node.branches.b[EB_RGHT] = new_leaf; new->node.leaf_p = new_rght; *up_ptr = new_left; } else { new->node.branches.b[EB_LEFT] = new_leaf; new->node.branches.b[EB_RGHT] = troot; new->node.leaf_p = new_left; *up_ptr = new_rght; } root->b[side] = eb_dotag(&new->node.branches, EB_NODE); return new; } #endif /* _EBMBTREE_H */ ebtree/examples/0000755000076400001440000000000011613243153013337 5ustar bernatusersebtree/examples/reduce.c0000644000076400001440000001017111613243153014752 0ustar bernatusers/* * Elastic Binary Trees - example of application to network list reduction * (C) 2010 - Willy Tarreau * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include struct one_net { struct ebmb_node eb_node; struct in_addr addr; /* keep it after eb_node */ /* any other information related to this network could be stored here */ }; struct eb_root tree = EB_ROOT; /* EB_ROOT || EB_ROOT_UNIQUE */ /* Insert an address into the tree, after checking that it does not match * another one. If it does, then only one is kept or they are merged in a * larger network and the function recurses over itself. The address is in * network byte order. */ void insert_net(unsigned addr, unsigned cidr) { unsigned mask; struct ebmb_node *node; struct one_net *net; /* clear unexpected bits */ mask = cidr ? ((signed)-0x80000000) >> (cidr - 1) : 0; mask = htonl(mask); addr &= mask; /* 1) check if the entry already exists or matches an existing one. If we * get a match, we have to compare prefixes and keep the widest one. */ if ((node = ebmb_lookup_longest(&tree, &addr)) != NULL) { if (node->node.pfx <= cidr) return; ebmb_delete(node); free(node); } /* 2) check if we can merge this network with the one just below or above */ if (cidr) { unsigned mask2, addr2; mask2 = cidr ? ((unsigned)0x80000000U) >> (cidr - 1) : 0; mask2 = htonl(mask2); /* invert the bit corresponding to the mask */ addr2 = addr ^ mask2; node = ebmb_lookup_prefix(&tree, &addr2, cidr); if (node) { /* we can merge both entries at cidr - 1 */ ebmb_delete(node); free(ebmb_entry(node, struct one_net, eb_node)); addr &= addr2; /* clear varying bit */ cidr--; /* recursively do the same above */ insert_net(addr, cidr); return; } } net = (struct one_net *)calloc(1, sizeof(*net)); net->addr.s_addr = addr; net->eb_node.node.pfx = cidr; ebmb_insert_prefix(&tree, &net->eb_node, sizeof(net->addr.s_addr)); /* 3) it is possible that this node covers other ones. All other ones * will always be located just after this one, so let's walk right as * long as we find some matches and kill them. */ node = ebmb_next(&net->eb_node); while (node) { net = ebmb_entry(node, struct one_net, eb_node); if ((addr & mask) != (net->addr.s_addr & mask)) break; node = ebmb_next(&net->eb_node); ebmb_delete(&net->eb_node); } } void read_nets_from_stdin() { struct in_addr addr; char str[256]; char *slash; int bits; while (fgets(str, sizeof(str), stdin) != NULL) { bits = 32; slash = strchr(str, '/'); if (slash) { *(slash++) = 0; if (strchr(slash, '.') == NULL) { bits = atoi(slash); } else { inet_aton(slash, &addr); bits = htonl(addr.s_addr); if (bits) bits = 32 - flsnz(~bits); } } inet_aton(str, &addr); insert_net(addr.s_addr, bits); } } void dump_nets() { struct ebmb_node *node = ebmb_first(&tree); while (node) { printf("%d.%d.%d.%d/%d\n", node->key[0], node->key[1], node->key[2], node->key[3], node->node.pfx); node = ebmb_next(node); if (!node) break; } } int main(int argc, char **argv) { if (argc > 1) { fprintf(stderr, "Enter networks one per line in the form [/]\n" "The output will contain the smallest reduction of these nets.\n" ); exit(1); } read_nets_from_stdin(); dump_nets(); return 0; } ebtree/examples/squidgrep.c0000644000076400001440000000474111613243153015514 0ustar bernatusers/* * Elastic Binary Trees - example of application to match multiple strings * (C) 2010 - Willy Tarreau * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include struct eb_root tree = EB_ROOT_UNIQUE; /* EB_ROOT || EB_ROOT_UNIQUE */ int input, match; void insert_url(const char *url) { struct ebmb_node *node; int l; l = strlen(url); while (l && url[l-1] == '\n') l--; node = calloc(1, sizeof(*node) + l + 1); memcpy(node->key, url, l); node->key[l] = 0; ebst_insert(&tree, node); } void read_urls_from_file(FILE *f) { char str[256]; while (fgets(str, sizeof(str), f) != NULL) insert_url(str); } void match_logs_from_stdin() { int field; char line[256]; char *str, *url, *end; struct ebmb_node *node; match = 0; input = 0; /* Note: this construct allows easier use of halog's fgets() */ while ((str = fgets(line, sizeof(line), stdin)) != NULL) { /* URL is on the 7th field */ url = str; for (field = 0; field < 6; field++) { while (*url && *url != ' ') url++; while (*url == ' ') url++; } end = url; while (*end && *end != ' ') end++; *end = 0; if (end == url) continue; input++; node = ebst_lookup(&tree, url); if (node) { match++; puts(str); } } } int main(int argc, char **argv) { FILE *f; int matches; if (argc != 2) { fprintf(stderr, "Usage:\n" " $0 url_file < squid_access.log\n" " Will output all lines referencing one of the URLs from url_file.\n" ); exit(1); } f = fopen(argv[1], "r"); if (!f) { perror("fopen"); exit(1); } read_urls_from_file(f); fclose(f); match_logs_from_stdin(); fprintf(stderr, "Matches: %d/%d\n", match, input); return 0; } ebtree/ebtree.c0000644000076400001440000000203411613243153013132 0ustar bernatusers/* * Elastic Binary Trees - exported generic functions * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "ebtree.h" void eb_delete(struct eb_node *node) { __eb_delete(node); } /* used by insertion primitives */ REGPRM1 struct eb_node *eb_insert_dup(struct eb_node *sub, struct eb_node *new) { return __eb_insert_dup(sub, new); } ebtree/ebtree.h0000644000076400001440000007465111613243153013155 0ustar bernatusers/* * Elastic Binary Trees - generic macros and structures. * Version 6.0.6 * (C) 2002-2011 - Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, version 2.1 * exclusively. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* General idea: ------------- In a radix binary tree, we may have up to 2N-1 nodes for N keys if all of them are leaves. If we find a way to differentiate intermediate nodes (later called "nodes") and final nodes (later called "leaves"), and we associate them by two, it is possible to build sort of a self-contained radix tree with intermediate nodes always present. It will not be as cheap as the ultree for optimal cases as shown below, but the optimal case almost never happens : Eg, to store 8, 10, 12, 13, 14 : ultree this theorical tree 8 8 / \ / \ 10 12 10 12 / \ / \ 13 14 12 14 / \ 12 13 Note that on real-world tests (with a scheduler), is was verified that the case with data on an intermediate node never happens. This is because the data spectrum is too large for such coincidences to happen. It would require for instance that a task has its expiration time at an exact second, with other tasks sharing that second. This is too rare to try to optimize for it. What is interesting is that the node will only be added above the leaf when necessary, which implies that it will always remain somewhere above it. So both the leaf and the node can share the exact value of the leaf, because when going down the node, the bit mask will be applied to comparisons. So we are tempted to have one single key shared between the node and the leaf. The bit only serves the nodes, and the dups only serve the leaves. So we can put a lot of information in common. This results in one single entity with two branch pointers and two parent pointers, one for the node part, and one for the leaf part : node's leaf's parent parent | | [node] [leaf] / \ left right branch branch The node may very well refer to its leaf counterpart in one of its branches, indicating that its own leaf is just below it : node's parent | [node] / \ left [leaf] branch Adding keys in such a tree simply consists in inserting nodes between other nodes and/or leaves : [root] | [node2] / \ [leaf1] [node3] / \ [leaf2] [leaf3] On this diagram, we notice that [node2] and [leaf2] have been pulled away from each other due to the insertion of [node3], just as if there would be an elastic between both parts. This elastic-like behaviour gave its name to the tree : "Elastic Binary Tree", or "EBtree". The entity which associates a node part and a leaf part will be called an "EB node". We also notice on the diagram that there is a root entity required to attach the tree. It only contains two branches and there is nothing above it. This is an "EB root". Some will note that [leaf1] has no [node1]. One property of the EBtree is that all nodes have their branches filled, and that if a node has only one branch, it does not need to exist. Here, [leaf1] was added below [root] and did not need any node. An EB node contains : - a pointer to the node's parent (node_p) - a pointer to the leaf's parent (leaf_p) - two branches pointing to lower nodes or leaves (branches) - a bit position (bit) - an optional key. The key here is optional because it's used only during insertion, in order to classify the nodes. Nothing else in the tree structure requires knowledge of the key. This makes it possible to write type-agnostic primitives for everything, and type-specific insertion primitives. This has led to consider two types of EB nodes. The type-agnostic ones will serve as a header for the other ones, and will simply be called "struct eb_node". The other ones will have their type indicated in the structure name. Eg: "struct eb32_node" for nodes carrying 32 bit keys. We will also node that the two branches in a node serve exactly the same purpose as an EB root. For this reason, a "struct eb_root" will be used as well inside the struct eb_node. In order to ease pointer manipulation and ROOT detection when walking upwards, all the pointers inside an eb_node will point to the eb_root part of the referenced EB nodes, relying on the same principle as the linked lists in Linux. Another important point to note, is that when walking inside a tree, it is very convenient to know where a node is attached in its parent, and what type of branch it has below it (leaf or node). In order to simplify the operations and to speed up the processing, it was decided in this specific implementation to use the lowest bit from the pointer to designate the side of the upper pointers (left/right) and the type of a branch (leaf/node). This practise is not mandatory by design, but an implementation-specific optimisation permitted on all platforms on which data must be aligned. All known 32 bit platforms align their integers and pointers to 32 bits, leaving the two lower bits unused. So, we say that the pointers are "tagged". And since they designate pointers to root parts, we simply call them "tagged root pointers", or "eb_troot" in the code. Duplicate keys are stored in a special manner. When inserting a key, if the same one is found, then an incremental binary tree is built at this place from these keys. This ensures that no special case has to be written to handle duplicates when walking through the tree or when deleting entries. It also guarantees that duplicates will be walked in the exact same order they were inserted. This is very important when trying to achieve fair processing distribution for instance. Algorithmic complexity can be derived from 3 variables : - the number of possible different keys in the tree : P - the number of entries in the tree : N - the number of duplicates for one key : D Note that this tree is deliberately NOT balanced. For this reason, the worst case may happen with a small tree (eg: 32 distinct keys of one bit). BUT, the operations required to manage such data are so much cheap that they make it worth using it even under such conditions. For instance, a balanced tree may require only 6 levels to store those 32 keys when this tree will require 32. But if per-level operations are 5 times cheaper, it wins. Minimal, Maximal and Average times are specified in number of operations. Minimal is given for best condition, Maximal for worst condition, and the average is reported for a tree containing random keys. An operation generally consists in jumping from one node to the other. Complexity : - lookup : min=1, max=log(P), avg=log(N) - insertion from root : min=1, max=log(P), avg=log(N) - insertion of dups : min=1, max=log(D), avg=log(D)/2 after lookup - deletion : min=1, max=1, avg=1 - prev/next : min=1, max=log(P), avg=2 : N/2 nodes need 1 hop => 1*N/2 N/4 nodes need 2 hops => 2*N/4 N/8 nodes need 3 hops => 3*N/8 ... N/x nodes need log(x) hops => log2(x)*N/x Total cost for all N nodes : sum[i=1..N](log2(i)*N/i) = N*sum[i=1..N](log2(i)/i) Average cost across N nodes = total / N = sum[i=1..N](log2(i)/i) = 2 This design is currently limited to only two branches per node. Most of the tree descent algorithm would be compatible with more branches (eg: 4, to cut the height in half), but this would probably require more complex operations and the deletion algorithm would be problematic. Useful properties : - a node is always added above the leaf it is tied to, and never can get below nor in another branch. This implies that leaves directly attached to the root do not use their node part, which is indicated by a NULL value in node_p. This also enhances the cache efficiency when walking down the tree, because when the leaf is reached, its node part will already have been visited (unless it's the first leaf in the tree). - pointers to lower nodes or leaves are stored in "branch" pointers. Only the root node may have a NULL in either branch, it is not possible for other branches. Since the nodes are attached to the left branch of the 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. 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. - a node can never have node_p pointing to itself. - a node is linked in a tree if and only if it has a non-null leaf_p. - a node can never have both branches equal, except for the root which can have them both NULL. - deletion only applies to leaves. When a leaf is deleted, its parent must be released too (unless it's the root), and its sibling must attach to the grand-parent, replacing the parent. Also, when a leaf is deleted, the node tied to this leaf will be removed and must be released too. If this node is different from the leaf's parent, the freshly released leaf's parent will be used to replace the node which must go. A released node will never be used anymore, so there's no point in tracking it. - the bit index in a node indicates the bit position in the key which is represented by the branches. That means that a node with (bit == 0) is just above two leaves. Negative bit values are used to build a duplicate tree. The first node above two identical leaves gets (bit == -1). This value logarithmically decreases as the duplicate tree grows. During duplicate insertion, a node is inserted above the highest bit value (the lowest absolute value) in the tree during the right-sided walk. If bit -1 is not encountered (highest < -1), we insert above last leaf. Otherwise, we insert above the node with the highest value which was not equal to the one of its parent + 1. - the "eb_next" primitive walks from left to right, which means from lower to higher keys. It returns duplicates in the order they were inserted. The "eb_first" primitive returns the left-most entry. - the "eb_prev" primitive walks from right to left, which means from 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 _EBTREE_H #define _EBTREE_H #include #include "compiler.h" static inline int flsnz8_generic(unsigned int x) { int ret = 0; if (x >> 4) { x >>= 4; ret += 4; } return ret + ((0xFFFFAA50U >> (x << 1)) & 3) + 1; } /* Note: we never need to run fls on null keys, so we can optimize the fls * function by removing a conditional jump. */ #if defined(__i386__) || defined(__x86_64__) /* this code is similar on 32 and 64 bit */ static inline int flsnz(int x) { int r; __asm__("bsrl %1,%0\n" : "=r" (r) : "rm" (x)); return r+1; } static inline int flsnz8(unsigned char x) { int r; __asm__("movzbl %%al, %%eax\n" "bsrl %%eax,%0\n" : "=r" (r) : "a" (x)); return r+1; } #else // returns 1 to 32 for 1<<0 to 1<<31. Undefined for 0. #define flsnz(___a) ({ \ register int ___x, ___bits = 0; \ ___x = (___a); \ if (___x & 0xffff0000) { ___x &= 0xffff0000; ___bits += 16;} \ if (___x & 0xff00ff00) { ___x &= 0xff00ff00; ___bits += 8;} \ if (___x & 0xf0f0f0f0) { ___x &= 0xf0f0f0f0; ___bits += 4;} \ if (___x & 0xcccccccc) { ___x &= 0xcccccccc; ___bits += 2;} \ if (___x & 0xaaaaaaaa) { ___x &= 0xaaaaaaaa; ___bits += 1;} \ ___bits + 1; \ }) static inline int flsnz8(unsigned int x) { return flsnz8_generic(x); } #endif static inline int fls64(unsigned long long x) { unsigned int h; unsigned int bits = 32; h = x >> 32; if (!h) { h = x; bits = 0; } return flsnz(h) + bits; } #define fls_auto(x) ((sizeof(x) > 4) ? fls64(x) : flsnz(x)) /* Linux-like "container_of". It returns a pointer to the structure of type * which has its member stored at address . */ #ifndef container_of #define container_of(ptr, type, name) ((type *)(((void *)(ptr)) - ((long)&((type *)0)->name))) #endif /* Number of bits per node, and number of leaves per node */ #define EB_NODE_BITS 1 #define EB_NODE_BRANCHES (1 << EB_NODE_BITS) #define EB_NODE_BRANCH_MASK (EB_NODE_BRANCHES - 1) /* Be careful not to tweak those values. The walking code is optimized for NULL * detection on the assumption that the following values are intact. */ #define EB_LEFT 0 #define EB_RGHT 1 #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 * - 0=link, 1=leaf to designate the branch's type for branch[] */ 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 (+/1 low-order bits). */ struct eb_root { eb_troot_t *b[EB_NODE_BRANCHES]; /* left and right branches */ }; /* The eb_node contains the two parts, one for the leaf, which always exists, * and one for the node, which remains unused in the very first node inserted * into the tree. This structure is 20 bytes per node on 32-bit machines. Do * not change the order, benchmarks have shown that it's optimal this way. */ struct eb_node { struct eb_root branches; /* branches, must be at the beginning */ eb_troot_t *node_p; /* link node's parent */ eb_troot_t *leaf_p; /* leaf node's parent */ short int bit; /* link's bit position. */ short unsigned int pfx; /* data prefix length, always related to leaf */ }; /* Return the structure of type whose member points to */ #define eb_entry(ptr, type, member) container_of(ptr, type, member) /* The root of a tree is an eb_root initialized with both pointers NULL. * During its life, only the left pointer will change. The right one will * always remain NULL, which is the way we detect it. */ #define EB_ROOT \ (struct eb_root) { \ .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 /***************************************\ * Private functions. Not for end-user * \***************************************/ /* Converts a root pointer to its equivalent eb_troot_t pointer, * ready to be stored in ->branch[], leaf_p or node_p. NULL is not * conserved. To be used with EB_LEAF, EB_NODE, EB_LEFT or EB_RGHT in . */ static inline eb_troot_t *eb_dotag(const struct eb_root *root, const int tag) { return (eb_troot_t *)((void *)root + tag); } /* Converts an eb_troot_t pointer pointer to its equivalent eb_root pointer, * for use with pointers from ->branch[], leaf_p or node_p. NULL is conserved * as long as the tree is not corrupted. To be used with EB_LEAF, EB_NODE, * EB_LEFT or EB_RGHT in . */ static inline struct eb_root *eb_untag(const eb_troot_t *troot, const int tag) { return (struct eb_root *)((void *)troot - tag); } /* returns the tag associated with an eb_troot_t pointer */ static inline int eb_gettag(eb_troot_t *troot) { return (unsigned long)troot & 1; } /* Converts a root pointer to its equivalent eb_troot_t pointer and clears the * tag, no matter what its value was. */ static inline struct eb_root *eb_clrtag(const eb_troot_t *troot) { return (struct eb_root *)((unsigned long)troot & ~1UL); } /* Returns a pointer to the eb_node holding */ static inline struct eb_node *eb_root_to_node(struct eb_root *root) { return container_of(root, struct eb_node, branches); } /* Walks down starting at root pointer , and always walking on side * . It either returns the node hosting the first leaf on that side, * or NULL if no leaf is found. may either be NULL or a branch pointer. * The pointer to the leaf (or NULL) is returned. */ static inline struct eb_node *eb_walk_down(eb_troot_t *start, unsigned int side) { /* A NULL pointer on an empty tree root will be returned as-is */ while (eb_gettag(start) == EB_NODE) start = (eb_untag(start, EB_NODE))->b[side]; /* NULL is left untouched (root==eb_node, EB_LEAF==0) */ return eb_root_to_node(eb_untag(start, EB_LEAF)); } /* This function is used to build a tree of duplicates by adding a new node to * a subtree of at least 2 entries. It will probably never be needed inlined, * and it is not for end-user. */ static forceinline struct eb_node * __eb_insert_dup(struct eb_node *sub, struct eb_node *new) { struct eb_node *head = sub; struct eb_troot *new_left = eb_dotag(&new->branches, EB_LEFT); struct eb_troot *new_rght = eb_dotag(&new->branches, EB_RGHT); struct eb_troot *new_leaf = eb_dotag(&new->branches, EB_LEAF); /* first, identify the deepest hole on the right branch */ while (eb_gettag(head->branches.b[EB_RGHT]) != EB_LEAF) { struct eb_node *last = head; head = container_of(eb_untag(head->branches.b[EB_RGHT], EB_NODE), struct eb_node, branches); if (head->bit > last->bit + 1) sub = head; /* there's a hole here */ } /* Here we have a leaf attached to (head)->b[EB_RGHT] */ if (head->bit < -1) { /* A hole exists just before the leaf, we insert there */ new->bit = -1; sub = container_of(eb_untag(head->branches.b[EB_RGHT], EB_LEAF), struct eb_node, branches); head->branches.b[EB_RGHT] = eb_dotag(&new->branches, EB_NODE); new->node_p = sub->leaf_p; new->leaf_p = new_rght; sub->leaf_p = new_left; new->branches.b[EB_LEFT] = eb_dotag(&sub->branches, EB_LEAF); new->branches.b[EB_RGHT] = new_leaf; return new; } else { int side; /* No hole was found before a leaf. We have to insert above * . Note that we cannot be certain that is attached * to the right of its parent, as this is only true if * is inside the dup tree, not at the head. */ new->bit = sub->bit - 1; /* install at the lowest level */ side = eb_gettag(sub->node_p); head = container_of(eb_untag(sub->node_p, side), struct eb_node, branches); head->branches.b[side] = eb_dotag(&new->branches, EB_NODE); new->node_p = sub->node_p; new->leaf_p = new_rght; sub->node_p = new_left; new->branches.b[EB_LEFT] = eb_dotag(&sub->branches, EB_NODE); new->branches.b[EB_RGHT] = new_leaf; return new; } } /**************************************\ * Public functions, for the end-user * \**************************************/ /* Return non-zero if the tree is empty, otherwise zero */ static inline int eb_is_empty(struct eb_root *root) { return !root->b[EB_LEFT]; } /* Return the first leaf in the tree starting at , or NULL if none */ static inline struct eb_node *eb_first(struct eb_root *root) { return eb_walk_down(root->b[0], EB_LEFT); } /* Return the last leaf in the tree starting at , or NULL if none */ static inline struct eb_node *eb_last(struct eb_root *root) { return eb_walk_down(root->b[0], EB_RGHT); } /* Return previous leaf node before an existing leaf node, or NULL if none. */ static inline struct eb_node *eb_prev(struct eb_node *node) { eb_troot_t *t = node->leaf_p; while (eb_gettag(t) == EB_LEFT) { /* Walking up from left branch. We must ensure that we never * walk beyond root. */ 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; } /* Note that cannot be NULL at this stage */ t = (eb_untag(t, EB_RGHT))->b[EB_LEFT]; return eb_walk_down(t, EB_RGHT); } /* Return next leaf node after an existing leaf node, or NULL if none. */ static inline struct eb_node *eb_next(struct eb_node *node) { eb_troot_t *t = node->leaf_p; while (eb_gettag(t) != EB_LEFT) /* Walking up from right branch, so we cannot be below root */ t = (eb_root_to_node(eb_untag(t, EB_RGHT)))->node_p; /* Note that 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); } /* Return previous leaf node before an existing leaf node, skipping duplicates, * or NULL if none. */ static inline struct eb_node *eb_prev_unique(struct eb_node *node) { eb_troot_t *t = node->leaf_p; while (1) { if (eb_gettag(t) != EB_LEFT) { node = eb_root_to_node(eb_untag(t, EB_RGHT)); /* if we're right and not in duplicates, stop here */ if (node->bit >= 0) break; t = node->node_p; } else { /* Walking up from left branch. We must ensure that we never * walk beyond root. */ 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; } } /* Note that cannot be NULL at this stage */ t = (eb_untag(t, EB_RGHT))->b[EB_LEFT]; return eb_walk_down(t, EB_RGHT); } /* Return next leaf node after an existing leaf node, skipping duplicates, or * NULL if none. */ static inline struct eb_node *eb_next_unique(struct eb_node *node) { eb_troot_t *t = node->leaf_p; while (1) { if (eb_gettag(t) == EB_LEFT) { 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 */ if (node->bit >= 0) break; t = node->node_p; } else { /* Walking up from right branch, so we cannot be below root */ t = (eb_root_to_node(eb_untag(t, EB_RGHT)))->node_p; } } /* Note that 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); } /* Removes a leaf node from the tree if it was still in it. Marks the node * as unlinked. */ static forceinline void __eb_delete(struct eb_node *node) { __label__ delete_unlink; unsigned int pside, gpside, sibtype; struct eb_node *parent; struct eb_root *gparent; if (!node->leaf_p) return; /* we need the parent, our side, and the grand parent */ pside = eb_gettag(node->leaf_p); parent = eb_root_to_node(eb_untag(node->leaf_p, pside)); /* We likely have to release the parent link, unless it's the root, * in which case we only set our branch to NULL. Note that we can * only be attached to the root by its left branch. */ 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; } /* To release our parent, we have to identify our sibling, and reparent * it directly to/from the grand parent. Note that the sibling can * either be a link or a leaf. */ gpside = eb_gettag(parent->node_p); gparent = eb_untag(parent->node_p, gpside); gparent->b[gpside] = parent->branches.b[!pside]; sibtype = eb_gettag(gparent->b[gpside]); if (sibtype == EB_LEAF) { eb_root_to_node(eb_untag(gparent->b[gpside], EB_LEAF))->leaf_p = eb_dotag(gparent, gpside); } else { eb_root_to_node(eb_untag(gparent->b[gpside], EB_NODE))->node_p = eb_dotag(gparent, gpside); } /* Mark the parent unused. Note that we do not check if the parent is * our own node, but that's not a problem because if it is, it will be * marked unused at the same time, which we'll use below to know we can * safely remove it. */ parent->node_p = NULL; /* The parent node has been detached, and is currently unused. It may * belong to another node, so we cannot remove it that way. Also, our * own node part might still be used. so we can use this spare node * to replace ours if needed. */ /* If our link part is unused, we can safely exit now */ if (!node->node_p) goto delete_unlink; /* From now on, and are necessarily different, and the * 's node part is in use. By definition, is at least * below , so keeping its key for the bit string is OK. */ parent->node_p = node->node_p; parent->branches = node->branches; parent->bit = node->bit; /* We must now update the new node's parent... */ gpside = eb_gettag(parent->node_p); gparent = eb_untag(parent->node_p, gpside); gparent->b[gpside] = eb_dotag(&parent->branches, EB_NODE); /* ... and its branches */ for (pside = 0; pside <= 1; pside++) { if (eb_gettag(parent->branches.b[pside]) == EB_NODE) { eb_root_to_node(eb_untag(parent->branches.b[pside], EB_NODE))->node_p = eb_dotag(&parent->branches, pside); } else { eb_root_to_node(eb_untag(parent->branches.b[pside], EB_LEAF))->leaf_p = eb_dotag(&parent->branches, pside); } } delete_unlink: /* Now the node has been completely unlinked */ node->leaf_p = NULL; return; /* tree is not empty yet */ } /* Compare blocks and byte-to-byte, from bit to bit . * Return the number of equal bits between strings, assuming that the first * bits are already identical. It is possible to return slightly more * than bits if does not stop on a byte boundary and we find exact * bytes. Note that parts or all of bits may be rechecked. It is only * passed here as a hint to speed up the check. */ static forceinline int equal_bits(const unsigned char *a, const unsigned char *b, int ignore, int len) { for (ignore >>= 3, a += ignore, b += ignore, ignore <<= 3; ignore < len; ) { unsigned char c; a++; b++; ignore += 8; c = b[-1] ^ a[-1]; if (c) { /* OK now we know that old and new differ at byte and that holds * the bit differences. We have to find what bit is differing and report * it as the number of identical bits. Note that low bit numbers are * assigned to high positions in the byte, as we compare them as strings. */ ignore -= flsnz8(c); break; } } return ignore; } /* check that the two blocks and are equal on bits. If it is known * they already are on some bytes, this number of equal bytes to be skipped may * be passed in . It returns 0 if they match, otherwise non-zero. */ static forceinline int check_bits(const unsigned char *a, const unsigned char *b, int skip, int len) { int bit, ret; /* This uncommon construction gives the best performance on x86 because * it makes heavy use multiple-index addressing and parallel instructions, * and it prevents gcc from reordering the loop since it is already * properly oriented. Tested to be fine with 2.95 to 4.2. */ bit = ~len + (skip << 3) + 9; // = (skip << 3) + (8 - len) ret = a[skip] ^ b[skip]; if (unlikely(bit >= 0)) return ret >> bit; while (1) { skip++; if (ret) return ret; ret = a[skip] ^ b[skip]; bit += 8; if (bit >= 0) return ret >> bit; } } /* Compare strings and byte-to-byte, from bit to the last 0. * Return the number of equal bits between strings, assuming that the first * bits are already identical. Note that parts or all of bits * may be rechecked. It is only passed here as a hint to speed up the check. * The caller is responsible for not passing an value larger than any * of the two strings. However, referencing any bit from the trailing zero is * permitted. Equal strings are reported as a negative number of bits, which * indicates the end was reached. */ static forceinline int string_equal_bits(const unsigned char *a, const unsigned char *b, int ignore) { int beg; unsigned char c; beg = ignore >> 3; /* skip known and identical bits. We stop at the first different byte * or at the first zero we encounter on either side. */ while (1) { unsigned char d; c = a[beg]; d = b[beg]; beg++; c ^= d; if (c) break; if (!d) return -1; } /* OK now we know that a and b differ at byte , or that both are zero. * We have to find what bit is differing and report it as the number of * identical bits. Note that low bit numbers are assigned to high positions * in the byte, as we compare them as strings. */ return (beg << 3) - flsnz8(c); } static forceinline int cmp_bits(const unsigned char *a, const unsigned char *b, unsigned int pos) { unsigned int ofs; unsigned char bit_a, bit_b; ofs = pos >> 3; pos = ~pos & 7; bit_a = (a[ofs] >> pos) & 1; bit_b = (b[ofs] >> pos) & 1; return bit_a - bit_b; /* -1: ab */ } static forceinline int get_bit(const unsigned char *a, unsigned int pos) { unsigned int ofs; ofs = pos >> 3; pos = ~pos & 7; return (a[ofs] >> pos) & 1; } /* These functions are declared in ebtree.c */ void eb_delete(struct eb_node *node); REGPRM1 struct eb_node *eb_insert_dup(struct eb_node *sub, struct eb_node *new); #endif /* _EB_TREE_H */ /* * Local variables: * c-indent-level: 8 * c-basic-offset: 8 * End: */