Merge branch 'ym/target_set_add_meta' of github.com:ymettier/collectd into target_set...
authorKevin Bowling <kbowling@llnw.com>
Wed, 6 Apr 2016 06:20:48 +0000 (23:20 -0700)
committerKevin Bowling <kbowling@llnw.com>
Wed, 6 Apr 2016 06:20:48 +0000 (23:20 -0700)
src/collectd.conf.pod
src/daemon/meta_data.c
src/daemon/meta_data.h
src/target_set.c

index cf7ccd0..54dc648 100644 (file)
@@ -8950,6 +8950,8 @@ Available options:
 
 =item B<TypeInstance> I<String>
 
+=item B<MetaDataSet> I<String> I<String>
+
 Set the appropriate field to the given string. The strings for plugin instance
 and type instance may be empty, the strings for host and plugin may not be
 empty. It's currently not possible to set the type of a value this way.
index f87e35e..03b1d26 100644 (file)
@@ -105,12 +105,15 @@ static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
   return (e);
 } /* }}} meta_entry_t *md_entry_alloc */
 
-static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+/* XXX: The lock on md must be held while calling this function! */
+static meta_entry_t *md_entry_clone_contents (const meta_entry_t *orig) /* {{{ */
 {
   meta_entry_t *copy;
 
-  if (orig == NULL)
-    return (NULL);
+  /* WARNINGS :
+   *  - we do not check that orig != NULL here. You should have done it before.
+   *  - we do not set copy->next. DO NOT FORGET TO SET copy->next IN YOUR FUNCTION
+   */
 
   copy = md_entry_alloc (orig->key);
   if (copy == NULL)
@@ -121,6 +124,18 @@ static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
   else
     copy->value = orig->value;
 
+  return (copy);
+} /* }}} meta_entry_t *md_entry_clone_contents */
+
+static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+{
+  meta_entry_t *copy;
+
+  if (orig == NULL)
+    return (NULL);
+
+  copy = md_entry_clone_contents(orig);
+
   copy->next = md_entry_clone (orig->next);
   return (copy);
 } /* }}} meta_entry_t *md_entry_clone */
@@ -197,6 +212,63 @@ static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
 } /* }}} int md_entry_insert */
 
 /* XXX: The lock on md must be held while calling this function! */
+static int md_entry_insert_clone (meta_data_t *md, meta_entry_t *orig) /* {{{ */
+{
+  meta_entry_t *e;
+  meta_entry_t *this;
+  meta_entry_t *prev;
+
+  /* WARNINGS :
+   *  - we do not check that md and e != NULL here. You should have done it before.
+   *  - we do not use the lock. You should have set it before.
+   */
+
+  e = md_entry_clone_contents(orig);
+
+  prev = NULL;
+  this = md->head;
+  while (this != NULL)
+  {
+    if (strcasecmp (e->key, this->key) == 0)
+      break;
+
+    prev = this;
+    this = this->next;
+  }
+
+  if (this == NULL)
+  {
+    /* This key does not exist yet. */
+    if (md->head == NULL)
+      md->head = e;
+    else
+    {
+      assert (prev != NULL);
+      prev->next = e;
+    }
+
+    e->next = NULL;
+  }
+  else /* (this != NULL) */
+  {
+    if (prev == NULL)
+      md->head = e;
+    else
+      prev->next = e;
+
+    e->next = this->next;
+  }
+
+  if (this != NULL)
+  {
+    this->next = NULL;
+    md_entry_free (this);
+  }
+
+  return (0);
+} /* }}} int md_entry_insert_clone */
+
+/* XXX: The lock on md must be held while calling this function! */
 static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
     const char *key)
 {
@@ -249,6 +321,27 @@ meta_data_t *meta_data_clone (meta_data_t *orig) /* {{{ */
   return (copy);
 } /* }}} meta_data_t *meta_data_clone */
 
+int meta_data_clone_merge (meta_data_t **dest, meta_data_t *orig) /* {{{ */
+{
+  meta_entry_t *e;
+
+  if (orig == NULL)
+    return (0);
+
+  if(NULL == *dest) {
+    *dest = meta_data_clone(orig);
+    return(0);
+  }
+
+  pthread_mutex_lock (&orig->lock);
+  for(e=orig->head; NULL != e; e = e->next) {
+    md_entry_insert_clone((*dest), e);
+  }
+  pthread_mutex_unlock (&orig->lock);
+
+  return (0);
+} /* }}} int meta_data_clone_merge */
+
 void meta_data_destroy (meta_data_t *md) /* {{{ */
 {
   if (md == NULL)
index fa48df3..9e448e5 100644 (file)
@@ -43,6 +43,7 @@ typedef struct meta_data_s meta_data_t;
 
 meta_data_t *meta_data_create (void);
 meta_data_t *meta_data_clone (meta_data_t *orig);
+int meta_data_clone_merge (meta_data_t **dest, meta_data_t *orig);
 void meta_data_destroy (meta_data_t *md);
 
 int meta_data_exists (meta_data_t *md, const char *key);
index faad0bf..99f8aa6 100644 (file)
@@ -35,9 +35,27 @@ struct ts_data_s
   char *plugin_instance;
   /* char *type; */
   char *type_instance;
+  meta_data_t *meta;
 };
 typedef struct ts_data_s ts_data_t;
 
