GNUnet  0.11.x
gnunet-seti-profiler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2013, 2020 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_seti_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 const static struct GNUNET_CONFIGURATION_Handle *config;
40 
41 struct SetInfo
42 {
43  char *id;
44  struct GNUNET_SETI_Handle *set;
48  int done;
49 } info1, info2;
50 
52 
53 static struct GNUNET_HashCode app_id;
54 
56 
58 
59 static unsigned int use_intersection;
60 
61 static unsigned int element_size = 32;
62 
67 
72 static char *statistics_filename;
73 
78 static FILE *statistics_file;
79 
80 
81 static int
83  const struct GNUNET_HashCode *key,
84  void *value)
85 {
86  struct GNUNET_CONTAINER_MultiHashMap *m = cls;
87  int ret;
88 
89  GNUNET_assert (NULL != key);
90 
92  if (GNUNET_OK != ret)
93  printf ("spurious element\n");
94  return GNUNET_YES;
95 }
96 
97 
108 static int
109 statistics_result (void *cls,
110  const char *subsystem,
111  const char *name,
112  uint64_t value,
113  int is_persistent)
114 {
115  if (NULL != statistics_file)
116  {
117  fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
118  long) value);
119  }
120  return GNUNET_OK;
121 }
122 
123 
124 static void
125 statistics_done (void *cls,
126  int success)
127 {
128  GNUNET_assert (GNUNET_YES == success);
129  if (NULL != statistics_file)
130  fclose (statistics_file);
132 }
133 
134 
135 static void
137 {
138  if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
139  return;
140 
142  info2.sent);
144  info1.sent);
145 
146  printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
147  info1.sent));
148  printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
149  info2.sent));
150 
151  if (NULL == statistics_filename)
152  {
154  return;
155  }
156 
157  statistics_file = fopen (statistics_filename, "w");
158  GNUNET_STATISTICS_get (statistics, NULL, NULL,
160  &statistics_result, NULL);
161 }
162 
163 
164 static void
165 set_result_cb (void *cls,
166  const struct GNUNET_SETI_Element *element,
167  uint64_t current_size,
169 {
170  struct SetInfo *info = cls;
171  struct GNUNET_HashCode hash;
172 
173  GNUNET_assert (GNUNET_NO == info->done);
174  switch (status)
175  {
177  info->done = GNUNET_YES;
179  "set intersection done\n");
180  check_all_done ();
181  info->oh = NULL;
182  return;
184  info->oh = NULL;
186  "failure\n");
188  return;
190  GNUNET_CRYPTO_hash (element->data,
191  element->size,
192  &hash);
194  "set %s: keep element %s\n",
195  info->id,
196  GNUNET_h2s (&hash));
197  break;
199  GNUNET_CRYPTO_hash (element->data,
200  element->size,
201  &hash);
203  "set %s: remove element %s\n",
204  info->id,
205  GNUNET_h2s (&hash));
206  return;
207  default:
208  GNUNET_assert (0);
209  }
210 
211  if (element->size != element_size)
212  {
214  "wrong element size: %u, expected %u\n",
215  element->size,
216  (unsigned int) sizeof(struct GNUNET_HashCode));
217  GNUNET_assert (0);
218  }
219 
221  "set %s: got element (%s)\n",
222  info->id, GNUNET_h2s (element->data));
223  GNUNET_assert (NULL != element->data);
224  {
225  struct GNUNET_HashCode data_hash;
226 
227  GNUNET_CRYPTO_hash (element->data,
228  element_size,
229  &data_hash);
231  &data_hash,
232  NULL,
234  }
235 }
236 
237 
238 static void
239 set_listen_cb (void *cls,
240  const struct GNUNET_PeerIdentity *other_peer,
241  const struct GNUNET_MessageHeader *context_msg,
243 {
244  /* max. 1 option plus terminator */
245  struct GNUNET_SETI_Option opts[2] = { { 0 } };
246  unsigned int n_opts = 0;
247 
248  if (NULL == request)
249  {
251  "listener failed\n");
252  return;
253  }
254  GNUNET_assert (NULL == info2.oh);
256  "set listen cb called\n");
257  if (use_intersection)
258  {
259  opts[n_opts++] = (struct GNUNET_SETI_Option) { .type =
261  }
262  opts[n_opts].type = GNUNET_SETI_OPTION_END;
263  info2.oh = GNUNET_SETI_accept (request,
264  opts,
265  &set_result_cb,
266  &info2);
268  info2.set);
269 }
270 
271 
272 static int
274  const struct GNUNET_HashCode *key,
275  void *value)
276 {
277  struct GNUNET_SETI_Handle *set = cls;
278  struct GNUNET_SETI_Element el;
279 
280  el.element_type = 0;
281  el.data = value;
282  el.size = element_size;
283  GNUNET_SETI_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  {
295  GNUNET_SETI_listen_cancel (set_listener);
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  }
318  GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
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. 1 option plus terminator */
330  struct GNUNET_SETI_Option opts[2] = { { 0 } };
331  unsigned int n_opts = 0;
332 
333  config = cfg;
334 
336 
338  {
340  "could not retrieve host identity\n");
341  ret = 0;
342  return;
343  }
344  statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
346  info1.id = "a";
347  info2.id = "b";
353  for (i = 0; i < num_a; i++)
354  {
355  char *data = GNUNET_malloc (element_size);
357  GNUNET_CRYPTO_hash (data, element_size, &hash);
360  }
361 
362  for (i = 0; i < num_b; i++)
363  {
364  char *data = GNUNET_malloc (element_size);
366  GNUNET_CRYPTO_hash (data, element_size, &hash);
369  }
370 
371  for (i = 0; i < num_c; i++)
372  {
373  char *data = GNUNET_malloc (element_size);
375  GNUNET_CRYPTO_hash (data, element_size, &hash);
376  GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
378  }
379 
381 
382  info1.set = GNUNET_SETI_create (config);
383  info2.set = GNUNET_SETI_create (config);
386  info1.set);
389  info2.set);
392  info1.set);
395  info2.set);
396 
397  set_listener = GNUNET_SETI_listen (config,
398  &app_id,
399  &set_listen_cb,
400  NULL);
401  if (use_intersection)
402  {
403  opts[n_opts++] = (struct GNUNET_SETI_Option) { .type =
405  }
406  opts[n_opts].type = GNUNET_SETI_OPTION_END;
407 
409  &app_id,
410  NULL,
411  opts,
413  &info1);
415  info1.set);
417  info1.set = NULL;
418 }
419 
420 
421 static void
422 pre_run (void *cls,
423  char *const *args,
424  const char *cfgfile,
425  const struct GNUNET_CONFIGURATION_Handle *cfg)
426 {
427  if (0 != GNUNET_TESTING_peer_run ("set-profiler",
428  cfgfile,
429  &run, NULL))
430  ret = 2;
431 }
432 
433 
434 int
435 main (int argc, char **argv)
436 {
437  struct GNUNET_GETOPT_CommandLineOption options[] = {
439  "num-first",
440  NULL,
441  gettext_noop ("number of values"),
442  &num_a),
444  "num-second",
445  NULL,
446  gettext_noop ("number of values"),
447  &num_b),
449  "num-common",
450  NULL,
451  gettext_noop ("number of values"),
452  &num_c),
454  "use-intersection",
455  NULL,
456  gettext_noop (
457  "return intersection instead of delta"),
460  "element-size",
461  NULL,
462  gettext_noop ("element size"),
463  &element_size),
465  "statistics",
466  "FILENAME",
467  gettext_noop ("write statistics to file"),
470  };
471 
472  GNUNET_PROGRAM_run2 (argc, argv,
473  "gnunet-seti-profiler",
474  "help",
475  options,
476  &pre_run,
477  NULL,
478  GNUNET_YES);
479  return ret;
480 }
static void statistics_done(void *cls, int success)
Success, all elements have been sent (and received).
static char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
int GNUNET_SETI_add_element(struct GNUNET_SETI_Handle *set, const struct GNUNET_SETI_Element *element, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Add an element to the given set.
Definition: seti_api.c:447
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
The other peer refused to do the operation with us, or something went wrong.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
If a value with the given key exists, replace it.
int 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, parse options).
Definition: program.c:141
static int set_insert_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
static int ret
uint16_t size
Number of bytes in the buffer pointed to by data.
Handle for a GNUnet peer controlled by testing.
Definition: testing.c:164
int GNUNET_SETI_commit(struct GNUNET_SETI_OperationHandle *oh, struct GNUNET_SETI_Handle *set)
Commit a set to be used with a set operation.
Definition: seti_api.c:836
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:1590
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
struct GNUNET_CONTAINER_MultiHashMap * received
Option for set operations.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SETI_OperationHandle * oh
static unsigned int num_c
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
static void pre_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Definition of a command line option.
static unsigned int use_intersection
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.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
Handle for the service.
struct GNUNET_SETI_ListenHandle * GNUNET_SETI_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *app_id, GNUNET_SETI_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application ID.
Definition: seti_api.c:715
Opaque handle to a listen operation.
Definition: seti_api.c:162
Internal representation of the hash map.
Handle for a set operation request from another peer.
Definition: seti_api.c:85
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
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 SetInfo info1
enum GNUNET_SETI_OptionType type
Type of the option.
Element should be added to the result set of the local peer, i.e.
Opaque handle to a set.
Definition: seti_api.c:39
static struct GNUNET_HashCode app_id
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:144
static char * value
Value of the record to add/remove.
struct GNUNET_SETI_OperationHandle * GNUNET_SETI_accept(struct GNUNET_SETI_Request *request, const struct GNUNET_SETI_Option options[], GNUNET_SETI_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SETI_listen().
Definition: seti_api.c:780
void GNUNET_SETI_operation_cancel(struct GNUNET_SETI_OperationHandle *oh)
Cancel the given set operation.
Definition: seti_api.c:335
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
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 void set_listen_cb(void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SETI_Request *request)
static FILE * statistics_file
The profiler will write statistics for all peers to this file.
Element stored in a set.
uint16_t status
See PRISM_STATUS_*-constants.
const void * data
Actual data of the element.
struct GNUNET_SETI_Handle * GNUNET_SETI_create(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create an empty set, supporting the specified operation.
Definition: seti_api.c:399
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
A 512-bit hashcode.
Handle to an operation.
Definition: seti_api.c:105
static struct GNUNET_PeerIdentity local_peer
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
static const struct GNUNET_CONFIGURATION_Handle * config
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.
Element should be delete from the result set of the local peer, i.e.
static struct GNUNET_SETI_ListenHandle * set_listener
int main(int argc, char **argv)
static struct GNUNET_CONTAINER_MultiHashMap * common_sent
static char * statistics_filename
The profiler will write statistics for all peers to the file with this name.
The identity of the host (wraps the signing key of the peer).
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
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.
static void check_all_done(void)
struct GNUNET_SET_Handle * set
configuration data
Definition: configuration.c:84
static unsigned int num_b
const char * name
GNUNET_SETI_Status
Status for the result callback.
static int map_remove_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
static unsigned int num_a
#define GNUNET_log(kind,...)
static unsigned int element_size
struct GNUNET_CONTAINER_MultiHashMap * sent
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
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&#39;s peer.
Return the elements remaining in the intersection (GNUNET_SETI_STATUS_ADD_LOCAL). ...
Header for all communications.
static void set_result_cb(void *cls, const struct GNUNET_SETI_Element *element, uint64_t current_size, enum GNUNET_SETI_Status status)
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_SET_OperationHandle * oh
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
uint32_t data
The data value.
void GNUNET_SETI_listen_cancel(struct GNUNET_SETI_ListenHandle *lh)
Cancel the given listen operation.
Definition: seti_api.c:747
struct SetInfo info2
uint16_t element_type
Application-specific element type.
static void handle_shutdown(void *cls)
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_SETI_OperationHandle * GNUNET_SETI_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, const struct GNUNET_SETI_Option options[], GNUNET_SETI_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: seti_api.c:526
#define gettext_noop(String)
Definition: gettext.h:69
void GNUNET_SETI_destroy(struct GNUNET_SETI_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: seti_api.c:488
High-quality operations are desired.