diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dht/gnunet-service-xdht_neighbours.c | 39 | ||||
-rw-r--r-- | src/dht/gnunet_dht_profiler.c | 19 | ||||
-rw-r--r-- | src/dht/gnunet_dht_r5n_profiler.c | 668 |
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, ¤t_successor->finger_identity, sizeof(uint64_t)); | 5011 | memcpy(&succ, ¤t_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; | |||
373 | static void | 373 | static void |
374 | collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 374 | collect_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 | */ | ||
46 | static struct GNUNET_CONFIGURATION_Handle *cfg; | ||
47 | |||
48 | /** | ||
49 | * Name of the file with the hosts to run the test over | ||
50 | */ | ||
51 | static char *hosts_file; | ||
52 | |||
53 | /** | ||
54 | * Context for a peer which actively does DHT PUT/GET | ||
55 | */ | ||
56 | struct ActiveContext; | ||
57 | |||
58 | /** | ||
59 | * Context to hold data of peer | ||
60 | */ | ||
61 | struct 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 | */ | ||
84 | struct 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 | */ | ||
141 | static struct Context *a_ctx; | ||
142 | |||
143 | /** | ||
144 | * Array of active peers | ||
145 | */ | ||
146 | static struct ActiveContext *a_ac; | ||
147 | |||
148 | /** | ||
149 | * The delay between starting to do PUTS and GETS | ||
150 | */ | ||
151 | static struct GNUNET_TIME_Relative delay; | ||
152 | |||
153 | /** | ||
154 | * The timeout for GET and PUT | ||
155 | */ | ||
156 | static struct GNUNET_TIME_Relative timeout; | ||
157 | |||
158 | /** | ||
159 | * Number of peers | ||
160 | */ | ||
161 | static unsigned int num_peers; | ||
162 | |||
163 | /** | ||
164 | * Number of active peers | ||
165 | */ | ||
166 | static unsigned int n_active; | ||
167 | |||
168 | /** | ||
169 | * Number of DHT service connections we currently have | ||
170 | */ | ||
171 | static unsigned int n_dht; | ||
172 | |||
173 | /** | ||
174 | * Number of DHT PUTs made | ||
175 | */ | ||
176 | static unsigned int n_puts; | ||
177 | |||
178 | /** | ||
179 | * Number of DHT PUTs succeeded | ||
180 | */ | ||
181 | static unsigned int n_puts_ok; | ||
182 | |||
183 | /** | ||
184 | * Number of DHT PUTs failed | ||
185 | */ | ||
186 | static unsigned int n_puts_fail; | ||
187 | |||
188 | /** | ||
189 | * Number of DHT GETs made | ||
190 | */ | ||
191 | static unsigned int n_gets; | ||
192 | |||
193 | /** | ||
194 | * Number of DHT GETs succeeded | ||
195 | */ | ||
196 | static unsigned int n_gets_ok; | ||
197 | |||
198 | /** | ||
199 | * Number of DHT GETs succeeded | ||
200 | */ | ||
201 | static 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 | */ | ||
210 | static void | ||
211 | do_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 | |||
243 | static void | ||
244 | summarize () | ||
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 | */ | ||
262 | static void | ||
263 | cancel_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 | */ | ||
296 | static void | ||
297 | get_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 | */ | ||
342 | static void | ||
343 | delayed_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 | */ | ||
385 | static void | ||
386 | put_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 | */ | ||
405 | static void | ||
406 | delayed_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 | */ | ||
442 | static void | ||
443 | dht_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 | */ | ||
475 | static void * | ||
476 | dht_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 | */ | ||
490 | static void | ||
491 | dht_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 | */ | ||
512 | static void | ||
513 | service_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 | */ | ||
546 | static void | ||
547 | test_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 | */ | ||
609 | static void | ||
610 | run (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 | */ | ||
635 | int | ||
636 | main (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 | } | ||