aboutsummaryrefslogtreecommitdiff
path: root/src/statistics
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-07-07 06:27:10 +0000
committerChristian Grothoff <christian@grothoff.org>2010-07-07 06:27:10 +0000
commitac2de52a5de68f6f4f13b7aa01a481869fffc6aa (patch)
tree856c9f0b2f55f8cae99f3c7b3bf22beaecbf58da /src/statistics
parentc1a3c11f8665432d9db6d549c28c0329668e66af (diff)
downloadgnunet-ac2de52a5de68f6f4f13b7aa01a481869fffc6aa.tar.gz
gnunet-ac2de52a5de68f6f4f13b7aa01a481869fffc6aa.zip
hacks from trip
Diffstat (limited to 'src/statistics')
-rw-r--r--src/statistics/gnunet-service-statistics.c332
-rw-r--r--src/statistics/statistics.h39
-rw-r--r--src/statistics/statistics_api.c365
-rw-r--r--src/statistics/test_statistics_api.c37
-rw-r--r--src/statistics/test_statistics_api_data.conf3
5 files changed, 719 insertions, 57 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 */
43struct 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 */
62struct 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 */
42struct StatsEntry 78struct 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 */
93static struct StatsEntry *start; 141static struct StatsEntry *start;
94 142
143static struct ClientEntry *client_head;
144
145static struct ClientEntry *client_tail;
146
147/**
148 * Our notification context.
149 */
150static struct GNUNET_SERVER_NotificationContext *nc;
151
152/**
153 * Counter used to generate unique values.
154 */
155static 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 */
211static void 274static void
212transmit (struct GNUNET_SERVER_TransmitContext *tc, 275transmit (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
319static struct ClientEntry *
320make_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
397static void
398notify_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 */
555static void
556handle_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
429shutdown_task (void *cls, 635shutdown_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 */
675static void
676handle_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,
diff --git a/src/statistics/statistics.h b/src/statistics/statistics.h
index c4a79765a..070a0aba5 100644
--- a/src/statistics/statistics.h
+++ b/src/statistics/statistics.h
@@ -91,4 +91,43 @@ struct GNUNET_STATISTICS_SetMessage
91 91
92}; 92};
93 93
94
95/**
96 * Message transmitted if a watched value changes.
97 */
98struct GNUNET_STATISTICS_WatchValueMessage
99{
100 /**
101 * Type: GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
102 */
103 struct GNUNET_MessageHeader header;
104
105 /**
106 * 0 for absolute value, 1 for relative value; 2 to make persistent
107 * (see GNUNET_STATISTICS_SETFLAG_*).
108 */
109 uint32_t flags GNUNET_PACKED;
110
111 /**
112 * Unique watch identification number (watch
113 * requests are enumerated in the order they
114 * are received, the first request having
115 * a wid of zero).
116 */
117 uint32_t wid GNUNET_PACKED;
118
119 /**
120 * Reserved (always 0).
121 */
122 uint32_t reserved GNUNET_PACKED;
123
124 /**
125 * Value. Note that if this is a relative value, it will
126 * be signed even though the type given here is unsigned.
127 */
128 uint64_t value GNUNET_PACKED;
129
130};
131
132
94#endif 133#endif
diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c
index 9de9f78fd..a5dde0e55 100644
--- a/src/statistics/statistics_api.c
+++ b/src/statistics/statistics_api.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
@@ -25,6 +25,7 @@
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_client_lib.h" 27#include "gnunet_client_lib.h"
28#include "gnunet_constants.h"
28#include "gnunet_container_lib.h" 29#include "gnunet_container_lib.h"
29#include "gnunet_protocols.h" 30#include "gnunet_protocols.h"
30#include "gnunet_server_lib.h" 31#include "gnunet_server_lib.h"
@@ -47,7 +48,37 @@ enum ActionType
47{ 48{
48 ACTION_GET, 49 ACTION_GET,
49 ACTION_SET, 50 ACTION_SET,
50 ACTION_UPDATE 51 ACTION_UPDATE,
52 ACTION_WATCH
53};
54
55
56/**
57 * Entry kept for each value we are watching.
58 */
59struct GNUNET_STATISTICS_WatchEntry
60{
61
62 /**
63 * What subsystem is this action about? (never NULL)
64 */
65 char *subsystem;
66
67 /**
68 * What value is this action about? (never NULL)
69 */
70 char *name;
71
72 /**
73 * Function to call
74 */
75 GNUNET_STATISTICS_Iterator proc;
76
77 /**
78 * Closure for proc
79 */
80 void *proc_cls;
81
51}; 82};
52 83
53 84
@@ -118,7 +149,7 @@ struct GNUNET_STATISTICS_GetHandle
118 int aborted; 149 int aborted;
119 150
120 /** 151 /**
121 * Is this a GET, SET or UPDATE? 152 * Is this a GET, SET, UPDATE or WATCH?
122 */ 153 */
123 enum ActionType type; 154 enum ActionType type;
124 155
@@ -179,14 +210,103 @@ struct GNUNET_STATISTICS_Handle
179 struct GNUNET_STATISTICS_GetHandle *current; 210 struct GNUNET_STATISTICS_GetHandle *current;
180 211
181 /** 212 /**
213 * Array of watch entries.
214 */
215 struct GNUNET_STATISTICS_WatchEntry **watches;
216
217 /**
218 * Task doing exponential back-off trying to reconnect.
219 */
220 GNUNET_SCHEDULER_TaskIdentifier backoff_task;
221
222 /**
223 * Time for next connect retry.
224 */
225 struct GNUNET_TIME_Relative backoff;
226
227 /**
228 * Size of the 'watches' array.
229 */
230 unsigned int watches_size;
231
232 /**
182 * Should this handle auto-destruct once all actions have 233 * Should this handle auto-destruct once all actions have
183 * been processed? 234 * been processed?
184 */ 235 */
185 int do_destroy; 236 int do_destroy;
186 237
238 /**
239 * Are we currently receiving from the service?
240 */
241 int receiving;
242
187}; 243};
188 244
189 245
246
247/**
248 * Schedule the next action to be performed.
249 */
250static void schedule_action (struct GNUNET_STATISTICS_Handle *h);
251
252/**
253 * Try to (re)connect to the statistics service.
254 *
255 * @return GNUNET_YES on success, GNUNET_NO on failure.
256 */
257static int
258try_connect (struct GNUNET_STATISTICS_Handle *ret);
259
260
261static void
262insert_ai (struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_GetHandle *ai)
263{
264 GNUNET_CONTAINER_DLL_insert_after (h->action_head,
265 h->action_tail,
266 h->action_tail,
267 ai);
268 if (h->action_head == ai)
269 schedule_action (h);
270}
271
272
273static void
274schedule_watch_request (struct GNUNET_STATISTICS_Handle *h,
275 struct GNUNET_STATISTICS_WatchEntry *watch)
276{
277
278 struct GNUNET_STATISTICS_GetHandle *ai;
279 size_t slen;
280 size_t nlen;
281 size_t nsize;
282
283 GNUNET_assert (h != NULL);
284 if (GNUNET_YES != try_connect (h))
285 {
286 schedule_action (h);
287 return;
288 }
289 slen = strlen (watch->subsystem) + 1;
290 nlen = strlen (watch->name) + 1;
291 nsize = sizeof (struct GNUNET_MessageHeader) + slen + nlen;
292 if (nsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
293 {
294 GNUNET_break (0);
295 return;
296 }
297 ai = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_GetHandle));
298 ai->sh = h;
299 ai->subsystem = GNUNET_strdup (watch->subsystem);
300 ai->name = GNUNET_strdup (watch->name);
301 ai->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
302 ai->msize = nsize;
303 ai->type = ACTION_WATCH;
304 ai->proc = watch->proc;
305 ai->cls = watch->proc_cls;
306 insert_ai (h, ai);
307}
308
309
190/** 310/**
191 * Try to (re)connect to the statistics service. 311 * Try to (re)connect to the statistics service.
192 * 312 *
@@ -195,11 +315,16 @@ struct GNUNET_STATISTICS_Handle
195static int 315static int
196try_connect (struct GNUNET_STATISTICS_Handle *ret) 316try_connect (struct GNUNET_STATISTICS_Handle *ret)
197{ 317{
318 unsigned int i;
198 if (ret->client != NULL) 319 if (ret->client != NULL)
199 return GNUNET_YES; 320 return GNUNET_YES;
200 ret->client = GNUNET_CLIENT_connect (ret->sched, "statistics", ret->cfg); 321 ret->client = GNUNET_CLIENT_connect (ret->sched, "statistics", ret->cfg);
201 if (ret->client != NULL) 322 if (ret->client != NULL)
202 return GNUNET_YES; 323 {
324 for (i=0;i<ret->watches_size;i++)
325 schedule_watch_request (ret, ret->watches[i]);
326 return GNUNET_YES;
327 }
203#if DEBUG_STATISTICS 328#if DEBUG_STATISTICS
204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
205 _("Failed to connect to statistics service!\n")); 330 _("Failed to connect to statistics service!\n"));
@@ -221,12 +346,6 @@ free_action_item (struct GNUNET_STATISTICS_GetHandle *ai)
221 346
222 347
223/** 348/**
224 * Schedule the next action to be performed.
225 */
226static void schedule_action (struct GNUNET_STATISTICS_Handle *h);
227
228
229/**
230 * GET processing is complete, tell client about it. 349 * GET processing is complete, tell client about it.
231 */ 350 */
232static void 351static void
@@ -259,7 +378,13 @@ process_message (struct GNUNET_STATISTICS_Handle *h,
259 uint16_t size; 378 uint16_t size;
260 379
261 if (h->current->aborted) 380 if (h->current->aborted)
262 return GNUNET_OK; /* don't bother */ 381 {
382#if DEBUG_STATISTICS
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Iteration was aborted, ignoring VALUE\n");
385#endif
386 return GNUNET_OK; /* don't bother */
387 }
263 size = ntohs (msg->size); 388 size = ntohs (msg->size);
264 if (size < sizeof (struct GNUNET_STATISTICS_ReplyMessage)) 389 if (size < sizeof (struct GNUNET_STATISTICS_ReplyMessage))
265 { 390 {
@@ -293,6 +418,42 @@ process_message (struct GNUNET_STATISTICS_Handle *h,
293#endif 418#endif
294 h->current->aborted = GNUNET_YES; 419 h->current->aborted = GNUNET_YES;
295 } 420 }
421#if DEBUG_STATISTICS
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "VALUE processed successfully\n");
424#endif
425 return GNUNET_OK;
426}
427
428
429static int
430process_watch_value (struct GNUNET_STATISTICS_Handle *h,
431 const struct GNUNET_MessageHeader *msg)
432{
433 const struct GNUNET_STATISTICS_WatchValueMessage *wvm;
434 struct GNUNET_STATISTICS_WatchEntry *w;
435 uint32_t wid;
436
437 if (sizeof(struct GNUNET_STATISTICS_WatchValueMessage) !=
438 ntohs (msg->size))
439 {
440 GNUNET_break (0);
441 return GNUNET_SYSERR;
442 }
443 wvm = (const struct GNUNET_STATISTICS_WatchValueMessage *)msg;
444 wid = ntohl (wvm->wid);
445 if (wid >= h->watches_size)
446 {
447 GNUNET_break (0);
448 return GNUNET_SYSERR;
449 }
450 w = h->watches[wid];
451 (void) w->proc (w->proc_cls,
452 w->subsystem,
453 w->name,
454 GNUNET_ntohll (wvm->value),
455 0 !=
456 (ntohl (wvm->flags) & GNUNET_STATISTICS_PERSIST_BIT));
296 return GNUNET_OK; 457 return GNUNET_OK;
297} 458}
298 459
@@ -329,21 +490,53 @@ receive_stats (void *cls, const struct GNUNET_MessageHeader *msg)
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
330 "Received end of statistics marker\n"); 491 "Received end of statistics marker\n");
331#endif 492#endif
493 h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
332 finish (h, GNUNET_OK); 494 finish (h, GNUNET_OK);
495 if (h->watches_size > 0)
496 {
497 GNUNET_CLIENT_receive (h->client,
498 &receive_stats,
499 h,
500 GNUNET_TIME_UNIT_FOREVER_REL);
501 }
502 else
503 {
504 h->receiving = GNUNET_NO;
505 }
333 return; 506 return;
334 case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE: 507 case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE:
335 if (GNUNET_OK == process_message (h, msg)) 508 if (GNUNET_OK == process_message (h, msg))
336 { 509 {
337 /* finally, look for more! */ 510 /* finally, look for more! */
511#if DEBUG_STATISTICS
512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
513 "Processing VALUE done, now reading more\n");
514#endif
338 GNUNET_CLIENT_receive (h->client, 515 GNUNET_CLIENT_receive (h->client,
339 &receive_stats, 516 &receive_stats,
340 h, 517 h,
341 GNUNET_TIME_absolute_get_remaining 518 GNUNET_TIME_absolute_get_remaining
342 (h->current->timeout)); 519 (h->current->timeout));
520 h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
343 return; 521 return;
344 } 522 }
345 GNUNET_break (0); 523 GNUNET_break (0);
346 break; 524 break;
525 case GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE:
526 if (GNUNET_OK ==
527 process_watch_value (h,
528 msg))
529 {
530 h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
531 GNUNET_assert (h->watches_size > 0);
532 GNUNET_CLIENT_receive (h->client,
533 &receive_stats,
534 h,
535 GNUNET_TIME_UNIT_FOREVER_REL);
536 return;
537 }
538 GNUNET_break (0);
539 break;
347 default: 540 default:
348 GNUNET_break (0); 541 GNUNET_break (0);
349 break; 542 break;
@@ -392,15 +585,69 @@ transmit_get (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf)
392 2, 585 2,
393 handle->current->subsystem, 586 handle->current->subsystem,
394 handle->current->name)); 587 handle->current->name));
395 GNUNET_CLIENT_receive (handle->client, 588 if (! handle->receiving)
396 &receive_stats, 589 {
397 handle, 590#if DEBUG_STATISTICS
398 GNUNET_TIME_absolute_get_remaining (handle-> 591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
399 current->timeout)); 592 "Transmission of GET done, now reading response\n");
593#endif
594 handle->receiving = GNUNET_YES;
595 GNUNET_CLIENT_receive (handle->client,
596 &receive_stats,
597 handle,
598 GNUNET_TIME_absolute_get_remaining (handle->
599 current->timeout));
600 }
400 return msize; 601 return msize;
401} 602}
402 603
403 604
605/**
606 * Transmit a WATCH request (and if successful, start to receive
607 * the response).
608 */
609static size_t
610transmit_watch (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf)
611{
612 struct GNUNET_MessageHeader *hdr;
613 size_t slen1;
614 size_t slen2;
615 uint16_t msize;
616
617 if (buf == NULL)
618 {
619 /* timeout / error */
620#if DEBUG_STATISTICS
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
622 "Transmission of request for statistics failed!\n");
623#endif
624 finish (handle, GNUNET_SYSERR);
625 return 0;
626 }
627 slen1 = strlen (handle->current->subsystem) + 1;
628 slen2 = strlen (handle->current->name) + 1;
629 msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader);
630 GNUNET_assert (msize <= size);
631 hdr = (struct GNUNET_MessageHeader *) buf;
632 hdr->size = htons (msize);
633 hdr->type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH);
634 GNUNET_assert (slen1 + slen2 ==
635 GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
636 slen1 + slen2,
637 2,
638 handle->current->subsystem,
639 handle->current->name));
640 if (! handle->receiving)
641 {
642 handle->receiving = GNUNET_YES;
643 GNUNET_CLIENT_receive (handle->client,
644 &receive_stats,
645 handle,
646 GNUNET_TIME_UNIT_FOREVER_REL);
647 }
648 return msize;
649}
650
404 651
405/** 652/**
406 * Transmit a SET/UPDATE request. 653 * Transmit a SET/UPDATE request.
@@ -464,6 +711,9 @@ transmit_action (void *cls, size_t size, void *buf)
464 case ACTION_UPDATE: 711 case ACTION_UPDATE:
465 ret = transmit_set (handle, size, buf); 712 ret = transmit_set (handle, size, buf);
466 break; 713 break;
714 case ACTION_WATCH:
715 ret = transmit_watch (handle, size, buf);
716 break;
467 default: 717 default:
468 ret = 0; 718 ret = 0;
469 GNUNET_break (0); 719 GNUNET_break (0);
@@ -495,6 +745,7 @@ GNUNET_STATISTICS_create (struct GNUNET_SCHEDULER_Handle *sched,
495 ret->sched = sched; 745 ret->sched = sched;
496 ret->cfg = cfg; 746 ret->cfg = cfg;
497 ret->subsystem = GNUNET_strdup (subsystem); 747 ret->subsystem = GNUNET_strdup (subsystem);
748 ret->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
498 try_connect (ret); 749 try_connect (ret);
499 return ret; 750 return ret;
500} 751}
@@ -516,7 +767,11 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
516 struct GNUNET_STATISTICS_GetHandle *next; 767 struct GNUNET_STATISTICS_GetHandle *next;
517 struct GNUNET_STATISTICS_GetHandle *prev; 768 struct GNUNET_STATISTICS_GetHandle *prev;
518 struct GNUNET_TIME_Relative timeout; 769 struct GNUNET_TIME_Relative timeout;
770 int i;
519 771
772 if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task)
773 GNUNET_SCHEDULER_cancel (h->sched,
774 h->backoff_task);
520 if (sync_first) 775 if (sync_first)
521 { 776 {
522 if (h->current != NULL) 777 if (h->current != NULL)
@@ -591,11 +846,30 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
591 GNUNET_CLIENT_disconnect (h->client, GNUNET_YES); 846 GNUNET_CLIENT_disconnect (h->client, GNUNET_YES);
592 h->client = NULL; 847 h->client = NULL;
593 } 848 }
849 for (i=0;i<h->watches_size;i++)
850 {
851 GNUNET_free (h->watches[i]->subsystem);
852 GNUNET_free (h->watches[i]->name);
853 GNUNET_free (h->watches[i]);
854 }
855 GNUNET_array_grow (h->watches,
856 h->watches_size,
857 0);
594 GNUNET_free (h->subsystem); 858 GNUNET_free (h->subsystem);
595 GNUNET_free (h); 859 GNUNET_free (h);
596} 860}
597 861
598 862
863static void
864finish_task (void *cls,
865 const struct GNUNET_SCHEDULER_TaskContext *tc)
866{
867 struct GNUNET_STATISTICS_Handle *h = cls;
868
869 h->backoff_task = GNUNET_SCHEDULER_NO_TASK;
870 finish (h, GNUNET_SYSERR);
871}
872
599 873
600/** 874/**
601 * Schedule the next action to be performed. 875 * Schedule the next action to be performed.
@@ -609,7 +883,13 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h)
609 return; /* action already pending */ 883 return; /* action already pending */
610 if (GNUNET_YES != try_connect (h)) 884 if (GNUNET_YES != try_connect (h))
611 { 885 {
612 finish (h, GNUNET_SYSERR); 886 h->backoff_task = GNUNET_SCHEDULER_add_delayed (h->sched,
887 h->backoff,
888 &finish_task,
889 h);
890 h->backoff = GNUNET_TIME_relative_multiply (h->backoff, 2);
891 h->backoff = GNUNET_TIME_relative_min (h->backoff,
892 GNUNET_CONSTANTS_SERVICE_TIMEOUT);
613 return; 893 return;
614 } 894 }
615 895
@@ -643,19 +923,6 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h)
643 } 923 }
644} 924}
645 925
646
647static void
648insert_ai (struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_GetHandle *ai)
649{
650 GNUNET_CONTAINER_DLL_insert_after (h->action_head,
651 h->action_tail,
652 h->action_tail,
653 ai);
654 if (h->action_head == ai)
655 schedule_action (h);
656}
657
658
659/** 926/**
660 * Get statistic from the peer. 927 * Get statistic from the peer.
661 * 928 *
@@ -742,6 +1009,40 @@ GNUNET_STATISTICS_get_cancel (struct GNUNET_STATISTICS_GetHandle *gh)
742} 1009}
743 1010
744 1011
1012/**
1013 * Watch statistics from the peer (be notified whenever they change).
1014 * Note that the only way to cancel a "watch" request is to destroy
1015 * the statistics handle given as the first argument to this call.
1016 *
1017 * @param handle identification of the statistics service
1018 * @param subsystem limit to the specified subsystem, never NULL
1019 * @param name name of the statistic value, never NULL
1020 * @param proc function to call on each value
1021 * @param proc_cls closure for proc
1022 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1023 */
1024int
1025GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle,
1026 const char *subsystem,
1027 const char *name,
1028 GNUNET_STATISTICS_Iterator proc,
1029 void *proc_cls)
1030{
1031 struct GNUNET_STATISTICS_WatchEntry *w;
1032
1033 w = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_WatchEntry));
1034 w->subsystem = GNUNET_strdup (subsystem);
1035 w->name = GNUNET_strdup (name);
1036 w->proc = proc;
1037 w->proc_cls = proc_cls;
1038 GNUNET_array_append (handle->watches,
1039 handle->watches_size,
1040 w);
1041 schedule_watch_request (handle, w);
1042 return GNUNET_OK;
1043}
1044
1045
745static void 1046static void
746add_setter_action (struct GNUNET_STATISTICS_Handle *h, 1047add_setter_action (struct GNUNET_STATISTICS_Handle *h,
747 const char *name, 1048 const char *name,
@@ -809,7 +1110,8 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h,
809 ai->type = type; 1110 ai->type = type;
810 } 1111 }
811 } 1112 }
812 ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); 1113 ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT);
1114 ai->make_persistent = make_persistent;
813 return; 1115 return;
814 } 1116 }
815 ai = ai->next; 1117 ai = ai->next;
@@ -824,7 +1126,6 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h,
824 ai->value = value; 1126 ai->value = value;
825 ai->type = type; 1127 ai->type = type;
826 insert_ai (h, ai); 1128 insert_ai (h, ai);
827 schedule_action (h);
828} 1129}
829 1130
830 1131
diff --git a/src/statistics/test_statistics_api.c b/src/statistics/test_statistics_api.c
index 378e17d0c..5c55a11a6 100644
--- a/src/statistics/test_statistics_api.c
+++ b/src/statistics/test_statistics_api.c
@@ -29,7 +29,7 @@
29#include "gnunet_scheduler_lib.h" 29#include "gnunet_scheduler_lib.h"
30#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
31 31
32#define VERBOSE GNUNET_NO 32#define DEBUG_STATISTICS GNUNET_NO
33 33
34#define START_SERVICE GNUNET_YES 34#define START_SERVICE GNUNET_YES
35 35
@@ -38,6 +38,11 @@ check_1 (void *cls,
38 const char *subsystem, 38 const char *subsystem,
39 const char *name, uint64_t value, int is_persistent) 39 const char *name, uint64_t value, int is_persistent)
40{ 40{
41 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
42 "Received value %llu for `%s:%s\n",
43 (unsigned long long) value,
44 subsystem,
45 name);
41 GNUNET_assert (0 == strcmp (name, "test-1")); 46 GNUNET_assert (0 == strcmp (name, "test-1"));
42 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); 47 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
43 GNUNET_assert (value == 1); 48 GNUNET_assert (value == 1);
@@ -50,6 +55,11 @@ check_2 (void *cls,
50 const char *subsystem, 55 const char *subsystem,
51 const char *name, uint64_t value, int is_persistent) 56 const char *name, uint64_t value, int is_persistent)
52{ 57{
58 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
59 "Received value %llu for `%s:%s\n",
60 (unsigned long long) value,
61 subsystem,
62 name);
53 GNUNET_assert (0 == strcmp (name, "test-2")); 63 GNUNET_assert (0 == strcmp (name, "test-2"));
54 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); 64 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
55 GNUNET_assert (value == 2); 65 GNUNET_assert (value == 2);
@@ -62,6 +72,11 @@ check_3 (void *cls,
62 const char *subsystem, 72 const char *subsystem,
63 const char *name, uint64_t value, int is_persistent) 73 const char *name, uint64_t value, int is_persistent)
64{ 74{
75 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
76 "Received value %llu for `%s:%s\n",
77 (unsigned long long) value,
78 subsystem,
79 name);
65 GNUNET_assert (0 == strcmp (name, "test-3")); 80 GNUNET_assert (0 == strcmp (name, "test-3"));
66 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); 81 GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
67 GNUNET_assert (value == 3); 82 GNUNET_assert (value == 3);
@@ -85,6 +100,8 @@ static void
85next (void *cls, int success) 100next (void *cls, int success)
86{ 101{
87 GNUNET_assert (success == GNUNET_OK); 102 GNUNET_assert (success == GNUNET_OK);
103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
104 "Issuing GET request\n");
88 GNUNET_break (NULL != 105 GNUNET_break (NULL !=
89 GNUNET_STATISTICS_get (h, NULL, "test-2", 106 GNUNET_STATISTICS_get (h, NULL, "test-2",
90 GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls)); 107 GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls));
@@ -102,6 +119,8 @@ run (void *cls,
102 GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO); 119 GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO);
103 GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO); 120 GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO);
104 GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES); 121 GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES);
122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
123 "Issuing GET request\n");
105 GNUNET_break (NULL != 124 GNUNET_break (NULL !=
106 GNUNET_STATISTICS_get (h, NULL, "test-1", 125 GNUNET_STATISTICS_get (h, NULL, "test-1",
107 GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls)); 126 GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls));
@@ -127,6 +146,11 @@ check ()
127 char *const argv[] = { "test-statistics-api", 146 char *const argv[] = { "test-statistics-api",
128 "-c", 147 "-c",
129 "test_statistics_api_data.conf", 148 "test_statistics_api_data.conf",
149#if DEBUG_STATISTICS
150 "-L", "DEBUG",
151#else
152 "-L", "WARNING",
153#endif
130 NULL 154 NULL
131 }; 155 };
132 struct GNUNET_GETOPT_CommandLineOption options[] = { 156 struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -141,7 +165,7 @@ check ()
141#endif 165#endif
142 "-c", "test_statistics_api_data.conf", NULL); 166 "-c", "test_statistics_api_data.conf", NULL);
143#endif 167#endif
144 GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", 168 GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp",
145 options, &run, &ok); 169 options, &run, &ok);
146#if START_SERVICE 170#if START_SERVICE
147 if (0 != PLIBC_KILL (pid, SIGTERM)) 171 if (0 != PLIBC_KILL (pid, SIGTERM))
@@ -163,7 +187,7 @@ check ()
163#endif 187#endif
164 "-c", "test_statistics_api_data.conf", NULL); 188 "-c", "test_statistics_api_data.conf", NULL);
165#endif 189#endif
166 GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", 190 GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp",
167 options, &run_more, &ok); 191 options, &run_more, &ok);
168#if START_SERVICE 192#if START_SERVICE
169 if (0 != PLIBC_KILL (pid, SIGTERM)) 193 if (0 != PLIBC_KILL (pid, SIGTERM))
@@ -181,6 +205,13 @@ main (int argc, char *argv[])
181{ 205{
182 int ret; 206 int ret;
183 207
208 GNUNET_log_setup ("test_statistics_api",
209#if DEBUG_STATISTICS
210 "DEBUG",
211#else
212 "WARNING",
213#endif
214 NULL);
184 ret = check (); 215 ret = check ();
185 216
186 return ret; 217 return ret;
diff --git a/src/statistics/test_statistics_api_data.conf b/src/statistics/test_statistics_api_data.conf
index 41cfd9596..ba8d4d68e 100644
--- a/src/statistics/test_statistics_api_data.conf
+++ b/src/statistics/test_statistics_api_data.conf
@@ -4,9 +4,12 @@ DEFAULTCONFIG = test_statistics_api_data.conf
4 4
5[statistics] 5[statistics]
6PORT = 22353 6PORT = 22353
7UNIXPATH = /tmp/test-statistics-service-statistics.unix
8DEBUG = YES
7 9
8[arm] 10[arm]
9PORT = 22354 11PORT = 22354
10DEFAULTSERVICES = 12DEFAULTSERVICES =
13UNIXPATH = /tmp/test-statistics-service-arm.unix
11# DEBUG = YES 14# DEBUG = YES
12 15