2 * collectd - src/meta_data.c
3 * Copyright (C) 2008 Florian octo Forster
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.
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.
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
19 * Florian octo Forster <octo at verplant.org>
23 * First tell the compiler to stick to the C99 and POSIX standards as close as
26 #ifndef __STRICT_ANSI__ /* {{{ */
27 # define __STRICT_ANSI__
30 #ifndef _ISOC99_SOURCE
31 # define _ISOC99_SOURCE
34 #ifdef _POSIX_C_SOURCE
35 # undef _POSIX_C_SOURCE
37 #define _POSIX_C_SOURCE 200112L
42 #define _XOPEN_SOURCE 600
59 #include "meta_data.h"
66 #define MD_TYPE_STRING 1
67 #define MD_TYPE_SIGNED_INT 2
68 #define MD_TYPE_UNSIGNED_INT 3
69 #define MD_TYPE_DOUBLE 4
77 int64_t mv_signed_int;
78 uint64_t mv_unsigned_int;
81 typedef union meta_value_u meta_value_t;
84 typedef struct meta_entry_s meta_entry_t;
102 static char *md_strdup (const char *orig) /* {{{ */
110 sz = strlen (orig) + 1;
111 dest = (char *) malloc (sz);
115 memcpy (dest, orig, sz);
118 } /* }}} char *md_strdup */
120 static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
124 e = (meta_entry_t *) malloc (sizeof (*e));
127 ERROR ("md_entry_alloc: malloc failed.");
130 memset (e, 0, sizeof (*e));
132 e->key = md_strdup (key);
136 ERROR ("md_entry_alloc: md_strdup failed.");
144 } /* }}} meta_entry_t *md_entry_alloc */
146 static void md_entry_free (meta_entry_t *e) /* {{{ */
153 if (e->type == MD_TYPE_STRING)
154 free (e->value.mv_string);
157 md_entry_free (e->next);
160 } /* }}} void md_entry_free */
162 static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
167 if ((md == NULL) || (e == NULL))
170 pthread_mutex_lock (&md->lock);
176 if (strcasecmp (e->key, this->key) == 0)
185 /* This key does not exist yet. */
186 if (md->head == NULL)
190 assert (prev != NULL);
196 else /* (this != NULL) */
203 e->next = this->next;
206 pthread_mutex_unlock (&md->lock);
211 md_entry_free (this);
215 } /* }}} int md_entry_insert */
217 /* XXX: The lock on md must be held while calling this function! */
218 static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
223 if ((md == NULL) || (key == NULL))
226 for (e = md->head; e != NULL; e = e->next)
227 if (strcasecmp (key, e->key) == 0)
231 } /* }}} meta_entry_t *md_entry_lookup */
236 meta_data_t *meta_data_create (void) /* {{{ */
240 md = (meta_data_t *) malloc (sizeof (*md));
243 ERROR ("meta_data_create: malloc failed.");
246 memset (md, 0, sizeof (*md));
249 pthread_mutex_init (&md->lock, /* attr = */ NULL);
252 } /* }}} meta_data_t *meta_data_create */
254 void meta_data_destroy (meta_data_t *md) /* {{{ */
259 md_entry_free (md->head);
261 } /* }}} void meta_data_destroy */
263 int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
267 if ((md == NULL) || (key == NULL))
270 pthread_mutex_lock (&md->lock);
272 for (e = md->head; e != NULL; e = e->next)
274 if (strcasecmp (key, e->key) == 0)
276 pthread_mutex_unlock (&md->lock);
281 pthread_mutex_unlock (&md->lock);
283 } /* }}} int meta_data_exists */
285 int meta_data_delete (meta_data_t *md, const char *key) /* {{{ */
290 if ((md == NULL) || (key == NULL))
293 pthread_mutex_lock (&md->lock);
299 if (strcasecmp (key, this->key) == 0)
308 pthread_mutex_unlock (&md->lock);
313 md->head = this->next;
315 prev->next = this->next;
317 pthread_mutex_unlock (&md->lock);
320 md_entry_free (this);
323 } /* }}} int meta_data_delete */
325 int meta_data_add_string (meta_data_t *md, /* {{{ */
326 const char *key, const char *value)
330 if ((md == NULL) || (key == NULL) || (value == NULL))
333 e = md_entry_alloc (key);
337 e->value.mv_string = md_strdup (value);
338 if (e->value.mv_string == NULL)
340 ERROR ("meta_data_add_string: md_strdup failed.");
344 e->type = MD_TYPE_STRING;
346 return (md_entry_insert (md, e));
347 } /* }}} int meta_data_add_string */
349 int meta_data_add_signed_int (meta_data_t *md, /* {{{ */
350 const char *key, int64_t value)
354 if ((md == NULL) || (key == NULL))
357 e = md_entry_alloc (key);
361 e->value.mv_signed_int = value;
362 e->type = MD_TYPE_SIGNED_INT;
364 return (md_entry_insert (md, e));
365 } /* }}} int meta_data_add_signed_int */
367 int meta_data_add_unsigned_int (meta_data_t *md, /* {{{ */
368 const char *key, uint64_t value)
372 if ((md == NULL) || (key == NULL))
375 e = md_entry_alloc (key);
379 e->value.mv_unsigned_int = value;
380 e->type = MD_TYPE_UNSIGNED_INT;
382 return (md_entry_insert (md, e));
383 } /* }}} int meta_data_add_unsigned_int */
385 int meta_data_add_double (meta_data_t *md, /* {{{ */
386 const char *key, double value)
390 if ((md == NULL) || (key == NULL))
393 e = md_entry_alloc (key);
397 e->value.mv_double = value;
398 e->type = MD_TYPE_DOUBLE;
400 return (md_entry_insert (md, e));
401 } /* }}} int meta_data_add_double */
403 int meta_data_get_string (meta_data_t *md, /* {{{ */
404 const char *key, char **value)
409 if ((md == NULL) || (key == NULL) || (value == NULL))
412 pthread_mutex_lock (&md->lock);
414 e = md_entry_lookup (md, key);
417 pthread_mutex_unlock (&md->lock);
421 if (e->type != MD_TYPE_SIGNED_INT)
423 ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
424 pthread_mutex_unlock (&md->lock);
428 temp = md_strdup (e->value.mv_string);
431 pthread_mutex_unlock (&md->lock);
432 ERROR ("meta_data_get_string: md_strdup failed.");
436 pthread_mutex_unlock (&md->lock);
441 } /* }}} int meta_data_get_string */
443 int meta_data_get_signed_int (meta_data_t *md, /* {{{ */
444 const char *key, int64_t *value)
448 if ((md == NULL) || (key == NULL) || (value == NULL))
451 pthread_mutex_lock (&md->lock);
453 e = md_entry_lookup (md, key);
456 pthread_mutex_unlock (&md->lock);
460 if (e->type != MD_TYPE_SIGNED_INT)
462 ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
463 pthread_mutex_unlock (&md->lock);
467 *value = e->value.mv_signed_int;
469 pthread_mutex_unlock (&md->lock);
471 } /* }}} int meta_data_get_signed_int */
473 int meta_data_get_unsigned_int (meta_data_t *md, /* {{{ */
474 const char *key, uint64_t *value)
478 if ((md == NULL) || (key == NULL) || (value == NULL))
481 pthread_mutex_lock (&md->lock);
483 e = md_entry_lookup (md, key);
486 pthread_mutex_unlock (&md->lock);
490 if (e->type != MD_TYPE_UNSIGNED_INT)
492 ERROR ("meta_data_get_unsigned_int: Type mismatch for key `%s'", e->key);
493 pthread_mutex_unlock (&md->lock);
497 *value = e->value.mv_unsigned_int;
499 pthread_mutex_unlock (&md->lock);
501 } /* }}} int meta_data_get_unsigned_int */
503 int meta_data_get_double (meta_data_t *md, /* {{{ */
504 const char *key, double *value)
508 if ((md == NULL) || (key == NULL) || (value == NULL))
511 pthread_mutex_lock (&md->lock);
513 e = md_entry_lookup (md, key);
516 pthread_mutex_unlock (&md->lock);
520 if (e->type != MD_TYPE_DOUBLE)
522 ERROR ("meta_data_get_double: Type mismatch for key `%s'", e->key);
523 pthread_mutex_unlock (&md->lock);
527 *value = e->value.mv_double;
529 pthread_mutex_unlock (&md->lock);
531 } /* }}} int meta_data_get_double */
533 /* vim: set sw=2 sts=2 et fdm=marker : */