X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_db_query.c;h=893d59075b6c0be7a609ba2f1e1424515f5a428b;hb=979b0fa58b2de639ff79209eff12ec17ff593483;hp=675272c049d52d671d7bd50a3ebfccc04b77f9f8;hpb=9039795bcb798f5ad7399afc16ef6770316a878e;p=collectd.git diff --git a/src/utils_db_query.c b/src/utils_db_query.c index 675272c0..893d5907 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,15 +43,8 @@ struct udb_result_s size_t instances_num; char **values; size_t values_num; - - /* Legacy data */ - int legacy_mode; - size_t legacy_position; - /* When in legacy mode: - * - type/ds hold the format of the data - * - instance_prefix is used as type-instance if non-NULL - * - legacy_position holds the index of the column to use as value. - */ + char **metadata; + size_t metadata_num; udb_result_t *next; }; /* }}} */ @@ -57,8 +55,6 @@ struct udb_query_s /* {{{ */ char *statement; void *user_data; - int legacy_mode; - unsigned int min_version; unsigned int max_version; @@ -70,8 +66,10 @@ 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; struct udb_result_preparation_area_s *next; }; /* }}} */ @@ -84,7 +82,7 @@ struct udb_query_preparation_area_s /* {{{ */ char *plugin; char *db_name; - int interval; + cdtime_t interval; udb_result_preparation_area_t *result_prep_areas; }; /* }}} */ @@ -191,173 +189,6 @@ static int udb_config_set_uint (unsigned int *ret_value, /* {{{ */ } /* }}} int udb_config_set_uint */ /* - * Legacy result private functions - */ -static void udb_legacy_result_finish_result (udb_result_t const *r, /* {{{ */ - udb_result_preparation_area_t *prep_area) -{ - if ((r == NULL) || (prep_area)) - return; - - assert (r->legacy_mode == 1); - - prep_area->ds = NULL; -} /* }}} void udb_legacy_result_finish_result */ - -static int udb_legacy_result_handle_result (udb_result_t *r, /* {{{ */ - udb_query_preparation_area_t *q_area, - udb_result_preparation_area_t *r_area, - udb_query_t const *q, char **column_values) -{ - value_list_t vl = VALUE_LIST_INIT; - value_t value; - char *value_str; - - assert (r->legacy_mode == 1); - assert (r_area->ds != NULL); - assert (r_area->ds->ds_num == 1); - - vl.values = &value; - vl.values_len = 1; - - value_str = column_values[r->legacy_position]; - if (0 != parse_value (value_str, &vl.values[0], r_area->ds->ds[0].type)) - { - ERROR ("db query utils: udb_legacy_result_handle_result: " - "Parsing `%s' as %s failed.", value_str, - DS_TYPE_TO_STRING (r_area->ds->ds[0].type)); - errno = EINVAL; - return (-1); - } - - if (q_area->interval > 0) - vl.interval = q_area->interval; - - 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)); - - if (r->instance_prefix != NULL) - sstrncpy (vl.type_instance, r->instance_prefix, - sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); - - return (0); -} /* }}} int udb_legacy_result_handle_result */ - -static int udb_legacy_result_prepare_result (udb_result_t const *r, /* {{{ */ - udb_result_preparation_area_t *prep_area, - char **column_names, size_t column_num) -{ - if (r == NULL) - return (-EINVAL); - - assert (r->legacy_mode == 1); - - /* Make sure previous preparations are cleaned up. */ - udb_legacy_result_finish_result (r, prep_area); - - if (r->legacy_position >= column_num) - { - ERROR ("db query utils: The legacy configuration specified (at least) " - "%zu `Column's, but the query returned only %zu columns!", - r->legacy_position + 1, column_num); - return (-ENOENT); - } - - /* Read `ds' and check number of values {{{ */ - prep_area->ds = plugin_get_ds (r->type); - if (prep_area->ds == NULL) - { - ERROR ("db query utils: udb_result_prepare_result: Type `%s' is not " - "known by the daemon. See types.db(5) for details.", - r->type); - return (-1); - } - - if (prep_area->ds->ds_num != 1) - { - ERROR ("db query utils: udb_result_prepare_result: The type `%s' " - "requires exactly %i values, but the legacy configuration " - "requires exactly one!", - r->type, - prep_area->ds->ds_num); - return (-1); - } - /* }}} */ - - return (0); -} /* }}} int udb_legacy_result_prepare_result */ - -static int udb_legacy_result_create (const char *query_name, /* {{{ */ - udb_result_t **r_head, oconfig_item_t *ci, size_t position) -{ - udb_result_t *r; - - if ((ci->values_num < 1) || (ci->values_num > 2) - || (ci->values[0].type != OCONFIG_TYPE_STRING) - || ((ci->values_num == 2) - && (ci->values[1].type != OCONFIG_TYPE_STRING))) - { - WARNING ("db query utils: The `Column' block needs either one or two " - "string arguments."); - return (-1); - } - - r = (udb_result_t *) malloc (sizeof (*r)); - if (r == NULL) - { - ERROR ("db query utils: malloc failed."); - return (-1); - } - memset (r, 0, sizeof (*r)); - - r->legacy_mode = 1; - r->legacy_position = position; - - r->type = strdup (ci->values[0].value.string); - if (r->type == NULL) - { - ERROR ("db query utils: strdup failed."); - free (r); - return (-1); - } - - r->instance_prefix = NULL; - if (ci->values_num == 2) - { - r->instance_prefix = strdup (ci->values[1].value.string); - if (r->instance_prefix == NULL) - { - ERROR ("db query utils: strdup failed."); - free (r->type); - free (r); - return (-1); - } - } - - /* If all went well, add this result to the list of results. */ - if (*r_head == NULL) - { - *r_head = r; - } - else - { - udb_result_t *last; - - last = *r_head; - while (last->next != NULL) - last = last->next; - - last->next = r; - } - - return (0); -} /* }}} int udb_legacy_result_create */ - -/* * Result private functions */ static int udb_result_submit (udb_result_t *r, /* {{{ */ @@ -366,9 +197,9 @@ 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->legacy_mode == 0); assert (r_area->ds != NULL); assert (((size_t) r_area->ds->ds_num) == r->values_num); @@ -432,8 +263,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 */ @@ -444,19 +305,13 @@ static void udb_result_finish_result (udb_result_t const *r, /* {{{ */ if ((r == NULL) || (prep_area == NULL)) return; - if (r->legacy_mode == 1) - { - udb_legacy_result_finish_result (r, prep_area); - return; - } - - assert (r->legacy_mode == 0); - 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, /* {{{ */ @@ -468,18 +323,15 @@ static int udb_result_handle_result (udb_result_t *r, /* {{{ */ assert (r && q_area && r_area); - if (r->legacy_mode == 1) - return (udb_legacy_result_handle_result (r, q_area, r_area, - q, column_values)); - - assert (r->legacy_mode == 0); - for (i = 0; i < r->instances_num; i++) r_area->instances_buffer[i] = column_values[r_area->instances_pos[i]]; 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]]; + return udb_result_submit (r, r_area, q, q_area); } /* }}} int udb_result_handle_result */ @@ -492,24 +344,21 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ if ((r == NULL) || (prep_area == NULL)) return (-EINVAL); - if (r->legacy_mode == 1) - return (udb_legacy_result_prepare_result (r, prep_area, - column_names, column_num)); - - assert (r->legacy_mode == 0); - #define BAIL_OUT(status) \ 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); @@ -532,8 +381,8 @@ 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 @@ -568,6 +417,23 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ ERROR ("db query utils: udb_result_prepare_result: malloc 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: malloc 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: malloc failed."); + BAIL_OUT (-ENOMEM); + } + /* }}} */ /* Determine the position of the instance columns {{{ */ @@ -616,6 +482,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 */ @@ -637,6 +526,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); @@ -667,6 +560,7 @@ static int udb_result_create (const char *query_name, /* {{{ */ r->instance_prefix = NULL; r->instances = NULL; r->values = NULL; + r->metadata = NULL; r->next = NULL; /* Fill the `udb_result_t' structure.. */ @@ -683,6 +577,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.", @@ -759,7 +655,7 @@ void udb_query_free_one (udb_query_t *q) /* {{{ */ */ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ size_t *ret_query_list_len, oconfig_item_t *ci, - udb_query_create_callback_t cb, int legacy_mode) + udb_query_create_callback_t cb) { udb_query_t **query_list; size_t query_list_len; @@ -768,8 +664,6 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ int status; int i; - size_t legacy_position; - if ((ret_query_list == NULL) || (ret_query_list_len == NULL)) return (-EINVAL); query_list = *ret_query_list; @@ -790,12 +684,9 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ return (-1); } memset (q, 0, sizeof (*q)); - q->legacy_mode = legacy_mode; q->min_version = 0; q->max_version = UINT_MAX; - legacy_position = 0; - status = udb_config_set_string (&q->name, ci); if (status != 0) { @@ -817,42 +708,6 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ else if (strcasecmp ("MaxVersion", child->key) == 0) status = udb_config_set_uint (&q->max_version, child); - /* PostgreSQL compatibility code */ - else if ((strcasecmp ("Query", child->key) == 0) - && (q->legacy_mode == 1)) - { - WARNING ("db query utils: Query `%s': The `Query' option is " - "deprecated. Please use `Statement' instead.", - q->name); - status = udb_config_set_string (&q->statement, child); - } - else if ((strcasecmp ("Column", child->key) == 0) - && (q->legacy_mode == 1)) - { - WARNING ("db query utils: Query `%s': The `Column' option is " - "deprecated. Please use the new syntax instead.", - q->name); - status = udb_legacy_result_create (q->name, &q->results, child, - legacy_position); - legacy_position++; - } - else if ((strcasecmp ("MinPGVersion", child->key) == 0) - && (q->legacy_mode == 1)) - { - WARNING ("db query utils: Query `%s': The `MinPGVersion' option is " - "deprecated. Please use `MinVersion' instead.", - q->name); - status = udb_config_set_uint (&q->min_version, child); - } - else if ((strcasecmp ("MaxPGVersion", child->key) == 0) - && (q->legacy_mode == 1)) - { - WARNING ("db query utils: Query `%s': The `MaxPGVersion' option is " - "deprecated. Please use `MaxVersion' instead.", - q->name); - status = udb_config_set_uint (&q->max_version, child); - } - /* Call custom callbacks */ else if (cb != NULL) { @@ -1079,7 +934,7 @@ void udb_query_finish_result (udb_query_t const *q, /* {{{ */ sfree (prep_area->plugin); sfree (prep_area->db_name); - prep_area->interval = -1; + prep_area->interval = 0; for (r = q->results, r_area = prep_area->result_prep_areas; r != NULL; r = r->next, r_area = r_area->next) @@ -1147,7 +1002,7 @@ int udb_query_handle_result (udb_query_t const *q, /* {{{ */ int udb_query_prepare_result (udb_query_t const *q, /* {{{ */ udb_query_preparation_area_t *prep_area, const char *host, const char *plugin, const char *db_name, - char **column_names, size_t column_num, int interval) + char **column_names, size_t column_num, cdtime_t interval) { udb_result_preparation_area_t *r_area; udb_result_t *r;