GNUnet  0.11.x
gnunet-service-statistics.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2012, 2014, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet_bio_lib.h"
28 #include "gnunet_container_lib.h"
29 #include "gnunet_disk_lib.h"
30 #include "gnunet_getopt_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_service_lib.h"
34 #include "gnunet_strings_lib.h"
35 #include "gnunet_time_lib.h"
36 #include "statistics.h"
37 
41 struct WatchEntry
42 {
46  struct WatchEntry *next;
47 
51  struct WatchEntry *prev;
52 
56  struct ClientEntry *ce;
57 
61  uint64_t last_value;
62 
66  uint32_t wid;
67 
73 };
74 
75 
80 struct SubsystemEntry;
81 
82 
86 struct StatsEntry
87 {
91  struct StatsEntry *next;
92 
96  struct StatsEntry *prev;
97 
102 
107  const char *name;
108 
113 
118 
122  uint64_t value;
123 
127  uint32_t uid;
128 
133 
138  int set;
139 };
140 
141 
147 {
152 
157 
162 
167 
172  const char *service;
173 };
174 
175 
179 struct ClientEntry
180 {
184  struct GNUNET_SERVICE_Client *client;
185 
189  struct GNUNET_MQ_Handle *mq;
190 
195 
199  uint32_t max_wid;
200 };
201 
202 
206 static const struct GNUNET_CONFIGURATION_Handle *cfg;
207 
211 static struct SubsystemEntry *sub_head;
212 
216 static struct SubsystemEntry *sub_tail;
217 
221 static unsigned int client_count;
222 
227 
231 static uint32_t uidgen;
232 
236 static int in_shutdown;
237 
238 
242 static void
244 {
245  struct SubsystemEntry *se;
246  struct StatsEntry *pos;
247  char *fn;
248  struct GNUNET_BIO_WriteHandle *wh;
249  uint16_t size;
250  unsigned long long total;
251  size_t nlen;
252  size_t slen;
254 
256  "STATISTICS",
257  "DATABASE",
258  &fn))
259  {
261  "STATISTICS",
262  "DATABASE");
263  return;
264  }
266  wh = GNUNET_BIO_write_open (fn);
267  total = 0;
268  while (NULL != (se = sub_head))
269  {
270  GNUNET_CONTAINER_DLL_remove (sub_head, sub_tail, se);
271  slen = strlen (se->service) + 1;
272  while (NULL != (pos = se->stat_head))
273  {
275  if ((pos->persistent) && (NULL != wh))
276  {
277  nlen = strlen (pos->name) + 1;
278  size = sizeof(struct GNUNET_STATISTICS_SetMessage) + nlen + slen;
279  GNUNET_assert (size < UINT16_MAX);
280  msg = GNUNET_malloc (size);
281 
282  msg->header.size = htons ((uint16_t) size);
284  GNUNET_assert (nlen + slen ==
285  GNUNET_STRINGS_buffer_fill ((char *) &msg[1],
286  nlen + slen,
287  2,
288  se->service,
289  pos->name));
290  msg->flags =
292  msg->value = GNUNET_htonll (pos->value);
293  if (GNUNET_OK != GNUNET_BIO_write (wh, msg, size))
294  {
296  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
298  wh = NULL;
299  }
300  else
301  {
302  total += size;
303  }
304  GNUNET_free (msg);
305  }
306  GNUNET_free (pos);
307  }
308  GNUNET_free (se);
309  }
310  if (NULL != wh)
311  {
312  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
314  if (0 == total)
315  GNUNET_break (0 == unlink (fn));
316  else
318  _ ("Wrote %llu bytes of statistics to `%s'\n"),
319  total,
320  fn);
321  }
323 }
324 
325 
332 static void
333 transmit (struct ClientEntry *ce, const struct StatsEntry *e)
334 {
335  struct GNUNET_MQ_Envelope *env;
337  size_t size;
338 
339  size = strlen (e->subsystem->service) + 1 + strlen (e->name) + 1;
342  m->uid = htonl (e->uid);
343  if (e->persistent)
344  m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT);
345  m->value = GNUNET_htonll (e->value);
346  GNUNET_assert (size == GNUNET_STRINGS_buffer_fill ((char *) &m[1],
347  size,
348  2,
349  e->subsystem->service,
350  e->name));
352  "Transmitting value for `%s:%s' (%d): %llu\n",
353  e->subsystem->service,
354  e->name,
355  e->persistent,
356  (unsigned long long) e->value);
357  GNUNET_MQ_send (ce->mq, env);
358 }
359 
360 
369 static void *
370 client_connect_cb (void *cls,
371  struct GNUNET_SERVICE_Client *c,
372  struct GNUNET_MQ_Handle *mq)
373 {
374  struct ClientEntry *ce;
375 
376  ce = GNUNET_new (struct ClientEntry);
377  ce->client = c;
378  ce->mq = mq;
379  client_count++;
381  return ce;
382 }
383 
384 
392 static int
393 check_get (void *cls, const struct GNUNET_MessageHeader *message)
394 {
395  const char *service;
396  const char *name;
397  size_t size;
398 
399  size = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
400  if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
401  size,
402  2,
403  &service,
404  &name))
405  {
406  GNUNET_break (0);
407  return GNUNET_SYSERR;
408  }
409  return GNUNET_OK;
410 }
411 
412 
419 static void
420 handle_get (void *cls, const struct GNUNET_MessageHeader *message)
421 {
422  struct ClientEntry *ce = cls;
423  struct GNUNET_MQ_Envelope *env;
424  struct GNUNET_MessageHeader *end;
425  const char *service;
426  const char *name;
427  size_t slen;
428  size_t nlen;
429  struct SubsystemEntry *se;
430  struct StatsEntry *pos;
431  size_t size;
432 
433  size = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
434  GNUNET_assert (size ==
435  GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
436  size,
437  2,
438  &service,
439  &name));
440  slen = strlen (service);
441  nlen = strlen (name);
443  "Received request for statistics on `%s:%s'\n",
444  slen ? service : "*",
445  nlen ? name : "*");
446  for (se = sub_head; NULL != se; se = se->next)
447  {
448  if (! ((0 == slen) || (0 == strcmp (service, se->service))))
449  continue;
450  for (pos = se->stat_head; NULL != pos; pos = pos->next)
451  {
452  if (! ((0 == nlen) || (0 == strcmp (name, pos->name))))
453  continue;
454  transmit (ce, pos);
455  }
456  }
458  GNUNET_MQ_send (ce->mq, env);
460 }
461 
462 
468 static void
470 {
471  struct GNUNET_MQ_Envelope *env;
473  struct WatchEntry *pos;
474 
475  for (pos = se->we_head; NULL != pos; pos = pos->next)
476  {
477  if (GNUNET_YES == pos->last_value_set)
478  {
479  if (pos->last_value == se->value)
480  continue;
481  }
482  else
483  {
484  pos->last_value_set = GNUNET_YES;
485  }
487  wvm->flags =
489  wvm->wid = htonl (pos->wid);
490  wvm->reserved = htonl (0);
491  wvm->value = GNUNET_htonll (se->value);
492  GNUNET_MQ_send (pos->ce->mq, env);
493  pos->last_value = se->value;
494  }
495 }
496 
497 
506 static struct SubsystemEntry *
508 {
509  size_t slen;
510  struct SubsystemEntry *se;
511 
512  if (NULL != ce)
513  se = ce->subsystem;
514  else
515  se = NULL;
516  if ((NULL == se) || (0 != strcmp (service, se->service)))
517  {
518  for (se = sub_head; NULL != se; se = se->next)
519  if (0 == strcmp (service, se->service))
520  break;
521  if (NULL != ce)
522  ce->subsystem = se;
523  }
524  if (NULL != se)
525  return se;
527  "Allocating new subsystem entry `%s'\n",
528  service);
529  slen = strlen (service) + 1;
530  se = GNUNET_malloc (sizeof(struct SubsystemEntry) + slen);
531  GNUNET_memcpy (&se[1], service, slen);
532  se->service = (const char *) &se[1];
533  GNUNET_CONTAINER_DLL_insert (sub_head, sub_tail, se);
534  if (NULL != ce)
535  ce->subsystem = se;
536  return se;
537 }
538 
539 
547 static struct StatsEntry *
548 find_stat_entry (struct SubsystemEntry *se, const char *name)
549 {
550  struct StatsEntry *pos;
551 
552  for (pos = se->stat_head; NULL != pos; pos = pos->next)
553  if (0 == strcmp (name, pos->name))
554  return pos;
555  return NULL;
556 }
557 
558 
566 static int
567 check_set (void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
568 {
569  const char *service;
570  const char *name;
571  size_t msize;
572 
573  msize = ntohs (msg->header.size) - sizeof(*msg);
574  if (msize != GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
575  msize,
576  2,
577  &service,
578  &name))
579  {
580  GNUNET_break (0);
581  return GNUNET_SYSERR;
582  }
583  return GNUNET_OK;
584 }
585 
586 
593 static void
594 handle_set (void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
595 {
596  struct ClientEntry *ce = cls;
597  const char *service;
598  const char *name;
599  size_t nlen;
600  uint16_t msize;
601  uint16_t size;
602  struct SubsystemEntry *se;
603  struct StatsEntry *pos;
604  uint32_t flags;
605  uint64_t value;
606  int64_t delta;
607  int changed;
608  int initial_set;
609 
610  msize = ntohs (msg->header.size);
611  size = msize - sizeof(struct GNUNET_STATISTICS_SetMessage);
612  GNUNET_assert (size == GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
613  size,
614  2,
615  &service,
616  &name));
617  se = find_subsystem_entry (ce, service);
618  flags = ntohl (msg->flags);
619  value = GNUNET_ntohll (msg->value);
621  "Received request to update statistic on `%s:%s' (%u) to/by %llu\n",
622  service,
623  name,
624  (unsigned int) flags,
625  (unsigned long long) value);
626  pos = find_stat_entry (se, name);
627  if (NULL != pos)
628  {
629  initial_set = 0;
630  if (0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE))
631  {
632  changed = (pos->value != value);
633  pos->value = value;
634  }
635  else
636  {
637  delta = (int64_t) value;
638  if ((delta < 0) && (pos->value < -delta))
639  {
640  changed = (0 != pos->value);
641  pos->value = 0;
642  }
643  else
644  {
645  changed = (0 != delta);
646  GNUNET_break ((delta <= 0) || (pos->value + delta > pos->value));
647  pos->value += delta;
648  }
649  }
650  if (GNUNET_NO == pos->set)
651  {
652  pos->set = GNUNET_YES;
653  initial_set = 1;
654  }
655  pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT));
656  if (pos != se->stat_head)
657  {
658  /* move to front for faster setting next time! */
661  }
663  "Statistic `%s:%s' updated to value %llu (%d).\n",
664  service,
665  name,
666  (unsigned long long) pos->value,
667  pos->persistent);
668  if ((changed) || (1 == initial_set))
669  notify_change (pos);
671  return;
672  }
673  /* not found, create a new entry */
674  nlen = strlen (name) + 1;
675  pos = GNUNET_malloc (sizeof(struct StatsEntry) + nlen);
676  GNUNET_memcpy (&pos[1], name, nlen);
677  pos->name = (const char *) &pos[1];
678  pos->subsystem = se;
679  if ((0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE)) ||
680  (0 < (int64_t) GNUNET_ntohll (msg->value)))
681  {
682  pos->value = GNUNET_ntohll (msg->value);
683  pos->set = GNUNET_YES;
684  }
685  else
686  {
687  pos->set = GNUNET_NO;
688  }
689  pos->uid = uidgen++;
690  pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT));
693  "New statistic on `%s:%s' with value %llu created.\n",
694  service,
695  name,
696  (unsigned long long) pos->value);
697  if (NULL != ce)
699 }
700 
701 
709 static int
710 check_watch (void *cls, const struct GNUNET_MessageHeader *message)
711 {
712  size_t size;
713  const char *service;
714  const char *name;
715 
716  size = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
717  if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
718  size,
719  2,
720  &service,
721  &name))
722  {
723  GNUNET_break (0);
724  return GNUNET_SYSERR;
725  }
726  return GNUNET_OK;
727 }
728 
729 
736 static void
737 handle_watch (void *cls, const struct GNUNET_MessageHeader *message)
738 {
739  struct ClientEntry *ce = cls;
740  const char *service;
741  const char *name;
742  uint16_t msize;
743  uint16_t size;
744  struct SubsystemEntry *se;
745  struct StatsEntry *pos;
746  struct WatchEntry *we;
747  size_t nlen;
748 
749  if (NULL == nc)
750  {
752  return;
753  }
755  msize = ntohs (message->size);
756  size = msize - sizeof(struct GNUNET_MessageHeader);
757  GNUNET_assert (size ==
758  GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
759  size,
760  2,
761  &service,
762  &name));
764  "Received request to watch statistic on `%s:%s'\n",
765  service,
766  name);
767  se = find_subsystem_entry (ce, service);
768  pos = find_stat_entry (se, name);
769  if (NULL == pos)
770  {
771  nlen = strlen (name) + 1;
772  pos = GNUNET_malloc (sizeof(struct StatsEntry) + nlen);
773  GNUNET_memcpy (&pos[1], name, nlen);
774  pos->name = (const char *) &pos[1];
775  pos->subsystem = se;
777  pos->uid = uidgen++;
778  pos->set = GNUNET_NO;
780  "New statistic on `%s:%s' with value %llu created.\n",
781  service,
782  name,
783  (unsigned long long) pos->value);
784  }
785  we = GNUNET_new (struct WatchEntry);
786  we->ce = ce;
788  we->wid = ce->max_wid++;
790  if (0 != pos->value)
791  notify_change (pos);
793 }
794 
795 
804 static void
805 handle_disconnect (void *cls, const struct GNUNET_MessageHeader *message)
806 {
807  struct ClientEntry *ce = cls;
808  struct GNUNET_MQ_Envelope *env;
809  struct GNUNET_MessageHeader *msg;
810 
812  GNUNET_MQ_send (ce->mq, env);
814 }
815 
816 
820 static void
822 {
823  struct WatchEntry *we;
824  struct StatsEntry *pos;
825  struct SubsystemEntry *se;
826 
827  if (NULL == nc)
828  return;
829  save ();
831  nc = NULL;
833  while (NULL != (se = sub_head))
834  {
835  GNUNET_CONTAINER_DLL_remove (sub_head, sub_tail, se);
836  while (NULL != (pos = se->stat_head))
837  {
839  while (NULL != (we = pos->we_head))
840  {
841  GNUNET_break (0);
843  GNUNET_free (we);
844  }
845  GNUNET_free (pos);
846  }
847  GNUNET_free (se);
848  }
849 }
850 
851 
857 static void
858 shutdown_task (void *cls)
859 {
861  if (0 != client_count)
862  return;
863  do_shutdown ();
864 }
865 
866 
874 static void
876  struct GNUNET_SERVICE_Client *client,
877  void *app_cls)
878 {
879  struct ClientEntry *ce = app_cls;
880  struct WatchEntry *we;
881  struct WatchEntry *wen;
882  struct StatsEntry *pos;
883  struct SubsystemEntry *se;
884 
885  client_count--;
886  for (se = sub_head; NULL != se; se = se->next)
887  {
888  for (pos = se->stat_head; NULL != pos; pos = pos->next)
889  {
890  wen = pos->we_head;
891  while (NULL != (we = wen))
892  {
893  wen = we->next;
894  if (we->ce != ce)
895  continue;
897  GNUNET_free (we);
898  }
899  }
900  }
901  GNUNET_free (ce);
902  if ((0 == client_count) && (GNUNET_YES == in_shutdown))
903  do_shutdown ();
904 }
905 
906 
918 static int
919 inject_message (void *cls, const struct GNUNET_MessageHeader *message)
920 {
921  uint16_t msize = ntohs (message->size);
922  const struct GNUNET_STATISTICS_SetMessage *sm;
923 
924  sm = (const struct GNUNET_STATISTICS_SetMessage *) message;
925  if ((sizeof(struct GNUNET_STATISTICS_SetMessage) > msize) ||
926  (GNUNET_OK != check_set (NULL, sm)))
927  {
928  GNUNET_break (0);
929  return GNUNET_SYSERR;
930  }
931  handle_set (NULL, sm);
932  return GNUNET_OK;
933 }
934 
935 
940 static void
942 {
943  char *fn;
944  struct GNUNET_BIO_ReadHandle *rh;
945  uint64_t fsize;
946  char *buf;
947  struct GNUNET_MessageStreamTokenizer *mst;
948 
950  "STATISTICS",
951  "DATABASE",
952  &fn))
953  {
955  "STATISTICS",
956  "DATABASE");
957  return;
958  }
959  if ((GNUNET_OK !=
960  GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) ||
961  (0 == fsize))
962  {
963  GNUNET_free (fn);
964  return;
965  }
966  buf = GNUNET_malloc (fsize);
967  rh = GNUNET_BIO_read_open (fn);
968  if (! rh)
969  {
970  GNUNET_free (buf);
971  GNUNET_free (fn);
972  return;
973  }
974  if (GNUNET_OK != GNUNET_BIO_read (rh, fn, buf, fsize))
975  {
978  GNUNET_free (buf);
979  GNUNET_free (fn);
980  return;
981  }
983  _ ("Loading %llu bytes of statistics from `%s'\n"),
984  (unsigned long long) fsize,
985  fn);
986  mst = GNUNET_MST_create (&inject_message, NULL);
987  GNUNET_break (
988  GNUNET_OK ==
989  GNUNET_MST_from_buffer (mst, buf, (size_t) fsize, GNUNET_YES, GNUNET_NO));
990  GNUNET_MST_destroy (mst);
991  GNUNET_free (buf);
993  GNUNET_free (fn);
994 }
995 
996 
1004 static void
1005 run (void *cls,
1006  const struct GNUNET_CONFIGURATION_Handle *c,
1008 {
1009  cfg = c;
1011  load ();
1013 }
1014 
1015 
1020  "statistics",
1022  &run,
1025  NULL,
1026  GNUNET_MQ_hd_var_size (set,
1029  NULL),
1030  GNUNET_MQ_hd_var_size (get,
1032  struct GNUNET_MessageHeader,
1033  NULL),
1036  struct GNUNET_MessageHeader,
1037  NULL),
1040  struct GNUNET_MessageHeader,
1041  NULL),
1043 
1044 
1045 #if defined(LINUX) && defined(__GLIBC__)
1046 #include <malloc.h>
1047 
1051 void __attribute__ ((constructor))
1052 GNUNET_STATISTICS_memory_init ()
1053 {
1054  mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1055  mallopt (M_TOP_PAD, 1 * 1024);
1056  malloc_trim (0);
1057 }
1058 
1059 
1060 #endif
1061 
1062 
1063 /* end of gnunet-service-statistics.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static void handle_get(void *cls, const struct GNUNET_MessageHeader *message)
Handle GET-message.
struct StatsEntry * stat_head
Head of list of values kept for this subsystem.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:75
#define GNUNET_MESSAGE_TYPE_STATISTICS_SET
Set a statistical value.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
const char * service
Name of the subsystem this entry is for, allocated at the end of this struct, do not free()...
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
#define GNUNET_MESSAGE_TYPE_STATISTICS_END
Response to a STATISTICS_GET message (end of value stream).
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static void load()
Load persistent values from disk.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct SubsystemEntry * subsystem
Which subsystem is this client writing to (SET/UPDATE)?
uint64_t value
Our value.
struct StatsEntry * prev
This is a linked list.
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH
Watch changes to a statistical value.
Handle to a service.
Definition: service.c:116
static unsigned int client_count
Number of connected clients.
Statistics message.
Definition: statistics.h:40
static int check_get(void *cls, const struct GNUNET_MessageHeader *message)
Check integrity of GET-message.
uint32_t uid
Unique numerical identifier for the value (will not change during the same client-session).
Definition: statistics.h:53
struct StatsEntry * next
This is a linked list.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1300
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
A client disconnected.
static void notify_change(struct StatsEntry *se)
Notify all clients listening about a change to a value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct WatchEntry * we_head
Watch context for changes to this value, or NULL for none.
static void shutdown_task(void *cls)
Task run during shutdown.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
static struct Experiment * e
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
#define GNUNET_NO
Definition: gnunet_common.h:78
Message to set a statistic.
Definition: statistics.h:91
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE
Response to a STATISTICS_GET message (with value).
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
uint32_t flags
0 for absolute value, 1 for relative value; 2 to make persistent (see GNUNET_STATISTICS_SETFLAG_*).
Definition: statistics.h:126
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint32_t reserved
Reserved (always 0).
Definition: statistics.h:139
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static void save()
Write persistent statistics to disk.
#define GNUNET_STATISTICS_SETFLAG_RELATIVE
The value being set is a relative change.
Definition: statistics.h:75
struct WatchEntry * prev
Watch entries are kept in a linked list.
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:160
struct GNUNET_SERVICE_Client * client
Handle identifying the client.
int GNUNET_BIO_read_close(struct GNUNET_BIO_ReadHandle *h, char **emsg)
Close an open file.
Definition: bio.c:119
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Handle to a client that is connected to a service.
Definition: service.c:250
static int in_shutdown
Set to GNUNET_YES if we are shutting down as soon as possible.
struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open(const char *fn)
Open a file for reading.
Definition: bio.c:94
struct SubsystemEntry * next
Subsystems are kept in a DLL.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
int GNUNET_BIO_read(struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: bio.c:144
unsigned int GNUNET_STRINGS_buffer_tokenize(const char *buffer, size_t size, unsigned int count,...)
Given a buffer of a given size, find "count" 0-terminated strings in the buffer and assign the count ...
Definition: strings.c:135
Message transmitted if a watched value changes.
Definition: statistics.h:115
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct WatchEntry * we_tail
Watch context for changes to this value, or NULL for none.
static int inject_message(void *cls, const struct GNUNET_MessageHeader *message)
We&#39;ve read a struct GNUNET_STATISTICS_SetMessage * from disk.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
We keep the statistics organized by subsystem for faster lookup during SET operations.
#define GNUNET_MESSAGE_TYPE_STATISTICS_GET
Get a statistical value(s).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
uint32_t wid
Unique watch number for this client and this watched value.
static char * value
Value of the record to add/remove.
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
Service confirms disconnect and that it is done processing all requests from the client.
Information about one of our clients.
int last_value_set
Is last_value valid GNUNET_NO : last_value is n/a, GNUNET_YES: last_value is valid.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:411
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
static struct SubsystemEntry * sub_tail
Tail of linked list of subsystems with active statistics.
static char * fn
Filename of the unique file.
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
Changes to a watched value.
Handle to a message stream tokenizer.
Definition: mst.c:43
static char buf[2048]
static void disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the peerstore service.
static int check_set(void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
Check format of SET-message.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:85
static void do_shutdown()
Actually perform the shutdown.
size_t GNUNET_STRINGS_buffer_fill(char *buffer, size_t size, unsigned int count,...)
Fill a buffer of the given size with count 0-terminated strings (given as varargs).
Definition: strings.c:65
int persistent
Is this value persistent?
int GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:114
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2407
Handle for buffered writing.
Definition: bio.c:379
GNUNET_SERVICE_MAIN("statistics", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(set, GNUNET_MESSAGE_TYPE_STATISTICS_SET, struct GNUNET_STATISTICS_SetMessage, NULL), GNUNET_MQ_hd_var_size(get, GNUNET_MESSAGE_TYPE_STATISTICS_GET, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_var_size(watch, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(disconnect, GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
static void transmit(struct ClientEntry *ce, const struct StatsEntry *e)
Transmit the given stats value.
static void handle_disconnect(void *cls, const struct GNUNET_MessageHeader *message)
Handle DISCONNECT-message.
uint32_t wid
Unique watch identification number (watch requests are enumerated in the order they are received...
Definition: statistics.h:134
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
uint64_t last_value
Last value we communicated to the client for this watch entry.
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT
Client is done sending service requests and will now disconnect.
static int watch
Watch value continuously.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_MQ_Handle * mq
Queue for transmissions to client.
static void handle_set(void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
Handle SET-message.
static uint32_t uidgen
Counter used to generate unique values.
Entry in the statistics list.
#define GNUNET_STATISTICS_PERSIST_BIT
Flag for the struct GNUNET_STATISTICS_ReplyMessage UID only.
Definition: statistics.h:65
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct ClientEntry * ce
For which client is this watch entry?
static struct GNUNET_TESTBED_BarrierWaitHandle * wh
Our barrier wait handle.
static struct SubsystemEntry * sub_head
Head of linked list of subsystems with active statistics.
int GNUNET_BIO_write_close(struct GNUNET_BIO_WriteHandle *h)
Close an open file for writing.
Definition: bio.c:438
const char * name
Name for the value stored by this entry, allocated at the end of this struct.
int set
Is this value set? GNUNET_NO: value is n/a, GNUNET_YES: value is valid.
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:257
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
static struct GNUNET_NotificationContext * nc
Our notification context.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:121
Handle to a message queue.
Definition: mq.c:85
enum RadiotapType __attribute__
struct StatsEntry * stat_tail
Tail of list of values kept for this subsystem.
static int check_watch(void *cls, const struct GNUNET_MessageHeader *message)
Check integrity of WATCH-message.
configuration data
Definition: configuration.c:85
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:410
const char * name
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_STATISTICS_SET.
Definition: statistics.h:96
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Process statistics requests.
static struct StatsEntry * find_stat_entry(struct SubsystemEntry *se, const char *name)
Find the statistics entry of the given subsystem.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
struct SubsystemEntry * prev
Subsystems are kept in a DLL.
Header for all communications.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:137
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
int GNUNET_BIO_write(struct GNUNET_BIO_WriteHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: bio.c:483
uint32_t uid
Unique ID.
struct SubsystemEntry * subsystem
Subsystem this entry belongs to.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
struct WatchEntry * next
Watch entries are kept in a linked list.
uint64_t value
The value.
Definition: statistics.h:58
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
uint32_t max_wid
Maximum watch ID used by this client so far.
static void handle_watch(void *cls, const struct GNUNET_MessageHeader *message)
Handle WATCH-message.
#define GNUNET_malloc(size)
Wrapper around malloc.
Handle for buffered reading.
Definition: bio.c:53
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
#define GNUNET_STATISTICS_SETFLAG_PERSISTENT
The value being set is to be persistent (note that this bit can be combined with GNUNET_STATISTICS_SE...
Definition: statistics.h:83
#define GNUNET_free(ptr)
Wrapper around free.
static struct SubsystemEntry * find_subsystem_entry(struct ClientEntry *ce, const char *service)
Find the subsystem entry of the given name for the specified client.