summaryrefslogtreecommitdiff
path: root/src/statistics
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-20 02:28:01 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-20 02:28:01 +0000
commit6a131ab255bb3419eb0e59a24879556d5b1c75d3 (patch)
tree3d5a543eb36d2184fbc9d390ecd3c9e092614e13 /src/statistics
parent102ef991828f70f8a4baa9755be02e5a17a67110 (diff)
downloadgnunet-6a131ab255bb3419eb0e59a24879556d5b1c75d3.tar.gz
gnunet-6a131ab255bb3419eb0e59a24879556d5b1c75d3.zip
convert statistics service to new service MQ API
Diffstat (limited to 'src/statistics')
-rw-r--r--src/statistics/gnunet-service-statistics.c645
-rw-r--r--src/statistics/gnunet-statistics.c181
-rw-r--r--src/statistics/statistics_api.c18
3 files changed, 462 insertions, 382 deletions
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c
index c0be7c668..161327421 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 Copyright (C) 2009, 2010, 2012, 2014 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2012, 2014, 2016 GNUnet e.V.
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
@@ -54,7 +54,7 @@ struct WatchEntry
54 /** 54 /**
55 * For which client is this watch entry? 55 * For which client is this watch entry?
56 */ 56 */
57 struct GNUNET_SERVER_Client *client; 57 struct ClientEntry *ce;
58 58
59 /** 59 /**
60 * Last value we communicated to the client for this watch entry. 60 * Last value we communicated to the client for this watch entry.
@@ -185,7 +185,12 @@ struct ClientEntry
185 /** 185 /**
186 * Corresponding server handle. 186 * Corresponding server handle.
187 */ 187 */
188 struct GNUNET_SERVER_Client *client; 188 struct GNUNET_SERVICE_Client *client;
189
190 /**
191 * Corresponding message queue.
192 */
193 struct GNUNET_MQ_Handle *mq;
189 194
190 /** 195 /**
191 * Which subsystem is this client writing to (SET/UPDATE)? 196 * Which subsystem is this client writing to (SET/UPDATE)?
@@ -221,14 +226,9 @@ static struct SubsystemEntry *sub_tail;
221static unsigned int client_count; 226static unsigned int client_count;
222 227
223/** 228/**
224 * Handle to our server.
225 */
226static struct GNUNET_SERVER_Handle *srv;
227
228/**
229 * Our notification context. 229 * Our notification context.
230 */ 230 */
231static struct GNUNET_SERVER_NotificationContext *nc; 231static struct GNUNET_NotificationContext *nc;
232 232
233/** 233/**
234 * Counter used to generate unique values. 234 * Counter used to generate unique values.
@@ -242,103 +242,6 @@ static int in_shutdown;
242 242
243 243
244/** 244/**
245 * Inject a message to our server with a client of 'NULL'.
246 *
247 * @param cls the `struct GNUNET_SERVER_Handle`
248 * @param client unused
249 * @param msg message to inject
250 */
251static int
252inject_message (void *cls,
253 void *client,
254 const struct GNUNET_MessageHeader *msg)
255{
256 struct GNUNET_SERVER_Handle *server = cls;
257
258 GNUNET_break (GNUNET_OK == GNUNET_SERVER_inject (server, NULL, msg));
259 return GNUNET_OK;
260}
261
262
263/**
264 * Load persistent values from disk. Disk format is exactly the same
265 * format that we also use for setting the values over the network.
266 *
267 * @param server handle to the server context
268 */
269static void
270load (struct GNUNET_SERVER_Handle *server)
271{
272 char *fn;
273 struct GNUNET_BIO_ReadHandle *rh;
274 uint64_t fsize;
275 char *buf;
276 struct GNUNET_SERVER_MessageStreamTokenizer *mst;
277
278 if (GNUNET_OK !=
279 GNUNET_CONFIGURATION_get_value_filename (cfg,
280 "STATISTICS",
281 "DATABASE",
282 &fn))
283 {
284 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
285 "STATISTICS",
286 "DATABASE");
287 return;
288 }
289 if ( (GNUNET_OK !=
290 GNUNET_DISK_file_size (fn,
291 &fsize,
292 GNUNET_NO,
293 GNUNET_YES)) ||
294 (0 == fsize) )
295 {
296 GNUNET_free (fn);
297 return;
298 }
299 buf = GNUNET_malloc (fsize);
300 rh = GNUNET_BIO_read_open (fn);
301 if (!rh)
302 {
303 GNUNET_free (buf);
304 GNUNET_free (fn);
305 return;
306 }
307 if (GNUNET_OK !=
308 GNUNET_BIO_read (rh,
309 fn,
310 buf,
311 fsize))
312 {
313 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
314 "read",
315 fn);
316 GNUNET_break (GNUNET_OK ==
317 GNUNET_BIO_read_close (rh, NULL));
318 GNUNET_free (buf);
319 GNUNET_free (fn);
320 return;
321 }
322 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
323 _("Loading %llu bytes of statistics from `%s'\n"),
324 (unsigned long long) fsize, fn);
325 mst = GNUNET_SERVER_mst_create (&inject_message,
326 server);
327 GNUNET_break (GNUNET_OK ==
328 GNUNET_SERVER_mst_receive (mst, NULL,
329 buf, fsize,
330 GNUNET_YES,
331 GNUNET_NO));
332 GNUNET_SERVER_mst_destroy (mst);
333 GNUNET_free (buf);
334 GNUNET_break (GNUNET_OK ==
335 GNUNET_BIO_read_close (rh,
336 NULL));
337 GNUNET_free (fn);
338}
339
340
341/**
342 * Write persistent statistics to disk. 245 * Write persistent statistics to disk.
343 */ 246 */
344static void 247static void
@@ -379,7 +282,8 @@ save ()
379 GNUNET_CONTAINER_DLL_remove (se->stat_head, 282 GNUNET_CONTAINER_DLL_remove (se->stat_head,
380 se->stat_tail, 283 se->stat_tail,
381 pos); 284 pos);
382 if ((pos->persistent) && (NULL != wh)) 285 if ( (pos->persistent) &&
286 (NULL != wh) )
383 { 287 {
384 nlen = strlen (pos->name) + 1; 288 nlen = strlen (pos->name) + 1;
385 size = sizeof (struct GNUNET_STATISTICS_SetMessage) + nlen + slen; 289 size = sizeof (struct GNUNET_STATISTICS_SetMessage) + nlen + slen;
@@ -446,24 +350,23 @@ save ()
446 * @param e value to transmit 350 * @param e value to transmit
447 */ 351 */
448static void 352static void
449transmit (struct GNUNET_SERVER_Client *client, 353transmit (struct ClientEntry *ce,
450 const struct StatsEntry *e) 354 const struct StatsEntry *e)
451{ 355{
356 struct GNUNET_MQ_Envelope *env;
452 struct GNUNET_STATISTICS_ReplyMessage *m; 357 struct GNUNET_STATISTICS_ReplyMessage *m;
453 size_t size; 358 size_t size;
454 359
455 size = sizeof (struct GNUNET_STATISTICS_ReplyMessage) + 360 size = strlen (e->subsystem->service) + 1 +
456 strlen (e->subsystem->service) + 1 +
457 strlen (e->name) + 1; 361 strlen (e->name) + 1;
458 GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); 362 GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
459 m = GNUNET_malloc (size); 363 env = GNUNET_MQ_msg_extra (m,
460 m->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_VALUE); 364 size,
461 m->header.size = htons (size); 365 GNUNET_MESSAGE_TYPE_STATISTICS_VALUE);
462 m->uid = htonl (e->uid); 366 m->uid = htonl (e->uid);
463 if (e->persistent) 367 if (e->persistent)
464 m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT); 368 m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT);
465 m->value = GNUNET_htonll (e->value); 369 m->value = GNUNET_htonll (e->value);
466 size -= sizeof (struct GNUNET_STATISTICS_ReplyMessage);
467 GNUNET_assert (size == 370 GNUNET_assert (size ==
468 GNUNET_STRINGS_buffer_fill ((char *) &m[1], 371 GNUNET_STRINGS_buffer_fill ((char *) &m[1],
469 size, 372 size,
@@ -476,66 +379,51 @@ transmit (struct GNUNET_SERVER_Client *client,
476 e->name, 379 e->name,
477 e->persistent, 380 e->persistent,
478 (unsigned long long) e->value); 381 (unsigned long long) e->value);
479 GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, 382 GNUNET_MQ_send (ce->mq,
480 GNUNET_NO); 383 env);
481 GNUNET_free (m);
482} 384}
483 385
484 386
485/** 387/**
486 * Find a client entry for the given client handle, or create one. 388 * Callback called when a client connects to the service.
487 * 389 *
488 * @param client handle to match 390 * @param cls closure for the service
489 * @return corresponding client entry struct 391 * @param c the new client that connected to the service
392 * @param mq the message queue used to send messages to the client
393 * @return @a c
490 */ 394 */
491static struct ClientEntry * 395static void *
492make_client_entry (struct GNUNET_SERVER_Client *client) 396client_connect_cb (void *cls,
397 struct GNUNET_SERVICE_Client *c,
398 struct GNUNET_MQ_Handle *mq)
493{ 399{
494 struct ClientEntry *ce; 400 struct ClientEntry *ce;
495 401
496 ce = GNUNET_SERVER_client_get_user_context (client,
497 struct ClientEntry);
498 if (NULL != ce)
499 return ce;
500 if (NULL == nc)
501 {
502 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
503 return NULL;
504 }
505 ce = GNUNET_new (struct ClientEntry); 402 ce = GNUNET_new (struct ClientEntry);
506 ce->client = client; 403 ce->client = c;
507 GNUNET_SERVER_client_set_user_context (client, ce); 404 ce->mq = mq;
508 client_count++; 405 client_count++;
509 GNUNET_SERVER_notification_context_add (nc, client); 406 GNUNET_notification_context_add (nc,
407 mq);
510 return ce; 408 return ce;
511} 409}
512 410
513 411
514/** 412/**
515 * Handle GET-message. 413 * Check integrity of GET-message.
516 * 414 *
517 * @param cls closure 415 * @param cls identification of the client
518 * @param client identification of the client
519 * @param message the actual message 416 * @param message the actual message
520 * @return #GNUNET_OK to keep the connection open, 417 * @return #GNUNET_OK if @a message is well-formed
521 * #GNUNET_SYSERR to close it (signal serious error)
522 */ 418 */
523static void 419static int
524handle_get (void *cls, 420check_get (void *cls,
525 struct GNUNET_SERVER_Client *client, 421 const struct GNUNET_MessageHeader *message)
526 const struct GNUNET_MessageHeader *message)
527{ 422{
528 struct GNUNET_MessageHeader end;
529 const char *service; 423 const char *service;
530 const char *name; 424 const char *name;
531 size_t slen;
532 size_t nlen;
533 struct SubsystemEntry *se;
534 struct StatsEntry *pos;
535 size_t size; 425 size_t size;
536 426
537 if (NULL == make_client_entry (client))
538 return; /* new client during shutdown */
539 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); 427 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
540 if (size != 428 if (size !=
541 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 429 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
@@ -545,10 +433,40 @@ handle_get (void *cls,
545 &name)) 433 &name))
546 { 434 {
547 GNUNET_break (0); 435 GNUNET_break (0);
548 GNUNET_SERVER_receive_done (client, 436 return GNUNET_SYSERR;
549 GNUNET_SYSERR);
550 return;
551 } 437 }
438 return GNUNET_OK;
439}
440
441
442/**
443 * Handle GET-message.
444 *
445 * @param cls identification of the client
446 * @param message the actual message
447 */
448static void
449handle_get (void *cls,
450 const struct GNUNET_MessageHeader *message)
451{
452 struct ClientEntry *ce = cls;
453 struct GNUNET_MQ_Envelope *env;
454 struct GNUNET_MessageHeader *end;
455 const char *service;
456 const char *name;
457 size_t slen;
458 size_t nlen;
459 struct SubsystemEntry *se;
460 struct StatsEntry *pos;
461 size_t size;
462
463 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
464 GNUNET_assert (size ==
465 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
466 size,
467 2,
468 &service,
469 &name));
552 slen = strlen (service); 470 slen = strlen (service);
553 nlen = strlen (name); 471 nlen = strlen (name);
554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -563,18 +481,18 @@ handle_get (void *cls,
563 for (pos = se->stat_head; NULL != pos; pos = pos->next) 481 for (pos = se->stat_head; NULL != pos; pos = pos->next)
564 { 482 {
565 if (! ( (0 == nlen) || 483 if (! ( (0 == nlen) ||
566 (0 == strcmp (name, pos->name))) ) 484 (0 == strcmp (name,
485 pos->name))) )
567 continue; 486 continue;
568 transmit (client, pos); 487 transmit (ce,
488 pos);
569 } 489 }
570 } 490 }
571 end.size = htons (sizeof (struct GNUNET_MessageHeader)); 491 env = GNUNET_MQ_msg (end,
572 end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END); 492 GNUNET_MESSAGE_TYPE_STATISTICS_END);
573 GNUNET_SERVER_notification_context_unicast (nc, 493 GNUNET_MQ_send (ce->mq,
574 client, 494 env);
575 &end, 495 GNUNET_SERVICE_client_continue (ce->client);
576 GNUNET_NO);
577 GNUNET_SERVER_receive_done (client, GNUNET_OK);
578} 496}
579 497
580 498
@@ -586,7 +504,8 @@ handle_get (void *cls,
586static void 504static void
587notify_change (struct StatsEntry *se) 505notify_change (struct StatsEntry *se)
588{ 506{
589 struct GNUNET_STATISTICS_WatchValueMessage wvm; 507 struct GNUNET_MQ_Envelope *env;
508 struct GNUNET_STATISTICS_WatchValueMessage *wvm;
590 struct WatchEntry *pos; 509 struct WatchEntry *pos;
591 510
592 for (pos = se->we_head; NULL != pos; pos = pos->next) 511 for (pos = se->we_head; NULL != pos; pos = pos->next)
@@ -600,17 +519,14 @@ notify_change (struct StatsEntry *se)
600 { 519 {
601 pos->last_value_set = GNUNET_YES; 520 pos->last_value_set = GNUNET_YES;
602 } 521 }
603 wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); 522 env = GNUNET_MQ_msg (wvm,
604 wvm.header.size = 523 GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE);
605 htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); 524 wvm->flags = htonl (se->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0);
606 wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0); 525 wvm->wid = htonl (pos->wid);
607 wvm.wid = htonl (pos->wid); 526 wvm->reserved = htonl (0);
608 wvm.reserved = htonl (0); 527 wvm->value = GNUNET_htonll (se->value);
609 wvm.value = GNUNET_htonll (se->value); 528 GNUNET_MQ_send (pos->ce->mq,
610 GNUNET_SERVER_notification_context_unicast (nc, 529 env);
611 pos->client,
612 &wvm.header,
613 GNUNET_NO);
614 pos->last_value = se->value; 530 pos->last_value = se->value;
615 } 531 }
616} 532}
@@ -688,25 +604,52 @@ find_stat_entry (struct SubsystemEntry *se,
688 604
689 605
690/** 606/**
607 * Check format of SET-message.
608 *
609 * @param cls the `struct ClientEntry`
610 * @param message the actual message
611 * @return #GNUNET_OK if message is well-formed
612 */
613static int
614check_set (void *cls,
615 const struct GNUNET_STATISTICS_SetMessage *msg)
616{
617 const char *service;
618 const char *name;
619 size_t msize;
620
621 msize = ntohs (msg->header.size) - sizeof (*msg);
622 if (msize !=
623 GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
624 msize,
625 2,
626 &service,
627 &name))
628 {
629 GNUNET_break (0);
630 return GNUNET_SYSERR;
631 }
632 return GNUNET_OK;
633}
634
635
636/**
691 * Handle SET-message. 637 * Handle SET-message.
692 * 638 *
693 * @param cls closure 639 * @param cls the `struct ClientEntry`
694 * @param client identification of the client
695 * @param message the actual message 640 * @param message the actual message
696 */ 641 */
697static void 642static void
698handle_set (void *cls, 643handle_set (void *cls,
699 struct GNUNET_SERVER_Client *client, 644 const struct GNUNET_STATISTICS_SetMessage *msg)
700 const struct GNUNET_MessageHeader *message)
701{ 645{
646 struct ClientEntry *ce = cls;
702 const char *service; 647 const char *service;
703 const char *name; 648 const char *name;
704 size_t nlen; 649 size_t nlen;
705 uint16_t msize; 650 uint16_t msize;
706 uint16_t size; 651 uint16_t size;
707 const struct GNUNET_STATISTICS_SetMessage *msg;
708 struct SubsystemEntry *se; 652 struct SubsystemEntry *se;
709 struct ClientEntry *ce;
710 struct StatsEntry *pos; 653 struct StatsEntry *pos;
711 uint32_t flags; 654 uint32_t flags;
712 uint64_t value; 655 uint64_t value;
@@ -714,32 +657,16 @@ handle_set (void *cls,
714 int changed; 657 int changed;
715 int initial_set; 658 int initial_set;
716 659
717 ce = NULL; 660 msize = ntohs (msg->header.size);
718 if ( (NULL != client) &&
719 (NULL == (ce = make_client_entry (client))) )
720 return; /* new client during shutdown */
721 msize = ntohs (message->size);
722 if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage))
723 {
724 GNUNET_break (0);
725 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
726 return;
727 }
728 size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage); 661 size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage);
729 msg = (const struct GNUNET_STATISTICS_SetMessage *) message; 662 GNUNET_assert (size ==
730 if (size != 663 GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
731 GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1], 664 size,
732 size, 665 2,
733 2, 666 &service,
734 &service, 667 &name));
735 &name)) 668 se = find_subsystem_entry (ce,
736 { 669 service);
737 GNUNET_break (0);
738 GNUNET_SERVER_receive_done (client,
739 GNUNET_SYSERR);
740 return;
741 }
742 se = find_subsystem_entry (ce, service);
743 flags = ntohl (msg->flags); 670 flags = ntohl (msg->flags);
744 value = GNUNET_ntohll (msg->value); 671 value = GNUNET_ntohll (msg->value);
745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -748,7 +675,8 @@ handle_set (void *cls,
748 name, 675 name,
749 (unsigned int) flags, 676 (unsigned int) flags,
750 (unsigned long long) value); 677 (unsigned long long) value);
751 pos = find_stat_entry (se, name); 678 pos = find_stat_entry (se,
679 name);
752 if (NULL != pos) 680 if (NULL != pos)
753 { 681 {
754 initial_set = 0; 682 initial_set = 0;
@@ -798,16 +726,15 @@ handle_set (void *cls,
798 if ( (changed) || 726 if ( (changed) ||
799 (1 == initial_set) ) 727 (1 == initial_set) )
800 notify_change (pos); 728 notify_change (pos);
801 GNUNET_SERVER_receive_done (client, 729 GNUNET_SERVICE_client_continue (ce->client);
802 GNUNET_OK);
803 return; 730 return;
804 } 731 }
805 /* not found, create a new entry */ 732 /* not found, create a new entry */
806 nlen = strlen (name) + 1; 733 nlen = strlen (name) + 1;
807 pos = GNUNET_malloc (sizeof (struct StatsEntry) + nlen); 734 pos = GNUNET_malloc (sizeof (struct StatsEntry) + nlen);
808 GNUNET_memcpy (&pos[1], 735 GNUNET_memcpy (&pos[1],
809 name, 736 name,
810 nlen); 737 nlen);
811 pos->name = (const char *) &pos[1]; 738 pos->name = (const char *) &pos[1];
812 pos->subsystem = se; 739 pos->subsystem = se;
813 if ( (0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE)) || 740 if ( (0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE)) ||
@@ -830,72 +757,91 @@ handle_set (void *cls,
830 service, 757 service,
831 name, 758 name,
832 (unsigned long long) pos->value); 759 (unsigned long long) pos->value);
833 GNUNET_SERVER_receive_done (client, 760 if (NULL != ce)
834 GNUNET_OK); 761 GNUNET_SERVICE_client_continue (ce->client);
762}
763
764
765/**
766 * Check integrity of WATCH-message.
767 *
768 * @param cls the `struct ClientEntry *`
769 * @param message the actual message
770 * @return #GNUNET_OK if message is well-formed
771 */
772static int
773check_watch (void *cls,
774 const struct GNUNET_MessageHeader *message)
775{
776 size_t size;
777 const char *service;
778 const char *name;
779
780 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
781 if (size !=
782 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
783 size,
784 2,
785 &service,
786 &name))
787 {
788 GNUNET_break (0);
789 return GNUNET_SYSERR;
790 }
791 return GNUNET_OK;
835} 792}
836 793
837 794
838/** 795/**
839 * Handle WATCH-message. 796 * Handle WATCH-message.
840 * 797 *
841 * @param cls closure 798 * @param cls the `struct ClientEntry *`
842 * @param client identification of the client
843 * @param message the actual message 799 * @param message the actual message
844 */ 800 */
845static void 801static void
846handle_watch (void *cls, 802handle_watch (void *cls,
847 struct GNUNET_SERVER_Client *client,
848 const struct GNUNET_MessageHeader *message) 803 const struct GNUNET_MessageHeader *message)
849{ 804{
805 struct ClientEntry *ce = cls;
850 const char *service; 806 const char *service;
851 const char *name; 807 const char *name;
852 uint16_t msize; 808 uint16_t msize;
853 uint16_t size; 809 uint16_t size;
854 struct SubsystemEntry *se; 810 struct SubsystemEntry *se;
855 struct StatsEntry *pos; 811 struct StatsEntry *pos;
856 struct ClientEntry *ce;
857 struct WatchEntry *we; 812 struct WatchEntry *we;
858 size_t nlen; 813 size_t nlen;
859 814
860 if (NULL == nc) 815 if (NULL == nc)
861 { 816 {
862 GNUNET_SERVER_receive_done (client, 817 GNUNET_SERVICE_client_drop (ce->client);
863 GNUNET_SYSERR);
864 return; 818 return;
865 } 819 }
866 GNUNET_SERVER_client_mark_monitor (client); 820 GNUNET_SERVICE_client_mark_monitor (ce->client);
867 ce = make_client_entry (client);
868 msize = ntohs (message->size); 821 msize = ntohs (message->size);
869 if (msize < sizeof (struct GNUNET_MessageHeader))
870 {
871 GNUNET_break (0);
872 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
873 return;
874 }
875 size = msize - sizeof (struct GNUNET_MessageHeader); 822 size = msize - sizeof (struct GNUNET_MessageHeader);
876 if (size != 823 GNUNET_assert (size ==
877 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 824 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
878 size, 825 size,
879 2, 826 2,
880 &service, 827 &service,
881 &name)) 828 &name));
882 {
883 GNUNET_break (0);
884 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
885 return;
886 }
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
888 "Received request to watch statistic on `%s:%s'\n", 830 "Received request to watch statistic on `%s:%s'\n",
889 service, 831 service,
890 name); 832 name);
891 se = find_subsystem_entry (ce, service); 833 se = find_subsystem_entry (ce,
892 pos = find_stat_entry (se, name); 834 service);
835 pos = find_stat_entry (se,
836 name);
893 if (NULL == pos) 837 if (NULL == pos)
894 { 838 {
895 nlen = strlen (name) + 1; 839 nlen = strlen (name) + 1;
896 pos = GNUNET_malloc (sizeof (struct StatsEntry) + 840 pos = GNUNET_malloc (sizeof (struct StatsEntry) +
897 nlen); 841 nlen);
898 GNUNET_memcpy (&pos[1], name, nlen); 842 GNUNET_memcpy (&pos[1],
843 name,
844 nlen);
899 pos->name = (const char *) &pos[1]; 845 pos->name = (const char *) &pos[1];
900 pos->subsystem = se; 846 pos->subsystem = se;
901 GNUNET_CONTAINER_DLL_insert (se->stat_head, 847 GNUNET_CONTAINER_DLL_insert (se->stat_head,
@@ -910,7 +856,7 @@ handle_watch (void *cls,
910 (unsigned long long) pos->value); 856 (unsigned long long) pos->value);
911 } 857 }
912 we = GNUNET_new (struct WatchEntry); 858 we = GNUNET_new (struct WatchEntry);
913 we->client = client; 859 we->ce = ce;
914 we->last_value_set = GNUNET_NO; 860 we->last_value_set = GNUNET_NO;
915 we->wid = ce->max_wid++; 861 we->wid = ce->max_wid++;
916 GNUNET_CONTAINER_DLL_insert (pos->we_head, 862 GNUNET_CONTAINER_DLL_insert (pos->we_head,
@@ -918,7 +864,31 @@ handle_watch (void *cls,
918 we); 864 we);
919 if (0 != pos->value) 865 if (0 != pos->value)
920 notify_change (pos); 866 notify_change (pos);
921 GNUNET_SERVER_receive_done (client, GNUNET_OK); 867 GNUNET_SERVICE_client_continue (ce->client);
868}
869
870
871/**
872 * Handle DISCONNECT-message. Sync to disk and send
873 * back a #GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
874 * message.
875 *
876 * @param cls the `struct ClientEntry *`
877 * @param message the actual message
878 */
879static void
880handle_disconnect (void *cls,
881 const struct GNUNET_MessageHeader *message)
882{
883 struct ClientEntry *ce = cls;
884 struct GNUNET_MQ_Envelope *env;
885 struct GNUNET_MessageHeader *msg;
886
887 env = GNUNET_MQ_msg (msg,
888 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM);
889 GNUNET_MQ_send (ce->mq,
890 env);
891 GNUNET_SERVICE_client_continue (ce->client);
922} 892}
923 893
924 894
@@ -935,7 +905,7 @@ do_shutdown ()
935 if (NULL == nc) 905 if (NULL == nc)
936 return; 906 return;
937 save (); 907 save ();
938 GNUNET_SERVER_notification_context_destroy (nc); 908 GNUNET_notification_context_destroy (nc);
939 nc = NULL; 909 nc = NULL;
940 GNUNET_assert (0 == client_count); 910 GNUNET_assert (0 == client_count);
941 while (NULL != (se = sub_head)) 911 while (NULL != (se = sub_head))
@@ -983,25 +953,19 @@ shutdown_task (void *cls)
983 * 953 *
984 * @param cls closure, NULL 954 * @param cls closure, NULL
985 * @param client identification of the client 955 * @param client identification of the client
956 * @param app_cls the `struct ClientEntry *`
986 */ 957 */
987static void 958static void
988handle_client_disconnect (void *cls, 959client_disconnect_cb (void *cls,
989 struct GNUNET_SERVER_Client *client) 960 struct GNUNET_SERVICE_Client *client,
961 void *app_cls)
990{ 962{
991 struct ClientEntry *ce; 963 struct ClientEntry *ce = app_cls;
992 struct WatchEntry *we; 964 struct WatchEntry *we;
993 struct WatchEntry *wen; 965 struct WatchEntry *wen;
994 struct StatsEntry *pos; 966 struct StatsEntry *pos;
995 struct SubsystemEntry *se; 967 struct SubsystemEntry *se;
996 968
997 if (NULL == client)
998 return;
999 ce = GNUNET_SERVER_client_get_user_context (client,
1000 struct ClientEntry);
1001 if (NULL == ce)
1002 return;
1003 GNUNET_SERVER_client_set_user_context (client,
1004 NULL);
1005 client_count--; 969 client_count--;
1006 for (se = sub_head; NULL != se; se = se->next) 970 for (se = sub_head; NULL != se; se = se->next)
1007 { 971 {
@@ -1011,7 +975,7 @@ handle_client_disconnect (void *cls,
1011 while (NULL != (we = wen)) 975 while (NULL != (we = wen))
1012 { 976 {
1013 wen = we->next; 977 wen = we->next;
1014 if (we->client != client) 978 if (we->ce != ce)
1015 continue; 979 continue;
1016 GNUNET_CONTAINER_DLL_remove (pos->we_head, 980 GNUNET_CONTAINER_DLL_remove (pos->we_head,
1017 pos->we_tail, 981 pos->we_tail,
@@ -1027,52 +991,163 @@ handle_client_disconnect (void *cls,
1027 991
1028 992
1029/** 993/**
994 * We've read a `struct GNUNET_STATISTICS_SetMessage *` from
995 * disk. Check that it is well-formed, and if so pass it to
996 * the handler for set messages.
997 *
998 * @param cls NULL
999 * @param message the message found on disk
1000 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
1001 */
1002static int
1003inject_message (void *cls,
1004 const struct GNUNET_MessageHeader *message)
1005{
1006 uint16_t msize = ntohs (message->size);
1007 const struct GNUNET_STATISTICS_SetMessage *sm;
1008
1009 sm = (const struct GNUNET_STATISTICS_SetMessage *) message;
1010 if ( (sizeof (struct GNUNET_STATISTICS_SetMessage) > msize) ||
1011 (GNUNET_OK !=
1012 check_set (NULL,
1013 sm)) )
1014 {
1015 GNUNET_break (0);
1016 return GNUNET_SYSERR;
1017 }
1018 handle_set (NULL,
1019 sm);
1020 return GNUNET_OK;
1021}
1022
1023
1024/**
1025 * Load persistent values from disk. Disk format is exactly the same
1026 * format that we also use for setting the values over the network.
1027 */
1028static void
1029load ()
1030{
1031 char *fn;
1032 struct GNUNET_BIO_ReadHandle *rh;
1033 uint64_t fsize;
1034 char *buf;
1035 struct GNUNET_MessageStreamTokenizer *mst;
1036
1037 if (GNUNET_OK !=
1038 GNUNET_CONFIGURATION_get_value_filename (cfg,
1039 "STATISTICS",
1040 "DATABASE",
1041 &fn))
1042 {
1043 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1044 "STATISTICS",
1045 "DATABASE");
1046 return;
1047 }
1048 if ( (GNUNET_OK !=
1049 GNUNET_DISK_file_size (fn,
1050 &fsize,
1051 GNUNET_NO,
1052 GNUNET_YES)) ||
1053 (0 == fsize) )
1054 {
1055 GNUNET_free (fn);
1056 return;
1057 }
1058 buf = GNUNET_malloc (fsize);
1059 rh = GNUNET_BIO_read_open (fn);
1060 if (! rh)
1061 {
1062 GNUNET_free (buf);
1063 GNUNET_free (fn);
1064 return;
1065 }
1066 if (GNUNET_OK !=
1067 GNUNET_BIO_read (rh,
1068 fn,
1069 buf,
1070 fsize))
1071 {
1072 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1073 "read",
1074 fn);
1075 GNUNET_break (GNUNET_OK ==
1076 GNUNET_BIO_read_close (rh,
1077 NULL));
1078 GNUNET_free (buf);
1079 GNUNET_free (fn);
1080 return;
1081 }
1082 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1083 _("Loading %llu bytes of statistics from `%s'\n"),
1084 (unsigned long long) fsize,
1085 fn);
1086 mst = GNUNET_MST_create (&inject_message,
1087 NULL);
1088 GNUNET_break (GNUNET_OK ==
1089 GNUNET_MST_from_buffer (mst,
1090 buf,
1091 (size_t) fsize,
1092 GNUNET_YES,
1093 GNUNET_NO));
1094 GNUNET_MST_destroy (mst);
1095 GNUNET_free (buf);
1096 GNUNET_break (GNUNET_OK ==
1097 GNUNET_BIO_read_close (rh,
1098 NULL));
1099 GNUNET_free (fn);
1100}
1101
1102
1103/**
1030 * Process statistics requests. 1104 * Process statistics requests.
1031 * 1105 *
1032 * @param cls closure 1106 * @param cls closure
1033 * @param server the initialized server
1034 * @param c configuration to use 1107 * @param c configuration to use
1108 * @param service the initialized service
1035 */ 1109 */
1036static void 1110static void
1037run (void *cls, 1111run (void *cls,
1038 struct GNUNET_SERVER_Handle *server, 1112 const struct GNUNET_CONFIGURATION_Handle *c,
1039 const struct GNUNET_CONFIGURATION_Handle *c) 1113 struct GNUNET_SERVICE_Handle *service)
1040{ 1114{
1041 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1042 {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0},
1043 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0},
1044 {&handle_watch, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, 0},
1045 {NULL, NULL, 0, 0}
1046 };
1047 cfg = c; 1115 cfg = c;
1048 srv = server; 1116 nc = GNUNET_notification_context_create (16);
1049 GNUNET_SERVER_add_handlers (server, 1117 load ();
1050 handlers);
1051 nc = GNUNET_SERVER_notification_context_create (server, 16);
1052 GNUNET_SERVER_disconnect_notify (server,
1053 &handle_client_disconnect,
1054 NULL);
1055 load (server);
1056 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1118 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1057 NULL); 1119 NULL);
1058} 1120}
1059 1121
1060 1122
1061/** 1123/**
1062 * The main function for the statistics service. 1124 * Define "main" method using service macro.
1063 *
1064 * @param argc number of arguments from the command line
1065 * @param argv command line arguments
1066 * @return 0 ok, 1 on error
1067 */ 1125 */
1068int 1126GNUNET_SERVICE_MAIN
1069main (int argc, char *const *argv) 1127("statistics",
1070{ 1128 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1071 return (GNUNET_OK == 1129 &run,
1072 GNUNET_SERVICE_run (argc, argv, "statistics", 1130 &client_connect_cb,
1073 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, 1131 &client_disconnect_cb,
1074 &run, NULL)) ? 0 : 1; 1132 NULL,
1075} 1133 GNUNET_MQ_hd_var_size (set,
1134 GNUNET_MESSAGE_TYPE_STATISTICS_SET,
1135 struct GNUNET_STATISTICS_SetMessage,
1136 NULL),
1137 GNUNET_MQ_hd_var_size (get,
1138 GNUNET_MESSAGE_TYPE_STATISTICS_GET,
1139 struct GNUNET_MessageHeader,
1140 NULL),
1141 GNUNET_MQ_hd_var_size (watch,
1142 GNUNET_MESSAGE_TYPE_STATISTICS_WATCH,
1143 struct GNUNET_MessageHeader,
1144 NULL),
1145 GNUNET_MQ_hd_fixed_size (disconnect,
1146 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT,
1147 struct GNUNET_MessageHeader,
1148 NULL),
1149 GNUNET_MQ_handler_end ());
1150
1076 1151
1077#if defined(LINUX) && defined(__GLIBC__) 1152#if defined(LINUX) && defined(__GLIBC__)
1078#include <malloc.h> 1153#include <malloc.h>
diff --git a/src/statistics/gnunet-statistics.c b/src/statistics/gnunet-statistics.c
index 192a450ac..ed0c3f27d 100644
--- a/src/statistics/gnunet-statistics.c
+++ b/src/statistics/gnunet-statistics.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V. 3 Copyright (C) 2001, 2002, 2004-2007, 2009, 2016 GNUnet e.V.
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
@@ -104,27 +104,35 @@ printer (void *cls,
104 int is_persistent) 104 int is_persistent)
105{ 105{
106 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); 106 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
107 const char * now_str; 107 const char *now_str;
108 108
109 if (quiet == GNUNET_NO) 109 if (quiet == GNUNET_NO)
110 { 110 {
111 if (GNUNET_YES == watch) 111 if (GNUNET_YES == watch)
112 { 112 {
113 now_str = GNUNET_STRINGS_absolute_time_to_string(now); 113 now_str = GNUNET_STRINGS_absolute_time_to_string (now);
114 FPRINTF (stdout, "%24s %s%12s %50s: %16llu \n", 114 FPRINTF (stdout,
115 "%24s %s%12s %50s: %16llu\n",
115 now_str, 116 now_str,
116 is_persistent ? "!" : " ", 117 is_persistent ? "!" : " ",
117 subsystem, _(name), (unsigned long long) value); 118 subsystem,
119 _(name),
120 (unsigned long long) value);
118 } 121 }
119 else 122 else
120 { 123 {
121 FPRINTF (stdout, "%s%12s %50s: %16llu \n", 124 FPRINTF (stdout,
125 "%s%12s %50s: %16llu\n",
122 is_persistent ? "!" : " ", 126 is_persistent ? "!" : " ",
123 subsystem, _(name), (unsigned long long) value); 127 subsystem,
128 _(name),
129 (unsigned long long) value);
124 } 130 }
125 } 131 }
126 else 132 else
127 FPRINTF (stdout, "%llu\n", (unsigned long long) value); 133 FPRINTF (stdout,
134 "%llu\n",
135 (unsigned long long) value);
128 136
129 return GNUNET_OK; 137 return GNUNET_OK;
130} 138}
@@ -183,7 +191,8 @@ shutdown_task (void *cls)
183 GNUNET_STATISTICS_watch_cancel (h, 191 GNUNET_STATISTICS_watch_cancel (h,
184 subsystem, 192 subsystem,
185 name, 193 name,
186 &printer, h)); 194 &printer,
195 h));
187 GNUNET_STATISTICS_destroy (h, 196 GNUNET_STATISTICS_destroy (h,
188 GNUNET_NO); 197 GNUNET_NO);
189 h = NULL; 198 h = NULL;
@@ -205,17 +214,22 @@ main_task (void *cls)
205 { 214 {
206 if (NULL == subsystem) 215 if (NULL == subsystem)
207 { 216 {
208 FPRINTF (stderr, "%s", _("Missing argument: subsystem \n")); 217 FPRINTF (stderr,
218 "%s",
219 _("Missing argument: subsystem \n"));
209 ret = 1; 220 ret = 1;
210 return; 221 return;
211 } 222 }
212 if (NULL == name) 223 if (NULL == name)
213 { 224 {
214 FPRINTF (stderr, "%s", _("Missing argument: name\n")); 225 FPRINTF (stderr,
226 "%s",
227 _("Missing argument: name\n"));
215 ret = 1; 228 ret = 1;
216 return; 229 return;
217 } 230 }
218 h = GNUNET_STATISTICS_create (subsystem, cfg); 231 h = GNUNET_STATISTICS_create (subsystem,
232 cfg);
219 if (NULL == h) 233 if (NULL == h)
220 { 234 {
221 ret = 1; 235 ret = 1;
@@ -243,15 +257,19 @@ main_task (void *cls)
243 subsystem, 257 subsystem,
244 name, 258 name,
245 &cleanup, 259 &cleanup,
246 &printer, h)) ) 260 &printer,
247 cleanup (h, GNUNET_SYSERR); 261 h)) )
262 cleanup (h,
263 GNUNET_SYSERR);
248 } 264 }
249 else 265 else
250 { 266 {
251 if ((NULL == subsystem) || (NULL == name)) 267 if ( (NULL == subsystem) ||
268 (NULL == name) )
252 { 269 {
253 printf (_("No subsystem or name given\n")); 270 printf (_("No subsystem or name given\n"));
254 GNUNET_STATISTICS_destroy (h, GNUNET_NO); 271 GNUNET_STATISTICS_destroy (h,
272 GNUNET_NO);
255 h = NULL; 273 h = NULL;
256 ret = 1; 274 ret = 1;
257 return; 275 return;
@@ -260,7 +278,8 @@ main_task (void *cls)
260 GNUNET_STATISTICS_watch (h, 278 GNUNET_STATISTICS_watch (h,
261 subsystem, 279 subsystem,
262 name, 280 name,
263 &printer, h)) 281 &printer,
282 h))
264 { 283 {
265 fprintf (stderr, 284 fprintf (stderr,
266 _("Failed to initialize watch routine\n")); 285 _("Failed to initialize watch routine\n"));
@@ -275,65 +294,6 @@ main_task (void *cls)
275 294
276 295
277/** 296/**
278 * Function called with th test result to see if the resolver is
279 * running.
280 *
281 * @param cls closure with our configuration
282 * @param result #GNUNET_YES if the resolver is running
283 */
284static void
285resolver_test_task (void *cls,
286 int result)
287{
288 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
289
290 if (GNUNET_YES != result)
291 {
292 FPRINTF (stderr,
293 _("Trying to connect to remote host, but service `%s' is not running\n"),
294 "resolver");
295 return;
296 }
297 /* connect to a remote host */
298 if (0 == remote_port)
299 {
300 if (GNUNET_SYSERR ==
301 GNUNET_CONFIGURATION_get_value_number (cfg, "statistics",
302 "PORT",
303 &remote_port))
304 {
305 FPRINTF (stderr,
306 _("A port is required to connect to host `%s'\n"),
307 remote_host);
308 return;
309 }
310 }
311 else if (65535 <= remote_port)
312 {
313 FPRINTF (stderr,
314 _("A port has to be between 1 and 65535 to connect to host `%s'\n"),
315 remote_host);
316 return;
317 }
318
319 /* Manipulate configuration */
320 GNUNET_CONFIGURATION_set_value_string (cfg,
321 "statistics",
322 "UNIXPATH",
323 "");
324 GNUNET_CONFIGURATION_set_value_string (cfg,
325 "statistics",
326 "HOSTNAME",
327 remote_host);
328 GNUNET_CONFIGURATION_set_value_number (cfg,
329 "statistics",
330 "PORT",
331 remote_port);
332 GNUNET_SCHEDULER_add_now (&main_task, cfg);
333}
334
335
336/**
337 * Main function that will be run by the scheduler. 297 * Main function that will be run by the scheduler.
338 * 298 *
339 * @param cls closure 299 * @param cls closure
@@ -347,24 +307,64 @@ run (void *cls,
347 const char *cfgfile, 307 const char *cfgfile,
348 const struct GNUNET_CONFIGURATION_Handle *cfg) 308 const struct GNUNET_CONFIGURATION_Handle *cfg)
349{ 309{
310 struct GNUNET_CONFIGURATION_Handle *c;
311
312 c = (struct GNUNET_CONFIGURATION_Handle *) cfg;
350 set_value = GNUNET_NO; 313 set_value = GNUNET_NO;
351 if (NULL != args[0]) 314 if (NULL != args[0])
352 { 315 {
353 if (1 != SSCANF (args[0], "%llu", &set_val)) 316 if (1 != SSCANF (args[0],
317 "%llu",
318 &set_val))
354 { 319 {
355 FPRINTF (stderr, _("Invalid argument `%s'\n"), args[0]); 320 FPRINTF (stderr,
321 _("Invalid argument `%s'\n"),
322 args[0]);
356 ret = 1; 323 ret = 1;
357 return; 324 return;
358 } 325 }
359 set_value = GNUNET_YES; 326 set_value = GNUNET_YES;
360 } 327 }
361 if (NULL != remote_host) 328 if (NULL != remote_host)
362 GNUNET_CLIENT_service_test ("resolver", 329 {
363 cfg, 330 if (0 == remote_port)
364 GNUNET_TIME_UNIT_SECONDS, 331 {
365 &resolver_test_task, (void *) cfg); 332 if (GNUNET_SYSERR ==
366 else 333 GNUNET_CONFIGURATION_get_value_number (cfg,
367 GNUNET_SCHEDULER_add_now (&main_task, (void *) cfg); 334 "statistics",
335 "PORT",
336 &remote_port))
337 {
338 FPRINTF (stderr,
339 _("A port is required to connect to host `%s'\n"),
340 remote_host);
341 return;
342 }
343 }
344 else if (65535 <= remote_port)
345 {
346 FPRINTF (stderr,
347 _("A port has to be between 1 and 65535 to connect to host `%s'\n"),
348 remote_host);
349 return;
350 }
351
352 /* Manipulate configuration */
353 GNUNET_CONFIGURATION_set_value_string (c,
354 "statistics",
355 "UNIXPATH",
356 "");
357 GNUNET_CONFIGURATION_set_value_string (c,
358 "statistics",
359 "HOSTNAME",
360 remote_host);
361 GNUNET_CONFIGURATION_set_value_number (c,
362 "statistics",
363 "PORT",
364 remote_port);
365 }
366 GNUNET_SCHEDULER_add_now (&main_task,
367 c);
368} 368}
369 369
370 370
@@ -404,15 +404,20 @@ main (int argc, char *const *argv)
404 }; 404 };
405 remote_port = 0; 405 remote_port = 0;
406 remote_host = NULL; 406 remote_host = NULL;
407 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, 407 if (GNUNET_OK !=
408 &argc, &argv)) 408 GNUNET_STRINGS_get_utf8_args (argc, argv,
409 &argc, &argv))
409 return 2; 410 return 2;
410 411
411 ret = (GNUNET_OK == 412 ret = (GNUNET_OK ==
412 GNUNET_PROGRAM_run (argc, argv, "gnunet-statistics [options [value]]", 413 GNUNET_PROGRAM_run (argc,
414 argv,
415 "gnunet-statistics [options [value]]",
413 gettext_noop 416 gettext_noop
414 ("Print statistics about GNUnet operations."), 417 ("Print statistics about GNUnet operations."),
415 options, &run, NULL)) ? ret : 1; 418 options,
419 &run,
420 NULL)) ? ret : 1;
416 GNUNET_free_non_null (remote_host); 421 GNUNET_free_non_null (remote_host);
417 GNUNET_free ((void*) argv); 422 GNUNET_free ((void*) argv);
418 return ret; 423 return ret;
diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c
index 856873d00..e8aa9cf9c 100644
--- a/src/statistics/statistics_api.c
+++ b/src/statistics/statistics_api.c
@@ -576,16 +576,16 @@ do_destroy (void *cls)
576 576
577 577
578/** 578/**
579 * Handle a #GNUNET_MESSAGE_TYPE_TEST (sic) message. We receive this 579 * Handle a #GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
580 * message at the end of the shutdown when the service confirms that 580 * message. We receive this message at the end of the shutdown when
581 * all data has been written to disk. 581 * the service confirms that all data has been written to disk.
582 * 582 *
583 * @param cls our `struct GNUNET_STATISTICS_Handle *` 583 * @param cls our `struct GNUNET_STATISTICS_Handle *`
584 * @param msg the message 584 * @param msg the message
585 */ 585 */
586static void 586static void
587handle_test (void *cls, 587handle_disconnect_confirm (void *cls,
588 const struct GNUNET_MessageHeader *msg) 588 const struct GNUNET_MessageHeader *msg)
589{ 589{
590 struct GNUNET_STATISTICS_Handle *h = cls; 590 struct GNUNET_STATISTICS_Handle *h = cls;
591 591
@@ -598,7 +598,7 @@ handle_test (void *cls,
598 return; 598 return;
599 } 599 }
600 LOG (GNUNET_ERROR_TYPE_DEBUG, 600 LOG (GNUNET_ERROR_TYPE_DEBUG,
601 "Received TEST message from statistics, can complete disconnect\n"); 601 "Received DISCONNNECT_CONFIRM message from statistics, can complete disconnect\n");
602 if (NULL != h->destroy_task) 602 if (NULL != h->destroy_task)
603 GNUNET_SCHEDULER_cancel (h->destroy_task); 603 GNUNET_SCHEDULER_cancel (h->destroy_task);
604 h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy, 604 h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy,
@@ -653,8 +653,8 @@ static int
653try_connect (struct GNUNET_STATISTICS_Handle *h) 653try_connect (struct GNUNET_STATISTICS_Handle *h)
654{ 654{
655 struct GNUNET_MQ_MessageHandler handlers[] = { 655 struct GNUNET_MQ_MessageHandler handlers[] = {
656 GNUNET_MQ_hd_fixed_size (test, 656 GNUNET_MQ_hd_fixed_size (disconnect_confirm,
657 GNUNET_MESSAGE_TYPE_TEST, 657 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM,
658 struct GNUNET_MessageHeader, 658 struct GNUNET_MessageHeader,
659 h), 659 h),
660 GNUNET_MQ_hd_fixed_size (statistics_end, 660 GNUNET_MQ_hd_fixed_size (statistics_end,
@@ -1032,7 +1032,7 @@ schedule_action (void *cls)
1032 "Notifying service that we are done\n"); 1032 "Notifying service that we are done\n");
1033 h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */ 1033 h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */
1034 env = GNUNET_MQ_msg (hdr, 1034 env = GNUNET_MQ_msg (hdr,
1035 GNUNET_MESSAGE_TYPE_TEST); 1035 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT);
1036 GNUNET_MQ_notify_sent (env, 1036 GNUNET_MQ_notify_sent (env,
1037 &schedule_action, 1037 &schedule_action,
1038 h); 1038 h);