aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSupriti Singh <supritisingh08@gmail.com>2014-08-24 22:28:45 +0000
committerSupriti Singh <supritisingh08@gmail.com>2014-08-24 22:28:45 +0000
commit4e042c2ff9035c96c1e1edf83100c2dc6863fa17 (patch)
treedbf030f2531bf61ea1f8a43a9850b9a70f5dedb0 /src
parent7b9618d4bb1b6bf38877b9b85ad29b4595923c46 (diff)
downloadgnunet-4e042c2ff9035c96c1e1edf83100c2dc6863fa17.tar.gz
gnunet-4e042c2ff9035c96c1e1edf83100c2dc6863fa17.zip
Randomized PUT/GET delay interval.
Diffstat (limited to 'src')
-rw-r--r--src/dht/gnunet-service-xdht_neighbours.c39
-rw-r--r--src/dht/gnunet_dht_profiler.c19
-rw-r--r--src/dht/gnunet_dht_r5n_profiler.c668
3 files changed, 688 insertions, 38 deletions
diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c
index 332156d00..dde456037 100644
--- a/src/dht/gnunet-service-xdht_neighbours.c
+++ b/src/dht/gnunet-service-xdht_neighbours.c
@@ -80,7 +80,7 @@
80/** 80/**
81 * How long to wait before sending another verify successor message. 81 * How long to wait before sending another verify successor message.
82 */ 82 */
83#define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) 83#define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
84 84
85/** 85/**
86 * How long to wait before sending another verify successor message. 86 * How long to wait before sending another verify successor message.
@@ -4826,31 +4826,7 @@ handle_dht_p2p_verify_successor(void *cls,
4826 { 4826 {
4827 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST); 4827 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
4828 if (NULL == next_hop) 4828 if (NULL == next_hop)
4829 { 4829 {
4830 //SUPUs anyways you are passing the trail, just do the lookup
4831 // and pass the message forward.
4832// int my_index = search_my_index (trail, trail_length);
4833// if(-1 == my_index)
4834// {
4835// DEBUG(" Peer %s not present in trail id %s, line =%d",
4836// GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__);
4837// GNUNET_break_op (0);
4838// return GNUNET_OK;
4839// }
4840// if((my_index == trail_length + 1))
4841// {
4842// DEBUG(" Peer %s present twice in trail id %s, line =%d",
4843// GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__);
4844// GNUNET_break_op (0);
4845// return GNUNET_OK;
4846// }
4847// if(my_index == (trail_length - 1))
4848// {
4849// *next_hop = successor;
4850// }
4851// else
4852// *next_hop = trail[my_index + 1];
4853
4854 return GNUNET_OK; 4830 return GNUNET_OK;
4855 } 4831 }
4856 4832
@@ -5033,17 +5009,10 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ,
5033 memcpy (&my_id, &my_identity, sizeof(uint64_t)); 5009 memcpy (&my_id, &my_identity, sizeof(uint64_t));
5034 my_id_str = GNUNET_strdup (GNUNET_i2s_full (&my_identity)); 5010 my_id_str = GNUNET_strdup (GNUNET_i2s_full (&my_identity));
5035 memcpy(&succ, &current_successor->finger_identity, sizeof(uint64_t)); 5011 memcpy(&succ, &current_successor->finger_identity, sizeof(uint64_t));
5012 succ = GNUNET_ntohll(succ);
5036 GNUNET_asprintf (&key, "XDHT:%s:", my_id_str); 5013 GNUNET_asprintf (&key, "XDHT:%s:", my_id_str);
5037 GNUNET_free (my_id_str); 5014 GNUNET_free (my_id_str);
5038 FPRINTF (stderr,_("\nSUPU %s, %s, %d,MY_ID = %llu and successor_id = %llu"), 5015
5039 __FILE__, __func__,__LINE__,(unsigned long long)my_id, (unsigned long long)succ);
5040 struct GNUNET_PeerIdentity print_peer;
5041 print_peer = my_identity;
5042 FPRINTF (stderr,_("\nSUPU my_id = %s,my_id64 = %llu, %s, %s, %d"),
5043 GNUNET_i2s(&print_peer),(unsigned long long)my_id,__FILE__, __func__,__LINE__);
5044 print_peer = current_successor->finger_identity;
5045 FPRINTF (stderr,_("\nSUPU current_successor->finger_identity = %s,my_id64 = %llu, %s, %s, %d"),
5046 GNUNET_i2s(&print_peer),(unsigned long long)succ,__FILE__, __func__,__LINE__);
5047 GNUNET_STATISTICS_set (GDS_stats, key, succ, 0); 5016 GNUNET_STATISTICS_set (GDS_stats, key, succ, 0);
5048 GNUNET_free (key); 5017 GNUNET_free (key);
5049 } 5018 }
diff --git a/src/dht/gnunet_dht_profiler.c b/src/dht/gnunet_dht_profiler.c
index bc6a08ebc..12fa7be4d 100644
--- a/src/dht/gnunet_dht_profiler.c
+++ b/src/dht/gnunet_dht_profiler.c
@@ -373,7 +373,6 @@ static int in_shutdown = 0;
373static void 373static void
374collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 374collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
375 375
376
377/** 376/**
378 * Shutdown task. Cleanup all resources and operations. 377 * Shutdown task. Cleanup all resources and operations.
379 * 378 *
@@ -741,12 +740,24 @@ dht_connected (void *cls,
741 switch (mode) 740 switch (mode)
742 { 741 {
743 case MODE_PUT: 742 case MODE_PUT:
743 {
744 delay_put.rel_value_us =
745 delay_put.rel_value_us +
746 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
747 delay_put.rel_value_us);
744 ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay_put, &delayed_put, ac); 748 ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay_put, &delayed_put, ac);
745 break; 749 break;
750 }
746 case MODE_GET: 751 case MODE_GET:
752 {
753 delay_get.rel_value_us =
754 delay_get.rel_value_us +
755 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
756 delay_get.rel_value_us);
747 ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay_get, &delayed_get, ac); 757 ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay_get, &delayed_get, ac);
748 break; 758 break;
749 } 759 }
760 }
750} 761}
751 762
752 763
@@ -1060,6 +1071,8 @@ set_malicious()
1060 } 1071 }
1061} 1072}
1062#endif 1073#endif
1074
1075
1063/** 1076/**
1064 * Callback called when DHT service on the peer is started 1077 * Callback called when DHT service on the peer is started
1065 * 1078 *
@@ -1254,10 +1267,10 @@ main (int argc, char *const *argv)
1254 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 1267 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1255 return 2; 1268 return 2;
1256 /* set default delays */ 1269 /* set default delays */
1257 delay_stats = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); 1270 delay_stats = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1);
1258 delay_put = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1); 1271 delay_put = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1);
1259 delay_get = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1); 1272 delay_get = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1);
1260 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3); 1273 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5);
1261 replication = 1; /* default replication */ 1274 replication = 1; /* default replication */
1262 rc = 0; 1275 rc = 0;
1263 if (GNUNET_OK != 1276 if (GNUNET_OK !=
diff --git a/src/dht/gnunet_dht_r5n_profiler.c b/src/dht/gnunet_dht_r5n_profiler.c
new file mode 100644
index 000000000..9921c0aed
--- /dev/null
+++ b/src/dht/gnunet_dht_r5n_profiler.c
@@ -0,0 +1,668 @@
1/*
2 This file is part of GNUnet.
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet_dht_profiler.c
23 * @brief Profiler for GNUnet DHT
24 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testbed_service.h"
30#include "gnunet_dht_service.h"
31
32#define INFO(...) \
33 GNUNET_log (GNUNET_ERROR_TYPE_INFO, __VA_ARGS__)
34
35#define DEBUG(...) \
36 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
37
38/**
39 * Number of peers which should perform a PUT out of 100 peers
40 */
41#define PUT_PROBABILITY 50
42
43/**
44 * Configuration
45 */
46static struct GNUNET_CONFIGURATION_Handle *cfg;
47
48/**
49 * Name of the file with the hosts to run the test over
50 */
51static char *hosts_file;
52
53/**
54 * Context for a peer which actively does DHT PUT/GET
55 */
56struct ActiveContext;
57
58/**
59 * Context to hold data of peer
60 */
61struct Context
62{
63
64 /**
65 * The testbed peer this context belongs to
66 */
67 struct GNUNET_TESTBED_Peer *peer;
68
69 /**
70 * Testbed operation acting on this peer
71 */
72 struct GNUNET_TESTBED_Operation *op;
73
74 /**
75 * Active context; NULL if this peer is not an active peer
76 */
77 struct ActiveContext *ac;
78};
79
80
81/**
82 * Context for a peer which actively does DHT PUT/GET
83 */
84struct ActiveContext
85{
86 /**
87 * The linked peer context
88 */
89 struct Context *ctx;
90
91 /**
92 * Handler to the DHT service
93 */
94 struct GNUNET_DHT_Handle *dht;
95
96 /**
97 * The data used for do a PUT. Will be NULL if a PUT hasn't been performed yet
98 */
99 void *put_data;
100
101 /**
102 * The active context used for our DHT GET
103 */
104 struct ActiveContext *get_ac;
105
106 /**
107 * The put handle
108 */
109 struct GNUNET_DHT_PutHandle *dht_put;
110
111 /**
112 * The get handle
113 */
114 struct GNUNET_DHT_GetHandle *dht_get;
115
116 /**
117 * The hash of the @put_data
118 */
119 struct GNUNET_HashCode hash;
120
121 /**
122 * Delay task
123 */
124 GNUNET_SCHEDULER_TaskIdentifier delay_task;
125
126 /**
127 * The size of the put_data
128 */
129 uint16_t put_data_size;
130
131 /**
132 * The number of peers currently doing GET on our data
133 */
134 uint16_t nrefs;
135};
136
137
138/**
139 * An array of contexts. The size of this array should be equal to @a num_peers
140 */
141static struct Context *a_ctx;
142
143/**
144 * Array of active peers
145 */
146static struct ActiveContext *a_ac;
147
148/**
149 * The delay between starting to do PUTS and GETS
150 */
151static struct GNUNET_TIME_Relative delay;
152
153/**
154 * The timeout for GET and PUT
155 */
156static struct GNUNET_TIME_Relative timeout;
157
158/**
159 * Number of peers
160 */
161static unsigned int num_peers;
162
163/**
164 * Number of active peers
165 */
166static unsigned int n_active;
167
168/**
169 * Number of DHT service connections we currently have
170 */
171static unsigned int n_dht;
172
173/**
174 * Number of DHT PUTs made
175 */
176static unsigned int n_puts;
177
178/**
179 * Number of DHT PUTs succeeded
180 */
181static unsigned int n_puts_ok;
182
183/**
184 * Number of DHT PUTs failed
185 */
186static unsigned int n_puts_fail;
187
188/**
189 * Number of DHT GETs made
190 */
191static unsigned int n_gets;
192
193/**
194 * Number of DHT GETs succeeded
195 */
196static unsigned int n_gets_ok;
197
198/**
199 * Number of DHT GETs succeeded
200 */
201static unsigned int n_gets_fail;
202
203
204/**
205 * Shutdown task. Cleanup all resources and operations.
206 *
207 * @param cls NULL
208 * @param tc scheduler task context
209 */
210static void
211do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
212{
213 struct ActiveContext *ac;
214 unsigned int cnt;
215
216 if (NULL != a_ctx)
217 {
218 for (cnt=0; cnt < num_peers; cnt++)
219 {
220 if (NULL != a_ctx[cnt].op)
221 GNUNET_TESTBED_operation_done (a_ctx[cnt].op);
222
223 /* Cleanup active context if this peer is an active peer */
224 ac = a_ctx[cnt].ac;
225 if (NULL == ac)
226 continue;
227 if (GNUNET_SCHEDULER_NO_TASK != ac->delay_task)
228 GNUNET_SCHEDULER_cancel (ac->delay_task);
229 if (NULL != ac->put_data)
230 GNUNET_free (ac->put_data);
231 if (NULL != ac->dht_put)
232 GNUNET_DHT_put_cancel (ac->dht_put);
233 if (NULL != ac->dht_get)
234 GNUNET_DHT_get_stop (ac->dht_get);
235 }
236 GNUNET_free (a_ctx);
237 a_ctx = NULL;
238 }
239 GNUNET_free_non_null (a_ac);
240}
241
242
243static void
244summarize ()
245{
246 INFO ("# PUTS made: %u\n", n_puts);
247 INFO ("# PUTS succeeded: %u\n", n_puts_ok);
248 INFO ("# PUTS failed: %u\n", n_puts_fail);
249 INFO ("# GETS made: %u\n", n_gets);
250 INFO ("# GETS succeeded: %u\n", n_gets_ok);
251 INFO ("# GETS failed: %u\n", n_gets_fail);
252 GNUNET_SCHEDULER_shutdown ();
253}
254
255
256/**
257 * Task to cancel DHT GET.
258 *
259 * @param cls NULL
260 * @param tc scheduler task context
261 */
262static void
263cancel_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
264{
265 struct ActiveContext *ac = cls;
266
267 ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
268 GNUNET_assert (NULL != ac->dht_get);
269 GNUNET_DHT_get_stop (ac->dht_get);
270 ac->dht_get = NULL;
271 n_gets_fail++;
272
273 /* If profiling is complete, summarize */
274 if (n_gets == n_gets_fail + n_gets_ok)
275 summarize ();
276}
277
278
279/**
280 * Iterator called on each result obtained for a DHT
281 * operation that expects a reply
282 *
283 * @param cls closure
284 * @param exp when will this value expire
285 * @param key key of the result
286 * @param get_path peers on reply path (or NULL if not recorded)
287 * [0] = datastore's first neighbor, [length - 1] = local peer
288 * @param get_path_length number of entries in @a get_path
289 * @param put_path peers on the PUT path (or NULL if not recorded)
290 * [0] = origin, [length - 1] = datastore
291 * @param put_path_length number of entries in @a put_path
292 * @param type type of the result
293 * @param size number of bytes in @a data
294 * @param data pointer to the result data
295 */
296static void
297get_iter (void *cls,
298 struct GNUNET_TIME_Absolute exp,
299 const struct GNUNET_HashCode *key,
300 const struct GNUNET_PeerIdentity *get_path,
301 unsigned int get_path_length,
302 const struct GNUNET_PeerIdentity *put_path,
303 unsigned int put_path_length,
304 enum GNUNET_BLOCK_Type type,
305 size_t size, const void *data)
306{
307 struct ActiveContext *ac = cls;
308 struct ActiveContext *get_ac = ac->get_ac;
309
310 if (get_ac->put_data_size != size)
311 {
312 DEBUG ("Found a GET with incorrect data length (this may happen, but very unlikely)\n");
313 return;
314 }
315 if (0 != memcmp (data, get_ac->put_data, size))
316 {
317 DEBUG ("Found a GET with incorrect data (this may happen, but very unlikely)\n");
318 return;
319 }
320
321 /* we found the data we are looking for */
322 DEBUG ("We found a GET request; %u remaining\n", n_gets - (n_gets_fail + n_gets_ok));
323 n_gets_ok++;
324 get_ac->nrefs--;
325 GNUNET_DHT_get_stop (ac->dht_get);
326 ac->dht_get = NULL;
327 GNUNET_SCHEDULER_cancel (ac->delay_task);
328 ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
329
330 /* Summarize if profiling is complete */
331 if (n_gets == n_gets_fail + n_gets_ok)
332 summarize ();
333}
334
335
336/**
337 * Task to do DHT GETs
338 *
339 * @param cls the active context
340 * @param tc the scheduler task context
341 */
342static void
343delayed_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
344{
345 struct ActiveContext *ac = cls;
346 struct ActiveContext *get_ac;
347 unsigned int r;
348
349 ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
350 get_ac = NULL;
351 while (1)
352 {
353 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, n_active);
354 get_ac = &a_ac[r];
355 if (NULL != get_ac->put_data)
356 break;
357 }
358 get_ac->nrefs++;
359 ac->get_ac = get_ac;
360 ac->dht_get = GNUNET_DHT_get_start (ac->dht,
361 GNUNET_BLOCK_TYPE_TEST,
362 &ac->hash,
363 1, /* replication level */
364 GNUNET_DHT_RO_NONE,
365 NULL, 0, /* extended query and size */
366 get_iter, ac); /* GET iterator and closure
367 */
368 n_gets++;
369
370 /* schedule the timeout task for GET */
371 ac->delay_task = GNUNET_SCHEDULER_add_delayed (timeout, &cancel_get, ac);
372}
373
374
375/**
376 * Queue up a delayed task for doing DHT GET
377 *
378 * @param cls the active context
379 * @param success #GNUNET_OK if the PUT was transmitted,
380 * #GNUNET_NO on timeout,
381 * #GNUNET_SYSERR on disconnect from service
382 * after the PUT message was transmitted
383 * (so we don't know if it was received or not)
384 */
385static void
386put_cont (void *cls, int success)
387{
388 struct ActiveContext *ac = cls;
389
390 ac->dht_put = NULL;
391 if (success)
392 n_puts_ok++;
393 else
394 n_puts_fail++;
395 ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay, &delayed_get, ac);
396}
397
398
399/**
400 * Task to do DHT PUTS
401 *
402 * @param cls the active context
403 * @param tc the scheduler task context
404 */
405static void
406delayed_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
407{
408 struct ActiveContext *ac = cls;
409
410 ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
411 /* Generate and DHT PUT some random data */
412 ac->put_data_size = 16; /* minimum */
413 ac->put_data_size += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
414 (63*1024));
415 ac->put_data = GNUNET_malloc (ac->put_data_size);
416 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
417 ac->put_data, ac->put_data_size);
418 GNUNET_CRYPTO_hash (ac->put_data, ac->put_data_size, &ac->hash);
419 DEBUG ("Doing a DHT PUT with data of size %u\n", ac->put_data_size);
420 ac->dht_put = GNUNET_DHT_put (ac->dht, &ac->hash,
421 1, /* replication level */
422 GNUNET_DHT_RO_NONE,
423 GNUNET_BLOCK_TYPE_TEST,
424 ac->put_data_size,
425 ac->put_data,
426 GNUNET_TIME_UNIT_FOREVER_ABS, /* expiration time */
427 timeout, /* PUT timeout */
428 put_cont, ac); /* continuation and its closure */
429 n_puts++;
430}
431
432
433/**
434 * Connection to DHT has been established. Call the delay task.
435 *
436 * @param cls the active context
437 * @param op the operation that has been finished
438 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
439 * @param emsg error message in case the operation has failed; will be NULL if
440 * operation has executed successfully.
441 */
442static void
443dht_connected (void *cls,
444 struct GNUNET_TESTBED_Operation *op,
445 void *ca_result,
446 const char *emsg)
447{
448 struct ActiveContext *ac = cls;
449 struct Context *ctx = ac->ctx;
450
451 GNUNET_assert (NULL != ctx);
452 GNUNET_assert (NULL != ctx->op);
453 GNUNET_assert (ctx->op == op);
454 ac->dht = (struct GNUNET_DHT_Handle *) ca_result;
455 if (NULL != emsg)
456 {
457 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to DHT service failed: %s\n", emsg);
458 GNUNET_TESTBED_operation_done (ctx->op); /* Calls dht_disconnect() */
459 ctx->op = NULL;
460 return;
461 }
462 ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay, &delayed_put, ac);
463}
464
465
466/**
467 * Connect to DHT service and return the DHT client handler
468 *
469 * @param cls the active context
470 * @param cfg configuration of the peer to connect to; will be available until
471 * GNUNET_TESTBED_operation_done() is called on the operation returned
472 * from GNUNET_TESTBED_service_connect()
473 * @return service handle to return in 'op_result', NULL on error
474 */
475static void *
476dht_connect (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
477{
478 n_dht++;
479 return GNUNET_DHT_connect (cfg, 10);
480}
481
482
483/**
484 * Adapter function called to destroy a connection to
485 * a service.
486 *
487 * @param cls the active context
488 * @param op_result service handle returned from the connect adapter
489 */
490static void
491dht_disconnect (void *cls, void *op_result)
492{
493 struct ActiveContext *ac = cls;
494
495 GNUNET_assert (NULL != ac->dht);
496 GNUNET_assert (ac->dht == op_result);
497 GNUNET_DHT_disconnect (ac->dht);
498 n_dht--;
499 if (0 == n_dht)
500 GNUNET_SCHEDULER_shutdown ();
501}
502
503
504/**
505 * Callback called when DHT service on the peer is started
506 *
507 * @param cls the context
508 * @param op the operation that has been finished
509 * @param emsg error message in case the operation has failed; will be NULL if
510 * operation has executed successfully.
511 */
512static void
513service_started (void *cls,
514 struct GNUNET_TESTBED_Operation *op,
515 const char *emsg)
516{
517 struct Context *ctx = cls;
518
519 GNUNET_assert (NULL != ctx);
520 GNUNET_assert (NULL != ctx->op);
521 GNUNET_TESTBED_operation_done (ctx->op);
522 ctx->op = NULL;
523 if (NULL == ctx->ac)
524 return;
525 /* FIXME: connect to the DHT service and wait before starting a PUT */
526 ctx->op = GNUNET_TESTBED_service_connect (ctx, ctx->peer,
527 "dht",
528 &dht_connected, ctx->ac,
529 &dht_connect,
530 &dht_disconnect,
531 ctx->ac);
532}
533
534
535/**
536 * Signature of a main function for a testcase.
537 *
538 * @param cls closure
539 * @param h the run handle
540 * @param num_peers number of peers in 'peers'
541 * @param peers handle to peers run in the testbed
542 * @param links_succeeded the number of overlay link connection attempts that
543 * succeeded
544 * @param links_failed the number of overlay link
545 */
546static void
547test_run (void *cls,
548 struct GNUNET_TESTBED_RunHandle *h,
549 unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
550 unsigned int links_succeeded,
551 unsigned int links_failed)
552{
553 unsigned int cnt;
554 unsigned int ac_cnt;
555
556 if (NULL == peers)
557 {
558 /* exit */
559 GNUNET_assert (0);
560 }
561 INFO ("%u peers started\n", num_peers);
562 a_ctx = GNUNET_malloc (sizeof (struct Context) * num_peers);
563
564 /* select the peers which actively participate in profiling */
565 n_active = num_peers * PUT_PROBABILITY / 100;
566 if (0 == n_active)
567 {
568 GNUNET_SCHEDULER_shutdown ();
569 GNUNET_free (a_ctx);
570 return;
571 }
572 a_ac = GNUNET_malloc (n_active * sizeof (struct ActiveContext));
573 ac_cnt = 0;
574 for (cnt = 0; cnt < num_peers && ac_cnt < n_active; cnt++)
575 {
576 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100) >=
577 PUT_PROBABILITY)
578 continue;
579 a_ctx[cnt].ac = &a_ac[ac_cnt];
580 a_ac[ac_cnt].ctx = &a_ctx[cnt];
581 ac_cnt++;
582 }
583 n_active = ac_cnt;
584 a_ac = GNUNET_realloc (a_ac, n_active * sizeof (struct ActiveContext));
585 INFO ("Active peers: %u\n", n_active);
586
587 /* start DHT service on all peers */
588 for (cnt = 0; cnt < num_peers; cnt++)
589 {
590 a_ctx[cnt].peer = peers[cnt];
591 a_ctx[cnt].op = GNUNET_TESTBED_peer_manage_service (&a_ctx[cnt],
592 peers[cnt],
593 "dht",
594 &service_started,
595 &a_ctx[cnt],
596 1);
597 }
598}
599
600
601/**
602 * Main function that will be run by the scheduler.
603 *
604 * @param cls closure
605 * @param args remaining command-line arguments
606 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
607 * @param config configuration
608 */
609static void
610run (void *cls, char *const *args, const char *cfgfile,
611 const struct GNUNET_CONFIGURATION_Handle *config)
612{
613 uint64_t event_mask;
614
615 if (0 == num_peers)
616 {
617 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Exiting as the number of peers is %u\n"),
618 num_peers);
619 return;
620 }
621 cfg = GNUNET_CONFIGURATION_dup (config);
622 event_mask = 0;
623 GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, NULL,
624 NULL, &test_run, NULL);
625 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
626 NULL);
627}
628
629
630/**
631 * Main function.
632 *
633 * @return 0 on success
634 */
635int
636main (int argc, char *const *argv)
637{
638 int rc;
639
640 static struct GNUNET_GETOPT_CommandLineOption options[] = {
641 {'n', "peers", "COUNT",
642 gettext_noop ("number of peers to start"),
643 1, &GNUNET_GETOPT_set_uint, &num_peers},
644 {'H', "hosts", "FILENAME",
645 gettext_noop ("name of the file with the login information for the testbed"),
646 1, &GNUNET_GETOPT_set_string, &hosts_file},
647 {'d', "delay", "DELAY",
648 gettext_noop ("delay for starting DHT PUT and GET"),
649 1, &GNUNET_GETOPT_set_relative_time, &delay},
650 {'t', "timeout", "TIMEOUT",
651 gettext_noop ("timeout for DHT PUT and GET requests"),
652 1, &GNUNET_GETOPT_set_relative_time, &timeout},
653 GNUNET_GETOPT_OPTION_END
654 };
655
656 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
657 return 2;
658 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3); /* default delay */
659 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3); /* default timeout */
660 rc = 0;
661 if (GNUNET_OK !=
662 GNUNET_PROGRAM_run (argc, argv, "dht-profiler",
663 gettext_noop
664 ("Measure quality and performance of the DHT service."),
665 options, &run, NULL))
666 rc = 1;
667 return rc;
668}