Collectd's scale plugin now supports scaling only on specific data sources, yay!
[collectd.git] / src / target_scale.c
index af224f1..6bcbb05 100644 (file)
@@ -29,6 +29,9 @@ struct ts_data_s
 {
        double factor;
        double offset;
+
+       char **data_sources;
+       size_t data_sources_num;
 };
 typedef struct ts_data_s ts_data_t;
 
@@ -300,6 +303,67 @@ static int ts_config_set_double (double *ret, oconfig_item_t *ci) /* {{{ */
        return (0);
 } /* }}} int ts_config_set_double */
 
+static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
+               oconfig_item_t *ci)
+{
+       size_t new_data_sources_num;
+       char **temp;
+       int i;
+
+       /* Check number of arbuments. */
+       if (ci->values_num < 1)
+       {
+               ERROR ("`value' match: `%s' needs at least one argument.",
+                               ci->key);
+               return (-1);
+       }
+
+       /* Check type of arguments */
+       for (i = 0; i < ci->values_num; i++)
+       {
+               if (ci->values[i].type == OCONFIG_TYPE_STRING)
+                       continue;
+
+               ERROR ("`value' match: `%s' accepts only string arguments "
+                               "(argument %i is a %s).",
+                               ci->key, i + 1,
+                               (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
+                               ? "truth value" : "number");
+               return (-1);
+       }
+
+       /* Allocate space for the char pointers */
+       new_data_sources_num = data->data_sources_num + ((size_t) ci->values_num);
+       temp = (char **) realloc (data->data_sources,
+                       new_data_sources_num * sizeof (char *));
+       if (temp == NULL)
+       {
+               ERROR ("`value' match: realloc failed.");
+               return (-1);
+       }
+       data->data_sources = temp;
+
+       /* Copy the strings, allocating memory as needed.  */
+       for (i = 0; i < ci->values_num; i++)
+       {
+               size_t j;
+
+               /* If we get here, there better be memory for us to write to.  */
+               assert (data->data_sources_num < new_data_sources_num);
+
+               j = data->data_sources_num;
+               data->data_sources[j] = sstrdup (ci->values[i].value.string);
+               if (data->data_sources[j] == NULL)
+               {
+                       ERROR ("`value' match: sstrdup failed.");
+                       continue;
+               }
+               data->data_sources_num++;
+       }
+
+       return (0);
+} /* }}} int ts_config_add_data_source */
+
 static int ts_destroy (void **user_data) /* {{{ */
 {
        ts_data_t **data;
@@ -309,6 +373,13 @@ static int ts_destroy (void **user_data) /* {{{ */
 
        data = (ts_data_t **) user_data;
 
+       if (*data && (*data)->data_sources) {
+               size_t i;
+               for (i = 0; i < (*data)->data_sources_num; i++)
+                       free((*data)->data_sources[i]);
+               free((*data)->data_sources);
+       }
+
        free (*data);
        *data = NULL;
 
@@ -341,6 +412,8 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
                                status = ts_config_set_double (&data->factor, child);
                else if (strcasecmp ("Offset", child->key) == 0)
                                status = ts_config_set_double (&data->offset, child);
+               else if (strcasecmp ("DataSource", child->key) == 0)
+                               status = ts_config_add_data_source(data, child);
                else
                {
                        ERROR ("Target `scale': The `%s' configuration option is not understood "
@@ -393,6 +466,18 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
        for (i = 0; i < ds->ds_num; i++)
        {
+               /* If we've got a list of data sources, is it in the list? */
+               if (data->data_sources) {
+                       size_t j;
+                       for (j = 0; j < data->data_sources_num; j++)
+                               if (strcasecmp(ds->ds[i].name, data->data_sources[j]) == 0)
+                                       break;
+
+                       /* No match, ignore */
+                       if (j >= data->data_sources_num)
+                               continue;
+               }
+
                if (ds->ds[i].type == DS_TYPE_COUNTER)
                        ts_invoke_counter (ds, vl, data, i);
                else if (ds->ds[i].type == DS_TYPE_GAUGE)