GNUnet  0.11.x
gnunet-set-profiler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2013 GNUnet e.V.
4 
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.
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  Affero General Public License for more details.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
29 #include "gnunet_set_service.h"
30 #include "gnunet_testbed_service.h"
31 
32 
33 static int ret;
34 
35 static unsigned int num_a = 5;
36 static unsigned int num_b = 5;
37 static unsigned int num_c = 20;
38 
39 static char *op_str = "union";
40 
41 const static struct GNUNET_CONFIGURATION_Handle *config;
42 
43 struct SetInfo
44 {
45  char *id;
50  int done;
52 
54 
55 static struct GNUNET_HashCode app_id;
56 
57 static struct GNUNET_PeerIdentity local_peer;
58 
60 
61 static int byzantine;
62 static unsigned int force_delta;
63 static unsigned int force_full;
64 static unsigned int element_size = 32;
65 
70 
75 static char *statistics_filename;
76 
81 static FILE *statistics_file;
82 
83 
84 static int
86  const struct GNUNET_HashCode *key,
87  void *value)
88 {
89  struct GNUNET_CONTAINER_MultiHashMap *m = cls;
90  int ret;
91 
92  GNUNET_assert (NULL != key);
93 
95  if (GNUNET_OK != ret)
96  printf ("spurious element\n");
97  return GNUNET_YES;
98 }
99 
100 
111 static int
112 statistics_result (void *cls,
113  const char *subsystem,
114  const char *name,
115  uint64_t value,
116  int is_persistent)
117 {
118  if (NULL != statistics_file)
119  {
120  fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
121  long) value);
122  }
123  return GNUNET_OK;
124 }
125 
126 
127 static void
128 statistics_done (void *cls,
129  int success)
130 {
131  GNUNET_assert (GNUNET_YES == success);
132  if (NULL != statistics_file)
133  fclose (statistics_file);
135 }
136 
137 
138 static void
140 {
141  if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
142  return;
143 
145  info2.sent);
147  info1.sent);
148 
149  printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
150  info1.sent));
151  printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
152  info2.sent));
153 
154  if (NULL == statistics_filename)
155  {
157  return;
158  }
159 
160  statistics_file = fopen (statistics_filename, "w");
161  GNUNET_STATISTICS_get (statistics, NULL, NULL,
163  &statistics_result, NULL);
164 }
165 
166 
167 static void
168 set_result_cb (void *cls,
169  const struct GNUNET_SET_Element *element,
170  uint64_t current_size,
172 {
173  struct SetInfo *info = cls;
174  struct GNUNET_HashCode hash;
175 
176  GNUNET_assert (GNUNET_NO == info->done);
177  switch (status)
178  {
181  info->done = GNUNET_YES;
182  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id);
183  check_all_done ();
184  info->oh = NULL;
185  return;
186 
188  info->oh = NULL;
189  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n");
191  return;
192 
194  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: local element\n", info->id);
195  break;
196 
198  GNUNET_CRYPTO_hash (element->data, element->size, &hash);
199  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: remote element %s\n", info->id,
200  GNUNET_h2s (&hash));
201  // XXX: record and check
202  return;
203 
204  default:
205  GNUNET_assert (0);
206  }
207 
208  if (element->size != element_size)
209  {
211  "wrong element size: %u, expected %u\n",
212  element->size,
213  (unsigned int) sizeof(struct GNUNET_HashCode));
214  GNUNET_assert (0);
215  }
216 
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);
223  &data_hash, NULL,
225 }
226 
227 
228 static void
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)
233 {
234  /* max. 2 options plus terminator */
235  struct GNUNET_SET_Option opts[3] = { { 0 } };
236  unsigned int n_opts = 0;
237 
238  if (NULL == request)
239  {
241  "listener failed\n");
242  return;
243  }
244  GNUNET_assert (NULL == info2.oh);
246  "set listen cb called\n");
247  if (byzantine)
248  {
249  opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
251  }
253  if (force_full)
254  {
255  opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
257  }
258  if (force_delta)
259  {
260  opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
262  }
263 
264  opts[n_opts].type = 0;
266  opts,
267  set_result_cb, &info2);
269 }
270 
271 
272 static int
274  const struct GNUNET_HashCode *key,
275  void *value)
276 {
277  struct GNUNET_SET_Handle *set = cls;
278  struct GNUNET_SET_Element el;
279 
280  el.element_type = 0;
281  el.data = value;
282  el.size = element_size;
283  GNUNET_SET_add_element (set, &el, NULL, NULL);
284  return GNUNET_YES;
285 }
286 
287 
288 static void
289 handle_shutdown (void *cls)
290 {
292  "Shutting down set profiler\n");
293  if (NULL != set_listener)
294  {
296  set_listener = NULL;
297  }
298  if (NULL != info1.oh)
299  {
301  info1.oh = NULL;
302  }
303  if (NULL != info2.oh)
304  {
306  info2.oh = NULL;
307  }
308  if (NULL != info1.set)
309  {
311  info1.set = NULL;
312  }
313  if (NULL != info2.set)
314  {
316  info2.set = NULL;
317  }
319 }
320 
321 
322 static void
323 run (void *cls,
324  const struct GNUNET_CONFIGURATION_Handle *cfg,
325  struct GNUNET_TESTING_Peer *peer)
326 {
327  unsigned int i;
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;
332 
333  config = cfg;
334 
336 
338  {
339  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
340  ret = 0;
341  return;
342  }
343 
344  statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
345 
347 
348  info1.id = "a";
349  info2.id = "b";
350 
354 
357 
358  for (i = 0; i < num_a; i++)
359  {
360  char *data = GNUNET_malloc (element_size);
365  }
366 
367  for (i = 0; i < num_b; i++)
368  {
369  char *data = GNUNET_malloc (element_size);
374  }
375 
376  for (i = 0; i < num_c; i++)
377  {
378  char *data = GNUNET_malloc (element_size);
383  }
384 
386 
387  /* FIXME: also implement intersection etc. */
390 
392  info1.set);
394  info2.set);
396  info1.set);
398  info2.set);
399 
401  &app_id, set_listen_cb, NULL);
402 
403 
404  if (byzantine)
405  {
406  opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
408  }
410  if (force_full)
411  {
412  opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
414  }
415  if (force_delta)
416  {
417  opts[n_opts++] = (struct GNUNET_SET_Option) { .type =
419  }
420 
421  opts[n_opts].type = 0;
422 
425  opts,
426  set_result_cb, &info1);
429  info1.set = NULL;
430 }
431 
432 
433 static void
434 pre_run (void *cls, char *const *args, const char *cfgfile,
435  const struct GNUNET_CONFIGURATION_Handle *cfg)
436 {
437  if (0 != GNUNET_TESTING_peer_run ("set-profiler",
438  cfgfile,
439  &run, NULL))
440  ret = 2;
441 }
442 
443 
444 int
445 main (int argc, char **argv)
446 {
449  "num-first",
450  NULL,
451  gettext_noop ("number of values"),
452  &num_a),
453 
455  "num-second",
456  NULL,
457  gettext_noop ("number of values"),
458  &num_b),
459 
461  "byzantine",
462  gettext_noop ("use byzantine mode"),
463  &byzantine),
464 
466  "force-full",
467  NULL,
468  gettext_noop ("force sending full set"),
469  &force_full),
470 
472  "force-delta",
473  NULL,
474  gettext_noop ("number delta operation"),
475  &force_delta),
476 
478  "num-common",
479  NULL,
480  gettext_noop ("number of values"),
481  &num_c),
482 
484  "operation",
485  NULL,
486  gettext_noop ("operation to execute"),
487  &op_str),
488 
490  "element-size",
491  NULL,
492  gettext_noop ("element size"),
493  &element_size),
494 
496  "statistics",
497  "FILENAME",
498  gettext_noop ("write statistics to file"),
500 
502  };
503 
504  GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set-profiler",
505  "help",
506  options, &pre_run, NULL, GNUNET_YES);
507  return ret;
508 }
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define gettext_noop(String)
Definition: gettext.h:69
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_IDENTITY_EgoLookup * el
EgoLookup.
Definition: gnunet-abd.c:51
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
struct GNUNET_HashCode key
The key used in the DHT.
uint32_t data
The data value.
uint16_t status
See PRISM_STATUS_*-constants.
static char * value
Value of the record to add/remove.
static unsigned int num_a
static void statistics_done(void *cls, int success)
struct SetInfo info1
static unsigned int force_full
int main(int argc, char **argv)
static void set_listen_cb(void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request)
static unsigned int num_b
static void pre_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
static int ret
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
static unsigned int force_delta
static int map_remove_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
static struct GNUNET_HashCode app_id
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
static int byzantine
static void check_all_done(void)
struct SetInfo info2
static const struct GNUNET_CONFIGURATION_Handle * config
static int statistics_result(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
Callback function to process statistic values.
static unsigned int num_c
static FILE * statistics_file
The profiler will write statistics for all peers to this file.
static struct GNUNET_CONTAINER_MultiHashMap * common_sent
static int set_insert_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
static void set_result_cb(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
static char * op_str
static char * statistics_filename
The profiler will write statistics for all peers to the file with this name.
static unsigned int element_size
static struct GNUNET_SET_ListenHandle * set_listener
static struct GNUNET_PeerIdentity local_peer
static void handle_shutdown(void *cls)
static char * subsystem
Set to subsystem that we're going to get stats for (or NULL for all).
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
#define GNUNET_log(kind,...)
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
int GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host's peer.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_filename(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a filename (automatically path expanded).
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_uint(char shortName, const char *name, const char *argumentHelp, const char *description, unsigned int *val)
Allow user to specify an unsigned int.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:99
int GNUNET_CONTAINER_multihashmap_remove_all(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Remove all entries for the given key from the map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_malloc(size)
Wrapper around malloc.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run2(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls, int run_without_scheduler)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:126
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1331
GNUNET_SET_Status
Status for the result callback.
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:771
void GNUNET_SET_listen_cancel(struct GNUNET_SET_ListenHandle *lh)
Cancel the given listen operation.
Definition: set_api.c:1050
struct GNUNET_SET_Handle * GNUNET_SET_create(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op)
Create an empty set, supporting the specified operation.
Definition: set_api.c:656
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:516
struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: set_api.c:812
int GNUNET_SET_commit(struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set)
Commit a set to be used with a set operation.
Definition: set_api.c:1127
struct GNUNET_SET_OperationHandle * GNUNET_SET_accept(struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SET_listen().
Definition: set_api.c:1084
struct GNUNET_SET_ListenHandle * GNUNET_SET_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op_type, const struct GNUNET_HashCode *app_id, GNUNET_SET_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application ID.
Definition: set_api.c:1016
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:686
@ GNUNET_SET_STATUS_FAILURE
The other peer refused to to the operation with us, or something went wrong.
@ GNUNET_SET_STATUS_ADD_REMOTE
Element should be added to the result set of the remote peer, i.e.
@ GNUNET_SET_STATUS_HALF_DONE
Success, all elements have been returned (but the other peer might still be receiving some from us,...
@ GNUNET_SET_STATUS_DONE
Success, all elements have been sent (and received).
@ GNUNET_SET_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
@ GNUNET_SET_OPTION_FORCE_DELTA
Only use optimized set operations, even though for this particular set operation they might be much s...
@ GNUNET_SET_OPTION_BYZANTINE
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault.
@ GNUNET_SET_OPTION_FORCE_FULL
Do not use the optimized set operation, but send full sets.
@ GNUNET_SET_RESULT_SYMMETRIC
Client gets notified of the required changes for both the local and the remote set.
@ GNUNET_SET_OPERATION_UNION
Set union, return all elements that are in at least one of the sets.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls)
Get statistic from the peer.
int GNUNET_TESTING_peer_run(const char *testdir, const char *cfgfilename, GNUNET_TESTING_TestMain tm, void *tm_cls)
Start a single peer and run a test using the testing library.
Definition: testing.c:1592
const char * name
Internal representation of the hash map.
Definition of a command line option.
A 512-bit hashcode.
Header for all communications.
The identity of the host (wraps the signing key of the peer).
Element stored in a set.
uint16_t size
Number of bytes in the buffer pointed to by data.
const void * data
Actual data of the element.
Opaque handle to a set.
Definition: set_api.c:50
Opaque handle to a listen operation.
Definition: set_api.c:187
Handle to an operation.
Definition: set_api.c:136
Option for set operations.
Handle for a set operation request from another peer.
Definition: set_api.c:116
Handle for the service.
Handle for a GNUnet peer controlled by testing.
Definition: testing.c:167
struct GNUNET_SET_OperationHandle * oh
struct GNUNET_CONTAINER_MultiHashMap * sent
struct GNUNET_SET_Handle * set
struct GNUNET_CONTAINER_MultiHashMap * received
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.