GNUnet  0.19.5
statistics_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2011, 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_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
31 #include "statistics.h"
32 
38 #define SET_TRANSMIT_TIMEOUT GNUNET_TIME_relative_multiply ( \
39  GNUNET_TIME_UNIT_SECONDS, 2)
40 
41 #define LOG(kind, ...) GNUNET_log_from (kind, "statistics-api", __VA_ARGS__)
42 
47 {
52 
57 
62 
67 };
68 
69 
74 {
78  char *subsystem;
79 
83  char *name;
84 
89 
93  void *proc_cls;
94 };
95 
96 
101 {
106 
111 
116 
120  char *subsystem;
121 
125  char *name;
126 
131 
136 
140  void *cls;
141 
146 
150  uint64_t value;
151 
156 
160  int aborted;
161 
165  enum ActionType type;
166 
170  uint16_t msize;
171 };
172 
173 
178 {
182  char *subsystem;
183 
188 
193 
199 
204 
211 
216 
221 
226 
231 
235  uint64_t peak_heap_size;
236 
240  uint64_t peak_rss;
241 
245  unsigned int watches_size;
246 
252 
257 };
258 
259 
264 static void
266 {
267 #if ENABLE_HEAP_STATISTICS
268  uint64_t current_heap_size = 0;
269  uint64_t current_rss = 0;
270 
271  if (GNUNET_NO != h->do_destroy)
272  return;
273 #if HAVE_MALLINFO2
274  {
275  struct mallinfo2 mi;
276 
277  mi = mallinfo2 ();
278  current_heap_size = mi.uordblks + mi.fordblks;
279  }
280 #endif
281 #if HAVE_GETRUSAGE
282  {
283  struct rusage ru;
284 
285  if (0 == getrusage (RUSAGE_SELF, &ru))
286  {
287  current_rss = 1024LL * ru.ru_maxrss;
288  }
289  }
290 #endif
291  if (current_heap_size > h->peak_heap_size)
292  {
293  h->peak_heap_size = current_heap_size;
295  "# peak heap size",
296  current_heap_size,
297  GNUNET_NO);
298  }
299  if (current_rss > h->peak_rss)
300  {
301  h->peak_rss = current_rss;
303  "# peak resident set size",
304  current_rss,
305  GNUNET_NO);
306  }
307 #endif
308 }
309 
310 
316 static void
318 
319 
325 static void
326 schedule_action (void *cls);
327 
328 
336 static void
339 {
341  size_t slen;
342  size_t nlen;
343  size_t nsize;
344 
345  slen = strlen (watch->subsystem) + 1;
346  nlen = strlen (watch->name) + 1;
347  nsize = sizeof(struct GNUNET_MessageHeader) + slen + nlen;
348  if (nsize >= GNUNET_MAX_MESSAGE_SIZE)
349  {
350  GNUNET_break (0);
351  return;
352  }
354  ai->sh = h;
355  ai->subsystem = GNUNET_strdup (watch->subsystem);
356  ai->name = GNUNET_strdup (watch->name);
357  ai->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
358  ai->msize = nsize;
359  ai->type = ACTION_WATCH;
360  ai->proc = watch->proc;
361  ai->cls = watch->proc_cls;
362  GNUNET_CONTAINER_DLL_insert_tail (h->action_head,
363  h->action_tail,
364  ai);
365  schedule_action (h);
366 }
367 
368 
374 static void
376 {
377  GNUNET_free (gh->subsystem);
378  GNUNET_free (gh->name);
379  GNUNET_free (gh);
380 }
381 
382 
388 static void
390 {
391  struct GNUNET_STATISTICS_GetHandle *c;
392 
393  h->receiving = GNUNET_NO;
394  if (NULL != (c = h->current))
395  {
396  h->current = NULL;
397  if ((NULL != c->cont) &&
398  (GNUNET_YES != c->aborted))
399  {
400  c->cont (c->cls,
401  GNUNET_SYSERR);
402  c->cont = NULL;
403  }
404  free_action_item (c);
405  }
406  if (NULL != h->mq)
407  {
409  h->mq = NULL;
410  }
411 }
412 
413 
421 static int
423  const struct GNUNET_STATISTICS_ReplyMessage *smsg)
424 {
425  const char *service;
426  const char *name;
427  uint16_t size;
428 
429  size = ntohs (smsg->header.size);
430  size -= sizeof(struct GNUNET_STATISTICS_ReplyMessage);
431  if (size !=
432  GNUNET_STRINGS_buffer_tokenize ((const char *) &smsg[1],
433  size,
434  2,
435  &service,
436  &name))
437  {
438  GNUNET_break (0);
439  return GNUNET_SYSERR;
440  }
441  return GNUNET_OK;
442 }
443 
444 
452 static void
454  const struct GNUNET_STATISTICS_ReplyMessage *smsg)
455 {
456  struct GNUNET_STATISTICS_Handle *h = cls;
457  const char *service;
458  const char *name;
459  uint16_t size;
460 
461  if (h->current->aborted)
462  return; /* iteration aborted, don't bother */
463 
464  size = ntohs (smsg->header.size);
465  size -= sizeof(struct GNUNET_STATISTICS_ReplyMessage);
466  GNUNET_assert (size ==
467  GNUNET_STRINGS_buffer_tokenize ((const char *) &smsg[1],
468  size,
469  2,
470  &service,
471  &name));
473  "Received valid statistic on `%s:%s': %llu\n",
474  service, name,
475  (unsigned long long) GNUNET_ntohll (smsg->value));
476  if (GNUNET_OK !=
477  h->current->proc (h->current->cls,
478  service,
479  name,
480  GNUNET_ntohll (smsg->value),
481  (0 !=
482  (ntohl (smsg->uid) & GNUNET_STATISTICS_PERSIST_BIT)) ))
483  {
485  "Processing of remaining statistics aborted by client.\n");
486  h->current->aborted = GNUNET_YES;
487  }
488 }
489 
490 
497 static void
499  const struct
501 {
502  struct GNUNET_STATISTICS_Handle *h = cls;
504  uint32_t wid;
505 
506  GNUNET_break (0 == ntohl (wvm->reserved));
507  wid = ntohl (wvm->wid);
508  if (wid >= h->watches_size)
509  {
510  do_disconnect (h);
511  reconnect_later (h);
512  return;
513  }
514  w = h->watches[wid];
515  if (NULL == w)
516  return;
517  (void) w->proc (w->proc_cls,
518  w->subsystem,
519  w->name,
520  GNUNET_ntohll (wvm->value),
521  0 != (ntohl (wvm->flags) & GNUNET_STATISTICS_PERSIST_BIT));
522 }
523 
524 
533 static void
534 mq_error_handler (void *cls,
535  enum GNUNET_MQ_Error error)
536 {
537  struct GNUNET_STATISTICS_Handle *h = cls;
538 
539  if (GNUNET_NO != h->do_destroy)
540  {
541  h->do_destroy = GNUNET_NO;
542  if (NULL != h->destroy_task)
543  {
544  GNUNET_SCHEDULER_cancel (h->destroy_task);
545  h->destroy_task = NULL;
546  }
548  GNUNET_NO);
549  return;
550  }
551  do_disconnect (h);
552  reconnect_later (h);
553 }
554 
555 
561 static void
562 do_destroy (void *cls)
563 {
564  struct GNUNET_STATISTICS_Handle *h = cls;
565 
566  h->destroy_task = NULL;
567  h->do_destroy = GNUNET_NO;
569  "Running final destruction\n");
571  GNUNET_NO);
572 }
573 
574 
583 static void
585  const struct GNUNET_MessageHeader *msg)
586 {
587  struct GNUNET_STATISTICS_Handle *h = cls;
588 
589  if (GNUNET_SYSERR != h->do_destroy)
590  {
591  /* not in shutdown, why do we get 'TEST'? */
592  GNUNET_break (0);
593  do_disconnect (h);
594  reconnect_later (h);
595  return;
596  }
598  "Received DISCONNNECT_CONFIRM message from statistics, can complete disconnect\n");
599  if (NULL != h->destroy_task)
600  GNUNET_SCHEDULER_cancel (h->destroy_task);
601  h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy,
602  h);
603 }
604 
605 
614 static void
616  const struct GNUNET_MessageHeader *msg)
617 {
618  struct GNUNET_STATISTICS_Handle *h = cls;
619  struct GNUNET_STATISTICS_GetHandle *c;
620 
622  "Received end of statistics marker\n");
623  if (NULL == (c = h->current))
624  {
625  GNUNET_break (0);
626  do_disconnect (h);
627  reconnect_later (h);
628  return;
629  }
630  h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
631  h->current = NULL;
632  schedule_action (h);
633  if (NULL != c->cont)
634  {
635  c->cont (c->cls,
636  GNUNET_OK);
637  c->cont = NULL;
638  }
639  free_action_item (c);
640 }
641 
642 
649 static int
651 {
653  GNUNET_MQ_hd_fixed_size (disconnect_confirm,
655  struct GNUNET_MessageHeader,
656  h),
657  GNUNET_MQ_hd_fixed_size (statistics_end,
659  struct GNUNET_MessageHeader,
660  h),
661  GNUNET_MQ_hd_var_size (statistics_value,
664  h),
665  GNUNET_MQ_hd_fixed_size (statistics_watch_value,
668  h),
670  };
672  struct GNUNET_STATISTICS_GetHandle *gn;
673 
674  if (NULL != h->backoff_task)
675  return GNUNET_NO;
676  if (NULL != h->mq)
677  return GNUNET_YES;
679  "statistics",
680  handlers,
682  h);
683  if (NULL == h->mq)
684  {
686  "Failed to connect to statistics service!\n");
687  return GNUNET_NO;
688  }
689  gn = h->action_head;
690  while (NULL != (gh = gn))
691  {
692  gn = gh->next;
693  if (gh->type == ACTION_WATCH)
694  {
695  GNUNET_CONTAINER_DLL_remove (h->action_head,
696  h->action_tail,
697  gh);
699  }
700  }
701  for (unsigned int i = 0; i < h->watches_size; i++)
702  if (NULL != h->watches[i])
704  h->watches[i]);
705  return GNUNET_YES;
706 }
707 
708 
714 static void
716 {
717  struct GNUNET_STATISTICS_Handle *h = cls;
718 
719  h->backoff_task = NULL;
720  schedule_action (h);
721 }
722 
723 
729 static void
731 {
732  int loss;
734 
735  GNUNET_assert (NULL == h->backoff_task);
736  if (GNUNET_YES == h->do_destroy)
737  {
738  /* So we are shutting down and the service is not reachable.
739  * Chances are that it's down for good and we are not going to connect to
740  * it anymore.
741  * Give up and don't sync the rest of the data.
742  */loss = GNUNET_NO;
743  for (gh = h->action_head; NULL != gh; gh = gh->next)
744  if ((gh->make_persistent) &&
745  (ACTION_SET == gh->type))
746  loss = GNUNET_YES;
747  if (GNUNET_YES == loss)
749  _ ("Could not save some persistent statistics\n"));
750  if (NULL != h->destroy_task)
751  GNUNET_SCHEDULER_cancel (h->destroy_task);
752  h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy,
753  h);
754  return;
755  }
756  h->backoff_task
757  = GNUNET_SCHEDULER_add_delayed (h->backoff,
759  h);
760  h->backoff = GNUNET_TIME_STD_BACKOFF (h->backoff);
761 }
762 
763 
770 static void
772 {
773  struct GNUNET_STATISTICS_GetHandle *c;
774  struct GNUNET_MessageHeader *hdr;
775  struct GNUNET_MQ_Envelope *env;
776  size_t slen1;
777  size_t slen2;
778 
779  GNUNET_assert (NULL != (c = handle->current));
780  slen1 = strlen (c->subsystem) + 1;
781  slen2 = strlen (c->name) + 1;
782  env = GNUNET_MQ_msg_extra (hdr,
783  slen1 + slen2,
785  GNUNET_assert (slen1 + slen2 ==
786  GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
787  slen1 + slen2,
788  2,
789  c->subsystem,
790  c->name));
793  handle);
795  env);
796 }
797 
798 
805 static void
807 {
808  struct GNUNET_MessageHeader *hdr;
809  struct GNUNET_MQ_Envelope *env;
810  size_t slen1;
811  size_t slen2;
812 
814  "Transmitting watch request for `%s'\n",
815  handle->current->name);
816  slen1 = strlen (handle->current->subsystem) + 1;
817  slen2 = strlen (handle->current->name) + 1;
818  env = GNUNET_MQ_msg_extra (hdr,
819  slen1 + slen2,
821  GNUNET_assert (slen1 + slen2 ==
822  GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
823  slen1 + slen2,
824  2,
825  handle->current->subsystem,
826  handle->current->name));
829  handle);
831  env);
832  GNUNET_assert (NULL == handle->current->cont);
833  free_action_item (handle->current);
834  handle->current = NULL;
836 }
837 
838 
844 static void
846 {
848  struct GNUNET_MQ_Envelope *env;
849  size_t slen;
850  size_t nlen;
851 
852  slen = strlen (handle->current->subsystem) + 1;
853  nlen = strlen (handle->current->name) + 1;
855  slen + nlen,
857  r->flags = 0;
858  r->value = GNUNET_htonll (handle->current->value);
859  if (handle->current->make_persistent)
861  if (handle->current->type == ACTION_UPDATE)
863  GNUNET_assert (slen + nlen ==
864  GNUNET_STRINGS_buffer_fill ((char *) &r[1],
865  slen + nlen,
866  2,
867  handle->current->subsystem,
868  handle->current->name));
869  GNUNET_assert (NULL == handle->current->cont);
870  free_action_item (handle->current);
871  handle->current = NULL;
875  handle);
877  env);
878 }
879 
880 
890  const struct GNUNET_CONFIGURATION_Handle *cfg)
891 {
892  struct GNUNET_STATISTICS_Handle *h;
893 
894  if (GNUNET_YES ==
896  "statistics",
897  "DISABLE"))
898  return NULL;
900  h->cfg = cfg;
901  h->subsystem = GNUNET_strdup (subsystem);
902  h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
903  return h;
904 }
905 
906 
915 void
917  int sync_first)
918 {
919  struct GNUNET_STATISTICS_GetHandle *pos;
921 
922  if (NULL == h)
923  return;
924  GNUNET_assert (GNUNET_NO == h->do_destroy); /* Don't call twice. */
925  if ((sync_first) &&
926  (NULL != h->mq) &&
927  (0 != GNUNET_MQ_get_length (h->mq)))
928  {
929  if ((NULL != h->current) &&
930  (ACTION_GET == h->current->type))
931  h->current->aborted = GNUNET_YES;
932  next = h->action_head;
933  while (NULL != (pos = next))
934  {
935  next = pos->next;
936  if ((ACTION_GET == pos->type) ||
937  (ACTION_WATCH == pos->type))
938  {
939  GNUNET_CONTAINER_DLL_remove (h->action_head,
940  h->action_tail,
941  pos);
942  free_action_item (pos);
943  }
944  }
945  h->do_destroy = GNUNET_YES;
946  schedule_action (h);
947  GNUNET_assert (NULL == h->destroy_task);
948  h->destroy_task
950  5),
951  &do_destroy,
952  h);
954  "Deferring destruction\n");
955  return; /* do not finish destruction just yet */
956  }
957  /* do clean up all */
959  "Cleaning all up\n");
960  while (NULL != (pos = h->action_head))
961  {
962  GNUNET_CONTAINER_DLL_remove (h->action_head,
963  h->action_tail,
964  pos);
965  free_action_item (pos);
966  }
967  do_disconnect (h);
968  if (NULL != h->backoff_task)
969  {
970  GNUNET_SCHEDULER_cancel (h->backoff_task);
971  h->backoff_task = NULL;
972  }
973  if (NULL != h->destroy_task)
974  {
975  GNUNET_break (0);
976  GNUNET_SCHEDULER_cancel (h->destroy_task);
977  h->destroy_task = NULL;
978  }
979  for (unsigned int i = 0; i < h->watches_size; i++)
980  {
981  if (NULL == h->watches[i])
982  continue;
983  GNUNET_free (h->watches[i]->subsystem);
984  GNUNET_free (h->watches[i]->name);
985  GNUNET_free (h->watches[i]);
986  }
987  GNUNET_array_grow (h->watches,
988  h->watches_size,
989  0);
990  GNUNET_free (h->subsystem);
991  GNUNET_free (h);
992 }
993 
994 
1000 static void
1002 {
1003  struct GNUNET_STATISTICS_Handle *h = cls;
1004 
1005  if (NULL != h->backoff_task)
1006  return; /* action already pending */
1007  if (GNUNET_YES != try_connect (h))
1008  {
1009  reconnect_later (h);
1010  return;
1011  }
1012  if (0 < GNUNET_MQ_get_length (h->mq))
1013  return; /* Wait for queue to be reduced more */
1014  /* schedule next action */
1015  while (NULL == h->current)
1016  {
1017  h->current = h->action_head;
1018  if (NULL == h->current)
1019  {
1020  struct GNUNET_MessageHeader *hdr;
1021  struct GNUNET_MQ_Envelope *env;
1022 
1023  if (GNUNET_YES != h->do_destroy)
1024  return; /* nothing to do */
1025  /* let service know that we're done */
1027  "Notifying service that we are done\n");
1028  h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */
1029  env = GNUNET_MQ_msg (hdr,
1032  &schedule_action,
1033  h);
1034  GNUNET_MQ_send (h->mq,
1035  env);
1036  return;
1037  }
1038  GNUNET_CONTAINER_DLL_remove (h->action_head,
1039  h->action_tail,
1040  h->current);
1041  switch (h->current->type)
1042  {
1043  case ACTION_GET:
1044  transmit_get (h);
1045  break;
1046 
1047  case ACTION_SET:
1048  case ACTION_UPDATE:
1049  transmit_set (h);
1050  break;
1051 
1052  case ACTION_WATCH:
1053  transmit_watch (h);
1054  break;
1055 
1056  default:
1057  GNUNET_assert (0);
1058  break;
1059  }
1060  }
1061 }
1062 
1063 
1066  const char *subsystem,
1067  const char *name,
1070  void *cls)
1071 {
1072  size_t slen1;
1073  size_t slen2;
1075 
1076  if (NULL == handle)
1077  return NULL;
1078  GNUNET_assert (NULL != proc);
1079  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1080  if (NULL == subsystem)
1081  subsystem = "";
1082  if (NULL == name)
1083  name = "";
1084  slen1 = strlen (subsystem) + 1;
1085  slen2 = strlen (name) + 1;
1086  GNUNET_assert (slen1 + slen2 + sizeof(struct GNUNET_MessageHeader) <
1089  ai->sh = handle;
1090  ai->subsystem = GNUNET_strdup (subsystem);
1091  ai->name = GNUNET_strdup (name);
1092  ai->cont = cont;
1093  ai->proc = proc;
1094  ai->cls = cls;
1095  ai->type = ACTION_GET;
1096  ai->msize = slen1 + slen2 + sizeof(struct GNUNET_MessageHeader);
1098  handle->action_tail,
1099  ai);
1101  return ai;
1102 }
1103 
1104 
1105 void
1107 {
1108  if (NULL == gh)
1109  return;
1110  gh->cont = NULL;
1111  if (gh->sh->current == gh)
1112  {
1113  gh->aborted = GNUNET_YES;
1114  return;
1115  }
1116  GNUNET_CONTAINER_DLL_remove (gh->sh->action_head,
1117  gh->sh->action_tail,
1118  gh);
1119  GNUNET_free (gh->name);
1120  GNUNET_free (gh->subsystem);
1121  GNUNET_free (gh);
1122 }
1123 
1124 
1135 int
1137  const char *subsystem,
1138  const char *name,
1140  void *proc_cls)
1141 {
1142  struct GNUNET_STATISTICS_WatchEntry *w;
1143 
1144  if (NULL == handle)
1145  return GNUNET_SYSERR;
1148  w->name = GNUNET_strdup (name);
1149  w->proc = proc;
1150  w->proc_cls = proc_cls;
1151  GNUNET_array_append (handle->watches,
1152  handle->watches_size,
1153  w);
1155  w);
1156  return GNUNET_OK;
1157 }
1158 
1159 
1170 int
1172  const char *subsystem,
1173  const char *name,
1175  void *proc_cls)
1176 {
1177  struct GNUNET_STATISTICS_WatchEntry *w;
1178 
1179  if (NULL == handle)
1180  return GNUNET_SYSERR;
1181  for (unsigned int i = 0; i < handle->watches_size; i++)
1182  {
1183  w = handle->watches[i];
1184  if (NULL == w)
1185  continue;
1186  if ((w->proc == proc) &&
1187  (w->proc_cls == proc_cls) &&
1188  (0 == strcmp (w->name,
1189  name)) &&
1190  (0 == strcmp (w->subsystem,
1191  subsystem)))
1192  {
1193  GNUNET_free (w->name);
1194  GNUNET_free (w->subsystem);
1195  GNUNET_free (w);
1196  handle->watches[i] = NULL;
1197  return GNUNET_OK;
1198  }
1199  }
1200  return GNUNET_SYSERR;
1201 }
1202 
1203 
1213 static void
1215  const char *name,
1216  int make_persistent,
1217  uint64_t value,
1218  enum ActionType type)
1219 {
1221  size_t slen;
1222  size_t nlen;
1223  size_t nsize;
1224  int64_t delta;
1225 
1226  slen = strlen (h->subsystem) + 1;
1227  nlen = strlen (name) + 1;
1228  nsize = sizeof(struct GNUNET_STATISTICS_SetMessage) + slen + nlen;
1229  if (nsize >= GNUNET_MAX_MESSAGE_SIZE)
1230  {
1231  GNUNET_break (0);
1232  return;
1233  }
1234  for (ai = h->action_head; NULL != ai; ai = ai->next)
1235  {
1236  if (! ((0 == strcmp (ai->subsystem,
1237  h->subsystem)) &&
1238  (0 == strcmp (ai->name,
1239  name)) &&
1240  ((ACTION_UPDATE == ai->type) ||
1241  (ACTION_SET == ai->type))))
1242  continue;
1243  if (ACTION_SET == ai->type)
1244  {
1245  if (ACTION_UPDATE == type)
1246  {
1247  delta = (int64_t) value;
1248  if (delta > 0)
1249  {
1250  /* update old set by new delta */
1251  ai->value += delta;
1252  }
1253  else
1254  {
1255  /* update old set by new delta, but never go negative */
1256  if (ai->value < -delta)
1257  ai->value = 0;
1258  else
1259  ai->value += delta;
1260  }
1261  }
1262  else
1263  {
1264  /* new set overrides old set */
1265  ai->value = value;
1266  }
1267  }
1268  else
1269  {
1270  if (ACTION_UPDATE == type)
1271  {
1272  /* make delta cumulative */
1273  delta = (int64_t) value;
1274  ai->value += delta;
1275  }
1276  else
1277  {
1278  /* drop old 'update', use new 'set' instead */
1279  ai->value = value;
1280  ai->type = type;
1281  }
1282  }
1283  ai->timeout
1285  ai->make_persistent
1286  = make_persistent;
1287  return;
1288  }
1289  /* no existing entry matches, create a fresh one */
1291  ai->sh = h;
1292  ai->subsystem = GNUNET_strdup (h->subsystem);
1293  ai->name = GNUNET_strdup (name);
1295  ai->make_persistent = make_persistent;
1296  ai->msize = nsize;
1297  ai->value = value;
1298  ai->type = type;
1299  GNUNET_CONTAINER_DLL_insert_tail (h->action_head,
1300  h->action_tail,
1301  ai);
1302  schedule_action (h);
1303 }
1304 
1305 
1306 void
1308  const char *name,
1309  uint64_t value,
1310  int make_persistent)
1311 {
1312  if (NULL == handle)
1313  return;
1314  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1316  name,
1317  make_persistent,
1318  value,
1319  ACTION_SET);
1320 }
1321 
1322 
1323 void
1325  const char *name,
1326  int64_t delta,
1327  int make_persistent)
1328 {
1329  if (NULL == handle)
1330  return;
1331  if (0 == delta)
1332  return;
1333  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1335  name,
1336  make_persistent,
1337  (uint64_t) delta,
1338  ACTION_UPDATE);
1339 }
1340 
1341 
1342 /* end of statistics_api.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
static char * value
Value of the record to add/remove.
static struct GNUNET_TRANSPORT_HelloGetHandle * gh
Pending GNUNET_TRANSPORT_hello_get() operation.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static int watch
Watch value continuously.
static char * subsystem
Set to subsystem that we're going to get stats for (or NULL for all).
Constants for network protocols.
API to create, modify and access statistics.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:293
GNUNET_MQ_Error
Error codes for the queue.
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:304
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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:62
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:77
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition: mq.c:638
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
#define GNUNET_MESSAGE_TYPE_STATISTICS_END
Response to a STATISTICS_GET message (end of value stream).
#define GNUNET_MESSAGE_TYPE_STATISTICS_GET
Get a statistical value(s).
#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE
Response to a STATISTICS_GET message (with value).
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
Changes to a watched value.
#define GNUNET_MESSAGE_TYPE_STATISTICS_SET
Set a statistical value.
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
Service confirms disconnect and that it is done processing all requests from the client.
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH
Watch changes to a statistical value.
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT
Client is done sending service requests and will now disconnect.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1299
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272
int(* GNUNET_STATISTICS_Iterator)(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
Callback function to process statistic values.
int GNUNET_STATISTICS_watch_cancel(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Iterator proc, void *proc_cls)
Stop watching statistics from the peer.
void GNUNET_STATISTICS_get_cancel(struct GNUNET_STATISTICS_GetHandle *gh)
Cancel a GNUNET_STATISTICS_get request.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void(* GNUNET_STATISTICS_Callback)(void *cls, int success)
Continuation called by GNUNET_STATISTICS_get() functions.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
int GNUNET_STATISTICS_watch(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Iterator proc, void *proc_cls)
Watch statistics from the peer (be notified whenever they change).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls)
Get statistic from the peer.
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:72
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:44
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:484
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
const char * name
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
#define GNUNET_STATISTICS_PERSIST_BIT
Flag for the struct GNUNET_STATISTICS_ReplyMessage UID only.
Definition: statistics.h:65
#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_STATISTICS_SETFLAG_RELATIVE
The value being set is a relative change.
Definition: statistics.h:75
static int check_statistics_value(void *cls, const struct GNUNET_STATISTICS_ReplyMessage *smsg)
Process a GNUNET_MESSAGE_TYPE_STATISTICS_VALUE message.
ActionType
Types of actions.
@ ACTION_SET
Set a value.
@ ACTION_GET
Get a value.
@ ACTION_WATCH
Watch a value.
@ ACTION_UPDATE
Update a value.
static void reconnect_later(struct GNUNET_STATISTICS_Handle *h)
Reconnect at a later time, respecting back-off.
#define SET_TRANSMIT_TIMEOUT
How long do we wait until a statistics request for setting a value times out? (The update will be los...
static void transmit_watch(struct GNUNET_STATISTICS_Handle *handle)
Transmit a WATCH request (and if successful, start to receive the response).
static void handle_disconnect_confirm(void *cls, const struct GNUNET_MessageHeader *msg)
Handle a GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM message.
static void handle_statistics_value(void *cls, const struct GNUNET_STATISTICS_ReplyMessage *smsg)
Process a GNUNET_MESSAGE_TYPE_STATISTICS_VALUE message.
static void schedule_watch_request(struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_WatchEntry *watch)
Transmit request to service that we want to watch the development of a particular value.
static void free_action_item(struct GNUNET_STATISTICS_GetHandle *gh)
Free memory associated with the given action item.
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static void schedule_action(void *cls)
Schedule the next action to be performed.
static void handle_statistics_watch_value(void *cls, const struct GNUNET_STATISTICS_WatchValueMessage *wvm)
We have received a watch value from the service.
static int try_connect(struct GNUNET_STATISTICS_Handle *h)
Try to (re)connect to the statistics service.
static void transmit_get(struct GNUNET_STATISTICS_Handle *handle)
Transmit a GET request (and if successful, start to receive the response).
static void update_memory_statistics(struct GNUNET_STATISTICS_Handle *h)
Obtain statistics about this process's memory consumption and report those as well (if they changed).
static void do_destroy(void *cls)
Task used to destroy the statistics handle.
#define LOG(kind,...)
static void transmit_set(struct GNUNET_STATISTICS_Handle *handle)
Transmit a SET/UPDATE request.
static void do_disconnect(struct GNUNET_STATISTICS_Handle *h)
Disconnect from the statistics service.
static void add_setter_action(struct GNUNET_STATISTICS_Handle *h, const char *name, int make_persistent, uint64_t value, enum ActionType type)
Queue a request to change a statistic.
static void handle_statistics_end(void *cls, const struct GNUNET_MessageHeader *msg)
Handle a GNUNET_MESSAGE_TYPE_STATISTICS_END message.
static void reconnect_task(void *cls)
We've waited long enough, reconnect now.
struct GNUNET_MQ_Handle * mq
Our connection to the ARM service.
Definition: arm_api.c:107
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration that we are using.
Definition: arm_api.c:112
struct GNUNET_MQ_Handle * mq
Connection to DNS service, or NULL.
Definition: dns_api.c:61
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Entry in list of pending tasks.
Definition: scheduler.c:136
Linked list of things we still need to do.
char * name
What value is this action about? (can be NULL)
uint64_t value
Associated value.
GNUNET_STATISTICS_Callback cont
Continuation to call once action is complete.
int make_persistent
Flag for SET/UPDATE actions.
struct GNUNET_STATISTICS_GetHandle * prev
This is a doubly linked list.
GNUNET_STATISTICS_Iterator proc
Function to call (for GET actions only).
uint16_t msize
Size of the message that we will be transmitting.
enum ActionType type
Is this a ACTION_GET, ACTION_SET, ACTION_UPDATE or ACTION_WATCH?
struct GNUNET_TIME_Absolute timeout
Timeout for this action.
struct GNUNET_STATISTICS_GetHandle * next
This is a doubly linked list.
int aborted
Has the current iteration been aborted; for GET actions.
struct GNUNET_STATISTICS_Handle * sh
Main statistics handle.
char * subsystem
What subsystem is this action about? (can be NULL)
void * cls
Closure for proc and cont.
Handle for the service.
struct GNUNET_MQ_Handle * mq
Message queue to the service.
char * subsystem
Name of our subsystem.
struct GNUNET_STATISTICS_WatchEntry ** watches
Array of watch entries.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
struct GNUNET_STATISTICS_GetHandle * current
Action we are currently busy with (action request has been transmitted, we're now receiving the respo...
int do_destroy
Should this handle auto-destruct once all actions have been processed?
struct GNUNET_TIME_Relative backoff
Time for next connect retry.
unsigned int watches_size
Size of the watches array.
int receiving
Are we currently receiving from the service?
struct GNUNET_SCHEDULER_Task * destroy_task
Task for running do_destroy().
uint64_t peak_heap_size
Maximum heap size observed so far (if available).
struct GNUNET_STATISTICS_GetHandle * action_head
Head of the linked list of pending actions (first action to be performed).
struct GNUNET_SCHEDULER_Task * backoff_task
Task doing exponential back-off trying to reconnect.
struct GNUNET_STATISTICS_GetHandle * action_tail
Tail of the linked list of actions (for fast append).
uint64_t peak_rss
Maximum resident set side observed so far (if available).
Statistics message.
Definition: statistics.h:41
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_STATISTICS_VALUE.
Definition: statistics.h:45
uint32_t uid
Unique numerical identifier for the value (will not change during the same client-session).
Definition: statistics.h:53
uint64_t value
The value.
Definition: statistics.h:58
Message to set a statistic.
Definition: statistics.h:92
uint32_t flags
0 for absolute value, 1 for relative value; 2 to make persistent (see GNUNET_STATISTICS_SETFLAG_*).
Definition: statistics.h:102
Entry kept for each value we are watching.
void * proc_cls
Closure for proc.
char * name
What value is this action about? (never NULL)
GNUNET_STATISTICS_Iterator proc
Function to call.
char * subsystem
What subsystem is this action about? (never NULL)
Message transmitted if a watched value changes.
Definition: statistics.h:116
uint32_t reserved
Reserved (always 0).
Definition: statistics.h:139
uint32_t flags
0 for absolute value, 1 for relative value; 2 to make persistent (see GNUNET_STATISTICS_SETFLAG_*).
Definition: statistics.h:126
uint32_t wid
Unique watch identification number (watch requests are enumerated in the order they are received,...
Definition: statistics.h:134
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_TRANSPORT_AddressIdentifier * next
Kept in a DLL.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model