replace rbtree implementation with tree.h from freebsd
added tree.h from freebsd repository and ported our name cache and client owner code Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
91f584ba4b
commit
32f9fa9334
7 changed files with 837 additions and 715 deletions
|
|
@ -215,7 +215,6 @@
|
||||||
<ClCompile Include="..\daemon\pnfs_device.c" />
|
<ClCompile Include="..\daemon\pnfs_device.c" />
|
||||||
<ClCompile Include="..\daemon\pnfs_io.c" />
|
<ClCompile Include="..\daemon\pnfs_io.c" />
|
||||||
<ClCompile Include="..\daemon\pnfs_layout.c" />
|
<ClCompile Include="..\daemon\pnfs_layout.c" />
|
||||||
<ClCompile Include="..\daemon\rbtree.c" />
|
|
||||||
<ClCompile Include="..\daemon\readdir.c" />
|
<ClCompile Include="..\daemon\readdir.c" />
|
||||||
<ClCompile Include="..\daemon\readwrite.c" />
|
<ClCompile Include="..\daemon\readwrite.c" />
|
||||||
<ClCompile Include="..\daemon\service.c" />
|
<ClCompile Include="..\daemon\service.c" />
|
||||||
|
|
@ -239,8 +238,8 @@
|
||||||
<ClInclude Include="..\daemon\nfs41_types.h" />
|
<ClInclude Include="..\daemon\nfs41_types.h" />
|
||||||
<ClInclude Include="..\daemon\nfs41_xdr.h" />
|
<ClInclude Include="..\daemon\nfs41_xdr.h" />
|
||||||
<ClInclude Include="..\daemon\pnfs.h" />
|
<ClInclude Include="..\daemon\pnfs.h" />
|
||||||
<ClInclude Include="..\daemon\rbtree.h" />
|
|
||||||
<ClInclude Include="..\daemon\service.h" />
|
<ClInclude Include="..\daemon\service.h" />
|
||||||
|
<ClInclude Include="..\daemon\tree.h" />
|
||||||
<ClInclude Include="..\daemon\upcall.h" />
|
<ClInclude Include="..\daemon\upcall.h" />
|
||||||
<ClInclude Include="..\daemon\util.h" />
|
<ClInclude Include="..\daemon\util.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,6 @@
|
||||||
<ClCompile Include="..\daemon\lookup.c">
|
<ClCompile Include="..\daemon\lookup.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\daemon\rbtree.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\daemon\name_cache.c">
|
<ClCompile Include="..\daemon\name_cache.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -151,9 +148,6 @@
|
||||||
<ClInclude Include="..\daemon\list.h">
|
<ClInclude Include="..\daemon\list.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\daemon\rbtree.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\daemon\name_cache.h">
|
<ClInclude Include="..\daemon\name_cache.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -166,6 +160,9 @@
|
||||||
<ClInclude Include="..\daemon\idmap.h">
|
<ClInclude Include="..\daemon\idmap.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\daemon\tree.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\daemon\sources">
|
<None Include="..\daemon\sources">
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
#include "nfs41_compound.h"
|
#include "nfs41_compound.h"
|
||||||
#include "name_cache.h"
|
#include "name_cache.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "rbtree.h"
|
#include "tree.h"
|
||||||
#include "daemon_debug.h"
|
#include "daemon_debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ enum {
|
||||||
|
|
||||||
/* attribute cache */
|
/* attribute cache */
|
||||||
struct attr_cache_entry {
|
struct attr_cache_entry {
|
||||||
struct rb_node rbnode;
|
RB_ENTRY(attr_cache_entry) rbnode;
|
||||||
struct list_entry free_entry;
|
struct list_entry free_entry;
|
||||||
uint64_t change;
|
uint64_t change;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
|
@ -75,12 +75,20 @@ struct attr_cache_entry {
|
||||||
};
|
};
|
||||||
#define ATTR_ENTRY_SIZE sizeof(struct attr_cache_entry)
|
#define ATTR_ENTRY_SIZE sizeof(struct attr_cache_entry)
|
||||||
|
|
||||||
|
RB_HEAD(attr_tree, attr_cache_entry);
|
||||||
|
|
||||||
struct attr_cache {
|
struct attr_cache {
|
||||||
struct rb_root root;
|
struct attr_tree head;
|
||||||
struct attr_cache_entry *pool;
|
struct attr_cache_entry *pool;
|
||||||
struct list_entry free_entries;
|
struct list_entry free_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int attr_cmp(struct attr_cache_entry *lhs, struct attr_cache_entry *rhs)
|
||||||
|
{
|
||||||
|
return lhs->fileid < rhs->fileid ? -1 : lhs->fileid > rhs->fileid;
|
||||||
|
}
|
||||||
|
RB_GENERATE(attr_tree, attr_cache_entry, rbnode, attr_cmp)
|
||||||
|
|
||||||
|
|
||||||
/* attr_cache_entry */
|
/* attr_cache_entry */
|
||||||
#define attr_entry(pos) list_container(pos, struct attr_cache_entry, free_entry)
|
#define attr_entry(pos) list_container(pos, struct attr_cache_entry, free_entry)
|
||||||
|
|
@ -112,7 +120,7 @@ static __inline void attr_cache_entry_free(
|
||||||
IN struct attr_cache_entry *entry)
|
IN struct attr_cache_entry *entry)
|
||||||
{
|
{
|
||||||
dprintf(NCLVL1, "attr_cache_entry_free(%llu)\n", entry->fileid);
|
dprintf(NCLVL1, "attr_cache_entry_free(%llu)\n", entry->fileid);
|
||||||
rb_erase(&entry->rbnode, &cache->root);
|
RB_REMOVE(attr_tree, &cache->head, entry);
|
||||||
/* add it back to free_entries */
|
/* add it back to free_entries */
|
||||||
list_add_tail(&cache->free_entries, &entry->free_entry);
|
list_add_tail(&cache->free_entries, &entry->free_entry);
|
||||||
}
|
}
|
||||||
|
|
@ -176,32 +184,10 @@ static struct attr_cache_entry* attr_cache_search(
|
||||||
IN struct attr_cache *cache,
|
IN struct attr_cache *cache,
|
||||||
IN uint64_t fileid)
|
IN uint64_t fileid)
|
||||||
{
|
{
|
||||||
struct rb_node *node;
|
/* find an entry that matches fileid */
|
||||||
struct attr_cache_entry *entry;
|
struct attr_cache_entry tmp;
|
||||||
|
tmp.fileid = fileid;
|
||||||
dprintf(NCLVL2, "--> attr_cache_search(%llu)\n", fileid);
|
return RB_FIND(attr_tree, &cache->head, &tmp);
|
||||||
|
|
||||||
entry = NULL;
|
|
||||||
node = cache->root.rb_node;
|
|
||||||
|
|
||||||
while (node) {
|
|
||||||
entry = rb_entry(node, struct attr_cache_entry, rbnode);
|
|
||||||
|
|
||||||
if (fileid < entry->fileid)
|
|
||||||
node = node->rb_left;
|
|
||||||
else if (fileid > entry->fileid)
|
|
||||||
node = node->rb_right;
|
|
||||||
else {
|
|
||||||
dprintf(NCLVL2, "<-- attr_cache_search() "
|
|
||||||
"found existing entry 0x%p\n", entry);
|
|
||||||
goto out_success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry = NULL;
|
|
||||||
dprintf(NCLVL2, "<-- attr_cache_search() returning NULL\n");
|
|
||||||
|
|
||||||
out_success:
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int attr_cache_insert(
|
static int attr_cache_insert(
|
||||||
|
|
@ -209,31 +195,12 @@ static int attr_cache_insert(
|
||||||
IN struct attr_cache_entry *entry)
|
IN struct attr_cache_entry *entry)
|
||||||
{
|
{
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
struct rb_node **node, *prev;
|
|
||||||
struct attr_cache_entry *current;
|
|
||||||
|
|
||||||
dprintf(NCLVL2, "--> attr_cache_insert(%llu)\n", entry->fileid);
|
dprintf(NCLVL2, "--> attr_cache_insert(%llu)\n", entry->fileid);
|
||||||
|
|
||||||
node = &cache->root.rb_node;
|
if (RB_INSERT(attr_tree, &cache->head, entry))
|
||||||
prev = NULL;
|
status = ERROR_FILE_EXISTS;
|
||||||
|
|
||||||
while (*node) {
|
|
||||||
current = rb_entry(*node, struct attr_cache_entry, rbnode);
|
|
||||||
|
|
||||||
prev = *node;
|
|
||||||
if (entry->fileid < current->fileid)
|
|
||||||
node = &(*node)->rb_left;
|
|
||||||
else if (entry->fileid > current->fileid)
|
|
||||||
node = &(*node)->rb_right;
|
|
||||||
else {
|
|
||||||
status = ERROR_FILE_EXISTS;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_link_node(&entry->rbnode, prev, node);
|
|
||||||
rb_insert_color(&entry->rbnode, &cache->root);
|
|
||||||
out:
|
|
||||||
dprintf(NCLVL2, "<-- attr_cache_insert() returning %d\n", status);
|
dprintf(NCLVL2, "<-- attr_cache_insert() returning %d\n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -331,11 +298,12 @@ static void copy_attrs(
|
||||||
|
|
||||||
|
|
||||||
/* name cache */
|
/* name cache */
|
||||||
|
RB_HEAD(name_tree, name_cache_entry);
|
||||||
struct name_cache_entry {
|
struct name_cache_entry {
|
||||||
char component[NFS41_MAX_COMPONENT_SIZE];
|
char component[NFS41_MAX_COMPONENT_SIZE];
|
||||||
nfs41_fh fh;
|
nfs41_fh fh;
|
||||||
struct rb_node rbnode;
|
RB_ENTRY(name_cache_entry) rbnode;
|
||||||
struct rb_root rbchildren;
|
struct name_tree rbchildren;
|
||||||
struct attr_cache_entry *attributes;
|
struct attr_cache_entry *attributes;
|
||||||
struct name_cache_entry *parent;
|
struct name_cache_entry *parent;
|
||||||
struct list_entry exp_entry;
|
struct list_entry exp_entry;
|
||||||
|
|
@ -344,6 +312,13 @@ struct name_cache_entry {
|
||||||
};
|
};
|
||||||
#define NAME_ENTRY_SIZE sizeof(struct name_cache_entry)
|
#define NAME_ENTRY_SIZE sizeof(struct name_cache_entry)
|
||||||
|
|
||||||
|
int name_cmp(struct name_cache_entry *lhs, struct name_cache_entry *rhs)
|
||||||
|
{
|
||||||
|
const int diff = rhs->component_len - lhs->component_len;
|
||||||
|
return diff ? diff : strncmp(lhs->component, rhs->component, lhs->component_len);
|
||||||
|
}
|
||||||
|
RB_GENERATE(name_tree, name_cache_entry, rbnode, name_cmp)
|
||||||
|
|
||||||
struct nfs41_name_cache {
|
struct nfs41_name_cache {
|
||||||
struct name_cache_entry *root;
|
struct name_cache_entry *root;
|
||||||
struct name_cache_entry *pool;
|
struct name_cache_entry *pool;
|
||||||
|
|
@ -380,7 +355,7 @@ static __inline void name_cache_remove(
|
||||||
IN struct name_cache_entry *entry,
|
IN struct name_cache_entry *entry,
|
||||||
IN struct name_cache_entry *parent)
|
IN struct name_cache_entry *parent)
|
||||||
{
|
{
|
||||||
rb_erase(&entry->rbnode, &parent->rbchildren);
|
RB_REMOVE(name_tree, &parent->rbchildren, entry);
|
||||||
entry->parent = NULL;
|
entry->parent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,14 +389,9 @@ static void name_cache_unlink_children_recursive(
|
||||||
IN struct nfs41_name_cache *cache,
|
IN struct nfs41_name_cache *cache,
|
||||||
IN struct name_cache_entry *parent)
|
IN struct name_cache_entry *parent)
|
||||||
{
|
{
|
||||||
struct name_cache_entry *entry;
|
struct name_cache_entry *entry, *tmp;
|
||||||
struct rb_node *node = rb_first(&parent->rbchildren);
|
RB_FOREACH_SAFE(entry, name_tree, &parent->rbchildren, tmp)
|
||||||
|
|
||||||
while (node) {
|
|
||||||
entry = rb_entry(node, struct name_cache_entry, rbnode);
|
|
||||||
node = rb_next(node);
|
|
||||||
name_cache_unlink(cache, entry);
|
name_cache_unlink(cache, entry);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int name_cache_entry_create(
|
static int name_cache_entry_create(
|
||||||
|
|
@ -531,51 +501,26 @@ static void name_cache_entry_invalidate(
|
||||||
name_cache_unlink(cache, entry);
|
name_cache_unlink(cache, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int component_cmp(
|
|
||||||
IN const char *lhs,
|
|
||||||
IN unsigned short lhs_len,
|
|
||||||
IN const char *rhs,
|
|
||||||
IN unsigned short rhs_len)
|
|
||||||
{
|
|
||||||
const int diff = rhs_len - lhs_len;
|
|
||||||
return diff ? diff : strncmp(lhs, rhs, lhs_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct name_cache_entry* name_cache_search(
|
static struct name_cache_entry* name_cache_search(
|
||||||
IN struct nfs41_name_cache *cache,
|
IN struct nfs41_name_cache *cache,
|
||||||
IN struct name_cache_entry *parent,
|
IN struct name_cache_entry *parent,
|
||||||
IN const nfs41_component *component)
|
IN const nfs41_component *component)
|
||||||
{
|
{
|
||||||
struct rb_node *node;
|
struct name_cache_entry tmp, *entry;
|
||||||
struct name_cache_entry *entry;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
dprintf(NCLVL2, "--> name_cache_search('%.*s' under '%s')\n",
|
dprintf(NCLVL2, "--> name_cache_search('%.*s' under '%s')\n",
|
||||||
component->len, component->name, parent->component);
|
component->len, component->name, parent->component);
|
||||||
|
|
||||||
entry = NULL;
|
StringCchCopyNA(tmp.component, NFS41_MAX_COMPONENT_SIZE,
|
||||||
node = parent->rbchildren.rb_node;
|
component->name, component->len);
|
||||||
|
tmp.component_len = component->len;
|
||||||
|
|
||||||
while (node) {
|
entry = RB_FIND(name_tree, &parent->rbchildren, &tmp);
|
||||||
entry = rb_entry(node, struct name_cache_entry, rbnode);
|
if (entry)
|
||||||
|
dprintf(NCLVL2, "<-- name_cache_search() "
|
||||||
result = component_cmp(component->name, component->len,
|
"found existing entry 0x%p\n", entry);
|
||||||
entry->component, entry->component_len);
|
else
|
||||||
|
dprintf(NCLVL2, "<-- name_cache_search() returning NULL\n");
|
||||||
if (result < 0)
|
|
||||||
node = node->rb_left;
|
|
||||||
else if (result > 0)
|
|
||||||
node = node->rb_right;
|
|
||||||
else {
|
|
||||||
dprintf(NCLVL2, "<-- name_cache_search() "
|
|
||||||
"found existing entry 0x%p\n", entry);
|
|
||||||
goto out_success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry = NULL;
|
|
||||||
dprintf(NCLVL2, "<-- name_cache_search() returning NULL\n");
|
|
||||||
|
|
||||||
out_success:
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -654,38 +599,13 @@ static int name_cache_insert(
|
||||||
IN struct name_cache_entry *entry,
|
IN struct name_cache_entry *entry,
|
||||||
IN struct name_cache_entry *parent)
|
IN struct name_cache_entry *parent)
|
||||||
{
|
{
|
||||||
int result, status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
struct rb_node **node, *prev;
|
|
||||||
struct name_cache_entry *current;
|
|
||||||
|
|
||||||
dprintf(NCLVL2, "--> name_cache_insert('%s')\n", entry->component);
|
dprintf(NCLVL2, "--> name_cache_insert('%s')\n", entry->component);
|
||||||
|
|
||||||
node = &parent->rbchildren.rb_node;
|
if (RB_INSERT(name_tree, &parent->rbchildren, entry))
|
||||||
prev = NULL;
|
status = ERROR_FILE_EXISTS;
|
||||||
|
|
||||||
while (*node) {
|
|
||||||
current = rb_entry(*node, struct name_cache_entry, rbnode);
|
|
||||||
|
|
||||||
result = component_cmp(entry->component, entry->component_len,
|
|
||||||
current->component, current->component_len);
|
|
||||||
|
|
||||||
prev = *node;
|
|
||||||
if (result < 0)
|
|
||||||
node = &(*node)->rb_left;
|
|
||||||
else if (result > 0)
|
|
||||||
node = &(*node)->rb_right;
|
|
||||||
else {
|
|
||||||
status = ERROR_FILE_EXISTS;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current = NULL;
|
|
||||||
|
|
||||||
rb_link_node(&entry->rbnode, prev, node);
|
|
||||||
rb_insert_color(&entry->rbnode, &parent->rbchildren);
|
|
||||||
entry->parent = parent;
|
|
||||||
|
|
||||||
out:
|
|
||||||
dprintf(NCLVL2, "<-- name_cache_insert() returning %u\n", status);
|
dprintf(NCLVL2, "<-- name_cache_insert() returning %u\n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
#include <iphlpapi.h> /* for GetAdaptersAddresses() */
|
#include <iphlpapi.h> /* for GetAdaptersAddresses() */
|
||||||
#include <wincrypt.h> /* for Crypt*() functions */
|
#include <wincrypt.h> /* for Crypt*() functions */
|
||||||
|
|
||||||
#include "rbtree.h"
|
#include "tree.h"
|
||||||
#include "daemon_debug.h"
|
#include "daemon_debug.h"
|
||||||
#include "nfs41_ops.h"
|
#include "nfs41_ops.h"
|
||||||
|
|
||||||
|
|
@ -253,47 +253,36 @@ void nfs41_client_free(
|
||||||
|
|
||||||
/* use an rbtree to sort mac address entries */
|
/* use an rbtree to sort mac address entries */
|
||||||
struct mac_entry {
|
struct mac_entry {
|
||||||
struct rb_node rbnode;
|
RB_ENTRY(mac_entry) rbnode;
|
||||||
PBYTE address;
|
PBYTE address;
|
||||||
ULONG length;
|
ULONG length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int mac_cmp(struct mac_entry *lhs, struct mac_entry *rhs)
|
||||||
|
{
|
||||||
|
const int diff = rhs->length - lhs->length;
|
||||||
|
return diff ? diff : strncmp((const char*)lhs->address,
|
||||||
|
(const char*)rhs->address, lhs->length);
|
||||||
|
}
|
||||||
|
RB_HEAD(mac_tree, mac_entry);
|
||||||
|
RB_GENERATE(mac_tree, mac_entry, rbnode, mac_cmp)
|
||||||
|
|
||||||
static void mac_entry_insert(
|
static void mac_entry_insert(
|
||||||
IN struct rb_root *root,
|
IN struct mac_tree *root,
|
||||||
IN PBYTE address,
|
IN PBYTE address,
|
||||||
IN ULONG length)
|
IN ULONG length)
|
||||||
{
|
{
|
||||||
struct rb_node **node, *prev;
|
|
||||||
struct mac_entry *entry;
|
struct mac_entry *entry;
|
||||||
int diff;
|
|
||||||
|
|
||||||
node = &root->rb_node;
|
|
||||||
prev = NULL;
|
|
||||||
|
|
||||||
while (*node) {
|
|
||||||
entry = rb_entry(*node, struct mac_entry, rbnode);
|
|
||||||
prev = *node;
|
|
||||||
|
|
||||||
diff = length - entry->length;
|
|
||||||
if (diff == 0)
|
|
||||||
diff = memcmp(address, entry->address, length);
|
|
||||||
|
|
||||||
if (diff < 0)
|
|
||||||
node = &(*node)->rb_left;
|
|
||||||
else if (diff > 0)
|
|
||||||
node = &(*node)->rb_right;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = calloc(1, sizeof(struct mac_entry));
|
entry = calloc(1, sizeof(struct mac_entry));
|
||||||
if (entry) {
|
if (entry == NULL)
|
||||||
entry->address = address;
|
return;
|
||||||
entry->length = length;
|
|
||||||
|
|
||||||
rb_link_node(&entry->rbnode, prev, node);
|
entry->address = address;
|
||||||
rb_insert_color(&entry->rbnode, root);
|
entry->length = length;
|
||||||
}
|
|
||||||
|
if (RB_INSERT(mac_tree, root, entry))
|
||||||
|
free(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adapter_valid(
|
static int adapter_valid(
|
||||||
|
|
@ -316,9 +305,8 @@ static DWORD hash_mac_addrs(
|
||||||
IN HCRYPTHASH hash)
|
IN HCRYPTHASH hash)
|
||||||
{
|
{
|
||||||
PIP_ADAPTER_ADDRESSES addr, addrs = NULL;
|
PIP_ADAPTER_ADDRESSES addr, addrs = NULL;
|
||||||
struct rb_root rbtree = { NULL };
|
struct mac_tree rbtree = RB_INITIALIZER(rbtree);
|
||||||
struct rb_node *node;
|
struct mac_entry *entry, *node;
|
||||||
struct mac_entry *entry;
|
|
||||||
ULONG len;
|
ULONG len;
|
||||||
DWORD status;
|
DWORD status;
|
||||||
|
|
||||||
|
|
@ -353,18 +341,15 @@ static DWORD hash_mac_addrs(
|
||||||
addr->PhysicalAddressLength);
|
addr->PhysicalAddressLength);
|
||||||
|
|
||||||
/* require at least one valid address */
|
/* require at least one valid address */
|
||||||
node = rb_first(&rbtree);
|
if (RB_EMPTY(&rbtree)) {
|
||||||
if (node == NULL) {
|
|
||||||
status = ERROR_FILE_NOT_FOUND;
|
status = ERROR_FILE_NOT_FOUND;
|
||||||
eprintf("GetAdaptersAddresses() did not return "
|
eprintf("GetAdaptersAddresses() did not return "
|
||||||
"any valid mac addresses, failing with %d.\n", status);
|
"any valid mac addresses, failing with %d.\n", status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (node) {
|
RB_FOREACH_SAFE(entry, mac_tree, &rbtree, node) {
|
||||||
entry = rb_entry(node, struct mac_entry, rbnode);
|
RB_REMOVE(mac_tree, &rbtree, entry);
|
||||||
node = rb_next(node);
|
|
||||||
rb_erase(&entry->rbnode, &rbtree);
|
|
||||||
|
|
||||||
if (!CryptHashData(hash, entry->address, entry->length, 0)) {
|
if (!CryptHashData(hash, entry->address, entry->length, 0)) {
|
||||||
status = GetLastError();
|
status = GetLastError();
|
||||||
|
|
|
||||||
385
daemon/rbtree.c
385
daemon/rbtree.c
|
|
@ -1,385 +0,0 @@
|
||||||
/*
|
|
||||||
Red Black Trees
|
|
||||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
|
||||||
(C) 2002 David Woodhouse <dwmw2@infradead.org>
|
|
||||||
|
|
||||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
linux/lib/rbtree.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rbtree.h"
|
|
||||||
|
|
||||||
#pragma warning(disable:4706)
|
|
||||||
|
|
||||||
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *right = node->rb_right;
|
|
||||||
struct rb_node *parent = rb_parent(node);
|
|
||||||
|
|
||||||
if ((node->rb_right = right->rb_left))
|
|
||||||
rb_set_parent(right->rb_left, node);
|
|
||||||
right->rb_left = node;
|
|
||||||
|
|
||||||
rb_set_parent(right, parent);
|
|
||||||
|
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
if (node == parent->rb_left)
|
|
||||||
parent->rb_left = right;
|
|
||||||
else
|
|
||||||
parent->rb_right = right;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
root->rb_node = right;
|
|
||||||
rb_set_parent(node, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *left = node->rb_left;
|
|
||||||
struct rb_node *parent = rb_parent(node);
|
|
||||||
|
|
||||||
if ((node->rb_left = left->rb_right))
|
|
||||||
rb_set_parent(left->rb_right, node);
|
|
||||||
left->rb_right = node;
|
|
||||||
|
|
||||||
rb_set_parent(left, parent);
|
|
||||||
|
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
if (node == parent->rb_right)
|
|
||||||
parent->rb_right = left;
|
|
||||||
else
|
|
||||||
parent->rb_left = left;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
root->rb_node = left;
|
|
||||||
rb_set_parent(node, left);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rb_insert_color(struct rb_node *node, struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *parent, *gparent;
|
|
||||||
|
|
||||||
while ((parent = rb_parent(node)) && rb_is_red(parent))
|
|
||||||
{
|
|
||||||
gparent = rb_parent(parent);
|
|
||||||
|
|
||||||
if (parent == gparent->rb_left)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
register struct rb_node *uncle = gparent->rb_right;
|
|
||||||
if (uncle && rb_is_red(uncle))
|
|
||||||
{
|
|
||||||
rb_set_black(uncle);
|
|
||||||
rb_set_black(parent);
|
|
||||||
rb_set_red(gparent);
|
|
||||||
node = gparent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent->rb_right == node)
|
|
||||||
{
|
|
||||||
register struct rb_node *tmp;
|
|
||||||
__rb_rotate_left(parent, root);
|
|
||||||
tmp = parent;
|
|
||||||
parent = node;
|
|
||||||
node = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_set_black(parent);
|
|
||||||
rb_set_red(gparent);
|
|
||||||
__rb_rotate_right(gparent, root);
|
|
||||||
} else {
|
|
||||||
{
|
|
||||||
register struct rb_node *uncle = gparent->rb_left;
|
|
||||||
if (uncle && rb_is_red(uncle))
|
|
||||||
{
|
|
||||||
rb_set_black(uncle);
|
|
||||||
rb_set_black(parent);
|
|
||||||
rb_set_red(gparent);
|
|
||||||
node = gparent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent->rb_left == node)
|
|
||||||
{
|
|
||||||
register struct rb_node *tmp;
|
|
||||||
__rb_rotate_right(parent, root);
|
|
||||||
tmp = parent;
|
|
||||||
parent = node;
|
|
||||||
node = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_set_black(parent);
|
|
||||||
rb_set_red(gparent);
|
|
||||||
__rb_rotate_left(gparent, root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_set_black(root->rb_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
|
|
||||||
struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *other;
|
|
||||||
|
|
||||||
while ((!node || rb_is_black(node)) && node != root->rb_node)
|
|
||||||
{
|
|
||||||
if (parent->rb_left == node)
|
|
||||||
{
|
|
||||||
other = parent->rb_right;
|
|
||||||
if (rb_is_red(other))
|
|
||||||
{
|
|
||||||
rb_set_black(other);
|
|
||||||
rb_set_red(parent);
|
|
||||||
__rb_rotate_left(parent, root);
|
|
||||||
other = parent->rb_right;
|
|
||||||
}
|
|
||||||
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
|
||||||
(!other->rb_right || rb_is_black(other->rb_right)))
|
|
||||||
{
|
|
||||||
rb_set_red(other);
|
|
||||||
node = parent;
|
|
||||||
parent = rb_parent(node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!other->rb_right || rb_is_black(other->rb_right))
|
|
||||||
{
|
|
||||||
rb_set_black(other->rb_left);
|
|
||||||
rb_set_red(other);
|
|
||||||
__rb_rotate_right(other, root);
|
|
||||||
other = parent->rb_right;
|
|
||||||
}
|
|
||||||
rb_set_color(other, rb_color(parent));
|
|
||||||
rb_set_black(parent);
|
|
||||||
rb_set_black(other->rb_right);
|
|
||||||
__rb_rotate_left(parent, root);
|
|
||||||
node = root->rb_node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
other = parent->rb_left;
|
|
||||||
if (rb_is_red(other))
|
|
||||||
{
|
|
||||||
rb_set_black(other);
|
|
||||||
rb_set_red(parent);
|
|
||||||
__rb_rotate_right(parent, root);
|
|
||||||
other = parent->rb_left;
|
|
||||||
}
|
|
||||||
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
|
||||||
(!other->rb_right || rb_is_black(other->rb_right)))
|
|
||||||
{
|
|
||||||
rb_set_red(other);
|
|
||||||
node = parent;
|
|
||||||
parent = rb_parent(node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!other->rb_left || rb_is_black(other->rb_left))
|
|
||||||
{
|
|
||||||
rb_set_black(other->rb_right);
|
|
||||||
rb_set_red(other);
|
|
||||||
__rb_rotate_left(other, root);
|
|
||||||
other = parent->rb_left;
|
|
||||||
}
|
|
||||||
rb_set_color(other, rb_color(parent));
|
|
||||||
rb_set_black(parent);
|
|
||||||
rb_set_black(other->rb_left);
|
|
||||||
__rb_rotate_right(parent, root);
|
|
||||||
node = root->rb_node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node)
|
|
||||||
rb_set_black(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rb_erase(struct rb_node *node, struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *child, *parent;
|
|
||||||
int color;
|
|
||||||
|
|
||||||
if (!node->rb_left)
|
|
||||||
child = node->rb_right;
|
|
||||||
else if (!node->rb_right)
|
|
||||||
child = node->rb_left;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct rb_node *old = node, *left;
|
|
||||||
|
|
||||||
node = node->rb_right;
|
|
||||||
while ((left = node->rb_left) != NULL)
|
|
||||||
node = left;
|
|
||||||
|
|
||||||
if (rb_parent(old)) {
|
|
||||||
if (rb_parent(old)->rb_left == old)
|
|
||||||
rb_parent(old)->rb_left = node;
|
|
||||||
else
|
|
||||||
rb_parent(old)->rb_right = node;
|
|
||||||
} else
|
|
||||||
root->rb_node = node;
|
|
||||||
|
|
||||||
child = node->rb_right;
|
|
||||||
parent = rb_parent(node);
|
|
||||||
color = rb_color(node);
|
|
||||||
|
|
||||||
if (parent == old) {
|
|
||||||
parent = node;
|
|
||||||
} else {
|
|
||||||
if (child)
|
|
||||||
rb_set_parent(child, parent);
|
|
||||||
parent->rb_left = child;
|
|
||||||
|
|
||||||
node->rb_right = old->rb_right;
|
|
||||||
rb_set_parent(old->rb_right, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
node->rb_parent_color = old->rb_parent_color;
|
|
||||||
node->rb_left = old->rb_left;
|
|
||||||
rb_set_parent(old->rb_left, node);
|
|
||||||
|
|
||||||
goto color;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent = rb_parent(node);
|
|
||||||
color = rb_color(node);
|
|
||||||
|
|
||||||
if (child)
|
|
||||||
rb_set_parent(child, parent);
|
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
if (parent->rb_left == node)
|
|
||||||
parent->rb_left = child;
|
|
||||||
else
|
|
||||||
parent->rb_right = child;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
root->rb_node = child;
|
|
||||||
|
|
||||||
color:
|
|
||||||
if (color == RB_BLACK)
|
|
||||||
__rb_erase_color(child, parent, root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function returns the first node (in sort order) of the tree.
|
|
||||||
*/
|
|
||||||
struct rb_node *rb_first(const struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *n;
|
|
||||||
|
|
||||||
n = root->rb_node;
|
|
||||||
if (!n)
|
|
||||||
return NULL;
|
|
||||||
while (n->rb_left)
|
|
||||||
n = n->rb_left;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_node *rb_last(const struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *n;
|
|
||||||
|
|
||||||
n = root->rb_node;
|
|
||||||
if (!n)
|
|
||||||
return NULL;
|
|
||||||
while (n->rb_right)
|
|
||||||
n = n->rb_right;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_node *rb_next(const struct rb_node *node)
|
|
||||||
{
|
|
||||||
struct rb_node *parent;
|
|
||||||
|
|
||||||
if (rb_parent(node) == node)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* If we have a right-hand child, go down and then left as far
|
|
||||||
as we can. */
|
|
||||||
if (node->rb_right) {
|
|
||||||
node = node->rb_right;
|
|
||||||
while (node->rb_left)
|
|
||||||
node=node->rb_left;
|
|
||||||
return (struct rb_node *)node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No right-hand children. Everything down and left is
|
|
||||||
smaller than us, so any 'next' node must be in the general
|
|
||||||
direction of our parent. Go up the tree; any time the
|
|
||||||
ancestor is a right-hand child of its parent, keep going
|
|
||||||
up. First time it's a left-hand child of its parent, said
|
|
||||||
parent is our 'next' node. */
|
|
||||||
while ((parent = rb_parent(node)) && node == parent->rb_right)
|
|
||||||
node = parent;
|
|
||||||
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_node *rb_prev(const struct rb_node *node)
|
|
||||||
{
|
|
||||||
struct rb_node *parent;
|
|
||||||
|
|
||||||
if (rb_parent(node) == node)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* If we have a left-hand child, go down and then right as far
|
|
||||||
as we can. */
|
|
||||||
if (node->rb_left) {
|
|
||||||
node = node->rb_left;
|
|
||||||
while (node->rb_right)
|
|
||||||
node=node->rb_right;
|
|
||||||
return (struct rb_node *)node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No left-hand children. Go up till we find an ancestor which
|
|
||||||
is a right-hand child of its parent */
|
|
||||||
while ((parent = rb_parent(node)) && node == parent->rb_left)
|
|
||||||
node = parent;
|
|
||||||
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
|
||||||
struct rb_root *root)
|
|
||||||
{
|
|
||||||
struct rb_node *parent = rb_parent(victim);
|
|
||||||
|
|
||||||
/* Set the surrounding nodes to point to the replacement */
|
|
||||||
if (parent) {
|
|
||||||
if (victim == parent->rb_left)
|
|
||||||
parent->rb_left = new;
|
|
||||||
else
|
|
||||||
parent->rb_right = new;
|
|
||||||
} else {
|
|
||||||
root->rb_node = new;
|
|
||||||
}
|
|
||||||
if (victim->rb_left)
|
|
||||||
rb_set_parent(victim->rb_left, new);
|
|
||||||
if (victim->rb_right)
|
|
||||||
rb_set_parent(victim->rb_right, new);
|
|
||||||
|
|
||||||
/* Copy the pointers/colour from the victim to the replacement */
|
|
||||||
*new = *victim;
|
|
||||||
}
|
|
||||||
159
daemon/rbtree.h
159
daemon/rbtree.h
|
|
@ -1,159 +0,0 @@
|
||||||
/*
|
|
||||||
Red Black Trees
|
|
||||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
|
||||||
|
|
||||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
linux/include/linux/rbtree.h
|
|
||||||
|
|
||||||
To use rbtrees you'll have to implement your own insert and search cores.
|
|
||||||
This will avoid us to use callbacks and to drop drammatically performances.
|
|
||||||
I know it's not the cleaner way, but in C (not in C++) to get
|
|
||||||
performances and genericity...
|
|
||||||
|
|
||||||
Some example of insert and search follows here. The search is a plain
|
|
||||||
normal search over an ordered tree. The insert instead must be implemented
|
|
||||||
int two steps: as first thing the code must insert the element in
|
|
||||||
order as a red leaf in the tree, then the support library function
|
|
||||||
rb_insert_color() must be called. Such function will do the
|
|
||||||
not trivial work to rebalance the rbtree if necessary.
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
static inline struct page * rb_search_page_cache(struct inode * inode,
|
|
||||||
unsigned long offset)
|
|
||||||
{
|
|
||||||
struct rb_node * n = inode->i_rb_page_cache.rb_node;
|
|
||||||
struct page * page;
|
|
||||||
|
|
||||||
while (n)
|
|
||||||
{
|
|
||||||
page = rb_entry(n, struct page, rb_page_cache);
|
|
||||||
|
|
||||||
if (offset < page->offset)
|
|
||||||
n = n->rb_left;
|
|
||||||
else if (offset > page->offset)
|
|
||||||
n = n->rb_right;
|
|
||||||
else
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct page * __rb_insert_page_cache(struct inode * inode,
|
|
||||||
unsigned long offset,
|
|
||||||
struct rb_node * node)
|
|
||||||
{
|
|
||||||
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
|
|
||||||
struct rb_node * parent = NULL;
|
|
||||||
struct page * page;
|
|
||||||
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
parent = *p;
|
|
||||||
page = rb_entry(parent, struct page, rb_page_cache);
|
|
||||||
|
|
||||||
if (offset < page->offset)
|
|
||||||
p = &(*p)->rb_left;
|
|
||||||
else if (offset > page->offset)
|
|
||||||
p = &(*p)->rb_right;
|
|
||||||
else
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_link_node(node, parent, p);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct page * rb_insert_page_cache(struct inode * inode,
|
|
||||||
unsigned long offset,
|
|
||||||
struct rb_node * node)
|
|
||||||
{
|
|
||||||
struct page * ret;
|
|
||||||
if ((ret = __rb_insert_page_cache(inode, offset, node)))
|
|
||||||
goto out;
|
|
||||||
rb_insert_color(node, &inode->i_rb_page_cache);
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LINUX_RBTREE_H
|
|
||||||
#define _LINUX_RBTREE_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
struct rb_node
|
|
||||||
{
|
|
||||||
size_t rb_parent_color;
|
|
||||||
#define RB_RED 0
|
|
||||||
#define RB_BLACK 1
|
|
||||||
struct rb_node *rb_right;
|
|
||||||
struct rb_node *rb_left;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rb_root
|
|
||||||
{
|
|
||||||
struct rb_node *rb_node;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
|
|
||||||
#define rb_color(r) ((r)->rb_parent_color & 1)
|
|
||||||
#define rb_is_red(r) (!rb_color(r))
|
|
||||||
#define rb_is_black(r) rb_color(r)
|
|
||||||
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
|
|
||||||
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
|
|
||||||
|
|
||||||
static __inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
|
||||||
{
|
|
||||||
rb->rb_parent_color = (rb->rb_parent_color & 3) | (size_t)p;
|
|
||||||
}
|
|
||||||
static __inline void rb_set_color(struct rb_node *rb, int color)
|
|
||||||
{
|
|
||||||
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RB_ROOT (struct rb_root) { NULL, }
|
|
||||||
#define rb_entry(ptr, type, member) CONTAINING_RECORD(ptr, type, member)
|
|
||||||
|
|
||||||
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
|
|
||||||
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
|
|
||||||
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
|
|
||||||
|
|
||||||
extern void rb_insert_color(struct rb_node *, struct rb_root *);
|
|
||||||
extern void rb_erase(struct rb_node *, struct rb_root *);
|
|
||||||
|
|
||||||
/* Find logical next and previous nodes in a tree */
|
|
||||||
extern struct rb_node *rb_next(const struct rb_node *);
|
|
||||||
extern struct rb_node *rb_prev(const struct rb_node *);
|
|
||||||
extern struct rb_node *rb_first(const struct rb_root *);
|
|
||||||
extern struct rb_node *rb_last(const struct rb_root *);
|
|
||||||
|
|
||||||
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
|
|
||||||
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
|
||||||
struct rb_root *root);
|
|
||||||
|
|
||||||
static __inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
|
||||||
struct rb_node ** rb_link)
|
|
||||||
{
|
|
||||||
node->rb_parent_color = (size_t)parent;
|
|
||||||
node->rb_left = node->rb_right = NULL;
|
|
||||||
|
|
||||||
*rb_link = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _LINUX_RBTREE_H */
|
|
||||||
765
daemon/tree.h
Normal file
765
daemon/tree.h
Normal file
|
|
@ -0,0 +1,765 @@
|
||||||
|
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
|
||||||
|
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||||
|
/* $FreeBSD: src/sys/sys/tree.h,v 1.9.2.1.4.1 2010/06/14 02:09:06 kensmith Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_TREE_H_
|
||||||
|
#define _SYS_TREE_H_
|
||||||
|
|
||||||
|
//#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file defines data structures for different types of trees:
|
||||||
|
* splay trees and red-black trees.
|
||||||
|
*
|
||||||
|
* A splay tree is a self-organizing data structure. Every operation
|
||||||
|
* on the tree causes a splay to happen. The splay moves the requested
|
||||||
|
* node to the root of the tree and partly rebalances it.
|
||||||
|
*
|
||||||
|
* This has the benefit that request locality causes faster lookups as
|
||||||
|
* the requested nodes move to the top of the tree. On the other hand,
|
||||||
|
* every lookup causes memory writes.
|
||||||
|
*
|
||||||
|
* The Balance Theorem bounds the total access time for m operations
|
||||||
|
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||||
|
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||||
|
*
|
||||||
|
* A red-black tree is a binary search tree with the node color as an
|
||||||
|
* extra attribute. It fulfills a set of conditions:
|
||||||
|
* - every search path from the root to a leaf consists of the
|
||||||
|
* same number of black nodes,
|
||||||
|
* - each red node (except for the root) has a black parent,
|
||||||
|
* - each leaf node is black.
|
||||||
|
*
|
||||||
|
* Every operation on a red-black tree is bounded as O(lg n).
|
||||||
|
* The maximum height of a red-black tree is 2lg (n+1).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SPLAY_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *sph_root; /* root of the tree */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPLAY_INITIALIZER(root) \
|
||||||
|
{ NULL }
|
||||||
|
|
||||||
|
#define SPLAY_INIT(root) do { \
|
||||||
|
(root)->sph_root = NULL; \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define SPLAY_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *spe_left; /* left element */ \
|
||||||
|
struct type *spe_right; /* right element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||||
|
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||||
|
#define SPLAY_ROOT(head) (head)->sph_root
|
||||||
|
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||||
|
|
||||||
|
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||||
|
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||||
|
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||||
|
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||||
|
(head)->sph_root = tmp; \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||||
|
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||||
|
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||||
|
(head)->sph_root = tmp; \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||||
|
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||||
|
tmp = (head)->sph_root; \
|
||||||
|
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||||
|
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||||
|
tmp = (head)->sph_root; \
|
||||||
|
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||||
|
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||||
|
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||||
|
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||||
|
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
/* Generates prototypes and inline functions */
|
||||||
|
|
||||||
|
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||||
|
void name##_SPLAY(struct name *, struct type *); \
|
||||||
|
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||||
|
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||||
|
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||||
|
\
|
||||||
|
/* Finds the node with the same key as elm */ \
|
||||||
|
static __inline struct type * \
|
||||||
|
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
if (SPLAY_EMPTY(head)) \
|
||||||
|
return(NULL); \
|
||||||
|
name##_SPLAY(head, elm); \
|
||||||
|
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||||
|
return (head->sph_root); \
|
||||||
|
return (NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static __inline struct type * \
|
||||||
|
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
name##_SPLAY(head, elm); \
|
||||||
|
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||||
|
elm = SPLAY_RIGHT(elm, field); \
|
||||||
|
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||||
|
elm = SPLAY_LEFT(elm, field); \
|
||||||
|
} \
|
||||||
|
} else \
|
||||||
|
elm = NULL; \
|
||||||
|
return (elm); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static __inline struct type * \
|
||||||
|
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||||
|
{ \
|
||||||
|
name##_SPLAY_MINMAX(head, val); \
|
||||||
|
return (SPLAY_ROOT(head)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main splay operation.
|
||||||
|
* Moves node close to the key of elm to top
|
||||||
|
*/
|
||||||
|
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||||
|
struct type * \
|
||||||
|
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
if (SPLAY_EMPTY(head)) { \
|
||||||
|
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||||
|
} else { \
|
||||||
|
int __comp; \
|
||||||
|
name##_SPLAY(head, elm); \
|
||||||
|
__comp = (cmp)(elm, (head)->sph_root); \
|
||||||
|
if(__comp < 0) { \
|
||||||
|
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||||
|
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||||
|
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||||
|
} else if (__comp > 0) { \
|
||||||
|
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||||
|
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||||
|
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||||
|
} else \
|
||||||
|
return ((head)->sph_root); \
|
||||||
|
} \
|
||||||
|
(head)->sph_root = (elm); \
|
||||||
|
return (NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
struct type * \
|
||||||
|
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *__tmp; \
|
||||||
|
if (SPLAY_EMPTY(head)) \
|
||||||
|
return (NULL); \
|
||||||
|
name##_SPLAY(head, elm); \
|
||||||
|
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||||
|
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||||
|
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||||
|
} else { \
|
||||||
|
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||||
|
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||||
|
name##_SPLAY(head, elm); \
|
||||||
|
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||||
|
} \
|
||||||
|
return (elm); \
|
||||||
|
} \
|
||||||
|
return (NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void \
|
||||||
|
name##_SPLAY(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type __node, *__left, *__right, *__tmp; \
|
||||||
|
int __comp; \
|
||||||
|
\
|
||||||
|
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||||
|
__left = __right = &__node; \
|
||||||
|
\
|
||||||
|
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||||
|
if (__comp < 0) { \
|
||||||
|
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||||
|
if (__tmp == NULL) \
|
||||||
|
break; \
|
||||||
|
if ((cmp)(elm, __tmp) < 0){ \
|
||||||
|
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||||
|
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
SPLAY_LINKLEFT(head, __right, field); \
|
||||||
|
} else if (__comp > 0) { \
|
||||||
|
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||||
|
if (__tmp == NULL) \
|
||||||
|
break; \
|
||||||
|
if ((cmp)(elm, __tmp) > 0){ \
|
||||||
|
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||||
|
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
SPLAY_LINKRIGHT(head, __left, field); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Splay with either the minimum or the maximum element \
|
||||||
|
* Used to find minimum or maximum element in tree. \
|
||||||
|
*/ \
|
||||||
|
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||||
|
{ \
|
||||||
|
struct type __node, *__left, *__right, *__tmp; \
|
||||||
|
\
|
||||||
|
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||||
|
__left = __right = &__node; \
|
||||||
|
\
|
||||||
|
while (1) { \
|
||||||
|
if (__comp < 0) { \
|
||||||
|
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||||
|
if (__tmp == NULL) \
|
||||||
|
break; \
|
||||||
|
if (__comp < 0){ \
|
||||||
|
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||||
|
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
SPLAY_LINKLEFT(head, __right, field); \
|
||||||
|
} else if (__comp > 0) { \
|
||||||
|
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||||
|
if (__tmp == NULL) \
|
||||||
|
break; \
|
||||||
|
if (__comp > 0) { \
|
||||||
|
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||||
|
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
SPLAY_LINKRIGHT(head, __left, field); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPLAY_NEGINF -1
|
||||||
|
#define SPLAY_INF 1
|
||||||
|
|
||||||
|
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||||
|
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||||
|
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||||
|
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||||
|
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||||
|
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||||
|
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||||
|
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||||
|
|
||||||
|
#define SPLAY_FOREACH(x, name, head) \
|
||||||
|
for ((x) = SPLAY_MIN(name, head); \
|
||||||
|
(x) != NULL; \
|
||||||
|
(x) = SPLAY_NEXT(name, head, x))
|
||||||
|
|
||||||
|
/* Macros that define a red-black tree */
|
||||||
|
#define RB_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *rbh_root; /* root of the tree */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RB_INITIALIZER(root) \
|
||||||
|
{ NULL }
|
||||||
|
|
||||||
|
#define RB_INIT(root) do { \
|
||||||
|
(root)->rbh_root = NULL; \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define RB_BLACK 0
|
||||||
|
#define RB_RED 1
|
||||||
|
#define RB_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *rbe_left; /* left element */ \
|
||||||
|
struct type *rbe_right; /* right element */ \
|
||||||
|
struct type *rbe_parent; /* parent element */ \
|
||||||
|
int rbe_color; /* node color */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||||
|
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||||
|
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||||
|
#define RB_COLOR(elm, field) (elm)->field.rbe_color
|
||||||
|
#define RB_ROOT(head) (head)->rbh_root
|
||||||
|
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||||
|
|
||||||
|
#define RB_SET(elm, parent, field) do { \
|
||||||
|
RB_PARENT(elm, field) = parent; \
|
||||||
|
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||||
|
RB_COLOR(elm, field) = RB_RED; \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define RB_SET_BLACKRED(black, red, field) do { \
|
||||||
|
RB_COLOR(black, field) = RB_BLACK; \
|
||||||
|
RB_COLOR(red, field) = RB_RED; \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#ifndef RB_AUGMENT
|
||||||
|
#define RB_AUGMENT(x) do {} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||||
|
(tmp) = RB_RIGHT(elm, field); \
|
||||||
|
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||||
|
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
|
||||||
|
} \
|
||||||
|
RB_AUGMENT(elm); \
|
||||||
|
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||||
|
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||||
|
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||||
|
else \
|
||||||
|
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||||
|
} else \
|
||||||
|
(head)->rbh_root = (tmp); \
|
||||||
|
RB_LEFT(tmp, field) = (elm); \
|
||||||
|
RB_PARENT(elm, field) = (tmp); \
|
||||||
|
RB_AUGMENT(tmp); \
|
||||||
|
if ((RB_PARENT(tmp, field))) \
|
||||||
|
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||||
|
(tmp) = RB_LEFT(elm, field); \
|
||||||
|
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||||
|
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
|
||||||
|
} \
|
||||||
|
RB_AUGMENT(elm); \
|
||||||
|
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||||
|
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||||
|
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||||
|
else \
|
||||||
|
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||||
|
} else \
|
||||||
|
(head)->rbh_root = (tmp); \
|
||||||
|
RB_RIGHT(tmp, field) = (elm); \
|
||||||
|
RB_PARENT(elm, field) = (tmp); \
|
||||||
|
RB_AUGMENT(tmp); \
|
||||||
|
if ((RB_PARENT(tmp, field))) \
|
||||||
|
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||||
|
} while (/*CONSTCOND*/ 0)
|
||||||
|
|
||||||
|
/* Generates prototypes and inline functions */
|
||||||
|
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||||
|
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
|
||||||
|
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
|
||||||
|
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
|
||||||
|
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
|
||||||
|
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||||
|
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||||
|
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||||
|
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||||
|
attr struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||||
|
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
|
||||||
|
attr struct type *name##_RB_NEXT(struct type *); \
|
||||||
|
attr struct type *name##_RB_PREV(struct type *); \
|
||||||
|
attr struct type *name##_RB_MINMAX(struct name *, int); \
|
||||||
|
\
|
||||||
|
|
||||||
|
/* Main rb operation.
|
||||||
|
* Moves node close to the key of elm to top
|
||||||
|
*/
|
||||||
|
#define RB_GENERATE(name, type, field, cmp) \
|
||||||
|
RB_GENERATE_INTERNAL(name, type, field, cmp,)
|
||||||
|
#define RB_GENERATE_STATIC(name, type, field, cmp) \
|
||||||
|
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
|
||||||
|
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
|
||||||
|
attr void \
|
||||||
|
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *parent, *gparent, *tmp; \
|
||||||
|
while ((parent = RB_PARENT(elm, field)) != NULL && \
|
||||||
|
RB_COLOR(parent, field) == RB_RED) { \
|
||||||
|
gparent = RB_PARENT(parent, field); \
|
||||||
|
if (parent == RB_LEFT(gparent, field)) { \
|
||||||
|
tmp = RB_RIGHT(gparent, field); \
|
||||||
|
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||||
|
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||||
|
RB_SET_BLACKRED(parent, gparent, field);\
|
||||||
|
elm = gparent; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
if (RB_RIGHT(parent, field) == elm) { \
|
||||||
|
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||||
|
tmp = parent; \
|
||||||
|
parent = elm; \
|
||||||
|
elm = tmp; \
|
||||||
|
} \
|
||||||
|
RB_SET_BLACKRED(parent, gparent, field); \
|
||||||
|
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
|
||||||
|
} else { \
|
||||||
|
tmp = RB_LEFT(gparent, field); \
|
||||||
|
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||||
|
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||||
|
RB_SET_BLACKRED(parent, gparent, field);\
|
||||||
|
elm = gparent; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
if (RB_LEFT(parent, field) == elm) { \
|
||||||
|
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||||
|
tmp = parent; \
|
||||||
|
parent = elm; \
|
||||||
|
elm = tmp; \
|
||||||
|
} \
|
||||||
|
RB_SET_BLACKRED(parent, gparent, field); \
|
||||||
|
RB_ROTATE_LEFT(head, gparent, tmp, field); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
attr void \
|
||||||
|
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *tmp; \
|
||||||
|
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
|
||||||
|
elm != RB_ROOT(head)) { \
|
||||||
|
if (RB_LEFT(parent, field) == elm) { \
|
||||||
|
tmp = RB_RIGHT(parent, field); \
|
||||||
|
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||||
|
RB_SET_BLACKRED(tmp, parent, field); \
|
||||||
|
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||||
|
tmp = RB_RIGHT(parent, field); \
|
||||||
|
} \
|
||||||
|
if ((RB_LEFT(tmp, field) == NULL || \
|
||||||
|
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||||
|
(RB_RIGHT(tmp, field) == NULL || \
|
||||||
|
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||||
|
RB_COLOR(tmp, field) = RB_RED; \
|
||||||
|
elm = parent; \
|
||||||
|
parent = RB_PARENT(elm, field); \
|
||||||
|
} else { \
|
||||||
|
if (RB_RIGHT(tmp, field) == NULL || \
|
||||||
|
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
|
||||||
|
struct type *oleft; \
|
||||||
|
if ((oleft = RB_LEFT(tmp, field)) \
|
||||||
|
!= NULL) \
|
||||||
|
RB_COLOR(oleft, field) = RB_BLACK;\
|
||||||
|
RB_COLOR(tmp, field) = RB_RED; \
|
||||||
|
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
|
||||||
|
tmp = RB_RIGHT(parent, field); \
|
||||||
|
} \
|
||||||
|
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||||
|
RB_COLOR(parent, field) = RB_BLACK; \
|
||||||
|
if (RB_RIGHT(tmp, field)) \
|
||||||
|
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
|
||||||
|
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||||
|
elm = RB_ROOT(head); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
tmp = RB_LEFT(parent, field); \
|
||||||
|
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||||
|
RB_SET_BLACKRED(tmp, parent, field); \
|
||||||
|
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||||
|
tmp = RB_LEFT(parent, field); \
|
||||||
|
} \
|
||||||
|
if ((RB_LEFT(tmp, field) == NULL || \
|
||||||
|
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||||
|
(RB_RIGHT(tmp, field) == NULL || \
|
||||||
|
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||||
|
RB_COLOR(tmp, field) = RB_RED; \
|
||||||
|
elm = parent; \
|
||||||
|
parent = RB_PARENT(elm, field); \
|
||||||
|
} else { \
|
||||||
|
if (RB_LEFT(tmp, field) == NULL || \
|
||||||
|
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
|
||||||
|
struct type *oright; \
|
||||||
|
if ((oright = RB_RIGHT(tmp, field)) \
|
||||||
|
!= NULL) \
|
||||||
|
RB_COLOR(oright, field) = RB_BLACK;\
|
||||||
|
RB_COLOR(tmp, field) = RB_RED; \
|
||||||
|
RB_ROTATE_LEFT(head, tmp, oright, field);\
|
||||||
|
tmp = RB_LEFT(parent, field); \
|
||||||
|
} \
|
||||||
|
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||||
|
RB_COLOR(parent, field) = RB_BLACK; \
|
||||||
|
if (RB_LEFT(tmp, field)) \
|
||||||
|
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
|
||||||
|
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||||
|
elm = RB_ROOT(head); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (elm) \
|
||||||
|
RB_COLOR(elm, field) = RB_BLACK; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *child, *parent, *old = elm; \
|
||||||
|
int color; \
|
||||||
|
if (RB_LEFT(elm, field) == NULL) \
|
||||||
|
child = RB_RIGHT(elm, field); \
|
||||||
|
else if (RB_RIGHT(elm, field) == NULL) \
|
||||||
|
child = RB_LEFT(elm, field); \
|
||||||
|
else { \
|
||||||
|
struct type *left; \
|
||||||
|
elm = RB_RIGHT(elm, field); \
|
||||||
|
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||||
|
elm = left; \
|
||||||
|
child = RB_RIGHT(elm, field); \
|
||||||
|
parent = RB_PARENT(elm, field); \
|
||||||
|
color = RB_COLOR(elm, field); \
|
||||||
|
if (child) \
|
||||||
|
RB_PARENT(child, field) = parent; \
|
||||||
|
if (parent) { \
|
||||||
|
if (RB_LEFT(parent, field) == elm) \
|
||||||
|
RB_LEFT(parent, field) = child; \
|
||||||
|
else \
|
||||||
|
RB_RIGHT(parent, field) = child; \
|
||||||
|
RB_AUGMENT(parent); \
|
||||||
|
} else \
|
||||||
|
RB_ROOT(head) = child; \
|
||||||
|
if (RB_PARENT(elm, field) == old) \
|
||||||
|
parent = elm; \
|
||||||
|
(elm)->field = (old)->field; \
|
||||||
|
if (RB_PARENT(old, field)) { \
|
||||||
|
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
|
||||||
|
RB_LEFT(RB_PARENT(old, field), field) = elm;\
|
||||||
|
else \
|
||||||
|
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
|
||||||
|
RB_AUGMENT(RB_PARENT(old, field)); \
|
||||||
|
} else \
|
||||||
|
RB_ROOT(head) = elm; \
|
||||||
|
RB_PARENT(RB_LEFT(old, field), field) = elm; \
|
||||||
|
if (RB_RIGHT(old, field)) \
|
||||||
|
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
|
||||||
|
if (parent) { \
|
||||||
|
left = parent; \
|
||||||
|
do { \
|
||||||
|
RB_AUGMENT(left); \
|
||||||
|
} while ((left = RB_PARENT(left, field)) != NULL); \
|
||||||
|
} \
|
||||||
|
goto color; \
|
||||||
|
} \
|
||||||
|
parent = RB_PARENT(elm, field); \
|
||||||
|
color = RB_COLOR(elm, field); \
|
||||||
|
if (child) \
|
||||||
|
RB_PARENT(child, field) = parent; \
|
||||||
|
if (parent) { \
|
||||||
|
if (RB_LEFT(parent, field) == elm) \
|
||||||
|
RB_LEFT(parent, field) = child; \
|
||||||
|
else \
|
||||||
|
RB_RIGHT(parent, field) = child; \
|
||||||
|
RB_AUGMENT(parent); \
|
||||||
|
} else \
|
||||||
|
RB_ROOT(head) = child; \
|
||||||
|
color: \
|
||||||
|
if (color == RB_BLACK) \
|
||||||
|
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||||
|
return (old); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Inserts a node into the RB tree */ \
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *tmp; \
|
||||||
|
struct type *parent = NULL; \
|
||||||
|
int comp = 0; \
|
||||||
|
tmp = RB_ROOT(head); \
|
||||||
|
while (tmp) { \
|
||||||
|
parent = tmp; \
|
||||||
|
comp = (cmp)(elm, parent); \
|
||||||
|
if (comp < 0) \
|
||||||
|
tmp = RB_LEFT(tmp, field); \
|
||||||
|
else if (comp > 0) \
|
||||||
|
tmp = RB_RIGHT(tmp, field); \
|
||||||
|
else \
|
||||||
|
return (tmp); \
|
||||||
|
} \
|
||||||
|
RB_SET(elm, parent, field); \
|
||||||
|
if (parent != NULL) { \
|
||||||
|
if (comp < 0) \
|
||||||
|
RB_LEFT(parent, field) = elm; \
|
||||||
|
else \
|
||||||
|
RB_RIGHT(parent, field) = elm; \
|
||||||
|
RB_AUGMENT(parent); \
|
||||||
|
} else \
|
||||||
|
RB_ROOT(head) = elm; \
|
||||||
|
name##_RB_INSERT_COLOR(head, elm); \
|
||||||
|
return (NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Finds the node with the same key as elm */ \
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *tmp = RB_ROOT(head); \
|
||||||
|
int comp; \
|
||||||
|
while (tmp) { \
|
||||||
|
comp = cmp(elm, tmp); \
|
||||||
|
if (comp < 0) \
|
||||||
|
tmp = RB_LEFT(tmp, field); \
|
||||||
|
else if (comp > 0) \
|
||||||
|
tmp = RB_RIGHT(tmp, field); \
|
||||||
|
else \
|
||||||
|
return (tmp); \
|
||||||
|
} \
|
||||||
|
return (NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Finds the first node greater than or equal to the search key */ \
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||||
|
{ \
|
||||||
|
struct type *tmp = RB_ROOT(head); \
|
||||||
|
struct type *res = NULL; \
|
||||||
|
int comp; \
|
||||||
|
while (tmp) { \
|
||||||
|
comp = cmp(elm, tmp); \
|
||||||
|
if (comp < 0) { \
|
||||||
|
res = tmp; \
|
||||||
|
tmp = RB_LEFT(tmp, field); \
|
||||||
|
} \
|
||||||
|
else if (comp > 0) \
|
||||||
|
tmp = RB_RIGHT(tmp, field); \
|
||||||
|
else \
|
||||||
|
return (tmp); \
|
||||||
|
} \
|
||||||
|
return (res); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* ARGSUSED */ \
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_NEXT(struct type *elm) \
|
||||||
|
{ \
|
||||||
|
if (RB_RIGHT(elm, field)) { \
|
||||||
|
elm = RB_RIGHT(elm, field); \
|
||||||
|
while (RB_LEFT(elm, field)) \
|
||||||
|
elm = RB_LEFT(elm, field); \
|
||||||
|
} else { \
|
||||||
|
if (RB_PARENT(elm, field) && \
|
||||||
|
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
|
||||||
|
elm = RB_PARENT(elm, field); \
|
||||||
|
else { \
|
||||||
|
while (RB_PARENT(elm, field) && \
|
||||||
|
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
|
||||||
|
elm = RB_PARENT(elm, field); \
|
||||||
|
elm = RB_PARENT(elm, field); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return (elm); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* ARGSUSED */ \
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_PREV(struct type *elm) \
|
||||||
|
{ \
|
||||||
|
if (RB_LEFT(elm, field)) { \
|
||||||
|
elm = RB_LEFT(elm, field); \
|
||||||
|
while (RB_RIGHT(elm, field)) \
|
||||||
|
elm = RB_RIGHT(elm, field); \
|
||||||
|
} else { \
|
||||||
|
if (RB_PARENT(elm, field) && \
|
||||||
|
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
|
||||||
|
elm = RB_PARENT(elm, field); \
|
||||||
|
else { \
|
||||||
|
while (RB_PARENT(elm, field) && \
|
||||||
|
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
|
||||||
|
elm = RB_PARENT(elm, field); \
|
||||||
|
elm = RB_PARENT(elm, field); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return (elm); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
attr struct type * \
|
||||||
|
name##_RB_MINMAX(struct name *head, int val) \
|
||||||
|
{ \
|
||||||
|
struct type *tmp = RB_ROOT(head); \
|
||||||
|
struct type *parent = NULL; \
|
||||||
|
while (tmp) { \
|
||||||
|
parent = tmp; \
|
||||||
|
if (val < 0) \
|
||||||
|
tmp = RB_LEFT(tmp, field); \
|
||||||
|
else \
|
||||||
|
tmp = RB_RIGHT(tmp, field); \
|
||||||
|
} \
|
||||||
|
return (parent); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RB_NEGINF -1
|
||||||
|
#define RB_INF 1
|
||||||
|
|
||||||
|
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||||
|
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||||
|
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||||
|
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
|
||||||
|
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||||
|
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||||
|
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||||
|
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||||
|
|
||||||
|
#define RB_FOREACH(x, name, head) \
|
||||||
|
for ((x) = RB_MIN(name, head); \
|
||||||
|
(x) != NULL; \
|
||||||
|
(x) = name##_RB_NEXT(x))
|
||||||
|
|
||||||
|
#define RB_FOREACH_FROM(x, name, y) \
|
||||||
|
for ((x) = (y); \
|
||||||
|
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||||
|
(x) = (y))
|
||||||
|
|
||||||
|
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||||
|
for ((x) = RB_MIN(name, head); \
|
||||||
|
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||||
|
(x) = (y))
|
||||||
|
|
||||||
|
#define RB_FOREACH_REVERSE(x, name, head) \
|
||||||
|
for ((x) = RB_MAX(name, head); \
|
||||||
|
(x) != NULL; \
|
||||||
|
(x) = name##_RB_PREV(x))
|
||||||
|
|
||||||
|
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
|
||||||
|
for ((x) = (y); \
|
||||||
|
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||||
|
(x) = (y))
|
||||||
|
|
||||||
|
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
|
||||||
|
for ((x) = RB_MAX(name, head); \
|
||||||
|
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||||
|
(x) = (y))
|
||||||
|
|
||||||
|
#endif /* _SYS_TREE_H_ */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue