Code

e7d193266e4d38622ff6ad35a659102cb605be50
[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  **/
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>
34 #include "graph_ident.h"
35 #include "common.h"
36 #include "filesystem.h"
37 #include "utils_cgi.h"
39 #include <fcgiapp.h>
40 #include <fcgi_stdio.h>
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 */
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);
63   if ((flags & IDENT_FLAG_REPLACE_ANY) && IS_ANY (part))
64     return (NULL);
66   if ((flags & IDENT_FLAG_REPLACE_ALL) && IS_ALL (part))
67     return (NULL);
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   }
79   if (IS_ALL (selector))
80   {
81     if (flags & IDENT_FLAG_REPLACE_ALL)
82       return (strdup (part));
83     else
84       return (strdup (selector));
85   }
87   if (strcmp (selector, part) != 0)
88     return (NULL);
90   /* Otherwise (no replacement), return a copy of the selector. */
91   return (strdup (selector));
92 } /* }}} char *part_copy_with_selector */
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
102   if (selector == NULL) /* && (part != NULL) */
103     return (0);
105   if (IS_ANY(selector) || IS_ALL(selector))
106     return (1);
108   if (part == NULL) /* && (selector != NULL) */
109     return (0);
111   if (strcmp (selector, part) == 0)
112     return (1);
114   return (0);
115 } /* }}} _Bool part_matches */
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)
124   graph_ident_t *ret;
126   if ((host == NULL)
127       || (plugin == NULL) || (plugin_instance == NULL)
128       || (type == NULL) || (type_instance == NULL))
129     return (NULL);
131   ret = malloc (sizeof (*ret));
132   if (ret == NULL)
133     return (NULL);
134   memset (ret, 0, sizeof (*ret));
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;
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)
157   COPY_PART(host);
158   COPY_PART(plugin);
159   COPY_PART(plugin_instance);
160   COPY_PART(type);
161   COPY_PART(type_instance);
163 #undef COPY_PART
165   return (ret);
166 } /* }}} graph_ident_t *ident_create */
168 graph_ident_t *ident_clone (const graph_ident_t *ident) /* {{{ */
170   return (ident_create (ident->host,
171         ident->plugin, ident->plugin_instance,
172         ident->type, ident->type_instance));
173 } /* }}} graph_ident_t *ident_clone */
175 graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector, /* {{{ */
176     const graph_ident_t *ident, unsigned int flags)
178   graph_ident_t *ret;
180   if ((selector == NULL) || (ident == NULL))
181     return (NULL);
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;
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)
206   COPY_PART (host);
207   COPY_PART (plugin);
208   COPY_PART (plugin_instance);
209   COPY_PART (type);
210   COPY_PART (type_instance);
212 #undef COPY_PART
214   return (ret);
215 } /* }}} graph_ident_t *ident_copy_with_selector */
217 void ident_destroy (graph_ident_t *ident) /* {{{ */
219   if (ident == NULL)
220     return;
222   free (ident->host);
223   free (ident->plugin);
224   free (ident->plugin_instance);
225   free (ident->type);
226   free (ident->type_instance);
228   free (ident);
229 } /* }}} void ident_destroy */
231 /* ident_get_* methods {{{ */
232 const char *ident_get_host (const graph_ident_t *ident) /* {{{ */
234   if (ident == NULL)
235     return (NULL);
237   return (ident->host);
238 } /* }}} char *ident_get_host */
240 const char *ident_get_plugin (const graph_ident_t *ident) /* {{{ */
242   if (ident == NULL)
243     return (NULL);
245   return (ident->plugin);
246 } /* }}} char *ident_get_plugin */
248 const char *ident_get_plugin_instance (const graph_ident_t *ident) /* {{{ */
250   if (ident == NULL)
251     return (NULL);
253   return (ident->plugin_instance);
254 } /* }}} char *ident_get_plugin_instance */
256 const char *ident_get_type (const graph_ident_t *ident) /* {{{ */
258   if (ident == NULL)
259     return (NULL);
261   return (ident->type);
262 } /* }}} char *ident_get_type */
264 const char *ident_get_type_instance (const graph_ident_t *ident) /* {{{ */
266   if (ident == NULL)
267     return (NULL);
269   return (ident->type_instance);
270 } /* }}} char *ident_get_type_instance */
272 const char *ident_get_field (const graph_ident_t *ident, /* {{{ */
273     graph_ident_field_t field)
275   if ((ident == NULL) || (field >= _GIF_LAST))
276     return (NULL);
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 */
293 /* ident_set_* methods {{{ */
294 int ident_set_host (graph_ident_t *ident, const char *host) /* {{{ */
296   char *tmp;
298   if ((ident == NULL) || (host == NULL))
299     return (EINVAL);
301   tmp = strdup (host);
302   if (tmp == NULL)
303     return (ENOMEM);
305   free (ident->host);
306   ident->host = tmp;
308   return (0);
309 } /* }}} int ident_set_host */
311 int ident_set_plugin (graph_ident_t *ident, const char *plugin) /* {{{ */
313   char *tmp;
315   if ((ident == NULL) || (plugin == NULL))
316     return (EINVAL);
318   tmp = strdup (plugin);
319   if (tmp == NULL)
320     return (ENOMEM);
322   free (ident->plugin);
323   ident->plugin = tmp;
325   return (0);
326 } /* }}} int ident_set_plugin */
328 int ident_set_plugin_instance (graph_ident_t *ident, const char *plugin_instance) /* {{{ */
330   char *tmp;
332   if ((ident == NULL) || (plugin_instance == NULL))
333     return (EINVAL);
335   tmp = strdup (plugin_instance);
336   if (tmp == NULL)
337     return (ENOMEM);
339   free (ident->plugin_instance);
340   ident->plugin_instance = tmp;
342   return (0);
343 } /* }}} int ident_set_plugin_instance */
345 int ident_set_type (graph_ident_t *ident, const char *type) /* {{{ */
347   char *tmp;
349   if ((ident == NULL) || (type == NULL))
350     return (EINVAL);
352   tmp = strdup (type);
353   if (tmp == NULL)
354     return (ENOMEM);
356   free (ident->type);
357   ident->type = tmp;
359   return (0);
360 } /* }}} int ident_set_type */
362 int ident_set_type_instance (graph_ident_t *ident, const char *type_instance) /* {{{ */
364   char *tmp;
366   if ((ident == NULL) || (type_instance == NULL))
367     return (EINVAL);
369   tmp = strdup (type_instance);
370   if (tmp == NULL)
371     return (ENOMEM);
373   free (ident->type_instance);
374   ident->type_instance = tmp;
376   return (0);
377 } /* }}} int ident_set_type_instance */
379 /* }}} ident_set_* methods */
381 int ident_compare (const graph_ident_t *i0, /* {{{ */
382     const graph_ident_t *i1)
384   int status;
386 #define COMPARE_PART(p) do {       \
387   status = strcmp (i0->p, i1->p);  \
388   if (status != 0)                 \
389     return (status);               \
390 } while (0)
392   COMPARE_PART (host);
393   COMPARE_PART (plugin);
394   COMPARE_PART (plugin_instance);
395   COMPARE_PART (type);
396   COMPARE_PART (type_instance);
398 #undef COMPARE_PART
400   return (0);
401 } /* }}} int ident_compare */
403 _Bool ident_matches (const graph_ident_t *selector, /* {{{ */
404     const graph_ident_t *ident)
406 #if C4_DEBUG
407   if ((selector == NULL) || (ident == NULL))
408     return (0);
409 #endif
411   if (!part_matches (selector->host, ident->host))
412     return (0);
414   if (!part_matches (selector->plugin, ident->plugin))
415     return (0);
417   if (!part_matches (selector->plugin_instance, ident->plugin_instance))
418     return (0);
420   if (!part_matches (selector->type, ident->type))
421     return (0);
423   if (!part_matches (selector->type_instance, ident->type_instance))
424     return (0);
426   return (1);
427 } /* }}} _Bool ident_matches */
429 _Bool ident_intersect (const graph_ident_t *s0, /* {{{ */
430     const graph_ident_t *s1)
432 #define INTERSECT_PART(p) do {                                               \
433   if (!IS_ANY (s0->p) && !IS_ALL (s0->p)                                     \
434       && !IS_ANY (s1->p) && !IS_ALL (s1->p)                                  \
435       && (strcmp (s0->p, s1->p) != 0))                                       \
436     return (0);                                                              \
437 } while (0)
439   INTERSECT_PART (host);
440   INTERSECT_PART (plugin);
441   INTERSECT_PART (plugin_instance);
442   INTERSECT_PART (type);
443   INTERSECT_PART (type_instance);
445 #undef INTERSECT_PART
447   return (1);
448 } /* }}} _Bool ident_intersect */
450 char *ident_to_string (const graph_ident_t *ident) /* {{{ */
452   char buffer[PATH_MAX];
454   buffer[0] = 0;
456   strlcat (buffer, ident->host, sizeof (buffer));
457   strlcat (buffer, "/", sizeof (buffer));
458   strlcat (buffer, ident->plugin, sizeof (buffer));
459   if (ident->plugin_instance[0] != 0)
460   {
461     strlcat (buffer, "-", sizeof (buffer));
462     strlcat (buffer, ident->plugin_instance, sizeof (buffer));
463   }
464   strlcat (buffer, "/", sizeof (buffer));
465   strlcat (buffer, ident->type, sizeof (buffer));
466   if (ident->type_instance[0] != 0)
467   {
468     strlcat (buffer, "-", sizeof (buffer));
469     strlcat (buffer, ident->type_instance, sizeof (buffer));
470   }
472   return (strdup (buffer));
473 } /* }}} char *ident_to_string */
475 char *ident_to_file (const graph_ident_t *ident) /* {{{ */
477   char buffer[PATH_MAX];
479   buffer[0] = 0;
481   strlcat (buffer, DATA_DIR, sizeof (buffer));
482   strlcat (buffer, "/", sizeof (buffer));
484   strlcat (buffer, ident->host, sizeof (buffer));
485   strlcat (buffer, "/", sizeof (buffer));
486   strlcat (buffer, ident->plugin, sizeof (buffer));
487   if (ident->plugin_instance[0] != 0)
488   {
489     strlcat (buffer, "-", sizeof (buffer));
490     strlcat (buffer, ident->plugin_instance, sizeof (buffer));
491   }
492   strlcat (buffer, "/", sizeof (buffer));
493   strlcat (buffer, ident->type, sizeof (buffer));
494   if (ident->type_instance[0] != 0)
495   {
496     strlcat (buffer, "-", sizeof (buffer));
497     strlcat (buffer, ident->type_instance, sizeof (buffer));
498   }
500   strlcat (buffer, ".rrd", sizeof (buffer));
502   return (strdup (buffer));
503 } /* }}} char *ident_to_file */
505 int ident_to_json (const graph_ident_t *ident, /* {{{ */
506     yajl_gen handler)
508   yajl_gen_status status;
510   if ((ident == NULL) || (handler == NULL))
511     return (EINVAL);
513 #define ADD_STRING(str) do {                              \
514   status = yajl_gen_string (handler,                      \
515       (unsigned char *) (str),                            \
516       (unsigned int) strlen (str));                       \
517   if (status != yajl_gen_status_ok)                       \
518     return ((int) status);                                \
519 } while (0)
521   yajl_gen_map_open (handler);
522   ADD_STRING ("host");
523   ADD_STRING (ident->host);
524   ADD_STRING ("plugin");
525   ADD_STRING (ident->plugin);
526   ADD_STRING ("plugin_instance");
527   ADD_STRING (ident->plugin_instance);
528   ADD_STRING ("type");
529   ADD_STRING (ident->type);
530   ADD_STRING ("type_instance");
531   ADD_STRING (ident->type_instance);
532   yajl_gen_map_close (handler);
534 #undef ADD_FIELD
536   return (0);
537 } /* }}} char *ident_to_json */
539 int ident_describe (const graph_ident_t *ident, /* {{{ */
540     const graph_ident_t *selector,
541     char *buffer, size_t buffer_size)
543   if ((ident == NULL) || (selector == NULL)
544       || (buffer == NULL) || (buffer_size < 2))
545     return (EINVAL);
547   buffer[0] = 0;
549 #define CHECK_FIELD(field) do {                                              \
550   if (strcasecmp (selector->field, ident->field) != 0)                       \
551   {                                                                          \
552     if (buffer[0] != 0)                                                      \
553       strlcat (buffer, "/", buffer_size);                                    \
554     strlcat (buffer, ident->field, buffer_size);                             \
555   }                                                                          \
556 } while (0)
558   CHECK_FIELD (host);
559   CHECK_FIELD (plugin);
560   CHECK_FIELD (plugin_instance);
561   CHECK_FIELD (type);
562   CHECK_FIELD (type_instance);
564 #undef CHECK_FIELD
566   if (buffer[0] == 0)
567     strlcat (buffer, "default", buffer_size);
569   return (0);
570 } /* }}} int ident_describe */
572 time_t ident_get_mtime (const graph_ident_t *ident) /* {{{ */
574   char *file;
575   struct stat statbuf;
576   int status;
578   if (ident == NULL)
579     return (0);
581   file = ident_to_file (ident);
582   if (file == NULL)
583     return (0);
585   memset (&statbuf, 0, sizeof (statbuf));
586   status = stat (file, &statbuf);
587   if (status != 0)
588   {
589     fprintf (stderr, "ident_get_mtime: stat'ing file \"%s\" failed: %s\n",
590         file, strerror (errno));
591     return (0);
592   }
594   free (file);
595   return (statbuf.st_mtime);
596 } /* }}} time_t ident_get_mtime */
598 /* vim: set sw=2 sts=2 et fdm=marker : */