Commit 676d4f4e authored by Pieter Hintjens's avatar Pieter Hintjens

Merge pull request #222 from gimaker/trie-pruning

Fix for LIBZMQ-305
parents 0c94cd03 bc4d1b60
/* /*
Copyright (c) 2011 250bpm s.r.o. Copyright (c) 2011 250bpm s.r.o.
Copyright (c) 2011-2012 Spotify AB
Copyright (c) 2011 Other contributors as noted in the AUTHORS file Copyright (c) 2011 Other contributors as noted in the AUTHORS file
This file is part of 0MQ. This file is part of 0MQ.
...@@ -34,14 +35,18 @@ ...@@ -34,14 +35,18 @@
zmq::mtrie_t::mtrie_t () : zmq::mtrie_t::mtrie_t () :
min (0), min (0),
count (0) count (0),
live_nodes (0)
{ {
} }
zmq::mtrie_t::~mtrie_t () zmq::mtrie_t::~mtrie_t ()
{ {
if (count == 1) if (count == 1) {
zmq_assert (next.node);
delete next.node; delete next.node;
next.node = 0;
}
else if (count > 1) { else if (count > 1) {
for (unsigned short i = 0; i != count; ++i) for (unsigned short i = 0; i != count; ++i)
if (next.table [i]) if (next.table [i])
...@@ -118,6 +123,7 @@ bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_, ...@@ -118,6 +123,7 @@ bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_,
if (count == 1) { if (count == 1) {
if (!next.node) { if (!next.node) {
next.node = new (std::nothrow) mtrie_t; next.node = new (std::nothrow) mtrie_t;
++live_nodes;
zmq_assert (next.node); zmq_assert (next.node);
} }
return next.node->add_helper (prefix_ + 1, size_ - 1, pipe_); return next.node->add_helper (prefix_ + 1, size_ - 1, pipe_);
...@@ -125,6 +131,7 @@ bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_, ...@@ -125,6 +131,7 @@ bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_,
else { else {
if (!next.table [c - min]) { if (!next.table [c - min]) {
next.table [c - min] = new (std::nothrow) mtrie_t; next.table [c - min] = new (std::nothrow) mtrie_t;
++live_nodes;
zmq_assert (next.table [c - min]); zmq_assert (next.table [c - min]);
} }
return next.table [c - min]->add_helper (prefix_ + 1, size_ - 1, pipe_); return next.table [c - min]->add_helper (prefix_ + 1, size_ - 1, pipe_);
...@@ -167,16 +174,28 @@ void zmq::mtrie_t::rm_helper (pipe_t *pipe_, unsigned char **buff_, ...@@ -167,16 +174,28 @@ void zmq::mtrie_t::rm_helper (pipe_t *pipe_, unsigned char **buff_,
buffsize_++; buffsize_++;
next.node->rm_helper (pipe_, buff_, buffsize_, maxbuffsize_, next.node->rm_helper (pipe_, buff_, buffsize_, maxbuffsize_,
func_, arg_); func_, arg_);
if (next.node->is_redundant ()) {
delete next.node;
next.node = 0;
count = 0;
--live_nodes;
}
return; return;
} }
// If there are multiple subnodes. // If there are multiple subnodes.
for (unsigned short c = 0; c != count; c++) { for (unsigned short c = 0; c != count; c++) {
(*buff_) [buffsize_] = min + c; (*buff_) [buffsize_] = min + c;
if (next.table [c]) if (next.table [c]) {
next.table [c]->rm_helper (pipe_, buff_, buffsize_ + 1, next.table [c]->rm_helper (pipe_, buff_, buffsize_ + 1,
maxbuffsize_, func_, arg_); maxbuffsize_, func_, arg_);
} if (next.table [c]->is_redundant ()) {
delete next.table [c];
next.table [c] = 0;
--live_nodes;
}
}
}
} }
bool zmq::mtrie_t::rm (unsigned char *prefix_, size_t size_, pipe_t *pipe_) bool zmq::mtrie_t::rm (unsigned char *prefix_, size_t size_, pipe_t *pipe_)
...@@ -203,7 +222,20 @@ bool zmq::mtrie_t::rm_helper (unsigned char *prefix_, size_t size_, ...@@ -203,7 +222,20 @@ bool zmq::mtrie_t::rm_helper (unsigned char *prefix_, size_t size_,
if (!next_node) if (!next_node)
return false; return false;
return next_node->rm_helper (prefix_ + 1, size_ - 1, pipe_); bool ret = next_node->rm_helper (prefix_ + 1, size_ - 1, pipe_);
if (next_node->is_redundant ()) {
delete next_node;
if (count == 1) {
next.node = 0;
count = 0;
}
else
next.table [c - min] = 0;
--live_nodes;
}
return ret;
} }
void zmq::mtrie_t::match (unsigned char *data_, size_t size_, void zmq::mtrie_t::match (unsigned char *data_, size_t size_,
...@@ -247,3 +279,7 @@ void zmq::mtrie_t::match (unsigned char *data_, size_t size_, ...@@ -247,3 +279,7 @@ void zmq::mtrie_t::match (unsigned char *data_, size_t size_,
} }
} }
bool zmq::mtrie_t::is_redundant () const
{
return pipes.empty () && live_nodes == 0;
}
/* /*
Copyright (c) 2011 250bpm s.r.o. Copyright (c) 2011 250bpm s.r.o.
Copyright (c) 2011-2012 Spotify AB
Copyright (c) 2011 Other contributors as noted in the AUTHORS file Copyright (c) 2011 Other contributors as noted in the AUTHORS file
This file is part of 0MQ. This file is part of 0MQ.
...@@ -69,12 +70,14 @@ namespace zmq ...@@ -69,12 +70,14 @@ namespace zmq
void *arg_); void *arg_);
bool rm_helper (unsigned char *prefix_, size_t size_, bool rm_helper (unsigned char *prefix_, size_t size_,
zmq::pipe_t *pipe_); zmq::pipe_t *pipe_);
bool is_redundant () const;
typedef std::set <zmq::pipe_t*> pipes_t; typedef std::set <zmq::pipe_t*> pipes_t;
pipes_t pipes; pipes_t pipes;
unsigned char min; unsigned char min;
unsigned short count; unsigned short count;
unsigned short live_nodes;
union { union {
class mtrie_t *node; class mtrie_t *node;
class mtrie_t **table; class mtrie_t **table;
......
/* /*
Copyright (c) 2009-2011 250bpm s.r.o. Copyright (c) 2009-2011 250bpm s.r.o.
Copyright (c) 2007-2009 iMatix Corporation Copyright (c) 2007-2009 iMatix Corporation
Copyright (c) 2011-2012 Spotify AB
Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
This file is part of 0MQ. This file is part of 0MQ.
...@@ -35,14 +36,18 @@ ...@@ -35,14 +36,18 @@
zmq::trie_t::trie_t () : zmq::trie_t::trie_t () :
refcnt (0), refcnt (0),
min (0), min (0),
count (0) count (0),
live_nodes (0)
{ {
} }
zmq::trie_t::~trie_t () zmq::trie_t::~trie_t ()
{ {
if (count == 1) if (count == 1) {
zmq_assert (next.node);
delete next.node; delete next.node;
next.node = 0;
}
else if (count > 1) { else if (count > 1) {
for (unsigned short i = 0; i != count; ++i) for (unsigned short i = 0; i != count; ++i)
if (next.table [i]) if (next.table [i])
...@@ -113,6 +118,7 @@ bool zmq::trie_t::add (unsigned char *prefix_, size_t size_) ...@@ -113,6 +118,7 @@ bool zmq::trie_t::add (unsigned char *prefix_, size_t size_)
if (!next.node) { if (!next.node) {
next.node = new (std::nothrow) trie_t; next.node = new (std::nothrow) trie_t;
zmq_assert (next.node); zmq_assert (next.node);
++live_nodes;
} }
return next.node->add (prefix_ + 1, size_ - 1); return next.node->add (prefix_ + 1, size_ - 1);
} }
...@@ -120,6 +126,7 @@ bool zmq::trie_t::add (unsigned char *prefix_, size_t size_) ...@@ -120,6 +126,7 @@ bool zmq::trie_t::add (unsigned char *prefix_, size_t size_)
if (!next.table [c - min]) { if (!next.table [c - min]) {
next.table [c - min] = new (std::nothrow) trie_t; next.table [c - min] = new (std::nothrow) trie_t;
zmq_assert (next.table [c - min]); zmq_assert (next.table [c - min]);
++live_nodes;
} }
return next.table [c - min]->add (prefix_ + 1, size_ - 1); return next.table [c - min]->add (prefix_ + 1, size_ - 1);
} }
...@@ -146,7 +153,20 @@ bool zmq::trie_t::rm (unsigned char *prefix_, size_t size_) ...@@ -146,7 +153,20 @@ bool zmq::trie_t::rm (unsigned char *prefix_, size_t size_)
if (!next_node) if (!next_node)
return false; return false;
return next_node->rm (prefix_ + 1, size_ - 1); bool ret = next_node->rm (prefix_ + 1, size_ - 1);
if (next_node->is_redundant ()) {
delete next_node;
if (count == 1) {
next.node = 0;
count = 0;
}
else
next.table [c - min] = 0;
--live_nodes;
}
return ret;
} }
bool zmq::trie_t::check (unsigned char *data_, size_t size_) bool zmq::trie_t::check (unsigned char *data_, size_t size_)
...@@ -224,6 +244,10 @@ void zmq::trie_t::apply_helper ( ...@@ -224,6 +244,10 @@ void zmq::trie_t::apply_helper (
if (next.table [c]) if (next.table [c])
next.table [c]->apply_helper (buff_, buffsize_ + 1, maxbuffsize_, next.table [c]->apply_helper (buff_, buffsize_ + 1, maxbuffsize_,
func_, arg_); func_, arg_);
} }
} }
bool zmq::trie_t::is_redundant () const
{
return refcnt == 0 && live_nodes == 0;
}
/* /*
Copyright (c) 2009-2011 250bpm s.r.o. Copyright (c) 2009-2011 250bpm s.r.o.
Copyright (c) 2007-2009 iMatix Corporation Copyright (c) 2007-2009 iMatix Corporation
Copyright (c) 2011-2012 Spotify AB
Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
This file is part of 0MQ. This file is part of 0MQ.
...@@ -57,10 +58,12 @@ namespace zmq ...@@ -57,10 +58,12 @@ namespace zmq
unsigned char **buff_, size_t buffsize_, size_t maxbuffsize_, unsigned char **buff_, size_t buffsize_, size_t maxbuffsize_,
void (*func_) (unsigned char *data_, size_t size_, void *arg_), void (*func_) (unsigned char *data_, size_t size_, void *arg_),
void *arg_); void *arg_);
bool is_redundant () const;
uint32_t refcnt; uint32_t refcnt;
unsigned char min; unsigned char min;
unsigned short count; unsigned short count;
unsigned short live_nodes;
union { union {
class trie_t *node; class trie_t *node;
class trie_t **table; class trie_t **table;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment