* 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 <sh at tokkee.org>
C_PSQL_PARAM_DB,
C_PSQL_PARAM_USER,
C_PSQL_PARAM_INTERVAL,
+ C_PSQL_PARAM_INSTANCE,
} c_psql_param_t;
/* Parameter configuration. Stored as `user data' in the query objects. */
udb_query_t **queries;
size_t queries_num;
- int interval;
+ cdtime_t interval;
char *host;
char *port;
char *user;
char *password;
+ char *instance;
+
char *sslmode;
char *krbsrvname;
db->user = NULL;
db->password = NULL;
+ db->instance = sstrdup (name);
+
db->sslmode = NULL;
db->krbsrvname = NULL;
sfree (db->user);
sfree (db->password);
+ sfree (db->instance);
+
sfree (db->sslmode);
sfree (db->krbsrvname);
if (CONNECTION_OK != PQstatus (db->conn)) {
c_complain (LOG_ERR, &db->conn_complaint,
- "Failed to connect to database %s: %s",
- db->database, PQerrorMessage (db->conn));
+ "Failed to connect to database %s (%s): %s",
+ db->database, db->instance,
+ PQerrorMessage (db->conn));
return -1;
}
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)
+ : plugin_get_interval ());
params[i] = interval;
break;
+ case C_PSQL_PARAM_INSTANCE:
+ params[i] = db->instance;
+ break;
default:
assert (0);
}
else if ((NULL == data) || (0 == data->params_num))
res = c_psql_exec_query_noparams (db, q);
else {
- log_err ("Connection to database \"%s\" does not support parameters "
- "(protocol version %d) - cannot execute query \"%s\".",
- db->database, db->proto_version,
+ log_err ("Connection to database \"%s\" (%s) does not support "
+ "parameters (protocol version %d) - "
+ "cannot execute query \"%s\".",
+ db->database, db->instance, db->proto_version,
udb_query_get_name (q));
return -1;
}
host = db->host;
status = udb_query_prepare_result (q, prep_area, host, "postgresql",
- db->database, column_names, (size_t) column_num, db->interval);
+ db->instance, column_names, (size_t) column_num, db->interval);
if (0 != status) {
log_err ("udb_query_prepare_result failed with status %i.",
status);
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)) {
db = ud->data;
assert (NULL != db->database);
+ assert (NULL != db->instance);
if (0 != c_psql_check_connection (db))
return -1;
&& (udb_query_check_version (q, db->server_version) <= 0))
continue;
- c_psql_exec_query (db, q, prep_area);
+ if (0 == c_psql_exec_query (db, q, prep_area))
+ success = 1;
}
+
+ if (! success)
+ return -1;
return 0;
} /* c_psql_read */
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;
data->params[data->params_num] = C_PSQL_PARAM_USER;
else if (0 == strcasecmp (param_str, "interval"))
data->params[data->params_num] = C_PSQL_PARAM_INTERVAL;
+ else if (0 == strcasecmp (param_str, "instance"))
+ data->params[data->params_num] = C_PSQL_PARAM_INSTANCE;
else {
log_err ("Invalid parameter \"%s\".", param_str);
return 1;
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;
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, "Instance"))
+ cf_util_get_string (c, &db->instance);
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);
}
ud.data = db;
ud.free_func = c_psql_database_delete;
- ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->database);
+ ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance);
- 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 */
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