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;
}
}
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);
{
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)
{
+ 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 : */