GNUnet  0.20.0
gnunet-setu-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_setu_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_SETU_Element *element,
170  uint64_t current_size,
172 {
173  struct SetInfo *info = cls;
174 
175  GNUNET_assert (GNUNET_NO == info->done);
176  switch (status)
177  {
179  info->done = GNUNET_YES;
180  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id);
181  check_all_done ();
182  info->oh = NULL;
183  return;
184 
186  info->oh = NULL;
187  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n");
189  return;
190 
192  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: local element\n", info->id);
193  break;
194  default:
195  GNUNET_assert (0);
196  }
197 
198  if (element->size != element_size)
199  {
201  "wrong element size: %u, expected %u\n",
202  element->size,
203  (unsigned int) sizeof(struct GNUNET_HashCode));
204  GNUNET_assert (0);
205  }
206 
207  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n",
208  info->id, GNUNET_h2s (element->data));
209  GNUNET_assert (NULL != element->data);
210  struct GNUNET_HashCode data_hash;
211  GNUNET_CRYPTO_hash (element->data, element_size, &data_hash);
213  &data_hash, NULL,
215 }
216 
217 
218 static void
219 set_listen_cb (void *cls,
220  const struct GNUNET_PeerIdentity *other_peer,
221  const struct GNUNET_MessageHeader *context_msg,
223 {
224  /* max. 2 options plus terminator */
225  struct GNUNET_SETU_Option opts[3] = { { 0 } };
226  unsigned int n_opts = 0;
227 
228  if (NULL == request)
229  {
231  "listener failed\n");
232  return;
233  }
234  GNUNET_assert (NULL == info2.oh);
236  "set listen cb called\n");
237  if (byzantine)
238  {
239  opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
241  }
243  if (force_full)
244  {
245  opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
247  }
248  if (force_delta)
249  {
250  opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
252  }
253 
254  opts[n_opts].type = 0;
256  opts,
257  set_result_cb, &info2);
259 }
260 
261 
262 static int
264  const struct GNUNET_HashCode *key,
265  void *value)
266 {
267  struct GNUNET_SETU_Handle *set = cls;
268  struct GNUNET_SETU_Element el;
269 
270  el.element_type = 0;
271  el.data = value;
272  el.size = element_size;
273  GNUNET_SETU_add_element (set, &el, NULL, NULL);
274  return GNUNET_YES;
275 }
276 
277 
278 static void
279 handle_shutdown (void *cls)
280 {
282  "Shutting down set profiler\n");
283  if (NULL != set_listener)
284  {
286  set_listener = NULL;
287  }
288  if (NULL != info1.oh)
289  {
291  info1.oh = NULL;
292  }
293  if (NULL != info2.oh)
294  {
296  info2.oh = NULL;
297  }
298  if (NULL != info1.set)
299  {
301  info1.set = NULL;
302  }
303  if (NULL != info2.set)
304  {
306  info2.set = NULL;
307  }
309 }
310 
311 
312 static void
313 run (void *cls,
314  const struct GNUNET_CONFIGURATION_Handle *cfg,
315  struct GNUNET_TESTING_Peer *peer)
316 {
317  unsigned int i;
318  struct GNUNET_HashCode hash;
319  /* max. 2 options plus terminator */
320  struct GNUNET_SETU_Option opts[3] = { { 0 } };
321  unsigned int n_opts = 0;
322 
323  config = cfg;
324 
326 
328  {
329  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
330  ret = 0;
331  return;
332  }
333 
334  statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
335 
337 
338  info1.id = "a";
339  info2.id = "b";
340 
344 
347 
348  for (i = 0; i < num_a; i++)
349  {
350  char *data = GNUNET_malloc (element_size);
355  }
356 
357  for (i = 0; i < num_b; i++)
358  {
359  char *data = GNUNET_malloc (element_size);
364  }
365 
366  for (i = 0; i < num_c; i++)
367  {
368  char *data = GNUNET_malloc (element_size);
373  }
374 
376 
377  /* FIXME: also implement intersection etc. */
380 
382  info1.set);
384  info2.set);
386  info1.set);
388  info2.set);
389 
391  &app_id,
392  &set_listen_cb,
393  NULL);
394 
395 
396  if (byzantine)
397  {
398  opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
400  }
402  if (force_full)
403  {
404  opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
406  }
407  if (force_delta)
408  {
409  opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
411  }
412 
413  opts[n_opts].type = 0;
414 
416  opts,
417  set_result_cb, &info1);
420  info1.set = NULL;
421 }
422 
423 
424 static void
425 pre_run (void *cls, char *const *args, const char *cfgfile,
426  const struct GNUNET_CONFIGURATION_Handle *cfg)
427 {
428  if (0 != GNUNET_TESTING_peer_run ("set-profiler",
429  cfgfile,
430  &run, NULL))
431  ret = 2;
432 }
433 
434 
435 int
436 main (int argc, char **argv)
437 {
440  "num-first",
441  NULL,
442  gettext_noop ("number of values"),
443  &num_a),
444 
446  "num-second",
447  NULL,
448  gettext_noop ("number of values"),
449  &num_b),
450 
452  "byzantine",
453  gettext_noop ("use byzantine mode"),
454  &byzantine),
455 
457  "force-full",
458  NULL,
459  gettext_noop ("force sending full set"),
460  &force_full),
461 
463  "force-delta",
464  NULL,
465  gettext_noop ("number delta operation"),
466  &force_delta),
467 
469  "num-common",
470  NULL,
471  gettext_noop ("number of values"),
472  &num_c),
473 
475  "operation",
476  NULL,
477  gettext_noop ("operation to execute"),
478  &op_str),
479 
481  "element-size",
482  NULL,
483  gettext_noop ("element size"),
484  &element_size),
485 
487  "statistics",
488  "FILENAME",
489  gettext_noop ("write statistics to file"),
491 
493  };
494 
495  GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set-profiler",
496  "help",
497  options, &pre_run, NULL, GNUNET_YES);
498  return ret;
499 }
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:70
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.
#define info
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 unsigned int num_b
static void set_listen_cb(void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SETU_Request *request)
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 void set_result_cb(void *cls, const struct GNUNET_SETU_Element *element, uint64_t current_size, enum GNUNET_SETU_Status status)
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 struct GNUNET_SETU_ListenHandle * set_listener
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_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:40
Two-peer set union operations.
API to create, modify and access statistics.
API for writing tests and creating large-scale emulation testbeds for GNUnet.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue 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:100
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.
enum GNUNET_GenericReturnValue 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.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback 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_log(kind,...)
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#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:132
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
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:1334
struct GNUNET_SETU_Handle * GNUNET_SETU_create(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create an empty set, supporting the specified operation.
Definition: setu_api.c:384
void GNUNET_SETU_operation_cancel(struct GNUNET_SETU_OperationHandle *oh)
Cancel the given set operation.
Definition: setu_api.c:320
struct GNUNET_SETU_ListenHandle * GNUNET_SETU_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *app_id, GNUNET_SETU_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application ID.
Definition: setu_api.c:717
struct GNUNET_SETU_OperationHandle * GNUNET_SETU_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, const struct GNUNET_SETU_Option options[], GNUNET_SETU_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: setu_api.c:497
void GNUNET_SETU_destroy(struct GNUNET_SETU_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: setu_api.c:471
struct GNUNET_SETU_OperationHandle * GNUNET_SETU_accept(struct GNUNET_SETU_Request *request, const struct GNUNET_SETU_Option options[], GNUNET_SETU_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SETU_listen().
Definition: setu_api.c:769
int GNUNET_SETU_commit(struct GNUNET_SETU_OperationHandle *oh, struct GNUNET_SETU_Handle *set)
Commit a set to be used with a set operation.
Definition: setu_api.c:851
GNUNET_SETU_Status
Status for the result callback.
void GNUNET_SETU_listen_cancel(struct GNUNET_SETU_ListenHandle *lh)
Cancel the given listen operation.
Definition: setu_api.c:749
int GNUNET_SETU_add_element(struct GNUNET_SETU_Handle *set, const struct GNUNET_SETU_Element *element, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Add an element to the given set.
Definition: setu_api.c:429
@ GNUNET_SETU_OPTION_FORCE_DELTA
Only use optimized set operations, even though for this particular set operation they might be much s...
@ GNUNET_SETU_OPTION_BYZANTINE
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault.
@ GNUNET_SETU_OPTION_FORCE_FULL
Do not use the optimized set operation, but send full sets.
@ GNUNET_SETU_STATUS_DONE
Success, all elements have been sent (and received).
@ GNUNET_SETU_STATUS_FAILURE
The other peer refused to do the operation with us, or something went wrong.
@ GNUNET_SETU_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
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: setu_api.c:40
Opaque handle to a listen operation.
Definition: setu_api.c:146
Handle to an operation.
Definition: setu_api.c:95
Option for set operations.
Handle for a set operation request from another peer.
Definition: setu_api.c:75
Handle for the service.
Handle for a GNUnet peer controlled by testing.
Definition: testing.c:195
struct GNUNET_SET_OperationHandle * oh
struct GNUNET_CONTAINER_MultiHashMap * sent
struct GNUNET_SET_Handle * set
struct GNUNET_SETU_OperationHandle * oh
struct GNUNET_SETU_Handle * set
struct GNUNET_CONTAINER_MultiHashMap * received
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.