fix whitespace
[oweals/gnunet.git] / src / statistics / gnunet-statistics.c
index 159a7548dfaca6b504e060c3edc7373d24dd7e6a..159afda53c5a7f919421312ad68e8defb1a92286 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2001, 2002, 2004-2007, 2009, 2016 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
 */
 
 /**
  * @author Igor Wronsky
  */
 #include "platform.h"
  * @author Igor Wronsky
  */
 #include "platform.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_program_lib.h"
+#include "gnunet_util_lib.h"
 #include "gnunet_statistics_service.h"
 #include "statistics.h"
 
 #include "gnunet_statistics_service.h"
 #include "statistics.h"
 
-#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 
 /**
  * Final status code.
 
 /**
  * Final status code.
@@ -52,6 +50,42 @@ static char *name;
  */
 static int persistent;
 
  */
 static int persistent;
 
+/**
+ * Watch value continuously
+ */
+static int watch;
+
+/**
+ * Quiet mode
+ */
+static int quiet;
+
+/**
+ * Remote host
+ */
+static char *remote_host;
+
+/**
+ * Remote host's port
+ */
+static unsigned long long remote_port;
+
+/**
+ * Value to set
+ */
+static unsigned long long set_val;
+
+/**
+ * Set operation
+ */
+static int set_value;
+
+/**
+ * Handle for pending GET operation.
+ */
+static struct GNUNET_STATISTICS_GetHandle *gh;
+
+
 /**
  * Callback function to process statistic values.
  *
 /**
  * Callback function to process statistic values.
  *
@@ -59,19 +93,47 @@ static int persistent;
  * @param subsystem name of subsystem that created the statistic
  * @param name the name of the datum
  * @param value the current value
  * @param subsystem name of subsystem that created the statistic
  * @param name the name of the datum
  * @param value the current value
- * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
- * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
+ * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
 static int
 printer (void *cls,
          const char *subsystem,
  */
 static int
 printer (void *cls,
          const char *subsystem,
-         const char *name, 
-        uint64_t value, int is_persistent)
+         const char *name,
+         uint64_t value,
+         int is_persistent)
 {
 {
-  FPRINTF (stdout,
-           "%s%-12s %-50s: %16llu\n",
-           is_persistent ? "!" : " ", subsystem, _(name),
-          (unsigned long long) value);
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
+  const char *now_str;
+
+  if (quiet == GNUNET_NO)
+  {
+    if (GNUNET_YES == watch)
+    {
+      now_str = GNUNET_STRINGS_absolute_time_to_string (now);
+      FPRINTF (stdout,
+              "%24s %s%12s %50s: %16llu\n",
+               now_str,
+               is_persistent ? "!" : " ",
+               subsystem,
+              _(name),
+              (unsigned long long) value);
+    }
+    else
+    {
+      FPRINTF (stdout,
+              "%s%12s %50s: %16llu\n",
+               is_persistent ? "!" : " ",
+               subsystem,
+              _(name),
+              (unsigned long long) value);
+    }
+  }
+  else
+    FPRINTF (stdout,
+            "%llu\n",
+            (unsigned long long) value);
+
   return GNUNET_OK;
 }
 
   return GNUNET_OK;
 }
 
