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>
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
42 int64_t mv_signed_int;
43 uint64_t mv_unsigned_int;
46 typedef union meta_value_u meta_value_t;
49 typedef struct meta_entry_s meta_entry_t;
67 static char *md_strdup (const char *orig) /* {{{ */
75 sz = strlen (orig) + 1;
76 dest = (char *) malloc (sz);
80 memcpy (dest, orig, sz);
83 } /* }}} char *md_strdup */
85 static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
89 e = (meta_entry_t *) malloc (sizeof (*e));
92 ERROR ("md_entry_alloc: malloc failed.");
95 memset (e, 0, sizeof (*e));
97 e->key = md_strdup (key);
101 ERROR ("md_entry_alloc: md_strdup failed.");
109 } /* }}} meta_entry_t *md_entry_alloc */
111 static void md_entry_free (meta_entry_t *e) /* {{{ */
118 if (e->type == MD_TYPE_STRING)
119 free (e->value.mv_string);
122 md_entry_free (e->next);
125 } /* }}} void md_entry_free */
127 static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
132 if ((md == NULL) || (e == NULL))
135 pthread_mutex_lock (&md->lock);
141 if (strcasecmp (e->key, this->key) == 0)
150 /* This key does not exist yet. */
151 if (md->head == NULL)
155 assert (prev != NULL);
161 else /* (this != NULL) */
168 e->next = this->next;
171 pthread_mutex_unlock (&md->lock);
176 md_entry_free (this);
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, /* {{{ */
188 if ((md == NULL) || (key == NULL))
191 for (e = md->head; e != NULL; e = e->next)
192 if (strcasecmp (key, e->key) == 0)
196 } /* }}} meta_entry_t *md_entry_lookup */
201 meta_data_t *meta_data_create (void) /* {{{ */
205 md = (meta_data_t *) malloc (sizeof (*md));
208 ERROR ("meta_data_create: malloc failed.");
211 memset (md, 0, sizeof (*md));
214 pthread_mutex_init (&md->lock, /* attr = */ NULL);
217 } /* }}} meta_data_t *meta_data_create */
219 void meta_data_destroy (meta_data_t *md) /* {{{ */
224 md_entry_free (md->head);
226 } /* }}} void meta_data_destroy */
228 int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
232 if ((md == NULL) || (key == NULL))
235 pthread_mutex_lock (&md->lock);
237 for (e = md->head; e != NULL; e = e->next)
239 if (strcasecmp (key, e->key) == 0)
241 pthread_mutex_unlock (&md->lock);
246 pthread_mutex_unlock (&md->lock);
248 } /* }}} int meta_data_exists */
250 int meta_data_delete (meta_data_t *md, const char *key) /* {{{ */
255 if ((md == NULL) || (key == NULL))
258 pthread_mutex_lock (&md->lock);
264 if (strcasecmp (key, this->key) == 0)
273 pthread_mutex_unlock (&md->lock);
278 md->head = this->next;
280 prev->next = this->next;
282 pthread_mutex_unlock (&md->lock);
285 md_entry_free (this);
288 } /* }}} int meta_data_delete */
290 int meta_data_add_string (meta_data_t *md, /* {{{ */
291 const char *key, const char *value)
295 if ((md == NULL) || (key == NULL) || (value == NULL))
298 e = md_entry_alloc (key);
302 e->value.mv_string = md_strdup (value);
303 if (e->value.mv_string == NULL)
305 ERROR ("meta_data_add_string: md_strdup failed.");
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)
319 if ((md == NULL) || (key == NULL))
322 e = md_entry_alloc (key);
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)
337 if ((md == NULL) || (key == NULL))
340 e = md_entry_alloc (key);
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)
355 if ((md == NULL) || (key == NULL))
358 e = md_entry_alloc (key);
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)
374 if ((md == NULL) || (key == NULL) || (value == NULL))
377 pthread_mutex_lock (&md->lock);
379 e = md_entry_lookup (md, key);
382 pthread_mutex_unlock (&md->lock);
386 if (e->type != MD_TYPE_STRING)
388 ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
389 pthread_mutex_unlock (&md->lock);
393 temp = md_strdup (e->value.mv_string);
396 pthread_mutex_unlock (&md->lock);
397 ERROR ("meta_data_get_string: md_strdup failed.");
401 pthread_mutex_unlock (&md->lock);
406 } /* }}} int meta_data_get_string */
408 int meta_data_get_signed_int (meta_data_t *md, /* {{{ */
409 const char *key, int64_t *value)
413 if ((md == NULL) || (key == NULL) || (value == NULL))
416 pthread_mutex_lock (&md->lock);
418 e = md_entry_lookup (md, key);
421 pthread_mutex_unlock (&md->lock);
425 if (e->type != MD_TYPE_SIGNED_INT)
427 ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
428 pthread_mutex_unlock (&md->lock);
432 *value = e->value.mv_signed_int;
434 pthread_mutex_unlock (&md->lock);
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)
443 if ((md == NULL) || (key == NULL) || (value == NULL))
446 pthread_mutex_lock (&md->lock);
448 e = md_entry_lookup (md, key);
451 pthread_mutex_unlock (&md->lock);
455 if (e->type != MD_TYPE_UNSIGNED_INT)
457 ERROR ("meta_data_get_unsigned_int: Type mismatch for key `%s'", e->key);
458 pthread_mutex_unlock (&md->lock);
462 *value = e->value.mv_unsigned_int;
464 pthread_mutex_unlock (&md->lock);
466 } /* }}} int meta_data_get_unsigned_int */
468 int meta_data_get_double (meta_data_t *md, /* {{{ */
469 const char *key, double *value)
473 if ((md == NULL) || (key == NULL) || (value == NULL))
476 pthread_mutex_lock (&md->lock);
478 e = md_entry_lookup (md, key);
481 pthread_mutex_unlock (&md->lock);
485 if (e->type != MD_TYPE_DOUBLE)
487 ERROR ("meta_data_get_double: Type mismatch for key `%s'", e->key);
488 pthread_mutex_unlock (&md->lock);
492 *value = e->value.mv_double;
494 pthread_mutex_unlock (&md->lock);
496 } /* }}} int meta_data_get_double */
498 /* vim: set sw=2 sts=2 et fdm=marker : */