X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_db_query.c;h=5531b25fe7fd60eb5e34300b8f2cfb0ce3cbbf2f;hb=633c3966f770e4d46651a2fe219a18d8a9907a9f;hp=868b53bf5c92e68fb24c0aaf7ae42612dd22c645;hpb=0b8442dd33105499df02180294c36d5705d596f0;p=collectd.git diff --git a/src/utils_db_query.c b/src/utils_db_query.c index 868b53bf..43ca2965 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" @@ -39,13 +44,6 @@ struct udb_result_s char **values; size_t values_num; - /* Preparation area */ - const data_set_t *ds; - size_t *instances_pos; - size_t *values_pos; - char **instances_buffer; - char **values_buffer; - udb_result_t *next; }; /* }}} */ @@ -58,13 +56,31 @@ struct udb_query_s /* {{{ */ unsigned int min_version; unsigned int max_version; - /* Preparation area */ + udb_result_t *results; +}; /* }}} */ + +struct udb_result_preparation_area_s /* {{{ */ +{ + const data_set_t *ds; + size_t *instances_pos; + size_t *values_pos; + char **instances_buffer; + char **values_buffer; + + struct udb_result_preparation_area_s *next; +}; /* }}} */ +typedef struct udb_result_preparation_area_s udb_result_preparation_area_t; + +struct udb_query_preparation_area_s /* {{{ */ +{ size_t column_num; char *host; char *plugin; char *db_name; - udb_result_t *results; + cdtime_t interval; + + udb_result_preparation_area_t *result_prep_areas; }; /* }}} */ /* @@ -171,132 +187,139 @@ static int udb_config_set_uint (unsigned int *ret_value, /* {{{ */ /* * Result private functions */ -static void udb_result_submit (udb_result_t *r, udb_query_t *q) /* {{{ */ +static int udb_result_submit (udb_result_t *r, /* {{{ */ + udb_result_preparation_area_t *r_area, + udb_query_t const *q, udb_query_preparation_area_t *q_area) { value_list_t vl = VALUE_LIST_INIT; size_t i; - assert (((size_t) r->ds->ds_num) == r->values_num); - - DEBUG ("db query utils: udb_result_submit: r->instance_prefix = %s;", - (r->instance_prefix == NULL) ? "NULL" : r->instance_prefix); - for (i = 0; i < r->instances_num; i++) - { - DEBUG ("db query utils: udb_result_submit: r->instances_buffer[%zu] = %s;", - i, r->instances_buffer[i]); - } + assert (r != NULL); + assert (r_area->ds != NULL); + assert (((size_t) r_area->ds->ds_num) == r->values_num); - vl.values = (value_t *) calloc (r->ds->ds_num, sizeof (value_t)); + vl.values = (value_t *) calloc (r_area->ds->ds_num, sizeof (value_t)); if (vl.values == NULL) { ERROR ("db query utils: malloc failed."); - return; + return (-1); } - vl.values_len = r->ds->ds_num; + vl.values_len = r_area->ds->ds_num; for (i = 0; i < r->values_num; i++) { - char *endptr; - - endptr = NULL; - errno = 0; - if (r->ds->ds[i].type == DS_TYPE_COUNTER) - vl.values[i].counter = (counter_t) strtoll (r->values_buffer[i], - &endptr, /* base = */ 0); - else if (r->ds->ds[i].type == DS_TYPE_GAUGE) - vl.values[i].gauge = (gauge_t) strtod (r->values_buffer[i], &endptr); - else - errno = EINVAL; + char *value_str = r_area->values_buffer[i]; - if ((endptr == r->values_buffer[i]) || (errno != 0)) + if (0 != parse_value (value_str, &vl.values[i], r_area->ds->ds[i].type)) { - WARNING ("db query utils: udb_result_submit: Parsing `%s' as %s failed.", - r->values_buffer[i], - (r->ds->ds[i].type == DS_TYPE_COUNTER) ? "counter" : "gauge"); - vl.values[i].gauge = NAN; + 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; + return (-1); } } - vl.time = time (NULL); - sstrncpy (vl.host, q->host, sizeof (vl.host)); - sstrncpy (vl.plugin, q->plugin, sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, q->db_name, sizeof (vl.type_instance)); + 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) + /* Set vl.type_instance {{{ */ + if (r->instances_num <= 0) { - strjoin (vl.type_instance, sizeof (vl.type_instance), - r->instances_buffer, r->instances_num, "-"); + if (r->instance_prefix == NULL) + vl.type_instance[0] = 0; + else + sstrncpy (vl.type_instance, r->instance_prefix, + sizeof (vl.type_instance)); } - else + else /* if ((r->instances_num > 0) */ { - char tmp[DATA_MAX_NAME_LEN]; + if (r->instance_prefix == NULL) + { + strjoin (vl.type_instance, sizeof (vl.type_instance), + r_area->instances_buffer, r->instances_num, "-"); + } + else + { + char tmp[DATA_MAX_NAME_LEN]; - strjoin (tmp, sizeof (tmp), r->instances_buffer, r->instances_num, "-"); - tmp[sizeof (tmp) - 1] = 0; + strjoin (tmp, sizeof (tmp), r_area->instances_buffer, + r->instances_num, "-"); + tmp[sizeof (tmp) - 1] = 0; - snprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s", - r->instance_prefix, tmp); + snprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s", + r->instance_prefix, tmp); + } } vl.type_instance[sizeof (vl.type_instance) - 1] = 0; + /* }}} */ plugin_dispatch_values (&vl); sfree (vl.values); + return (0); } /* }}} void udb_result_submit */ -static void udb_result_finish_result (udb_result_t *r) /* {{{ */ +static void udb_result_finish_result (udb_result_t const *r, /* {{{ */ + udb_result_preparation_area_t *prep_area) { - if (r == NULL) + if ((r == NULL) || (prep_area == NULL)) return; - r->ds = NULL; - sfree (r->instances_pos); - sfree (r->values_pos); - sfree (r->instances_buffer); - sfree (r->values_buffer); + prep_area->ds = NULL; + sfree (prep_area->instances_pos); + sfree (prep_area->values_pos); + sfree (prep_area->instances_buffer); + sfree (prep_area->values_buffer); } /* }}} void udb_result_finish_result */ static int udb_result_handle_result (udb_result_t *r, /* {{{ */ - udb_query_t *q, char **column_values) + udb_query_preparation_area_t *q_area, + udb_result_preparation_area_t *r_area, + udb_query_t const *q, char **column_values) { size_t i; + assert (r && q_area && r_area); + for (i = 0; i < r->instances_num; i++) - r->instances_buffer[i] = column_values[r->instances_pos[i]]; + r_area->instances_buffer[i] = column_values[r_area->instances_pos[i]]; for (i = 0; i < r->values_num; i++) - r->values_buffer[i] = column_values[r->values_pos[i]]; - - udb_result_submit (r, q); + r_area->values_buffer[i] = column_values[r_area->values_pos[i]]; - return (0); + return udb_result_submit (r, r_area, q, q_area); } /* }}} int udb_result_handle_result */ -static int udb_result_prepare_result (udb_result_t *r, /* {{{ */ +static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */ + udb_result_preparation_area_t *prep_area, char **column_names, size_t column_num) { size_t i; - if (r == NULL) + if ((r == NULL) || (prep_area == NULL)) return (-EINVAL); #define BAIL_OUT(status) \ - r->ds = NULL; \ - sfree (r->instances_pos); \ - sfree (r->values_pos); \ - sfree (r->instances_buffer); \ - sfree (r->values_buffer); \ + prep_area->ds = NULL; \ + sfree (prep_area->instances_pos); \ + sfree (prep_area->values_pos); \ + sfree (prep_area->instances_buffer); \ + sfree (prep_area->values_buffer); \ return (status) /* Make sure previous preparations are cleaned up. */ - udb_result_finish_result (r); - r->instances_pos = NULL; - r->values_pos = NULL; + udb_result_finish_result (r, prep_area); + prep_area->instances_pos = NULL; + prep_area->values_pos = NULL; /* Read `ds' and check number of values {{{ */ - r->ds = plugin_get_ds (r->type); - if (r->ds == NULL) + 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.", @@ -304,12 +327,12 @@ static int udb_result_prepare_result (udb_result_t *r, /* {{{ */ BAIL_OUT (-1); } - if (((size_t) r->ds->ds_num) != r->values_num) + if (((size_t) 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.", r->type, - r->ds->ds_num, (r->ds->ds_num == 1) ? "" : "s", + prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num); BAIL_OUT (-1); } @@ -317,29 +340,36 @@ static int udb_result_prepare_result (udb_result_t *r, /* {{{ */ /* Allocate r->instances_pos, r->values_pos, r->instances_buffer, and * r->values_buffer {{{ */ - r->instances_pos = (size_t *) calloc (r->instances_num, sizeof (size_t)); - if (r->instances_pos == NULL) + if (r->instances_num > 0) { - ERROR ("db query utils: udb_result_prepare_result: malloc failed."); - BAIL_OUT (-ENOMEM); - } + 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."); + BAIL_OUT (-ENOMEM); + } - r->values_pos = (size_t *) calloc (r->values_num, sizeof (size_t)); - if (r->values_pos == NULL) - { - ERROR ("db query utils: udb_result_prepare_result: malloc failed."); - BAIL_OUT (-ENOMEM); - } + prep_area->instances_buffer + = (char **) calloc (r->instances_num, sizeof (char *)); + if (prep_area->instances_buffer == NULL) + { + ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + BAIL_OUT (-ENOMEM); + } + } /* if (r->instances_num > 0) */ - r->instances_buffer = (char **) calloc (r->instances_num, sizeof (char *)); - if (r->instances_buffer == NULL) + prep_area->values_pos + = (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."); BAIL_OUT (-ENOMEM); } - r->values_buffer = (char **) calloc (r->values_num, sizeof (char *)); - if (r->values_buffer == NULL) + prep_area->values_buffer + = (char **) calloc (r->values_num, sizeof (char *)); + if (prep_area->values_buffer == NULL) { ERROR ("db query utils: udb_result_prepare_result: malloc failed."); BAIL_OUT (-ENOMEM); @@ -355,7 +385,7 @@ static int udb_result_prepare_result (udb_result_t *r, /* {{{ */ { if (strcasecmp (r->instances[i], column_names[j]) == 0) { - r->instances_pos[i] = j; + prep_area->instances_pos[i] = j; break; } } @@ -378,7 +408,7 @@ static int udb_result_prepare_result (udb_result_t *r, /* {{{ */ { if (strcasecmp (r->values[i], column_names[j]) == 0) { - r->values_pos[i] = j; + prep_area->values_pos[i] = j; break; } } @@ -479,12 +509,6 @@ static int udb_result_create (const char *query_name, /* {{{ */ "result in query `%s'", query_name); status = -1; } - if (r->instances == NULL) - { - WARNING ("db query utils: `InstancesFrom' not given for " - "result in query `%s'", query_name); - status = -1; - } if (r->values == NULL) { WARNING ("db query utils: `ValuesFrom' not given for " @@ -540,7 +564,8 @@ void udb_query_free_one (udb_query_t *q) /* {{{ */ * Query public functions */ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */ - size_t *ret_query_list_len, oconfig_item_t *ci) + size_t *ret_query_list_len, oconfig_item_t *ci, + udb_query_create_callback_t cb) { udb_query_t **query_list; size_t query_list_len; @@ -592,20 +617,16 @@ 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); - /* PostgreSQL compatibility code */ - else if (strcasecmp ("MinPGVersion", child->key) == 0) - { - 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) + + /* Call custom callbacks */ + else if (cb != NULL) { - 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); + status = (*cb) (q, child); + if (status != 0) + { + WARNING ("db query utils: The configuration callback failed " + "to handle `%s'.", child->key); + } } else { @@ -680,63 +701,90 @@ void udb_query_free (udb_query_t **query_list, size_t query_list_len) /* {{{ */ sfree (query_list); } /* }}} void udb_query_free */ -int udb_query_pick_from_list (oconfig_item_t *ci, /* {{{ */ +int udb_query_pick_from_list_by_name (const char *name, /* {{{ */ udb_query_t **src_list, size_t src_list_len, udb_query_t ***dst_list, size_t *dst_list_len) { - const char *name; - udb_query_t *q; - udb_query_t **tmp_list; - size_t tmp_list_len; size_t i; + int num_added; - if ((ci == NULL) || (src_list == NULL) || (dst_list == NULL) + if ((name == NULL) || (src_list == NULL) || (dst_list == NULL) || (dst_list_len == NULL)) { - ERROR ("db query utils: Invalid argument."); + ERROR ("db query utils: udb_query_pick_from_list_by_name: " + "Invalid argument."); return (-EINVAL); } - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_STRING)) + num_added = 0; + for (i = 0; i < src_list_len; i++) { - ERROR ("db query utils: The `%s' config option " - "needs exactly one string argument.", ci->key); - return (-1); - } - name = ci->values[0].value.string; + udb_query_t **tmp_list; + size_t tmp_list_len; - q = NULL; - for (i = 0; i < src_list_len; i++) - if (strcasecmp (name, src_list[i]->name) == 0) + if (strcasecmp (name, src_list[i]->name) != 0) + continue; + + tmp_list_len = *dst_list_len; + tmp_list = (udb_query_t **) realloc (*dst_list, (tmp_list_len + 1) + * sizeof (udb_query_t *)); + if (tmp_list == NULL) { - q = src_list[i]; - break; + ERROR ("db query utils: realloc failed."); + return (-ENOMEM); } - if (q == NULL) + tmp_list[tmp_list_len] = src_list[i]; + tmp_list_len++; + + *dst_list = tmp_list; + *dst_list_len = tmp_list_len; + + num_added++; + } /* for (i = 0; i < src_list_len; i++) */ + + if (num_added <= 0) { - ERROR ("db query utils: Cannot find query `%s'. Make sure the <%s> " + ERROR ("db query utils: Cannot find query `%s'. Make sure the " "block is above the database definition!", - name, ci->key); + name); return (-ENOENT); } + else + { + DEBUG ("db query utils: Added %i versions of query `%s'.", + num_added, name); + } + + return (0); +} /* }}} int udb_query_pick_from_list_by_name */ + +int udb_query_pick_from_list (oconfig_item_t *ci, /* {{{ */ + udb_query_t **src_list, size_t src_list_len, + udb_query_t ***dst_list, size_t *dst_list_len) +{ + const char *name; - tmp_list_len = *dst_list_len; - tmp_list = (udb_query_t **) realloc (*dst_list, (tmp_list_len + 1) - * sizeof (udb_query_t *)); - if (tmp_list == NULL) + if ((ci == NULL) || (src_list == NULL) || (dst_list == NULL) + || (dst_list_len == NULL)) { - ERROR ("db query utils: realloc failed."); - return (-ENOMEM); + ERROR ("db query utils: udb_query_pick_from_list: " + "Invalid argument."); + return (-EINVAL); } - tmp_list[tmp_list_len] = q; - tmp_list_len++; - *dst_list = tmp_list; - *dst_list_len = tmp_list_len; + if ((ci->values_num != 1) + || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + ERROR ("db query utils: The `%s' config option " + "needs exactly one string argument.", ci->key); + return (-1); + } + name = ci->values[0].value.string; - return (0); + return (udb_query_pick_from_list_by_name (name, + src_list, src_list_len, + dst_list, dst_list_len)); } /* }}} int udb_query_pick_from_list */ const char *udb_query_get_name (udb_query_t *q) /* {{{ */ @@ -782,33 +830,45 @@ int udb_query_check_version (udb_query_t *q, unsigned int version) /* {{{ */ return (1); } /* }}} int udb_query_check_version */ -void udb_query_finish_result (udb_query_t *q) /* {{{ */ +void udb_query_finish_result (udb_query_t const *q, /* {{{ */ + udb_query_preparation_area_t *prep_area) { + udb_result_preparation_area_t *r_area; udb_result_t *r; - if (q == NULL) + if ((q == NULL) || (prep_area == NULL)) return; - q->column_num = 0; - sfree (q->host); - sfree (q->plugin); - sfree (q->db_name); + prep_area->column_num = 0; + sfree (prep_area->host); + sfree (prep_area->plugin); + sfree (prep_area->db_name); - for (r = q->results; r != NULL; r = r->next) - udb_result_finish_result (r); + 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) + { + /* this may happen during error conditions of the caller */ + if (r_area == NULL) + break; + udb_result_finish_result (r, r_area); + } } /* }}} void udb_query_finish_result */ -int udb_query_handle_result (udb_query_t *q, char **column_values) /* {{{ */ +int udb_query_handle_result (udb_query_t const *q, /* {{{ */ + udb_query_preparation_area_t *prep_area, char **column_values) { + udb_result_preparation_area_t *r_area; udb_result_t *r; int success; int status; - if (q == NULL) + if ((q == NULL) || (prep_area == NULL)) return (-EINVAL); - if ((q->column_num < 1) || (q->host == NULL) || (q->plugin == NULL) - || (q->db_name == NULL)) + if ((prep_area->column_num < 1) || (prep_area->host == NULL) + || (prep_area->plugin == NULL) || (prep_area->db_name == NULL)) { ERROR ("db query utils: Query `%s': Query is not prepared; " "can't handle result.", q->name); @@ -820,19 +880,21 @@ int udb_query_handle_result (udb_query_t *q, char **column_values) /* {{{ */ { size_t i; - for (i = 0; i < q->column_num; i++) + for (i = 0; i < prep_area->column_num; i++) { DEBUG ("db query utils: udb_query_handle_result (%s, %s): " "column[%zu] = %s;", - q->db_name, q->name, i, column_values[i]); + prep_area->db_name, q->name, i, column_values[i]); } } while (0); #endif /* }}} */ success = 0; - for (r = q->results; r != NULL; r = r->next) + for (r = q->results, r_area = prep_area->result_prep_areas; + r != NULL; r = r->next, r_area = r_area->next) { - status = udb_result_handle_result (r, q, column_values); + status = udb_result_handle_result (r, prep_area, r_area, + q, column_values); if (status == 0) success++; } @@ -840,34 +902,39 @@ int udb_query_handle_result (udb_query_t *q, char **column_values) /* {{{ */ if (success == 0) { ERROR ("db query utils: udb_query_handle_result (%s, %s): " - "All results failed.", q->db_name, q->name); + "All results failed.", prep_area->db_name, q->name); return (-1); } return (0); } /* }}} int udb_query_handle_result */ -int udb_query_prepare_result (udb_query_t *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) + char **column_names, size_t column_num, cdtime_t interval) { + udb_result_preparation_area_t *r_area; udb_result_t *r; int status; - if (q == NULL) + if ((q == NULL) || (prep_area == NULL)) return (-EINVAL); - udb_query_finish_result (q); + udb_query_finish_result (q, prep_area); + + prep_area->column_num = column_num; + prep_area->host = strdup (host); + prep_area->plugin = strdup (plugin); + prep_area->db_name = strdup (db_name); - q->column_num = column_num; - q->host = strdup (host); - q->plugin = strdup (plugin); - q->db_name = strdup (db_name); + prep_area->interval = interval; - if ((q->host == NULL) || (q->plugin == NULL) || (q->db_name == NULL)) + if ((prep_area->host == NULL) || (prep_area->plugin == NULL) + || (prep_area->db_name == NULL)) { ERROR ("db query utils: Query `%s': Prepare failed: Out of memory.", q->name); - udb_query_finish_result (q); + udb_query_finish_result (q, prep_area); return (-ENOMEM); } @@ -885,12 +952,21 @@ int udb_query_prepare_result (udb_query_t *q, /* {{{ */ } while (0); #endif - for (r = q->results; r != NULL; r = r->next) + for (r = q->results, r_area = prep_area->result_prep_areas; + r != NULL; r = r->next, r_area = r_area->next) { - status = udb_result_prepare_result (r, column_names, column_num); + if (! r_area) + { + ERROR ("db query utils: Query `%s': Invalid number of result " + "preparation areas.", q->name); + udb_query_finish_result (q, prep_area); + return (-EINVAL); + } + + status = udb_result_prepare_result (r, r_area, column_names, column_num); if (status != 0) { - udb_query_finish_result (q); + udb_query_finish_result (q, prep_area); return (status); } } @@ -898,4 +974,72 @@ int udb_query_prepare_result (udb_query_t *q, /* {{{ */ return (0); } /* }}} int udb_query_prepare_result */ +udb_query_preparation_area_t * +udb_query_allocate_preparation_area (udb_query_t *q) /* {{{ */ +{ + udb_query_preparation_area_t *q_area; + udb_result_preparation_area_t **next_r_area; + udb_result_t *r; + + q_area = (udb_query_preparation_area_t *)malloc (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 = (udb_result_preparation_area_t *)malloc (sizeof (*r_area)); + if (r_area == NULL) + { + for (r_area = q_area->result_prep_areas; + r_area != NULL; r_area = r_area->next) + { + free (r_area); + } + free (q_area); + return NULL; + } + + memset (r_area, 0, sizeof (*r_area)); + + *next_r_area = r_area; + next_r_area = &r_area->next; + } + + return (q_area); +} /* }}} udb_query_preparation_area_t *udb_query_allocate_preparation_area */ + +void +udb_query_delete_preparation_area (udb_query_preparation_area_t *q_area) /* {{{ */ +{ + udb_result_preparation_area_t *r_area; + + if (q_area == NULL) + return; + + r_area = q_area->result_prep_areas; + while (r_area != NULL) + { + udb_result_preparation_area_t *area = r_area; + + r_area = r_area->next; + + sfree (area->instances_pos); + sfree (area->values_pos); + sfree (area->instances_buffer); + sfree (area->values_buffer); + free (area); + } + + sfree (q_area->host); + sfree (q_area->plugin); + sfree (q_area->db_name); + + free (q_area); +} /* }}} void udb_query_delete_preparation_area */ + /* vim: set sw=2 sts=2 et fdm=marker : */