@@ -80,23 +142,154 @@ printer (void *cls,
  * Function called last by the statistics code.
  *
  * @param cls closure
  * Function called last by the statistics code.
  *
  * @param cls closure
- * @param success GNUNET_OK if statistics were
- *        successfully obtained, GNUNET_SYSERR if not.
+ * @param success #GNUNET_OK if statistics were
+ *        successfully obtained, #GNUNET_SYSERR if not.
  */
 static void
  */
 static void
-cleanup (void *cls, int success)
+cleanup (void *cls,
+         int success)
+{
+  gh = NULL;
+  if (GNUNET_OK != success)
+  {
+    if (NULL == remote_host)
+      FPRINTF (stderr,
+               "%s",
+               _("Failed to obtain statistics.\n"));
+    else
+      FPRINTF (stderr,
+               _("Failed to obtain statistics from host `%s:%llu'\n"),
+               remote_host,
+               remote_port);
+    ret = 1;
+  }
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Function run on shutdown to clean up.
+ *
+ * @param cls the statistics handle
+ */
+static void
+shutdown_task (void *cls)
 {
   struct GNUNET_STATISTICS_Handle *h = cls;
 
 {
   struct GNUNET_STATISTICS_Handle *h = cls;
 
-  if (success != GNUNET_OK)
+  if (NULL == h)
+    return;
+  if (NULL != gh)
+  {
+    GNUNET_STATISTICS_get_cancel (gh);
+    gh = NULL;
+  }
+  if ( (GNUNET_YES == watch) &&
+       (NULL != subsystem) &&
+       (NULL != name) )
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_STATISTICS_watch_cancel (h,
+                                                   subsystem,
+                                                   name,
+                                                   &printer,
+                                                  h));
+  GNUNET_STATISTICS_destroy (h,
+                             GNUNET_NO);
+  h = NULL;
+}
+
+
+/**
+ * Main task that does the actual work.
+ *
+ * @param cls closure with our configuration
+ */
+static void
+main_task (void *cls)
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct GNUNET_STATISTICS_Handle *h;
+
+  if (set_value)
+  {
+    if (NULL == subsystem)
     {
     {
-      fprintf (stderr,
-              _("Failed to obtain statistics.\n"));
+      FPRINTF (stderr,
+              "%s",
+              _("Missing argument: subsystem \n"));
       ret = 1;
       ret = 1;
+      return;
     }
     }
-  if (h != NULL)
+    if (NULL == name)
+    {
+      FPRINTF (stderr,
+              "%s",
+              _("Missing argument: name\n"));
+      ret = 1;
+      return;
+    }
+    h = GNUNET_STATISTICS_create (subsystem,
+                                 cfg);
+    if (NULL == h)
+    {
+      ret = 1;
+      return;
+    }
+    GNUNET_STATISTICS_set (h,
+                           name,
+                           (uint64_t) set_val,
+                           persistent);
     GNUNET_STATISTICS_destroy (h,
     GNUNET_STATISTICS_destroy (h,
-                              GNUNET_NO);
+                               GNUNET_YES);
+    h = NULL;
+    return;
+  }
+  if (NULL == (h = GNUNET_STATISTICS_create ("gnunet-statistics",
+                                             cfg)))
+  {
+    ret = 1;
+    return;
+  }
+  if (GNUNET_NO == watch)
+  {
+    if (NULL ==
+        (gh = GNUNET_STATISTICS_get (h,
+                                     subsystem,
+                                     name,
+                                     &cleanup,
+                                     &printer,
+                                    h)) )
+      cleanup (h,
+              GNUNET_SYSERR);
+  }
+  else
+  {
+    if ( (NULL == subsystem) ||
+        (NULL == name) )
+    {
+      printf (_("No subsystem or name given\n"));
+      GNUNET_STATISTICS_destroy (h,
+                                GNUNET_NO);
+      h = NULL;
+      ret = 1;
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_STATISTICS_watch (h,
+                                 subsystem,
+                                 name,
+                                 &printer,
+                                h))
+    {
+      fprintf (stderr,
+               _("Failed to initialize watch routine\n"));
+      GNUNET_SCHEDULER_add_now (&shutdown_task,
+                                h);
+      return;
+    }
+  }
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                 h);
 }
 
 
 }
 
 
@@ -104,51 +297,77 @@ cleanup (void *cls, int success)
  * Main function that will be run by the scheduler.
  *
  * @param cls closure
  * Main function that will be run by the scheduler.
  *
  * @param cls closure
- * @param sched the scheduler to use
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  * @param cfg configuration
  */
 static void
 run (void *cls,
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  * @param cfg configuration
  */
 static void
 run (void *cls,
-     struct GNUNET_SCHEDULER_Handle *sched,
      char *const *args,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
      char *const *args,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  struct GNUNET_STATISTICS_Handle *h;
-  unsigned long long val;
+  struct GNUNET_CONFIGURATION_Handle *c;
 
 
-  if (args[0] != NULL)
+  c = (struct GNUNET_CONFIGURATION_Handle *) cfg;
+  set_value = GNUNET_NO;
+  if (NULL != args[0])
+  {
+    if (1 != SSCANF (args[0],
+                    "%llu",
+                    &set_val))
     {
     {
-      if ((1 != SSCANF (args[0], "%llu", &val)) ||
-          (subsystem == NULL) || (name == NULL))
-        {
-          FPRINTF (stderr, _("Invalid argument `%s'\n"), args[0]);
-          ret = 1;
-          return;
-        }
-      h = GNUNET_STATISTICS_create (sched, subsystem, cfg);
-      if (h == NULL)
-        {
-          ret = 1;
-          return;
-        }
-      GNUNET_STATISTICS_set (h, name, (uint64_t) val, persistent);
-      GNUNET_STATISTICS_destroy (h, GNUNET_YES);
+      FPRINTF (stderr,
+              _("Invalid argument `%s'\n"),
+              args[0]);
+      ret = 1;
       return;
     }
       return;
     }
-  h = GNUNET_STATISTICS_create (sched, "gnunet-statistics", cfg);
-  if (h == NULL)
+    set_value = GNUNET_YES;
+  }
+  if (NULL != remote_host)
+  {
+    if (0 == remote_port)
     {
     {
-      ret = 1;
+      if (GNUNET_SYSERR ==
+         GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                "statistics",
+                                                "PORT",
+                                                &remote_port))
+      {
+       FPRINTF (stderr,
+                _("A port is required to connect to host `%s'\n"),
+                remote_host);
+       return;
+      }
+    }
+    else if (65535 <= remote_port)
+    {
+      FPRINTF (stderr,
+              _("A port has to be between 1 and 65535 to connect to host `%s'\n"),
+              remote_host);
       return;
     }
       return;
     }
-  if (NULL == GNUNET_STATISTICS_get (h,
-                                    subsystem, name, GET_TIMEOUT, &cleanup, &printer, h))
-    cleanup (h, GNUNET_SYSERR);
+
+    /* Manipulate configuration */
+    GNUNET_CONFIGURATION_set_value_string (c,
+                                          "statistics",
+                                          "UNIXPATH",
+                                          "");
+    GNUNET_CONFIGURATION_set_value_string (c,
+                                          "statistics",
+                                          "HOSTNAME",
+                                          remote_host);
+    GNUNET_CONFIGURATION_set_value_number (c,
+                                          "statistics",
+                                          "PORT",
+                                          remote_port);
+  }
+  GNUNET_SCHEDULER_add_now (&main_task,
+                           c);
 }
 
 }
 
