aboutsummaryrefslogtreecommitdiff
path: root/src/common/container.h
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-04-08 17:06:41 +0000
committerNick Mathewson <nickm@torproject.org>2008-04-08 17:06:41 +0000
commita627407fcba1d5b1671e5789f420e4b5f8b63f99 (patch)
treee15ea16047c2352de2100aaa816ead54232cb236 /src/common/container.h
parent0c9efd6a1e252c2d6f495d158fdc1ec6877e0f10 (diff)
downloadtor-a627407fcba1d5b1671e5789f420e4b5f8b63f99.tar
tor-a627407fcba1d5b1671e5789f420e4b5f8b63f99.tar.gz
r19233@catbus: nickm | 2008-04-08 13:06:34 -0400
When we remove old routers, use Bloom filters rather than a digestmap-based set in order to tell which ones we absolutely need to keep. This will save us roughly a kazillion little short-lived allocations for hash table entries. svn:r14318
Diffstat (limited to 'src/common/container.h')
-rw-r--r--src/common/container.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/common/container.h b/src/common/container.h
index 866cb1b8a..3746c3056 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -564,6 +564,49 @@ bitarray_is_set(bitarray_t *b, int bit)
return b[bit >> BITARRAY_SHIFT] & (1u << (bit & BITARRAY_MASK));
}
+/** A set of digests, implemented as a Bloom filter. */
+typedef struct {
+ int mask; /* One less than the number of bits in <b>ba</b>; always one less
+ * than a power of two. */
+ bitarray_t *ba; /* A bit array to implement the Bloom filter. */
+} digestset_t;
+
+#define BIT(n) ((n) & set->mask)
+/** Add the digest <b>digest</b> to <b>set</b>. */
+static INLINE void
+digestset_add(digestset_t *set, const char *digest)
+{
+ const uint32_t *p = (const uint32_t *)digest;
+ const uint32_t d1 = p[0] + (p[1]>>16);
+ const uint32_t d2 = p[1] + (p[2]>>16);
+ const uint32_t d3 = p[2] + (p[3]>>16);
+ const uint32_t d4 = p[3] + (p[0]>>16);
+ bitarray_set(set->ba, BIT(d1));
+ bitarray_set(set->ba, BIT(d2));
+ bitarray_set(set->ba, BIT(d3));
+ bitarray_set(set->ba, BIT(d4));
+}
+
+/** If <b>digest</b> is in <b>set</b>, return nonzero. Otherwise,
+ * <em>probably</em> return zero. */
+static INLINE int
+digestset_isin(const digestset_t *set, const char *digest)
+{
+ const uint32_t *p = (const uint32_t *)digest;
+ const uint32_t d1 = p[0] + (p[1]>>16);
+ const uint32_t d2 = p[1] + (p[2]>>16);
+ const uint32_t d3 = p[2] + (p[3]>>16);
+ const uint32_t d4 = p[3] + (p[0]>>16);
+ return bitarray_is_set(set->ba, BIT(d1)) &&
+ bitarray_is_set(set->ba, BIT(d2)) &&
+ bitarray_is_set(set->ba, BIT(d3)) &&
+ bitarray_is_set(set->ba, BIT(d4));
+}
+#undef BIT
+
+digestset_t *digestset_new(int max_elements);
+void digestset_free(digestset_t* set);
+
/* These functions, given an <b>array</b> of <b>n_elements</b>, return the
* <b>nth</b> lowest element. <b>nth</b>=0 gives the lowest element;
* <b>n_elements</b>-1 gives the highest; and (<b>n_elements</b>-1) / 2 gives