GNUnet  0.11.x
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 
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_MALLINFO
274  {
275  struct mallinfo mi;
276 
277  mi = mallinfo ();
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);
358  ai->msize = nsize;
359  ai->type = ACTION_WATCH;
360  ai->proc = watch->proc;
361  ai->cls = watch->proc_cls;
363  h->action_tail,
364  ai);
365  schedule_action (h);
366 }
367 
368 
374 static void
376 {
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  {
408  GNUNET_MQ_destroy (h->mq);
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  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  {
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)
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  }
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 {
652  struct GNUNET_MQ_MessageHandler handlers[] = {
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;
678  h->mq = GNUNET_CLIENT_connect (h->cfg,
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  {
696  h->action_tail,
697  gh);
698  free_action_item (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)
753  h);
754  return;
755  }
756  h->backoff_task
759  h);
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);
794  GNUNET_MQ_send (handle->mq,
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);
830  GNUNET_MQ_send (handle->mq,
831  env);
832  GNUNET_assert (NULL == handle->current->cont);
833  free_action_item (handle->current);
834  handle->current = NULL;
835  schedule_action (handle);
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;
854  env = GNUNET_MQ_msg_extra (r,
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;
872  update_memory_statistics (handle);
875  handle);
876  GNUNET_MQ_send (handle->mq,
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);
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  {
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  {
963  h->action_tail,
964  pos);
965  free_action_item (pos);
966  }
967  do_disconnect (h);
968  if (NULL != h->backoff_task)
969  {
971  h->backoff_task = NULL;
972  }
973  if (NULL != h->destroy_task)
974  {
975  GNUNET_break (0);
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  }
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,
1031  GNUNET_MQ_notify_sent (env,
1032  &schedule_action,
1033  h);
1034  GNUNET_MQ_send (h->mq,
1035  env);
1036  return;
1037  }
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 
1078  const char *subsystem,
1079  const char *name,
1082  void *cls)
1083 {
1084  size_t slen1;
1085  size_t slen2;
1087 
1088  if (NULL == handle)
1089  return NULL;
1090  GNUNET_assert (NULL != proc);
1091  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1092  if (NULL == subsystem)
1093  subsystem = "";
1094  if (NULL == name)
1095  name = "";
1096  slen1 = strlen (subsystem) + 1;
1097  slen2 = strlen (name) + 1;
1098  GNUNET_assert (slen1 + slen2 + sizeof(struct GNUNET_MessageHeader) <
1101  ai->sh = handle;
1102  ai->subsystem = GNUNET_strdup (subsystem);
1103  ai->name = GNUNET_strdup (name);
1104  ai->cont = cont;
1105  ai->proc = proc;
1106  ai->cls = cls;
1107  ai->type = ACTION_GET;
1108  ai->msize = slen1 + slen2 + sizeof(struct GNUNET_MessageHeader);
1110  handle->action_tail,
1111  ai);
1112  schedule_action (handle);
1113  return ai;
1114 }
1115 
1116 
1123 void
1125 {
1126  if (NULL == gh)
1127  return;
1128  gh->cont = NULL;
1129  if (gh->sh->current == gh)
1130  {
1131  gh->aborted = GNUNET_YES;
1132  return;
1133  }
1135  gh->sh->action_tail,
1136  gh);
1137  GNUNET_free (gh->name);
1138  GNUNET_free (gh->subsystem);
1139  GNUNET_free (gh);
1140 }
1141 
1142 
1153 int
1155  const char *subsystem,
1156  const char *name,
1158  void *proc_cls)
1159 {
1160  struct GNUNET_STATISTICS_WatchEntry *w;
1161 
1162  if (NULL == handle)
1163  return GNUNET_SYSERR;
1165  w->subsystem = GNUNET_strdup (subsystem);
1166  w->name = GNUNET_strdup (name);
1167  w->proc = proc;
1168  w->proc_cls = proc_cls;
1169  GNUNET_array_append (handle->watches,
1170  handle->watches_size,
1171  w);
1172  schedule_watch_request (handle,
1173  w);
1174  return GNUNET_OK;
1175 }
1176 
1177 
1188 int
1190  const char *subsystem,
1191  const char *name,
1193  void *proc_cls)
1194 {
1195  struct GNUNET_STATISTICS_WatchEntry *w;
1196 
1197  if (NULL == handle)
1198  return GNUNET_SYSERR;
1199  for (unsigned int i = 0; i < handle->watches_size; i++)
1200  {
1201  w = handle->watches[i];
1202  if (NULL == w)
1203  continue;
1204  if ((w->proc == proc) &&
1205  (w->proc_cls == proc_cls) &&
1206  (0 == strcmp (w->name,
1207  name)) &&
1208  (0 == strcmp (w->subsystem,
1209  subsystem)))
1210  {
1211  GNUNET_free (w->name);
1212  GNUNET_free (w->subsystem);
1213  GNUNET_free (w);
1214  handle->watches[i] = NULL;
1215  return GNUNET_OK;
1216  }
1217  }
1218  return GNUNET_SYSERR;
1219 }
1220 
1221 
1231 static void
1233  const char *name,
1234  int make_persistent,
1235  uint64_t value,
1236  enum ActionType type)
1237 {
1239  size_t slen;
1240  size_t nlen;
1241  size_t nsize;
1242  int64_t delta;
1243 
1244  slen = strlen (h->subsystem) + 1;
1245  nlen = strlen (name) + 1;
1246  nsize = sizeof(struct GNUNET_STATISTICS_SetMessage) + slen + nlen;
1247  if (nsize >= GNUNET_MAX_MESSAGE_SIZE)
1248  {
1249  GNUNET_break (0);
1250  return;
1251  }
1252  for (ai = h->action_head; NULL != ai; ai = ai->next)
1253  {
1254  if (! ((0 == strcmp (ai->subsystem,
1255  h->subsystem)) &&
1256  (0 == strcmp (ai->name,
1257  name)) &&
1258  ((ACTION_UPDATE == ai->type) ||
1259  (ACTION_SET == ai->type))))
1260  continue;
1261  if (ACTION_SET == ai->type)
1262  {
1263  if (ACTION_UPDATE == type)
1264  {
1265  delta = (int64_t) value;
1266  if (delta > 0)
1267  {
1268  /* update old set by new delta */
1269  ai->value += delta;
1270  }
1271  else
1272  {
1273  /* update old set by new delta, but never go negative */
1274  if (ai->value < -delta)
1275  ai->value = 0;
1276  else
1277  ai->value += delta;
1278  }
1279  }
1280  else
1281  {
1282  /* new set overrides old set */
1283  ai->value = value;
1284  }
1285  }
1286  else
1287  {
1288  if (ACTION_UPDATE == type)
1289  {
1290  /* make delta cummulative */
1291  delta = (int64_t) value;
1292  ai->value += delta;
1293  }
1294  else
1295  {
1296  /* drop old 'update', use new 'set' instead */
1297  ai->value = value;
1298  ai->type = type;
1299  }
1300  }
1301  ai->timeout
1303  ai->make_persistent
1304  = make_persistent;
1305  return;
1306  }
1307  /* no existing entry matches, create a fresh one */
1309  ai->sh = h;
1310  ai->subsystem = GNUNET_strdup (h->subsystem);
1311  ai->name = GNUNET_strdup (name);
1313  ai->make_persistent = make_persistent;
1314  ai->msize = nsize;
1315  ai->value = value;
1316  ai->type = type;
1318  h->action_tail,
1319  ai);
1320  schedule_action (h);
1321 }
1322 
1323 
1333 void
1335  const char *name,
1336  uint64_t value,
1337  int make_persistent)
1338 {
1339  if (NULL == handle)
1340  return;
1341  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1342  add_setter_action (handle,
1343  name,
1344  make_persistent,
1345  value,
1346  ACTION_SET);
1347 }
1348 
1349 
1359 void
1361  const char *name,
1362  int64_t delta,
1363  int make_persistent)
1364 {
1365  if (NULL == handle)
1366  return;
1367  if (0 == delta)
1368  return;
1369  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1370  add_setter_action (handle,
1371  name,
1372  make_persistent,
1373  (uint64_t) delta,
1374  ACTION_UPDATE);
1375 }
1376 
1377 
1378 /* end of statistics_api.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
int do_destroy
Should this handle auto-destruct once all actions have been processed?
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_STATISTICS_VALUE.
Definition: statistics.h:45
int make_persistent
Flag for SET/UPDATE actions.
char * name
What value is this action about? (can be NULL)
#define LOG(kind,...)
char * subsystem
Name of our subsystem.
static void reconnect_later(struct GNUNET_STATISTICS_Handle *h)
Reconnect at a later time, respecting back-off.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static void transmit_set(struct GNUNET_STATISTICS_Handle *handle)
Transmit a SET/UPDATE request.
#define GNUNET_MESSAGE_TYPE_STATISTICS_SET
Set a statistical value.
struct GNUNET_STATISTICS_WatchEntry ** watches
Array of watch entries.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void handle_disconnect_confirm(void *cls, const struct GNUNET_MessageHeader *msg)
Handle a GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM message.
void * proc_cls
Closure for proc.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
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).
GNUNET_STATISTICS_Iterator proc
Function to call (for GET actions only).
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
Definition: resolver_api.c:83
static void update_memory_statistics(struct GNUNET_STATISTICS_Handle *h)
Obtain statistics about this process&#39;s memory consumption and report those as well (if they changed)...
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
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH
Watch changes to a statistical value.
Statistics message.
Definition: statistics.h:40
char * subsystem
What subsystem is this action about? (can be NULL)
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
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:246
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
enum ActionType type
Is this a ACTION_GET, ACTION_SET, ACTION_UPDATE or ACTION_WATCH?
static void do_disconnect(struct GNUNET_STATISTICS_Handle *h)
Disconnect from the statistics service.
char * name
What value is this action about? (never NULL)
void GNUNET_STATISTICS_get_cancel(struct GNUNET_STATISTICS_GetHandle *gh)
Cancel a &#39;get&#39; request.
int receiving
Are we currently receiving from the service?
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
Linked list of things we still need to do.
#define GNUNET_NO
Definition: gnunet_common.h:78
Message to set a statistic.
Definition: statistics.h:91
uint16_t msize
Size of the message that we will be transmitting.
#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 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...
struct GNUNET_TIME_Absolute timeout
Timeout for this action.
uint64_t peak_rss
Maximum resident set side observed so far (if available).
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
Handle for the service.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
ActionType
Types of actions.
#define GNUNET_STATISTICS_SETFLAG_RELATIVE
The value being set is a relative change.
Definition: statistics.h:75
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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 GNUNET_TIME_Relative backoff
Time for next connect retry.
Watch a value.
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:1253
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_MESSAGE_TYPE_STATISTICS_GET
Get a statistical value(s).
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
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:774
static char * value
Value of the record to add/remove.
GNUNET_STATISTICS_Iterator proc
Function to call.
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
Service confirms disconnect and that it is done processing all requests from the client.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:335
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:1280
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
Changes to a watched value.
uint64_t value
Associated value.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
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:442
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
struct GNUNET_SCHEDULER_Task * backoff_task
Task doing exponential back-off trying to reconnect.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
Message handler for a specific message type.
uint32_t wid
Unique watch identification number (watch requests are enumerated in the order they are received...
Definition: statistics.h:134
uint64_t peak_heap_size
Maximum heap size observed so far (if available).
static int try_connect(struct GNUNET_STATISTICS_Handle *h)
Try to (re)connect to the statistics service.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT
Client is done sending service requests and will now disconnect.
int(* GNUNET_STATISTICS_Iterator)(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
Callback function to process statistic values.
struct GNUNET_STATISTICS_GetHandle * action_tail
Tail of the linked list of actions (for fast append).
static void reconnect_task(void *cls)
We&#39;ve waited long enough, reconnect now.
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
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
struct GNUNET_STATISTICS_GetHandle * prev
This is a doubly linked 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
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static void do_destroy(void *cls)
Task used to destroy the statistics handle.
GNUNET_STATISTICS_Callback cont
Continuation to call once action is complete.
struct GNUNET_SCHEDULER_Task * destroy_task
Task for running do_destroy().
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
struct GNUNET_STATISTICS_Handle * sh
Main statistics handle.
struct GNUNET_MQ_Handle * mq
Message queue to the service.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
Update a value.
Handle to a message queue.
Definition: mq.c:85
Get a value.
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
uint32_t flags
0 for absolute value, 1 for relative value; 2 to make persistent (see GNUNET_STATISTICS_SETFLAG_*).
Definition: statistics.h:102
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.
static void transmit_get(struct GNUNET_STATISTICS_Handle *handle)
Transmit a GET request (and if successful, start to receive the response).
#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 handle_statistics_value(void *cls, const struct GNUNET_STATISTICS_ReplyMessage *smsg)
Process a GNUNET_MESSAGE_TYPE_STATISTICS_VALUE message.
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.
configuration data
Definition: configuration.c:85
Set a value.
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 schedule_action(void *cls)
Schedule the next action to be performed.
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 * cls
Closure for proc and cont.
static struct GNUNET_TRANSPORT_HelloGetHandle * gh
Pending GNUNET_TRANSPORT_hello_get() operation.
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...
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
void(* GNUNET_STATISTICS_Callback)(void *cls, int success)
Continuation called by GNUNET_STATISTICS_get() functions.
static void handle_statistics_watch_value(void *cls, const struct GNUNET_STATISTICS_WatchValueMessage *wvm)
We have received a watch value from the service.
struct GNUNET_STATISTICS_GetHandle * current
Action we are currently busy with (action request has been transmitted, we&#39;re now receiving the respo...
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
unsigned int watches_size
Size of the watches array.
#define GNUNET_YES
Definition: gnunet_common.h:77
Entry kept for each value we are watching.
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
struct GNUNET_STATISTICS_GetHandle * next
This is a doubly linked list.
char * subsystem
What subsystem is this action about? (never NULL)
static void free_action_item(struct GNUNET_STATISTICS_GetHandle *gh)
Free memory associated with the given action item.
int 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".
static int check_statistics_value(void *cls, const struct GNUNET_STATISTICS_ReplyMessage *smsg)
Process a GNUNET_MESSAGE_TYPE_STATISTICS_VALUE message.
static void transmit_watch(struct GNUNET_STATISTICS_Handle *handle)
Transmit a WATCH request (and if successful, start to receive the response).
struct GNUNET_STATISTICS_GetHandle * action_head
Head of the linked list of pending actions (first action to be performed).
int aborted
Has the current iteration been aborted; for GET actions.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
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.
Time for relative time used by GNUnet, in microseconds.
static void handle_statistics_end(void *cls, const struct GNUNET_MessageHeader *msg)
Handle a GNUNET_MESSAGE_TYPE_STATISTICS_END message.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966