GNUnet  0.10.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 {
45  struct WatchEntry *next;
46 
50  struct WatchEntry *prev;
51 
55  struct ClientEntry *ce;
56 
60  uint64_t last_value;
61 
65  uint32_t wid;
66 
72 };
73 
74 
79 struct SubsystemEntry;
80 
81 
85 struct StatsEntry {
89  struct StatsEntry *next;
90 
94  struct StatsEntry *prev;
95 
100 
105  const char *name;
106 
111 
116 
120  uint64_t value;
121 
125  uint32_t uid;
126 
131 
136  int set;
137 };
138 
139 
149 
154 
159 
164 
169  const char *service;
170 };
171 
172 
176 struct ClientEntry {
180  struct GNUNET_SERVICE_Client *client;
181 
185  struct GNUNET_MQ_Handle *mq;
186 
191 
195  uint32_t max_wid;
196 };
197 
198 
202 static const struct GNUNET_CONFIGURATION_Handle *cfg;
203 
207 static struct SubsystemEntry *sub_head;
208 
212 static struct SubsystemEntry *sub_tail;
213 
217 static unsigned int client_count;
218 
223 
227 static uint32_t uidgen;
228 
232 static int in_shutdown;
233 
234 
238 static void
240 {
241  struct SubsystemEntry *se;
242  struct StatsEntry *pos;
243  char *fn;
244  struct GNUNET_BIO_WriteHandle *wh;
245  uint16_t size;
246  unsigned long long total;
247  size_t nlen;
248  size_t slen;
250 
252  "STATISTICS",
253  "DATABASE",
254  &fn))
255  {
257  "STATISTICS",
258  "DATABASE");
259  return;
260  }
262  wh = GNUNET_BIO_write_open(fn);
263  total = 0;
264  while (NULL != (se = sub_head))
265  {
266  GNUNET_CONTAINER_DLL_remove(sub_head, sub_tail, se);
267  slen = strlen(se->service) + 1;
268  while (NULL != (pos = se->stat_head))
269  {
271  if ((pos->persistent) && (NULL != wh))
272  {
273  nlen = strlen(pos->name) + 1;
274  size = sizeof(struct GNUNET_STATISTICS_SetMessage) + nlen + slen;
275  GNUNET_assert(size < UINT16_MAX);
276  msg = GNUNET_malloc(size);
277 
278  msg->header.size = htons((uint16_t)size);
280  GNUNET_assert(nlen + slen ==
281  GNUNET_STRINGS_buffer_fill((char *)&msg[1],
282  nlen + slen,
283  2,
284  se->service,
285  pos->name));
286  msg->flags =
288  msg->value = GNUNET_htonll(pos->value);
289  if (GNUNET_OK != GNUNET_BIO_write(wh, msg, size))
290  {
294  wh = NULL;
295  }
296  else
297  {
298  total += size;
299  }
300  GNUNET_free(msg);
301  }
302  GNUNET_free(pos);
303  }
304  GNUNET_free(se);
305  }
306  if (NULL != wh)
307  {
310  if (0 == total)
311  GNUNET_break(0 == unlink(fn));
312  else
314  _("Wrote %llu bytes of statistics to `%s'\n"),
315  total,
316  fn);
317  }
319 }
320 
321 
328 static void
329 transmit(struct ClientEntry *ce, const struct StatsEntry *e)
330 {
331  struct GNUNET_MQ_Envelope *env;
333  size_t size;
334 
335  size = strlen(e->subsystem->service) + 1 + strlen(e->name) + 1;
338  m->uid = htonl(e->uid);
339  if (e->persistent)
340  m->uid |= htonl(GNUNET_STATISTICS_PERSIST_BIT);
341  m->value = GNUNET_htonll(e->value);
342  GNUNET_assert(size == GNUNET_STRINGS_buffer_fill((char *)&m[1],
343  size,
344  2,
345  e->subsystem->service,
346  e->name));
348  "Transmitting value for `%s:%s' (%d): %llu\n",
349  e->subsystem->service,
350  e->name,
351  e->persistent,
352  (unsigned long long)e->value);
353  GNUNET_MQ_send(ce->mq, env);
354 }
355 
356 
365 static void *
367  struct GNUNET_SERVICE_Client *c,
368  struct GNUNET_MQ_Handle *mq)
369 {
370  struct ClientEntry *ce;
371 
372  ce = GNUNET_new(struct ClientEntry);
373  ce->client = c;
374  ce->mq = mq;
375  client_count++;
377  return ce;
378 }
379 
380 
388 static int
389 check_get(void *cls, const struct GNUNET_MessageHeader *message)
390 {
391  const char *service;
392  const char *name;
393  size_t size;
394 
395  size = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader);
396  if (size != GNUNET_STRINGS_buffer_tokenize((const char *)&message[1],
397  size,
398  2,
399  &service,
400  &name))
401  {
402  GNUNET_break(0);
403  return GNUNET_SYSERR;
404  }
405  return GNUNET_OK;
406 }
407 
408 
415 static void
416 handle_get(void *cls, const struct GNUNET_MessageHeader *message)
417 {
418  struct ClientEntry *ce = cls;
419  struct GNUNET_MQ_Envelope *env;
420  struct GNUNET_MessageHeader *end;
421  const char *service;
422  const char *name;
423  size_t slen;
424  size_t nlen;
425  struct SubsystemEntry *se;
426  struct StatsEntry *pos;
427  size_t size;
428 
429  size = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader);
430  GNUNET_assert(size ==
431  GNUNET_STRINGS_buffer_tokenize((const char *)&message[1],
432  size,
433  2,
434  &service,
435  &name));
436  slen = strlen(service);
437  nlen = strlen(name);
439  "Received request for statistics on `%s:%s'\n",
440  slen ? service : "*",
441  nlen ? name : "*");
442  for (se = sub_head; NULL != se; se = se->next)
443  {
444  if (!((0 == slen) || (0 == strcmp(service, se->service))))
445  continue;
446  for (pos = se->stat_head; NULL != pos; pos = pos->next)
447  {
448  if (!((0 == nlen) || (0 == strcmp(name, pos->name))))
449  continue;
450  transmit(ce, pos);
451  }
452  }
454  GNUNET_MQ_send(ce->mq, env);
456 }
457 
458 
464 static void
466 {
467  struct GNUNET_MQ_Envelope *env;
469  struct WatchEntry *pos;
470 
471  for (pos = se->we_head; NULL != pos; pos = pos->next)
472  {
473  if (GNUNET_YES == pos->last_value_set)
474  {
475  if (pos->last_value == se->value)
476  continue;
477  }
478  else
479  {
480  pos->last_value_set = GNUNET_YES;
481  }
483  wvm->flags =
485  wvm->wid = htonl(pos->wid);
486  wvm->reserved = htonl(0);
487  wvm->value = GNUNET_htonll(se->value);
488  GNUNET_MQ_send(pos->ce->mq, env);
489  pos->last_value = se->value;
490  }
491 }
492 
493 
502 static struct SubsystemEntry *
504 {
505  size_t slen;
506  struct SubsystemEntry *se;
507 
508  if (NULL != ce)
509  se = ce->subsystem;
510  else
511  se = NULL;
512  if ((NULL == se) || (0 != strcmp(service, se->service)))
513  {
514  for (se = sub_head; NULL != se; se = se->next)
515  if (0 == strcmp(service, se->service))
516  break;
517  if (NULL != ce)
518  ce->subsystem = se;
519  }
520  if (NULL != se)
521  return se;
523  "Allocating new subsystem entry `%s'\n",
524  service);
525  slen = strlen(service) + 1;
526  se = GNUNET_malloc(sizeof(struct SubsystemEntry) + slen);
527  GNUNET_memcpy(&se[1], service, slen);
528  se->service = (const char *)&se[1];
529  GNUNET_CONTAINER_DLL_insert(sub_head, sub_tail, se);
530  if (NULL != ce)
531  ce->subsystem = se;
532  return se;
533 }
534 
535 
543 static struct StatsEntry *
544 find_stat_entry(struct SubsystemEntry *se, const char *name)
545 {
546  struct StatsEntry *pos;
547 
548  for (pos = se->stat_head; NULL != pos; pos = pos->next)
549  if (0 == strcmp(name, pos->name))
550  return pos;
551  return NULL;
552 }
553 
554 
562 static int
563 check_set(void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
564 {
565  const char *service;
566  const char *name;
567  size_t msize;
568 
569  msize = ntohs(msg->header.size) - sizeof(*msg);
570  if (msize != GNUNET_STRINGS_buffer_tokenize((const char *)&msg[1],
571  msize,
572  2,
573  &service,
574  &name))
575  {
576  GNUNET_break(0);
577  return GNUNET_SYSERR;
578  }
579  return GNUNET_OK;
580 }
581 
582 
589 static void
590 handle_set(void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
591 {
592  struct ClientEntry *ce = cls;
593  const char *service;
594  const char *name;
595  size_t nlen;
596  uint16_t msize;
597  uint16_t size;
598  struct SubsystemEntry *se;
599  struct StatsEntry *pos;
600  uint32_t flags;
601  uint64_t value;
602  int64_t delta;
603  int changed;
604  int initial_set;
605 
606  msize = ntohs(msg->header.size);
607  size = msize - sizeof(struct GNUNET_STATISTICS_SetMessage);
608  GNUNET_assert(size == GNUNET_STRINGS_buffer_tokenize((const char *)&msg[1],
609  size,
610  2,
611  &service,
612  &name));
613  se = find_subsystem_entry(ce, service);
614  flags = ntohl(msg->flags);
615  value = GNUNET_ntohll(msg->value);
617  "Received request to update statistic on `%s:%s' (%u) to/by %llu\n",
618  service,
619  name,
620  (unsigned int)flags,
621  (unsigned long long)value);
622  pos = find_stat_entry(se, name);
623  if (NULL != pos)
624  {
625  initial_set = 0;
626  if (0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE))
627  {
628  changed = (pos->value != value);
629  pos->value = value;
630  }
631  else
632  {
633  delta = (int64_t)value;
634  if ((delta < 0) && (pos->value < -delta))
635  {
636  changed = (0 != pos->value);
637  pos->value = 0;
638  }
639  else
640  {
641  changed = (0 != delta);
642  GNUNET_break((delta <= 0) || (pos->value + delta > pos->value));
643  pos->value += delta;
644  }
645  }
646  if (GNUNET_NO == pos->set)
647  {
648  pos->set = GNUNET_YES;
649  initial_set = 1;
650  }
651  pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT));
652  if (pos != se->stat_head)
653  {
654  /* move to front for faster setting next time! */
657  }
659  "Statistic `%s:%s' updated to value %llu (%d).\n",
660  service,
661  name,
662  (unsigned long long)pos->value,
663  pos->persistent);
664  if ((changed) || (1 == initial_set))
665  notify_change(pos);
667  return;
668  }
669  /* not found, create a new entry */
670  nlen = strlen(name) + 1;
671  pos = GNUNET_malloc(sizeof(struct StatsEntry) + nlen);
672  GNUNET_memcpy(&pos[1], name, nlen);
673  pos->name = (const char *)&pos[1];
674  pos->subsystem = se;
675  if ((0 == (flags & GNUNET_STATISTICS_SETFLAG_RELATIVE)) ||
676  (0 < (int64_t)GNUNET_ntohll(msg->value)))
677  {
678  pos->value = GNUNET_ntohll(msg->value);
679  pos->set = GNUNET_YES;
680  }
681  else
682  {
683  pos->set = GNUNET_NO;
684  }
685  pos->uid = uidgen++;
686  pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT));
689  "New statistic on `%s:%s' with value %llu created.\n",
690  service,
691  name,
692  (unsigned long long)pos->value);
693  if (NULL != ce)
695 }
696 
697 
705 static int
706 check_watch(void *cls, const struct GNUNET_MessageHeader *message)
707 {
708  size_t size;
709  const char *service;
710  const char *name;
711 
712  size = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader);
713  if (size != GNUNET_STRINGS_buffer_tokenize((const char *)&message[1],
714  size,
715  2,
716  &service,
717  &name))
718  {
719  GNUNET_break(0);
720  return GNUNET_SYSERR;
721  }
722  return GNUNET_OK;
723 }
724 
725 
732 static void
733 handle_watch(void *cls, const struct GNUNET_MessageHeader *message)
734 {
735  struct ClientEntry *ce = cls;
736  const char *service;
737  const char *name;
738  uint16_t msize;
739  uint16_t size;
740  struct SubsystemEntry *se;
741  struct StatsEntry *pos;
742  struct WatchEntry *we;
743  size_t nlen;
744 
745  if (NULL == nc)
746  {
748  return;
749  }
751  msize = ntohs(message->size);
752  size = msize - sizeof(struct GNUNET_MessageHeader);
753  GNUNET_assert(size ==
754  GNUNET_STRINGS_buffer_tokenize((const char *)&message[1],
755  size,
756  2,
757  &service,
758  &name));
760  "Received request to watch statistic on `%s:%s'\n",
761  service,
762  name);
763  se = find_subsystem_entry(ce, service);
764  pos = find_stat_entry(se, name);
765  if (NULL == pos)
766  {
767  nlen = strlen(name) + 1;
768  pos = GNUNET_malloc(sizeof(struct StatsEntry) + nlen);
769  GNUNET_memcpy(&pos[1], name, nlen);
770  pos->name = (const char *)&pos[1];
771  pos->subsystem = se;
773  pos->uid = uidgen++;
774  pos->set = GNUNET_NO;
776  "New statistic on `%s:%s' with value %llu created.\n",
777  service,
778  name,
779  (unsigned long long)pos->value);
780  }
781  we = GNUNET_new(struct WatchEntry);
782  we->ce = ce;
784  we->wid = ce->max_wid++;
786  if (0 != pos->value)
787  notify_change(pos);
789 }
790 
791 
800 static void
801 handle_disconnect(void *cls, const struct GNUNET_MessageHeader *message)
802 {
803  struct ClientEntry *ce = cls;
804  struct GNUNET_MQ_Envelope *env;
805  struct GNUNET_MessageHeader *msg;
806 
808  GNUNET_MQ_send(ce->mq, env);
810 }
811 
812 
816 static void
818 {
819  struct WatchEntry *we;
820  struct StatsEntry *pos;
821  struct SubsystemEntry *se;
822 
823  if (NULL == nc)
824  return;
825  save();
827  nc = NULL;
829  while (NULL != (se = sub_head))
830  {
831  GNUNET_CONTAINER_DLL_remove(sub_head, sub_tail, se);
832  while (NULL != (pos = se->stat_head))
833  {
835  while (NULL != (we = pos->we_head))
836  {
837  GNUNET_break(0);
839  GNUNET_free(we);
840  }
841  GNUNET_free(pos);
842  }
843  GNUNET_free(se);
844  }
845 }
846 
847 
853 static void
854 shutdown_task(void *cls)
855 {
857  if (0 != client_count)
858  return;
859  do_shutdown();
860 }
861 
862 
870 static void
872  struct GNUNET_SERVICE_Client *client,
873  void *app_cls)
874 {
875  struct ClientEntry *ce = app_cls;
876  struct WatchEntry *we;
877  struct WatchEntry *wen;
878  struct StatsEntry *pos;
879  struct SubsystemEntry *se;
880 
881  client_count--;
882  for (se = sub_head; NULL != se; se = se->next)
883  {
884  for (pos = se->stat_head; NULL != pos; pos = pos->next)
885  {
886  wen = pos->we_head;
887  while (NULL != (we = wen))
888  {
889  wen = we->next;
890  if (we->ce != ce)
891  continue;
893  GNUNET_free(we);
894  }
895  }
896  }
897  GNUNET_free(ce);
898  if ((0 == client_count) && (GNUNET_YES == in_shutdown))
899  do_shutdown();
900 }
901 
902 
914 static int
915 inject_message(void *cls, const struct GNUNET_MessageHeader *message)
916 {
917  uint16_t msize = ntohs(message->size);
918  const struct GNUNET_STATISTICS_SetMessage *sm;
919 
920  sm = (const struct GNUNET_STATISTICS_SetMessage *)message;
921  if ((sizeof(struct GNUNET_STATISTICS_SetMessage) > msize) ||
922  (GNUNET_OK != check_set(NULL, sm)))
923  {
924  GNUNET_break(0);
925  return GNUNET_SYSERR;
926  }
927  handle_set(NULL, sm);
928  return GNUNET_OK;
929 }
930 
931 
936 static void
938 {
939  char *fn;
940  struct GNUNET_BIO_ReadHandle *rh;
941  uint64_t fsize;
942  char *buf;
943  struct GNUNET_MessageStreamTokenizer *mst;
944 
946  "STATISTICS",
947  "DATABASE",
948  &fn))
949  {
951  "STATISTICS",
952  "DATABASE");
953  return;
954  }
955  if ((GNUNET_OK !=
956  GNUNET_DISK_file_size(fn, &fsize, GNUNET_NO, GNUNET_YES)) ||
957  (0 == fsize))
958  {
959  GNUNET_free(fn);
960  return;
961  }
962  buf = GNUNET_malloc(fsize);
963  rh = GNUNET_BIO_read_open(fn);
964  if (!rh)
965  {
966  GNUNET_free(buf);
967  GNUNET_free(fn);
968  return;
969  }
970  if (GNUNET_OK != GNUNET_BIO_read(rh, fn, buf, fsize))
971  {
974  GNUNET_free(buf);
975  GNUNET_free(fn);
976  return;
977  }
979  _("Loading %llu bytes of statistics from `%s'\n"),
980  (unsigned long long)fsize,
981  fn);
982  mst = GNUNET_MST_create(&inject_message, NULL);
983  GNUNET_break(
984  GNUNET_OK ==
985  GNUNET_MST_from_buffer(mst, buf, (size_t)fsize, GNUNET_YES, GNUNET_NO));
986  GNUNET_MST_destroy(mst);
987  GNUNET_free(buf);
989  GNUNET_free(fn);
990 }
991 
992 
1000 static void
1001 run(void *cls,
1002  const struct GNUNET_CONFIGURATION_Handle *c,
1004 {
1005  cfg = c;
1007  load();
1009 }
1010 
1011 
1016  "statistics",
1018  &run,
1021  NULL,
1025  NULL),
1028  struct GNUNET_MessageHeader,
1029  NULL),
1032  struct GNUNET_MessageHeader,
1033  NULL),
1036  struct GNUNET_MessageHeader,
1037  NULL),
1039 
1040 
1041 #if defined(LINUX) && defined(__GLIBC__)
1042 #include <malloc.h>
1043 
1047 void __attribute__ ((constructor)) GNUNET_STATISTICS_memory_init()
1048 {
1049  mallopt(M_TRIM_THRESHOLD, 4 * 1024);
1050  mallopt(M_TOP_PAD, 1 * 1024);
1051  malloc_trim(0);
1052 }
1053 #endif
1054 
1055 
1056 /* 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:74
#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:114
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:52
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:1284
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:681
#define GNUNET_NO
Definition: gnunet_common.h:78
Message to set a statistic.
Definition: statistics.h:90
#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:123
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint32_t reserved
Reserved (always 0).
Definition: statistics.h:136
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:74
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:158
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:118
#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:246
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:93
struct SubsystemEntry * next
Subsystems are kept in a DLL.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
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:143
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:113
#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:410
#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:84
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:113
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2394
Handle for buffered writing.
Definition: bio.c:378
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:2315
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:131
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:66
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.
const char * name
Entry in the statistics list.
#define GNUNET_STATISTICS_PERSIST_BIT
Flag for the struct GNUNET_STATISTICS_ReplyMessage UID only.
Definition: statistics.h:64
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:436
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:254
#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:119
Handle to a message queue.
Definition: mq.c:84
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:83
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:408
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_STATISTICS_SET.
Definition: statistics.h:94
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:135
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:351
int GNUNET_BIO_write(struct GNUNET_BIO_WriteHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: bio.c:481
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:57
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
#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:82
#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.