2 This file is part of GNUnet.
3 (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file sysmon/gnunet-service-sysmon.c
23 * @brief system monitoring service
24 * @author Matthias Wachs
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
51 * A system property to monitor
56 * Next element in in the DLL
58 struct SysmonProperty *next;
61 * Previous element in in the DLL
63 struct SysmonProperty *prev;
65 struct SysmonGtopProcProperty *gtop_proc_head;
66 struct SysmonGtopProcProperty *gtop_proc_tail;
69 * Description used for statistics valuesd
86 struct GNUNET_TIME_Relative interval;
99 * Command execution handle
101 void * cmd_exec_handle;
116 GNUNET_SCHEDULER_TaskIdentifier task_id;
121 GNUNET_SCHEDULER_Task task;
126 * A system property to monitor
128 struct SysmonGtopProcProperty
130 struct SysmonGtopProcProperty *prev;
131 struct SysmonGtopProcProperty *next;
142 * Configuration handle
144 const struct GNUNET_CONFIGURATION_Handle *cfg;
150 struct GNUNET_STATISTICS_Handle *stats;
155 GNUNET_SCHEDULER_TaskIdentifier end_task;
157 struct SysmonProperty *sp_head;
158 struct SysmonProperty *sp_tail;
160 struct SysmonGtopProcProperty *pp_head;
161 struct SysmonGtopProcProperty *pp_tail;
164 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
166 struct SysmonProperty *sp;
167 struct SysmonProperty *next;
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sysdaemon stopping ... \n");
171 end_task = GNUNET_SCHEDULER_NO_TASK;
175 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
180 while (NULL != (sp = next))
182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping `%s' \n", sp->desc);
183 GNUNET_CONTAINER_DLL_remove (sp_head, sp_tail, sp);
185 if (GNUNET_SCHEDULER_NO_TASK != sp->task_id)
187 GNUNET_SCHEDULER_cancel (sp->task_id);
188 sp->task_id = GNUNET_SCHEDULER_NO_TASK;
190 GNUNET_free_non_null (sp->cmd);
191 GNUNET_free_non_null (sp->cmd_args);
192 GNUNET_free (sp->desc);
201 if (GNUNET_SCHEDULER_NO_TASK != end_task)
202 GNUNET_SCHEDULER_cancel (end_task);
203 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
207 to_lower_str (char * str)
210 for (c = 0; c <= strlen (str); c++)
211 str[c] = tolower(str[c]);
215 put_property (struct SysmonProperty *sp)
217 if (v_numeric ==sp->value_type)
219 fprintf (stderr, "%s : %s : %llu\n",
220 GNUNET_STRINGS_absolute_time_to_string(GNUNET_TIME_absolute_get()),
221 sp->desc, (unsigned long long) sp->num_val);
223 else if (v_string ==sp->value_type)
225 fprintf (stderr, "%s : %s : %s\n",
226 GNUNET_STRINGS_absolute_time_to_string(GNUNET_TIME_absolute_get()),
227 sp->desc, sp->str_val);
232 return GNUNET_SYSERR;
238 update_uptime (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
240 struct SysmonProperty *sp = cls;
241 static int first_run = GNUNET_YES;
243 if (GNUNET_YES == first_run)
244 first_run = GNUNET_NO;
246 sp->num_val += sp->interval.rel_value / 1000;
252 exec_cmd_proc (void *cls, const char *line)
254 struct SysmonProperty *sp = cls;
255 unsigned long long tmp;
256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property output: `%s'\n", line);
259 GNUNET_OS_command_stop (sp->cmd_exec_handle);
260 sp->cmd_exec_handle = NULL;
264 switch (sp->value_type) {
266 if (1 != sscanf (line, "%llu", &tmp))
268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Command output was not a numerical value: `%s'\n", line);
273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "NOT IMPLEMENTED\n");
281 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property output: `%s'\n", line);
288 exec_cmd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
290 struct SysmonProperty *sp = cls;
291 GNUNET_assert (NULL != sp->cmd);
293 if (NULL != sp->cmd_exec_handle)
295 GNUNET_OS_command_stop (sp->cmd_exec_handle);
296 sp->cmd_exec_handle = NULL;
299 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property `%s': command `%s' `%s'\n", sp->desc, sp->cmd, sp->cmd_args);
300 if (NULL == (sp->cmd_exec_handle = GNUNET_OS_command_run (&exec_cmd_proc, sp,
301 GNUNET_TIME_UNIT_SECONDS,
305 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Property `%s': command `%s' failed\n", sp->desc, sp->cmd);
309 exec_gtop_proc_mon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
311 //struct SysmonGtopProcProperty *sp = cls;
315 load_property (void *cls,
318 struct GNUNET_CONFIGURATION_Handle *properties = cls;
319 struct SysmonProperty *sp;
322 if (NULL == strstr (section, "sysmon-"))
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading section `%s'\n", section);
327 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section, "TYPE"))
329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
333 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"VALUE"))
335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
339 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"DESCRIPTION"))
341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
342 "DESCRIPTION", section);
345 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"CMD"))
347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
351 sp = GNUNET_malloc (sizeof (struct SysmonProperty));
354 GNUNET_CONFIGURATION_get_value_string (properties, section, "DESCRIPTION", &sp->desc);
357 GNUNET_CONFIGURATION_get_value_string (properties, section, "CMD", &tmp);
359 if (NULL != strchr (tmp, ' '))
361 args = strchr (tmp, ' ');
362 if (strlen (args) > 1)
368 sp->cmd = GNUNET_strdup (tmp);
369 sp->cmd_args = GNUNET_strdup (args);
371 sp->task = &exec_cmd;
374 GNUNET_CONFIGURATION_get_value_string (properties, section, "TYPE", &tmp);
376 if (0 == strcasecmp(tmp, "static"))
378 else if (0 == strcasecmp(tmp, "continous"))
379 sp->type = t_continous;
382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid value %s for %s in section `%s'\n",
383 tmp, "TYPE", section);
391 GNUNET_CONFIGURATION_get_value_string (properties, section, "VALUE", &tmp);
393 if (0 == strcasecmp(tmp, "numeric"))
394 sp->value_type = v_numeric;
395 else if (0 == strcasecmp(tmp, "string"))
396 sp->value_type = v_string;
399 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid value %s for %s in section `%s'\n",
400 tmp, "VALUE", section);
408 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (properties, section,"INTERVAL"))
409 sp->interval = GNUNET_TIME_UNIT_MINUTES;
412 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (properties, section, "INTERVAL", &sp->interval))
414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
415 _("Could not parse execution interval for `%s', set to default 60 sec.\n"), section);
416 sp->interval = GNUNET_TIME_UNIT_MINUTES;
420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded property `%s': %s, %s, interval %llu\n",
421 (NULL != sp->desc) ? sp->desc: "<undefined>",
422 (t_continous == sp->type) ? "continious" : "static",
423 (v_numeric == sp->value_type) ? "numeric" : "string",
424 sp->interval.rel_value);
426 GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
431 load_default_properties (void)
433 struct SysmonProperty *sp;
434 /* GNUnet version array */
437 /* GNUnet vcs revision */
438 unsigned int revision;
441 if (3 != sscanf (VERSION, "%u.%u.%u", &ver[0], &ver[1], &ver[2]))
446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse version string `%s'\n", VERSION);
452 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Version string is undefined \n");
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Version: %u.%u.%u\n", ver[0], ver[1], ver[2]);
456 sp = GNUNET_malloc (sizeof (struct SysmonProperty));
457 sp->desc = GNUNET_strdup ("GNUnet version");
459 sp->value_type = v_numeric;
460 sp->num_val = 100 * ver[0] + 10 * ver[1] + ver[2];
461 GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
464 if (1 != sscanf (VCS_VERSION, "svn-%uM", &revision))
467 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse revision string `%s'\n", VCS_VERSION);
470 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "VCS revision string is undefined \n");
473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Revision: %u\n", revision);
474 sp = GNUNET_malloc (sizeof (struct SysmonProperty));
475 sp->desc = GNUNET_strdup ("GNUnet vcs revision");
477 sp->value_type = v_numeric;
478 sp->num_val = (uint64_t) revision;
479 GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
482 /* GNUnet startup time */
483 sp = GNUNET_malloc (sizeof (struct SysmonProperty));
484 sp->desc = GNUNET_strdup ("GNUnet startup time");
486 sp->value_type = v_numeric;
487 sp->num_val = (uint64_t) GNUNET_TIME_absolute_get().abs_value;
488 GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
491 /* GNUnet sysmon daemon uptime in seconds */
492 sp = GNUNET_malloc (sizeof (struct SysmonProperty));
493 sp->desc = GNUNET_strdup ("GNUnet uptime");
494 sp->type = t_continous;
495 sp->value_type = v_numeric;
496 sp->num_val = (uint64_t) 0;
497 sp->interval = GNUNET_TIME_UNIT_MINUTES;
498 sp->task_id = GNUNET_SCHEDULER_NO_TASK;
499 sp->task = update_uptime;
500 GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
505 load_gtop_properties (void)
510 struct SysmonGtopProcProperty *pp;
512 /* Load network monitoring tasks */
514 /* Load service memory monitoring tasks */
515 if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (cfg, "sysmon", "MONITOR_SERVICES"))
518 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "sysmon", "MONITOR_SERVICES", &services))
519 return GNUNET_SYSERR;
521 s = strtok (services, " ");
525 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, s, "BINARY", &binary))
527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitoring service `%s' with binary `%s'\n", s, binary);
528 pp = GNUNET_malloc (sizeof (struct SysmonGtopProcProperty));
530 GNUNET_CONTAINER_DLL_insert (pp_head, pp_tail, pp);
533 s = strtok (NULL, " ");
535 GNUNET_free (services);
548 run_property (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
550 struct SysmonProperty *sp = cls;
551 sp->task_id = GNUNET_SCHEDULER_NO_TASK;
552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running continous property `%s' \n", sp->desc);
554 sp->task_id = GNUNET_SCHEDULER_add_delayed (sp->interval, &run_property, sp);
559 run_properties (void)
561 struct SysmonProperty *sp;
563 for (sp = sp_head; NULL != sp; sp = sp->next)
565 if (t_static == sp->type)
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running static property `%s' \n", sp->desc);
572 if (NULL == sp->task)
577 sp->task_id = GNUNET_SCHEDULER_add_now (&run_property, sp);
585 * Task run during shutdown.
591 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
593 struct SysmonGtopProcProperty *cur;
594 struct SysmonGtopProcProperty *next;
597 while (NULL != (cur = next))
600 GNUNET_CONTAINER_DLL_remove (pp_head, pp_tail, cur);
601 GNUNET_free (cur->binary);
609 * Process template requests.
612 * @param server the initialized server
613 * @param mycfg configuration to use
616 run (void *cls, struct GNUNET_SERVER_Handle *server,
617 const struct GNUNET_CONFIGURATION_Handle *mycfg)
619 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
620 /* FIXME: add handlers here! */
623 /* FIXME: do setup here */
624 GNUNET_SERVER_add_handlers (server, handlers);
625 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
628 struct GNUNET_CONFIGURATION_Handle *properties;
631 end_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL);
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sysdaemon starting ... \n");
636 if (GNUNET_SYSERR ==GNUNET_CONFIGURATION_get_value_filename (mycfg, "sysmon", "CFGFILE", &file))
638 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sysmon configuration file not set, exit! \n");
644 properties = GNUNET_CONFIGURATION_create();
645 if (NULL == properties)
652 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (properties, file))
655 GNUNET_CONFIGURATION_destroy (properties);
662 GNUNET_CONFIGURATION_iterate_sections (properties, &load_property, properties);
664 GNUNET_CONFIGURATION_destroy (properties);
666 /* Creating statistics */
667 stats = GNUNET_STATISTICS_create ("sysmon", mycfg);
676 /* load properties */
677 if (GNUNET_SYSERR == load_default_properties ())
686 if (GNUNET_SYSERR == load_gtop_properties ())
688 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to load gtop properties \n");
693 if (GNUNET_SYSERR == run_properties ())
704 * The main function for the template service.
706 * @param argc number of arguments from the command line
707 * @param argv command line arguments
708 * @return 0 ok, 1 on error
711 main (int argc, char *const *argv)
714 GNUNET_SERVICE_run (argc, argv, "sysmon",
715 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
718 /* end of gnunet-service-sysmon.c */