diff --git a/src/dbi.c b/src/dbi.c
index 5be9cae43c1d28cb8b6febbe2161a29e7d8e62ba..80488d8478f6df99c748de2e4e39e872b1236701 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
/**
* collectd - src/dbi.c
- * Copyright (C) 2008,2009 Florian octo Forster
+ * Copyright (C) 2008-2013 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
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
struct cdbi_driver_option_s /* {{{ */
{
char *key;
- char *value;
+ union
+ {
+ char *string;
+ int numeric;
+ } value;
+ _Bool is_numeric;
};
typedef struct cdbi_driver_option_s cdbi_driver_option_t; /* }}} */
char *select_db;
char *driver;
+ char *host;
cdbi_driver_option_t *driver_options;
size_t driver_options_num;
+ udb_query_preparation_area_t **q_prep_areas;
udb_query_t **queries;
size_t queries_num;
else
sstrncpy (buffer, value, buffer_size);
}
+ /* DBI_TYPE_BINARY */
+ /* DBI_TYPE_DATETIME */
else
{
- ERROR ("dbi plugin: cdbi_result_get: Don't know how to handle "
- "source type %hu.", src_type);
+ const char *field_name;
+
+ field_name = dbi_result_get_field_name (res, index);
+ if (field_name == NULL)
+ field_name = "<unknown>";
+
+ ERROR ("dbi plugin: Column `%s': Don't know how to handle "
+ "source type %hu.",
+ field_name, src_type);
return (-1);
}
for (i = 0; i < db->driver_options_num; i++)
{
sfree (db->driver_options[i].key);
- sfree (db->driver_options[i].value);
+ if (!db->driver_options[i].is_numeric)
+ sfree (db->driver_options[i].value.string);
}
sfree (db->driver_options);
+ 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);
} /* }}} void cdbi_database_free */
* </Plugin>
*/
-static int cdbi_config_set_string (char **ret_string, /* {{{ */
- oconfig_item_t *ci)
-{
- char *string;
-
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("dbi plugin: The `%s' config option "
- "needs exactly one string argument.", ci->key);
- return (-1);
- }
-
- string = strdup (ci->values[0].value.string);
- if (string == NULL)
- {
- ERROR ("dbi plugin: strdup failed.");
- return (-1);
- }
-
- if (*ret_string != NULL)
- free (*ret_string);
- *ret_string = string;
-
- return (0);
-} /* }}} int cdbi_config_set_string */
-
static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ */
oconfig_item_t *ci)
{
@@ -212,10 +207,11 @@ static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ *
if ((ci->values_num != 2)
|| (ci->values[0].type != OCONFIG_TYPE_STRING)
- || (ci->values[1].type != OCONFIG_TYPE_STRING))
+ || ((ci->values[1].type != OCONFIG_TYPE_STRING)
+ && (ci->values[1].type != OCONFIG_TYPE_NUMBER)))
{
WARNING ("dbi plugin: The `DriverOption' config option "
- "needs exactly two string arguments.");
+ "needs exactly two arguments.");
return (-1);
}
@@ -229,6 +225,7 @@ static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ *
db->driver_options = option;
option = db->driver_options + db->driver_options_num;
+ memset (option, 0, sizeof (*option));
option->key = strdup (ci->values[0].value.string);
if (option->key == NULL)
@@ -237,12 +234,21 @@ static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ *
return (-1);
}
- option->value = strdup (ci->values[1].value.string);
- if (option->value == NULL)
+ if (ci->values[1].type == OCONFIG_TYPE_STRING)
{
- ERROR ("dbi plugin: strdup failed.");
- sfree (option->key);
- return (-1);
+ option->value.string = strdup (ci->values[1].value.string);
+ if (option->value.string == NULL)
+ {
+ ERROR ("dbi plugin: strdup failed.");
+ sfree (option->key);
+ return (-1);
+ }
+ }
+ else
+ {
+ assert (ci->values[1].type == OCONFIG_TYPE_NUMBER);
+ option->value.numeric = (int) (ci->values[1].value.number + .5);
+ option->is_numeric = 1;
}
db->driver_options_num++;
}
memset (db, 0, sizeof (*db));
- status = cdbi_config_set_string (&db->name, ci);
+ status = cf_util_get_string (ci, &db->name);
if (status != 0)
{
sfree (db);
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Driver", child->key) == 0)
- status = cdbi_config_set_string (&db->driver, child);
+ status = cf_util_get_string (child, &db->driver);
else if (strcasecmp ("DriverOption", child->key) == 0)
status = cdbi_config_add_database_driver_option (db, child);
else if (strcasecmp ("SelectDB", child->key) == 0)
- status = cdbi_config_set_string (&db->select_db, child);
+ status = cf_util_get_string (child, &db->select_db);
else if (strcasecmp ("Query", child->key) == 0)
status = udb_query_pick_from_list (child, queries, queries_num,
&db->queries, &db->queries_num);
+ else if (strcasecmp ("Host", child->key) == 0)
+ status = cf_util_get_string (child, &db->host);
else
{
WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
break;
} /* while (status == 0) */
+ while ((status == 0) && (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)
+ {
+ WARNING ("dbi plugin: malloc failed");
+ status = -1;
+ break;
+ }
+
+ for (i = 0; i < db->queries_num; ++i)
+ {
+ db->q_prep_areas[i]
+ = udb_query_allocate_preparation_area (db->queries[i]);
+
+ if (db->q_prep_areas[i] == NULL)
+ {
+ WARNING ("dbi plugin: udb_query_allocate_preparation_area failed");
+ status = -1;
+ break;
+ }
+ }
+
+ break;
+ }
+
/* If all went well, add this database to the global list of databases. */
if (status == 0)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Query", child->key) == 0)
udb_query_create (&queries, &queries_num, child,
- /* callback = */ NULL, /* legacy mode = */ 0);
+ /* callback = */ NULL);
else if (strcasecmp ("Database", child->key) == 0)
cdbi_config_add_database (child);
else
} /* }}} int cdbi_init */
static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
- udb_query_t *q)
+ udb_query_t *q, udb_query_preparation_area_t *prep_area)
{
const char *statement;
dbi_result res;
sstrncpy (column_names[i], column_name, DATA_MAX_NAME_LEN);
} /* }}} for (i = 0; i < column_num; i++) */
- udb_query_prepare_result (q, hostname_g, /* plugin = */ "dbi", db->name,
- column_names, column_num);
+ udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
+ /* plugin = */ "dbi", db->name,
+ column_names, column_num, /* interval = */ 0);
/* 0 = error; 1 = success; */
status = dbi_result_first_row (res); /* {{{ */
"return any rows?",
db->name, udb_query_get_name (q),
cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
- udb_query_finish_result (q);
+ udb_query_finish_result (q, prep_area);
BAIL_OUT (-1);
} /* }}} */
* to dispatch the row to the daemon. */
if (status == 0) /* {{{ */
{
- status = udb_query_handle_result (q, column_values);
+ status = udb_query_handle_result (q, prep_area, column_values);
if (status != 0)
{
ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
} /* }}} while (42) */
/* Tell the db query interface that we're done with this query. */
- udb_query_finish_result (q);
+ udb_query_finish_result (q, prep_area);
/* Clean up and return `status = 0' (success) */
BAIL_OUT (0);
* trouble finding out how to configure the plugin correctly.. */
for (i = 0; i < db->driver_options_num; i++)
{
- DEBUG ("dbi plugin: cdbi_connect_database (%s): "
- "key = %s; value = %s;",
- db->name,
- db->driver_options[i].key,
- db->driver_options[i].value);
+ if (db->driver_options[i].is_numeric)
+ {
+ status = dbi_conn_set_option_numeric (connection,
+ db->driver_options[i].key, db->driver_options[i].value.numeric);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_connect_database (%s): "
+ "dbi_conn_set_option_numeric (\"%s\", %i) failed: %s.",
+ db->name,
+ db->driver_options[i].key, db->driver_options[i].value.numeric,
+ cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+ }
+ }
+ else
+ {
+ status = dbi_conn_set_option (connection,
+ db->driver_options[i].key, db->driver_options[i].value.string);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_connect_database (%s): "
+ "dbi_conn_set_option (\"%s\", \"%s\") failed: %s.",
+ db->name,
+ db->driver_options[i].key, db->driver_options[i].value.string,
+ cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+ }
+ }
- status = dbi_conn_set_option (connection,
- db->driver_options[i].key, db->driver_options[i].value);
if (status != 0)
{
- char errbuf[1024];
- const char *opt;
-
- ERROR ("dbi plugin: cdbi_connect_database (%s): "
- "dbi_conn_set_option (%s, %s) failed: %s.",
- db->name,
- db->driver_options[i].key, db->driver_options[i].value,
- cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+ char const *opt;
INFO ("dbi plugin: This is a list of all options understood "
"by the `%s' driver:", db->driver);
&& (udb_query_check_version (db->queries[i], db_version) == 0))
continue;
- status = cdbi_read_database_query (db, db->queries[i]);
+ status = cdbi_read_database_query (db,
+ db->queries[i], db->q_prep_areas[i]);
if (status == 0)
success++;
}