diff options
author | Florian Dold <florian.dold@gmail.com> | 2012-12-21 10:06:41 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2012-12-21 10:06:41 +0000 |
commit | f8b94cad883643f08c9560d5899a44f4e995706c (patch) | |
tree | cb117fd31685410cb5d7cc4e6c0323106e482284 /src/consensus | |
parent | 836ae3f40cbd1734fb502609ca57afc2cb5a1a15 (diff) | |
download | gnunet-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.c | 23 | ||||
-rw-r--r-- | src/consensus/ibf.c | 67 | ||||
-rw-r--r-- | src/consensus/ibf.h | 5 |
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 | */ | ||
30 | struct InvertibleBloomFilter | 37 | struct 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 | */ |
70 | struct InvertibleBloomFilter * | 83 | struct InvertibleBloomFilter * |
71 | ibf_create (unsigned int size, unsigned int hash_num, uint32_t salt) | 84 | ibf_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 | */ |
90 | void | 108 | void |
91 | ibf_insert_on_side (struct InvertibleBloomFilter *ibf, | 109 | ibf_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 | */ |
132 | void | 168 | void |
133 | ibf_insert (struct InvertibleBloomFilter *ibf, const struct GNUNET_HashCode *key) | 169 | ibf_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 | */ |
217 | void | 251 | void |
218 | ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *ibf2) | 252 | ibf_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 | */ |
79 | void | 82 | void |
80 | ibf_subtract (struct InvertibleBloomFilter *ibf1, struct InvertibleBloomFilter *ibf2); | 83 | ibf_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 | */ |