2 * collection4 - graph_ident.c
3 * Copyright (C) 2010 Florian octo Forster
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.
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.
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
21 * Florian octo Forster <ff at octo.it>
30 #include <limits.h> /* PATH_MAX */
31 #include <sys/types.h>
34 #include "graph_ident.h"
36 #include "data_provider.h"
37 #include "filesystem.h"
38 #include "utils_cgi.h"
41 #include <fcgi_stdio.h>
46 struct graph_ident_s /* {{{ */
50 char *plugin_instance;
53 }; /* }}} struct graph_ident_s */
58 static char *part_copy_with_selector (const char *selector, /* {{{ */
59 const char *part, unsigned int flags)
61 if ((selector == NULL) || (part == NULL))
64 if ((flags & IDENT_FLAG_REPLACE_ANY) && IS_ANY (part))
67 if ((flags & IDENT_FLAG_REPLACE_ALL) && IS_ALL (part))
70 /* Replace the ANY and ALL flags if requested and if the selecter actually
72 if (IS_ANY (selector))
74 if (flags & IDENT_FLAG_REPLACE_ANY)
75 return (strdup (part));
77 return (strdup (selector));
80 if (IS_ALL (selector))
82 if (flags & IDENT_FLAG_REPLACE_ALL)
83 return (strdup (part));
85 return (strdup (selector));
88 if (strcmp (selector, part) != 0)
91 /* Otherwise (no replacement), return a copy of the selector. */
92 return (strdup (selector));
93 } /* }}} char *part_copy_with_selector */
95 static _Bool part_matches (const char *selector, /* {{{ */
99 if ((selector == NULL) && (part == NULL))
103 if (selector == NULL) /* && (part != NULL) */
106 if (IS_ANY(selector) || IS_ALL(selector))
109 if (part == NULL) /* && (selector != NULL) */
112 if (strcmp (selector, part) == 0)
116 } /* }}} _Bool part_matches */
121 graph_ident_t *ident_create (const char *host, /* {{{ */
122 const char *plugin, const char *plugin_instance,
123 const char *type, const char *type_instance)
128 || (plugin == NULL) || (plugin_instance == NULL)
129 || (type == NULL) || (type_instance == NULL))
132 ret = malloc (sizeof (*ret));
135 memset (ret, 0, sizeof (*ret));
140 ret->plugin_instance = NULL;
142 ret->type_instance = NULL;
144 #define COPY_PART(p) do { \
145 ret->p = strdup (p); \
146 if (ret->p == NULL) \
149 free (ret->plugin); \
150 free (ret->plugin_instance); \
152 free (ret->type_instance); \
160 COPY_PART(plugin_instance);
162 COPY_PART(type_instance);
167 } /* }}} graph_ident_t *ident_create */
169 graph_ident_t *ident_clone (const graph_ident_t *ident) /* {{{ */
171 return (ident_create (ident->host,
172 ident->plugin, ident->plugin_instance,
173 ident->type, ident->type_instance));
174 } /* }}} graph_ident_t *ident_clone */
176 graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector, /* {{{ */
177 const graph_ident_t *ident, unsigned int flags)
181 if ((selector == NULL) || (ident == NULL))
184 ret = malloc (sizeof (*ret));
187 memset (ret, 0, sizeof (*ret));
190 ret->plugin_instance = NULL;
192 ret->type_instance = NULL;
194 #define COPY_PART(p) do { \
195 ret->p = part_copy_with_selector (selector->p, ident->p, flags); \
196 if (ret->p == NULL) \
199 free (ret->plugin); \
200 free (ret->plugin_instance); \
202 free (ret->type_instance); \
209 COPY_PART (plugin_instance);
211 COPY_PART (type_instance);
216 } /* }}} graph_ident_t *ident_copy_with_selector */
218 void ident_destroy (graph_ident_t *ident) /* {{{ */
224 free (ident->plugin);
225 free (ident->plugin_instance);
227 free (ident->type_instance);
230 } /* }}} void ident_destroy */
232 /* ident_get_* methods {{{ */
233 const char *ident_get_host (const graph_ident_t *ident) /* {{{ */
238 return (ident->host);
239 } /* }}} char *ident_get_host */
241 const char *ident_get_plugin (const graph_ident_t *ident) /* {{{ */
246 return (ident->plugin);
247 } /* }}} char *ident_get_plugin */
249 const char *ident_get_plugin_instance (const graph_ident_t *ident) /* {{{ */
254 return (ident->plugin_instance);
255 } /* }}} char *ident_get_plugin_instance */
257 const char *ident_get_type (const graph_ident_t *ident) /* {{{ */
262 return (ident->type);
263 } /* }}} char *ident_get_type */
265 const char *ident_get_type_instance (const graph_ident_t *ident) /* {{{ */
270 return (ident->type_instance);
271 } /* }}} char *ident_get_type_instance */
273 const char *ident_get_field (const graph_ident_t *ident, /* {{{ */
274 graph_ident_field_t field)
276 if ((ident == NULL) || (field >= _GIF_LAST))
279 if (field == GIF_HOST)
280 return (ident->host);
281 else if (field == GIF_PLUGIN)
282 return (ident->plugin);
283 else if (field == GIF_PLUGIN_INSTANCE)
284 return (ident->plugin_instance);
285 else if (field == GIF_TYPE)
286 return (ident->type);
287 else if (field == GIF_TYPE_INSTANCE)
288 return (ident->type_instance);
290 return (NULL); /* never reached */
291 } /* }}} const char *ident_get_field */
292 /* }}} ident_get_* methods */
294 /* ident_set_* methods {{{ */
295 int ident_set_host (graph_ident_t *ident, const char *host) /* {{{ */
299 if ((ident == NULL) || (host == NULL))
310 } /* }}} int ident_set_host */
312 int ident_set_plugin (graph_ident_t *ident, const char *plugin) /* {{{ */
316 if ((ident == NULL) || (plugin == NULL))
319 tmp = strdup (plugin);
323 free (ident->plugin);
327 } /* }}} int ident_set_plugin */
329 int ident_set_plugin_instance (graph_ident_t *ident, const char *plugin_instance) /* {{{ */
333 if ((ident == NULL) || (plugin_instance == NULL))
336 tmp = strdup (plugin_instance);
340 free (ident->plugin_instance);
341 ident->plugin_instance = tmp;
344 } /* }}} int ident_set_plugin_instance */
346 int ident_set_type (graph_ident_t *ident, const char *type) /* {{{ */
350 if ((ident == NULL) || (type == NULL))
361 } /* }}} int ident_set_type */
363 int ident_set_type_instance (graph_ident_t *ident, const char *type_instance) /* {{{ */
367 if ((ident == NULL) || (type_instance == NULL))
370 tmp = strdup (type_instance);
374 free (ident->type_instance);
375 ident->type_instance = tmp;
378 } /* }}} int ident_set_type_instance */
380 /* }}} ident_set_* methods */
382 int ident_compare (const graph_ident_t *i0, /* {{{ */
383 const graph_ident_t *i1)
387 #define COMPARE_PART(p) do { \
388 status = strcmp (i0->p, i1->p); \
394 COMPARE_PART (plugin);
395 COMPARE_PART (plugin_instance);
397 COMPARE_PART (type_instance);
402 } /* }}} int ident_compare */
404 _Bool ident_matches (const graph_ident_t *selector, /* {{{ */
405 const graph_ident_t *ident)
408 if ((selector == NULL) || (ident == NULL))
412 if (!part_matches (selector->host, ident->host))
415 if (!part_matches (selector->plugin, ident->plugin))
418 if (!part_matches (selector->plugin_instance, ident->plugin_instance))
421 if (!part_matches (selector->type, ident->type))
424 if (!part_matches (selector->type_instance, ident->type_instance))
428 } /* }}} _Bool ident_matches */
430 _Bool ident_intersect (const graph_ident_t *s0, /* {{{ */
431 const graph_ident_t *s1)
433 #define INTERSECT_PART(p) do { \
434 if (!IS_ANY (s0->p) && !IS_ALL (s0->p) \
435 && !IS_ANY (s1->p) && !IS_ALL (s1->p) \
436 && (strcmp (s0->p, s1->p) != 0)) \
440 INTERSECT_PART (host);
441 INTERSECT_PART (plugin);
442 INTERSECT_PART (plugin_instance);
443 INTERSECT_PART (type);
444 INTERSECT_PART (type_instance);
446 #undef INTERSECT_PART
449 } /* }}} _Bool ident_intersect */
451 char *ident_to_string (const graph_ident_t *ident) /* {{{ */
453 char buffer[PATH_MAX];
457 strlcat (buffer, ident->host, sizeof (buffer));
458 strlcat (buffer, "/", sizeof (buffer));
459 strlcat (buffer, ident->plugin, sizeof (buffer));
460 if (ident->plugin_instance[0] != 0)
462 strlcat (buffer, "-", sizeof (buffer));
463 strlcat (buffer, ident->plugin_instance, sizeof (buffer));
465 strlcat (buffer, "/", sizeof (buffer));
466 strlcat (buffer, ident->type, sizeof (buffer));
467 if (ident->type_instance[0] != 0)
469 strlcat (buffer, "-", sizeof (buffer));
470 strlcat (buffer, ident->type_instance, sizeof (buffer));
473 return (strdup (buffer));
474 } /* }}} char *ident_to_string */
476 char *ident_to_file (const graph_ident_t *ident) /* {{{ */
478 char buffer[PATH_MAX];
482 strlcat (buffer, DATA_DIR, sizeof (buffer));
483 strlcat (buffer, "/", sizeof (buffer));
485 strlcat (buffer, ident->host, sizeof (buffer));
486 strlcat (buffer, "/", sizeof (buffer));
487 strlcat (buffer, ident->plugin, sizeof (buffer));
488 if (ident->plugin_instance[0] != 0)
490 strlcat (buffer, "-", sizeof (buffer));
491 strlcat (buffer, ident->plugin_instance, sizeof (buffer));
493 strlcat (buffer, "/", sizeof (buffer));
494 strlcat (buffer, ident->type, sizeof (buffer));
495 if (ident->type_instance[0] != 0)
497 strlcat (buffer, "-", sizeof (buffer));
498 strlcat (buffer, ident->type_instance, sizeof (buffer));
501 strlcat (buffer, ".rrd", sizeof (buffer));
503 return (strdup (buffer));
504 } /* }}} char *ident_to_file */
506 int ident_to_json (const graph_ident_t *ident, /* {{{ */
509 yajl_gen_status status;
511 if ((ident == NULL) || (handler == NULL))
514 #define ADD_STRING(str) do { \
515 status = yajl_gen_string (handler, \
516 (unsigned char *) (str), \
517 (unsigned int) strlen (str)); \
518 if (status != yajl_gen_status_ok) \
519 return ((int) status); \
522 yajl_gen_map_open (handler);
524 ADD_STRING (ident->host);
525 ADD_STRING ("plugin");
526 ADD_STRING (ident->plugin);
527 ADD_STRING ("plugin_instance");
528 ADD_STRING (ident->plugin_instance);
530 ADD_STRING (ident->type);
531 ADD_STRING ("type_instance");
532 ADD_STRING (ident->type_instance);
533 yajl_gen_map_close (handler);
538 } /* }}} char *ident_to_json */
540 /* {{{ ident_data_to_json */
541 struct ident_data_to_json__data_s
547 typedef struct ident_data_to_json__data_s ident_data_to_json__data_t;
549 #define yajl_gen_string_cast(h,s,l) \
550 yajl_gen_string (h, (unsigned char *) s, (unsigned int) l)
552 static int ident_data_to_json__get_ident_data (
553 __attribute__((unused)) graph_ident_t *ident, /* {{{ */
554 __attribute__((unused)) const char *ds_name,
555 const dp_data_point_t *dp, size_t dp_num,
558 ident_data_to_json__data_t *data = user_data;
561 yajl_gen_map_open (data->handler);
563 for (i = 0; i < dp_num; i++)
565 yajl_gen_map_open (data->handler);
566 yajl_gen_integer (data->handler, (long) dp[i].time.tv_sec);
567 yajl_gen_double (data->handler, dp[i].value);
568 yajl_gen_map_close (data->handler);
571 yajl_gen_map_close (data->handler);
574 } /* }}} int ident_data_to_json__get_ident_data */
576 /* Called for each DS name */
577 static int ident_data_to_json__get_ds_name (const graph_ident_t *ident, /* {{{ */
578 const char *ds_name, void *user_data)
580 ident_data_to_json__data_t *data = user_data;
583 yajl_gen_map_open (data->handler);
585 yajl_gen_string_cast (data->handler, "ds_name", strlen ("ds_name"));
586 yajl_gen_string_cast (data->handler, ds_name, strlen (ds_name));
588 yajl_gen_string_cast (data->handler, "data", strlen ("data"));
589 yajl_gen_array_open (data->handler);
591 status = data_provider_get_ident_data (ident, ds_name,
592 data->begin, data->end,
593 ident_data_to_json__get_ident_data,
596 yajl_gen_array_close (data->handler);
597 yajl_gen_map_close (data->handler);
600 } /* }}} int ident_data_to_json__get_ds_name */
602 int ident_data_to_json (const graph_ident_t *ident, /* {{{ */
603 dp_time_t begin, dp_time_t end,
606 ident_data_to_json__data_t data;
611 data.handler = handler;
613 /* Iterate over all DS names */
614 status = data_provider_get_ident_ds_names (ident,
615 ident_data_to_json__get_ds_name, &data);
617 fprintf (stderr, "ident_data_to_json: data_provider_get_ident_ds_names "
618 "failed with status %i\n", status);
621 } /* }}} int ident_data_to_json */
622 /* }}} ident_data_to_json */
624 int ident_describe (const graph_ident_t *ident, /* {{{ */
625 const graph_ident_t *selector,
626 char *buffer, size_t buffer_size)
628 if ((ident == NULL) || (selector == NULL)
629 || (buffer == NULL) || (buffer_size < 2))
634 #define CHECK_FIELD(field) do { \
635 if (strcasecmp (selector->field, ident->field) != 0) \
637 if (buffer[0] != 0) \
638 strlcat (buffer, "/", buffer_size); \
639 strlcat (buffer, ident->field, buffer_size); \
644 CHECK_FIELD (plugin);
645 CHECK_FIELD (plugin_instance);
647 CHECK_FIELD (type_instance);
652 strlcat (buffer, "default", buffer_size);
655 } /* }}} int ident_describe */
657 time_t ident_get_mtime (const graph_ident_t *ident) /* {{{ */
666 file = ident_to_file (ident);
670 memset (&statbuf, 0, sizeof (statbuf));
671 status = stat (file, &statbuf);
674 fprintf (stderr, "ident_get_mtime: stat'ing file \"%s\" failed: %s\n",
675 file, strerror (errno));
680 return (statbuf.st_mtime);
681 } /* }}} time_t ident_get_mtime */
683 /* vim: set sw=2 sts=2 et fdm=marker : */