3 * Copyright (C) 2008,2009 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Florian octo Forster <octo at verplant.org>
25 #include "configfile.h"
32 struct cdbi_driver_option_s
37 typedef struct cdbi_driver_option_s cdbi_driver_option_t;
40 typedef struct cdbi_result_s cdbi_result_t;
57 cdbi_result_t *results;
59 typedef struct cdbi_query_s cdbi_query_t;
61 struct cdbi_database_s
67 cdbi_driver_option_t *driver_options;
68 size_t driver_options_num;
70 cdbi_query_t **queries;
75 typedef struct cdbi_database_s cdbi_database_t;
80 static cdbi_query_t **queries = NULL;
81 static size_t queries_num = 0;
82 static cdbi_database_t **databases = NULL;
83 static size_t databases_num = 0;
88 static const char *cdbi_strerror (dbi_conn conn, /* {{{ */
89 char *buffer, size_t buffer_size)
96 sstrncpy (buffer, "connection is NULL", buffer_size);
101 status = dbi_conn_error (conn, &msg);
102 if ((status >= 0) && (msg != NULL))
103 ssnprintf (buffer, buffer_size, "%s (status %i)", msg, status);
105 ssnprintf (buffer, buffer_size, "dbi_conn_error failed with status %i",
109 } /* }}} const char *cdbi_conn_error */
111 static int cdbi_result_get_field (dbi_result res, /* {{{ */
112 const char *name, int dst_type, value_t *ret_value)
116 unsigned short src_type;
119 index = dbi_result_get_field_idx (res, name);
122 ERROR ("dbi plugin: cdbi_result_get: No such column: %s.", name);
126 src_type = dbi_result_get_field_type_idx (res, index);
127 if (src_type == DBI_TYPE_ERROR)
129 ERROR ("dbi plugin: cdbi_result_get: "
130 "dbi_result_get_field_type_idx failed.");
134 if ((dst_type != DS_TYPE_COUNTER) && (dst_type != DS_TYPE_GAUGE))
136 ERROR ("dbi plugin: cdbi_result_get: Don't know how to handle "
137 "destination type %i.", dst_type);
141 if (src_type == DBI_TYPE_INTEGER)
143 if (dst_type == DS_TYPE_COUNTER)
144 value.counter = dbi_result_get_ulonglong_idx (res, index);
146 value.gauge = (gauge_t) dbi_result_get_longlong_idx (res, index);
148 else if (src_type == DBI_TYPE_DECIMAL)
150 value.gauge = dbi_result_get_double_idx (res, index);
151 if (dst_type == DS_TYPE_COUNTER)
152 value.counter = (counter_t) round (value.gauge);
154 else if (src_type == DBI_TYPE_STRING)
156 const char *string = dbi_result_get_string_idx (res, index);
161 else if (dst_type == DS_TYPE_COUNTER)
162 value.counter = (counter_t) strtoll (string, &endptr, 0);
164 value.gauge = (gauge_t) strtod (string, &endptr);
166 if (string == endptr)
168 ERROR ("dbi plugin: cdbi_result_get: Can't parse string as number: %s.",
175 ERROR ("dbi plugin: cdbi_result_get: Don't know how to handle "
176 "source type %hu.", src_type);
180 connection = dbi_result_get_conn (res);
181 if (dbi_conn_error (connection, NULL) != 0)
184 ERROR ("dbi plugin: cdbi_result_get: dbi_result_get_*_idx failed: %s.",
185 cdbi_strerror (connection, errbuf, sizeof (errbuf)));
191 } /* }}} int cdbi_result_get_field */
193 static void cdbi_result_free (cdbi_result_t *r) /* {{{ */
202 for (i = 0; i < r->instances_num; i++)
203 sfree (r->instances[i]);
204 sfree (r->instances);
206 for (i = 0; i < r->values_num; i++)
207 sfree (r->values[i]);
210 cdbi_result_free (r->next);
213 } /* }}} void cdbi_result_free */
215 static void cdbi_query_free (cdbi_query_t *q) /* {{{ */
221 sfree (q->statement);
223 cdbi_result_free (q->results);
226 } /* }}} void cdbi_query_free */
228 static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
238 for (i = 0; i < db->driver_options_num; i++)
240 sfree (db->driver_options[i].key);
241 sfree (db->driver_options[i].value);
243 sfree (db->driver_options);
246 } /* }}} void cdbi_database_free */
248 static void cdbi_submit (cdbi_database_t *db, cdbi_result_t *r, /* {{{ */
249 char **instances, value_t *values)
251 value_list_t vl = VALUE_LIST_INIT;
254 vl.values_len = (int) r->values_num;
255 vl.time = time (NULL);
256 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
257 sstrncpy (vl.plugin, "dbi", sizeof (vl.plugin));
258 sstrncpy (vl.plugin_instance, db->name, sizeof (vl.type_instance));
259 sstrncpy (vl.type, r->type, sizeof (vl.type));
260 strjoin (vl.type_instance, sizeof (vl.type_instance),
261 instances, r->instances_num, "-");
262 vl.type_instance[sizeof (vl.type_instance) - 1] = 0;
264 plugin_dispatch_values (&vl);
265 } /* }}} void cdbi_submit */
267 /* Configuration handling functions {{{
270 * <Query "plugin_instance0">
271 * Statement "SELECT name, value FROM table"
274 * InstancesFrom "name"
280 * <Database "plugin_instance1">
282 * DriverOption "hostname" "localhost"
284 * Query "plugin_instance0"
289 static int cdbi_config_set_string (char **ret_string, /* {{{ */
294 if ((ci->values_num != 1)
295 || (ci->values[0].type != OCONFIG_TYPE_STRING))
297 WARNING ("dbi plugin: The `%s' config option "
298 "needs exactly one string argument.", ci->key);
302 string = strdup (ci->values[0].value.string);
305 ERROR ("dbi plugin: strdup failed.");
309 if (*ret_string != NULL)
311 *ret_string = string;
314 } /* }}} int cdbi_config_set_string */
316 static int cdbi_config_add_string (char ***ret_array, /* {{{ */
317 size_t *ret_array_len, oconfig_item_t *ci)
323 if (ci->values_num < 1)
325 WARNING ("dbi plugin: The `%s' config option "
326 "needs at least one argument.", ci->key);
330 for (i = 0; i < ci->values_num; i++)
332 if (ci->values[i].type != OCONFIG_TYPE_STRING)
334 WARNING ("dbi plugin: Argument %i to the `%s' option "
335 "is not a string.", i + 1, ci->key);
340 array_len = *ret_array_len;
341 array = (char **) realloc (*ret_array,
342 sizeof (char *) * (array_len + ci->values_num));
345 ERROR ("dbi plugin: realloc failed.");
350 for (i = 0; i < ci->values_num; i++)
352 array[array_len] = strdup (ci->values[i].value.string);
353 if (array[array_len] == NULL)
355 ERROR ("dbi plugin: strdup failed.");
356 *ret_array_len = array_len;
362 *ret_array_len = array_len;
364 } /* }}} int cdbi_config_add_string */
366 static int cdbi_config_add_query_result (cdbi_query_t *q, /* {{{ */
373 if (ci->values_num != 0)
375 WARNING ("dbi plugin: The `Result' block doesn't accept any arguments. "
376 "Ignoring %i argument%s.",
377 ci->values_num, (ci->values_num == 1) ? "" : "s");
380 r = (cdbi_result_t *) malloc (sizeof (*r));
383 ERROR ("dbi plugin: malloc failed.");
386 memset (r, 0, sizeof (*r));
392 /* Fill the `cdbi_result_t' structure.. */
393 for (i = 0; i < ci->children_num; i++)
395 oconfig_item_t *child = ci->children + i;
397 if (strcasecmp ("Type", child->key) == 0)
398 status = cdbi_config_set_string (&r->type, child);
399 else if (strcasecmp ("InstancesFrom", child->key) == 0)
400 status = cdbi_config_add_string (&r->instances, &r->instances_num, child);
401 else if (strcasecmp ("ValuesFrom", child->key) == 0)
402 status = cdbi_config_add_string (&r->values, &r->values_num, child);
405 WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
413 /* Check that all necessary options have been given. */
418 WARNING ("dbi plugin: `Type' not given for "
419 "result in query `%s'", q->name);
422 if (r->instances == NULL)
424 WARNING ("dbi plugin: `InstancesFrom' not given for "
425 "result in query `%s'", q->name);
428 if (r->values == NULL)
430 WARNING ("dbi plugin: `ValuesFrom' not given for "
431 "result in query `%s'", q->name);
436 } /* while (status == 0) */
438 /* If all went well, add this result to the list of results within the
439 * query structure. */
442 if (q->results == NULL)
451 while (last->next != NULL)
460 cdbi_result_free (r);
465 } /* }}} int cdbi_config_add_query_result */
467 static int cdbi_config_add_query (oconfig_item_t *ci) /* {{{ */
473 if ((ci->values_num != 1)
474 || (ci->values[0].type != OCONFIG_TYPE_STRING))
476 WARNING ("dbi plugin: The `Query' block "
477 "needs exactly one string argument.");
481 q = (cdbi_query_t *) malloc (sizeof (*q));
484 ERROR ("dbi plugin: malloc failed.");
487 memset (q, 0, sizeof (*q));
489 status = cdbi_config_set_string (&q->name, ci);
496 /* Fill the `cdbi_query_t' structure.. */
497 for (i = 0; i < ci->children_num; i++)
499 oconfig_item_t *child = ci->children + i;
501 if (strcasecmp ("Statement", child->key) == 0)
502 status = cdbi_config_set_string (&q->statement, child);
503 else if (strcasecmp ("Result", child->key) == 0)
504 status = cdbi_config_add_query_result (q, child);
507 WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
515 /* Check that all necessary options have been given. */
518 if (q->statement == NULL)
520 WARNING ("dbi plugin: `Statement' not given for query `%s'", q->name);
523 if (q->results == NULL)
525 WARNING ("dbi plugin: No (valid) `Result' block given for query `%s'",
531 } /* while (status == 0) */
533 /* If all went well, add this query to the list of queries within the
534 * database structure. */
539 temp = (cdbi_query_t **) realloc (queries,
540 sizeof (*queries) * (queries_num + 1));
543 ERROR ("dbi plugin: realloc failed");
549 queries[queries_num] = q;
561 } /* }}} int cdbi_config_add_query */
563 static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ */
566 cdbi_driver_option_t *option;
568 if ((ci->values_num != 2)
569 || (ci->values[0].type != OCONFIG_TYPE_STRING)
570 || (ci->values[1].type != OCONFIG_TYPE_STRING))
572 WARNING ("dbi plugin: The `DriverOption' config option "
573 "needs exactly two string arguments.");
577 option = (cdbi_driver_option_t *) realloc (db->driver_options,
578 sizeof (*option) * (db->driver_options_num + 1));
581 ERROR ("dbi plugin: realloc failed");
585 db->driver_options = option;
586 option = db->driver_options + db->driver_options_num;
588 option->key = strdup (ci->values[0].value.string);
589 if (option->key == NULL)
591 ERROR ("dbi plugin: strdup failed.");
595 option->value = strdup (ci->values[1].value.string);
596 if (option->value == NULL)
598 ERROR ("dbi plugin: strdup failed.");
603 db->driver_options_num++;
605 } /* }}} int cdbi_config_add_database_driver_option */
607 static int cdbi_config_add_database_query (cdbi_database_t *db, /* {{{ */
614 if ((ci->values_num != 1)
615 || (ci->values[0].type != OCONFIG_TYPE_STRING))
617 WARNING ("dbi plugin: The `Query' config option "
618 "needs exactly one string argument.");
623 for (i = 0; i < queries_num; i++)
625 if (strcasecmp (queries[i]->name, ci->values[0].value.string) == 0)
634 WARNING ("dbi plugin: Database `%s': Unknown query `%s'. "
635 "Please make sure that the <Query \"%s\"> block comes before "
636 "the <Database \"%s\"> block.",
637 db->name, ci->values[0].value.string,
638 ci->values[0].value.string, db->name);
642 temp = (cdbi_query_t **) realloc (db->queries,
643 sizeof (*db->queries) * (db->queries_num + 1));
646 ERROR ("dbi plugin: realloc failed");
652 db->queries[db->queries_num] = q;
657 } /* }}} int cdbi_config_add_database_query */
659 static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
665 if ((ci->values_num != 1)
666 || (ci->values[0].type != OCONFIG_TYPE_STRING))
668 WARNING ("dbi plugin: The `Database' block "
669 "needs exactly one string argument.");
673 db = (cdbi_database_t *) malloc (sizeof (*db));
676 ERROR ("dbi plugin: malloc failed.");
679 memset (db, 0, sizeof (*db));
681 status = cdbi_config_set_string (&db->name, ci);
688 /* Fill the `cdbi_database_t' structure.. */
689 for (i = 0; i < ci->children_num; i++)
691 oconfig_item_t *child = ci->children + i;
693 if (strcasecmp ("Driver", child->key) == 0)
694 status = cdbi_config_set_string (&db->driver, child);
695 else if (strcasecmp ("DriverOption", child->key) == 0)
696 status = cdbi_config_add_database_driver_option (db, child);
697 else if (strcasecmp ("SelectDB", child->key) == 0)
698 status = cdbi_config_set_string (&db->select_db, child);
699 else if (strcasecmp ("Query", child->key) == 0)
700 status = cdbi_config_add_database_query (db, child);
703 WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
711 /* Check that all necessary options have been given. */
714 if (db->driver == NULL)
716 WARNING ("dbi plugin: `Driver' not given for database `%s'", db->name);
719 if (db->driver_options_num == 0)
721 WARNING ("dbi plugin: No `DriverOption' given for database `%s'. "
722 "This will likely not work.", db->name);
726 } /* while (status == 0) */
728 /* If all went well, add this database to the global list of databases. */
731 cdbi_database_t **temp;
733 temp = (cdbi_database_t **) realloc (databases,
734 sizeof (*databases) * (databases_num + 1));
737 ERROR ("dbi plugin: realloc failed");
743 databases[databases_num] = db;
750 cdbi_database_free (db);
755 } /* }}} int cdbi_config_add_database */
757 static int cdbi_config (oconfig_item_t *ci) /* {{{ */
761 for (i = 0; i < ci->children_num; i++)
763 oconfig_item_t *child = ci->children + i;
764 if (strcasecmp ("Query", child->key) == 0)
765 cdbi_config_add_query (child);
766 else if (strcasecmp ("Database", child->key) == 0)
767 cdbi_config_add_database (child);
770 WARNING ("snmp plugin: Ignoring unknown config option `%s'.", child->key);
772 } /* for (ci->children) */
775 } /* }}} int cdbi_config */
777 /* }}} End of configuration handling functions */
779 static int cdbi_init (void) /* {{{ */
781 static int did_init = 0;
787 if (queries_num == 0)
789 ERROR ("dbi plugin: No <Query> blocks have been found. Without them, "
790 "this plugin can't do anything useful, so we will returns an error.");
794 if (databases_num == 0)
796 ERROR ("dbi plugin: No <Database> blocks have been found. Without them, "
797 "this plugin can't do anything useful, so we will returns an error.");
801 status = dbi_initialize (NULL);
804 ERROR ("dbi plugin: cdbi_init: dbi_initialize failed with status %i.",
808 else if (status == 0)
810 ERROR ("dbi plugin: `dbi_initialize' could not load any drivers. Please "
811 "install at least one `DBD' or check your installation.");
814 DEBUG ("dbi plugin: cdbi_init: dbi_initialize reports %i driver%s.",
815 status, (status == 1) ? "" : "s");
818 } /* }}} int cdbi_init */
820 static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
826 /* Macro that cleans up dynamically allocated memory and returns the
827 * specified status. */
828 #define BAIL_OUT(status) \
829 if (res != NULL) { dbi_result_free (res); res = NULL; } \
832 res = dbi_conn_query (db->connection, q->statement);
836 ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
837 "dbi_conn_query failed: %s",
839 cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
843 /* 0 = error; 1 = success; */
844 status = dbi_result_first_row (res);
848 ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
849 "dbi_result_first_row failed: %s. Maybe the statement didn't "
852 cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
856 /* Iterate over all rows and use every result with each row. */
861 /* Iterate over all results, get the appropriate data_set, allocate memory
862 * for the instance(s) and value(s), copy the values and finally call
863 * `cdbi_submit' to create and dispatch a value_list. */
864 for (r = q->results; r != NULL; r = r->next) /* {{{ */
866 const data_set_t *ds;
874 /* Macro to clean up dynamically allocated memory and continue with the
875 * next iteration of the containing loop, i. e. the `for' loop iterating
876 * over all `Result' sets. */
877 #define BAIL_OUT_CONTINUE \
878 if (instances != NULL) { sfree (instances[0]); sfree (instances); } \
882 /* Read `ds' and check number of values {{{ */
883 ds = plugin_get_ds (r->type);
886 ERROR ("dbi plugin: cdbi_read_database_query: Query `%s': Type `%s' is not "
887 "known by the daemon. See types.db(5) for details.",
892 if (((size_t) ds->ds_num) != r->values_num)
894 ERROR ("dbi plugin: cdbi_read_database_query: Query `%s': The type `%s' "
895 "requires exactly %i value%s, but the configuration specifies %zu.",
897 ds->ds_num, (ds->ds_num == 1) ? "" : "s",
903 /* Allocate `instances' and `values' {{{ */
904 instances = (char **) malloc (sizeof (*instances) * r->instances_num);
905 if (instances == NULL)
907 ERROR ("dbi plugin: malloc failed.");
911 instances[0] = (char *) malloc (r->instances_num * DATA_MAX_NAME_LEN);
912 if (instances[0] == NULL)
914 ERROR ("dbi plugin: malloc failed.");
917 for (i = 1; i < r->instances_num; i++)
918 instances[i] = instances[i - 1] + DATA_MAX_NAME_LEN;
920 values = (value_t *) malloc (sizeof (*values) * r->values_num);
923 ERROR ("dbi plugin: malloc failed.");
928 /* Get instance names and values from the result: */
929 for (i = 0; i < r->instances_num; i++) /* {{{ */
933 inst = dbi_result_get_string (res, r->instances[i]);
934 if (dbi_conn_error (db->connection, NULL) != 0)
937 ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
938 "dbi_result_get_string (%s) failed: %s",
939 db->name, q->name, r->instances[i],
940 cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
944 sstrncpy (instances[i], (inst == NULL) ? "" : inst, DATA_MAX_NAME_LEN);
945 DEBUG ("dbi plugin: cdbi_read_database_query (%s, %s): "
946 "instances[%zu] = %s;",
947 db->name, q->name, i, instances[i]);
948 } /* }}} for (i = 0; i < q->instances_num; i++) */
950 for (i = 0; i < r->values_num; i++) /* {{{ */
952 status = cdbi_result_get_field (res, r->values[i], ds->ds[i].type,
959 if (ds->ds[i].type == DS_TYPE_COUNTER)
961 DEBUG ("dbi plugin: cdbi_read_database_query (%s, %s): values[%zu] = %llu;",
962 db->name, q->name, i, values[i].counter);
966 DEBUG ("dbi plugin: cdbi_read_database_query (%s, %s): values[%zu] = %g;",
967 db->name, q->name, i, values[i].gauge);
969 } /* }}} for (i = 0; i < q->values_num; i++) */
971 /* Dispatch this row to the daemon. */
972 cdbi_submit (db, r, instances, values);
975 #undef BAIL_OUT_CONTINUE
976 } /* }}} for (r = q->results; r != NULL; r = r->next) */
978 /* Get the next row from the database. */
979 status = dbi_result_next_row (res);
982 if (dbi_conn_error (db->connection, NULL) != 0)
985 WARNING ("dbi plugin: cdbi_read_database_query (%s, %s): "
986 "dbi_result_next_row failed: %s.",
988 cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
992 } /* }}} while (42) */
994 /* Clean up and return `status = 0' (success) */
997 } /* }}} int cdbi_read_database_query */
999 static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
1002 dbi_conn connection;
1006 if (db->connection != NULL)
1008 status = dbi_conn_ping (db->connection);
1009 if (status != 0) /* connection is alive */
1012 dbi_conn_close (db->connection);
1013 db->connection = NULL;
1016 driver = dbi_driver_open (db->driver);
1019 ERROR ("dbi plugin: cdbi_connect_database: dbi_driver_open (%s) failed.",
1021 INFO ("dbi plugin: Maybe the driver isn't installed? "
1022 "Known drivers are:");
1023 for (driver = dbi_driver_list (NULL);
1025 driver = dbi_driver_list (driver))
1027 INFO ("dbi plugin: * %s", dbi_driver_get_name (driver));
1032 connection = dbi_conn_open (driver);
1033 if (connection == NULL)
1035 ERROR ("dbi plugin: cdbi_connect_database: dbi_conn_open (%s) failed.",
1040 /* Set all the driver options. Because this is a very very very generic
1041 * interface, the error handling is kind of long. If an invalid option is
1042 * encountered, it will get a list of options understood by the driver and
1043 * report that as `INFO'. This way, users hopefully don't have too much
1044 * trouble finding out how to configure the plugin correctly.. */
1045 for (i = 0; i < db->driver_options_num; i++)
1047 DEBUG ("dbi plugin: cdbi_connect_database (%s): "
1048 "key = %s; value = %s;",
1050 db->driver_options[i].key,
1051 db->driver_options[i].value);
1053 status = dbi_conn_set_option (connection,
1054 db->driver_options[i].key, db->driver_options[i].value);
1060 ERROR ("dbi plugin: cdbi_connect_database (%s): "
1061 "dbi_conn_set_option (%s, %s) failed: %s.",
1063 db->driver_options[i].key, db->driver_options[i].value,
1064 cdbi_strerror (connection, errbuf, sizeof (errbuf)));
1066 INFO ("dbi plugin: This is a list of all options understood "
1067 "by the `%s' driver:", db->driver);
1068 for (opt = dbi_conn_get_option_list (connection, NULL);
1070 opt = dbi_conn_get_option_list (connection, opt))
1072 INFO ("dbi plugin: * %s", opt);
1075 dbi_conn_close (connection);
1078 } /* for (i = 0; i < db->driver_options_num; i++) */
1080 status = dbi_conn_connect (connection);
1084 ERROR ("dbi plugin: cdbi_connect_database (%s): "
1085 "dbi_conn_connect failed: %s",
1086 db->name, cdbi_strerror (connection, errbuf, sizeof (errbuf)));
1087 dbi_conn_close (connection);
1091 if (db->select_db != NULL)
1093 status = dbi_conn_select_db (connection, db->select_db);
1097 WARNING ("dbi plugin: cdbi_connect_database (%s): "
1098 "dbi_conn_select_db (%s) failed: %s. Check the `SelectDB' option.",
1099 db->name, db->select_db,
1100 cdbi_strerror (connection, errbuf, sizeof (errbuf)));
1101 dbi_conn_close (connection);
1106 db->connection = connection;
1108 } /* }}} int cdbi_connect_database */
1110 static int cdbi_read_database (cdbi_database_t *db) /* {{{ */
1116 status = cdbi_connect_database (db);
1119 assert (db->connection != NULL);
1122 for (i = 0; i < db->queries_num; i++)
1124 status = cdbi_read_database_query (db, db->queries[i]);
1131 ERROR ("dbi plugin: All queries failed for database `%s'.", db->name);
1136 } /* }}} int cdbi_read_database */
1138 static int cdbi_read (void) /* {{{ */
1144 for (i = 0; i < databases_num; i++)
1146 status = cdbi_read_database (databases[i]);
1153 ERROR ("dbi plugin: No database could be read. Will return an error so "
1154 "the plugin will be delayed.");
1159 } /* }}} int cdbi_read */
1161 static int cdbi_shutdown (void) /* {{{ */
1165 for (i = 0; i < databases_num; i++)
1167 if (databases[i]->connection != NULL)
1169 dbi_conn_close (databases[i]->connection);
1170 databases[i]->connection = NULL;
1172 cdbi_database_free (databases[i]);
1177 for (i = 0; i < queries_num; i++)
1178 cdbi_query_free (queries[i]);
1183 } /* }}} int cdbi_shutdown */
1185 void module_register (void) /* {{{ */
1187 plugin_register_complex_config ("dbi", cdbi_config);
1188 plugin_register_init ("dbi", cdbi_init);
1189 plugin_register_read ("dbi", cdbi_read);
1190 plugin_register_shutdown ("dbi", cdbi_shutdown);
1191 } /* }}} void module_register */
1194 * vim: shiftwidth=2 softtabstop=2 et fdm=marker