X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fpostgresql.c;h=a8812e2158327bf86153689894e8eada7e620022;hb=59c7ee1cafaf53814838794908dd84f8101334c7;hp=4f140b6062a8c9043a7462abee4dd775e9e14392;hpb=0175b4a333bc426133dac1bfa8cf14d352a495ed;p=collectd.git diff --git a/src/postgresql.c b/src/postgresql.c index 4f140b60..a8812e21 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,9 +113,12 @@ typedef struct { int max_params_num; /* user configuration */ + udb_query_preparation_area_t **q_prep_areas; udb_query_t **queries; size_t queries_num; + cdtime_t interval; + char *host; char *port; char *database; @@ -139,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; @@ -151,9 +165,12 @@ 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; + db->interval = 0; + db->database = sstrdup (name); db->host = NULL; db->port = NULL; @@ -170,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; @@ -311,7 +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", interval_g); + ssnprintf (interval, sizeof (interval), "%.3f", + (db->interval > 0) + ? CDTIME_T_TO_DOUBLE (db->interval) : interval_g); params[i] = interval; break; default: @@ -325,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; @@ -408,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); @@ -432,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 */ @@ -446,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)) { @@ -462,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 */ @@ -560,6 +597,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 = { 0, 0 }; user_data_t ud; int i; @@ -573,6 +611,8 @@ 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; @@ -594,24 +634,45 @@ static int c_psql_config_database (oconfig_item_t *ci) 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")) + 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; @@ -619,8 +680,11 @@ static int c_psql_config_database (oconfig_item_t *ci) ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->database); + CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval); + plugin_register_complex_read ("postgresql", cb_name, c_psql_read, - /* interval = */ NULL, &ud); + /* interval = */ (db->interval > 0) ? &cb_interval : NULL, + &ud); return 0; } /* c_psql_config_database */ @@ -651,8 +715,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