GNUnet  0.10.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 (GNUNET_TIME_UNIT_SECONDS, 2)
39 
40 #define LOG(kind,...) GNUNET_log_from (kind, "statistics-api",__VA_ARGS__)
41 
46 {
51 
56 
61 
66 };
67 
68 
73 {
74 
78  char *subsystem;
79 
83  char *name;
84 
89 
93  void *proc_cls;
94 
95 };
96 
97 
102 {
103 
108 
113 
118 
122  char *subsystem;
123 
127  char *name;
128 
133 
138 
142  void *cls;
143 
148 
152  uint64_t value;
153 
158 
162  int aborted;
163 
168 
172  uint16_t msize;
173 
174 };
175 
176 
181 {
185  char *subsystem;
186 
191 
196 
202 
207 
214 
219 
224 
229 
234 
238  uint64_t peak_heap_size;
239 
243  uint64_t peak_rss;
244 
248  unsigned int watches_size;
249 
255 
260 
261 };
262 
263 
268 static void
270 {
271 #if ENABLE_HEAP_STATISTICS
272  uint64_t current_heap_size = 0;
273  uint64_t current_rss = 0;
274 
275  if (GNUNET_NO != h->do_destroy)
276  return;
277 #if HAVE_MALLINFO
278  {
279  struct mallinfo mi;
280 
281  mi = mallinfo();
282  current_heap_size = mi.uordblks + mi.fordblks;
283  }
284 #endif
285 #if HAVE_GETRUSAGE
286  {
287  struct rusage ru;
288 
289  if (0 == getrusage (RUSAGE_SELF, &ru))
290  {
291  current_rss = 1024LL * ru.ru_maxrss;
292  }
293  }
294 #endif
295  if (current_heap_size > h->peak_heap_size)
296  {
297  h->peak_heap_size = current_heap_size;
299  "# peak heap size",
300  current_heap_size,
301  GNUNET_NO);
302  }
303  if (current_rss > h->peak_rss)
304  {
305  h->peak_rss = current_rss;
307  "# peak resident set size",
308  current_rss,
309  GNUNET_NO);
310  }
311 #endif
312 }
313 
314 
320 static void
322 
323 
329 static void
330 schedule_action (void *cls);
331 
332 
340 static void
343 {
345  size_t slen;
346  size_t nlen;
347  size_t nsize;
348 
349  slen = strlen (watch->subsystem) + 1;
350  nlen = strlen (watch->name) + 1;
351  nsize = sizeof (struct GNUNET_MessageHeader) + slen + nlen;
352  if (nsize >= GNUNET_MAX_MESSAGE_SIZE)
353  {
354  GNUNET_break (0);
355  return;
356  }
358  ai->sh = h;
359  ai->subsystem = GNUNET_strdup (watch->subsystem);
360  ai->name = GNUNET_strdup (watch->name);
362  ai->msize = nsize;
363  ai->type = ACTION_WATCH;
364  ai->proc = watch->proc;
365  ai->cls = watch->proc_cls;
367  h->action_tail,
368  ai);
369  schedule_action (h);
370 }
371 
372 
378 static void
380 {
383  GNUNET_free (gh);
384 }
385 
386 
392 static void
394 {
395  struct GNUNET_STATISTICS_GetHandle *c;
396 
397  h->receiving = GNUNET_NO;
398  if (NULL != (c = h->current))
399  {
400  h->current = NULL;
401  if ( (NULL != c->cont) &&
402  (GNUNET_YES != c->aborted) )
403  {
404  c->cont (c->cls,
405  GNUNET_SYSERR);
406  c->cont = NULL;
407  }
408  free_action_item (c);
409  }
410  if (NULL != h->mq)
411  {
412  GNUNET_MQ_destroy (h->mq);
413  h->mq = NULL;
414  }
415 }
416 
417 
425 static int
427  const struct GNUNET_STATISTICS_ReplyMessage *smsg)
428 {
429  const char *service;
430  const char *name;
431  uint16_t size;
432 
433  size = ntohs (smsg->header.size);
434  size -= sizeof (struct GNUNET_STATISTICS_ReplyMessage);
435  if (size !=
436  GNUNET_STRINGS_buffer_tokenize ((const char *) &smsg[1],
437  size,
438  2,
439  &service,
440  &name))
441  {
442  GNUNET_break (0);
443  return GNUNET_SYSERR;
444  }
445  return GNUNET_OK;
446 }
447 
448 
456 static void
458  const struct GNUNET_STATISTICS_ReplyMessage *smsg)
459 {
460  struct GNUNET_STATISTICS_Handle *h = cls;
461  const char *service;
462  const char *name;
463  uint16_t size;
464 
465  if (h->current->aborted)
466  return; /* iteration aborted, don't bother */
467 
468  size = ntohs (smsg->header.size);
469  size -= sizeof (struct GNUNET_STATISTICS_ReplyMessage);
470  GNUNET_assert (size ==
471  GNUNET_STRINGS_buffer_tokenize ((const char *) &smsg[1],
472  size,
473  2,
474  &service,
475  &name));
477  "Received valid statistic on `%s:%s': %llu\n",
478  service, name,
479  GNUNET_ntohll (smsg->value));
480  if (GNUNET_OK !=
481  h->current->proc (h->current->cls,
482  service,
483  name,
484  GNUNET_ntohll (smsg->value),
485  0 !=
486  (ntohl (smsg->uid) & GNUNET_STATISTICS_PERSIST_BIT)))
487  {
489  "Processing of remaining statistics aborted by client.\n");
490  h->current->aborted = GNUNET_YES;
491  }
492 }
493 
494 
501 static void
503  const struct GNUNET_STATISTICS_WatchValueMessage *wvm)
504 {
505  struct GNUNET_STATISTICS_Handle *h = cls;
507  uint32_t wid;
508 
509  GNUNET_break (0 == ntohl (wvm->reserved));
510  wid = ntohl (wvm->wid);
511  if (wid >= h->watches_size)
512  {
513  do_disconnect (h);
514  reconnect_later (h);
515  return;
516  }
517  w = h->watches[wid];
518  if (NULL == w)
519  return;
520  (void) w->proc (w->proc_cls,
521  w->subsystem,
522  w->name,
523  GNUNET_ntohll (wvm->value),
524  0 != (ntohl (wvm->flags) & GNUNET_STATISTICS_PERSIST_BIT));
525 }
526 
527 
536 static void
537 mq_error_handler (void *cls,
538  enum GNUNET_MQ_Error error)
539 {
540  struct GNUNET_STATISTICS_Handle *h = cls;
541 
542  if (GNUNET_NO != h->do_destroy)
543  {
544  h->do_destroy = GNUNET_NO;
545  if (NULL != h->destroy_task)
546  {
548  h->destroy_task = NULL;
549  }
551  GNUNET_NO);
552  return;
553  }
554  do_disconnect (h);
555  reconnect_later (h);
556 }
557 
558 
564 static void
565 do_destroy (void *cls)
566 {
567  struct GNUNET_STATISTICS_Handle *h = cls;
568 
569  h->destroy_task = NULL;
570  h->do_destroy = GNUNET_NO;
572  "Running final destruction\n");
574  GNUNET_NO);
575 }
576 
577 
586 static void
588  const struct GNUNET_MessageHeader *msg)
589 {
590  struct GNUNET_STATISTICS_Handle *h = cls;
591 
592  if (GNUNET_SYSERR != h->do_destroy)
593  {
594  /* not in shutdown, why do we get 'TEST'? */
595  GNUNET_break (0);
596  do_disconnect (h);
597  reconnect_later (h);
598  return;
599  }
601  "Received DISCONNNECT_CONFIRM message from statistics, can complete disconnect\n");
602  if (NULL != h->destroy_task)
605  h);
606 }
607 
608 
617 static void
619  const struct GNUNET_MessageHeader *msg)
620 {
621  struct GNUNET_STATISTICS_Handle *h = cls;
622  struct GNUNET_STATISTICS_GetHandle *c;
623 
625  "Received end of statistics marker\n");
626  if (NULL == (c = h->current))
627  {
628  GNUNET_break (0);
629  do_disconnect (h);
630  reconnect_later (h);
631  return;
632  }
634  h->current = NULL;
635  schedule_action (h);
636  if (NULL != c->cont)
637  {
638  c->cont (c->cls,
639  GNUNET_OK);
640  c->cont = NULL;
641  }
642  free_action_item (c);
643 }
644 
645 
652 static int
654 {
655  struct GNUNET_MQ_MessageHandler handlers[] = {
656  GNUNET_MQ_hd_fixed_size (disconnect_confirm,
658  struct GNUNET_MessageHeader,
659  h),
660  GNUNET_MQ_hd_fixed_size (statistics_end,
662  struct GNUNET_MessageHeader,
663  h),
664  GNUNET_MQ_hd_var_size (statistics_value,
667  h),
668  GNUNET_MQ_hd_fixed_size (statistics_watch_value,
671  h),
673  };
675  struct GNUNET_STATISTICS_GetHandle *gn;
676 
677  if (NULL != h->backoff_task)
678  return GNUNET_NO;
679  if (NULL != h->mq)
680  return GNUNET_YES;
681  h->mq = GNUNET_CLIENT_connect (h->cfg,
682  "statistics",
683  handlers,
685  h);
686  if (NULL == h->mq)
687  {
689  "Failed to connect to statistics service!\n");
690  return GNUNET_NO;
691  }
692  gn = h->action_head;
693  while (NULL != (gh = gn))
694  {
695  gn = gh->next;
696  if (gh->type == ACTION_WATCH)
697  {
699  h->action_tail,
700  gh);
701  free_action_item (gh);
702  }
703  }
704  for (unsigned int i = 0; i < h->watches_size; i++)
705  if (NULL != h->watches[i])
707  h->watches[i]);
708  return GNUNET_YES;
709 }
710 
711 
717 static void
719 {
720  struct GNUNET_STATISTICS_Handle *h = cls;
721 
722  h->backoff_task = NULL;
723  schedule_action (h);
724 }
725 
726 
732 static void
734 {
735  int loss;
737 
738  GNUNET_assert (NULL == h->backoff_task);
739  if (GNUNET_YES == h->do_destroy)
740  {
741  /* So we are shutting down and the service is not reachable.
742  * Chances are that it's down for good and we are not going to connect to
743  * it anymore.
744  * Give up and don't sync the rest of the data.
745  */
746  loss = GNUNET_NO;
747  for (gh = h->action_head; NULL != gh; gh = gh->next)
748  if ( (gh->make_persistent) &&
749  (ACTION_SET == gh->type) )
750  loss = GNUNET_YES;
751  if (GNUNET_YES == loss)
753  _("Could not save some persistent statistics\n"));
754  if (NULL != h->destroy_task)
757  h);
758  return;
759  }
760  h->backoff_task
763  h);
765 }
766 
767 
768 
775 static void
777 {
778  struct GNUNET_STATISTICS_GetHandle *c;
779  struct GNUNET_MessageHeader *hdr;
780  struct GNUNET_MQ_Envelope *env;
781  size_t slen1;
782  size_t slen2;
783 
784  GNUNET_assert (NULL != (c = handle->current));
785  slen1 = strlen (c->subsystem) + 1;
786  slen2 = strlen (c->name) + 1;
787  env = GNUNET_MQ_msg_extra (hdr,
788  slen1 + slen2,
790  GNUNET_assert (slen1 + slen2 ==
791  GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
792  slen1 + slen2,
793  2,
794  c->subsystem,
795  c->name));
798  handle);
799  GNUNET_MQ_send (handle->mq,
800  env);
801 }
802 
803 
810 static void
812 {
813  struct GNUNET_MessageHeader *hdr;
814  struct GNUNET_MQ_Envelope *env;
815  size_t slen1;
816  size_t slen2;
817 
819  "Transmitting watch request for `%s'\n",
820  handle->current->name);
821  slen1 = strlen (handle->current->subsystem) + 1;
822  slen2 = strlen (handle->current->name) + 1;
823  env = GNUNET_MQ_msg_extra (hdr,
824  slen1 + slen2,
826  GNUNET_assert (slen1 + slen2 ==
827  GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
828  slen1 + slen2,
829  2,
830  handle->current->subsystem,
831  handle->current->name));
834  handle);
835  GNUNET_MQ_send (handle->mq,
836  env);
837  GNUNET_assert (NULL == handle->current->cont);
838  free_action_item (handle->current);
839  handle->current = NULL;
840  schedule_action (handle);
841 }
842 
843 
849 static void
851 {
853  struct GNUNET_MQ_Envelope *env;
854  size_t slen;
855  size_t nlen;
856 
857  slen = strlen (handle->current->subsystem) + 1;
858  nlen = strlen (handle->current->name) + 1;
859  env = GNUNET_MQ_msg_extra (r,
860  slen + nlen,
862  r->flags = 0;
863  r->value = GNUNET_htonll (handle->current->value);
864  if (handle->current->make_persistent)
866  if (handle->current->type == ACTION_UPDATE)
868  GNUNET_assert (slen + nlen ==
869  GNUNET_STRINGS_buffer_fill ((char *) &r[1],
870  slen + nlen,
871  2,
872  handle->current->subsystem,
873  handle->current->name));
874  GNUNET_assert (NULL == handle->current->cont);
875  free_action_item (handle->current);
876  handle->current = NULL;
877  update_memory_statistics (handle);
880  handle);
881  GNUNET_MQ_send (handle->mq,
882  env);
883 }
884 
885 
895  const struct GNUNET_CONFIGURATION_Handle *cfg)
896 {
897  struct GNUNET_STATISTICS_Handle *h;
898 
899  if (GNUNET_YES ==
901  "statistics",
902  "DISABLE"))
903  return NULL;
905  h->cfg = cfg;
906  h->subsystem = GNUNET_strdup (subsystem);
908  return h;
909 }
910 
911 
920 void
922  int sync_first)
923 {
924  struct GNUNET_STATISTICS_GetHandle *pos;
926 
927  if (NULL == h)
928  return;
929  GNUNET_assert (GNUNET_NO == h->do_destroy); /* Don't call twice. */
930  if ( (sync_first) &&
931  (NULL != h->mq) &&
932  (0 != GNUNET_MQ_get_length (h->mq)) )
933  {
934  if ( (NULL != h->current) &&
935  (ACTION_GET == h->current->type) )
936  h->current->aborted = GNUNET_YES;
937  next = h->action_head;
938  while (NULL != (pos = next))
939  {
940  next = pos->next;
941  if ( (ACTION_GET == pos->type) ||
942  (ACTION_WATCH == pos->type) )
943  {
945  h->action_tail,
946  pos);
947  free_action_item (pos);
948  }
949  }
950  h->do_destroy = GNUNET_YES;
951  schedule_action (h);
952  GNUNET_assert (NULL == h->destroy_task);
953  h->destroy_task
955  5),
956  &do_destroy,
957  h);
959  "Deferring destruction\n");
960  return; /* do not finish destruction just yet */
961  }
962  /* do clean up all */
964  "Cleaning all up\n");
965  while (NULL != (pos = h->action_head))
966  {
968  h->action_tail,
969  pos);
970  free_action_item (pos);
971  }
972  do_disconnect (h);
973  if (NULL != h->backoff_task)
974  {
976  h->backoff_task = NULL;
977  }
978  if (NULL != h->destroy_task)
979  {
980  GNUNET_break (0);
982  h->destroy_task = NULL;
983  }
984  for (unsigned int i = 0; i < h->watches_size; i++)
985  {
986  if (NULL == h->watches[i])
987  continue;
988  GNUNET_free (h->watches[i]->subsystem);
989  GNUNET_free (h->watches[i]->name);
990  GNUNET_free (h->watches[i]);
991  }
993  h->watches_size,
994  0);
995  GNUNET_free (h->subsystem);
996  GNUNET_free (h);
997 }
998 
999 
1005 static void
1007 {
1008  struct GNUNET_STATISTICS_Handle *h = cls;
1009 
1010  if (NULL != h->backoff_task)
1011  return; /* action already pending */
1012  if (GNUNET_YES != try_connect (h))
1013  {
1014  reconnect_later (h);
1015  return;
1016  }
1017  if (0 < GNUNET_MQ_get_length (h->mq))
1018  return; /* Wait for queue to be reduced more */
1019  /* schedule next action */
1020  while (NULL == h->current)
1021  {
1022  h->current = h->action_head;
1023  if (NULL == h->current)
1024  {
1025  struct GNUNET_MessageHeader *hdr;
1026  struct GNUNET_MQ_Envelope *env;
1027 
1028  if (GNUNET_YES != h->do_destroy)
1029  return; /* nothing to do */
1030  /* let service know that we're done */
1032  "Notifying service that we are done\n");
1033  h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */
1034  env = GNUNET_MQ_msg (hdr,
1036  GNUNET_MQ_notify_sent (env,
1037  &schedule_action,
1038  h);
1039  GNUNET_MQ_send (h->mq,
1040  env);
1041  return;
1042  }
1044  h->action_tail,
1045  h->current);
1046  switch (h->current->type)
1047  {
1048  case ACTION_GET:
1049  transmit_get (h);
1050  break;
1051  case ACTION_SET:
1052  case ACTION_UPDATE:
1053  transmit_set (h);
1054  break;
1055  case ACTION_WATCH:
1056  transmit_watch (h);
1057  break;
1058  default:
1059  GNUNET_assert (0);
1060  break;
1061  }
1062  }
1063 }
1064 
1065 
1080  const char *subsystem,
1081  const char *name,
1084  void *cls)
1085 {
1086  size_t slen1;
1087  size_t slen2;
1089 
1090  if (NULL == handle)
1091  return NULL;
1092  GNUNET_assert (NULL != proc);
1093  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1094  if (NULL == subsystem)
1095  subsystem = "";
1096  if (NULL == name)
1097  name = "";
1098  slen1 = strlen (subsystem) + 1;
1099  slen2 = strlen (name) + 1;
1100  GNUNET_assert (slen1 + slen2 + sizeof (struct GNUNET_MessageHeader) <
1103  ai->sh = handle;
1104  ai->subsystem = GNUNET_strdup (subsystem);
1105  ai->name = GNUNET_strdup (name);
1106  ai->cont = cont;
1107  ai->proc = proc;
1108  ai->cls = cls;
1109  ai->type = ACTION_GET;
1110  ai->msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader);
1112  handle->action_tail,
1113  ai);
1114  schedule_action (handle);
1115  return ai;
1116 }
1117 
1118 
1125 void
1127 {
1128  if (NULL == gh)
1129  return;
1130  gh->cont = NULL;
1131  if (gh->sh->current == gh)
1132  {
1133  gh->aborted = GNUNET_YES;
1134  return;
1135  }
1137  gh->sh->action_tail,
1138  gh);
1139  GNUNET_free (gh->name);
1140  GNUNET_free (gh->subsystem);
1141  GNUNET_free (gh);
1142 }
1143 
1144 
1155 int
1157  const char *subsystem,
1158  const char *name,
1160  void *proc_cls)
1161 {
1162  struct GNUNET_STATISTICS_WatchEntry *w;
1163 
1164  if (NULL == handle)
1165  return GNUNET_SYSERR;
1167  w->subsystem = GNUNET_strdup (subsystem);
1168  w->name = GNUNET_strdup (name);
1169  w->proc = proc;
1170  w->proc_cls = proc_cls;
1171  GNUNET_array_append (handle->watches,
1172  handle->watches_size,
1173  w);
1174  schedule_watch_request (handle,
1175  w);
1176  return GNUNET_OK;
1177 }
1178 
1179 
1190 int
1192  const char *subsystem,
1193  const char *name,
1195  void *proc_cls)
1196 {
1197  struct GNUNET_STATISTICS_WatchEntry *w;
1198 
1199  if (NULL == handle)
1200  return GNUNET_SYSERR;
1201  for (unsigned int i=0;i<handle->watches_size;i++)
1202  {
1203  w = handle->watches[i];
1204  if (NULL == w)
1205  continue;
1206  if ( (w->proc == proc) &&
1207  (w->proc_cls == proc_cls) &&
1208  (0 == strcmp (w->name,
1209  name)) &&
1210  (0 == strcmp (w->subsystem,
1211  subsystem)) )
1212  {
1213  GNUNET_free (w->name);
1214  GNUNET_free (w->subsystem);
1215  GNUNET_free (w);
1216  handle->watches[i] = NULL;
1217  return GNUNET_OK;
1218  }
1219  }
1220  return GNUNET_SYSERR;
1221 }
1222 
1223 
1233 static void
1235  const char *name,
1236  int make_persistent,
1237  uint64_t value,
1238  enum ActionType type)
1239 {
1241  size_t slen;
1242  size_t nlen;
1243  size_t nsize;
1244  int64_t delta;
1245 
1246  slen = strlen (h->subsystem) + 1;
1247  nlen = strlen (name) + 1;
1248  nsize = sizeof (struct GNUNET_STATISTICS_SetMessage) + slen + nlen;
1249  if (nsize >= GNUNET_MAX_MESSAGE_SIZE)
1250  {
1251  GNUNET_break (0);
1252  return;
1253  }
1254  for (ai = h->action_head; NULL != ai; ai = ai->next)
1255  {
1256  if (! ( (0 == strcmp (ai->subsystem,
1257  h->subsystem)) &&
1258  (0 == strcmp (ai->name,
1259  name)) &&
1260  ( (ACTION_UPDATE == ai->type) ||
1261  (ACTION_SET == ai->type) ) ) )
1262  continue;
1263  if (ACTION_SET == ai->type)
1264  {
1265  if (ACTION_UPDATE == type)
1266  {
1267  delta = (int64_t) value;
1268  if (delta > 0)
1269  {
1270  /* update old set by new delta */
1271  ai->value += delta;
1272  }
1273  else
1274  {
1275  /* update old set by new delta, but never go negative */
1276  if (ai->value < -delta)
1277  ai->value = 0;
1278  else
1279  ai->value += delta;
1280  }
1281  }
1282  else
1283  {
1284  /* new set overrides old set */
1285  ai->value = value;
1286  }
1287  }
1288  else
1289  {
1290  if (ACTION_UPDATE == type)
1291  {
1292  /* make delta cummulative */
1293  delta = (int64_t) value;
1294  ai->value += delta;
1295  }
1296  else
1297  {
1298  /* drop old 'update', use new 'set' instead */
1299  ai->value = value;
1300  ai->type = type;
1301  }
1302  }
1303  ai->timeout
1305  ai->make_persistent
1306  = make_persistent;
1307  return;
1308  }
1309  /* no existing entry matches, create a fresh one */
1311  ai->sh = h;
1312  ai->subsystem = GNUNET_strdup (h->subsystem);
1313  ai->name = GNUNET_strdup (name);
1315  ai->make_persistent = make_persistent;
1316  ai->msize = nsize;
1317  ai->value = value;
1318  ai->type = type;
1320  h->action_tail,
1321  ai);
1322  schedule_action (h);
1323 }
1324 
1325 
1335 void
1337  const char *name,
1338  uint64_t value,
1339  int make_persistent)
1340 {
1341  if (NULL == handle)
1342  return;
1343  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1344  add_setter_action (handle,
1345  name,
1346  make_persistent,
1347  value,
1348  ACTION_SET);
1349 }
1350 
1351 
1361 void
1363  const char *name,
1364  int64_t delta,
1365  int make_persistent)
1366 {
1367  if (NULL == handle)
1368  return;
1369  if (0 == delta)
1370  return;
1371  GNUNET_assert (GNUNET_NO == handle->do_destroy);
1372  add_setter_action (handle,
1373  name,
1374  make_persistent,
1375  (uint64_t) delta,
1376  ACTION_UPDATE);
1377 }
1378 
1379 
1380 /* 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 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:81
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:901
#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:245
#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:81
Message to set a statistic.
Definition: statistics.h:92
uint16_t msize
Size of the message that we will be transmitting.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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:128
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint32_t reserved
Reserved (always 0).
Definition: statistics.h:141
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:76
#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:94
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
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:136
Message transmitted if a watched value changes.
Definition: statistics.h:117
#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:1246
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
#define GNUNET_MESSAGE_TYPE_STATISTICS_GET
Get a statistical value(s).
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:1273
#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:439
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:64
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:136
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
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:79
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:66
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:103
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:80
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:84
#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:965