+
 /**
  * The main function to obtain statistics in GNUnet.
  *
 /**
  * The main function to obtain statistics in GNUnet.
  *
@@ -159,25 +378,65 @@ run (void *cls,
 int
 main (int argc, char *const *argv)
 {
 int
 main (int argc, char *const *argv)
 {
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'n', "name", "NAME",
-     gettext_noop ("limit output to statistcs for the given NAME"), 1,
-     &GNUNET_GETOPT_set_string, &name},
-    {'p', "persistent", NULL,
-     gettext_noop ("make the value being set persistent"), 0,
-     &GNUNET_GETOPT_set_one, &persistent},
-    {'s', "subsystem", "SUBSYSTEM",
-     gettext_noop ("limit output to the given SUBSYSTEM"), 1,
-     &GNUNET_GETOPT_set_string, &subsystem},
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_string ('n',
+                                 "name",
+                                 "NAME",
+                                 gettext_noop ("limit output to statistics for the given NAME"),
+                                 &name),
+
+    GNUNET_GETOPT_option_flag ('p',
+                                  "persistent",
+                                  gettext_noop ("make the value being set persistent"),
+                                  &persistent),
+
+    GNUNET_GETOPT_option_string ('s',
+                                 "subsystem",
+                                 "SUBSYSTEM",
+                                 gettext_noop ("limit output to the given SUBSYSTEM"),
+                                 &subsystem),
+
+    GNUNET_GETOPT_option_flag ('q',
+                                  "quiet",
+                                  gettext_noop ("just print the statistics value"),
+                                  &quiet),
+
+    GNUNET_GETOPT_option_flag ('w',
+                                  "watch",
+                                  gettext_noop ("watch value continuously"),
+                                  &watch),
+
+    GNUNET_GETOPT_option_string ('r',
+                                 "remote",
+                                 "REMOTE",
+                                 gettext_noop ("connect to remote host"),
+                                 &remote_host),
+    GNUNET_GETOPT_option_ulong ('o',
+                                    "port",
+                                    "PORT",
+                                    gettext_noop ("port for remote host"),
+                                    &remote_port),
     GNUNET_GETOPT_OPTION_END
   };
     GNUNET_GETOPT_OPTION_END
   };
-  return (GNUNET_OK ==
-          GNUNET_PROGRAM_run (argc,
-                              argv,
-                              "gnunet-statistics [options [value]]",
-                              gettext_noop
-                              ("Print statistics about GNUnet operations."),
-                              options, &run, NULL)) ? ret : 1;
+  remote_port = 0;
+  remote_host = NULL;
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                   &argc, &argv))
+    return 2;
+
+  ret = (GNUNET_OK ==
+        GNUNET_PROGRAM_run (argc,
+                            argv,
+                            "gnunet-statistics [options [value]]",
+                            gettext_noop
+                            ("Print statistics about GNUnet operations."),
+                            options,
+                            &run,
+                            NULL)) ? ret : 1;
+  GNUNET_free_non_null (remote_host);
+  GNUNET_free ((void*) argv);
+  return ret;
 }
 
 /* end of gnunet-statistics.c */
 }
 
 /* end of gnunet-statistics.c */