GNUnet  0.10.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;
46  struct GNUNET_SET_Handle *set;
50  int done;
51 } info1, info2;
52 
54 
55 static struct GNUNET_HashCode app_id;
56 
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 
101 
112 static int
113 statistics_result (void *cls,
114  const char *subsystem,
115  const char *name,
116  uint64_t value,
117  int is_persistent)
118 {
119  if (NULL != statistics_file)
120  {
121  fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned 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 
146 
147  printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (info1.sent));
148  printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (info2.sent));
149 
150  if (NULL == statistics_filename)
151  {
153  return;
154  }
155 
156  statistics_file = fopen (statistics_filename, "w");
157  GNUNET_STATISTICS_get (statistics, NULL, NULL,
159  &statistics_result, NULL);
160 }
161 
162 
163 static void
164 set_result_cb (void *cls,
165  const struct GNUNET_SET_Element *element,
166  uint64_t current_size,
168 {
169  struct SetInfo *info = cls;
170  struct GNUNET_HashCode hash;
171 
172  GNUNET_assert (GNUNET_NO == info->done);
173  switch (status)
174  {
177  info->done = GNUNET_YES;
178  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id);
179  check_all_done ();
180  info->oh = NULL;
181  return;
183  info->oh = NULL;
184  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n");
186  return;
188  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: local element\n", info->id);
189  break;
191  GNUNET_CRYPTO_hash (element->data, element->size, &hash);
192  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: remote element %s\n", info->id,
193  GNUNET_h2s (&hash));
194  // XXX: record and check
195  return;
196  default:
197  GNUNET_assert (0);
198  }
199 
200  if (element->size != element_size)
201  {
203  "wrong element size: %u, expected %u\n",
204  element->size,
205  (unsigned int) sizeof (struct GNUNET_HashCode));
206  GNUNET_assert (0);
207  }
208 
209  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n",
210  info->id, GNUNET_h2s (element->data));
211  GNUNET_assert (NULL != element->data);
212  struct GNUNET_HashCode data_hash;
213  GNUNET_CRYPTO_hash (element->data, element_size, &data_hash);
215  &data_hash, NULL,
217 }
218 
219 
220 static void
221 set_listen_cb (void *cls,
222  const struct GNUNET_PeerIdentity *other_peer,
223  const struct GNUNET_MessageHeader *context_msg,
224  struct GNUNET_SET_Request *request)
225 {
226  /* max. 2 options plus terminator */
227  struct GNUNET_SET_Option opts[3] = {{0}};
228  unsigned int n_opts = 0;
229 
230  if (NULL == request)
231  {
233  "listener failed\n");
234  return;
235  }
236  GNUNET_assert (NULL == info2.oh);
238  "set listen cb called\n");
239  if (byzantine)
240  {
241  opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_BYZANTINE };
242  }
244  if (force_full)
245  {
246  opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_FULL };
247  }
248  if (force_delta)
249  {
250  opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_DELTA };
251  }
252 
253  opts[n_opts].type = 0;
255  opts,
256  set_result_cb, &info2);
258 }
259 
260 
261 static int
263  const struct GNUNET_HashCode *key,
264  void *value)
265 {
266  struct GNUNET_SET_Handle *set = cls;
267  struct GNUNET_SET_Element el;
268 
269  el.element_type = 0;
270  el.data = value;
271  el.size = element_size;
272  GNUNET_SET_add_element (set, &el, NULL, NULL);
273  return GNUNET_YES;
274 }
275 
276 
277 static void
278 handle_shutdown (void *cls)
279 {
281  "Shutting down set profiler\n");
282  if (NULL != set_listener)
283  {
284  GNUNET_SET_listen_cancel (set_listener);
285  set_listener = NULL;
286  }
287  if (NULL != info1.oh)
288  {
290  info1.oh = NULL;
291  }
292  if (NULL != info2.oh)
293  {
295  info2.oh = NULL;
296  }
297  if (NULL != info1.set)
298  {
300  info1.set = NULL;
301  }
302  if (NULL != info2.set)
303  {
305  info2.set = NULL;
306  }
307  GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
308 }
309 
310 
311 static void
312 run (void *cls,
313  const struct GNUNET_CONFIGURATION_Handle *cfg,
314  struct GNUNET_TESTING_Peer *peer)
315 {
316  unsigned int i;
317  struct GNUNET_HashCode hash;
318  /* max. 2 options plus terminator */
319  struct GNUNET_SET_Option opts[3] = {{0}};
320  unsigned int n_opts = 0;
321 
322  config = cfg;
323 
325 
327  {
328  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
329  ret = 0;
330  return;
331  }
332 
333  statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
334 
336 
337  info1.id = "a";
338  info2.id = "b";
339 
343 
346 
347  for (i = 0; i < num_a; i++)
348  {
349  char *data = GNUNET_malloc (element_size);
351  GNUNET_CRYPTO_hash (data, element_size, &hash);
354  }
355 
356  for (i = 0; i < num_b; i++)
357  {
358  char *data = GNUNET_malloc (element_size);
360  GNUNET_CRYPTO_hash (data, element_size, &hash);
363  }
364 
365  for (i = 0; i < num_c; i++)
366  {
367  char *data = GNUNET_malloc (element_size);
369  GNUNET_CRYPTO_hash (data, element_size, &hash);
370  GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
372  }
373 
375 
376  /* FIXME: also implement intersection etc. */
379 
384 
385  set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION,
386  &app_id, set_listen_cb, NULL);
387 
388 
389  if (byzantine)
390  {
391  opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_BYZANTINE };
392  }
394  if (force_full)
395  {
396  opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_FULL };
397  }
398  if (force_delta)
399  {
400  opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_DELTA };
401  }
402 
403  opts[n_opts].type = 0;
404 
407  opts,
408  set_result_cb, &info1);
411  info1.set = NULL;
412 }
413 
414 
415 static void
416 pre_run (void *cls, char *const *args, const char *cfgfile,
417  const struct GNUNET_CONFIGURATION_Handle *cfg)
418 {
419  if (0 != GNUNET_TESTING_peer_run ("set-profiler",
420  cfgfile,
421  &run, NULL))
422  ret = 2;
423 }
424 
425 
426 int
427 main (int argc, char **argv)
428 {
429  struct GNUNET_GETOPT_CommandLineOption options[] = {
431  "num-first",
432  NULL,
433  gettext_noop ("number of values"),
434  &num_a),
435 
437  "num-second",
438  NULL,
439  gettext_noop ("number of values"),
440  &num_b),
441 
443  "byzantine",
444  gettext_noop ("use byzantine mode"),
445  &byzantine),
446 
448  "force-full",
449  NULL,
450  gettext_noop ("force sending full set"),
451  &force_full),
452 
454  "force-delta",
455  NULL,
456  gettext_noop ("number delta operation"),
457  &force_delta),
458 
460  "num-common",
461  NULL,
462  gettext_noop ("number of values"),
463  &num_c),
464 
466  "operation",
467  NULL,
468  gettext_noop ("operation to execute"),
469  &op_str),
470 
472  "element-size",
473  NULL,
474  gettext_noop ("element size"),
475  &element_size),
476 
478  "statistics",
479  "FILENAME",
480  gettext_noop ("write statistics to file"),
482 
484  };
485  GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set-profiler",
486  "help",
487  options, &pre_run, NULL, GNUNET_YES);
488  return ret;
489 }
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
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:1013
static char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
static unsigned int element_size
static int byzantine
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
If a value with the given key exists, replace it.
Handle for a set operation request from another peer.
Definition: set_api.c:115
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
Element should be added to the result set of the remote peer, i.e.
Handle for a GNUnet peer controlled by testing.
Definition: testing.c:175
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:1553
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:1293
Element stored in a set.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
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
Element should be added to the result set of the local peer, i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Do not use the optimized set operation, but send full sets.
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
#define GNUNET_NO
Definition: gnunet_common.h:81
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static char * op_str
static struct GNUNET_HashCode app_id
Definition of a command line option.
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_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
static struct GNUNET_PeerIdentity local_peer
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:524
Handle for the service.
static unsigned int force_full
Success, all elements have been sent (and received).
Internal representation of the hash map.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
const void * data
Actual data of the element.
enum GNUNET_SET_OptionType type
Type of the option.
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.
static void statistics_done(void *cls, int success)
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:771
struct GNUNET_CONTAINER_MultiHashMap * received
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
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).
Only use optimized set operations, even though for this particular set operation they might be much s...
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:138
static char * value
Value of the record to add/remove.
The other peer refused to to the operation with us, or something went wrong.
Success, all elements have been returned (but the other peer might still be receiving some from us...
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
GNUNET_SET_Status
Status for the result callback.
static unsigned int num_a
static int map_remove_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
uint16_t status
See PRISM_STATUS_*-constants.
static const struct GNUNET_CONFIGURATION_Handle * config
static int set_insert_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
static struct GNUNET_SET_ListenHandle * set_listener
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 int ret
A 512-bit hashcode.
Client gets notified of the required changes for both the local and the remote set.
static unsigned int num_c
Opaque handle to a set.
Definition: set_api.c:49
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
static char * statistics_filename
The profiler will write statistics for all peers to the file with this name.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
static FILE * statistics_file
The profiler will write statistics for all peers to this file.
int main(int argc, char **argv)
const char * name
static void check_all_done(void)
void GNUNET_SET_listen_cancel(struct GNUNET_SET_ListenHandle *lh)
Cancel the given listen operation.
Definition: set_api.c:1047
Option for set operations.
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.
static void handle_shutdown(void *cls)
struct SetInfo info1
Handle to an operation.
Definition: set_api.c:135
The identity of the host (wraps the signing key of the peer).
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:1124
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.
struct GNUNET_SET_Handle * set
configuration data
Definition: configuration.c:85
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.
uint16_t size
Number of bytes in the buffer pointed to by data.
#define GNUNET_log(kind,...)
Opaque handle to a listen operation.
Definition: set_api.c:186
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.
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:515
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
Header for all communications.
#define GNUNET_YES
Definition: gnunet_common.h:80
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.
static void pre_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
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.
Set union, return all elements that are in at least one of the sets.
static struct GNUNET_CONTAINER_MultiHashMap * common_sent
uint32_t data
The data value.
static void set_result_cb(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
static unsigned int force_delta
struct SetInfo info2
uint16_t element_type
Application-specific element type.
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:1081
#define gettext_noop(String)
Definition: gettext.h:69
struct GNUNET_CONTAINER_MultiHashMap * sent
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
High-quality operations are desired.