diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-09-20 02:28:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-09-20 02:28:01 +0000 |
commit | 6a131ab255bb3419eb0e59a24879556d5b1c75d3 (patch) | |
tree | 3d5a543eb36d2184fbc9d390ecd3c9e092614e13 /src/statistics | |
parent | 102ef991828f70f8a4baa9755be02e5a17a67110 (diff) | |
download | gnunet-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.c | 645 | ||||
-rw-r--r-- | src/statistics/gnunet-statistics.c | 181 | ||||
-rw-r--r-- | src/statistics/statistics_api.c | 18 |
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; | |||
221 | static unsigned int client_count; | 226 | static unsigned int client_count; |
222 | 227 | ||
223 | /** | 228 | /** |
224 | * Handle to our server. | ||
225 | */ | ||
226 | static struct GNUNET_SERVER_Handle *srv; | ||
227 | |||
228 | /** | ||
229 | * Our notification context. | 229 | * Our notification context. |
230 | */ | 230 | */ |
231 | static struct GNUNET_SERVER_NotificationContext *nc; | 231 | static 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 | */ | ||
251 | static int | ||
252 | inject_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 | */ | ||
269 | static void | ||
270 | load (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 | */ |
344 | static void | 247 | static 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 | */ |
448 | static void | 352 | static void |
449 | transmit (struct GNUNET_SERVER_Client *client, | 353 | transmit (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 | */ |
491 | static struct ClientEntry * | 395 | static void * |
492 | make_client_entry (struct GNUNET_SERVER_Client *client) | 396 | client_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 | */ |
523 | static void | 419 | static int |
524 | handle_get (void *cls, | 420 | check_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 | */ | ||
448 | static void | ||
449 | handle_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, | |||
586 | static void | 504 | static void |
587 | notify_change (struct StatsEntry *se) | 505 | notify_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 | */ | ||
613 | static int | ||
614 | check_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 | */ |
697 | static void | 642 | static void |
698 | handle_set (void *cls, | 643 | handle_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 | */ | ||
772 | static int | ||
773 | check_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 | */ |
845 | static void | 801 | static void |
846 | handle_watch (void *cls, | 802 | handle_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 | */ | ||
879 | static void | ||
880 | handle_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 | */ |
987 | static void | 958 | static void |
988 | handle_client_disconnect (void *cls, | 959 | client_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 | */ | ||
1002 | static int | ||
1003 | inject_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 | */ | ||
1028 | static void | ||
1029 | load () | ||
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 | */ |
1036 | static void | 1110 | static void |
1037 | run (void *cls, | 1111 | run (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 | */ |
1068 | int | 1126 | GNUNET_SERVICE_MAIN |
1069 | main (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 | */ | ||
284 | static void | ||
285 | resolver_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 | */ |
586 | static void | 586 | static void |
587 | handle_test (void *cls, | 587 | handle_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 | |||
653 | try_connect (struct GNUNET_STATISTICS_Handle *h) | 653 | try_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); |