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