enable_plugin="yes"
force="yes"
else
- enable_plugin="no"
+ enable_plugin="no (disabled on command line)"
fi; fi
],
[
(st->host != NULL) ? st->host : hostname_g,
(st->name != NULL) ? st->name : "default"),
- status = plugin_register_complex_read (callback_name,
+ status = plugin_register_complex_read (/* group = */ NULL,
+ /* name = */ callback_name,
/* callback = */ apache_read_host,
/* interval = */ NULL,
/* user_data = */ &ud);
</Database>
<Database bar>
+ Interval 300
Service "service_name"
Query backend # predefined
Query rt36_tickets
=item I<interval>
-The interval collectd is using (as specified by the B<Interval> option).
+The interval with which this database is queried (as specified by the database
+specific or global B<Interval> options).
=back
=over 4
+=item B<Interval> I<seconds>
+
+Specify the interval with which the database should be queried. The default is
+to use the global B<Interval> setting.
+
=item B<Host> I<hostname>
Specify the hostname or IP of the PostgreSQL server to connect to. If the
fprintf (use_stdio == 1 ? stdout : stderr,
"PUTVAL %s interval=%i %s\n",
- filename, interval_g, values);
+ filename, vl->interval, values);
return (0);
}
ssnprintf (cb_name, sizeof (cb_name), "curl_json-%s-%s",
db->instance, db->url);
- plugin_register_complex_read (cb_name, cj_read,
+ plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
/* interval = */ NULL, &ud);
}
else
ssnprintf (cb_name, sizeof (cb_name), "curl_xml-%s-%s",
db->instance, db->url);
- plugin_register_complex_read (cb_name, cx_read,
+ plugin_register_complex_read (/* group = */ NULL, cb_name, cx_read,
/* interval = */ NULL, &ud);
}
else
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;
}
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 */
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)
{
} /* }}} 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, hostname_g,
+ /* plugin = */ "dbi", db->name,
+ column_names, column_num, /* interval = */ -1);
/* 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);
&& (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++;
}
ud.data = (void *) cbi;
ud.free_func = cjni_callback_info_destroy;
- plugin_register_complex_read (cbi->name, cjni_read,
+ plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
/* interval = */ NULL, &ud);
(*jvm_env)->DeleteLocalRef (jvm_env, o_read);
else
sstrncpy (cb_name, "mysql", sizeof (cb_name));
- plugin_register_complex_read (cb_name, mysql_read,
+ plugin_register_complex_read (/* group = */ NULL, cb_name,
+ mysql_read,
/* interval = */ NULL, &ud);
}
else
ud.data = host;
ud.free_func = (void (*) (void *)) free_host_config;
- plugin_register_complex_read (cb_name,
+ plugin_register_complex_read (/* group = */ NULL, cb_name,
/* callback = */ cna_read,
/* interval = */ (host->interval > 0) ? &interval : NULL,
/* user data = */ &ud);
if (ow_interval > 0)
cb_interval.tv_sec = (time_t) ow_interval;
- plugin_register_complex_read ("onewire", cow_read,
+ plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read,
&cb_interval, /* user data = */ NULL);
plugin_register_shutdown ("onewire", cow_shutdown);
char *username;
char *password;
+ udb_query_preparation_area_t **q_prep_areas;
udb_query_t **queries;
size_t queries_num;
static void o_database_free (o_database_t *db) /* {{{ */
{
+ size_t i;
+
if (db == NULL)
return;
sfree (db->password);
sfree (db->queries);
+ if (db->q_prep_areas != NULL)
+ 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 o_database_free */
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 ("oracle 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 ("oracle plugin: udb_query_allocate_preparation_area failed");
+ status = -1;
+ break;
+ }
+ }
+
+ break;
+ }
+
/* If all went well, add this query to the list of queries within the
* database structure. */
if (status == 0)
} /* }}} int o_init */
static int o_read_database_query (o_database_t *db, /* {{{ */
- udb_query_t *q)
+ udb_query_t *q, udb_query_preparation_area_t *prep_area)
{
char **column_names;
char **column_values;
} /* for (j = 1; j <= param_counter; j++) */
/* }}} End of the ``define'' stuff. */
- status = udb_query_prepare_result (q, hostname_g, /* plugin = */ "oracle",
- db->name, column_names, column_num);
+ status = udb_query_prepare_result (q, prep_area, hostname_g,
+ /* plugin = */ "oracle", db->name, column_names, column_num,
+ /* interval = */ -1);
if (status != 0)
{
ERROR ("oracle plugin: o_read_database_query (%s, %s): "
break;
}
- status = udb_query_handle_result (q, column_values);
+ status = udb_query_handle_result (q, prep_area, column_values);
if (status != 0)
{
WARNING ("oracle plugin: o_read_database_query (%s, %s): "
db->connect_id, db->oci_service_context);
for (i = 0; i < db->queries_num; i++)
- o_read_database_query (db, db->queries[i]);
+ o_read_database_query (db, db->queries[i], db->q_prep_areas[i]);
return (0);
} /* }}} int o_read_database */
#define rf_callback rf_super.cf_callback
#define rf_udata rf_super.cf_udata
callback_func_t rf_super;
+ char rf_group[DATA_MAX_NAME_LEN];
char rf_name[DATA_MAX_NAME_LEN];
int rf_type;
struct timespec rf_interval;
rf->rf_callback = (void *) callback;
rf->rf_udata.data = NULL;
rf->rf_udata.free_func = NULL;
+ rf->rf_group[0] = '\0';
sstrncpy (rf->rf_name, name, sizeof (rf->rf_name));
rf->rf_type = RF_SIMPLE;
rf->rf_interval.tv_sec = 0;
return (plugin_insert_read (rf));
} /* int plugin_register_read */
-int plugin_register_complex_read (const char *name,
+int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
const struct timespec *interval,
user_data_t *user_data)
memset (rf, 0, sizeof (read_func_t));
rf->rf_callback = (void *) callback;
+ if (group != NULL)
+ sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
+ else
+ rf->rf_group[0] = '\0';
sstrncpy (rf->rf_name, name, sizeof (rf->rf_name));
rf->rf_type = RF_COMPLEX;
if (interval != NULL)
return (0);
} /* }}} int plugin_unregister_read */
+static int compare_read_func_group (llentry_t *e, void *ud) /* {{{ */
+{
+ read_func_t *rf = e->value;
+ char *group = ud;
+
+ return strcmp (rf->rf_group, (const char *)group);
+} /* }}} int compare_read_func_group */
+
+int plugin_unregister_read_group (const char *group) /* {{{ */
+{
+ llentry_t *le;
+ read_func_t *rf;
+
+ int found = 0;
+
+ if (group == NULL)
+ return (-ENOENT);
+
+ pthread_mutex_lock (&read_lock);
+
+ if (read_list == NULL)
+ {
+ pthread_mutex_unlock (&read_lock);
+ return (-ENOENT);
+ }
+
+ while (42)
+ {
+ le = llist_search_custom (read_list,
+ compare_read_func_group, (void *)group);
+
+ if (le == NULL)
+ break;
+
+ ++found;
+
+ llist_remove (read_list, le);
+
+ rf = le->value;
+ assert (rf != NULL);
+ rf->rf_type = RF_REMOVE;
+
+ llentry_destroy (le);
+
+ DEBUG ("plugin_unregister_read_group: "
+ "Marked `%s' (group `%s') for removal.",
+ rf->rf_name, group);
+ }
+
+ pthread_mutex_unlock (&read_lock);
+
+ if (found == 0)
+ {
+ WARNING ("plugin_unregister_read_group: No such "
+ "group of read function: %s", group);
+ return (-ENOENT);
+ }
+
+ return (0);
+} /* }}} int plugin_unregister_read_group */
+
int plugin_unregister_write (const char *name)
{
return (plugin_unregister (list_write, name));
plugin_init_cb callback);
int plugin_register_read (const char *name,
int (*callback) (void));
-int plugin_register_complex_read (const char *name,
+int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
const struct timespec *interval,
user_data_t *user_data);
int plugin_unregister_complex_config (const char *name);
int plugin_unregister_init (const char *name);
int plugin_unregister_read (const char *name);
+int plugin_unregister_read_group (const char *group);
int plugin_unregister_write (const char *name);
int plugin_unregister_flush (const char *name);
int plugin_unregister_shutdown (const char *name);
* 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>
int max_params_num;
/* user configuration */
+ udb_query_preparation_area_t **q_prep_areas;
udb_query_t **queries;
size_t queries_num;
+ int interval;
+
char *host;
char *port;
char *database;
static udb_query_t **queries = NULL;
static size_t queries_num = 0;
-static c_psql_database_t *databases = NULL;
-static int databases_num = 0;
-
static c_psql_database_t *c_psql_database_new (const char *name)
{
c_psql_database_t *db;
- ++databases_num;
- if (NULL == (databases = (c_psql_database_t *)realloc (databases,
- databases_num * sizeof (*databases)))) {
+ db = (c_psql_database_t *)malloc (sizeof (*db));
+ if (NULL == db) {
log_err ("Out of memory.");
- exit (5);
+ return NULL;
}
- db = databases + (databases_num - 1);
-
db->conn = NULL;
C_COMPLAIN_INIT (&db->conn_complaint);
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;
return db;
} /* c_psql_database_new */
-static void c_psql_database_delete (c_psql_database_t *db)
+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;
return;
} /* c_psql_database_delete */
+static int c_psql_connect (c_psql_database_t *db)
+{
+ char conninfo[4096];
+ char *buf = conninfo;
+ int buf_len = sizeof (conninfo);
+ int status;
+
+ if (! db)
+ return -1;
+
+ status = ssnprintf (buf, buf_len, "dbname = '%s'", db->database);
+ if (0 < status) {
+ buf += status;
+ buf_len -= status;
+ }
+
+ C_PSQL_PAR_APPEND (buf, buf_len, "host", db->host);
+ C_PSQL_PAR_APPEND (buf, buf_len, "port", db->port);
+ C_PSQL_PAR_APPEND (buf, buf_len, "user", db->user);
+ C_PSQL_PAR_APPEND (buf, buf_len, "password", db->password);
+ C_PSQL_PAR_APPEND (buf, buf_len, "sslmode", db->sslmode);
+ C_PSQL_PAR_APPEND (buf, buf_len, "krbsrvname", db->krbsrvname);
+ C_PSQL_PAR_APPEND (buf, buf_len, "service", db->service);
+
+ db->conn = PQconnectdb (conninfo);
+ db->proto_version = PQprotocolVersion (db->conn);
+ return 0;
+} /* c_psql_connect */
+
static int c_psql_check_connection (c_psql_database_t *db)
{
+ _Bool init = 0;
+
+ if (! db->conn) {
+ init = 1;
+
+ /* trigger c_release() */
+ if (0 == db->conn_complaint.interval)
+ db->conn_complaint.interval = 1;
+
+ c_psql_connect (db);
+ }
+
/* "ping" */
PQclear (PQexec (db->conn, "SELECT 42;"));
}
db->proto_version = PQprotocolVersion (db->conn);
- if (3 > db->proto_version)
- log_warn ("Protocol version %d does not support parameters.",
- db->proto_version);
}
db->server_version = PQserverVersion (db->conn);
- c_release (LOG_INFO, &db->conn_complaint,
- "Successfully reconnected to database %s", PQdb (db->conn));
+ if (c_would_release (&db->conn_complaint)) {
+ char *server_host;
+ int server_version;
+
+ server_host = PQhost (db->conn);
+ server_version = PQserverVersion (db->conn);
+
+ c_do_release (LOG_INFO, &db->conn_complaint,
+ "Successfully %sconnected to database %s (user %s) "
+ "at server %s%s%s (server version: %d.%d.%d, "
+ "protocol version: %d, pid: %d)", init ? "" : "re",
+ PQdb (db->conn), PQuser (db->conn),
+ C_PSQL_SOCKET3 (server_host, PQport (db->conn)),
+ C_PSQL_SERVER_VERSION3 (server_version),
+ db->proto_version, PQbackendPID (db->conn));
+
+ if (3 > db->proto_version)
+ log_warn ("Protocol version %d does not support parameters.",
+ db->proto_version);
+ }
return 0;
} /* c_psql_check_connection */
params[i] = db->user;
break;
case C_PSQL_PARAM_INTERVAL:
- ssnprintf (interval, sizeof (interval), "%i", interval_g);
+ ssnprintf (interval, sizeof (interval), "%i",
+ db->interval > 0 ? db->interval : interval_g);
params[i] = interval;
break;
default:
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;
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);
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 */
-static int c_psql_read (void)
+static int c_psql_read (user_data_t *ud)
{
+ c_psql_database_t *db;
+
int success = 0;
int i;
- for (i = 0; i < databases_num; ++i) {
- c_psql_database_t *db = databases + i;
+ if ((ud == NULL) || (ud->data == NULL)) {
+ log_err ("c_psql_read: Invalid user data.");
+ return -1;
+ }
- int j;
+ db = ud->data;
- assert (NULL != db->database);
+ assert (NULL != db->database);
- if (0 != c_psql_check_connection (db))
- continue;
+ if (0 != c_psql_check_connection (db))
+ return -1;
- for (j = 0; j < db->queries_num; ++j)
- {
- udb_query_t *q;
+ for (i = 0; i < db->queries_num; ++i)
+ {
+ udb_query_preparation_area_t *prep_area;
+ udb_query_t *q;
- q = db->queries[j];
+ prep_area = db->q_prep_areas[i];
+ q = db->queries[i];
- if ((0 != db->server_version)
+ if ((0 != db->server_version)
&& (udb_query_check_version (q, db->server_version) <= 0))
- continue;
-
- c_psql_exec_query (db, q);
- }
+ continue;
- ++success;
+ if (0 == c_psql_exec_query (db, q, prep_area))
+ success = 1;
}
if (! success)
static int c_psql_shutdown (void)
{
- int i;
-
- if ((NULL == databases) || (0 == databases_num))
- return 0;
-
- plugin_unregister_read ("postgresql");
- plugin_unregister_shutdown ("postgresql");
-
- for (i = 0; i < databases_num; ++i)
- c_psql_database_delete (databases + i);
-
- sfree (databases);
- databases_num = 0;
+ plugin_unregister_read_group ("postgresql");
udb_query_free (queries, queries_num);
queries = NULL;
return 0;
} /* c_psql_shutdown */
-static int c_psql_init (void)
-{
- int i;
-
- if ((NULL == databases) || (0 == databases_num))
- return 0;
-
- for (i = 0; i < databases_num; ++i) {
- c_psql_database_t *db = databases + i;
-
- char conninfo[4096];
- char *buf = conninfo;
- int buf_len = sizeof (conninfo);
- int status;
-
- char *server_host;
- int server_version;
-
- /* this will happen during reinitialization */
- if (NULL != db->conn) {
- c_psql_check_connection (db);
- continue;
- }
-
- status = ssnprintf (buf, buf_len, "dbname = '%s'", db->database);
- if (0 < status) {
- buf += status;
- buf_len -= status;
- }
-
- C_PSQL_PAR_APPEND (buf, buf_len, "host", db->host);
- C_PSQL_PAR_APPEND (buf, buf_len, "port", db->port);
- C_PSQL_PAR_APPEND (buf, buf_len, "user", db->user);
- C_PSQL_PAR_APPEND (buf, buf_len, "password", db->password);
- C_PSQL_PAR_APPEND (buf, buf_len, "sslmode", db->sslmode);
- C_PSQL_PAR_APPEND (buf, buf_len, "krbsrvname", db->krbsrvname);
- C_PSQL_PAR_APPEND (buf, buf_len, "service", db->service);
-
- db->conn = PQconnectdb (conninfo);
- if (0 != c_psql_check_connection (db))
- continue;
-
- db->proto_version = PQprotocolVersion (db->conn);
-
- server_host = PQhost (db->conn);
- server_version = PQserverVersion (db->conn);
- log_info ("Successfully connected to database %s (user %s) "
- "at server %s%s%s (server version: %d.%d.%d, "
- "protocol version: %d, pid: %d)",
- PQdb (db->conn), PQuser (db->conn),
- C_PSQL_SOCKET3 (server_host, PQport (db->conn)),
- C_PSQL_SERVER_VERSION3 (server_version),
- db->proto_version, PQbackendPID (db->conn));
-
- if (3 > db->proto_version)
- log_warn ("Protocol version %d does not support parameters.",
- db->proto_version);
- }
-
- plugin_register_read ("postgresql", c_psql_read);
- plugin_register_shutdown ("postgresql", c_psql_shutdown);
- return 0;
-} /* c_psql_init */
-
static int config_set_s (char *name, char **var, const oconfig_item_t *ci)
{
if ((0 != ci->children_num) || (1 != ci->values_num)
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;
{
c_psql_database_t *db;
+ char cb_name[DATA_MAX_NAME_LEN];
+ struct timespec cb_interval;
+ user_data_t ud;
+
int i;
if ((1 != ci->values_num)
return 1;
}
+ 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;
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);
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;
+ ud.free_func = c_psql_database_delete;
+
+ 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;
+
+ plugin_register_complex_read ("postgresql", cb_name, c_psql_read,
+ /* interval = */ &cb_interval, &ud);
return 0;
} /* c_psql_config_database */
void module_register (void)
{
plugin_register_complex_config ("postgresql", c_psql_config);
- plugin_register_init ("postgresql", c_psql_init);
+ plugin_register_shutdown ("postgresql", c_psql_shutdown);
} /* module_register */
/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
user_data->data = c;
ts.tv_sec = interval;
ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
- plugin_register_complex_read(buf, cpy_read_callback, &ts, user_data);
+ plugin_register_complex_read(/* group = */ NULL, buf,
+ cpy_read_callback, &ts, user_data);
return cpy_string_to_unicode_or_bytes(buf);
}
user_data.data = router_data;
user_data.free_func = (void *) cr_free_data;
if (status == 0)
- status = plugin_register_complex_read (read_name, cr_read,
- /* interval = */ NULL, &user_data);
+ status = plugin_register_complex_read (/* group = */ NULL, read_name,
+ cr_read, /* interval = */ NULL, &user_data);
if (status != 0)
cr_free_data (router_data);
if (hd->interval != 0)
cb_interval.tv_sec = (time_t) hd->interval;
- status = plugin_register_complex_read (cb_name, csnmp_read_host,
- /* interval = */ &cb_interval, /* user_data = */ &cb_data);
+ status = plugin_register_complex_read (/* group = */ NULL, cb_name,
+ csnmp_read_host, /* interval = */ &cb_interval,
+ /* user_data = */ &cb_data);
if (status != 0)
{
ERROR ("snmp plugin: Registering complex read function failed.");
static int ts_destroy (void **user_data) /* {{{ */
{
+ ts_data_t **data;
+
if (user_data == NULL)
return (-EINVAL);
- free (*user_data);
- *user_data = NULL;
+ data = (ts_data_t **) user_data;
+
+ free (*data);
+ *data = NULL;
return (0);
} /* }}} int ts_destroy */
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;
-
/* Legacy data */
int legacy_mode;
size_t legacy_position;
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;
+ int interval;
+
+ udb_result_preparation_area_t *result_prep_areas;
}; /* }}} */
/*
/*
* Legacy result private functions
*/
-static void udb_legacy_result_finish_result (udb_result_t *r) /* {{{ */
+static void udb_legacy_result_finish_result (const udb_result_t const *r, /* {{{ */
+ udb_result_preparation_area_t *prep_area)
{
- if (r == NULL)
+ if ((r == NULL) || (prep_area))
return;
assert (r->legacy_mode == 1);
- r->ds = NULL;
+ prep_area->ds = NULL;
} /* }}} void udb_legacy_result_finish_result */
static int udb_legacy_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,
+ const udb_query_t const *q, char **column_values)
{
value_list_t vl = VALUE_LIST_INIT;
value_t value;
char *value_str;
assert (r->legacy_mode == 1);
- assert (r->ds != NULL);
- assert (r->ds->ds_num == 1);
+ assert (r_area->ds != NULL);
+ assert (r_area->ds->ds_num == 1);
vl.values = &value;
vl.values_len = 1;
value_str = column_values[r->legacy_position];
- if (0 != parse_value (value_str, &vl.values[0], r->ds->ds[0].type))
+ if (0 != parse_value (value_str, &vl.values[0], r_area->ds->ds[0].type))
{
ERROR ("db query utils: udb_legacy_result_handle_result: "
"Parsing `%s' as %s failed.", value_str,
- DS_TYPE_TO_STRING (r->ds->ds[0].type));
+ DS_TYPE_TO_STRING (r_area->ds->ds[0].type));
errno = EINVAL;
return (-1);
}
- 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.type_instance));
sstrncpy (vl.type, r->type, sizeof (vl.type));
if (r->instance_prefix != NULL)
return (0);
} /* }}} int udb_legacy_result_handle_result */
-static int udb_legacy_result_prepare_result (udb_result_t *r, /* {{{ */
+static int udb_legacy_result_prepare_result (const udb_result_t const *r, /* {{{ */
+ udb_result_preparation_area_t *prep_area,
char **column_names, size_t column_num)
{
if (r == NULL)
assert (r->legacy_mode == 1);
/* Make sure previous preparations are cleaned up. */
- udb_legacy_result_finish_result (r);
+ udb_legacy_result_finish_result (r, prep_area);
if (r->legacy_position >= column_num)
{
}
/* 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.",
return (-1);
}
- if (r->ds->ds_num != 1)
+ if (prep_area->ds->ds_num != 1)
{
ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
"requires exactly %i values, but the legacy configuration "
"requires exactly one!",
r->type,
- r->ds->ds_num);
+ prep_area->ds->ds_num);
return (-1);
}
/* }}} */
/*
* Result private functions
*/
-static int 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,
+ const udb_query_t const *q, udb_query_preparation_area_t *q_area)
{
value_list_t vl = VALUE_LIST_INIT;
size_t i;
assert (r != NULL);
assert (r->legacy_mode == 0);
- assert (r->ds != NULL);
- assert (((size_t) r->ds->ds_num) == r->values_num);
+ 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 (-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 *value_str = r->values_buffer[i];
+ char *value_str = r_area->values_buffer[i];
- if (0 != parse_value (value_str, &vl.values[i], r->ds->ds[i].type))
+ if (0 != parse_value (value_str, &vl.values[i], r_area->ds->ds[i].type))
{
ERROR ("db query utils: udb_result_submit: Parsing `%s' as %s failed.",
- value_str, DS_TYPE_TO_STRING (r->ds->ds[i].type));
+ value_str, DS_TYPE_TO_STRING (r_area->ds->ds[i].type));
errno = EINVAL;
return (-1);
}
}
- 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.type_instance));
sstrncpy (vl.type, r->type, sizeof (vl.type));
/* Set vl.type_instance {{{ */
if (r->instance_prefix == NULL)
{
strjoin (vl.type_instance, sizeof (vl.type_instance),
- r->instances_buffer, r->instances_num, "-");
+ r_area->instances_buffer, r->instances_num, "-");
}
else
{
char tmp[DATA_MAX_NAME_LEN];
- strjoin (tmp, sizeof (tmp), r->instances_buffer, r->instances_num, "-");
+ 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",
return (0);
} /* }}} void udb_result_submit */
-static void udb_result_finish_result (udb_result_t *r) /* {{{ */
+static void udb_result_finish_result (const udb_result_t const *r, /* {{{ */
+ udb_result_preparation_area_t *prep_area)
{
- if (r == NULL)
+ if ((r == NULL) || (prep_area == NULL))
return;
if (r->legacy_mode == 1)
{
- udb_legacy_result_finish_result (r);
+ udb_legacy_result_finish_result (r, prep_area);
return;
}
assert (r->legacy_mode == 0);
- 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,
+ const udb_query_t const *q, char **column_values)
{
size_t i;
+ assert (r && q_area && r_area);
+
if (r->legacy_mode == 1)
- return (udb_legacy_result_handle_result (r, q, column_values));
+ return (udb_legacy_result_handle_result (r, q_area, r_area,
+ q, column_values));
assert (r->legacy_mode == 0);
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]];
+ r_area->values_buffer[i] = column_values[r_area->values_pos[i]];
- return udb_result_submit (r, q);
+ 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 (const 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);
if (r->legacy_mode == 1)
- return (udb_legacy_result_prepare_result (r, column_names, column_num));
+ return (udb_legacy_result_prepare_result (r, prep_area,
+ column_names, column_num));
assert (r->legacy_mode == 0);
#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.",
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);
}
* r->values_buffer {{{ */
if (r->instances_num > 0)
{
- r->instances_pos = (size_t *) calloc (r->instances_num, sizeof (size_t));
- if (r->instances_pos == NULL)
+ 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->instances_buffer = (char **) calloc (r->instances_num, sizeof (char *));
- if (r->instances_buffer == NULL)
+ 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->values_pos = (size_t *) calloc (r->values_num, sizeof (size_t));
- if (r->values_pos == 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);
{
if (strcasecmp (r->instances[i], column_names[j]) == 0)
{
- r->instances_pos[i] = j;
+ prep_area->instances_pos[i] = j;
break;
}
}
{
if (strcasecmp (r->values[i], column_names[j]) == 0)
{
- r->values_pos[i] = j;
+ prep_area->values_pos[i] = j;
break;
}
}
return (1);
} /* }}} int udb_query_check_version */
-void udb_query_finish_result (udb_query_t *q) /* {{{ */
+void udb_query_finish_result (const 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 = -1;
+
+ 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 (const 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);
{
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++;
}
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 (const 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, int 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);
}
} 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);
}
}
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 : */
struct udb_query_s;
typedef struct udb_query_s udb_query_t;
+struct udb_query_preparation_area_s;
+typedef struct udb_query_preparation_area_s udb_query_preparation_area_t;
+
typedef int (*udb_query_create_callback_t) (udb_query_t *q,
oconfig_item_t *ci);
*/
int udb_query_check_version (udb_query_t *q, unsigned int version);
-int udb_query_prepare_result (udb_query_t *q,
+int udb_query_prepare_result (const 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);
-int udb_query_handle_result (udb_query_t *q, char **column_values);
-void udb_query_finish_result (udb_query_t *q);
+ char **column_names, size_t column_num, int interval);
+int udb_query_handle_result (const udb_query_t const *q,
+ udb_query_preparation_area_t *prep_area, char **column_values);
+void udb_query_finish_result (const udb_query_t const *q,
+ udb_query_preparation_area_t *prep_area);
+
+udb_query_preparation_area_t *
+udb_query_allocate_preparation_area (udb_query_t *q);
+void
+udb_query_delete_preparation_area (udb_query_preparation_area_t *q_area);
#endif /* UTILS_DB_QUERY_H */
/* vim: set sw=2 sts=2 et : */
return (l ? l->size : 0);
}
+static int llist_strcmp (llentry_t *e, void *ud)
+{
+ if ((e == NULL) || (ud == NULL))
+ return (-1);
+ return (strcmp (e->key, (const char *)ud));
+}
+
llentry_t *llist_search (llist_t *l, const char *key)
{
+ return (llist_search_custom (l, llist_strcmp, (void *)key));
+}
+
+llentry_t *llist_search_custom (llist_t *l,
+ int (*compare) (llentry_t *, void *), void *user_data)
+{
llentry_t *e;
if (l == NULL)
return (NULL);
- for (e = l->head; e != NULL; e = e->next)
- if (strcmp (key, e->key) == 0)
+ e = l->head;
+ while (e != NULL) {
+ llentry_t *next = e->next;
+
+ if (compare (e, user_data) == 0)
break;
+ e = next;
+ }
+
return (e);
}
int llist_size (llist_t *l);
llentry_t *llist_search (llist_t *l, const char *key);
+llentry_t *llist_search_custom (llist_t *l,
+ int (*compare) (llentry_t *, void *), void *user_data);
llentry_t *llist_head (llist_t *l);
llentry_t *llist_tail (llist_t *l);