aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2013-04-16 18:32:56 +0000
committerFlorian Dold <florian.dold@gmail.com>2013-04-16 18:32:56 +0000
commite77e2db24ef3681f207521e539a2c1ca3584efda (patch)
tree1bb5afd004527fa6ce1ca213571dcbc60fa55ef6 /src
parentc5a460ec22898e2ce2c5c5b1d1a2abb083b8fc8d (diff)
downloadgnunet-e77e2db24ef3681f207521e539a2c1ca3584efda.tar.gz
gnunet-e77e2db24ef3681f207521e539a2c1ca3584efda.zip
added skeleton for gnunet set
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/consensus/gnunet-service-consensus.c14
-rw-r--r--src/set/Makefile.am72
-rw-r--r--src/set/gnunet-service-set.c71
-rw-r--r--src/set/gnunet-set.c62
-rw-r--r--src/set/ibf.c357
-rw-r--r--src/set/ibf.h224
-rw-r--r--src/set/set.conf.in0
-rw-r--r--src/set/set_api.c0
-rw-r--r--src/set/strata_estimator.c145
-rw-r--r--src/set/strata_estimator.h84
-rw-r--r--src/set/test_set.conf0
-rw-r--r--src/set/test_set_api.c39
13 files changed, 1060 insertions, 10 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d895b6095..ab51ee178 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@
3#endif 3#endif
4 4
5if HAVE_EXPERIMENTAL 5if HAVE_EXPERIMENTAL
6 EXP_DIR = gns chat consensus dv 6 EXP_DIR = gns chat consensus dv set
7endif 7endif
8 8
9if LINUX 9if LINUX
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c
index 179df0fb0..a7640c51f 100644
--- a/src/consensus/gnunet-service-consensus.c
+++ b/src/consensus/gnunet-service-consensus.c
@@ -2279,7 +2279,7 @@ add_incoming_peers (struct ConsensusSession *session)
2279static void 2279static void
2280initialize_session (struct ConsensusSession *session) 2280initialize_session (struct ConsensusSession *session)
2281{ 2281{
2282 const struct ConsensusSession *other_session; 2282 struct ConsensusSession *other_session;
2283 2283
2284 GNUNET_assert (NULL != session->join_msg); 2284 GNUNET_assert (NULL != session->join_msg);
2285 initialize_session_peer_list (session); 2285 initialize_session_peer_list (session);
@@ -2295,17 +2295,13 @@ initialize_session (struct ConsensusSession *session)
2295 { 2295 {
2296 if (GNUNET_NO == other_session->conclude) 2296 if (GNUNET_NO == other_session->conclude)
2297 { 2297 {
2298 /* session already owned by another client */
2299 GNUNET_break (0); 2298 GNUNET_break (0);
2300 disconnect_client (session->scss.client); 2299 destroy_session (session);
2301 return; 2300 return;
2302 } 2301 }
2303 else 2302 GNUNET_SERVER_client_drop (other_session->scss.client);
2304 { 2303 other_session->scss.client = NULL;
2305 GNUNET_SERVER_client_drop (session->scss.client); 2304 break;
2306 session->scss.client = NULL;
2307 break;
2308 }
2309 } 2305 }
2310 other_session = other_session->next; 2306 other_session = other_session->next;
2311 } 2307 }
diff --git a/src/set/Makefile.am b/src/set/Makefile.am
new file mode 100644
index 000000000..fb6aa5b21
--- /dev/null
+++ b/src/set/Makefile.am
@@ -0,0 +1,72 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3pkgcfgdir= $(pkgdatadir)/config.d/
4
5libexecdir= $(pkglibdir)/libexec/
6
7pkgcfg_DATA = \
8 set.conf
9
10if MINGW
11 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
12endif
13
14if USE_COVERAGE
15 AM_CFLAGS = -fprofile-arcs -ftest-coverage
16endif
17
18bin_PROGRAMS = \
19 gnunet-set
20
21libexec_PROGRAMS = \
22 gnunet-service-set
23
24lib_LTLIBRARIES = \
25 libgnunetset.la
26
27gnunet_set_SOURCES = \
28 gnunet-set.c
29gnunet_set_LDADD = \
30 $(top_builddir)/src/util/libgnunetutil.la \
31 $(top_builddir)/src/set/libgnunetset.la \
32 $(top_builddir)/src/testbed/libgnunettestbed.la \
33 $(GN_LIBINTL)
34gnunet_set_DEPENDENCIES = \
35 libgnunetset.la
36
37gnunet_service_set_SOURCES = \
38 gnunet-service-set.c \
39 ibf.c \
40 strata_estimator.c
41gnunet_service_set_LDADD = \
42 $(top_builddir)/src/util/libgnunetutil.la \
43 $(top_builddir)/src/core/libgnunetcore.la \
44 $(top_builddir)/src/stream/libgnunetstream.la \
45 $(top_builddir)/src/mesh/libgnunetmesh.la \
46 $(GN_LIBINTL)
47
48libgnunetset_la_SOURCES = \
49 set_api.c
50libgnunetset_la_LIBADD = \
51 $(top_builddir)/src/util/libgnunetutil.la \
52 $(LTLIBINTL)
53libgnunetset_la_LDFLAGS = \
54 $(GN_LIB_LDFLAGS)
55
56check_PROGRAMS = \
57 test_set_api
58
59if ENABLE_TEST_RUN
60TESTS = $(check_PROGRAMS)
61endif
62
63test_set_api_SOURCES = \
64 test_set_api.c
65test_set_api_LDADD = \
66 $(top_builddir)/src/util/libgnunetutil.la \
67 $(top_builddir)/src/testing/libgnunettesting.la \
68 $(top_builddir)/src/set/libgnunetset.la
69
70EXTRA_DIST = \
71 test_set.conf
72
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
new file mode 100644
index 000000000..9eaca990e
--- /dev/null
+++ b/src/set/gnunet-service-set.c
@@ -0,0 +1,71 @@
1/*
2 This file is part of GNUnet
3 (C) 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file set/gnunet-service-set.c
23 * @brief two-peer set operations
24 * @author Florian Dold
25 */
26
27#include "platform.h"
28#include "gnunet_common.h"
29#include "gnunet_protocols.h"
30#include "gnunet_applications.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_core_service.h"
33#include "gnunet_stream_lib.h"
34
35
36/**
37 * Function called by the service's run
38 * method to run service-specific setup code.
39 *
40 * @param cls closure
41 * @param server the initialized server
42 * @param cfg configuration to use
43 */
44static void
45run (void *cls,
46 struct GNUNET_SERVER_Handle * server,
47 const struct GNUNET_CONFIGURATION_Handle *
48 cfg)
49
50{
51 /* FIXME */
52}
53
54
55/**
56 * The main function for the set service.
57 *
58 * @param argc number of arguments from the command line
59 * @param argv command line arguments
60 * @return 0 ok, 1 on error
61 */
62int
63main (int argc, char *const *argv)
64{
65 int ret;
66 ret = GNUNET_SERVICE_run (argc, argv, "set", GNUNET_SERVICE_OPTION_NONE, &run, NULL);
67 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "exit\n");
68 return (GNUNET_OK == ret) ? 0 : 1;
69}
70
71
diff --git a/src/set/gnunet-set.c b/src/set/gnunet-set.c
new file mode 100644
index 000000000..bb494ffe7
--- /dev/null
+++ b/src/set/gnunet-set.c
@@ -0,0 +1,62 @@
1/*
2 This file is part of GNUnet
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/**
22 * @file set/gnunet-set.c
23 * @brief profiling tool for the set service
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testbed_service.h"
30
31
32/**
33 * Main function that will be run.
34 *
35 * @param cls closure
36 * @param args remaining command-line arguments
37 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
38 * @param cfg configuration
39 */
40static void
41run (void *cls, char *const *args,
42 const char *cfgfile,
43 const struct GNUNET_CONFIGURATION_Handle *
44 cfg)
45{
46 /* FIXME */
47}
48
49
50
51int
52main (int argc, char **argv)
53{
54 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
55 GNUNET_GETOPT_OPTION_END
56 };
57 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set",
58 "help",
59 options, &run, NULL, GNUNET_YES);
60 return 0;
61}
62
diff --git a/src/set/ibf.c b/src/set/ibf.c
new file mode 100644
index 000000000..739b97339
--- /dev/null
+++ b/src/set/ibf.c
@@ -0,0 +1,357 @@
1/*
2 This file is part of GNUnet
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file consensus/ibf.c
23 * @brief implementation of the invertible bloom filter
24 * @author Florian Dold
25 */
26
27#include "ibf.h"
28
29/**
30 * Create a key from a hashcode.
31 *
32 * @param hash the hashcode
33 * @return a key
34 */
35struct IBF_Key
36ibf_key_from_hashcode (const struct GNUNET_HashCode *hash)
37{
38 /* FIXME: endianess */
39 return *(struct IBF_Key *) hash;
40}
41
42/**
43 * Create a hashcode from a key, by replicating the key
44 * until the hascode is filled
45 *
46 * @param key the key
47 * @param dst hashcode to store the result in
48 */
49void
50ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst)
51{
52 struct IBF_Key *p;
53 unsigned int i;
54 const unsigned int keys_per_hashcode = sizeof (struct GNUNET_HashCode) / sizeof (struct IBF_Key);
55 p = (struct IBF_Key *) dst;
56 for (i = 0; i < keys_per_hashcode; i++)
57 *p++ = key;
58}
59
60
61/**
62 * Create an invertible bloom filter.
63 *
64 * @param size number of IBF buckets
65 * @param hash_num number of buckets one element is hashed in
66 * @return the newly created invertible bloom filter
67 */
68struct InvertibleBloomFilter *
69ibf_create (uint32_t size, uint8_t hash_num)
70{
71 struct InvertibleBloomFilter *ibf;
72
73 /* TODO: use malloc_large */
74
75 ibf = GNUNET_malloc (sizeof (struct InvertibleBloomFilter));
76 ibf->count = GNUNET_malloc (size * sizeof (uint8_t));
77 ibf->key_sum = GNUNET_malloc (size * sizeof (struct GNUNET_HashCode));
78 ibf->key_hash_sum = GNUNET_malloc (size * sizeof (struct GNUNET_HashCode));
79 ibf->size = size;
80 ibf->hash_num = hash_num;
81
82 return ibf;
83}
84
85/**
86 * Store unique bucket indices for the specified key in dst.
87 */
88static inline void
89ibf_get_indices (const struct InvertibleBloomFilter *ibf,
90 struct IBF_Key key, int *dst)
91{
92 struct GNUNET_HashCode bucket_indices;
93 unsigned int filled;
94 int i;
95 GNUNET_CRYPTO_hash (&key, sizeof key, &bucket_indices);
96 filled = 0;
97 for (i = 0; filled < ibf->hash_num; i++)
98 {
99 unsigned int bucket;
100 unsigned int j;
101 if ( (0 != i) && (0 == (i % 16)) )
102 GNUNET_CRYPTO_hash (&bucket_indices, sizeof (struct GNUNET_HashCode), &bucket_indices);
103 bucket = bucket_indices.bits[i % 16] % ibf->size;
104 for (j = 0; j < filled; j++)
105 if (dst[j] == bucket)
106 goto try_next;
107 dst[filled++] = bucket;
108 try_next: ;
109 }
110}
111
112
113static void
114ibf_insert_into (struct InvertibleBloomFilter *ibf,
115 struct IBF_Key key,
116 const int *buckets, int side)
117{
118 int i;
119 struct GNUNET_HashCode key_hash_sha;
120 struct IBF_KeyHash key_hash;
121 GNUNET_CRYPTO_hash (&key, sizeof key, &key_hash_sha);
122 key_hash.key_hash_val = key_hash_sha.bits[0];
123 for (i = 0; i < ibf->hash_num; i++)
124 {
125 const int bucket = buckets[i];
126 ibf->count[bucket].count_val += side;
127 ibf->key_sum[bucket].key_val ^= key.key_val;
128 ibf->key_hash_sum[bucket].key_hash_val ^= key_hash.key_hash_val;
129 }
130}
131
132
133/**
134 * Insert an element into an IBF.
135 *
136 * @param ibf the IBF
137 * @param key the element's hash code
138 */
139void
140ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
141{
142 int buckets[ibf->hash_num];
143 GNUNET_assert (ibf->hash_num <= ibf->size);
144 ibf_get_indices (ibf, key, buckets);
145 ibf_insert_into (ibf, key, buckets, 1);
146}
147
148/**
149 * Test is the IBF is empty, i.e. all counts, keys and key hashes are zero.
150 */
151static int
152ibf_is_empty (struct InvertibleBloomFilter *ibf)
153{
154 int i;
155 for (i = 0; i < ibf->size; i++)
156 {
157 if (0 != ibf->count[i].count_val)
158 return GNUNET_NO;
159 if (0 != ibf->key_hash_sum[i].key_hash_val)
160 return GNUNET_NO;
161 if (0 != ibf->key_sum[i].key_val)
162 return GNUNET_NO;
163 }
164 return GNUNET_YES;
165}
166
167
168/**
169 * Decode and remove an element from the IBF, if possible.
170 *
171 * @param ibf the invertible bloom filter to decode
172 * @param ret_side sign of the cell's count where the decoded element came from.
173 * A negative sign indicates that the element was recovered
174 * resides in an IBF that was previously subtracted from.
175 * @param ret_id receives the hash code of the decoded element, if successful
176 * @return GNUNET_YES if decoding an element was successful,
177 * GNUNET_NO if the IBF is empty,
178 * GNUNET_SYSERR if the decoding has failed
179 */
180int
181ibf_decode (struct InvertibleBloomFilter *ibf,
182 int *ret_side, struct IBF_Key *ret_id)
183{
184 struct IBF_KeyHash hash;
185 int i;
186 struct GNUNET_HashCode key_hash_sha;
187 int buckets[ibf->hash_num];
188
189 GNUNET_assert (NULL != ibf);
190
191 for (i = 0; i < ibf->size; i++)
192 {
193 int j;
194 int hit;
195
196 /* we can only decode from pure buckets */
197 if ((1 != ibf->count[i].count_val) && (-1 != ibf->count[i].count_val))
198 continue;
199
200 GNUNET_CRYPTO_hash (&ibf->key_sum[i], sizeof (struct IBF_Key), &key_hash_sha);
201 hash.key_hash_val = key_hash_sha.bits[0];
202
203 /* test if the hash matches the key */
204 if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val)
205 continue;
206
207 /* test if key in bucket hits its own location,
208 * if not, the key hash was subject to collision */
209 hit = GNUNET_NO;
210 ibf_get_indices (ibf, ibf->key_sum[i], buckets);
211 for (j = 0; j < ibf->hash_num; j++)
212 if (buckets[j] == i)
213 hit = GNUNET_YES;
214
215 if (GNUNET_NO == hit)
216 continue;
217
218 if (NULL != ret_side)
219 *ret_side = ibf->count[i].count_val;
220 if (NULL != ret_id)
221 *ret_id = ibf->key_sum[i];
222
223 /* insert on the opposite side, effectively removing the element */
224 ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val);
225
226 return GNUNET_YES;
227 }
228
229 if (GNUNET_YES == ibf_is_empty (ibf))
230 return GNUNET_NO;
231 return GNUNET_SYSERR;
232}
233
234
235/**
236 * Write buckets from an ibf to a buffer.
237 * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.
238 *
239 * @param ibf the ibf to write
240 * @param start with which bucket to start
241 * @param count how many buckets to write
242 * @param buf buffer to write the data to
243 */
244void
245ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf)
246{
247 struct IBF_Key *key_dst;
248 struct IBF_KeyHash *key_hash_dst;
249 struct IBF_Count *count_dst;
250
251 GNUNET_assert (start + count <= ibf->size);
252
253 /* copy keys */
254 key_dst = (struct IBF_Key *) buf;
255 memcpy (key_dst, ibf->key_sum + start, count * sizeof *key_dst);
256 key_dst += count;
257 /* copy key hashes */
258 key_hash_dst = (struct IBF_KeyHash *) key_dst;
259 memcpy (key_hash_dst, ibf->key_hash_sum + start, count * sizeof *key_hash_dst);
260 key_hash_dst += count;
261 /* copy counts */
262 count_dst = (struct IBF_Count *) key_hash_dst;
263 memcpy (count_dst, ibf->count + start, count * sizeof *count_dst);
264 count_dst += count;
265}
266
267
268/**
269 * Read buckets from a buffer into an ibf.
270 *
271 * @param buf pointer to the buffer to read from
272 * @param start which bucket to start at
273 * @param count how many buckets to read
274 * @param ibf the ibf to read from
275 */
276void
277ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf)
278{
279 struct IBF_Key *key_src;
280 struct IBF_KeyHash *key_hash_src;
281 struct IBF_Count *count_src;
282
283 GNUNET_assert (start + count <= ibf->size);
284
285 /* copy keys */
286 key_src = (struct IBF_Key *) buf;
287 memcpy (ibf->key_sum + start, key_src, count * sizeof *key_src);
288 key_src += count;
289 /* copy key hashes */
290 key_hash_src = (struct IBF_KeyHash *) key_src;
291 memcpy (ibf->key_hash_sum + start, key_hash_src, count * sizeof *key_hash_src);
292 key_hash_src += count;
293 /* copy counts */
294 count_src = (struct IBF_Count *) key_hash_src;
295 memcpy (ibf->count + start, count_src, count * sizeof *count_src);
296 count_src += count;
297}
298
299
300/**
301 * Subtract ibf2 from ibf1, storing the result in ibf1.
302 * The two IBF's must have the same parameters size and hash_num.
303 *
304 * @param ibf1 IBF that is subtracted from
305 * @param ibf2 IBF that will be subtracted from ibf1
306 */
307void
308ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
309{
310 int i;
311
312 GNUNET_assert (ibf1->size == ibf2->size);
313 GNUNET_assert (ibf1->hash_num == ibf2->hash_num);
314
315 for (i = 0; i < ibf1->size; i++)
316 {
317 ibf1->count[i].count_val -= ibf2->count[i].count_val;
318 ibf1->key_hash_sum[i].key_hash_val ^= ibf2->key_hash_sum[i].key_hash_val;
319 ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val;
320 }
321}
322
323
324/**
325 * Create a copy of an IBF, the copy has to be destroyed properly.
326 *
327 * @param ibf the IBF to copy
328 */
329struct InvertibleBloomFilter *
330ibf_dup (const struct InvertibleBloomFilter *ibf)
331{
332 struct InvertibleBloomFilter *copy;
333 copy = GNUNET_malloc (sizeof *copy);
334 copy->hash_num = ibf->hash_num;
335 copy->size = ibf->size;
336 copy->key_hash_sum = GNUNET_memdup (ibf->key_hash_sum, ibf->size * sizeof (struct IBF_KeyHash));
337 copy->key_sum = GNUNET_memdup (ibf->key_sum, ibf->size * sizeof (struct IBF_Key));
338 copy->count = GNUNET_memdup (ibf->count, ibf->size * sizeof (struct IBF_Count));
339 return copy;
340}
341
342
343/**
344 * Destroy all resources associated with the invertible bloom filter.
345 * No more ibf_*-functions may be called on ibf after calling destroy.
346 *
347 * @param ibf the intertible bloom filter to destroy
348 */
349void
350ibf_destroy (struct InvertibleBloomFilter *ibf)
351{
352 GNUNET_free (ibf->key_sum);
353 GNUNET_free (ibf->key_hash_sum);
354 GNUNET_free (ibf->count);
355 GNUNET_free (ibf);
356}
357
diff --git a/src/set/ibf.h b/src/set/ibf.h
new file mode 100644
index 000000000..2bf3ef7c7
--- /dev/null
+++ b/src/set/ibf.h
@@ -0,0 +1,224 @@
1/*
2 This file is part of GNUnet
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file consensus/ibf.h
23 * @brief invertible bloom filter
24 * @author Florian Dold
25 */
26
27#ifndef GNUNET_CONSENSUS_IBF_H
28#define GNUNET_CONSENSUS_IBF_H
29
30#include "platform.h"
31#include "gnunet_common.h"
32#include "gnunet_util_lib.h"
33
34#ifdef __cplusplus
35extern "C"
36{
37#if 0 /* keep Emacsens' auto-indent happy */
38}
39#endif
40#endif
41
42
43struct IBF_Key
44{
45 uint64_t key_val;
46};
47
48struct IBF_KeyHash
49{
50 uint32_t key_hash_val;
51};
52
53struct IBF_Count
54{
55 int8_t count_val;
56};
57
58/**
59 * Size of one ibf bucket in bytes
60 */
61#define IBF_BUCKET_SIZE (sizeof (struct IBF_Count) + sizeof (struct IBF_Key) + \
62 sizeof (struct IBF_KeyHash))
63
64/**
65 * Invertible bloom filter (IBF).
66 *
67 * An IBF is a counting bloom filter that has the ability to restore
68 * the hashes of its stored elements with high probability.
69 */
70struct InvertibleBloomFilter
71{
72 /**
73 * How many cells does this IBF have?
74 */
75 uint32_t size;
76
77 /**
78 * In how many cells do we hash one element?
79 * Usually 4 or 3.
80 */
81 uint8_t hash_num;
82
83 /**
84 * Xor sums of the elements' keys, used to identify the elements.
85 * Array of 'size' elements.
86 */
87 struct IBF_Key *key_sum;
88
89 /**
90 * Xor sums of the hashes of the keys of inserted elements.
91 * Array of 'size' elements.
92 */
93 struct IBF_KeyHash *key_hash_sum;
94
95 /**
96 * How many times has a bucket been hit?
97 * Can be negative, as a result of IBF subtraction.
98 * Array of 'size' elements.
99 */
100 struct IBF_Count *count;
101};
102
103
104/**
105 * Write buckets from an ibf to a buffer.
106 * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.
107 *
108 * @param ibf the ibf to write
109 * @param start with which bucket to start
110 * @param count how many buckets to write
111 * @param buf buffer to write the data to
112 */
113void
114ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf);
115
116
117/**
118 * Read buckets from a buffer into an ibf.
119 *
120 * @param buf pointer to the buffer to read from
121 * @param start which bucket to start at
122 * @param count how many buckets to read
123 * @param ibf the ibf to read from
124 */
125void
126ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf);
127
128
129/**
130 * Create a key from a hashcode.
131 *
132 * @param hash the hashcode
133 * @return a key
134 */
135struct IBF_Key
136ibf_key_from_hashcode (const struct GNUNET_HashCode *hash);
137
138
139/**
140 * Create a hashcode from a key, by replicating the key
141 * until the hascode is filled
142 *
143 * @param key the key
144 * @param dst hashcode to store the result in
145 */
146void
147ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst);
148
149
150/**
151 * Create an invertible bloom filter.
152 *
153 * @param size number of IBF buckets
154 * @param hash_num number of buckets one element is hashed in, usually 3 or 4
155 * @return the newly created invertible bloom filter
156 */
157struct InvertibleBloomFilter *
158ibf_create (uint32_t size, uint8_t hash_num);
159
160
161/**
162 * Insert an element into an IBF.
163 *
164 * @param ibf the IBF
165 * @param key the element's hash code
166 */
167void
168ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key);
169
170
171/**
172 * Subtract ibf2 from ibf1, storing the result in ibf1.
173 * The two IBF's must have the same parameters size and hash_num.
174 *
175 * @param ibf1 IBF that is subtracted from
176 * @param ibf2 IBF that will be subtracted from ibf1
177 */
178void
179ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2);
180
181
182/**
183 * Decode and remove an element from the IBF, if possible.
184 *
185 * @param ibf the invertible bloom filter to decode
186 * @param ret_side sign of the cell's count where the decoded element came from.
187 * A negative sign indicates that the element was recovered
188 * resides in an IBF that was previously subtracted from.
189 * @param ret_id receives the hash code of the decoded element, if successful
190 * @return GNUNET_YES if decoding an element was successful,
191 * GNUNET_NO if the IBF is empty,
192 * GNUNET_SYSERR if the decoding has failed
193 */
194int
195ibf_decode (struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id);
196
197
198/**
199 * Create a copy of an IBF, the copy has to be destroyed properly.
200 *
201 * @param ibf the IBF to copy
202 */
203struct InvertibleBloomFilter *
204ibf_dup (const struct InvertibleBloomFilter *ibf);
205
206/**
207 * Destroy all resources associated with the invertible bloom filter.
208 * No more ibf_*-functions may be called on ibf after calling destroy.
209 *
210 * @param ibf the intertible bloom filter to destroy
211 */
212void
213ibf_destroy (struct InvertibleBloomFilter *ibf);
214
215
216#if 0 /* keep Emacsens' auto-indent happy */
217{
218#endif
219#ifdef __cplusplus
220}
221#endif
222
223#endif
224
diff --git a/src/set/set.conf.in b/src/set/set.conf.in
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/set/set.conf.in
diff --git a/src/set/set_api.c b/src/set/set_api.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/set/set_api.c
diff --git a/src/set/strata_estimator.c b/src/set/strata_estimator.c
new file mode 100644
index 000000000..685c50f0f
--- /dev/null
+++ b/src/set/strata_estimator.c
@@ -0,0 +1,145 @@
1/*
2 This file is part of GNUnet
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file consensus/ibf.h
23 * @brief invertible bloom filter
24 * @author Florian Dold
25 */
26
27#include "platform.h"
28#include "gnunet_common.h"
29#include "ibf.h"
30#include "strata_estimator.h"
31
32void
33strata_estimator_write (const struct StrataEstimator *se, void *buf)
34{
35 int i;
36 for (i = 0; i < se->strata_count; i++)
37 {
38 ibf_write_slice (se->strata[i], 0, se->ibf_size, buf);
39 buf += se->ibf_size * IBF_BUCKET_SIZE;
40 }
41}
42
43void
44strata_estimator_read (const void *buf, struct StrataEstimator *se)
45{
46 int i;
47 for (i = 0; i < se->strata_count; i++)
48 {
49 ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]);
50 buf += se->ibf_size * IBF_BUCKET_SIZE;
51 }
52}
53
54
55void
56strata_estimator_insert (struct StrataEstimator *se, struct GNUNET_HashCode *key)
57{
58 uint32_t v;
59 int i;
60 v = key->bits[0];
61 /* count trailing '1'-bits of v */
62 for (i = 0; v & 1; v>>=1, i++)
63 /* empty */;
64 ibf_insert (se->strata[i], ibf_key_from_hashcode (key));
65}
66
67
68
69struct StrataEstimator *
70strata_estimator_create (unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum)
71{
72 struct StrataEstimator *se;
73 int i;
74
75 /* fixme: allocate everything in one chunk */
76
77 se = GNUNET_malloc (sizeof (struct StrataEstimator));
78 se->strata_count = strata_count;
79 se->ibf_size = ibf_size;
80 se->strata = GNUNET_malloc (sizeof (struct InvertibleBloomFilter *) * strata_count);
81 for (i = 0; i < strata_count; i++)
82 se->strata[i] = ibf_create (ibf_size, ibf_hashnum);
83 return se;
84}
85
86
87/**
88 * Estimate set difference with two strata estimators,
89 * i.e. arrays of IBFs.
90 * Does not not modify its arguments.
91 *
92 * @param se1 first strata estimator
93 * @param se2 second strata estimator
94 * @return the estimated difference
95 */
96unsigned int
97strata_estimator_difference (const struct StrataEstimator *se1,
98 const struct StrataEstimator *se2)
99{
100 int i;
101 int count;
102
103 GNUNET_assert (se1->strata_count == se2->strata_count);
104 count = 0;
105 for (i = se1->strata_count - 1; i >= 0; i--)
106 {
107 struct InvertibleBloomFilter *diff;
108 /* number of keys decoded from the ibf */
109 int ibf_count;
110 int more;
111 ibf_count = 0;
112 /* FIXME: implement this without always allocating new IBFs */
113 diff = ibf_dup (se1->strata[i]);
114 ibf_subtract (diff, se2->strata[i]);
115 for (;;)
116 {
117 more = ibf_decode (diff, NULL, NULL);
118 if (GNUNET_NO == more)
119 {
120 count += ibf_count;
121 break;
122 }
123 if (GNUNET_SYSERR == more)
124 {
125 ibf_destroy (diff);
126 return count * (1 << (i + 1));
127 }
128 ibf_count++;
129 }
130 ibf_destroy (diff);
131 }
132 return count;
133}
134
135
136void
137strata_estimator_destroy (struct StrataEstimator *se)
138{
139 int i;
140 for (i = 0; i < se->strata_count; i++)
141 ibf_destroy (se->strata[i]);
142 GNUNET_free (se->strata);
143 GNUNET_free (se);
144}
145
diff --git a/src/set/strata_estimator.h b/src/set/strata_estimator.h
new file mode 100644
index 000000000..cb5bd3d0a
--- /dev/null
+++ b/src/set/strata_estimator.h
@@ -0,0 +1,84 @@
1/*
2 This file is part of GNUnet
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file consensus/strata_estimator.h
23 * @brief estimator of set difference
24 * @author Florian Dold
25 */
26
27#ifndef GNUNET_CONSENSUS_STRATA_ESTIMATOR_H
28#define GNUNET_CONSENSUS_STRATA_ESTIMATOR_H
29
30#include "platform.h"
31#include "gnunet_common.h"
32#include "gnunet_util_lib.h"
33
34#ifdef __cplusplus
35extern "C"
36{
37#if 0 /* keep Emacsens' auto-indent happy */
38}
39#endif
40#endif
41
42
43struct StrataEstimator
44{
45 struct InvertibleBloomFilter **strata;
46 unsigned int strata_count;
47 unsigned int ibf_size;
48};
49
50
51void
52strata_estimator_write (const struct StrataEstimator *se, void *buf);
53
54
55void
56strata_estimator_read (const void *buf, struct StrataEstimator *se);
57
58
59struct StrataEstimator *
60strata_estimator_create (unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum);
61
62
63unsigned int
64strata_estimator_difference (const struct StrataEstimator *se1,
65 const struct StrataEstimator *se2);
66
67
68void
69strata_estimator_insert (struct StrataEstimator *se, struct GNUNET_HashCode *key);
70
71
72void
73strata_estimator_destroy (struct StrataEstimator *se);
74
75
76#if 0 /* keep Emacsens' auto-indent happy */
77{
78#endif
79#ifdef __cplusplus
80}
81#endif
82
83#endif
84
diff --git a/src/set/test_set.conf b/src/set/test_set.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/set/test_set.conf
diff --git a/src/set/test_set_api.c b/src/set/test_set_api.c
new file mode 100644
index 000000000..f9e027a86
--- /dev/null
+++ b/src/set/test_set_api.c
@@ -0,0 +1,39 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file set/test_set_api.c
23 * @brief testcase for consensus_api.c
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_testing_lib.h"
28
29int
30main (int argc, char **argv)
31{
32 int ret;
33
34 ret = GNUNET_TESTING_peer_run ("test_set_api",
35 "test_set.conf",
36 &run, NULL);
37 return ret;
38}
39