diff options
Diffstat (limited to 'src/statistics/gnunet-service-statistics.c')
-rw-r--r-- | src/statistics/gnunet-service-statistics.c | 332 |
1 files changed, 310 insertions, 22 deletions
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c index 3ff751efe..251302a66 100644 --- a/src/statistics/gnunet-service-statistics.c +++ b/src/statistics/gnunet-service-statistics.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2010 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -27,6 +27,7 @@ | |||
27 | * - use BIO for IO operations | 27 | * - use BIO for IO operations |
28 | */ | 28 | */ |
29 | #include "platform.h" | 29 | #include "platform.h" |
30 | #include "gnunet_container_lib.h" | ||
30 | #include "gnunet_disk_lib.h" | 31 | #include "gnunet_disk_lib.h" |
31 | #include "gnunet_getopt_lib.h" | 32 | #include "gnunet_getopt_lib.h" |
32 | #include "gnunet_protocols.h" | 33 | #include "gnunet_protocols.h" |
@@ -37,6 +38,41 @@ | |||
37 | #include "statistics.h" | 38 | #include "statistics.h" |
38 | 39 | ||
39 | /** | 40 | /** |
41 | * Watch entry. | ||
42 | */ | ||
43 | struct WatchEntry | ||
44 | { | ||
45 | |||
46 | struct WatchEntry *next; | ||
47 | |||
48 | struct WatchEntry *prev; | ||
49 | |||
50 | struct GNUNET_SERVER_Client *client; | ||
51 | |||
52 | uint64_t last_value; | ||
53 | |||
54 | uint32_t wid; | ||
55 | |||
56 | }; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Client entry. | ||
61 | */ | ||
62 | struct ClientEntry | ||
63 | { | ||
64 | |||
65 | struct ClientEntry *next; | ||
66 | |||
67 | struct ClientEntry *prev; | ||
68 | |||
69 | struct GNUNET_SERVER_Client *client; | ||
70 | |||
71 | uint32_t max_wid; | ||
72 | |||
73 | }; | ||
74 | |||
75 | /** | ||
40 | * Entry in the statistics list. | 76 | * Entry in the statistics list. |
41 | */ | 77 | */ |
42 | struct StatsEntry | 78 | struct StatsEntry |
@@ -66,6 +102,18 @@ struct StatsEntry | |||
66 | struct GNUNET_STATISTICS_SetMessage *msg; | 102 | struct GNUNET_STATISTICS_SetMessage *msg; |
67 | 103 | ||
68 | /** | 104 | /** |
105 | * Watch context for changes to this | ||
106 | * value, or NULL for none. | ||
107 | */ | ||
108 | struct WatchEntry *we_head; | ||
109 | |||
110 | /** | ||
111 | * Watch context for changes to this | ||
112 | * value, or NULL for none. | ||
113 | */ | ||
114 | struct WatchEntry *we_tail; | ||
115 | |||
116 | /** | ||
69 | * Our value. | 117 | * Our value. |
70 | */ | 118 | */ |
71 | uint64_t value; | 119 | uint64_t value; |
@@ -92,6 +140,21 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
92 | */ | 140 | */ |
93 | static struct StatsEntry *start; | 141 | static struct StatsEntry *start; |
94 | 142 | ||
143 | static struct ClientEntry *client_head; | ||
144 | |||
145 | static struct ClientEntry *client_tail; | ||
146 | |||
147 | /** | ||
148 | * Our notification context. | ||
149 | */ | ||
150 | static struct GNUNET_SERVER_NotificationContext *nc; | ||
151 | |||
152 | /** | ||
153 | * Counter used to generate unique values. | ||
154 | */ | ||
155 | static uint32_t uidgen; | ||
156 | |||
157 | |||
95 | /** | 158 | /** |
96 | * Load persistent values from disk. Disk format is | 159 | * Load persistent values from disk. Disk format is |
97 | * exactly the same format that we also use for | 160 | * exactly the same format that we also use for |
@@ -209,7 +272,7 @@ save () | |||
209 | * Transmit the given stats value. | 272 | * Transmit the given stats value. |
210 | */ | 273 | */ |
211 | static void | 274 | static void |
212 | transmit (struct GNUNET_SERVER_TransmitContext *tc, | 275 | transmit (struct GNUNET_SERVER_Client *client, |
213 | const struct StatsEntry *e) | 276 | const struct StatsEntry *e) |
214 | { | 277 | { |
215 | struct GNUNET_STATISTICS_ReplyMessage *m; | 278 | struct GNUNET_STATISTICS_ReplyMessage *m; |
@@ -232,10 +295,11 @@ transmit (struct GNUNET_SERVER_TransmitContext *tc, | |||
232 | 2, e->service, e->name)); | 295 | 2, e->service, e->name)); |
233 | #if DEBUG_STATISTICS | 296 | #if DEBUG_STATISTICS |
234 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 297 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
235 | "Transmitting value for `%s:%s': %llu\n", | 298 | "Transmitting value for `%s:%s' (%d): %llu\n", |
236 | e->service, e->name, e->value); | 299 | e->service, e->name, |
300 | e->persistent, e->value); | ||
237 | #endif | 301 | #endif |
238 | GNUNET_SERVER_transmit_context_append_message (tc, &m->header); | 302 | GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, GNUNET_NO); |
239 | GNUNET_free (m); | 303 | GNUNET_free (m); |
240 | } | 304 | } |
241 | 305 | ||
@@ -252,6 +316,32 @@ matches (const struct StatsEntry *e, const char *service, const char *name) | |||
252 | } | 316 | } |
253 | 317 | ||
254 | 318 | ||
319 | static struct ClientEntry * | ||
320 | make_client_entry (struct GNUNET_SERVER_Client *client) | ||
321 | { | ||
322 | struct ClientEntry *ce; | ||
323 | |||
324 | if (client == NULL) | ||
325 | return NULL; | ||
326 | ce = client_head; | ||
327 | while (ce != NULL) | ||
328 | { | ||
329 | if (ce->client == client) | ||
330 | return ce; | ||
331 | ce = ce->next; | ||
332 | } | ||
333 | ce = GNUNET_malloc (sizeof (struct ClientEntry)); | ||
334 | ce->client = client; | ||
335 | GNUNET_SERVER_client_keep (client); | ||
336 | GNUNET_CONTAINER_DLL_insert (client_head, | ||
337 | client_tail, | ||
338 | ce); | ||
339 | GNUNET_SERVER_notification_context_add (nc, | ||
340 | client); | ||
341 | return ce; | ||
342 | } | ||
343 | |||
344 | |||
255 | /** | 345 | /** |
256 | * Handle GET-message. | 346 | * Handle GET-message. |
257 | * | 347 | * |
@@ -266,12 +356,13 @@ handle_get (void *cls, | |||
266 | struct GNUNET_SERVER_Client *client, | 356 | struct GNUNET_SERVER_Client *client, |
267 | const struct GNUNET_MessageHeader *message) | 357 | const struct GNUNET_MessageHeader *message) |
268 | { | 358 | { |
359 | struct GNUNET_MessageHeader end; | ||
269 | char *service; | 360 | char *service; |
270 | char *name; | 361 | char *name; |
271 | struct StatsEntry *pos; | 362 | struct StatsEntry *pos; |
272 | struct GNUNET_SERVER_TransmitContext *tc; | ||
273 | size_t size; | 363 | size_t size; |
274 | 364 | ||
365 | make_client_entry (client); | ||
275 | size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); | 366 | size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); |
276 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], | 367 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], |
277 | size, 2, &service, &name)) | 368 | size, 2, &service, &name)) |
@@ -285,20 +376,51 @@ handle_get (void *cls, | |||
285 | "Received request for statistics on `%s:%s'\n", | 376 | "Received request for statistics on `%s:%s'\n", |
286 | strlen (service) ? service : "*", strlen (name) ? name : "*"); | 377 | strlen (service) ? service : "*", strlen (name) ? name : "*"); |
287 | #endif | 378 | #endif |
288 | tc = GNUNET_SERVER_transmit_context_create (client); | ||
289 | pos = start; | 379 | pos = start; |
290 | while (pos != NULL) | 380 | while (pos != NULL) |
291 | { | 381 | { |
292 | if (matches (pos, service, name)) | 382 | if (matches (pos, service, name)) |
293 | transmit (tc, pos); | 383 | transmit (client, pos); |
294 | pos = pos->next; | 384 | pos = pos->next; |
295 | } | 385 | } |
296 | GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, | 386 | end.size = htons (sizeof (struct GNUNET_MessageHeader)); |
297 | GNUNET_MESSAGE_TYPE_STATISTICS_END); | 387 | end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END); |
298 | GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); | 388 | GNUNET_SERVER_notification_context_unicast (nc, |
389 | client, | ||
390 | &end, | ||
391 | GNUNET_NO); | ||
392 | GNUNET_SERVER_receive_done (client, | ||
393 | GNUNET_OK); | ||
299 | } | 394 | } |
300 | 395 | ||
301 | 396 | ||
397 | static void | ||
398 | notify_change (struct StatsEntry *se) | ||
399 | { | ||
400 | struct GNUNET_STATISTICS_WatchValueMessage wvm; | ||
401 | struct WatchEntry *pos; | ||
402 | |||
403 | pos = se->we_head; | ||
404 | while (pos != NULL) | ||
405 | { | ||
406 | if (pos->last_value != se->value) | ||
407 | { | ||
408 | wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); | ||
409 | wvm.header.size = htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); | ||
410 | wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0); | ||
411 | wvm.wid = htonl (pos->wid); | ||
412 | wvm.reserved = htonl (0); | ||
413 | wvm.value = GNUNET_htonll (se->value); | ||
414 | GNUNET_SERVER_notification_context_unicast (nc, | ||
415 | pos->client, | ||
416 | &wvm.header, | ||
417 | GNUNET_NO); | ||
418 | pos->last_value = se->value; | ||
419 | } | ||
420 | pos = pos->next; | ||
421 | } | ||
422 | } | ||
423 | |||
302 | /** | 424 | /** |
303 | * Handle SET-message. | 425 | * Handle SET-message. |
304 | * | 426 | * |
@@ -311,11 +433,6 @@ handle_set (void *cls, | |||
311 | struct GNUNET_SERVER_Client *client, | 433 | struct GNUNET_SERVER_Client *client, |
312 | const struct GNUNET_MessageHeader *message) | 434 | const struct GNUNET_MessageHeader *message) |
313 | { | 435 | { |
314 | /** | ||
315 | * Counter used to generate unique values. | ||
316 | */ | ||
317 | static uint32_t uidgen; | ||
318 | |||
319 | char *service; | 436 | char *service; |
320 | char *name; | 437 | char *name; |
321 | uint16_t msize; | 438 | uint16_t msize; |
@@ -326,7 +443,9 @@ handle_set (void *cls, | |||
326 | uint32_t flags; | 443 | uint32_t flags; |
327 | uint64_t value; | 444 | uint64_t value; |
328 | int64_t delta; | 445 | int64_t delta; |
446 | int changed; | ||
329 | 447 | ||
448 | make_client_entry (client); | ||
330 | msize = ntohs (message->size); | 449 | msize = ntohs (message->size); |
331 | if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) | 450 | if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) |
332 | { | 451 | { |
@@ -344,13 +463,15 @@ handle_set (void *cls, | |||
344 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 463 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
345 | return; | 464 | return; |
346 | } | 465 | } |
466 | flags = ntohl (msg->flags); | ||
467 | value = GNUNET_ntohll (msg->value); | ||
347 | #if DEBUG_STATISTICS | 468 | #if DEBUG_STATISTICS |
348 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 469 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
349 | "Received request to update statistic on `%s:%s'\n", | 470 | "Received request to update statistic on `%s:%s' (%u) to/by %llu\n", |
350 | service, name); | 471 | service, name, |
472 | (unsigned int) flags, | ||
473 | (unsigned long long) value); | ||
351 | #endif | 474 | #endif |
352 | flags = ntohl (msg->flags); | ||
353 | value = GNUNET_ntohll (msg->value); | ||
354 | pos = start; | 475 | pos = start; |
355 | prev = NULL; | 476 | prev = NULL; |
356 | while (pos != NULL) | 477 | while (pos != NULL) |
@@ -359,17 +480,20 @@ handle_set (void *cls, | |||
359 | { | 480 | { |
360 | if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) | 481 | if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) |
361 | { | 482 | { |
483 | changed = (pos->value != value); | ||
362 | pos->value = value; | 484 | pos->value = value; |
363 | } | 485 | } |
364 | else | 486 | else |
365 | { | 487 | { |
366 | delta = (int64_t) value; | 488 | delta = (int64_t) value; |
367 | if ((delta < 0) && (pos->value < -delta)) | 489 | if ((delta < 0) && (pos->value < -delta)) |
368 | { | 490 | { |
369 | pos->value = 0; | 491 | changed = (pos->value != 0); |
492 | pos->value = 0; | ||
370 | } | 493 | } |
371 | else | 494 | else |
372 | { | 495 | { |
496 | changed = (delta != 0); | ||
373 | GNUNET_break ((delta <= 0) || | 497 | GNUNET_break ((delta <= 0) || |
374 | (pos->value + delta > pos->value)); | 498 | (pos->value + delta > pos->value)); |
375 | pos->value += delta; | 499 | pos->value += delta; |
@@ -391,6 +515,8 @@ handle_set (void *cls, | |||
391 | "Statistic `%s:%s' updated to value %llu.\n", | 515 | "Statistic `%s:%s' updated to value %llu.\n", |
392 | service, name, pos->value); | 516 | service, name, pos->value); |
393 | #endif | 517 | #endif |
518 | if (changed) | ||
519 | notify_change (pos); | ||
394 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 520 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
395 | return; | 521 | return; |
396 | } | 522 | } |
@@ -420,6 +546,86 @@ handle_set (void *cls, | |||
420 | 546 | ||
421 | 547 | ||
422 | /** | 548 | /** |
549 | * Handle WATCH-message. | ||
550 | * | ||
551 | * @param cls closure | ||
552 | * @param client identification of the client | ||
553 | * @param message the actual message | ||
554 | */ | ||
555 | static void | ||
556 | handle_watch (void *cls, | ||
557 | struct GNUNET_SERVER_Client *client, | ||
558 | const struct GNUNET_MessageHeader *message) | ||
559 | { | ||
560 | char *service; | ||
561 | char *name; | ||
562 | uint16_t msize; | ||
563 | uint16_t size; | ||
564 | struct StatsEntry *pos; | ||
565 | struct ClientEntry *ce; | ||
566 | struct WatchEntry *we; | ||
567 | |||
568 | ce = make_client_entry (client); | ||
569 | msize = ntohs (message->size); | ||
570 | if (msize < sizeof (struct GNUNET_MessageHeader)) | ||
571 | { | ||
572 | GNUNET_break (0); | ||
573 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
574 | return; | ||
575 | } | ||
576 | size = msize - sizeof (struct GNUNET_MessageHeader); | ||
577 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], | ||
578 | size, 2, &service, &name)) | ||
579 | { | ||
580 | GNUNET_break (0); | ||
581 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
582 | return; | ||
583 | } | ||
584 | #if DEBUG_STATISTICS | ||
585 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
586 | "Received request to watch statistic on `%s:%s'\n", | ||
587 | service, name); | ||
588 | #endif | ||
589 | pos = start; | ||
590 | while (pos != NULL) | ||
591 | { | ||
592 | if (matches (pos, service, name)) | ||
593 | break; | ||
594 | pos = pos->next; | ||
595 | } | ||
596 | if (pos == NULL) | ||
597 | { | ||
598 | pos = GNUNET_malloc (sizeof (struct StatsEntry) + | ||
599 | sizeof (struct GNUNET_STATISTICS_SetMessage) + | ||
600 | size); | ||
601 | pos->next = start; | ||
602 | pos->uid = uidgen++; | ||
603 | pos->msg = (void *) &pos[1]; | ||
604 | pos->msg->header.size = htons (sizeof (struct GNUNET_STATISTICS_SetMessage) + | ||
605 | size); | ||
606 | pos->msg->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET); | ||
607 | memcpy (pos->msg, message, ntohs (message->size)); | ||
608 | pos->service = (const char *) &pos->msg[1]; | ||
609 | memcpy (&pos->msg[1], service, strlen (service)+1); | ||
610 | pos->name = &pos->service[strlen (pos->service) + 1]; | ||
611 | memcpy ((void*) pos->name, name, strlen (name)+1); | ||
612 | start = pos; | ||
613 | } | ||
614 | we = GNUNET_malloc (sizeof (struct WatchEntry)); | ||
615 | we->client = client; | ||
616 | GNUNET_SERVER_client_keep (client); | ||
617 | we->wid = ce->max_wid++; | ||
618 | GNUNET_CONTAINER_DLL_insert (pos->we_head, | ||
619 | pos->we_tail, | ||
620 | we); | ||
621 | if (pos->value != 0) | ||
622 | notify_change (pos); | ||
623 | GNUNET_SERVER_receive_done (client, | ||
624 | GNUNET_OK); | ||
625 | } | ||
626 | |||
627 | |||
628 | /** | ||
423 | * Task run during shutdown. | 629 | * Task run during shutdown. |
424 | * | 630 | * |
425 | * @param cls unused | 631 | * @param cls unused |
@@ -429,7 +635,84 @@ static void | |||
429 | shutdown_task (void *cls, | 635 | shutdown_task (void *cls, |
430 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 636 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
431 | { | 637 | { |
638 | struct ClientEntry *ce; | ||
639 | struct WatchEntry *we; | ||
640 | struct StatsEntry *se; | ||
641 | |||
432 | save (); | 642 | save (); |
643 | GNUNET_SERVER_notification_context_destroy (nc); | ||
644 | nc = NULL; | ||
645 | while (NULL != (ce = client_head)) | ||
646 | { | ||
647 | GNUNET_SERVER_client_drop (ce->client); | ||
648 | GNUNET_CONTAINER_DLL_remove (client_head, | ||
649 | client_tail, | ||
650 | ce); | ||
651 | GNUNET_free (ce); | ||
652 | } | ||
653 | while (NULL != (se = start)) | ||
654 | { | ||
655 | start = se->next; | ||
656 | while (NULL != (we = se->we_head)) | ||
657 | { | ||
658 | GNUNET_SERVER_client_drop (we->client); | ||
659 | GNUNET_CONTAINER_DLL_remove (se->we_head, | ||
660 | se->we_tail, | ||
661 | we); | ||
662 | GNUNET_free (we); | ||
663 | } | ||
664 | GNUNET_free (se); | ||
665 | } | ||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * A client disconnected. Remove all of its data structure entries. | ||
671 | * | ||
672 | * @param cls closure, NULL | ||
673 | * @param client identification of the client | ||
674 | */ | ||
675 | static void | ||
676 | handle_client_disconnect (void *cls, | ||
677 | struct GNUNET_SERVER_Client | ||
678 | * client) | ||
679 | { | ||
680 | struct ClientEntry *ce; | ||
681 | struct WatchEntry *we; | ||
682 | struct WatchEntry *wen; | ||
683 | struct StatsEntry *se; | ||
684 | |||
685 | ce = client_head; | ||
686 | while (NULL != ce) | ||
687 | { | ||
688 | if (ce->client == client) | ||
689 | { | ||
690 | GNUNET_SERVER_client_drop (ce->client); | ||
691 | GNUNET_CONTAINER_DLL_remove (client_head, | ||
692 | client_tail, | ||
693 | ce); | ||
694 | GNUNET_free (ce); | ||
695 | break; | ||
696 | } | ||
697 | ce = ce->next; | ||
698 | } | ||
699 | se = start; | ||
700 | while (NULL != se) | ||
701 | { | ||
702 | wen = se->we_head; | ||
703 | while (NULL != (we = wen)) | ||
704 | { | ||
705 | wen = we->next; | ||
706 | if (we->client != client) | ||
707 | continue; | ||
708 | GNUNET_SERVER_client_drop (we->client); | ||
709 | GNUNET_CONTAINER_DLL_remove (se->we_head, | ||
710 | se->we_tail, | ||
711 | we); | ||
712 | GNUNET_free (we); | ||
713 | } | ||
714 | se = se->next; | ||
715 | } | ||
433 | } | 716 | } |
434 | 717 | ||
435 | 718 | ||
@@ -450,10 +733,15 @@ run (void *cls, | |||
450 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | 733 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { |
451 | {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0}, | 734 | {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0}, |
452 | {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0}, | 735 | {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0}, |
736 | {&handle_watch, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, 0}, | ||
453 | {NULL, NULL, 0, 0} | 737 | {NULL, NULL, 0, 0} |
454 | }; | 738 | }; |
455 | cfg = c; | 739 | cfg = c; |
456 | GNUNET_SERVER_add_handlers (server, handlers); | 740 | GNUNET_SERVER_add_handlers (server, handlers); |
741 | nc = GNUNET_SERVER_notification_context_create (server, 16); | ||
742 | GNUNET_SERVER_disconnect_notify (server, | ||
743 | &handle_client_disconnect, | ||
744 | NULL); | ||
457 | load (server); | 745 | load (server); |
458 | GNUNET_SCHEDULER_add_delayed (sched, | 746 | GNUNET_SCHEDULER_add_delayed (sched, |
459 | GNUNET_TIME_UNIT_FOREVER_REL, | 747 | GNUNET_TIME_UNIT_FOREVER_REL, |