2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file set/gnunet-set-profiler.c
23 * @brief profiling tool for set
24 * @author Florian Dold
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet_set_service.h"
30 #include "gnunet_testbed_service.h"
35 static unsigned int num_a = 5;
36 static unsigned int num_b = 5;
37 static unsigned int num_c = 20;
39 static char *op_str = "union";
41 const static struct GNUNET_CONFIGURATION_Handle *config;
46 struct GNUNET_SET_Handle *set;
47 struct GNUNET_SET_OperationHandle *oh;
48 struct GNUNET_CONTAINER_MultiHashMap *sent;
49 struct GNUNET_CONTAINER_MultiHashMap *received;
53 static struct GNUNET_CONTAINER_MultiHashMap *common_sent;
55 static struct GNUNET_HashCode app_id;
57 static struct GNUNET_PeerIdentity local_peer;
59 static struct GNUNET_SET_ListenHandle *set_listener;
62 static unsigned int force_delta;
63 static unsigned int force_full;
64 static unsigned int element_size = 32;
67 * Handle to the statistics service.
69 static struct GNUNET_STATISTICS_Handle *statistics;
72 * The profiler will write statistics
73 * for all peers to the file with this name.
75 static char *statistics_filename;
78 * The profiler will write statistics
79 * for all peers to this file.
81 static FILE *statistics_file;
85 map_remove_iterator (void *cls,
86 const struct GNUNET_HashCode *key,
89 struct GNUNET_CONTAINER_MultiHashMap *m = cls;
92 GNUNET_assert (NULL != key);
94 ret = GNUNET_CONTAINER_multihashmap_remove_all (m, key);
96 printf ("spurious element\n");
102 * Callback function to process statistic values.
105 * @param subsystem name of subsystem that created the statistic
106 * @param name the name of the datum
107 * @param value the current value
108 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
109 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
112 statistics_result (void *cls,
113 const char *subsystem,
118 if (NULL != statistics_file)
120 fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
128 statistics_done (void *cls,
131 GNUNET_assert (GNUNET_YES == success);
132 if (NULL != statistics_file)
133 fclose (statistics_file);
134 GNUNET_SCHEDULER_shutdown ();
139 check_all_done (void)
141 if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
144 GNUNET_CONTAINER_multihashmap_iterate (info1.received, map_remove_iterator,
146 GNUNET_CONTAINER_multihashmap_iterate (info2.received, map_remove_iterator,
149 printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
151 printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
154 if (NULL == statistics_filename)
156 GNUNET_SCHEDULER_shutdown ();
160 statistics_file = fopen (statistics_filename, "w");
161 GNUNET_STATISTICS_get (statistics, NULL, NULL,
163 &statistics_result, NULL);
168 set_result_cb (void *cls,
169 const struct GNUNET_SET_Element *element,
170 uint64_t current_size,
171 enum GNUNET_SET_Status status)
173 struct SetInfo *info = cls;
174 struct GNUNET_HashCode hash;
176 GNUNET_assert (GNUNET_NO == info->done);
179 case GNUNET_SET_STATUS_DONE:
180 case GNUNET_SET_STATUS_HALF_DONE:
181 info->done = GNUNET_YES;
182 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id);
187 case GNUNET_SET_STATUS_FAILURE:
189 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n");
190 GNUNET_SCHEDULER_shutdown ();
193 case GNUNET_SET_STATUS_ADD_LOCAL:
194 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: local element\n", info->id);
197 case GNUNET_SET_STATUS_ADD_REMOTE:
198 GNUNET_CRYPTO_hash (element->data, element->size, &hash);
199 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: remote element %s\n", info->id,
201 // XXX: record and check
208 if (element->size != element_size)
210 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
211 "wrong element size: %u, expected %u\n",
213 (unsigned int) sizeof(struct GNUNET_HashCode));
217 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n",
218 info->id, GNUNET_h2s (element->data));
219 GNUNET_assert (NULL != element->data);
220 struct GNUNET_HashCode data_hash;
221 GNUNET_CRYPTO_hash (element->data, element_size, &data_hash);
222 GNUNET_CONTAINER_multihashmap_put (info->received,
224 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
229 set_listen_cb (void *cls,
230 const struct GNUNET_PeerIdentity *other_peer,
231 const struct GNUNET_MessageHeader *context_msg,
232 struct GNUNET_SET_Request *request)
234 /* max. 2 options plus terminator */
235 struct GNUNET_SET_Option opts[3] = { { 0 } };
236 unsigned int n_opts = 0;
240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
241 "listener failed\n");
244 GNUNET_assert (NULL == info2.oh);
245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
246 "set listen cb called\n");
249 opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
250 GNUNET_SET_OPTION_BYZANTINE };
252 GNUNET_assert (! (force_full && force_delta));
255 opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
256 GNUNET_SET_OPTION_FORCE_FULL };
260 opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
261 GNUNET_SET_OPTION_FORCE_DELTA };
264 opts[n_opts].type = 0;
265 info2.oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_SYMMETRIC,
267 set_result_cb, &info2);
268 GNUNET_SET_commit (info2.oh, info2.set);
273 set_insert_iterator (void *cls,
274 const struct GNUNET_HashCode *key,
277 struct GNUNET_SET_Handle *set = cls;
278 struct GNUNET_SET_Element el;
282 el.size = element_size;
283 GNUNET_SET_add_element (set, &el, NULL, NULL);
289 handle_shutdown (void *cls)
291 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
292 "Shutting down set profiler\n");
293 if (NULL != set_listener)
295 GNUNET_SET_listen_cancel (set_listener);
298 if (NULL != info1.oh)
300 GNUNET_SET_operation_cancel (info1.oh);
303 if (NULL != info2.oh)
305 GNUNET_SET_operation_cancel (info2.oh);
308 if (NULL != info1.set)
310 GNUNET_SET_destroy (info1.set);
313 if (NULL != info2.set)
315 GNUNET_SET_destroy (info2.set);
318 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
324 const struct GNUNET_CONFIGURATION_Handle *cfg,
325 struct GNUNET_TESTING_Peer *peer)
328 struct GNUNET_HashCode hash;
329 /* max. 2 options plus terminator */
330 struct GNUNET_SET_Option opts[3] = { { 0 } };
331 unsigned int n_opts = 0;
335 GNUNET_assert (element_size > 0);
337 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer))
339 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
344 statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
346 GNUNET_SCHEDULER_add_shutdown (&handle_shutdown, NULL);
351 info1.sent = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
352 info2.sent = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
353 common_sent = GNUNET_CONTAINER_multihashmap_create (num_c + 1, GNUNET_NO);
355 info1.received = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
356 info2.received = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
358 for (i = 0; i < num_a; i++)
360 char *data = GNUNET_malloc (element_size);
361 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
362 GNUNET_CRYPTO_hash (data, element_size, &hash);
363 GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, data,
364 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
367 for (i = 0; i < num_b; i++)
369 char *data = GNUNET_malloc (element_size);
370 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
371 GNUNET_CRYPTO_hash (data, element_size, &hash);
372 GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, data,
373 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
376 for (i = 0; i < num_c; i++)
378 char *data = GNUNET_malloc (element_size);
379 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
380 GNUNET_CRYPTO_hash (data, element_size, &hash);
381 GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
382 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
385 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &app_id);
387 /* FIXME: also implement intersection etc. */
388 info1.set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION);
389 info2.set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION);
391 GNUNET_CONTAINER_multihashmap_iterate (info1.sent, set_insert_iterator,
393 GNUNET_CONTAINER_multihashmap_iterate (info2.sent, set_insert_iterator,
395 GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator,
397 GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator,
400 set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION,
401 &app_id, set_listen_cb, NULL);
406 opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
407 GNUNET_SET_OPTION_BYZANTINE };
409 GNUNET_assert (! (force_full && force_delta));
412 opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
413 GNUNET_SET_OPTION_FORCE_FULL };
417 opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
418 GNUNET_SET_OPTION_FORCE_DELTA };
421 opts[n_opts].type = 0;
423 info1.oh = GNUNET_SET_prepare (&local_peer, &app_id, NULL,
424 GNUNET_SET_RESULT_SYMMETRIC,
426 set_result_cb, &info1);
427 GNUNET_SET_commit (info1.oh, info1.set);
428 GNUNET_SET_destroy (info1.set);
434 pre_run (void *cls, char *const *args, const char *cfgfile,
435 const struct GNUNET_CONFIGURATION_Handle *cfg)
437 if (0 != GNUNET_TESTING_peer_run ("set-profiler",
445 main (int argc, char **argv)
447 struct GNUNET_GETOPT_CommandLineOption options[] = {
448 GNUNET_GETOPT_option_uint ('A',
451 gettext_noop ("number of values"),
454 GNUNET_GETOPT_option_uint ('B',
457 gettext_noop ("number of values"),
460 GNUNET_GETOPT_option_flag ('b',
462 gettext_noop ("use byzantine mode"),
465 GNUNET_GETOPT_option_uint ('f',
468 gettext_noop ("force sending full set"),
471 GNUNET_GETOPT_option_uint ('d',
474 gettext_noop ("number delta operation"),
477 GNUNET_GETOPT_option_uint ('C',
480 gettext_noop ("number of values"),
483 GNUNET_GETOPT_option_string ('x',
486 gettext_noop ("operation to execute"),
489 GNUNET_GETOPT_option_uint ('w',
492 gettext_noop ("element size"),
495 GNUNET_GETOPT_option_filename ('s',
498 gettext_noop ("write statistics to file"),
499 &statistics_filename),
501 GNUNET_GETOPT_OPTION_END
504 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set-profiler",
506 options, &pre_run, NULL, GNUNET_YES);