tighten formatting rules
[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)).
256       rel_value_us)
257   {
258     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
259                 "Timeout during download, shutting down with error\n");
260     ok = 1;
261     GNUNET_SCHEDULER_shutdown ();
262     return;
263   }
264
265   del = GNUNET_TIME_absolute_get_duration (start_time);
266   if (del.rel_value_us == 0)
267     del.rel_value_us = 1;
268   fancy =
269     GNUNET_STRINGS_byte_size_fancy (((unsigned long long) FILESIZE)
270                                     * 1000000LL / del.rel_value_us);
271   fprintf (stdout,
272            "Download speed was %s/s\n",
273            fancy);
274   GNUNET_free (fancy);
275   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
276               "Finished download, shutting down\n");
277   sm = GNUNET_new (struct StatMaster);
278   sm->op =
279     GNUNET_TESTBED_service_connect (NULL,
280                                     daemons[sm->daemon],
281                                     "statistics",
282                                     &stat_run, sm,
283                                     &statistics_connect_adapter,
284                                     &statistics_disconnect_adapter,
285                                     NULL);
286 }
287
288
289 static void
290 do_download (void *cls,
291              const struct GNUNET_FS_Uri *uri,
292              const char *fn)
293 {
294   int anonymity;
295
296   if (NULL == uri)
297   {
298     GNUNET_SCHEDULER_shutdown ();
299     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
300                 "Timeout during upload attempt, shutting down with error\n");
301     ok = 1;
302     return;
303   }
304   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n",
305               (unsigned long long) FILESIZE);
306   start_time = GNUNET_TIME_absolute_get ();
307   if (NULL != strstr (progname, "dht"))
308     anonymity = 0;
309   else
310     anonymity = 1;
311   start_time = GNUNET_TIME_absolute_get ();
312   GNUNET_FS_TEST_download (daemons[0],
313                            TIMEOUT,
314                            anonymity,
315                            SEED,
316                            uri,
317                            VERBOSE,
318                            &do_report,
319                            (NULL == fn) ? NULL : GNUNET_strdup (fn));
320 }
321
322
323 static void
324 do_publish (void *cls,
325             struct GNUNET_TESTBED_RunHandle *h,
326             unsigned int num_peers,
327             struct GNUNET_TESTBED_Peer **peers,
328             unsigned int links_succeeded,
329             unsigned int links_failed)
330 {
331   unsigned int i;
332   int do_index;
333   int anonymity;
334
335   GNUNET_assert (NUM_DAEMONS == num_peers);
336   for (i = 0; i < num_peers; i++)
337     daemons[i] = peers[i];
338   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing %llu bytes\n",
339               (unsigned long long) FILESIZE);
340   if (NULL != strstr (progname, "index"))
341     do_index = GNUNET_YES;
342   else
343     do_index = GNUNET_NO;
344   if (NULL != strstr (progname, "dht"))
345     anonymity = 0;
346   else
347     anonymity = 1;
348   GNUNET_FS_TEST_publish (daemons[NUM_DAEMONS - 1], TIMEOUT, anonymity,
349                           do_index, FILESIZE, SEED, VERBOSE, &do_download,
350                           NULL);
351 }
352
353
354 int
355 main (int argc, char *argv[])
356 {
357   progname = argv[0];
358   (void) GNUNET_TESTBED_test_run ("perf-gnunet-service-fs-p2p",
359                                   "perf_gnunet_service_fs_p2p.conf",
360                                   NUM_DAEMONS,
361                                   0, NULL, NULL,
362                                   &do_publish, NULL);
363   GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-lib/");
364   return ok;
365 }
366
367
368 /* end of perf_gnunet_service_fs_p2p.c */