summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 5f73b72)
raw | patch | inline | side by side (parent: 5f73b72)
author | Sebastian Harl <sh@tokkee.org> | |
Tue, 30 Mar 2010 19:27:55 +0000 (21:27 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Tue, 30 Mar 2010 19:27:55 +0000 (21:27 +0200) |
These objects are used to store the temporary data needed during execution of
a query, which was previously stored in the query object itself. This allows
the query object to be used read-only, making it possible to use it from
multiple threads in parallel.
The dbi, oracle and postgresql plugins have been updated to use that
(mandatory) new feature.
a query, which was previously stored in the query object itself. This allows
the query object to be used read-only, making it possible to use it from
multiple threads in parallel.
The dbi, oracle and postgresql plugins have been updated to use that
(mandatory) new feature.
src/dbi.c | patch | blob | history | |
src/oracle.c | patch | blob | history | |
src/postgresql.c | patch | blob | history | |
src/utils_db_query.c | patch | blob | history | |
src/utils_db_query.h | patch | blob | history |
diff --git a/src/dbi.c b/src/dbi.c
index ce4cd02f551a5cc1f47aca54d1a2c5425764dd11..5dad197cc5f671b3a803bae7ceabdc87c94523cb 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
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,
+ udb_query_prepare_result (q, prep_area, hostname_g,
+ /* plugin = */ "dbi", db->name,
column_names, column_num);
/* 0 = error; 1 = success; */
"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++;
}
diff --git a/src/oracle.c b/src/oracle.c
index 7a8ccc6bf5b7ae3479743a86d945086b086fb9d0..7ab5a0c16b233243e2feb7d572e3211f605a5c77 100644 (file)
--- a/src/oracle.c
+++ b/src/oracle.c
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);
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 */
diff --git a/src/postgresql.c b/src/postgresql.c
index 9e916596e9fc2dc366f23965e35ca516cc326c2b..431f8e3bbfb71b351fcb7ff7089a8d284c4d88e7 100644 (file)
--- a/src/postgresql.c
+++ b/src/postgresql.c
int max_params_num;
/* user configuration */
+ udb_query_preparation_area_t **q_prep_areas;
udb_query_t **queries;
size_t queries_num;
db = (c_psql_database_t *)malloc (sizeof (*db));
if (NULL == db) {
log_err ("Out of memory.");
- exit (5);
+ return NULL;
}
db->conn = NULL;
db->max_params_num = 0;
+ db->q_prep_areas = NULL;
db->queries = NULL;
db->queries_num = 0;
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;
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",
+ status = udb_query_prepare_result (q, prep_area, host, "postgresql",
db->database, column_names, (size_t) column_num);
if (0 != status) {
log_err ("udb_query_prepare_result failed with status %i.",
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 */
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))
continue;
- c_psql_exec_query (db, q);
+ c_psql_exec_query (db, q, prep_area);
}
return 0;
} /* c_psql_read */
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 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;
diff --git a/src/utils_db_query.c b/src/utils_db_query.c
index 5f892a408b0c49f14e4560ad34100bfadfa0f398..13cdf9e57871226f69991c90652d457f895cf5f3 100644 (file)
--- a/src/utils_db_query.c
+++ b/src/utils_db_query.c
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;
+ 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));
+ 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));
+ 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;
}
}
@@ -1029,33 +1057,43 @@ int udb_query_check_version (udb_query_t *q, unsigned int version) /* {{{ */
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);
+ 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);
@@ -1067,19 +1105,21 @@ int udb_query_handle_result (udb_query_t *q, char **column_values) /* {{{ */
{
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++;
}
@@ -1087,34 +1127,37 @@ int udb_query_handle_result (udb_query_t *q, char **column_values) /* {{{ */
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)
{
+ 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);
- q->column_num = column_num;
- q->host = strdup (host);
- q->plugin = strdup (plugin);
- q->db_name = strdup (db_name);
+ prep_area->column_num = column_num;
+ prep_area->host = strdup (host);
+ prep_area->plugin = strdup (plugin);
+ prep_area->db_name = strdup (db_name);
- 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 : */
diff --git a/src/utils_db_query.h b/src/utils_db_query.h
index 6703e924ff14b45aea90e6ab3e1000864233f012..da235f798b1f4ee268485b13983d3591d2bfa708 100644 (file)
--- a/src/utils_db_query.h
+++ b/src/utils_db_query.h
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);
+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 : */