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