X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fpostgresql.c;h=0a5e66c25d934acd4de939cd049e6070a3121ca9;hb=3b473acc5d4d27e5cf5101a4b8cc8a21c2bb7262;hp=0141b23e22bed1236cc92bc8bd6a338f3689547a;hpb=87cdeb24ec6f02f623c9077e35904c0b7bec4a93;p=collectd.git diff --git a/src/postgresql.c b/src/postgresql.c index 0141b23e..0a5e66c2 100644 --- a/src/postgresql.c +++ b/src/postgresql.c @@ -2,19 +2,30 @@ * collectd - src/postgresql.c * Copyright (C) 2008, 2009 Sebastian Harl * Copyright (C) 2009 Florian Forster + * All rights reserved. * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 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. + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 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 + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * * Authors: * Sebastian Harl @@ -102,10 +113,11 @@ typedef struct { int max_params_num; /* user configuration */ + udb_query_preparation_area_t **q_prep_areas; udb_query_t **queries; size_t queries_num; - int interval; + cdtime_t interval; char *host; char *port; @@ -141,7 +153,7 @@ static c_psql_database_t *c_psql_database_new (const char *name) db = (c_psql_database_t *)malloc (sizeof (*db)); if (NULL == db) { log_err ("Out of memory."); - exit (5); + return NULL; } db->conn = NULL; @@ -153,6 +165,7 @@ static c_psql_database_t *c_psql_database_new (const char *name) db->max_params_num = 0; + db->q_prep_areas = NULL; db->queries = NULL; db->queries_num = 0; @@ -174,11 +187,18 @@ static c_psql_database_t *c_psql_database_new (const char *name) static void c_psql_database_delete (void *data) { + size_t i; + c_psql_database_t *db = data; PQfinish (db->conn); db->conn = NULL; + if (db->q_prep_areas) + for (i = 0; i < db->queries_num; ++i) + udb_query_delete_preparation_area (db->q_prep_areas[i]); + free (db->q_prep_areas); + sfree (db->queries); db->queries_num = 0; @@ -315,8 +335,9 @@ static PGresult *c_psql_exec_query_params (c_psql_database_t *db, params[i] = db->user; break; case C_PSQL_PARAM_INTERVAL: - ssnprintf (interval, sizeof (interval), "%i", - db->interval > 0 ? db->interval : interval_g); + ssnprintf (interval, sizeof (interval), "%.3f", + (db->interval > 0) + ? CDTIME_T_TO_DOUBLE (db->interval) : interval_g); params[i] = interval; break; default: @@ -330,7 +351,8 @@ static PGresult *c_psql_exec_query_params (c_psql_database_t *db, NULL, NULL, /* return text data */ 0); } /* c_psql_exec_query_params */ -static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q) +static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q, + udb_query_preparation_area_t *prep_area) { PGresult *res; @@ -413,8 +435,8 @@ static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q) else host = db->host; - status = udb_query_prepare_result (q, host, "postgresql", - db->database, column_names, (size_t) column_num); + status = udb_query_prepare_result (q, prep_area, host, "postgresql", + db->database, column_names, (size_t) column_num, db->interval); if (0 != status) { log_err ("udb_query_prepare_result failed with status %i.", status); @@ -437,13 +459,15 @@ static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q) if (col < column_num) continue; - status = udb_query_handle_result (q, column_values); + status = udb_query_handle_result (q, prep_area, column_values); if (status != 0) { log_err ("udb_query_handle_result failed with status %i.", status); } } /* for (row = 0; row < rows_num; ++row) */ + udb_query_finish_result (q, prep_area); + BAIL_OUT (0); #undef BAIL_OUT } /* c_psql_exec_query */ @@ -451,6 +475,8 @@ static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q) static int c_psql_read (user_data_t *ud) { c_psql_database_t *db; + + int success = 0; int i; if ((ud == NULL) || (ud->data == NULL)) { @@ -467,16 +493,22 @@ static int c_psql_read (user_data_t *ud) for (i = 0; i < db->queries_num; ++i) { + udb_query_preparation_area_t *prep_area; udb_query_t *q; + prep_area = db->q_prep_areas[i]; q = db->queries[i]; if ((0 != db->server_version) - && (udb_query_check_version (q, db->server_version) <= 0)) - return -1; + && (udb_query_check_version (q, db->server_version) <= 0)) + continue; - c_psql_exec_query (db, q); + if (0 == c_psql_exec_query (db, q, prep_area)) + success = 1; } + + if (! success) + return -1; return 0; } /* c_psql_read */ @@ -491,41 +523,6 @@ static int c_psql_shutdown (void) return 0; } /* c_psql_shutdown */ -static int config_set_s (char *name, char **var, const oconfig_item_t *ci) -{ - if ((0 != ci->children_num) || (1 != ci->values_num) - || (OCONFIG_TYPE_STRING != ci->values[0].type)) { - log_err ("%s expects a single string argument.", name); - return 1; - } - - sfree (*var); - *var = sstrdup (ci->values[0].value.string); - return 0; -} /* config_set_s */ - -static int config_set_i (char *name, int *var, - const oconfig_item_t *ci, int min) -{ - int value; - - if ((0 != ci->children_num) || (1 != ci->values_num) - || (OCONFIG_TYPE_NUMBER != ci->values[0].type)) { - log_err ("%s expects a single number argument.", name); - return 1; - } - - value = (int)ci->values[0].value.number; - - if (value < min) { - log_err ("%s expects a number greater or equal to %i.", name, min); - return 1; - } - - *var = value; - return 0; -} /* config_set_s */ - static int config_query_param_add (udb_query_t *q, oconfig_item_t *ci) { c_psql_user_data_t *data; @@ -587,7 +584,7 @@ static int c_psql_config_database (oconfig_item_t *ci) c_psql_database_t *db; char cb_name[DATA_MAX_NAME_LEN]; - struct timespec cb_interval; + struct timespec cb_interval = { 0, 0 }; user_data_t ud; int i; @@ -601,47 +598,68 @@ static int c_psql_config_database (oconfig_item_t *ci) memset (&ud, 0, sizeof (ud)); db = c_psql_database_new (ci->values[0].value.string); + if (db == NULL) + return -1; for (i = 0; i < ci->children_num; ++i) { oconfig_item_t *c = ci->children + i; if (0 == strcasecmp (c->key, "Host")) - config_set_s ("Host", &db->host, c); + cf_util_get_string (c, &db->host); else if (0 == strcasecmp (c->key, "Port")) - config_set_s ("Port", &db->port, c); + cf_util_get_service (c, &db->port); else if (0 == strcasecmp (c->key, "User")) - config_set_s ("User", &db->user, c); + cf_util_get_string (c, &db->user); else if (0 == strcasecmp (c->key, "Password")) - config_set_s ("Password", &db->password, c); + cf_util_get_string (c, &db->password); else if (0 == strcasecmp (c->key, "SSLMode")) - config_set_s ("SSLMode", &db->sslmode, c); + cf_util_get_string (c, &db->sslmode); else if (0 == strcasecmp (c->key, "KRBSrvName")) - config_set_s ("KRBSrvName", &db->krbsrvname, c); + cf_util_get_string (c, &db->krbsrvname); else if (0 == strcasecmp (c->key, "Service")) - config_set_s ("Service", &db->service, c); + cf_util_get_string (c, &db->service); else if (0 == strcasecmp (c->key, "Query")) udb_query_pick_from_list (c, queries, queries_num, &db->queries, &db->queries_num); else if (0 == strcasecmp (c->key, "Interval")) - config_set_i ("Interval", &db->interval, c, /* min = */ 1); + cf_util_get_cdtime (c, &db->interval); else log_warn ("Ignoring unknown config key \"%s\".", c->key); } /* If no `Query' options were given, add the default queries.. */ - if (db->queries_num == 0) - { + if (db->queries_num == 0) { for (i = 0; i < def_queries_num; i++) udb_query_pick_from_list_by_name (def_queries[i], queries, queries_num, &db->queries, &db->queries_num); } + if (db->queries_num > 0) { + db->q_prep_areas = (udb_query_preparation_area_t **) calloc ( + db->queries_num, sizeof (*db->q_prep_areas)); + + if (db->q_prep_areas == NULL) { + log_err ("Out of memory."); + c_psql_database_delete (db); + return -1; + } + } + for (i = 0; (size_t)i < db->queries_num; ++i) { c_psql_user_data_t *data; data = udb_query_get_user_data (db->queries[i]); if ((data != NULL) && (data->params_num > db->max_params_num)) db->max_params_num = data->params_num; + + db->q_prep_areas[i] + = udb_query_allocate_preparation_area (db->queries[i]); + + if (db->q_prep_areas[i] == NULL) { + log_err ("Out of memory."); + c_psql_database_delete (db); + return -1; + } } ud.data = db; @@ -649,12 +667,11 @@ static int c_psql_config_database (oconfig_item_t *ci) ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->database); - memset (&cb_interval, 0, sizeof (cb_interval)); - if (db->interval > 0) - cb_interval.tv_sec = (time_t)db->interval; + CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval); plugin_register_complex_read ("postgresql", cb_name, c_psql_read, - /* interval = */ &cb_interval, &ud); + /* interval = */ (db->interval > 0) ? &cb_interval : NULL, + &ud); return 0; } /* c_psql_config_database */ @@ -685,8 +702,7 @@ static int c_psql_config (oconfig_item_t *ci) if (0 == strcasecmp (c->key, "Query")) udb_query_create (&queries, &queries_num, c, - /* callback = */ config_query_callback, - /* legacy mode = */ 1); + /* callback = */ config_query_callback); else if (0 == strcasecmp (c->key, "Database")) c_psql_config_database (c); else