src/graph.c: Compare instances with "inst_compare" not "ident_compare".
[collection4.git] / src / graph_ident.c
1 /**
2  * collection4 - graph_ident.c
3  * Copyright (C) 2010  Florian octo Forster
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors:
21  *   Florian octo Forster <ff at octo.it>
22  **/
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <errno.h>
30 #include <limits.h> /* PATH_MAX */
31 #include <sys/types.h>
32 #include <sys/stat.h>
33
34 #include "graph_ident.h"
35 #include "common.h"
36 #include "filesystem.h"
37 #include "utils_cgi.h"
38
39 #include <fcgiapp.h>
40 #include <fcgi_stdio.h>
41
42 /*
43  * Data types
44  */
45 struct graph_ident_s /* {{{ */
46 {
47   char *host;
48   char *plugin;
49   char *plugin_instance;
50   char *type;
51   char *type_instance;
52 }; /* }}} struct graph_ident_s */
53
54 /*
55  * Private functions
56  */
57 static char *part_copy_with_selector (const char *selector, /* {{{ */
58     const char *part, unsigned int flags)
59 {
60   if ((selector == NULL) || (part == NULL))
61     return (NULL);
62
63   if ((flags & IDENT_FLAG_REPLACE_ANY) && IS_ANY (part))
64     return (NULL);
65
66   if ((flags & IDENT_FLAG_REPLACE_ALL) && IS_ALL (part))
67     return (NULL);
68
69   /* Replace the ANY and ALL flags if requested and if the selecter actually
70    * *is* that flag. */
71   if (IS_ANY (selector))
72   {
73     if (flags & IDENT_FLAG_REPLACE_ANY)
74       return (strdup (part));
75     else
76       return (strdup (selector));
77   }
78
79   if (IS_ALL (selector))
80   {
81     if (flags & IDENT_FLAG_REPLACE_ALL)
82       return (strdup (part));
83     else
84       return (strdup (selector));
85   }
86
87   if (strcmp (selector, part) != 0)
88     return (NULL);
89
90   /* Otherwise (no replacement), return a copy of the selector. */
91   return (strdup (selector));
92 } /* }}} char *part_copy_with_selector */
93
94 static _Bool part_matches (const char *selector, /* {{{ */
95     const char *part)
96 {
97 #if C4_DEBUG
98   if ((selector == NULL) && (part == NULL))
99     return (1);
100 #endif
101
102   if (selector == NULL) /* && (part != NULL) */
103     return (0);
104
105   if (IS_ANY(selector) || IS_ALL(selector))
106     return (1);
107
108   if (part == NULL) /* && (selector != NULL) */
109     return (0);
110
111   if (strcmp (selector, part) == 0)
112     return (1);
113
114   return (0);
115 } /* }}} _Bool part_matches */
116
117 /*
118  * Public functions
119  */
120 graph_ident_t *ident_create (const char *host, /* {{{ */
121     const char *plugin, const char *plugin_instance,
122     const char *type, const char *type_instance)
123 {
124   graph_ident_t *ret;
125
126   if ((host == NULL)
127       || (plugin == NULL) || (plugin_instance == NULL)
128       || (type == NULL) || (type_instance == NULL))
129     return (NULL);
130
131   ret = malloc (sizeof (*ret));
132   if (ret == NULL)
133     return (NULL);
134   memset (ret, 0, sizeof (*ret));
135
136   ret->host = NULL;
137   ret->host = NULL;
138   ret->plugin = NULL;
139   ret->plugin_instance = NULL;
140   ret->type = NULL;
141   ret->type_instance = NULL;
142
143 #define COPY_PART(p) do {        \
144   ret->p = strdup (p);           \
145   if (ret->p == NULL)            \
146   {                              \
147     free (ret->host);            \
148     free (ret->plugin);          \
149     free (ret->plugin_instance); \
150     free (ret->type);            \
151     free (ret->type_instance);   \
152     free (ret);                  \
153     return (NULL);               \
154   }                              \
155 } while (0)
156
157   COPY_PART(host);
158   COPY_PART(plugin);
159   COPY_PART(plugin_instance);
160   COPY_PART(type);
161   COPY_PART(type_instance);
162
163 #undef COPY_PART
164
165   return (ret);
166 } /* }}} graph_ident_t *ident_create */
167
168 graph_ident_t *ident_clone (const graph_ident_t *ident) /* {{{ */
169 {
170   return (ident_create (ident->host,
171         ident->plugin, ident->plugin_instance,
172         ident->type, ident->type_instance));
173 } /* }}} graph_ident_t *ident_clone */
174
175 graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector, /* {{{ */
176     const graph_ident_t *ident, unsigned int flags)
177 {
178   graph_ident_t *ret;
179
180   if ((selector == NULL) || (ident == NULL))
181     return (NULL);
182
183   ret = malloc (sizeof (*ret));
184   if (ret == NULL)
185     return (NULL);
186   memset (ret, 0, sizeof (*ret));
187   ret->host = NULL;
188   ret->plugin = NULL;
189   ret->plugin_instance = NULL;
190   ret->type = NULL;
191   ret->type_instance = NULL;
192
193 #define COPY_PART(p) do {                                  \
194   ret->p = part_copy_with_selector (selector->p, ident->p, flags); \
195   if (ret->p == NULL)                                      \
196   {                                                        \
197     free (ret->host);                                      \
198     free (ret->plugin);                                    \
199     free (ret->plugin_instance);                           \
200     free (ret->type);                                      \
201     free (ret->type_instance);                             \
202     return (NULL);                                         \
203   }                                                        \
204 } while (0)
205
206   COPY_PART (host);
207   COPY_PART (plugin);
208   COPY_PART (plugin_instance);
209   COPY_PART (type);
210   COPY_PART (type_instance);
211
212 #undef COPY_PART
213
214   return (ret);
215 } /* }}} graph_ident_t *ident_copy_with_selector */
216
217 void ident_destroy (graph_ident_t *ident) /* {{{ */
218 {
219   if (ident == NULL)
220     return;
221
222   free (ident->host);
223   free (ident->plugin);
224   free (ident->plugin_instance);
225   free (ident->type);
226   free (ident->type_instance);
227
228   free (ident);
229 } /* }}} void ident_destroy */
230
231 /* ident_get_* methods {{{ */
232 const char *ident_get_host (const graph_ident_t *ident) /* {{{ */
233 {
234   if (ident == NULL)
235     return (NULL);
236
237   return (ident->host);
238 } /* }}} char *ident_get_host */
239
240 const char *ident_get_plugin (const graph_ident_t *ident) /* {{{ */
241 {
242   if (ident == NULL)
243     return (NULL);
244
245   return (ident->plugin);
246 } /* }}} char *ident_get_plugin */
247
248 const char *ident_get_plugin_instance (const graph_ident_t *ident) /* {{{ */
249 {
250   if (ident == NULL)
251     return (NULL);
252
253   return (ident->plugin_instance);
254 } /* }}} char *ident_get_plugin_instance */
255
256 const char *ident_get_type (const graph_ident_t *ident) /* {{{ */
257 {
258   if (ident == NULL)
259     return (NULL);
260
261   return (ident->type);
262 } /* }}} char *ident_get_type */
263
264 const char *ident_get_type_instance (const graph_ident_t *ident) /* {{{ */
265 {
266   if (ident == NULL)
267     return (NULL);
268
269   return (ident->type_instance);
270 } /* }}} char *ident_get_type_instance */
271
272 const char *ident_get_field (const graph_ident_t *ident, /* {{{ */
273     graph_ident_field_t field)
274 {
275   if ((ident == NULL) || (field >= _GIF_LAST))
276     return (NULL);
277
278   if (field == GIF_HOST)
279     return (ident->host);
280   else if (field == GIF_PLUGIN)
281     return (ident->plugin);
282   else if (field == GIF_PLUGIN_INSTANCE)
283     return (ident->plugin_instance);
284   else if (field == GIF_TYPE)
285     return (ident->type);
286   else if (field == GIF_TYPE_INSTANCE)
287     return (ident->type_instance);
288   else
289     return (NULL); /* never reached */
290 } /* }}} const char *ident_get_field */
291 /* }}} ident_get_* methods */
292
293 /* ident_set_* methods {{{ */
294 int ident_set_host (graph_ident_t *ident, const char *host) /* {{{ */
295 {
296   char *tmp;
297
298   if ((ident == NULL) || (host == NULL))
299     return (EINVAL);
300
301   tmp = strdup (host);
302   if (tmp == NULL)
303     return (ENOMEM);
304
305   free (ident->host);
306   ident->host = tmp;
307
308   return (0);
309 } /* }}} int ident_set_host */
310
311 int ident_set_plugin (graph_ident_t *ident, const char *plugin) /* {{{ */
312 {
313   char *tmp;
314
315   if ((ident == NULL) || (plugin == NULL))
316     return (EINVAL);
317
318   tmp = strdup (plugin);
319   if (tmp == NULL)
320     return (ENOMEM);
321
322   free (ident->plugin);
323   ident->plugin = tmp;
324
325   return (0);
326 } /* }}} int ident_set_plugin */
327
328 int ident_set_plugin_instance (graph_ident_t *ident, const char *plugin_instance) /* {{{ */
329 {
330   char *tmp;
331
332   if ((ident == NULL) || (plugin_instance == NULL))
333     return (EINVAL);
334
335   tmp = strdup (plugin_instance);
336   if (tmp == NULL)
337     return (ENOMEM);
338
339   free (ident->plugin_instance);
340   ident->plugin_instance = tmp;
341
342   return (0);
343 } /* }}} int ident_set_plugin_instance */
344
345 int ident_set_type (graph_ident_t *ident, const char *type) /* {{{ */
346 {
347   char *tmp;
348
349   if ((ident == NULL) || (type == NULL))
350     return (EINVAL);
351
352   tmp = strdup (type);
353   if (tmp == NULL)
354     return (ENOMEM);
355
356   free (ident->type);
357   ident->type = tmp;
358
359   return (0);
360 } /* }}} int ident_set_type */
361
362 int ident_set_type_instance (graph_ident_t *ident, const char *type_instance) /* {{{ */
363 {
364   char *tmp;
365
366   if ((ident == NULL) || (type_instance == NULL))
367     return (EINVAL);
368
369   tmp = strdup (type_instance);
370   if (tmp == NULL)
371     return (ENOMEM);
372
373   free (ident->type_instance);
374   ident->type_instance = tmp;
375
376   return (0);
377 } /* }}} int ident_set_type_instance */
378
379 /* }}} ident_set_* methods */
380
381 int ident_compare (const graph_ident_t *i0, /* {{{ */
382     const graph_ident_t *i1)
383 {
384   int status;
385
386 #define COMPARE_PART(p) do {       \
387   status = strcmp (i0->p, i1->p);  \
388   if (status != 0)                 \
389     return (status);               \
390 } while (0)
391
392   COMPARE_PART (host);
393   COMPARE_PART (plugin);
394   COMPARE_PART (plugin_instance);
395   COMPARE_PART (type);
396   COMPARE_PART (type_instance);
397
398 #undef COMPARE_PART
399
400   return (0);
401 } /* }}} int ident_compare */
402
403 _Bool ident_matches (const graph_ident_t *selector, /* {{{ */
404     const graph_ident_t *ident)
405 {
406 #if C4_DEBUG
407   if ((selector == NULL) || (ident == NULL))
408     return (0);
409 #endif
410
411   if (!part_matches (selector->host, ident->host))
412     return (0);
413
414   if (!part_matches (selector->plugin, ident->plugin))
415     return (0);
416
417   if (!part_matches (selector->plugin_instance, ident->plugin_instance))
418     return (0);
419
420   if (!part_matches (selector->type, ident->type))
421     return (0);
422
423   if (!part_matches (selector->type_instance, ident->type_instance))
424     return (0);
425
426   return (1);
427 } /* }}} _Bool ident_matches */
428
429 char *ident_to_string (const graph_ident_t *ident) /* {{{ */
430 {
431   char buffer[PATH_MAX];
432
433   buffer[0] = 0;
434
435   strlcat (buffer, ident->host, sizeof (buffer));
436   strlcat (buffer, "/", sizeof (buffer));
437   strlcat (buffer, ident->plugin, sizeof (buffer));
438   if (ident->plugin_instance[0] != 0)
439   {
440     strlcat (buffer, "-", sizeof (buffer));
441     strlcat (buffer, ident->plugin_instance, sizeof (buffer));
442   }
443   strlcat (buffer, "/", sizeof (buffer));
444   strlcat (buffer, ident->type, sizeof (buffer));
445   if (ident->type_instance[0] != 0)
446   {
447     strlcat (buffer, "-", sizeof (buffer));
448     strlcat (buffer, ident->type_instance, sizeof (buffer));
449   }
450
451   return (strdup (buffer));
452 } /* }}} char *ident_to_string */
453
454 char *ident_to_file (const graph_ident_t *ident) /* {{{ */
455 {
456   char buffer[PATH_MAX];
457
458   buffer[0] = 0;
459
460   strlcat (buffer, DATA_DIR, sizeof (buffer));
461   strlcat (buffer, "/", sizeof (buffer));
462
463   strlcat (buffer, ident->host, sizeof (buffer));
464   strlcat (buffer, "/", sizeof (buffer));
465   strlcat (buffer, ident->plugin, sizeof (buffer));
466   if (ident->plugin_instance[0] != 0)
467   {
468     strlcat (buffer, "-", sizeof (buffer));
469     strlcat (buffer, ident->plugin_instance, sizeof (buffer));
470   }
471   strlcat (buffer, "/", sizeof (buffer));
472   strlcat (buffer, ident->type, sizeof (buffer));
473   if (ident->type_instance[0] != 0)
474   {
475     strlcat (buffer, "-", sizeof (buffer));
476     strlcat (buffer, ident->type_instance, sizeof (buffer));
477   }
478
479   strlcat (buffer, ".rrd", sizeof (buffer));
480
481   return (strdup (buffer));
482 } /* }}} char *ident_to_file */
483
484 #define ADD_FIELD(field) do {                              \
485   char json[1024];                                         \
486   json_escape_copy (json, ident->field, sizeof (json));    \
487   strlcat (buffer, json, sizeof (buffer));                 \
488 } while (0)
489
490 char *ident_to_json (const graph_ident_t *ident) /* {{{ */
491 {
492   char buffer[4096];
493
494   buffer[0] = 0;
495
496   strlcat (buffer, "{\"host\":\"", sizeof (buffer));
497   ADD_FIELD (host);
498   strlcat (buffer, "\",\"plugin\":\"", sizeof (buffer));
499   ADD_FIELD (plugin);
500   strlcat (buffer, "\",\"plugin_instance\":\"", sizeof (buffer));
501   ADD_FIELD (plugin_instance);
502   strlcat (buffer, "\",\"type\":\"", sizeof (buffer));
503   ADD_FIELD (type);
504   strlcat (buffer, "\",\"type_instance\":\"", sizeof (buffer));
505   ADD_FIELD (type_instance);
506   strlcat (buffer, "\"}", sizeof (buffer));
507
508   return (strdup (buffer));
509 } /* }}} char *ident_to_json */
510
511 #undef ADD_FIELD
512
513 time_t ident_get_mtime (const graph_ident_t *ident) /* {{{ */
514 {
515   char *file;
516   struct stat statbuf;
517   int status;
518
519   if (ident == NULL)
520     return (0);
521
522   file = ident_to_file (ident);
523   if (file == NULL)
524     return (0);
525
526   memset (&statbuf, 0, sizeof (statbuf));
527   status = stat (file, &statbuf);
528   if (status != 0)
529   {
530     fprintf (stderr, "ident_get_mtime: stat'ing file \"%s\" failed: %s\n",
531         file, strerror (errno));
532     return (0);
533   }
534
535   free (file);
536   return (statbuf.st_mtime);
537 } /* }}} time_t ident_get_mtime */
538
539 /* vim: set sw=2 sts=2 et fdm=marker : */
540