+int ts_util_get_key_and_string_wo_strdup (const oconfig_item_t *ci, char **ret_key, char **ret_string) /* {{{ */
+{
+  if ((ci->values_num != 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("ts_util_get_key_and_string_wo_strdup: The %s option requires "
+        "exactly two string argument.", ci->key);
+    return (-1);
+  }
+
+  *ret_key = ci->values[0].value.string;
+  *ret_string = ci->values[1].value.string;
+
+  return (0);
+} /* }}} int ts_util_get_key_and_string_wo_strdup */
+
 static int ts_config_add_string (char **dest, /* {{{ */
     const oconfig_item_t *ci, int may_be_empty)
 {
@@ -60,6 +78,42 @@ static int ts_config_add_string (char **dest, /* {{{ */
   return (0);
 } /* }}} int ts_config_add_string */
 
+static int ts_config_add_meta (meta_data_t **dest, /* {{{ */
+    const oconfig_item_t *ci, int may_be_empty)
+{
+  char *key = NULL;
+  char *string = NULL;
+  int status;
+
+  status = ts_util_get_key_and_string_wo_strdup (ci, &key, &string);
+  if (status != 0)
+    return (status);
+
+  if (strlen (key) == 0)
+  {
+    ERROR ("Target `set': The `%s' option does not accept empty string as first argument.",
+        ci->key);
+    return (-1);
+  }
+
+  if (!may_be_empty && (strlen (string) == 0))
+  {
+    ERROR ("Target `set': The `%s' option does not accept empty string as second argument.",
+        ci->key);
+    return (-1);
+  }
+
+  if(NULL == (*dest)) {
+    // Create a new meta_data_t
+    if( NULL == (*dest = meta_data_create())) {
+      ERROR ("Target `set': failed to create a meta data for `%s'.", ci->key);
+      return (-1);
+    }
+  }
+
+  return(meta_data_add_string (*dest, key, string));
+} /* }}} int ts_config_add_meta */
+
 static int ts_destroy (void **user_data) /* {{{ */
 {
   ts_data_t *data;
@@ -76,6 +130,7 @@ static int ts_destroy (void **user_data) /* {{{ */
   free (data->plugin_instance);
   /* free (data->type); */
   free (data->type_instance);
+  meta_data_destroy(data->meta);
   free (data);
 
   return (0);
@@ -99,6 +154,7 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
   data->plugin_instance = NULL;
   /* data->type = NULL; */
   data->type_instance = NULL;
+  data->meta = NULL;
 
   status = 0;
   for (i = 0; i < ci->children_num; i++)
@@ -123,6 +179,9 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
     else if (strcasecmp ("TypeInstance", child->key) == 0)
       status = ts_config_add_string (&data->type_instance, child,
           /* may be empty = */ 1);
+    else if (strcasecmp ("MetaDataSet", child->key) == 0)
+      status = ts_config_add_meta (&data->meta, child,
+          /* may be empty = */ 1);
     else
     {
       ERROR ("Target `set': The `%s' configuration option is not understood "
@@ -141,10 +200,12 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
         && (data->plugin == NULL)
         && (data->plugin_instance == NULL)
         /* && (data->type == NULL) */
-        && (data->type_instance == NULL))
+        && (data->type_instance == NULL)
+        && (data->meta == NULL))
     {
       ERROR ("Target `set': You need to set at least one of `Host', "
-          "`Plugin', `PluginInstance' or `TypeInstance'.");
+          "`Plugin', `PluginInstance', `TypeInstance', "
+          "`MetaDataSet' or `MetaDataEval'.");
       status = -1;
     }
 
@@ -176,6 +237,10 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
     return (-EINVAL);
   }
 
+  if(NULL != data->meta) {
+    meta_data_clone_merge(&(vl->meta), data->meta);
+  }
+
 #define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); }
   SET_FIELD (host);
   SET_FIELD (plugin);