X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_db_query.c;h=f683fb5d2bd571d409192bbc70e41ab295d871ee;hb=42ca41a0798e3a2b742f7da3bacc03fbaf6175fa;hp=6b3c056cb31d6bad732ec133a658c8645a044069;hpb=60451f81f174fc283345ade43d95857c56d17e88;p=collectd.git diff --git a/src/utils_db_query.c b/src/utils_db_query.c index 6b3c056c..f683fb5d 100644 --- a/src/utils_db_query.c +++ b/src/utils_db_query.c @@ -2,21 +2,26 @@ * collectd - src/utils_db_query.c * Copyright (C) 2008,2009 Florian octo Forster * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; only version 2 of the License is applicable. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Authors: - * Florian octo Forster + * Florian octo Forster **/ #include "collectd.h" @@ -38,6 +43,8 @@ struct udb_result_s size_t instances_num; char **values; size_t values_num; + char **metadata; + size_t metadata_num; udb_result_t *next; }; /* }}} */ @@ -47,6 +54,7 @@ struct udb_query_s /* {{{ */ char *name; char *statement; void *user_data; + char *plugin_instance_from; unsigned int min_version; unsigned int max_version; @@ -59,8 +67,11 @@ struct udb_result_preparation_area_s /* {{{ */ const data_set_t *ds; size_t *instances_pos; size_t *values_pos; + size_t *metadata_pos; char **instances_buffer; char **values_buffer; + char **metadata_buffer; + char *plugin_instance; struct udb_result_preparation_area_s *next; }; /* }}} */ @@ -69,6 +80,7 @@ typedef struct udb_result_preparation_area_s udb_result_preparation_area_t; struct udb_query_preparation_area_s /* {{{ */ { size_t column_num; + size_t plugin_instance_pos; char *host; char *plugin; char *db_name; @@ -133,7 +145,7 @@ static int udb_config_add_string (char ***ret_array, /* {{{ */ } array_len = *ret_array_len; - array = (char **) realloc (*ret_array, + array = realloc (*ret_array, sizeof (char *) * (array_len + ci->values_num)); if (array == NULL) { @@ -188,16 +200,17 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */ { value_list_t vl = VALUE_LIST_INIT; size_t i; + int status; assert (r != NULL); assert (r_area->ds != NULL); assert (((size_t) r_area->ds->ds_num) == r->values_num); assert (r->values_num > 0); - vl.values = (value_t *) calloc (r->values_num, sizeof (value_t)); + vl.values = calloc (r->values_num, sizeof (*vl.values)); if (vl.values == NULL) { - ERROR ("db query utils: malloc failed."); + ERROR ("db query utils: calloc failed."); return (-1); } vl.values_len = r_area->ds->ds_num; @@ -211,6 +224,7 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */ ERROR ("db query utils: udb_result_submit: Parsing `%s' as %s failed.", value_str, DS_TYPE_TO_STRING (r_area->ds->ds[i].type)); errno = EINVAL; + free (vl.values); return (-1); } } @@ -220,11 +234,18 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */ sstrncpy (vl.host, q_area->host, sizeof (vl.host)); sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance)); sstrncpy (vl.type, r->type, sizeof (vl.type)); + /* Set vl.plugin_instance */ + if (q->plugin_instance_from != NULL) { + sstrncpy (vl.plugin_instance, r_area->plugin_instance, sizeof (vl.plugin_instance)); + } + else { + sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance)); + } + /* Set vl.type_instance {{{ */ - if (r->instances_num <= 0) + if (r->instances_num == 0) { if (r->instance_prefix == NULL) vl.type_instance[0] = 0; @@ -254,8 +275,38 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */ vl.type_instance[sizeof (vl.type_instance) - 1] = 0; /* }}} */ + /* Annotate meta data. {{{ */ + if (r->metadata_num > 0) + { + vl.meta = meta_data_create (); + if (vl.meta == NULL) + { + ERROR ("db query utils:: meta_data_create failed."); + return (-ENOMEM); + } + + for (i = 0; i < r->metadata_num; i++) + { + status = meta_data_add_string (vl.meta, r->metadata[i], + r_area->metadata_buffer[i]); + if (status != 0) + { + ERROR ("db query utils:: meta_data_add_string failed."); + meta_data_destroy (vl.meta); + vl.meta = NULL; + return (status); + } + } + } + /* }}} */ + plugin_dispatch_values (&vl); + if (r->metadata_num > 0) + { + meta_data_destroy (vl.meta); + vl.meta = NULL; + } sfree (vl.values); return (0); } /* }}} void udb_result_submit */ @@ -269,8 +320,10 @@ static void udb_result_finish_result (udb_result_t const *r, /* {{{ */ prep_area->ds = NULL; sfree (prep_area->instances_pos); sfree (prep_area->values_pos); + sfree (prep_area->metadata_pos); sfree (prep_area->instances_buffer); sfree (prep_area->values_buffer); + sfree (prep_area->metadata_buffer); } /* }}} void udb_result_finish_result */ static int udb_result_handle_result (udb_result_t *r, /* {{{ */ @@ -288,6 +341,12 @@ static int udb_result_handle_result (udb_result_t *r, /* {{{ */ for (i = 0; i < r->values_num; i++) r_area->values_buffer[i] = column_values[r_area->values_pos[i]]; + for (i = 0; i < r->metadata_num; i++) + r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]]; + + if (q->plugin_instance_from) + r_area->plugin_instance = column_values[q_area->plugin_instance_pos]; + return udb_result_submit (r, r_area, q, q_area); } /* }}} int udb_result_handle_result */ @@ -304,14 +363,17 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ prep_area->ds = NULL; \ sfree (prep_area->instances_pos); \ sfree (prep_area->values_pos); \ + sfree (prep_area->metadata_pos); \ sfree (prep_area->instances_buffer); \ sfree (prep_area->values_buffer); \ + sfree (prep_area->metadata_buffer); \ return (status) /* Make sure previous preparations are cleaned up. */ udb_result_finish_result (r, prep_area); prep_area->instances_pos = NULL; prep_area->values_pos = NULL; + prep_area->metadata_pos = NULL; /* Read `ds' and check number of values {{{ */ prep_area->ds = plugin_get_ds (r->type); @@ -323,10 +385,10 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ BAIL_OUT (-1); } - if (((size_t) prep_area->ds->ds_num) != r->values_num) + if (prep_area->ds->ds_num != r->values_num) { ERROR ("db query utils: udb_result_prepare_result: The type `%s' " - "requires exactly %i value%s, but the configuration specifies %zu.", + "requires exactly %zu value%s, but the configuration specifies %zu.", r->type, prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num); @@ -334,15 +396,15 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ } /* }}} */ - /* Allocate r->instances_pos, r->values_pos, r->instances_buffer, and - * r->values_buffer {{{ */ + /* Allocate r->instances_pos, r->values_pos, r->metadata_post, + * r->instances_buffer, r->values_buffer, and r->metadata_buffer {{{ */ if (r->instances_num > 0) { prep_area->instances_pos = (size_t *) calloc (r->instances_num, sizeof (size_t)); if (prep_area->instances_pos == NULL) { - ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + ERROR ("db query utils: udb_result_prepare_result: calloc failed."); BAIL_OUT (-ENOMEM); } @@ -350,7 +412,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ = (char **) calloc (r->instances_num, sizeof (char *)); if (prep_area->instances_buffer == NULL) { - ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + ERROR ("db query utils: udb_result_prepare_result: calloc failed."); BAIL_OUT (-ENOMEM); } } /* if (r->instances_num > 0) */ @@ -359,7 +421,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ = (size_t *) calloc (r->values_num, sizeof (size_t)); if (prep_area->values_pos == NULL) { - ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + ERROR ("db query utils: udb_result_prepare_result: calloc failed."); BAIL_OUT (-ENOMEM); } @@ -367,12 +429,29 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ = (char **) calloc (r->values_num, sizeof (char *)); if (prep_area->values_buffer == NULL) { - ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + ERROR ("db query utils: udb_result_prepare_result: calloc failed."); + BAIL_OUT (-ENOMEM); + } + + prep_area->metadata_pos + = (size_t *) calloc (r->metadata_num, sizeof (size_t)); + if (prep_area->metadata_pos == NULL) + { + ERROR ("db query utils: udb_result_prepare_result: calloc failed."); BAIL_OUT (-ENOMEM); } + + prep_area->metadata_buffer + = (char **) calloc (r->metadata_num, sizeof (char *)); + if (prep_area->metadata_buffer == NULL) + { + ERROR ("db query utils: udb_result_prepare_result: calloc failed."); + BAIL_OUT (-ENOMEM); + } + /* }}} */ - /* Determine the position of the instance columns {{{ */ + /* Determine the position of the plugin instance column {{{ */ for (i = 0; i < r->instances_num; i++) { size_t j; @@ -395,6 +474,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ } } /* }}} for (i = 0; i < r->instances_num; i++) */ + /* Determine the position of the value columns {{{ */ for (i = 0; i < r->values_num; i++) { @@ -418,6 +498,29 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ } } /* }}} for (i = 0; i < r->values_num; i++) */ + /* Determine the position of the metadata columns {{{ */ + for (i = 0; i < r->metadata_num; i++) + { + size_t j; + + for (j = 0; j < column_num; j++) + { + if (strcasecmp (r->metadata[i], column_names[j]) == 0) + { + prep_area->metadata_pos[i] = j; + break; + } + } + + if (j >= column_num) + { + ERROR ("db query utils: udb_result_prepare_result: " + "Metadata column `%s' could not be found.", + r->values[i]); + BAIL_OUT (-ENOENT); + } + } /* }}} for (i = 0; i < r->metadata_num; i++) */ + #undef BAIL_OUT return (0); } /* }}} int udb_result_prepare_result */ @@ -430,6 +533,7 @@ static void udb_result_free (udb_result_t *r) /* {{{ */ return; sfree (r->type); + sfree (r->instance_prefix); for (i = 0; i < r->instances_num; i++) sfree (r->instances[i]); @@ -439,6 +543,10 @@ static void udb_result_free (udb_result_t *r) /* {{{ */ sfree (r->values[i]); sfree (r->values); + for (i = 0; i < r->metadata_num; i++) + sfree (r->metadata[i]); + sfree (r->metadata); + udb_result_free (r->next); sfree (r); @@ -458,17 +566,17 @@ static int udb_result_create (const char *query_name, /* {{{ */ ci->values_num, (ci->values_num == 1) ? "" : "s"); } - r = (udb_result_t *) malloc (sizeof (*r)); + r = calloc (1, sizeof (*r)); if (r == NULL) { - ERROR ("db query utils: malloc failed."); + ERROR ("db query utils: calloc failed."); return (-1); } - memset (r, 0, sizeof (*r)); r->type = NULL; r->instance_prefix = NULL; r->instances = NULL; r->values = NULL; + r->metadata = NULL; r->next = NULL; /* Fill the `udb_result_t' structure.. */ @@ -485,6 +593,8 @@ static int udb_result_create (const char *query_name, /* {{{ */ status = udb_config_add_string (&r->instances, &r->instances_num, child); else if (strcasecmp ("ValuesFrom", child->key) == 0) status = udb_config_add_string (&r->values, &r->values_num, child); + else if (strcasecmp ("MetadataFrom", child->key) == 0) + status = udb_config_add_string (&r->metadata, &r->metadata_num, child); else { WARNING ("db query utils: Query `%s': Option `%s' not allowed here.", @@ -550,6 +660,7 @@ static void udb_query_free_one (udb_query_t *q) /* {{{ */ sfree (q->name); sfree (q->statement); + sfree (q->plugin_instance_from); udb_result_free (q->results); @@ -583,15 +694,17 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ return (-1); } - q = (udb_query_t *) malloc (sizeof (*q)); + q = calloc (1, sizeof (*q)); if (q == NULL) { - ERROR ("db query utils: malloc failed."); + ERROR ("db query utils: calloc failed."); return (-1); } - memset (q, 0, sizeof (*q)); q->min_version = 0; q->max_version = UINT_MAX; + q->statement = NULL; + q->results = NULL; + q->plugin_instance_from = NULL; status = udb_config_set_string (&q->name, ci); if (status != 0) @@ -613,6 +726,8 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ status = udb_config_set_uint (&q->min_version, child); else if (strcasecmp ("MaxVersion", child->key) == 0) status = udb_config_set_uint (&q->max_version, child); + else if (strcasecmp ("PluginInstanceFrom", child->key) == 0) + status = udb_config_set_string (&q->plugin_instance_from, child); /* Call custom callbacks */ else if (cb != NULL) @@ -657,7 +772,7 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ { udb_query_t **temp; - temp = (udb_query_t **) realloc (query_list, + temp = realloc (query_list, sizeof (*query_list) * (query_list_len + 1)); if (temp == NULL) { @@ -722,7 +837,7 @@ int udb_query_pick_from_list_by_name (const char *name, /* {{{ */ continue; tmp_list_len = *dst_list_len; - tmp_list = (udb_query_t **) realloc (*dst_list, (tmp_list_len + 1) + tmp_list = realloc (*dst_list, (tmp_list_len + 1) * sizeof (udb_query_t *)); if (tmp_list == NULL) { @@ -948,6 +1063,31 @@ int udb_query_prepare_result (udb_query_t const *q, /* {{{ */ } while (0); #endif + /* Determine the position of the PluginInstance column {{{ */ + if (q->plugin_instance_from != NULL) + { + size_t i; + + for (i = 0; i < column_num; i++) + { + if (strcasecmp (q->plugin_instance_from, column_names[i]) == 0) + { + prep_area->plugin_instance_pos = i; + break; + } + } + + if (i >= column_num) + { + ERROR ("db query utils: udb_query_prepare_result: " + "Column `%s' from `PluginInstanceFrom' could not be found.", + q->plugin_instance_from); + udb_query_finish_result (q, prep_area); + return (-ENOENT); + } + } + /* }}} */ + for (r = q->results, r_area = prep_area->result_prep_areas; r != NULL; r = r->next, r_area = r_area->next) { @@ -977,17 +1117,16 @@ udb_query_allocate_preparation_area (udb_query_t *q) /* {{{ */ udb_result_preparation_area_t **next_r_area; udb_result_t *r; - q_area = malloc (sizeof (*q_area)); + q_area = calloc (1, sizeof (*q_area)); if (q_area == NULL) return NULL; - memset (q_area, 0, sizeof (*q_area)); next_r_area = &q_area->result_prep_areas; for (r = q->results; r != NULL; r = r->next) { udb_result_preparation_area_t *r_area; - r_area = malloc (sizeof (*r_area)); + r_area = calloc (1, sizeof (*r_area)); if (r_area == NULL) { udb_result_preparation_area_t *a = q_area->result_prep_areas; @@ -1003,8 +1142,6 @@ udb_query_allocate_preparation_area (udb_query_t *q) /* {{{ */ return NULL; } - memset (r_area, 0, sizeof (*r_area)); - *next_r_area = r_area; next_r_area = &r_area->next; }