-more datacache integration work
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_cpustatus.c
index dc48e11cdbc0385b8a7dca435ae0445a8d5ee6be..44d1c7624a158843e00a85d629a81a7fef0f13b1 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2003, 2005, 2006, 2013 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2008--2013 Christian Grothoff (and other contributing authors)
 
      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
@@ -30,6 +30,7 @@
 
 #include "platform.h"
 #include "gnunet_util_lib.h"
+#include "gnunet-service-testbed_meminfo.h"
 
 #if SOLARIS
 #if HAVE_KSTAT_H
@@ -53,6 +54,9 @@
 
 static processor_cpu_load_info_t prev_cpu_load;
 #endif
+#ifdef WINDOWS
+#include <winternl.h>
+#endif
 
 #define DEBUG_STATUSCALLS GNUNET_NO
 
@@ -81,7 +85,7 @@ static double agedIOLoad = -1;
  */
 struct GNUNET_BIO_WriteHandle *bw;
 
-GNUNET_SCHEDULER_TaskIdentifier sample_load_task_id;
+struct GNUNET_SCHEDULER_Task * sample_load_task_id;
 
 
 #ifdef OSX
@@ -120,7 +124,7 @@ initMachCpuStats ()
 #endif
 
 /**
- * Update the currentCPU and currentIO load values.
+ * Update the currentCPU and currentIO load (and on Linux, memory) values.
  *
  * Before its first invocation the method initStatusCalls() must be called.
  * If there is an error the method returns -1.
@@ -317,7 +321,7 @@ updateUsage ()
     kc = kstat_open ();
     if (kc == NULL)
       {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close");        
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close");
         goto ABORT_KSTAT;
       }
 
@@ -526,7 +530,7 @@ updateAgedLoad ()
 
   age = GNUNET_TIME_absolute_get_duration (lastCall);
   if ( (agedCPULoad == -1)
-       || (age.rel_value > 500) )
+       || (age.rel_value_us > 500000) )
     {
       /* use smoothing, but do NOT update lastRet at frequencies higher
          than 500ms; this makes the smoothing (mostly) independent from
@@ -596,6 +600,50 @@ disk_get_load ()
   return (int) agedIOLoad;
 }
 
+/**
+ * Get the percentage of memory used
+ *
+ * @return the percentage of memory used
+ */
+static unsigned int
+mem_get_usage ()
+{
+  double percentage;
+
+  meminfo ();
+  percentage = ( ((double) kb_main_used) / ((double) kb_main_total) * 100.0 );
+  return (unsigned int) percentage;
+}
+
+
+#ifdef LINUX
+#include <dirent.h>
+/**
+ * Returns the number of processes
+ *
+ * @return the number of processes
+ */
+static unsigned int
+get_nproc ()
+{
+  DIR *dir;
+  struct dirent *ent;
+  unsigned int nproc;
+
+  dir = opendir ("/proc");
+  if (NULL == dir)
+    return 0;
+  nproc = 0;
+  while (NULL != (ent = readdir (dir)))
+  {
+    if((*ent->d_name > '0') && (*ent->d_name <= '9'))
+      nproc++;
+  }
+  closedir (dir);
+  return nproc;
+}
+#endif
+
 
 static void
 sample_load_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -605,24 +653,32 @@ sample_load_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   int nbs;
   int ld_cpu;
   int ld_disk;
+  unsigned int mem_usage;
+  unsigned int nproc;
 
-  sample_load_task_id = GNUNET_SCHEDULER_NO_TASK;
+  sample_load_task_id = NULL;
   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
     return;
   ld_cpu = cpu_get_load ();
   ld_disk = disk_get_load ();
   if ( (-1 == ld_cpu) || (-1 == ld_disk) )
     goto reschedule;
+  mem_usage = mem_get_usage ();
+#ifdef LINUX
+  nproc = get_nproc ();
+#else
+  nproc = 0;
+#endif
   now = GNUNET_TIME_absolute_get ();
-  nbs = GNUNET_asprintf (&str, "%llu %d %d\n", now.abs_value / 1000,
-                         ld_cpu, ld_disk);
-  if (0 < nbs) 
+  nbs = GNUNET_asprintf (&str, "%llu %d %d %u %u\n", now.abs_value_us / 1000LL / 1000LL,
+                         ld_cpu, ld_disk, mem_usage, nproc);
+  if (0 < nbs)
   {
     GNUNET_BIO_write (bw, str, nbs);
-    GNUNET_free (str);
   }
   else
     GNUNET_break (0);
+  GNUNET_free (str);
 
  reschedule:
   sample_load_task_id =
@@ -642,6 +698,7 @@ GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
   char *hostname;
   char *stats_dir;
   char *fn;
+  size_t len;
 
 #if MINGW
   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -650,20 +707,23 @@ GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
 #endif
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
-                                             "STATS_DIR", &stats_dir))
+      GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed",
+                                               "STATS_DIR", &stats_dir))
     return;
-  hostname = GNUNET_malloc (GNUNET_OS_get_hostname_max_length ());
-  if (0 != gethostname  (hostname, GNUNET_OS_get_hostname_max_length ()))
+  len = GNUNET_OS_get_hostname_max_length ();
+  hostname = GNUNET_malloc (len);
+  if (0 != gethostname  (hostname, len))
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "gethostname");
     GNUNET_free (stats_dir);
+    GNUNET_free (hostname);
     return;
   }
-  fn = NULL;  
-  (void) GNUNET_asprintf (&fn, "%s/%s-%jd.dat", stats_dir, 
+  fn = NULL;
+  (void) GNUNET_asprintf (&fn, "%s/%.*s-%jd.dat", stats_dir, len,
                           hostname, (intmax_t) getpid());
   GNUNET_free (stats_dir);
+  GNUNET_free (hostname);
   if (NULL == (bw = GNUNET_BIO_write_open (fn)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -683,7 +743,7 @@ GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
   initMachCpuStats ();
 #endif
   updateUsage ();               /* initialize */
-  
+
 }
 
 
@@ -707,10 +767,10 @@ GST_stats_destroy ()
 #elif OSX
   GNUNET_free_non_null (prev_cpu_load);
 #endif
-  if (GNUNET_SCHEDULER_NO_TASK != sample_load_task_id)
+  if (NULL != sample_load_task_id)
   {
     GNUNET_SCHEDULER_cancel (sample_load_task_id);
-    sample_load_task_id = GNUNET_SCHEDULER_NO_TASK;
+    sample_load_task_id = NULL;
   }
   GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bw));
   bw = NULL;