aboutsummaryrefslogtreecommitdiff
path: root/src/sysmon/gnunet-service-sysmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sysmon/gnunet-service-sysmon.c')
-rw-r--r--src/sysmon/gnunet-service-sysmon.c838
1 files changed, 838 insertions, 0 deletions
diff --git a/src/sysmon/gnunet-service-sysmon.c b/src/sysmon/gnunet-service-sysmon.c
new file mode 100644
index 0000000..b5fc46a
--- /dev/null
+++ b/src/sysmon/gnunet-service-sysmon.c
@@ -0,0 +1,838 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 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 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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.
+*/
+
+/**
+ * @file sysmon/gnunet-service-sysmon.c
+ * @brief system monitoring service, can use libgtop to retrieve system information
+ * in a plattform independent way
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#if HAVE_LIBGTOP
+#include <glibtop.h>
+#include <glibtop/proclist.h>
+#include <glibtop/procstate.h>
+#include <glibtop/procargs.h>
+#include <glibtop/procmem.h>
+#include <glibtop/proctime.h>
+#include <glibtop/netlist.h>
+#include <glibtop/netload.h>
+#endif
+
+
+enum operation
+{
+ o_internal,
+ o_ligbtop,
+ o_command
+};
+
+
+enum type
+{
+ t_static,
+ t_continous
+};
+
+#define V_NUMERIC_STR "numeric"
+#define V_STRING_STR "string"
+
+enum value
+{
+ v_numeric,
+ v_string
+};
+
+/**
+ * A system property to monitor
+ */
+struct SysmonProperty
+{
+ /**
+ * Next element in in the DLL
+ */
+ struct SysmonProperty *next;
+
+ /**
+ * Previous element in in the DLL
+ */
+ struct SysmonProperty *prev;
+
+ struct SysmonGtopProcProperty *gtop_proc_head;
+ struct SysmonGtopProcProperty *gtop_proc_tail;
+
+ /**
+ * Description used for statistics valuesd
+ */
+ char * desc;
+
+ /**
+ * Type
+ */
+ int type;
+
+ /**
+ * Value type
+ */
+ int value_type;
+
+ /**
+ * Execution interval
+ */
+ struct GNUNET_TIME_Relative interval;
+
+ /**
+ * Command
+ */
+ char * cmd;
+
+ /**
+ * Command arguments
+ */
+ char * cmd_args;
+
+ /**
+ * Command execution handle
+ */
+ void * cmd_exec_handle;
+
+ /**
+ * Numerical value
+ */
+ uint64_t num_val;
+
+ /**
+ * String value
+ */
+ char * str_val;
+
+ /**
+ * Task id
+ */
+ GNUNET_SCHEDULER_TaskIdentifier task_id;
+
+ /**
+ * Task handle
+ */
+ GNUNET_SCHEDULER_Task task;
+
+ /**
+ * Task closure
+ */
+ void *task_cls;
+};
+
+/**
+ * A system property to monitor
+ */
+struct SysmonGtopProcProperty
+{
+ struct SysmonGtopProcProperty *prev;
+ struct SysmonGtopProcProperty *next;
+ char * srv;
+ char * binary;
+};
+
+
+/**
+ * Final status code.
+ */
+static int ret;
+
+/**
+ * Configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+
+/**
+ * Statistics handle
+ */
+struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Shutdown task
+ */
+GNUNET_SCHEDULER_TaskIdentifier end_task;
+
+struct SysmonProperty *sp_head;
+struct SysmonProperty *sp_tail;
+
+struct SysmonGtopProcProperty *pp_head;
+struct SysmonGtopProcProperty *pp_tail;
+
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SysmonProperty *sp;
+ struct SysmonProperty *next;
+ struct SysmonGtopProcProperty *gt_cur;
+ struct SysmonGtopProcProperty *gt_next;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sysdaemon stopping ... \n");
+ end_task = GNUNET_SCHEDULER_NO_TASK;
+
+ if (NULL != stats)
+ {
+ GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
+ stats = NULL;
+ }
+
+ next = sp_head;
+ while (NULL != (sp = next))
+ {
+ next = sp->next;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping `%s' \n", sp->desc);
+ GNUNET_CONTAINER_DLL_remove (sp_head, sp_tail, sp);
+ if (GNUNET_SCHEDULER_NO_TASK != sp->task_id)
+ {
+ GNUNET_SCHEDULER_cancel (sp->task_id);
+ sp->task_id = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_free_non_null (sp->cmd);
+ GNUNET_free_non_null (sp->cmd_args);
+ GNUNET_free (sp->desc);
+ GNUNET_free (sp);
+ }
+
+ gt_next = pp_head;
+ while (NULL != (gt_cur = gt_next))
+ {
+ gt_next = gt_cur->next;
+ GNUNET_CONTAINER_DLL_remove (pp_head, pp_tail, gt_cur);
+ GNUNET_free (gt_cur->srv);
+ GNUNET_free (gt_cur->binary);
+ GNUNET_free (gt_cur);
+ }
+
+#if HAVE_LIBGTOP
+ glibtop_close();
+#endif
+}
+
+static void
+shutdown_now (void)
+{
+ if (GNUNET_SCHEDULER_NO_TASK != end_task)
+ GNUNET_SCHEDULER_cancel (end_task);
+ GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+static void
+to_lower_str (char * str)
+{
+ int c;
+ for (c = 0; c <= strlen (str); c++)
+ str[c] = tolower(str[c]);
+}
+
+static int
+put_property (struct SysmonProperty *sp)
+{
+ if (v_numeric ==sp->value_type)
+ {
+ fprintf (stderr, "%s : %s : %llu\n",
+ GNUNET_STRINGS_absolute_time_to_string(GNUNET_TIME_absolute_get()),
+ sp->desc, (unsigned long long) sp->num_val);
+ }
+ else if (v_string ==sp->value_type)
+ {
+ fprintf (stderr, "%s : %s : %s\n",
+ GNUNET_STRINGS_absolute_time_to_string(GNUNET_TIME_absolute_get()),
+ sp->desc, sp->str_val);
+ }
+ else
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+static void
+update_uptime (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SysmonProperty *sp = cls;
+ static int first_run = GNUNET_YES;
+
+ if (GNUNET_YES == first_run)
+ first_run = GNUNET_NO;
+ else
+ sp->num_val += sp->interval.rel_value / 1000;
+
+ put_property (sp);
+}
+
+static void
+exec_cmd_proc (void *cls, const char *line)
+{
+ struct SysmonProperty *sp = cls;
+ unsigned long long tmp;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property output: `%s'\n", line);
+ if (NULL == line)
+ {
+ GNUNET_OS_command_stop (sp->cmd_exec_handle);
+ sp->cmd_exec_handle = NULL;
+ return;
+ }
+
+ switch (sp->value_type) {
+ case v_numeric:
+ if (1 != sscanf (line, "%llu", &tmp))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Command output was not a numerical value: `%s'\n", line);
+ return;
+ }
+ break;
+ case v_string:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "NOT IMPLEMENTED\n");
+ break;
+ default:
+ break;
+
+ }
+ sp->num_val = tmp;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property output: `%s'\n", line);
+ put_property (sp);
+
+
+}
+
+static void
+exec_cmd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SysmonProperty *sp = cls;
+ GNUNET_assert (NULL != sp->cmd);
+
+ if (NULL != sp->cmd_exec_handle)
+ {
+ GNUNET_OS_command_stop (sp->cmd_exec_handle);
+ sp->cmd_exec_handle = NULL;
+ GNUNET_break (0);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property `%s': command `%s' `%s'\n", sp->desc, sp->cmd, sp->cmd_args);
+ if (NULL == (sp->cmd_exec_handle = GNUNET_OS_command_run (&exec_cmd_proc, sp,
+ GNUNET_TIME_UNIT_SECONDS,
+ sp->cmd, sp->cmd,
+ sp->cmd_args,
+ NULL)))
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property `%s': command `%s' failed\n", sp->desc, sp->cmd);
+}
+
+#if HAVE_LIBGTOP
+static void
+exec_gtop_proc_mon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SysmonGtopProcProperty *sp = cls;
+ glibtop_proclist proc_list;
+ glibtop_proc_args proc_args;
+ glibtop_proc_mem proc_mem;
+ glibtop_proc_time proc_time;
+ pid_t *pids = NULL;
+ unsigned i;
+ char *argss;
+
+ /* get process list */
+ pids = glibtop_get_proclist(&proc_list, GLIBTOP_KERN_PROC_ALL, 0);
+ if (NULL == pids)
+ {
+ fprintf (stderr, "Could not retrieve process list!\n");
+ ret = 1;
+ return;
+ }
+ for (i = 0; i < proc_list.number; ++i)
+ {
+ //printf("PID %u:\n", pids[i]);
+
+ /* get process args */
+ argss = glibtop_get_proc_args (&proc_args, pids[i], 1024);
+ if (NULL == argss)
+ {
+ fprintf (stderr, "Could not retrieve process args!\n");
+ ret = 1;
+ return;
+ }
+ //printf ("\targument string: %s\n", argss);
+ if (NULL != strstr (argss, sp->binary))
+ {
+ /* get memory info */
+ glibtop_get_proc_mem (&proc_mem, pids[i]);
+ fprintf (stderr, "%s : %s process information\n",
+ GNUNET_STRINGS_absolute_time_to_string(GNUNET_TIME_absolute_get()),
+ sp->srv);
+ fprintf (stderr, "\t%s memory information:\n", sp->binary);
+ fprintf (stderr, "\t%-50s: %llu\n", "total # of pages of memory", (long long unsigned int) proc_mem.size);
+ fprintf (stderr, "\t%-50s: %llu\n", "number of pages of virtual memory", (long long unsigned int) proc_mem.vsize);
+ fprintf (stderr, "\t%-50s: %llu\n", "number of resident set", (long long unsigned int) proc_mem.resident);
+ fprintf (stderr, "\t%-50s: %llu\n", "number of pages of shared (mmap'd) memory", (long long unsigned int) proc_mem.share);
+ fprintf (stderr, "\t%-50s: %llu\n", "resident set size", (long long unsigned int) proc_mem.rss);
+
+ /* get time info */
+ glibtop_get_proc_time (&proc_time, pids[i]);
+ fprintf (stderr, "\t%s time information:\n", sp->binary);
+ fprintf (stderr, "\t%-50s: %llu\n", "real time accumulated by process", (long long unsigned int) proc_time.rtime);
+ fprintf (stderr, "\t%-50s: %llu\n", "user-mode CPU time accumulated by process", (long long unsigned int) proc_time.utime);
+ fprintf (stderr, "\t%-50s: %llu\n", "kernel-mode CPU time accumulated by process", (long long unsigned int) proc_time.stime);
+ }
+ g_free (argss);
+ }
+ g_free(pids);
+ pids = NULL;
+}
+#endif
+
+#if HAVE_LIBGTOP
+static void
+exec_gtop_net_mon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ glibtop_netlist netlist;
+ glibtop_netload netload;
+ int i;
+ char ** tmp;
+ uint8_t *address;
+ uint8_t *netmask;
+ char address6_string[INET6_ADDRSTRLEN];
+ char prefix6_string[INET6_ADDRSTRLEN];
+
+ tmp = glibtop_get_netlist (&netlist);
+
+ fprintf (stderr, "%s : Network information: %u devices\n",
+ GNUNET_STRINGS_absolute_time_to_string(GNUNET_TIME_absolute_get()),
+ netlist.number);
+ for (i = 0; i < netlist.number; ++i)
+ {
+ fprintf (stderr, "Device %i: %s\n", i, tmp[i]);
+ glibtop_get_netload (&netload, tmp[i]);
+ address = (uint8_t *) &netload.address;
+ netmask = (uint8_t *) &netload.subnet;
+ inet_ntop (AF_INET6, netload.address6, address6_string, INET6_ADDRSTRLEN);
+ inet_ntop (AF_INET6, netload.prefix6, prefix6_string, INET6_ADDRSTRLEN);
+ fprintf (stderr, "\t%-50s: %u.%u.%u.%u\n", "IPv4 subnet", netmask[0], netmask[1], netmask[2],netmask[3]);
+ fprintf (stderr, "\t%-50s: %u.%u.%u.%u\n", "IPv4 address", address[0], address[1], address[2],address[3]);
+ fprintf (stderr, "\t%-50s: %s\n", "IPv6 prefix", prefix6_string);
+ fprintf (stderr, "\t%-50s: %s\n", "IPv6 address", address6_string);
+
+
+ fprintf (stderr, "\t%-50s: %llu\n", "bytes in", (long long unsigned int) netload.bytes_in);
+ fprintf (stderr, "\t%-50s: %llu\n", "bytes out", (long long unsigned int) netload.bytes_out);
+ fprintf (stderr, "\t%-50s: %llu\n", "bytes total", (long long unsigned int) netload.bytes_total);
+ }
+ fprintf (stderr, "\n");
+}
+#endif
+
+static void
+load_property (void *cls,
+ const char *section)
+{
+ struct GNUNET_CONFIGURATION_Handle *properties = cls;
+ struct SysmonProperty *sp;
+ char *tmp;
+
+ if (NULL == strstr (section, "sysmon-"))
+ return;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading section `%s'\n", section);
+
+ if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section, "TYPE"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
+ "TYPE", section);
+ return;
+ }
+ if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"VALUE"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
+ "VALUE", section);
+ return;
+ }
+ if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"DESCRIPTION"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
+ "DESCRIPTION", section);
+ return;
+ }
+ if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"CMD"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
+ "CMD", section);
+ return;
+ }
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+
+ /* description */
+ GNUNET_CONFIGURATION_get_value_string (properties, section, "DESCRIPTION", &sp->desc);
+
+ /* cmd */
+ GNUNET_CONFIGURATION_get_value_string (properties, section, "CMD", &tmp);
+ char *args = "";
+ if (NULL != strchr (tmp, ' '))
+ {
+ args = strchr (tmp, ' ');
+ if (strlen (args) > 1)
+ {
+ args[0] = '\0';
+ args++;
+ }
+ }
+ sp->task_cls = sp;
+ sp->cmd = GNUNET_strdup (tmp);
+ sp->cmd_args = GNUNET_strdup (args);
+ GNUNET_free (tmp);
+ sp->task = &exec_cmd;
+
+ /* type */
+ GNUNET_CONFIGURATION_get_value_string (properties, section, "TYPE", &tmp);
+ to_lower_str (tmp);
+ if (0 == strcasecmp(tmp, "static"))
+ sp->type = t_static;
+ else if (0 == strcasecmp(tmp, "continous"))
+ sp->type = t_continous;
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid value %s for %s in section `%s'\n",
+ tmp, "TYPE", section);
+ GNUNET_free (tmp);
+ GNUNET_free (sp);
+ return;
+ }
+ GNUNET_free (tmp);
+
+ /* value */
+ GNUNET_CONFIGURATION_get_value_string (properties, section, "VALUE", &tmp);
+ to_lower_str (tmp);
+ if (0 == strcasecmp(tmp, V_NUMERIC_STR))
+ sp->value_type = v_numeric;
+ else if (0 == strcasecmp(tmp, V_STRING_STR))
+ sp->value_type = v_string;
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid value %s for %s in section `%s'\n",
+ tmp, "VALUE", section);
+ GNUNET_free (tmp);
+ GNUNET_free (sp);
+ return;
+ }
+ GNUNET_free (tmp);
+
+ /* interval */
+ if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"INTERVAL"))
+ sp->interval = GNUNET_TIME_UNIT_MINUTES;
+ else
+ {
+ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (properties, section, "INTERVAL", &sp->interval))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Could not parse execution interval for `%s', set to default 60 sec.\n"), section);
+ sp->interval = GNUNET_TIME_UNIT_MINUTES;
+ }
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded property `%s': %s, %s, interval %llu\n",
+ (NULL != sp->desc) ? sp->desc: "<undefined>",
+ (t_continous == sp->type) ? "continious" : "static",
+ (v_numeric == sp->value_type) ? "numeric" : "string",
+ sp->interval.rel_value);
+
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+
+}
+
+static int
+load_default_properties (void)
+{
+ struct SysmonProperty *sp;
+ /* GNUnet version array */
+ unsigned int ver[3];
+
+ /* GNUnet vcs revision */
+ unsigned int revision;
+ /* version */
+#ifdef VERSION
+ if (3 != sscanf (VERSION, "%u.%u.%u", &ver[0], &ver[1], &ver[2]))
+ {
+ ver[0] = 0;
+ ver[1] = 0;
+ ver[2] = 0;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse version string `%s'\n", VERSION);
+ }
+#else
+ ver[0] = 0;
+ ver[1] = 0;
+ ver[2] = 0;
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Version string is undefined \n");
+#endif
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Version: %u.%u.%u\n", ver[0], ver[1], ver[2]);
+
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+ sp->desc = GNUNET_strdup ("GNUnet version");
+ sp->type = t_static;
+ sp->value_type = v_numeric;
+ sp->num_val = 100 * ver[0] + 10 * ver[1] + ver[2];
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+ /* revision */
+#ifdef VCS_VERSION
+ if (1 != sscanf (VCS_VERSION, "svn-%uM", &revision))
+ {
+ revision = 0;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse revision string `%s'\n", VCS_VERSION);
+ }
+#else
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "VCS revision string is undefined \n");
+ revision = 0;
+#endif
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Revision: %u\n", revision);
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+ sp->desc = GNUNET_strdup ("GNUnet vcs revision");
+ sp->type = t_static;
+ sp->value_type = v_numeric;
+ sp->num_val = (uint64_t) revision;
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+
+
+ /* GNUnet startup time */
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+ sp->desc = GNUNET_strdup ("GNUnet startup time");
+ sp->type = t_static;
+ sp->value_type = v_numeric;
+ sp->num_val = (uint64_t) GNUNET_TIME_absolute_get().abs_value;
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+
+
+ /* GNUnet sysmon daemon uptime in seconds */
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+ sp->desc = GNUNET_strdup ("GNUnet uptime");
+ sp->type = t_continous;
+ sp->value_type = v_numeric;
+ sp->num_val = (uint64_t) 0;
+ sp->interval = GNUNET_TIME_UNIT_MINUTES;
+ sp->task_id = GNUNET_SCHEDULER_NO_TASK;
+ sp->task = update_uptime;
+ sp->task_cls = sp;
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+ return GNUNET_OK;
+}
+
+#if HAVE_LIBGTOP
+static int
+load_gtop_properties (void)
+{
+ char *services;
+ char *s;
+ char *binary;
+ struct SysmonGtopProcProperty *pp;
+ struct SysmonProperty *sp;
+ struct GNUNET_TIME_Relative interval;
+
+ /* Load service memory monitoring tasks */
+ if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (cfg, "sysmon", "MONITOR_SERVICES"))
+ return GNUNET_OK;
+
+ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "sysmon", "MONITOR_SERVICES", &services))
+ return GNUNET_SYSERR;
+
+ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,"sysmon", "MONITOR_SERVICES_INTERVAL", &interval))
+ interval = GNUNET_TIME_UNIT_MINUTES;
+
+ s = strtok (services, " ");
+ while (NULL != s)
+ {
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, s, "BINARY", &binary))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Monitoring service `%s' with binary `%s'\n", s, binary);
+ pp = GNUNET_malloc (sizeof (struct SysmonGtopProcProperty));
+ pp->srv = GNUNET_strdup (s);
+ pp->binary = binary;
+ GNUNET_CONTAINER_DLL_insert (pp_head, pp_tail, pp);
+
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+ GNUNET_asprintf(&sp->desc, "Process Monitoring for service %s", s);
+ sp->type = t_continous;
+ sp->value_type = v_numeric;
+ sp->num_val = (uint64_t) 0;
+ sp->interval = interval;
+ sp->task_id = GNUNET_SCHEDULER_NO_TASK;
+ sp->task = exec_gtop_proc_mon;
+ sp->task_cls = pp;
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+ }
+ s = strtok (NULL, " ");
+ }
+ GNUNET_free (services);
+
+ /* Load network monitoring tasks */
+
+ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,"sysmon", "MONITOR_NETWORK_INTERVAL", &interval))
+ interval = GNUNET_TIME_UNIT_MINUTES;
+
+ sp = GNUNET_malloc (sizeof (struct SysmonProperty));
+ GNUNET_asprintf(&sp->desc, "Network interface monitoring");
+ sp->type = t_continous;
+ sp->value_type = v_numeric;
+ sp->num_val = (uint64_t) 0;
+ sp->interval = interval;
+ sp->task_id = GNUNET_SCHEDULER_NO_TASK;
+ sp->task = exec_gtop_net_mon;
+ sp->task_cls = sp;
+ GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
+
+ return GNUNET_OK;
+}
+#endif
+
+
+static void
+run_property (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct SysmonProperty *sp = cls;
+ sp->task_id = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running continous property `%s' \n", sp->desc);
+ sp->task (sp->task_cls, tc);
+ sp->task_id = GNUNET_SCHEDULER_add_delayed (sp->interval, &run_property, sp);
+}
+
+
+static int
+run_properties (void)
+{
+ struct SysmonProperty *sp;
+
+ for (sp = sp_head; NULL != sp; sp = sp->next)
+ {
+ if (t_static == sp->type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running static property `%s' \n", sp->desc);
+ put_property (sp);
+ }
+ else
+ {
+ if (NULL == sp->task)
+ {
+ GNUNET_break (0);
+ continue;
+ }
+ sp->task_id = GNUNET_SCHEDULER_add_now (&run_property, sp);
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Process template requests.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param mycfg configuration to use
+ */
+static void
+run (void *cls, struct GNUNET_SERVER_Handle *server,
+ const struct GNUNET_CONFIGURATION_Handle *mycfg)
+{
+ static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+ /* FIXME: add handlers here! */
+ {NULL, NULL, 0, 0}
+ };
+ /* FIXME: do setup here */
+ GNUNET_SERVER_add_handlers (server, handlers);
+
+ struct GNUNET_CONFIGURATION_Handle *properties;
+ char *file;
+
+ end_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL);
+ cfg = mycfg;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sysmon starting ... \n");
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (mycfg, "sysmon", "CFGFILE", &file))
+ {
+ properties = GNUNET_CONFIGURATION_create();
+ if (NULL == properties)
+ {
+ GNUNET_break (0);
+ shutdown_now();
+ ret = 1;
+ return;
+ }
+ if ((GNUNET_YES == GNUNET_DISK_file_test(file)) &&
+ (GNUNET_OK == GNUNET_CONFIGURATION_load (properties, file)))
+ GNUNET_CONFIGURATION_iterate_sections (properties, &load_property, properties);
+
+ GNUNET_CONFIGURATION_destroy (properties);
+ GNUNET_free (file);
+
+ /* Creating statistics */
+ stats = GNUNET_STATISTICS_create ("sysmon", mycfg);
+ if (NULL == stats)
+ {
+ GNUNET_break (0);
+ shutdown_now();
+ ret = 1;
+ return;
+ }
+ }
+
+ /* load properties */
+ if (GNUNET_SYSERR == load_default_properties ())
+ {
+ GNUNET_break (0);
+ shutdown_now();
+ ret = 1;
+ return;
+ }
+
+#if HAVE_LIBGTOP
+ if (NULL != glibtop_init())
+ if ( GNUNET_SYSERR == load_gtop_properties ())
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to load gtop properties \n");
+ }
+#endif
+
+ /* run properties */
+ if (GNUNET_SYSERR == run_properties ())
+ {
+ GNUNET_break (0);
+ shutdown_now();
+ ret = 1;
+ return;
+ }
+}
+
+
+/**
+ * The main function for the sysmon service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ return (GNUNET_OK ==
+ GNUNET_SERVICE_run (argc, argv, "sysmon",
+ GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
+}
+
+/* end of gnunet-service-sysmon.c */