aboutsummaryrefslogtreecommitdiff
path: root/src/statistics/gnunet-service-statistics.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/statistics/gnunet-service-statistics.c')
-rw-r--r--src/statistics/gnunet-service-statistics.c418
1 files changed, 154 insertions, 264 deletions
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c
index 5ce54d768..18905f458 100644
--- a/src/statistics/gnunet-service-statistics.c
+++ b/src/statistics/gnunet-service-statistics.c
@@ -71,7 +71,6 @@ struct WatchEntry
71 * #GNUNET_NO : last_value is n/a, #GNUNET_YES: last_value is valid 71 * #GNUNET_NO : last_value is n/a, #GNUNET_YES: last_value is valid
72 */ 72 */
73 int last_value_set; 73 int last_value_set;
74
75}; 74};
76 75
77 76
@@ -138,7 +137,6 @@ struct StatsEntry
138 * #GNUNET_NO: value is n/a, #GNUNET_YES: value is valid 137 * #GNUNET_NO: value is n/a, #GNUNET_YES: value is valid
139 */ 138 */
140 int set; 139 int set;
141
142}; 140};
143 141
144 142
@@ -173,7 +171,6 @@ struct SubsystemEntry
173 * the end of this struct, do not free(). 171 * the end of this struct, do not free().
174 */ 172 */
175 const char *service; 173 const char *service;
176
177}; 174};
178 175
179 176
@@ -201,7 +198,6 @@ struct ClientEntry
201 * Maximum watch ID used by this client so far. 198 * Maximum watch ID used by this client so far.
202 */ 199 */
203 uint32_t max_wid; 200 uint32_t max_wid;
204
205}; 201};
206 202
207 203
@@ -257,11 +253,10 @@ save ()
257 size_t slen; 253 size_t slen;
258 struct GNUNET_STATISTICS_SetMessage *msg; 254 struct GNUNET_STATISTICS_SetMessage *msg;
259 255
260 if (GNUNET_OK != 256 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
261 GNUNET_CONFIGURATION_get_value_filename (cfg, 257 "STATISTICS",
262 "STATISTICS", 258 "DATABASE",
263 "DATABASE", 259 &fn))
264 &fn))
265 { 260 {
266 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 261 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
267 "STATISTICS", 262 "STATISTICS",
@@ -273,17 +268,12 @@ save ()
273 total = 0; 268 total = 0;
274 while (NULL != (se = sub_head)) 269 while (NULL != (se = sub_head))
275 { 270 {
276 GNUNET_CONTAINER_DLL_remove (sub_head, 271 GNUNET_CONTAINER_DLL_remove (sub_head, sub_tail, se);
277 sub_tail,
278 se);
279 slen = strlen (se->service) + 1; 272 slen = strlen (se->service) + 1;
280 while (NULL != (pos = se->stat_head)) 273 while (NULL != (pos = se->stat_head))
281 { 274 {
282 GNUNET_CONTAINER_DLL_remove (se->stat_head, 275 GNUNET_CONTAINER_DLL_remove (se->stat_head, se->stat_tail, pos);
283 se->stat_tail, 276 if ((pos->persistent) && (NULL != wh))
284 pos);
285 if ( (pos->persistent) &&
286 (NULL != wh) )
287 { 277 {
288 nlen = strlen (pos->name) + 1; 278 nlen = strlen (pos->name) + 1;
289 size = sizeof (struct GNUNET_STATISTICS_SetMessage) + nlen + slen; 279 size = sizeof (struct GNUNET_STATISTICS_SetMessage) + nlen + slen;
@@ -298,19 +288,14 @@ save ()
298 2, 288 2,
299 se->service, 289 se->service,
300 pos->name)); 290 pos->name));
301 msg->flags = htonl (pos->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0); 291 msg->flags =
292 htonl (pos->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0);
302 msg->value = GNUNET_htonll (pos->value); 293 msg->value = GNUNET_htonll (pos->value);
303 if (GNUNET_OK != GNUNET_BIO_write (wh, 294 if (GNUNET_OK != GNUNET_BIO_write (wh, msg, size))
304 msg,
305 size))
306 { 295 {
307 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 296 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn);
308 "write",
309 fn);
310 if (GNUNET_OK != GNUNET_BIO_write_close (wh)) 297 if (GNUNET_OK != GNUNET_BIO_write_close (wh))
311 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 298 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", fn);
312 "close",
313 fn);
314 wh = NULL; 299 wh = NULL;
315 } 300 }
316 else 301 else
@@ -325,17 +310,13 @@ save ()
325 } 310 }
326 if (NULL != wh) 311 if (NULL != wh)
327 { 312 {
328 if (GNUNET_OK != 313 if (GNUNET_OK != GNUNET_BIO_write_close (wh))
329 GNUNET_BIO_write_close (wh)) 314 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", fn);
330 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
331 "close",
332 fn);
333 if (0 == total) 315 if (0 == total)
334 GNUNET_break (0 == 316 GNUNET_break (0 == unlink (fn));
335 UNLINK (fn));
336 else 317 else
337 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 318 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
338 _("Wrote %llu bytes of statistics to `%s'\n"), 319 _ ("Wrote %llu bytes of statistics to `%s'\n"),
339 total, 320 total,
340 fn); 321 fn);
341 } 322 }
@@ -350,37 +331,31 @@ save ()
350 * @param e value to transmit 331 * @param e value to transmit
351 */ 332 */
352static void 333static void
353transmit (struct ClientEntry *ce, 334transmit (struct ClientEntry *ce, const struct StatsEntry *e)
354 const struct StatsEntry *e)
355{ 335{
356 struct GNUNET_MQ_Envelope *env; 336 struct GNUNET_MQ_Envelope *env;
357 struct GNUNET_STATISTICS_ReplyMessage *m; 337 struct GNUNET_STATISTICS_ReplyMessage *m;
358 size_t size; 338 size_t size;
359 339
360 size = strlen (e->subsystem->service) + 1 + 340 size = strlen (e->subsystem->service) + 1 + strlen (e->name) + 1;
361 strlen (e->name) + 1;
362 GNUNET_assert (size < GNUNET_MAX_MESSAGE_SIZE); 341 GNUNET_assert (size < GNUNET_MAX_MESSAGE_SIZE);
363 env = GNUNET_MQ_msg_extra (m, 342 env = GNUNET_MQ_msg_extra (m, size, GNUNET_MESSAGE_TYPE_STATISTICS_VALUE);
364 size,
365 GNUNET_MESSAGE_TYPE_STATISTICS_VALUE);
366 m->uid = htonl (e->uid); 343 m->uid = htonl (e->uid);
367 if (e->persistent) 344 if (e->persistent)
368 m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT); 345 m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT);
369 m->value = GNUNET_htonll (e->value); 346 m->value = GNUNET_htonll (e->value);
370 GNUNET_assert (size == 347 GNUNET_assert (size == GNUNET_STRINGS_buffer_fill ((char *) &m[1],
371 GNUNET_STRINGS_buffer_fill ((char *) &m[1], 348 size,
372 size, 349 2,
373 2, 350 e->subsystem->service,
374 e->subsystem->service, 351 e->name));
375 e->name));
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 "Transmitting value for `%s:%s' (%d): %llu\n", 353 "Transmitting value for `%s:%s' (%d): %llu\n",
378 e->subsystem->service, 354 e->subsystem->service,
379 e->name, 355 e->name,
380 e->persistent, 356 e->persistent,
381 (unsigned long long) e->value); 357 (unsigned long long) e->value);
382 GNUNET_MQ_send (ce->mq, 358 GNUNET_MQ_send (ce->mq, env);
383 env);
384} 359}
385 360
386 361
@@ -394,8 +369,8 @@ transmit (struct ClientEntry *ce,
394 */ 369 */
395static void * 370static void *
396client_connect_cb (void *cls, 371client_connect_cb (void *cls,
397 struct GNUNET_SERVICE_Client *c, 372 struct GNUNET_SERVICE_Client *c,
398 struct GNUNET_MQ_Handle *mq) 373 struct GNUNET_MQ_Handle *mq)
399{ 374{
400 struct ClientEntry *ce; 375 struct ClientEntry *ce;
401 376
@@ -403,8 +378,7 @@ client_connect_cb (void *cls,
403 ce->client = c; 378 ce->client = c;
404 ce->mq = mq; 379 ce->mq = mq;
405 client_count++; 380 client_count++;
406 GNUNET_notification_context_add (nc, 381 GNUNET_notification_context_add (nc, mq);
407 mq);
408 return ce; 382 return ce;
409} 383}
410 384
@@ -417,20 +391,18 @@ client_connect_cb (void *cls,
417 * @return #GNUNET_OK if @a message is well-formed 391 * @return #GNUNET_OK if @a message is well-formed
418 */ 392 */
419static int 393static int
420check_get (void *cls, 394check_get (void *cls, const struct GNUNET_MessageHeader *message)
421 const struct GNUNET_MessageHeader *message)
422{ 395{
423 const char *service; 396 const char *service;
424 const char *name; 397 const char *name;
425 size_t size; 398 size_t size;
426 399
427 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); 400 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
428 if (size != 401 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
429 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 402 size,
430 size, 403 2,
431 2, 404 &service,
432 &service, 405 &name))
433 &name))
434 { 406 {
435 GNUNET_break (0); 407 GNUNET_break (0);
436 return GNUNET_SYSERR; 408 return GNUNET_SYSERR;
@@ -446,8 +418,7 @@ check_get (void *cls,
446 * @param message the actual message 418 * @param message the actual message
447 */ 419 */
448static void 420static void
449handle_get (void *cls, 421handle_get (void *cls, const struct GNUNET_MessageHeader *message)
450 const struct GNUNET_MessageHeader *message)
451{ 422{
452 struct ClientEntry *ce = cls; 423 struct ClientEntry *ce = cls;
453 struct GNUNET_MQ_Envelope *env; 424 struct GNUNET_MQ_Envelope *env;
@@ -462,11 +433,11 @@ handle_get (void *cls,
462 433
463 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); 434 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
464 GNUNET_assert (size == 435 GNUNET_assert (size ==
465 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 436 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
466 size, 437 size,
467 2, 438 2,
468 &service, 439 &service,
469 &name)); 440 &name));
470 slen = strlen (service); 441 slen = strlen (service);
471 nlen = strlen (name); 442 nlen = strlen (name);
472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -475,23 +446,17 @@ handle_get (void *cls,
475 nlen ? name : "*"); 446 nlen ? name : "*");
476 for (se = sub_head; NULL != se; se = se->next) 447 for (se = sub_head; NULL != se; se = se->next)
477 { 448 {
478 if (! ( (0 == slen) || 449 if (! ((0 == slen) || (0 == strcmp (service, se->service))))
479 (0 == strcmp (service, se->service))) )
480 continue; 450 continue;
481 for (pos = se->stat_head; NULL != pos; pos = pos->next) 451 for (pos = se->stat_head; NULL != pos; pos = pos->next)
482 { 452 {
483 if (! ( (0 == nlen) || 453 if (! ((0 == nlen) || (0 == strcmp (name, pos->name))))
484 (0 == strcmp (name,
485 pos->name))) )
486 continue; 454 continue;
487 transmit (ce, 455 transmit (ce, pos);
488 pos);
489 } 456 }
490 } 457 }
491 env = GNUNET_MQ_msg (end, 458 env = GNUNET_MQ_msg (end, GNUNET_MESSAGE_TYPE_STATISTICS_END);
492 GNUNET_MESSAGE_TYPE_STATISTICS_END); 459 GNUNET_MQ_send (ce->mq, env);
493 GNUNET_MQ_send (ce->mq,
494 env);
495 GNUNET_SERVICE_client_continue (ce->client); 460 GNUNET_SERVICE_client_continue (ce->client);
496} 461}
497 462
@@ -519,14 +484,13 @@ notify_change (struct StatsEntry *se)
519 { 484 {
520 pos->last_value_set = GNUNET_YES; 485 pos->last_value_set = GNUNET_YES;
521 } 486 }
522 env = GNUNET_MQ_msg (wvm, 487 env = GNUNET_MQ_msg (wvm, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE);
523 GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); 488 wvm->flags =
524 wvm->flags = htonl (se->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0); 489 htonl (se->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0);
525 wvm->wid = htonl (pos->wid); 490 wvm->wid = htonl (pos->wid);
526 wvm->reserved = htonl (0); 491 wvm->reserved = htonl (0);
527 wvm->value = GNUNET_htonll (se->value); 492 wvm->value = GNUNET_htonll (se->value);
528 GNUNET_MQ_send (pos->ce->mq, 493 GNUNET_MQ_send (pos->ce->mq, env);
529 env);
530 pos->last_value = se->value; 494 pos->last_value = se->value;
531 } 495 }
532} 496}
@@ -541,8 +505,7 @@ notify_change (struct StatsEntry *se)
541 * @return subsystem entry, never NULL (subsystem entry is created if necessary) 505 * @return subsystem entry, never NULL (subsystem entry is created if necessary)
542 */ 506 */
543static struct SubsystemEntry * 507static struct SubsystemEntry *
544find_subsystem_entry (struct ClientEntry *ce, 508find_subsystem_entry (struct ClientEntry *ce, const char *service)
545 const char *service)
546{ 509{
547 size_t slen; 510 size_t slen;
548 struct SubsystemEntry *se; 511 struct SubsystemEntry *se;
@@ -551,13 +514,10 @@ find_subsystem_entry (struct ClientEntry *ce,
551 se = ce->subsystem; 514 se = ce->subsystem;
552 else 515 else
553 se = NULL; 516 se = NULL;
554 if ( (NULL == se) || 517 if ((NULL == se) || (0 != strcmp (service, se->service)))
555 (0 != strcmp (service,
556 se->service)) )
557 { 518 {
558 for (se = sub_head; NULL != se; se = se->next) 519 for (se = sub_head; NULL != se; se = se->next)
559 if (0 == strcmp (service, 520 if (0 == strcmp (service, se->service))
560 se->service))
561 break; 521 break;
562 if (NULL != ce) 522 if (NULL != ce)
563 ce->subsystem = se; 523 ce->subsystem = se;
@@ -568,15 +528,10 @@ find_subsystem_entry (struct ClientEntry *ce,
568 "Allocating new subsystem entry `%s'\n", 528 "Allocating new subsystem entry `%s'\n",
569 service); 529 service);
570 slen = strlen (service) + 1; 530 slen = strlen (service) + 1;
571 se = GNUNET_malloc (sizeof (struct SubsystemEntry) + 531 se = GNUNET_malloc (sizeof (struct SubsystemEntry) + slen);
572 slen); 532 GNUNET_memcpy (&se[1], service, slen);
573 GNUNET_memcpy (&se[1],
574 service,
575 slen);
576 se->service = (const char *) &se[1]; 533 se->service = (const char *) &se[1];
577 GNUNET_CONTAINER_DLL_insert (sub_head, 534 GNUNET_CONTAINER_DLL_insert (sub_head, sub_tail, se);
578 sub_tail,
579 se);
580 if (NULL != ce) 535 if (NULL != ce)
581 ce->subsystem = se; 536 ce->subsystem = se;
582 return se; 537 return se;
@@ -591,13 +546,12 @@ find_subsystem_entry (struct ClientEntry *ce,
591 * @return statistis entry, or NULL if not found 546 * @return statistis entry, or NULL if not found
592 */ 547 */
593static struct StatsEntry * 548static struct StatsEntry *
594find_stat_entry (struct SubsystemEntry *se, 549find_stat_entry (struct SubsystemEntry *se, const char *name)
595 const char *name)
596{ 550{
597 struct StatsEntry *pos; 551 struct StatsEntry *pos;
598 552
599 for (pos = se->stat_head; NULL != pos; pos = pos->next) 553 for (pos = se->stat_head; NULL != pos; pos = pos->next)
600 if (0 == strcmp (name, pos->name)) 554 if (0 == strcmp (name, pos->name))
601 return pos; 555 return pos;
602 return NULL; 556 return NULL;
603} 557}
@@ -611,20 +565,18 @@ find_stat_entry (struct SubsystemEntry *se,
611 * @return #GNUNET_OK if message is well-formed 565 * @return #GNUNET_OK if message is well-formed
612 */ 566 */
613static int 567static int
614check_set (void *cls, 568check_set (void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
615 const struct GNUNET_STATISTICS_SetMessage *msg)
616{ 569{
617 const char *service; 570 const char *service;
618 const char *name; 571 const char *name;
619 size_t msize; 572 size_t msize;
620 573
621 msize = ntohs (msg->header.size) - sizeof (*msg); 574 msize = ntohs (msg->header.size) - sizeof (*msg);
622 if (msize != 575 if (msize != GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
623 GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1], 576 msize,
624 msize, 577 2,
625 2, 578 &service,
626 &service, 579 &name))
627 &name))
628 { 580 {
629 GNUNET_break (0); 581 GNUNET_break (0);
630 return GNUNET_SYSERR; 582 return GNUNET_SYSERR;
@@ -640,8 +592,7 @@ check_set (void *cls,
640 * @param message the actual message 592 * @param message the actual message
641 */ 593 */
642static void 594static void
643handle_set (void *cls, 595handle_set (void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
644 const struct GNUNET_STATISTICS_SetMessage *msg)
645{ 596{
646 struct ClientEntry *ce = cls; 597 struct ClientEntry *ce = cls;
647 const char *service; 598 const char *service;
@@ -659,14 +610,12 @@ handle_set (void *cls,
659 610
660 msize = ntohs (msg->header.size); 611 msize = ntohs (msg->header.size);
661 size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage); 612 size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage);
662 GNUNET_assert (size == 613 GNUNET_assert (size == GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
663 GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1], 614 size,
664 size, 615 2,
665 2, 616 &service,
666 &service, 617 &name));
667 &name)); 618 se = find_subsystem_entry (ce, service);
668 se = find_subsystem_entry (ce,
669 service);
670 flags = ntohl (msg->flags); 619 flags = ntohl (msg->flags);
671 value = GNUNET_ntohll (msg->value); 620 value = GNUNET_ntohll (msg->value);
672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -675,8 +624,7 @@ handle_set (void *cls,
675 name, 624 name,
676 (unsigned int) flags, 625 (unsigned int) flags,
677 (unsigned long long) value); 626 (unsigned long long) value);
678 pos = find_stat_entry (se, 627 pos = find_stat_entry (se, name);
679 name);
680 if (NULL != pos) 628 if (NULL != pos)
681 { 629 {
682 initial_set = 0; 630 initial_set = 0;
@@ -696,8 +644,7 @@ handle_set (void *cls,
696 else 644 else
697 { 645 {
698 changed = (0 != delta); 646 changed = (0 != delta);
699 GNUNET_break ( (delta <= 0) || 647 GNUNET_break ((delta <= 0) || (pos->value + delta > pos->value));
700 (pos->value + delta > pos->value) );
701 pos->value += delta; 648 pos->value += delta;
702 } 649 }
703 } 650 }
@@ -710,12 +657,8 @@ handle_set (void *cls,
710 if (pos != se->stat_head) 657 if (pos != se->stat_head)
711 { 658 {
712 /* move to front for faster setting next time! */ 659 /* move to front for faster setting next time! */
713 GNUNET_CONTAINER_DLL_remove (se->stat_head, 660 GNUNET_CONTAINER_DLL_remove (se->stat_head, se->stat_tail, pos);
714 se->stat_tail, 661 GNUNET_CONTAINER_DLL_insert (se->stat_head, se->stat_tail, pos);
715 pos);
716 GNUNET_CONTAINER_DLL_insert (se->stat_head,
717 se->stat_tail,
718 pos);
719 } 662 }
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
721 "Statistic `%s:%s' updated to value %llu (%d).\n", 664 "Statistic `%s:%s' updated to value %llu (%d).\n",
@@ -723,8 +666,7 @@ handle_set (void *cls,
723 name, 666 name,
724 (unsigned long long) pos->value, 667 (unsigned long long) pos->value,
725 pos->persistent); 668 pos->persistent);
726 if ( (changed) || 669 if ((changed) || (1 == initial_set))
727 (1 == initial_set) )
728 notify_change (pos); 670 notify_change (pos);
729 GNUNET_SERVICE_client_continue (ce->client); 671 GNUNET_SERVICE_client_continue (ce->client);
730 return; 672 return;
@@ -732,13 +674,11 @@ handle_set (void *cls,
732 /* not found, create a new entry */ 674 /* not found, create a new entry */
733 nlen = strlen (name) + 1; 675 nlen = strlen (name) + 1;
734 pos = GNUNET_malloc (sizeof (struct StatsEntry) + nlen); 676 pos = GNUNET_malloc (sizeof (struct StatsEntry) + nlen);
735 GNUNET_memcpy (&pos[1], 677 GNUNET_memcpy (&pos[1], name, nlen);
736 name,
737 nlen);
738 pos->name = (const char *) &pos[1]; 678 pos->name = (const char *) &pos[1];
739 pos->subsystem = se; 679 pos->subsystem = se;
740 if ( (0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE)) || 680 if ((0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE)) ||
741 (0 < (int64_t) GNUNET_ntohll (msg->value)) ) 681 (0 < (int64_t) GNUNET_ntohll (msg->value)))
742 { 682 {
743 pos->value = GNUNET_ntohll (msg->value); 683 pos->value = GNUNET_ntohll (msg->value);
744 pos->set = GNUNET_YES; 684 pos->set = GNUNET_YES;
@@ -749,9 +689,7 @@ handle_set (void *cls,
749 } 689 }
750 pos->uid = uidgen++; 690 pos->uid = uidgen++;
751 pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); 691 pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT));
752 GNUNET_CONTAINER_DLL_insert (se->stat_head, 692 GNUNET_CONTAINER_DLL_insert (se->stat_head, se->stat_tail, pos);
753 se->stat_tail,
754 pos);
755 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
756 "New statistic on `%s:%s' with value %llu created.\n", 694 "New statistic on `%s:%s' with value %llu created.\n",
757 service, 695 service,
@@ -770,20 +708,18 @@ handle_set (void *cls,
770 * @return #GNUNET_OK if message is well-formed 708 * @return #GNUNET_OK if message is well-formed
771 */ 709 */
772static int 710static int
773check_watch (void *cls, 711check_watch (void *cls, const struct GNUNET_MessageHeader *message)
774 const struct GNUNET_MessageHeader *message)
775{ 712{
776 size_t size; 713 size_t size;
777 const char *service; 714 const char *service;
778 const char *name; 715 const char *name;
779 716
780 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); 717 size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
781 if (size != 718 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
782 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 719 size,
783 size, 720 2,
784 2, 721 &service,
785 &service, 722 &name))
786 &name))
787 { 723 {
788 GNUNET_break (0); 724 GNUNET_break (0);
789 return GNUNET_SYSERR; 725 return GNUNET_SYSERR;
@@ -799,8 +735,7 @@ check_watch (void *cls,
799 * @param message the actual message 735 * @param message the actual message
800 */ 736 */
801static void 737static void
802handle_watch (void *cls, 738handle_watch (void *cls, const struct GNUNET_MessageHeader *message)
803 const struct GNUNET_MessageHeader *message)
804{ 739{
805 struct ClientEntry *ce = cls; 740 struct ClientEntry *ce = cls;
806 const char *service; 741 const char *service;
@@ -821,32 +756,25 @@ handle_watch (void *cls,
821 msize = ntohs (message->size); 756 msize = ntohs (message->size);
822 size = msize - sizeof (struct GNUNET_MessageHeader); 757 size = msize - sizeof (struct GNUNET_MessageHeader);
823 GNUNET_assert (size == 758 GNUNET_assert (size ==
824 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], 759 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
825 size, 760 size,
826 2, 761 2,
827 &service, 762 &service,
828 &name)); 763 &name));
829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
830 "Received request to watch statistic on `%s:%s'\n", 765 "Received request to watch statistic on `%s:%s'\n",
831 service, 766 service,
832 name); 767 name);
833 se = find_subsystem_entry (ce, 768 se = find_subsystem_entry (ce, service);
834 service); 769 pos = find_stat_entry (se, name);
835 pos = find_stat_entry (se,
836 name);
837 if (NULL == pos) 770 if (NULL == pos)
838 { 771 {
839 nlen = strlen (name) + 1; 772 nlen = strlen (name) + 1;
840 pos = GNUNET_malloc (sizeof (struct StatsEntry) + 773 pos = GNUNET_malloc (sizeof (struct StatsEntry) + nlen);
841 nlen); 774 GNUNET_memcpy (&pos[1], name, nlen);
842 GNUNET_memcpy (&pos[1],
843 name,
844 nlen);
845 pos->name = (const char *) &pos[1]; 775 pos->name = (const char *) &pos[1];
846 pos->subsystem = se; 776 pos->subsystem = se;
847 GNUNET_CONTAINER_DLL_insert (se->stat_head, 777 GNUNET_CONTAINER_DLL_insert (se->stat_head, se->stat_tail, pos);
848 se->stat_tail,
849 pos);
850 pos->uid = uidgen++; 778 pos->uid = uidgen++;
851 pos->set = GNUNET_NO; 779 pos->set = GNUNET_NO;
852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -859,9 +787,7 @@ handle_watch (void *cls,
859 we->ce = ce; 787 we->ce = ce;
860 we->last_value_set = GNUNET_NO; 788 we->last_value_set = GNUNET_NO;
861 we->wid = ce->max_wid++; 789 we->wid = ce->max_wid++;
862 GNUNET_CONTAINER_DLL_insert (pos->we_head, 790 GNUNET_CONTAINER_DLL_insert (pos->we_head, pos->we_tail, we);
863 pos->we_tail,
864 we);
865 if (0 != pos->value) 791 if (0 != pos->value)
866 notify_change (pos); 792 notify_change (pos);
867 GNUNET_SERVICE_client_continue (ce->client); 793 GNUNET_SERVICE_client_continue (ce->client);
@@ -877,17 +803,14 @@ handle_watch (void *cls,
877 * @param message the actual message 803 * @param message the actual message
878 */ 804 */
879static void 805static void
880handle_disconnect (void *cls, 806handle_disconnect (void *cls, const struct GNUNET_MessageHeader *message)
881 const struct GNUNET_MessageHeader *message)
882{ 807{
883 struct ClientEntry *ce = cls; 808 struct ClientEntry *ce = cls;
884 struct GNUNET_MQ_Envelope *env; 809 struct GNUNET_MQ_Envelope *env;
885 struct GNUNET_MessageHeader *msg; 810 struct GNUNET_MessageHeader *msg;
886 811
887 env = GNUNET_MQ_msg (msg, 812 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM);
888 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM); 813 GNUNET_MQ_send (ce->mq, env);
889 GNUNET_MQ_send (ce->mq,
890 env);
891 GNUNET_SERVICE_client_continue (ce->client); 814 GNUNET_SERVICE_client_continue (ce->client);
892} 815}
893 816
@@ -910,20 +833,14 @@ do_shutdown ()
910 GNUNET_assert (0 == client_count); 833 GNUNET_assert (0 == client_count);
911 while (NULL != (se = sub_head)) 834 while (NULL != (se = sub_head))
912 { 835 {
913 GNUNET_CONTAINER_DLL_remove (sub_head, 836 GNUNET_CONTAINER_DLL_remove (sub_head, sub_tail, se);
914 sub_tail,
915 se);
916 while (NULL != (pos = se->stat_head)) 837 while (NULL != (pos = se->stat_head))
917 { 838 {
918 GNUNET_CONTAINER_DLL_remove (se->stat_head, 839 GNUNET_CONTAINER_DLL_remove (se->stat_head, se->stat_tail, pos);
919 se->stat_tail,
920 pos);
921 while (NULL != (we = pos->we_head)) 840 while (NULL != (we = pos->we_head))
922 { 841 {
923 GNUNET_break (0); 842 GNUNET_break (0);
924 GNUNET_CONTAINER_DLL_remove (pos->we_head, 843 GNUNET_CONTAINER_DLL_remove (pos->we_head, pos->we_tail, we);
925 pos->we_tail,
926 we);
927 GNUNET_free (we); 844 GNUNET_free (we);
928 } 845 }
929 GNUNET_free (pos); 846 GNUNET_free (pos);
@@ -957,8 +874,8 @@ shutdown_task (void *cls)
957 */ 874 */
958static void 875static void
959client_disconnect_cb (void *cls, 876client_disconnect_cb (void *cls,
960 struct GNUNET_SERVICE_Client *client, 877 struct GNUNET_SERVICE_Client *client,
961 void *app_cls) 878 void *app_cls)
962{ 879{
963 struct ClientEntry *ce = app_cls; 880 struct ClientEntry *ce = app_cls;
964 struct WatchEntry *we; 881 struct WatchEntry *we;
@@ -977,16 +894,13 @@ client_disconnect_cb (void *cls,
977 wen = we->next; 894 wen = we->next;
978 if (we->ce != ce) 895 if (we->ce != ce)
979 continue; 896 continue;
980 GNUNET_CONTAINER_DLL_remove (pos->we_head, 897 GNUNET_CONTAINER_DLL_remove (pos->we_head, pos->we_tail, we);
981 pos->we_tail,
982 we);
983 GNUNET_free (we); 898 GNUNET_free (we);
984 } 899 }
985 } 900 }
986 } 901 }
987 GNUNET_free (ce); 902 GNUNET_free (ce);
988 if ( (0 == client_count) && 903 if ((0 == client_count) && (GNUNET_YES == in_shutdown))
989 (GNUNET_YES == in_shutdown) )
990 do_shutdown (); 904 do_shutdown ();
991} 905}
992 906
@@ -1003,23 +917,19 @@ client_disconnect_cb (void *cls,
1003 * #GNUNET_SYSERR to stop further processing with error 917 * #GNUNET_SYSERR to stop further processing with error
1004 */ 918 */
1005static int 919static int
1006inject_message (void *cls, 920inject_message (void *cls, const struct GNUNET_MessageHeader *message)
1007 const struct GNUNET_MessageHeader *message)
1008{ 921{
1009 uint16_t msize = ntohs (message->size); 922 uint16_t msize = ntohs (message->size);
1010 const struct GNUNET_STATISTICS_SetMessage *sm; 923 const struct GNUNET_STATISTICS_SetMessage *sm;
1011 924
1012 sm = (const struct GNUNET_STATISTICS_SetMessage *) message; 925 sm = (const struct GNUNET_STATISTICS_SetMessage *) message;
1013 if ( (sizeof (struct GNUNET_STATISTICS_SetMessage) > msize) || 926 if ((sizeof (struct GNUNET_STATISTICS_SetMessage) > msize) ||
1014 (GNUNET_OK != 927 (GNUNET_OK != check_set (NULL, sm)))
1015 check_set (NULL,
1016 sm)) )
1017 { 928 {
1018 GNUNET_break (0); 929 GNUNET_break (0);
1019 return GNUNET_SYSERR; 930 return GNUNET_SYSERR;
1020 } 931 }
1021 handle_set (NULL, 932 handle_set (NULL, sm);
1022 sm);
1023 return GNUNET_OK; 933 return GNUNET_OK;
1024} 934}
1025 935
@@ -1037,23 +947,19 @@ load ()
1037 char *buf; 947 char *buf;
1038 struct GNUNET_MessageStreamTokenizer *mst; 948 struct GNUNET_MessageStreamTokenizer *mst;
1039 949
1040 if (GNUNET_OK != 950 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1041 GNUNET_CONFIGURATION_get_value_filename (cfg, 951 "STATISTICS",
1042 "STATISTICS", 952 "DATABASE",
1043 "DATABASE", 953 &fn))
1044 &fn))
1045 { 954 {
1046 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 955 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1047 "STATISTICS", 956 "STATISTICS",
1048 "DATABASE"); 957 "DATABASE");
1049 return; 958 return;
1050 } 959 }
1051 if ( (GNUNET_OK != 960 if ((GNUNET_OK !=
1052 GNUNET_DISK_file_size (fn, 961 GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) ||
1053 &fsize, 962 (0 == fsize))
1054 GNUNET_NO,
1055 GNUNET_YES)) ||
1056 (0 == fsize) )
1057 { 963 {
1058 GNUNET_free (fn); 964 GNUNET_free (fn);
1059 return; 965 return;
@@ -1066,39 +972,25 @@ load ()
1066 GNUNET_free (fn); 972 GNUNET_free (fn);
1067 return; 973 return;
1068 } 974 }
1069 if (GNUNET_OK != 975 if (GNUNET_OK != GNUNET_BIO_read (rh, fn, buf, fsize))
1070 GNUNET_BIO_read (rh,
1071 fn,
1072 buf,
1073 fsize))
1074 { 976 {
1075 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 977 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", fn);
1076 "read", 978 GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
1077 fn);
1078 GNUNET_break (GNUNET_OK ==
1079 GNUNET_BIO_read_close (rh,
1080 NULL));
1081 GNUNET_free (buf); 979 GNUNET_free (buf);
1082 GNUNET_free (fn); 980 GNUNET_free (fn);
1083 return; 981 return;
1084 } 982 }
1085 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 983 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1086 _("Loading %llu bytes of statistics from `%s'\n"), 984 _ ("Loading %llu bytes of statistics from `%s'\n"),
1087 (unsigned long long) fsize, 985 (unsigned long long) fsize,
1088 fn); 986 fn);
1089 mst = GNUNET_MST_create (&inject_message, 987 mst = GNUNET_MST_create (&inject_message, NULL);
1090 NULL); 988 GNUNET_break (
1091 GNUNET_break (GNUNET_OK == 989 GNUNET_OK ==
1092 GNUNET_MST_from_buffer (mst, 990 GNUNET_MST_from_buffer (mst, buf, (size_t) fsize, GNUNET_YES, GNUNET_NO));
1093 buf,
1094 (size_t) fsize,
1095 GNUNET_YES,
1096 GNUNET_NO));
1097 GNUNET_MST_destroy (mst); 991 GNUNET_MST_destroy (mst);
1098 GNUNET_free (buf); 992 GNUNET_free (buf);
1099 GNUNET_break (GNUNET_OK == 993 GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
1100 GNUNET_BIO_read_close (rh,
1101 NULL));
1102 GNUNET_free (fn); 994 GNUNET_free (fn);
1103} 995}
1104 996
@@ -1118,38 +1010,37 @@ run (void *cls,
1118 cfg = c; 1010 cfg = c;
1119 nc = GNUNET_notification_context_create (16); 1011 nc = GNUNET_notification_context_create (16);
1120 load (); 1012 load ();
1121 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1013 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1122 NULL);
1123} 1014}
1124 1015
1125 1016
1126/** 1017/**
1127 * Define "main" method using service macro. 1018 * Define "main" method using service macro.
1128 */ 1019 */
1129GNUNET_SERVICE_MAIN 1020GNUNET_SERVICE_MAIN (
1130("statistics", 1021 "statistics",
1131 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, 1022 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1132 &run, 1023 &run,
1133 &client_connect_cb, 1024 &client_connect_cb,
1134 &client_disconnect_cb, 1025 &client_disconnect_cb,
1135 NULL, 1026 NULL,
1136 GNUNET_MQ_hd_var_size (set, 1027 GNUNET_MQ_hd_var_size (set,
1137 GNUNET_MESSAGE_TYPE_STATISTICS_SET, 1028 GNUNET_MESSAGE_TYPE_STATISTICS_SET,
1138 struct GNUNET_STATISTICS_SetMessage, 1029 struct GNUNET_STATISTICS_SetMessage,
1139 NULL), 1030 NULL),
1140 GNUNET_MQ_hd_var_size (get, 1031 GNUNET_MQ_hd_var_size (get,
1141 GNUNET_MESSAGE_TYPE_STATISTICS_GET, 1032 GNUNET_MESSAGE_TYPE_STATISTICS_GET,
1142 struct GNUNET_MessageHeader, 1033 struct GNUNET_MessageHeader,
1143 NULL), 1034 NULL),
1144 GNUNET_MQ_hd_var_size (watch, 1035 GNUNET_MQ_hd_var_size (watch,
1145 GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, 1036 GNUNET_MESSAGE_TYPE_STATISTICS_WATCH,
1146 struct GNUNET_MessageHeader, 1037 struct GNUNET_MessageHeader,
1147 NULL), 1038 NULL),
1148 GNUNET_MQ_hd_fixed_size (disconnect, 1039 GNUNET_MQ_hd_fixed_size (disconnect,
1149 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT, 1040 GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT,
1150 struct GNUNET_MessageHeader, 1041 struct GNUNET_MessageHeader,
1151 NULL), 1042 NULL),
1152 GNUNET_MQ_handler_end ()); 1043 GNUNET_MQ_handler_end ());
1153 1044
1154 1045
1155#if defined(LINUX) && defined(__GLIBC__) 1046#if defined(LINUX) && defined(__GLIBC__)
@@ -1158,8 +1049,7 @@ GNUNET_SERVICE_MAIN
1158/** 1049/**
1159 * MINIMIZE heap size (way below 128k) since this process doesn't need much. 1050 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1160 */ 1051 */
1161void __attribute__ ((constructor)) 1052void __attribute__ ((constructor)) GNUNET_STATISTICS_memory_init ()
1162GNUNET_STATISTICS_memory_init ()
1163{ 1053{
1164 mallopt (M_TRIM_THRESHOLD, 4 * 1024); 1054 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1165 mallopt (M_TOP_PAD, 1 * 1024); 1055 mallopt (M_TOP_PAD, 1 * 1024);