Code

Various: Remove strict standards compliance defines.
[collectd.git] / src / meta_data.c
1 /**
2  * collectd - src/meta_data.c
3  * Copyright (C) 2008  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Florian octo Forster <octo at verplant.org>
20  **/
22 #include "collectd.h"
23 #include "plugin.h"
24 #include "meta_data.h"
26 #include <pthread.h>
28 /*
29  * Defines
30  */
31 #define MD_TYPE_STRING       1
32 #define MD_TYPE_SIGNED_INT   2
33 #define MD_TYPE_UNSIGNED_INT 3
34 #define MD_TYPE_DOUBLE       4
36 /*
37  * Data types
38  */
39 union meta_value_u
40 {
41   char    *mv_string;
42   int64_t  mv_signed_int;
43   uint64_t mv_unsigned_int;
44   double   mv_double;
45 };
46 typedef union meta_value_u meta_value_t;
48 struct meta_entry_s;
49 typedef struct meta_entry_s meta_entry_t;
50 struct meta_entry_s
51 {
52   char         *key;
53   meta_value_t  value;
54   int           type;
55   meta_entry_t *next;
56 };
58 struct meta_data_s
59 {
60   meta_entry_t   *head;
61   pthread_mutex_t lock;
62 };
64 /*
65  * Private functions
66  */
67 static char *md_strdup (const char *orig) /* {{{ */
68 {
69   size_t sz;
70   char *dest;
72   if (orig == NULL)
73     return (NULL);
75   sz = strlen (orig) + 1;
76   dest = (char *) malloc (sz);
77   if (dest == NULL)
78     return (NULL);
80   memcpy (dest, orig, sz);
82   return (dest);
83 } /* }}} char *md_strdup */
85 static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
86 {
87   meta_entry_t *e;
89   e = (meta_entry_t *) malloc (sizeof (*e));
90   if (e == NULL)
91   {
92     ERROR ("md_entry_alloc: malloc failed.");
93     return (NULL);
94   }
95   memset (e, 0, sizeof (*e));
97   e->key = md_strdup (key);
98   if (e->key == NULL)
99   {
100     free (e);
101     ERROR ("md_entry_alloc: md_strdup failed.");
102     return (NULL);
103   }
105   e->type = 0;
106   e->next = NULL;
108   return (e);
109 } /* }}} meta_entry_t *md_entry_alloc */
111 static void md_entry_free (meta_entry_t *e) /* {{{ */
113   if (e == NULL)
114     return;
116   free (e->key);
118   if (e->type == MD_TYPE_STRING)
119     free (e->value.mv_string);
121   if (e->next != NULL)
122     md_entry_free (e->next);
124   free (e);
125 } /* }}} void md_entry_free */
127 static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
129   meta_entry_t *this;
130   meta_entry_t *prev;
132   if ((md == NULL) || (e == NULL))
133     return (-EINVAL);
135   pthread_mutex_lock (&md->lock);
137   prev = NULL;
138   this = md->head;
139   while (this != NULL)
140   {
141     if (strcasecmp (e->key, this->key) == 0)
142       break;
144     prev = this;
145     this = this->next;
146   }
148   if (this == NULL)
149   {
150     /* This key does not exist yet. */
151     if (md->head == NULL)
152       md->head = e;
153     else
154     {
155       assert (prev != NULL);
156       prev->next = e;
157     }
159     e->next = NULL;
160   }
161   else /* (this != NULL) */
162   {
163     if (prev == NULL)
164       md->head = e;
165     else
166       prev->next = e;
168     e->next = this->next;
169   }
171   pthread_mutex_unlock (&md->lock);
173   if (this != NULL)
174   {
175     this->next = NULL;
176     md_entry_free (this);
177   }
179   return (0);
180 } /* }}} int md_entry_insert */
182 /* XXX: The lock on md must be held while calling this function! */
183 static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
184     const char *key)
186   meta_entry_t *e;
188   if ((md == NULL) || (key == NULL))
189     return (NULL);
191   for (e = md->head; e != NULL; e = e->next)
192     if (strcasecmp (key, e->key) == 0)
193       break;
195   return (e);
196 } /* }}} meta_entry_t *md_entry_lookup */
198 /*
199  * Public functions
200  */
201 meta_data_t *meta_data_create (void) /* {{{ */
203   meta_data_t *md;
205   md = (meta_data_t *) malloc (sizeof (*md));
206   if (md == NULL)
207   {
208     ERROR ("meta_data_create: malloc failed.");
209     return (NULL);
210   }
211   memset (md, 0, sizeof (*md));
213   md->head = NULL;
214   pthread_mutex_init (&md->lock, /* attr = */ NULL);
216   return (md);
217 } /* }}} meta_data_t *meta_data_create */
219 void meta_data_destroy (meta_data_t *md) /* {{{ */
221   if (md == NULL)
222     return;
224   md_entry_free (md->head);
225   free (md);
226 } /* }}} void meta_data_destroy */
228 int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
230   meta_entry_t *e;
232   if ((md == NULL) || (key == NULL))
233     return (-EINVAL);
235   pthread_mutex_lock (&md->lock);
237   for (e = md->head; e != NULL; e = e->next)
238   {
239     if (strcasecmp (key, e->key) == 0)
240     {
241       pthread_mutex_unlock (&md->lock);
242       return (1);
243     }
244   }
246   pthread_mutex_unlock (&md->lock);
247   return (0);
248 } /* }}} int meta_data_exists */
250 int meta_data_delete (meta_data_t *md, const char *key) /* {{{ */
252   meta_entry_t *this;
253   meta_entry_t *prev;
255   if ((md == NULL) || (key == NULL))
256     return (-EINVAL);
258   pthread_mutex_lock (&md->lock);
260   prev = NULL;
261   this = md->head;
262   while (this != NULL)
263   {
264     if (strcasecmp (key, this->key) == 0)
265       break;
267     prev = this;
268     this = this->next;
269   }
271   if (this == NULL)
272   {
273     pthread_mutex_unlock (&md->lock);
274     return (-ENOENT);
275   }
277   if (prev == NULL)
278     md->head = this->next;
279   else
280     prev->next = this->next;
282   pthread_mutex_unlock (&md->lock);
284   this->next = NULL;
285   md_entry_free (this);
287   return (0);
288 } /* }}} int meta_data_delete */
290 int meta_data_add_string (meta_data_t *md, /* {{{ */
291     const char *key, const char *value)
293   meta_entry_t *e;
295   if ((md == NULL) || (key == NULL) || (value == NULL))
296     return (-EINVAL);
298   e = md_entry_alloc (key);
299   if (e == NULL)
300     return (-ENOMEM);
302   e->value.mv_string = md_strdup (value);
303   if (e->value.mv_string == NULL)
304   {
305     ERROR ("meta_data_add_string: md_strdup failed.");
306     md_entry_free (e);
307     return (-ENOMEM);
308   }
309   e->type = MD_TYPE_STRING;
311   return (md_entry_insert (md, e));
312 } /* }}} int meta_data_add_string */
314 int meta_data_add_signed_int (meta_data_t *md, /* {{{ */
315     const char *key, int64_t value)
317   meta_entry_t *e;
319   if ((md == NULL) || (key == NULL))
320     return (-EINVAL);
322   e = md_entry_alloc (key);
323   if (e == NULL)
324     return (-ENOMEM);
326   e->value.mv_signed_int = value;
327   e->type = MD_TYPE_SIGNED_INT;
329   return (md_entry_insert (md, e));
330 } /* }}} int meta_data_add_signed_int */
332 int meta_data_add_unsigned_int (meta_data_t *md, /* {{{ */
333     const char *key, uint64_t value)
335   meta_entry_t *e;
337   if ((md == NULL) || (key == NULL))
338     return (-EINVAL);
340   e = md_entry_alloc (key);
341   if (e == NULL)
342     return (-ENOMEM);
344   e->value.mv_unsigned_int = value;
345   e->type = MD_TYPE_UNSIGNED_INT;
347   return (md_entry_insert (md, e));
348 } /* }}} int meta_data_add_unsigned_int */
350 int meta_data_add_double (meta_data_t *md, /* {{{ */
351     const char *key, double value)
353   meta_entry_t *e;
355   if ((md == NULL) || (key == NULL))
356     return (-EINVAL);
358   e = md_entry_alloc (key);
359   if (e == NULL)
360     return (-ENOMEM);
362   e->value.mv_double = value;
363   e->type = MD_TYPE_DOUBLE;
365   return (md_entry_insert (md, e));
366 } /* }}} int meta_data_add_double */
368 int meta_data_get_string (meta_data_t *md, /* {{{ */
369     const char *key, char **value)
371   meta_entry_t *e;
372   char *temp;
374   if ((md == NULL) || (key == NULL) || (value == NULL))
375     return (-EINVAL);
377   pthread_mutex_lock (&md->lock);
379   e = md_entry_lookup (md, key);
380   if (e == NULL)
381   {
382     pthread_mutex_unlock (&md->lock);
383     return (-ENOENT);
384   }
386   if (e->type != MD_TYPE_SIGNED_INT)
387   {
388     ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
389     pthread_mutex_unlock (&md->lock);
390     return (-ENOENT);
391   }
393   temp = md_strdup (e->value.mv_string);
394   if (temp == NULL)
395   {
396     pthread_mutex_unlock (&md->lock);
397     ERROR ("meta_data_get_string: md_strdup failed.");
398     return (-ENOMEM);
399   }
400  
401   pthread_mutex_unlock (&md->lock);
403   *value = temp;
405   return (0);
406 } /* }}} int meta_data_get_string */
408 int meta_data_get_signed_int (meta_data_t *md, /* {{{ */
409     const char *key, int64_t *value)
411   meta_entry_t *e;
413   if ((md == NULL) || (key == NULL) || (value == NULL))
414     return (-EINVAL);
416   pthread_mutex_lock (&md->lock);
418   e = md_entry_lookup (md, key);
419   if (e == NULL)
420   {
421     pthread_mutex_unlock (&md->lock);
422     return (-ENOENT);
423   }
425   if (e->type != MD_TYPE_SIGNED_INT)
426   {
427     ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
428     pthread_mutex_unlock (&md->lock);
429     return (-ENOENT);
430   }
432   *value = e->value.mv_signed_int;
434   pthread_mutex_unlock (&md->lock);
435   return (0);
436 } /* }}} int meta_data_get_signed_int */
438 int meta_data_get_unsigned_int (meta_data_t *md, /* {{{ */
439     const char *key, uint64_t *value)
441   meta_entry_t *e;
443   if ((md == NULL) || (key == NULL) || (value == NULL))
444     return (-EINVAL);
446   pthread_mutex_lock (&md->lock);
448   e = md_entry_lookup (md, key);
449   if (e == NULL)
450   {
451     pthread_mutex_unlock (&md->lock);
452     return (-ENOENT);
453   }
455   if (e->type != MD_TYPE_UNSIGNED_INT)
456   {
457     ERROR ("meta_data_get_unsigned_int: Type mismatch for key `%s'", e->key);
458     pthread_mutex_unlock (&md->lock);
459     return (-ENOENT);
460   }
462   *value = e->value.mv_unsigned_int;
464   pthread_mutex_unlock (&md->lock);
465   return (0);
466 } /* }}} int meta_data_get_unsigned_int */
468 int meta_data_get_double (meta_data_t *md, /* {{{ */
469     const char *key, double *value)
471   meta_entry_t *e;
473   if ((md == NULL) || (key == NULL) || (value == NULL))
474     return (-EINVAL);
476   pthread_mutex_lock (&md->lock);
478   e = md_entry_lookup (md, key);
479   if (e == NULL)
480   {
481     pthread_mutex_unlock (&md->lock);
482     return (-ENOENT);
483   }
485   if (e->type != MD_TYPE_DOUBLE)
486   {
487     ERROR ("meta_data_get_double: Type mismatch for key `%s'", e->key);
488     pthread_mutex_unlock (&md->lock);
489     return (-ENOENT);
490   }
492   *value = e->value.mv_double;
494   pthread_mutex_unlock (&md->lock);
495   return (0);
496 } /* }}} int meta_data_get_double */
498 /* vim: set sw=2 sts=2 et fdm=marker : */