aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-daemon-fsprofiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/gnunet-daemon-fsprofiler.c')
-rw-r--r--src/fs/gnunet-daemon-fsprofiler.c672
1 files changed, 0 insertions, 672 deletions
diff --git a/src/fs/gnunet-daemon-fsprofiler.c b/src/fs/gnunet-daemon-fsprofiler.c
deleted file mode 100644
index fbb7c6028..000000000
--- a/src/fs/gnunet-daemon-fsprofiler.c
+++ /dev/null
@@ -1,672 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 Christian Grothoff
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/gnunet-daemon-fsprofiler.c
23 * @brief daemon that publishes and downloads (random) files
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - how to signal driver that we're done?
28 */
29#include "platform.h"
30#include "gnunet_fs_service.h"
31#include "gnunet_statistics_service.h"
32
33/**
34 * We use 'patterns' of the form (x,y,t) to specify desired download/publish
35 * activities of a peer. They are stored in a DLL.
36 */
37struct Pattern
38{
39 /**
40 * Kept in a DLL.
41 */
42 struct Pattern *next;
43
44 /**
45 * Kept in a DLL.
46 */
47 struct Pattern *prev;
48
49 /**
50 * Execution context for the pattern (FS-handle to the operation).
51 */
52 void *ctx;
53
54 /**
55 * Secondary execution context for the pattern (FS-handle to the operation).
56 */
57 void *sctx;
58
59 /**
60 * When did the operation start?
61 */
62 struct GNUNET_TIME_Absolute start_time;
63
64 /**
65 * With how much delay should this operation be started?
66 */
67 struct GNUNET_TIME_Relative delay;
68
69 /**
70 * Task to run the operation.
71 */
72 struct GNUNET_SCHEDULER_Task *task;
73
74 /**
75 * Secondary task to run the operation.
76 */
77 struct GNUNET_SCHEDULER_Task *stask;
78
79 /**
80 * X-value.
81 */
82 unsigned long long x;
83
84 /**
85 * Y-value.
86 */
87 unsigned long long y;
88};
89
90
91/**
92 * Return value from 'main'.
93 */
94static int global_ret;
95
96/**
97 * Configuration we use.
98 */
99static const struct GNUNET_CONFIGURATION_Handle *cfg;
100
101/**
102 * Handle to the statistics service.
103 */
104static struct GNUNET_STATISTICS_Handle *stats_handle;
105
106/**
107 * Peer's FS handle.
108 */
109static struct GNUNET_FS_Handle *fs_handle;
110
111/**
112 * Unique number for this peer in the testbed.
113 */
114static unsigned long long my_peerid;
115
116/**
117 * Desired anonymity level.
118 */
119static unsigned long long anonymity_level;
120
121/**
122 * Desired replication level.
123 */
124static unsigned long long replication_level;
125
126/**
127 * String describing which publishing operations this peer should
128 * perform. The format is "(SIZE,SEED,TIME)*", for example:
129 * "(1,5,0)(7,3,13)" means to publish a file with 1 byte and
130 * seed/keyword 5 immediately and another file with 7 bytes and
131 * seed/keyword 3 after 13 ms.
132 */
133static char *publish_pattern;
134
135/**
136 * Head of the DLL of publish patterns.
137 */
138static struct Pattern *publish_head;
139
140/**
141 * Tail of the DLL of publish patterns.
142 */
143static struct Pattern *publish_tail;
144
145/**
146 * String describing which download operations this peer should
147 * perform. The format is "(KEYWORD,SIZE,DELAY)*"; for example,
148 * "(1,7,3)(3,8,8)" means to download one file of 7 bytes under
149 * keyword "1" starting the search after 3 ms; and another one of 8
150 * bytes under keyword '3' starting after 8 ms. The file size is
151 * used to determine which search result(s) should be used or ignored.
152 */
153static char *download_pattern;
154
155/**
156 * Head of the DLL of publish patterns.
157 */
158static struct Pattern *download_head;
159
160/**
161 * Tail of the DLL of publish patterns.
162 */
163static struct Pattern *download_tail;
164
165
166/**
167 * Parse a pattern string and store the corresponding
168 * 'struct Pattern' in the given head/tail.
169 *
170 * @param head where to store the head
171 * @param tail where to store the tail
172 * @param pattern pattern to parse
173 * @return GNUNET_OK on success
174 */
175static int
176parse_pattern (struct Pattern **head,
177 struct Pattern **tail,
178 const char *pattern)
179{
180 struct Pattern *p;
181 unsigned long long x;
182 unsigned long long y;
183 unsigned long long t;
184
185 while (3 == sscanf (pattern,
186 "(%llu,%llu,%llu)",
187 &x, &y, &t))
188 {
189 p = GNUNET_new (struct Pattern);
190 p->x = x;
191 p->y = y;
192 p->delay.rel_value_us = (uint64_t) t;
193 GNUNET_CONTAINER_DLL_insert (*head, *tail, p);
194 pattern = strstr (pattern, ")");
195 GNUNET_assert (NULL != pattern);
196 pattern++;
197 }
198 return (0 == strlen (pattern)) ? GNUNET_OK : GNUNET_SYSERR;
199}
200
201
202/**
203 * Create a KSK URI from a number.
204 *
205 * @param kval the number
206 * @return corresponding KSK URI
207 */
208static struct GNUNET_FS_Uri *
209make_keywords (uint64_t kval)
210{
211 char kw[128];
212
213 GNUNET_snprintf (kw, sizeof(kw),
214 "%llu", (unsigned long long) kval);
215 return GNUNET_FS_uri_ksk_create (kw, NULL);
216}
217
218
219/**
220 * Create a file of the given length with a deterministic amount
221 * of data to be published under keyword 'kval'.
222 *
223 * @param length number of bytes in the file
224 * @param kval keyword value and seed for the data of the file
225 * @param ctx context to pass to 'fi'
226 * @return file information handle for the file
227 */
228static struct GNUNET_FS_FileInformation *
229make_file (uint64_t length,
230 uint64_t kval,
231 void *ctx)
232{
233 struct GNUNET_FS_FileInformation *fi;
234 struct GNUNET_FS_BlockOptions bo;
235 char *data;
236 struct GNUNET_FS_Uri *keywords;
237 unsigned long long i;
238 uint64_t xor;
239
240 data = NULL; /* to make compilers happy */
241 if ((0 != length) &&
242 (NULL == (data = GNUNET_malloc_large ((size_t) length))))
243 return NULL;
244 /* initialize data with 'unique' data only depending on 'kval' and 'size',
245 making sure that blocks do not repeat */
246 for (i = 0; i < length; i += 8)
247 {
248 xor = length ^ kval ^ (uint64_t) (i / 32 / 1024);
249 GNUNET_memcpy (&data[i], &xor, GNUNET_MIN (length - i, sizeof(uint64_t)));
250 }
251 bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
252 bo.anonymity_level = (uint32_t) anonymity_level;
253 bo.content_priority = 128;
254 bo.replication_level = (uint32_t) replication_level;
255 keywords = make_keywords (kval);
256 fi = GNUNET_FS_file_information_create_from_data (fs_handle,
257 ctx,
258 length,
259 data, keywords,
260 NULL, GNUNET_NO, &bo);
261 GNUNET_FS_uri_destroy (keywords);
262 return fi;
263}
264
265
266/**
267 * Task run during shutdown.
268 *
269 * @param cls unused
270 */
271static void
272shutdown_task (void *cls)
273{
274 struct Pattern *p;
275
276 while (NULL != (p = publish_head))
277 {
278 if (NULL != p->task)
279 GNUNET_SCHEDULER_cancel (p->task);
280 if (NULL != p->ctx)
281 GNUNET_FS_publish_stop (p->ctx);
282 GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p);
283 GNUNET_free (p);
284 }
285 while (NULL != (p = download_head))
286 {
287 if (NULL != p->task)
288 GNUNET_SCHEDULER_cancel (p->task);
289 if (NULL != p->stask)
290 GNUNET_SCHEDULER_cancel (p->stask);
291 if (NULL != p->ctx)
292 GNUNET_FS_download_stop (p->ctx, GNUNET_YES);
293 if (NULL != p->sctx)
294 GNUNET_FS_search_stop (p->sctx);
295 GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p);
296 GNUNET_free (p);
297 }
298 if (NULL != fs_handle)
299 {
300 GNUNET_FS_stop (fs_handle);
301 fs_handle = NULL;
302 }
303 if (NULL != stats_handle)
304 {
305 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_YES);
306 stats_handle = NULL;
307 }
308}
309
310
311/**
312 * Task run when a publish operation should be stopped.
313 *
314 * @param cls the 'struct Pattern' of the publish operation to stop
315 */
316static void
317publish_stop_task (void *cls)
318{
319 struct Pattern *p = cls;
320
321 p->task = NULL;
322 GNUNET_FS_publish_stop (p->ctx);
323}
324
325
326/**
327 * Task run when a download operation should be stopped.
328 *
329 * @param cls the 'struct Pattern' of the download operation to stop
330 */
331static void
332download_stop_task (void *cls)
333{
334 struct Pattern *p = cls;
335
336 p->task = NULL;
337 GNUNET_FS_download_stop (p->ctx, GNUNET_YES);
338}
339
340
341/**
342 * Task run when a download operation should be stopped.
343 *
344 * @param cls the 'struct Pattern' of the download operation to stop
345 */
346static void
347search_stop_task (void *cls)
348{
349 struct Pattern *p = cls;
350
351 p->stask = NULL;
352 GNUNET_FS_search_stop (p->sctx);
353}
354
355
356/**
357 * Notification of FS to a client about the progress of an
358 * operation. Callbacks of this type will be used for uploads,
359 * downloads and searches. Some of the arguments depend a bit
360 * in their meaning on the context in which the callback is used.
361 *
362 * @param cls closure
363 * @param info details about the event, specifying the event type
364 * and various bits about the event
365 * @return client-context (for the next progress call
366 * for this operation; should be set to NULL for
367 * SUSPEND and STOPPED events). The value returned
368 * will be passed to future callbacks in the respective
369 * field in the GNUNET_FS_ProgressInfo struct.
370 */
371static void *
372progress_cb (void *cls,
373 const struct GNUNET_FS_ProgressInfo *info)
374{
375 struct Pattern *p;
376 const struct GNUNET_FS_Uri *uri;
377
378 switch (info->status)
379 {
380 case GNUNET_FS_STATUS_PUBLISH_START:
381 case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
382 p = info->value.publish.cctx;
383 return p;
384
385 case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY:
386 p = info->value.publish.cctx;
387 return p;
388
389 case GNUNET_FS_STATUS_PUBLISH_ERROR:
390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
391 "Publishing failed\n");
392 GNUNET_STATISTICS_update (stats_handle,
393 "# failed publish operations", 1, GNUNET_NO);
394 p = info->value.publish.cctx;
395 p->task = GNUNET_SCHEDULER_add_now (&publish_stop_task, p);
396 return p;
397
398 case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
399 p = info->value.publish.cctx;
400 GNUNET_STATISTICS_update (stats_handle,
401 "# publishing time (ms)",
402 (long long) GNUNET_TIME_absolute_get_duration (
403 p->start_time).rel_value_us / 1000LL,
404 GNUNET_NO);
405 p->task = GNUNET_SCHEDULER_add_now (&publish_stop_task, p);
406 return p;
407
408 case GNUNET_FS_STATUS_PUBLISH_STOPPED:
409 p = info->value.publish.cctx;
410 p->ctx = NULL;
411 GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p);
412 GNUNET_free (p);
413 return NULL;
414
415 case GNUNET_FS_STATUS_DOWNLOAD_START:
416 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
417 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
418 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
419 p = info->value.download.cctx;
420 return p;
421
422 case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 "Download failed\n");
425 GNUNET_STATISTICS_update (stats_handle,
426 "# failed downloads", 1, GNUNET_NO);
427 p = info->value.download.cctx;
428 p->task = GNUNET_SCHEDULER_add_now (&download_stop_task, p);
429 return p;
430
431 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
432 p = info->value.download.cctx;
433 GNUNET_STATISTICS_update (stats_handle,
434 "# download time (ms)",
435 (long long) GNUNET_TIME_absolute_get_duration (
436 p->start_time).rel_value_us / 1000LL,
437 GNUNET_NO);
438 p->task = GNUNET_SCHEDULER_add_now (&download_stop_task, p);
439 return p;
440
441 case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
442 p = info->value.download.cctx;
443 p->ctx = NULL;
444 if (NULL == p->sctx)
445 {
446 GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p);
447 GNUNET_free (p);
448 }
449 return NULL;
450
451 case GNUNET_FS_STATUS_SEARCH_START:
452 case GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE:
453 p = info->value.search.cctx;
454 return p;
455
456 case GNUNET_FS_STATUS_SEARCH_RESULT:
457 p = info->value.search.cctx;
458 uri = info->value.search.specifics.result.uri;
459 if (GNUNET_YES != GNUNET_FS_uri_test_chk (uri))
460 return NULL; /* not what we want */
461 if (p->y != GNUNET_FS_uri_chk_get_file_size (uri))
462 return NULL; /* not what we want */
463 GNUNET_STATISTICS_update (stats_handle,
464 "# search time (ms)",
465 (long long) GNUNET_TIME_absolute_get_duration (
466 p->start_time).rel_value_us / 1000LL,
467 GNUNET_NO);
468 p->start_time = GNUNET_TIME_absolute_get ();
469 p->ctx = GNUNET_FS_download_start (fs_handle, uri,
470 NULL, NULL, NULL,
471 0, GNUNET_FS_uri_chk_get_file_size (uri),
472 anonymity_level,
473 GNUNET_FS_DOWNLOAD_NO_TEMPORARIES,
474 p,
475 NULL);
476 p->stask = GNUNET_SCHEDULER_add_now (&search_stop_task, p);
477 return NULL;
478
479 case GNUNET_FS_STATUS_SEARCH_UPDATE:
480 case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
481 return NULL; /* don't care */
482
483 case GNUNET_FS_STATUS_SEARCH_ERROR:
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Search failed\n");
486 GNUNET_STATISTICS_update (stats_handle,
487 "# failed searches", 1, GNUNET_NO);
488 p = info->value.search.cctx;
489 p->stask = GNUNET_SCHEDULER_add_now (&search_stop_task, p);
490 return p;
491
492 case GNUNET_FS_STATUS_SEARCH_STOPPED:
493 p = info->value.search.cctx;
494 p->sctx = NULL;
495 if (NULL == p->ctx)
496 {
497 GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p);
498 GNUNET_free (p);
499 }
500 return NULL;
501
502 default:
503 /* unexpected event during profiling */
504 GNUNET_break (0);
505 return NULL;
506 }
507}
508
509
510/**
511 * Start publish operation.
512 *
513 * @param cls the 'struct Pattern' specifying the operation to perform
514 */
515static void
516start_publish (void *cls)
517{
518 struct Pattern *p = cls;
519 struct GNUNET_FS_FileInformation *fi;
520
521 p->task = NULL;
522 fi = make_file (p->x, p->y, p);
523 p->start_time = GNUNET_TIME_absolute_get ();
524 p->ctx = GNUNET_FS_publish_start (fs_handle,
525 fi,
526 NULL, NULL, NULL,
527 GNUNET_FS_PUBLISH_OPTION_NONE);
528}
529
530
531/**
532 * Start download operation.
533 *
534 * @param cls the 'struct Pattern' specifying the operation to perform
535 */
536static void
537start_download (void *cls)
538{
539 struct Pattern *p = cls;
540 struct GNUNET_FS_Uri *keywords;
541
542 p->task = NULL;
543 keywords = make_keywords (p->x);
544 p->start_time = GNUNET_TIME_absolute_get ();
545 p->sctx = GNUNET_FS_search_start (fs_handle, keywords,
546 anonymity_level,
547 GNUNET_FS_SEARCH_OPTION_NONE,
548 p);
549}
550
551
552/**
553 * @brief Main function that will be run by the scheduler.
554 *
555 * @param cls closure
556 * @param args remaining command-line arguments
557 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
558 * @param cfg_ configuration
559 */
560static void
561run (void *cls, char *const *args GNUNET_UNUSED,
562 const char *cfgfile GNUNET_UNUSED,
563 const struct GNUNET_CONFIGURATION_Handle *cfg_)
564{
565 char myoptname[128];
566 struct Pattern *p;
567
568 cfg = cfg_;
569 /* Scheduled the task to clean up when shutdown is called */
570 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
571 NULL);
572
573 if (GNUNET_OK !=
574 GNUNET_CONFIGURATION_get_value_number (cfg,
575 "TESTBED", "PEERID",
576 &my_peerid))
577 {
578 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
579 "TESTBED", "PEERID");
580 global_ret = GNUNET_SYSERR;
581 GNUNET_SCHEDULER_shutdown ();
582 return;
583 }
584 if (GNUNET_OK !=
585 GNUNET_CONFIGURATION_get_value_number (cfg,
586 "FSPROFILER", "ANONYMITY_LEVEL",
587 &anonymity_level))
588 anonymity_level = 1;
589 if (GNUNET_OK !=
590 GNUNET_CONFIGURATION_get_value_number (cfg,
591 "FSPROFILER", "REPLICATION_LEVEL",
592 &replication_level))
593 replication_level = 1;
594 GNUNET_snprintf (myoptname, sizeof(myoptname),
595 "DOWNLOAD-PATTERN-%llu", my_peerid);
596 if (GNUNET_OK !=
597 GNUNET_CONFIGURATION_get_value_string (cfg,
598 "FSPROFILER", myoptname,
599 &download_pattern))
600 download_pattern = GNUNET_strdup ("");
601 GNUNET_snprintf (myoptname, sizeof(myoptname),
602 "PUBLISH-PATTERN-%llu", my_peerid);
603 if (GNUNET_OK !=
604 GNUNET_CONFIGURATION_get_value_string (cfg,
605 "FSPROFILER", myoptname,
606 &publish_pattern))
607 publish_pattern = GNUNET_strdup ("");
608 if ((GNUNET_OK !=
609 parse_pattern (&download_head,
610 &download_tail,
611 download_pattern)) ||
612 (GNUNET_OK !=
613 parse_pattern (&publish_head,
614 &publish_tail,
615 publish_pattern)))
616 {
617 GNUNET_SCHEDULER_shutdown ();
618 return;
619 }
620
621 stats_handle = GNUNET_STATISTICS_create ("fsprofiler", cfg);
622 fs_handle =
623 GNUNET_FS_start (cfg,
624 "fsprofiler",
625 &progress_cb, NULL,
626 GNUNET_FS_FLAGS_NONE,
627 GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, 1,
628 GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, 1,
629 GNUNET_FS_OPTIONS_END);
630 if (NULL == fs_handle)
631 {
632 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
633 "Could not acquire FS handle. Exiting.\n");
634 global_ret = GNUNET_SYSERR;
635 GNUNET_SCHEDULER_shutdown ();
636 return;
637 }
638 for (p = publish_head; NULL != p; p = p->next)
639 p->task = GNUNET_SCHEDULER_add_delayed (p->delay,
640 &start_publish, p);
641 for (p = download_head; NULL != p; p = p->next)
642 p->task = GNUNET_SCHEDULER_add_delayed (p->delay,
643 &start_download, p);
644}
645
646
647/**
648 * Program that performs various "random" FS activities.
649 *
650 * @param argc number of arguments from the command line
651 * @param argv command line arguments
652 * @return 0 ok, 1 on error
653 */
654int
655main (int argc, char *const *argv)
656{
657 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
658 GNUNET_GETOPT_OPTION_END
659 };
660
661 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
662 return 2;
663 return (GNUNET_OK ==
664 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-fsprofiler",
665 gettext_noop
666 (
667 "Daemon to use file-sharing to measure its performance."),
668 options, &run, NULL)) ? global_ret : 1;
669}
670
671
672/* end of gnunet-daemon-fsprofiler.c */