changes
[oweals/gnunet.git] / src / sysmon / gnunet-daemon-sysmon.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
4
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.
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      General Public License for more details.
14
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.
19 */
20
21 /**
22  * @file sysmon/gnunet-daemon-sysmon.c
23  * @brief system monitoring aemon
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
29
30 enum type
31 {
32   t_static,
33   t_continous
34 };
35
36 enum value
37 {
38   v_numeric,
39   v_string
40 };
41
42 struct SysmonProperty
43 {
44   struct SysmonProperty *next;
45   struct SysmonProperty *prev;
46
47  char * desc;
48  int type;
49  int value;
50  struct GNUNET_TIME_Relative interval;
51 };
52
53 /**
54  * Final status code.
55  */
56 static int ret;
57
58 /**
59  * Configuration handle
60  */
61 const struct GNUNET_CONFIGURATION_Handle *cfg;
62
63
64 /**
65  * Statistics handle
66  */
67 struct GNUNET_STATISTICS_Handle *stats;
68
69 /**
70  * Shutdown task
71  */
72
73 GNUNET_SCHEDULER_TaskIdentifier end_task;
74
75 struct SysmonProperty *sp_head;
76 struct SysmonProperty *sp_tail;
77
78 static void
79 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
80 {
81   struct SysmonProperty *sp;
82   struct SysmonProperty *next;
83
84   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sysdaemon stopping ... \n");
85
86   end_task = GNUNET_SCHEDULER_NO_TASK;
87
88   if (NULL != stats)
89   {
90     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
91     stats = NULL;
92   }
93
94   next = sp_head;
95   while (NULL != (sp = next))
96   {
97       GNUNET_CONTAINER_DLL_remove (sp_head, sp_tail, sp);
98       next = sp->next;
99       GNUNET_free_non_null (sp->desc);
100       GNUNET_free (sp);
101   }
102
103 }
104
105 static void
106 shutdown_now ()
107 {
108   if (GNUNET_SCHEDULER_NO_TASK != end_task)
109     GNUNET_SCHEDULER_cancel (end_task);
110   GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
111 }
112
113 static void
114 to_lower_str (char * str)
115 {
116   int c;
117   for (c = 0; c <= strlen (str); c++)
118     str[c] = tolower(str[c]);
119 }
120
121 void load_property (void *cls,
122                     const char *section)
123 {
124   struct GNUNET_CONFIGURATION_Handle *properties = cls;
125   struct SysmonProperty *sp;
126   char *tmp;
127
128   if (NULL == strstr (section, "sysmon-"))
129     return;
130
131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading section `%s'\n", section);
132
133   if (GNUNET_NO == GNUNET_CONFIGURATION_have_value(properties, section, "TYPE"))
134   {
135     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
136         "TYPE", section);
137     return;
138   }
139   if (GNUNET_NO == GNUNET_CONFIGURATION_have_value(properties, section,"VALUE"))
140   {
141     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing value %s in section `%s'\n",
142         "VALUE", section);
143     return;
144   }
145
146
147   sp = GNUNET_malloc (sizeof (struct SysmonProperty));
148
149   /* description */
150   GNUNET_CONFIGURATION_get_value_string(properties, section, "DESCRIPTION", &sp->desc);
151
152   /* type */
153   GNUNET_CONFIGURATION_get_value_string(properties, section, "TYPE", &tmp);
154   to_lower_str (tmp);
155   if (0 == strcasecmp(tmp, "static"))
156     sp->type = t_static;
157   else if (0 == strcasecmp(tmp, "continous"))
158     sp->type = t_continous;
159   else
160   {
161     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid value %s for %s in section `%s'\n",
162         tmp, "TYPE", section);
163     GNUNET_free (tmp);
164     GNUNET_free (sp);
165     return;
166   }
167   GNUNET_free (tmp);
168
169   /* value */
170   GNUNET_CONFIGURATION_get_value_string(properties, section, "VALUE", &tmp);
171   to_lower_str (tmp);
172   if (0 == strcasecmp(tmp, "numeric"))
173     sp->value = v_numeric;
174   else if (0 == strcasecmp(tmp, "string"))
175     sp->value = v_string;
176   else
177   {
178     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid value %s for %s in section `%s'\n",
179         tmp, "VALUE", section);
180     GNUNET_free (tmp);
181     GNUNET_free (sp);
182     return;
183   }
184   GNUNET_free (tmp);
185   /* interval */
186
187   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded property `%s': type %u, value %u,\n",
188       (NULL != sp->desc) ? sp->desc: "<undefined>",
189       sp->type, sp->value);
190
191   GNUNET_CONTAINER_DLL_insert (sp_head, sp_tail, sp);
192
193 }
194
195 /**
196  * Main function that will be run by the scheduler.
197  *
198  * @param cls closure
199  * @param args remaining command-line arguments
200  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
201  * @param cfg configuration
202  */
203 static void
204 run (void *cls, char *const *args, const char *cfgfile,
205      const struct GNUNET_CONFIGURATION_Handle *mycfg)
206 {
207   struct GNUNET_CONFIGURATION_Handle *properties;
208   char *file;
209
210   end_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL);
211   cfg = mycfg;
212
213   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sysdaemon starting ... \n");
214
215   if (GNUNET_SYSERR ==GNUNET_CONFIGURATION_get_value_filename (mycfg, "sysmon", "CFGFILE", &file))
216   {
217     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sysmon configuration file not set, exit! \n");
218     shutdown_now();
219     ret = 1;
220     return;
221   }
222
223   properties = GNUNET_CONFIGURATION_create();
224   if (NULL == properties)
225   {
226     GNUNET_break (0);
227     shutdown_now();
228     ret = 1;
229     return;
230   }
231   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (properties, file))
232   {
233       GNUNET_break (0);
234       GNUNET_CONFIGURATION_destroy (properties);
235       GNUNET_free (file);
236       ret = 1;
237       shutdown_now();
238       return;
239   }
240   GNUNET_free (file);
241   GNUNET_CONFIGURATION_iterate_sections (properties, &load_property, properties);
242
243   GNUNET_CONFIGURATION_destroy (properties);
244
245   /* Creating statistics */
246   stats = GNUNET_STATISTICS_create ("sysmon", mycfg);
247   if (NULL == stats)
248   {
249     GNUNET_break (0);
250     shutdown_now();
251     ret = 1;
252     return;
253   }
254
255 }
256
257
258 /**
259  * The main function.
260  *
261  * @param argc number of arguments from the command line
262  * @param argv command line arguments
263  * @return 0 ok, 1 on error
264  */
265 int
266 main (int argc, char *const *argv)
267 {
268   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
269     GNUNET_GETOPT_OPTION_END
270   };
271   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
272     return 2;
273
274   ret = (GNUNET_OK ==
275          GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-sysmon",
276                              gettext_noop ("GNUnet system monitoring and information daemon"), options, &run,
277                              NULL)) ? ret : 1;
278   GNUNET_free ((void*) argv);
279   return ret;
280 }
281
282 /* end of gnunet-daemon-sysmon.c */