2 * collectd - src/meta_data.c
3 * Copyright (C) 2008,2009 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>
24 #include "meta_data.h"
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
35 #define MD_TYPE_BOOLEAN 5
43 int64_t mv_signed_int;
44 uint64_t mv_unsigned_int;
48 typedef union meta_value_u meta_value_t;
51 typedef struct meta_entry_s meta_entry_t;
69 static char *md_strdup (const char *orig) /* {{{ */
77 sz = strlen (orig) + 1;
78 dest = (char *) malloc (sz);
82 memcpy (dest, orig, sz);
85 } /* }}} char *md_strdup */
87 static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
91 e = (meta_entry_t *) malloc (sizeof (*e));
94 ERROR ("md_entry_alloc: malloc failed.");
97 memset (e, 0, sizeof (*e));
99 e->key = md_strdup (key);
103 ERROR ("md_entry_alloc: md_strdup failed.");
111 } /* }}} meta_entry_t *md_entry_alloc */
113 static void md_entry_free (meta_entry_t *e) /* {{{ */
120 if (e->type == MD_TYPE_STRING)
121 free (e->value.mv_string);
124 md_entry_free (e->next);
127 } /* }}} void md_entry_free */
129 static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
134 if ((md == NULL) || (e == NULL))
137 pthread_mutex_lock (&md->lock);
143 if (strcasecmp (e->key, this->key) == 0)
152 /* This key does not exist yet. */
153 if (md->head == NULL)
157 assert (prev != NULL);
163 else /* (this != NULL) */
170 e->next = this->next;
173 pthread_mutex_unlock (&md->lock);
178 md_entry_free (this);
182 } /* }}} int md_entry_insert */
184 /* XXX: The lock on md must be held while calling this function! */
185 static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
190 if ((md == NULL) || (key == NULL))
193 for (e = md->head; e != NULL; e = e->next)
194 if (strcasecmp (key, e->key) == 0)
198 } /* }}} meta_entry_t *md_entry_lookup */
203 meta_data_t *meta_data_create (void) /* {{{ */
207 md = (meta_data_t *) malloc (sizeof (*md));
210 ERROR ("meta_data_create: malloc failed.");
213 memset (md, 0, sizeof (*md));
216 pthread_mutex_init (&md->lock, /* attr = */ NULL);
219 } /* }}} meta_data_t *meta_data_create */
221 void meta_data_destroy (meta_data_t *md) /* {{{ */
226 md_entry_free (md->head);
228 } /* }}} void meta_data_destroy */
230 int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
234 if ((md == NULL) || (key == NULL))
237 pthread_mutex_lock (&md->lock);
239 for (e = md->head; e != NULL; e = e->next)
241 if (strcasecmp (key, e->key) == 0)
243 pthread_mutex_unlock (&md->lock);
248 pthread_mutex_unlock (&md->lock);
250 } /* }}} int meta_data_exists */
252 int meta_data_delete (meta_data_t *md, const char *key) /* {{{ */
257 if ((md == NULL) || (key == NULL))
260 pthread_mutex_lock (&md->lock);
266 if (strcasecmp (key, this->key) == 0)
275 pthread_mutex_unlock (&md->lock);
280 md->head = this->next;
282 prev->next = this->next;
284 pthread_mutex_unlock (&md->lock);
287 md_entry_free (this);
290 } /* }}} int meta_data_delete */
295 int meta_data_add_string (meta_data_t *md, /* {{{ */
296 const char *key, const char *value)
300 if ((md == NULL) || (key == NULL) || (value == NULL))
303 e = md_entry_alloc (key);
307 e->value.mv_string = md_strdup (value);
308 if (e->value.mv_string == NULL)
310 ERROR ("meta_data_add_string: md_strdup failed.");
314 e->type = MD_TYPE_STRING;
316 return (md_entry_insert (md, e));
317 } /* }}} int meta_data_add_string */
319 int meta_data_add_signed_int (meta_data_t *md, /* {{{ */
320 const char *key, int64_t value)
324 if ((md == NULL) || (key == NULL))
327 e = md_entry_alloc (key);
331 e->value.mv_signed_int = value;
332 e->type = MD_TYPE_SIGNED_INT;
334 return (md_entry_insert (md, e));
335 } /* }}} int meta_data_add_signed_int */
337 int meta_data_add_unsigned_int (meta_data_t *md, /* {{{ */
338 const char *key, uint64_t value)
342 if ((md == NULL) || (key == NULL))
345 e = md_entry_alloc (key);
349 e->value.mv_unsigned_int = value;
350 e->type = MD_TYPE_UNSIGNED_INT;
352 return (md_entry_insert (md, e));
353 } /* }}} int meta_data_add_unsigned_int */
355 int meta_data_add_double (meta_data_t *md, /* {{{ */
356 const char *key, double value)
360 if ((md == NULL) || (key == NULL))
363 e = md_entry_alloc (key);
367 e->value.mv_double = value;
368 e->type = MD_TYPE_DOUBLE;
370 return (md_entry_insert (md, e));
371 } /* }}} int meta_data_add_double */
373 int meta_data_add_boolean (meta_data_t *md, /* {{{ */
374 const char *key, _Bool value)
378 if ((md == NULL) || (key == NULL))
381 e = md_entry_alloc (key);
385 e->value.mv_boolean = value;
386 e->type = MD_TYPE_BOOLEAN;
388 return (md_entry_insert (md, e));
389 } /* }}} int meta_data_add_boolean */
394 int meta_data_get_string (meta_data_t *md, /* {{{ */
395 const char *key, char **value)
400 if ((md == NULL) || (key == NULL) || (value == NULL))
403 pthread_mutex_lock (&md->lock);
405 e = md_entry_lookup (md, key);
408 pthread_mutex_unlock (&md->lock);
412 if (e->type != MD_TYPE_STRING)
414 ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
415 pthread_mutex_unlock (&md->lock);
419 temp = md_strdup (e->value.mv_string);
422 pthread_mutex_unlock (&md->lock);
423 ERROR ("meta_data_get_string: md_strdup failed.");
427 pthread_mutex_unlock (&md->lock);
432 } /* }}} int meta_data_get_string */
434 int meta_data_get_signed_int (meta_data_t *md, /* {{{ */
435 const char *key, int64_t *value)
439 if ((md == NULL) || (key == NULL) || (value == NULL))
442 pthread_mutex_lock (&md->lock);
444 e = md_entry_lookup (md, key);
447 pthread_mutex_unlock (&md->lock);
451 if (e->type != MD_TYPE_SIGNED_INT)
453 ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
454 pthread_mutex_unlock (&md->lock);
458 *value = e->value.mv_signed_int;
460 pthread_mutex_unlock (&md->lock);
462 } /* }}} int meta_data_get_signed_int */
464 int meta_data_get_unsigned_int (meta_data_t *md, /* {{{ */
465 const char *key, uint64_t *value)
469 if ((md == NULL) || (key == NULL) || (value == NULL))
472 pthread_mutex_lock (&md->lock);
474 e = md_entry_lookup (md, key);
477 pthread_mutex_unlock (&md->lock);
481 if (e->type != MD_TYPE_UNSIGNED_INT)
483 ERROR ("meta_data_get_unsigned_int: Type mismatch for key `%s'", e->key);
484 pthread_mutex_unlock (&md->lock);
488 *value = e->value.mv_unsigned_int;
490 pthread_mutex_unlock (&md->lock);
492 } /* }}} int meta_data_get_unsigned_int */
494 int meta_data_get_double (meta_data_t *md, /* {{{ */
495 const char *key, double *value)
499 if ((md == NULL) || (key == NULL) || (value == NULL))
502 pthread_mutex_lock (&md->lock);
504 e = md_entry_lookup (md, key);
507 pthread_mutex_unlock (&md->lock);
511 if (e->type != MD_TYPE_DOUBLE)
513 ERROR ("meta_data_get_double: Type mismatch for key `%s'", e->key);
514 pthread_mutex_unlock (&md->lock);
518 *value = e->value.mv_double;
520 pthread_mutex_unlock (&md->lock);
522 } /* }}} int meta_data_get_double */
524 int meta_data_get_boolean (meta_data_t *md, /* {{{ */
525 const char *key, _Bool *value)
529 if ((md == NULL) || (key == NULL) || (value == NULL))
532 pthread_mutex_lock (&md->lock);
534 e = md_entry_lookup (md, key);
537 pthread_mutex_unlock (&md->lock);
541 if (e->type != MD_TYPE_BOOLEAN)
543 ERROR ("meta_data_get_boolean: Type mismatch for key `%s'", e->key);
544 pthread_mutex_unlock (&md->lock);
548 *value = e->value.mv_boolean;
550 pthread_mutex_unlock (&md->lock);
552 } /* }}} int meta_data_get_boolean */
554 /* vim: set sw=2 sts=2 et fdm=marker : */