glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / fs / perf_gnunet_service_fs_p2p.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010, 2012 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
16 /**
17  * @file fs/perf_gnunet_service_fs_p2p.c
18  * @brief profile P2P routing using simple publish + download operation
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "fs_test_lib.h"
23 #include "gnunet_testbed_service.h"
24
25 #define VERBOSE GNUNET_NO
26
27 /**
28  * File-size we use for testing.
29  */
30 #define FILESIZE (1024 * 1024 * 10)
31
32 /**
33  * How long until we give up on transmitting the message?
34  */
35 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
36
37 #define NUM_DAEMONS 2
38
39 #define SEED 42
40
41 static struct GNUNET_TESTBED_Peer *daemons[NUM_DAEMONS];
42
43 static int ok;
44
45 static struct GNUNET_TIME_Absolute start_time;
46
47 static const char *progname;
48
49 static struct GNUNET_TIME_Absolute start_time;
50
51
52 /**
53  * Master context for 'stat_run'.
54  */
55 struct StatMaster
56 {
57   struct GNUNET_STATISTICS_Handle *stat;
58   struct GNUNET_TESTBED_Operation *op;
59   unsigned int daemon;
60   unsigned int value;
61 };
62
63 struct StatValues
64 {
65   const char *subsystem;
66   const char *name;
67 };
68
69 /**
70  * Statistics we print out.
71  */
72 static struct StatValues stats[] = {
73   {"fs", "# queries forwarded"},
74   {"fs", "# replies received and matched"},
75   {"fs", "# results found locally"},
76   {"fs", "# requests forwarded due to high load"},
77   {"fs", "# requests done for free (low load)"},
78   {"fs", "# requests dropped, priority insufficient"},
79   {"fs", "# requests done for a price (normal load)"},
80   {"fs", "# requests dropped by datastore (queue length limit)"},
81   {"fs", "# P2P searches received"},
82   {"fs", "# P2P searches discarded (queue length bound)"},
83   {"fs", "# replies received for local clients"},
84   {"fs", "# queries retransmitted to same target"},
85   {"core", "# bytes decrypted"},
86   {"core", "# bytes encrypted"},
87   {"core", "# discarded CORE_SEND requests"},
88   {"core", "# discarded CORE_SEND request bytes"},
89   {"core", "# discarded lower priority CORE_SEND requests"},
90   {"core", "# discarded lower priority CORE_SEND request bytes"},
91   {"transport", "# bytes received via TCP"},
92   {"transport", "# bytes transmitted via TCP"},
93   {"datacache", "# bytes stored"},
94   {NULL, NULL}
95 };
96
97
98 /**
99  * Callback function to process statistic values.
100  *
101  * @param cls closure
102  * @param subsystem name of subsystem that created the statistic
103  * @param name the name of the datum
104  * @param value the current value
105  * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
106  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
107  */
108 static int
109 print_stat (void *cls, const char *subsystem, const char *name, uint64_t value,
110             int is_persistent)
111 {
112   struct StatMaster *sm = cls;
113
114   FPRINTF (stderr,
115            "Peer %2u: %12s/%50s = %12llu\n",
116            sm->daemon,
117            subsystem,
118            name,
119            (unsigned long long) value);
120   return GNUNET_OK;
121 }
122
123
124 /**
125  * Function that gathers stats from all daemons.
126  */
127 static void
128 stat_run (void *cls,
129           struct GNUNET_TESTBED_Operation *op,
130           void *ca_result,
131           const char *emsg);
132
133
134 /**
135  * Function called when GET operation on stats is done.
136  */
137 static void
138 get_done (void *cls, int success)
139 {
140   struct StatMaster *sm = cls;
141
142   GNUNET_break (GNUNET_OK == success);
143   sm->value++;
144   stat_run (sm, sm->op, sm->stat, NULL);
145 }
146
147
148 /**
149  * Adapter function called to establish a connection to
150  * statistics service.
151  *
152  * @param cls closure
153  * @param cfg configuration of the peer to connect to; will be available until
154  *          GNUNET_TESTBED_operation_done() is called on the operation returned
155  *          from GNUNET_TESTBED_service_connect()
156  * @return service handle to return in 'op_result', NULL on error
157  */
158 static void *
159 statistics_connect_adapter (void *cls,
160                             const struct GNUNET_CONFIGURATION_Handle *cfg)
161 {
162   return GNUNET_STATISTICS_create ("<driver>",
163                                    cfg);
164 }
165
166
167 /**
168  * Adapter function called to destroy a connection to
169  * statistics service.
170  *
171  * @param cls closure
172  * @param op_result service handle returned from the connect adapter
173  */
174 static void
175 statistics_disconnect_adapter (void *cls,
176                                void *op_result)
177 {
178   GNUNET_STATISTICS_destroy (op_result, GNUNET_NO);
179 }
180
181
182 /**
183  * Function that gathers stats from all daemons.
184  */
185 static void
186 stat_run (void *cls,
187           struct GNUNET_TESTBED_Operation *op,
188           void *ca_result,
189           const char *emsg)
190 {
191   struct StatMaster *sm = cls;
192
193   if (NULL != emsg)
194     {
195       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
196                   "Failed to statistics service: %s\n",
197                   emsg);
198       GNUNET_SCHEDULER_shutdown ();
199       return;
200     }
201   sm->stat = ca_result;
202
203   if (stats[sm->value].name != NULL)
204   {
205     GNUNET_STATISTICS_get (sm->stat,
206 #if 0
207                            NULL, NULL,
208 #else
209                            stats[sm->value].subsystem, stats[sm->value].name,
210 #endif
211                            &get_done, &print_stat,
212                            sm);
213     return;
214   }
215   GNUNET_TESTBED_operation_done (sm->op);
216   sm->value = 0;
217   sm->daemon++;
218   if (NUM_DAEMONS == sm->daemon)
219   {
220     GNUNET_free (sm);
221     GNUNET_SCHEDULER_shutdown ();
222     return;
223   }
224   sm->op =
225     GNUNET_TESTBED_service_connect (NULL,
226                                     daemons[sm->daemon],
227                                     "statistics",
228                                     &stat_run, sm,
229                                     &statistics_connect_adapter,
230                                     &statistics_disconnect_adapter,
231                                     NULL);
232 }
233
234
235 static void
236 do_report (void *cls)
237 {
238   char *fn = cls;
239   struct GNUNET_TIME_Relative del;
240   char *fancy;
241   struct StatMaster *sm;
242
243   if (NULL != fn)
244   {
245     GNUNET_DISK_directory_remove (fn);
246     GNUNET_free (fn);
247   }
248   if (0 ==
249       GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_add (start_time,
250                                                                     TIMEOUT)).rel_value_us)
251   {
252     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
253                 "Timeout during download, shutting down with error\n");
254     ok = 1;
255     GNUNET_SCHEDULER_shutdown ();
256     return;
257   }
258
259   del = GNUNET_TIME_absolute_get_duration (start_time);
260   if (del.rel_value_us == 0)
261     del.rel_value_us = 1;
262   fancy =
263     GNUNET_STRINGS_byte_size_fancy (((unsigned long long) FILESIZE) *
264                                     1000000LL / del.rel_value_us);
265   FPRINTF (stdout,
266            "Download speed was %s/s\n",
267            fancy);
268   GNUNET_free (fancy);
269   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
270               "Finished download, shutting down\n");
271   sm = GNUNET_new (struct StatMaster);
272   sm->op =
273     GNUNET_TESTBED_service_connect (NULL,
274                                     daemons[sm->daemon],
275                                     "statistics",
276                                     &stat_run, sm,
277                                     &statistics_connect_adapter,
278                                     &statistics_disconnect_adapter,
279                                     NULL);
280 }
281
282
283 static void
284 do_download (void *cls,
285              const struct GNUNET_FS_Uri *uri,
286              const char *fn)
287 {
288   int anonymity;
289
290   if (NULL == uri)
291   {
292     GNUNET_SCHEDULER_shutdown ();
293     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
294                 "Timeout during upload attempt, shutting down with error\n");
295     ok = 1;
296     return;
297   }
298   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n",
299               (unsigned long long) FILESIZE);
300   start_time = GNUNET_TIME_absolute_get ();
301   if (NULL != strstr (progname, "dht"))
302     anonymity = 0;
303   else
304     anonymity = 1;
305   start_time = GNUNET_TIME_absolute_get ();
306   GNUNET_FS_TEST_download (daemons[0],
307                            TIMEOUT,
308                            anonymity,
309                            SEED,
310                            uri,
311                            VERBOSE,
312                            &do_report,
313                            (NULL == fn) ? NULL : GNUNET_strdup (fn));
314 }
315
316
317 static void
318 do_publish (void *cls,
319             struct GNUNET_TESTBED_RunHandle *h,
320             unsigned int num_peers,
321             struct GNUNET_TESTBED_Peer **peers,
322             unsigned int links_succeeded,
323             unsigned int links_failed)
324 {
325   unsigned int i;
326   int do_index;
327   int anonymity;
328
329   GNUNET_assert (NUM_DAEMONS == num_peers);
330   for (i=0;i<num_peers;i++)
331     daemons[i] = peers[i];
332   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing %llu bytes\n",
333               (unsigned long long) FILESIZE);
334   if (NULL != strstr (progname, "index"))
335     do_index = GNUNET_YES;
336   else
337     do_index = GNUNET_NO;
338   if (NULL != strstr (progname, "dht"))
339     anonymity = 0;
340   else
341     anonymity = 1;
342   GNUNET_FS_TEST_publish (daemons[NUM_DAEMONS - 1], TIMEOUT, anonymity,
343                           do_index, FILESIZE, SEED, VERBOSE, &do_download,
344                           NULL);
345 }
346
347
348 int
349 main (int argc, char *argv[])
350 {
351   progname = argv[0];
352   (void) GNUNET_TESTBED_test_run ("perf-gnunet-service-fs-p2p",
353                                   "perf_gnunet_service_fs_p2p.conf",
354                                   NUM_DAEMONS,
355                                   0, NULL, NULL,
356                                   &do_publish, NULL);
357   GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-lib/");
358   return ok;
359 }
360
361 /* end of perf_gnunet_service_fs_p2p.c */