aboutsummaryrefslogtreecommitdiff
path: root/src/consensus
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2012-12-21 10:06:41 +0000
committerFlorian Dold <florian.dold@gmail.com>2012-12-21 10:06:41 +0000
commitf8b94cad883643f08c9560d5899a44f4e995706c (patch)
treecb117fd31685410cb5d7cc4e6c0323106e482284 /src/consensus
parent836ae3f40cbd1734fb502609ca57afc2cb5a1a15 (diff)
downloadgnunet-f8b94cad883643f08c9560d5899a44f4e995706c.tar.gz
gnunet-f8b94cad883643f08c9560d5899a44f4e995706c.zip
collision detection for IBF, timing for test tool
Diffstat (limited to 'src/consensus')
-rw-r--r--src/consensus/gnunet-consensus-ibf.c23
-rw-r--r--src/consensus/ibf.c67
-rw-r--r--src/consensus/ibf.h5
3 files changed, 67 insertions, 28 deletions
diff --git a/src/consensus/gnunet-consensus-ibf.c b/src/consensus/gnunet-consensus-ibf.c
index f29b91704..c9bcc1ab0 100644
--- a/src/consensus/gnunet-consensus-ibf.c
+++ b/src/consensus/gnunet-consensus-ibf.c
@@ -68,6 +68,8 @@ run (void *cls, char *const *args, const char *cfgfile,
68 int i; 68 int i;
69 int side; 69 int side;
70 int res; 70 int res;
71 struct GNUNET_TIME_Absolute start_time;
72 struct GNUNET_TIME_Relative delta_time;
71 73
72 set_a = GNUNET_CONTAINER_multihashmap_create (((asize == 0) ? 1 : (asize + csize)), 74 set_a = GNUNET_CONTAINER_multihashmap_create (((asize == 0) ? 1 : (asize + csize)),
73 GNUNET_NO); 75 GNUNET_NO);
@@ -85,7 +87,6 @@ run (void *cls, char *const *args, const char *cfgfile,
85 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id); 87 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id);
86 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) 88 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
87 continue; 89 continue;
88 printf("A: %s\n", GNUNET_h2s (&id));
89 GNUNET_CONTAINER_multihashmap_put ( 90 GNUNET_CONTAINER_multihashmap_put (
90 set_a, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 91 set_a, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
91 i++; 92 i++;
@@ -98,7 +99,6 @@ run (void *cls, char *const *args, const char *cfgfile,
98 continue; 99 continue;
99 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id)) 100 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id))
100 continue; 101 continue;
101 printf("B: %s\n", GNUNET_h2s (&id));
102 GNUNET_CONTAINER_multihashmap_put ( 102 GNUNET_CONTAINER_multihashmap_put (
103 set_b, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 103 set_b, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
104 i++; 104 i++;
@@ -111,25 +111,30 @@ run (void *cls, char *const *args, const char *cfgfile,
111 continue; 111 continue;
112 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id)) 112 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id))
113 continue; 113 continue;
114 printf("C: %s\n", GNUNET_h2s (&id));
115 GNUNET_CONTAINER_multihashmap_put ( 114 GNUNET_CONTAINER_multihashmap_put (
116 set_c, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 115 set_c, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
117 i++; 116 i++;
118 } 117 }
119 118
120
121 ibf_a = ibf_create (ibf_size, hash_num, 0); 119 ibf_a = ibf_create (ibf_size, hash_num, 0);
122 ibf_b = ibf_create (ibf_size, hash_num, 0); 120 ibf_b = ibf_create (ibf_size, hash_num, 0);
123 121
122 start_time = GNUNET_TIME_absolute_get ();
123
124 GNUNET_CONTAINER_multihashmap_iterate (set_a, &insert_iterator, ibf_a); 124 GNUNET_CONTAINER_multihashmap_iterate (set_a, &insert_iterator, ibf_a);
125 GNUNET_CONTAINER_multihashmap_iterate (set_b, &insert_iterator, ibf_b); 125 GNUNET_CONTAINER_multihashmap_iterate (set_b, &insert_iterator, ibf_b);
126 GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_a); 126 GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_a);
127 GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_b); 127 GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_b);
128 128
129 delta_time = GNUNET_TIME_absolute_get_duration (start_time);
130
131 printf ("encoded in: %s\n", GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO));
129 132
130 printf ("-----------------\n");
131 ibf_subtract (ibf_a, ibf_b); 133 ibf_subtract (ibf_a, ibf_b);
132 134
135
136 start_time = GNUNET_TIME_absolute_get ();
137
133 for (;;) 138 for (;;)
134 { 139 {
135 res = ibf_decode (ibf_a, &side, &id); 140 res = ibf_decode (ibf_a, &side, &id);
@@ -142,15 +147,15 @@ run (void *cls, char *const *args, const char *cfgfile,
142 { 147 {
143 if ((0 == GNUNET_CONTAINER_multihashmap_size (set_b)) && 148 if ((0 == GNUNET_CONTAINER_multihashmap_size (set_b)) &&
144 (0 == GNUNET_CONTAINER_multihashmap_size (set_a))) 149 (0 == GNUNET_CONTAINER_multihashmap_size (set_a)))
145 printf ("decode succeeded\n"); 150 {
151 delta_time = GNUNET_TIME_absolute_get_duration (start_time);
152 printf ("decoded successfully in: %s\n", GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO));
153 }
146 else 154 else
147 printf ("decode missed elements\n"); 155 printf ("decode missed elements\n");
148 return; 156 return;
149 } 157 }
150 158
151 printf("R: %s\n", GNUNET_h2s (&id));
152 printf("s: %d\n", side);
153
154 if (side == 1) 159 if (side == 1)
155 res = GNUNET_CONTAINER_multihashmap_remove (set_a, &id, NULL); 160 res = GNUNET_CONTAINER_multihashmap_remove (set_a, &id, NULL);
156 if (side == -1) 161 if (side == -1)
diff --git a/src/consensus/ibf.c b/src/consensus/ibf.c
index 12d0fd320..84d87dfed 100644
--- a/src/consensus/ibf.c
+++ b/src/consensus/ibf.c
@@ -27,6 +27,13 @@
27 27
28#include "ibf.h" 28#include "ibf.h"
29 29
30
31/**
32 * Opaque handle to an invertible bloom filter (IBF).
33 *
34 * An IBF is a counting bloom filter that has the ability to restore
35 * the hashes of its stored elements with high probability.
36 */
30struct InvertibleBloomFilter 37struct InvertibleBloomFilter
31{ 38{
32 /** 39 /**
@@ -66,6 +73,12 @@ struct InvertibleBloomFilter
66 73
67/** 74/**
68 * Create an invertible bloom filter. 75 * Create an invertible bloom filter.
76 *
77 * @param size number of IBF buckets
78 * @param hash_num number of buckets one element is hashed in
79 * @param salt salt for mingling hashes, different salt may
80 * result in less (or more) collisions
81 * @return the newly created invertible bloom filter
69 */ 82 */
70struct InvertibleBloomFilter * 83struct InvertibleBloomFilter *
71ibf_create (unsigned int size, unsigned int hash_num, uint32_t salt) 84ibf_create (unsigned int size, unsigned int hash_num, uint32_t salt)
@@ -85,7 +98,12 @@ ibf_create (unsigned int size, unsigned int hash_num, uint32_t salt)
85 98
86 99
87/** 100/**
88 * Insert an element into an IBF. 101 * Insert an element into an IBF, with either positive or negative sign.
102 *
103 * @param ibf the IBF
104 * @param id the element's hash code
105 * @param side the sign of side determines the sign of the
106 * inserted element.
89 */ 107 */
90void 108void
91ibf_insert_on_side (struct InvertibleBloomFilter *ibf, 109ibf_insert_on_side (struct InvertibleBloomFilter *ibf,
@@ -93,33 +111,48 @@ ibf_insert_on_side (struct InvertibleBloomFilter *ibf,
93 int side) 111 int side)
94{ 112{
95 struct GNUNET_HashCode bucket_indices; 113 struct GNUNET_HashCode bucket_indices;
96 struct GNUNET_HashCode remove_key; 114 struct GNUNET_HashCode key_copy;
97 struct GNUNET_HashCode key_hash; 115 struct GNUNET_HashCode key_hash;
98 int i; 116 int *used_buckets;
117 unsigned int i;
99 118
100 /* copy the key, if key and an entry in the IBF alias */
101 remove_key = *key;
102 119
103 GNUNET_assert ((1 == side) || (-1 == side)); 120 GNUNET_assert ((1 == side) || (-1 == side));
121 GNUNET_assert (NULL != ibf);
122
123 used_buckets = alloca (ibf->hash_num * sizeof (int));
104 124
105 bucket_indices = remove_key; 125 /* copy the key, if key and an entry in the IBF alias */
126 key_copy = *key;
127
128 bucket_indices = key_copy;
106 GNUNET_CRYPTO_hash (key, sizeof (struct GNUNET_HashCode), &key_hash); 129 GNUNET_CRYPTO_hash (key, sizeof (struct GNUNET_HashCode), &key_hash);
107 130
108 for (i = 0; i < ibf->hash_num; i++) 131 for (i = 0; i < ibf->hash_num; i++)
109 { 132 {
110 unsigned int bucket; 133 unsigned int bucket;
134 unsigned int j;
135 int collided;
136
111 if ((i % 16) == 0) 137 if ((i % 16) == 0)
112 GNUNET_CRYPTO_hash (&bucket_indices, sizeof (struct GNUNET_HashCode), 138 GNUNET_CRYPTO_hash (&bucket_indices, sizeof (struct GNUNET_HashCode),
113 &bucket_indices); 139 &bucket_indices);
114 140
115 bucket = bucket_indices.bits[i%16] % ibf->size; 141 bucket = bucket_indices.bits[i%16] % ibf->size;
116 142 collided = GNUNET_NO;
117 printf ("inserting %s in bucket %u side %d\n", 143 for (j = 0; j < i; j++)
118 GNUNET_h2s (&remove_key), bucket, side); 144 if (used_buckets[j] == bucket)
145 collided = GNUNET_YES;
146 if (GNUNET_YES == collided)
147 {
148 used_buckets[i] = -1;
149 continue;
150 }
151 used_buckets[i] = bucket;
119 152
120 ibf->count[bucket] += side; 153 ibf->count[bucket] += side;
121 154
122 GNUNET_CRYPTO_hash_xor (&remove_key, &ibf->id_sum[bucket], 155 GNUNET_CRYPTO_hash_xor (&key_copy, &ibf->id_sum[bucket],
123 &ibf->id_sum[bucket]); 156 &ibf->id_sum[bucket]);
124 GNUNET_CRYPTO_hash_xor (&key_hash, &ibf->hash_sum[bucket], 157 GNUNET_CRYPTO_hash_xor (&key_hash, &ibf->hash_sum[bucket],
125 &ibf->hash_sum[bucket]); 158 &ibf->hash_sum[bucket]);
@@ -128,6 +161,9 @@ ibf_insert_on_side (struct InvertibleBloomFilter *ibf,
128 161
129/** 162/**
130 * Insert an element into an IBF. 163 * Insert an element into an IBF.
164 *
165 * @param ibf the IBF
166 * @param id the element's hash code
131 */ 167 */
132void 168void
133ibf_insert (struct InvertibleBloomFilter *ibf, const struct GNUNET_HashCode *key) 169ibf_insert (struct InvertibleBloomFilter *ibf, const struct GNUNET_HashCode *key)
@@ -160,10 +196,10 @@ ibf_is_empty (struct InvertibleBloomFilter *ibf)
160 * Decode and remove an element from the IBF, if possible. 196 * Decode and remove an element from the IBF, if possible.
161 * 197 *
162 * @param ibf the invertible bloom filter to decode 198 * @param ibf the invertible bloom filter to decode
163 * @param ret_id the hash code of the decoded element, if successful
164 * @param side sign of the cell's count where the decoded element came from. 199 * @param side sign of the cell's count where the decoded element came from.
165 * A negative sign indicates that the element was recovered 200 * A negative sign indicates that the element was recovered
166 * resides in an IBF that was previously subtracted from. 201 * resides in an IBF that was previously subtracted from.
202 * @param ret_id the hash code of the decoded element, if successful
167 * @return GNUNET_YES if decoding an element was successful, 203 * @return GNUNET_YES if decoding an element was successful,
168 * GNUNET_NO if the IBF is empty, 204 * GNUNET_NO if the IBF is empty,
169 * GNUNET_SYSERR if the decoding has failed 205 * GNUNET_SYSERR if the decoding has failed
@@ -189,9 +225,6 @@ ibf_decode (struct InvertibleBloomFilter *ibf,
189 if (0 != memcmp (&hash, &ibf->hash_sum[i], sizeof (struct GNUNET_HashCode))) 225 if (0 != memcmp (&hash, &ibf->hash_sum[i], sizeof (struct GNUNET_HashCode)))
190 continue; 226 continue;
191 227
192 printf ("%d pure\n", i);
193 printf ("%d count\n", ibf->count[i]);
194
195 *ret_side = ibf->count[i]; 228 *ret_side = ibf->count[i];
196 *ret_id = ibf->id_sum[i]; 229 *ret_id = ibf->id_sum[i];
197 230
@@ -212,7 +245,8 @@ ibf_decode (struct InvertibleBloomFilter *ibf,
212 * Subtract ibf2 from ibf1, storing the result in ibf1. 245 * Subtract ibf2 from ibf1, storing the result in ibf1.
213 * The two IBF's must have the same parameters size and hash_num. 246 * The two IBF's must have the same parameters size and hash_num.
214 * 247 *
215 * @return a newly allocated invertible bloom filter 248 * @param ibf1 IBF that is subtracted from
249 * @param ibf2 IBF that will be subtracted from ibf1
216 */ 250 */
217void 251void
218ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *ibf2) 252ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *ibf2)
@@ -225,10 +259,7 @@ ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *
225 259
226 for (i = 0; i < ibf1->size; i++) 260 for (i = 0; i < ibf1->size; i++)
227 { 261 {
228 printf ("ibf1->count[%d]=%d, ibf2->count[%d]=%d\n", i, ibf1->count[i], i,
229 ibf2->count[i]);
230 ibf1->count[i] -= ibf2->count[i]; 262 ibf1->count[i] -= ibf2->count[i];
231 printf("diff: %d\n", ibf1->count[i]);
232 GNUNET_CRYPTO_hash_xor (&ibf1->id_sum[i], &ibf2->id_sum[i], 263 GNUNET_CRYPTO_hash_xor (&ibf1->id_sum[i], &ibf2->id_sum[i],
233 &ibf1->id_sum[i]); 264 &ibf1->id_sum[i]);
234 GNUNET_CRYPTO_hash_xor (&ibf1->hash_sum[i], &ibf2->hash_sum[i], 265 GNUNET_CRYPTO_hash_xor (&ibf1->hash_sum[i], &ibf2->hash_sum[i],
diff --git a/src/consensus/ibf.h b/src/consensus/ibf.h
index 12aef5d2f..e43d7c5fe 100644
--- a/src/consensus/ibf.h
+++ b/src/consensus/ibf.h
@@ -75,6 +75,9 @@ ibf_insert (struct InvertibleBloomFilter *ibf, const struct GNUNET_HashCode *id)
75/** 75/**
76 * Subtract ibf2 from ibf1, storing the result in ibf1. 76 * Subtract ibf2 from ibf1, storing the result in ibf1.
77 * The two IBF's must have the same parameters size and hash_num. 77 * The two IBF's must have the same parameters size and hash_num.
78 *
79 * @param ibf1 IBF that is subtracted from
80 * @param ibf2 IBF that will be subtracted from ibf1
78 */ 81 */
79void 82void
80ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *ibf2); 83ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *ibf2);
@@ -84,10 +87,10 @@ ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *
84 * Decode and remove an element from the IBF, if possible. 87 * Decode and remove an element from the IBF, if possible.
85 * 88 *
86 * @param ibf the invertible bloom filter to decode 89 * @param ibf the invertible bloom filter to decode
87 * @param ret_id the hash code of the decoded element, if successful
88 * @param side sign of the cell's count where the decoded element came from. 90 * @param side sign of the cell's count where the decoded element came from.
89 * A negative sign indicates that the element was recovered resides in an IBF 91 * A negative sign indicates that the element was recovered resides in an IBF
90 * that was previously subtracted from. 92 * that was previously subtracted from.
93 * @param ret_id the hash code of the decoded element, if successful
91 * @return GNUNET_YES if decoding an element was successful, GNUNET_NO if the IBF is empty, 94 * @return GNUNET_YES if decoding an element was successful, GNUNET_NO if the IBF is empty,
92 * GNUNET_SYSERR if the decoding has faile 95 * GNUNET_SYSERR if the decoding has faile
93 */ 96 */