X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Foracle.c;h=ec45996bdebfdda8e8a27d54eb125b8544d0afc7;hb=26fbc23e518dcc74502ae3b2495112adc3840879;hp=accaee35045d815f9e1b29b19694a4bf6a9a7c82;hpb=4c9b0f6dd36455ad853af1b5b2b1a63f6964cbfd;p=collectd.git diff --git a/src/oracle.c b/src/oracle.c index accaee35..ec45996b 100644 --- a/src/oracle.c +++ b/src/oracle.c @@ -1,6 +1,7 @@ /** * collectd - src/oracle.c - * Copyright (C) 2008,2009 Florian octo Forster + * Copyright (C) 2008,2009 noris network AG + * Copyright (C) 2012 Florian octo Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -41,7 +42,7 @@ * affiliates. Other names may be trademarks of their respective owners. * * Authors: - * Florian octo Forster + * Florian octo Forster **/ #include "collectd.h" @@ -62,6 +63,7 @@ struct o_database_s char *username; char *password; + udb_query_preparation_area_t **q_prep_areas; udb_query_t **queries; size_t queries_num; @@ -90,37 +92,51 @@ static void o_report_error (const char *where, /* {{{ */ sb4 error_code; int status; - status = OCIErrorGet (eh, /* record number = */ 1, - /* sqlstate = */ NULL, - &error_code, - (text *) &buffer[0], - (ub4) sizeof (buffer), - OCI_HTYPE_ERROR); - buffer[sizeof (buffer) - 1] = 0; - - if (status == OCI_SUCCESS) + /* An operation may cause / return multiple errors. Loop until we have + * handled all errors available. */ + while (42) { - size_t buffer_length; + memset (buffer, 0, sizeof (buffer)); + error_code = -1; + + status = OCIErrorGet (eh, /* record number = */ 1, + /* sqlstate = */ NULL, + &error_code, + (text *) &buffer[0], + (ub4) sizeof (buffer), + OCI_HTYPE_ERROR); + buffer[sizeof (buffer) - 1] = 0; + + if (status == OCI_NO_DATA) + return; - buffer_length = strlen (buffer); - while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32)) + if (status == OCI_SUCCESS) { - buffer_length--; - buffer[buffer_length] = 0; - } + size_t buffer_length; - ERROR ("oracle plugin: %s: %s failed: %s", - where, what, buffer); - } - else - { - ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.", - where, what, status); + buffer_length = strlen (buffer); + while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32)) + { + buffer_length--; + buffer[buffer_length] = 0; + } + + ERROR ("oracle plugin: %s: %s failed: %s", + where, what, buffer); + } + else + { + ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.", + where, what, status); + return; + } } } /* }}} void o_report_error */ static void o_database_free (o_database_t *db) /* {{{ */ { + size_t i; + if (db == NULL) return; @@ -130,6 +146,11 @@ static void o_database_free (o_database_t *db) /* {{{ */ 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 */ @@ -256,6 +277,34 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */ 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) @@ -294,7 +343,8 @@ static int o_config (oconfig_item_t *ci) /* {{{ */ { oconfig_item_t *child = ci->children + i; if (strcasecmp ("Query", child->key) == 0) - udb_query_create (&queries, &queries_num, child); + udb_query_create (&queries, &queries_num, child, + /* callback = */ NULL); else if (strcasecmp ("Database", child->key) == 0) o_config_add_database (child); else @@ -348,7 +398,7 @@ static int o_init (void) /* {{{ */ } /* }}} 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; @@ -496,7 +546,7 @@ static int o_read_database_query (o_database_t *db, /* {{{ */ for (i = 0; i < column_num; i++) /* {{{ */ { char *column_name; - size_t column_name_length; + ub4 column_name_length; OCIParam *oci_param; oci_param = NULL; @@ -518,11 +568,15 @@ static int o_read_database_query (o_database_t *db, /* {{{ */ &column_name, &column_name_length, OCI_ATTR_NAME, oci_error); if (status != OCI_SUCCESS) { + OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM); o_report_error ("o_read_database_query", "OCIAttrGet (OCI_ATTR_NAME)", oci_error); continue; } + OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM); + oci_param = NULL; + /* Copy the name to column_names. Warning: The ``string'' returned by OCI * may not be null terminated! */ memset (column_names[i], 0, DATA_MAX_NAME_LEN); @@ -532,8 +586,8 @@ static int o_read_database_query (o_database_t *db, /* {{{ */ column_names[i][column_name_length] = 0; DEBUG ("oracle plugin: o_read_database_query: column_names[%zu] = %s; " - "column_name_length = %zu;", - i, column_names[i], column_name_length); + "column_name_length = %"PRIu32";", + i, column_names[i], (uint32_t) column_name_length); status = OCIDefineByPos (oci_statement, &oci_defines[i], oci_error, (ub4) (i + 1), @@ -547,8 +601,9 @@ static int o_read_database_query (o_database_t *db, /* {{{ */ } /* 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 = */ 0); if (status != 0) { ERROR ("oracle plugin: o_read_database_query (%s, %s): " @@ -575,7 +630,7 @@ static int o_read_database_query (o_database_t *db, /* {{{ */ 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): " @@ -597,6 +652,47 @@ static int o_read_database (o_database_t *db) /* {{{ */ size_t i; int status; + if (db->oci_service_context != NULL) + { + OCIServer *server_handle; + ub4 connection_status; + + server_handle = NULL; + status = OCIAttrGet ((void *) db->oci_service_context, OCI_HTYPE_SVCCTX, + (void *) &server_handle, /* size pointer = */ NULL, + OCI_ATTR_SERVER, oci_error); + if (status != OCI_SUCCESS) + { + o_report_error ("o_read_database", "OCIAttrGet", oci_error); + return (-1); + } + + if (server_handle == NULL) + { + connection_status = OCI_SERVER_NOT_CONNECTED; + } + else /* if (server_handle != NULL) */ + { + connection_status = 0; + status = OCIAttrGet ((void *) server_handle, OCI_HTYPE_SERVER, + (void *) &connection_status, /* size pointer = */ NULL, + OCI_ATTR_SERVER_STATUS, oci_error); + if (status != OCI_SUCCESS) + { + o_report_error ("o_read_database", "OCIAttrGet", oci_error); + return (-1); + } + } + + if (connection_status != OCI_SERVER_NORMAL) + { + INFO ("oracle plugin: Connection to %s lost. Trying to reconnect.", + db->name); + OCIHandleFree (db->oci_service_context, OCI_HTYPE_SVCCTX); + db->oci_service_context = NULL; + } + } /* if (db->oci_service_context != NULL) */ + if (db->oci_service_context == NULL) { status = OCILogon (oci_env, oci_error, @@ -619,7 +715,7 @@ static int o_read_database (o_database_t *db) /* {{{ */ 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 */ @@ -658,6 +754,7 @@ static int o_shutdown (void) /* {{{ */ } OCIHandleFree (oci_env, OCI_HTYPE_ENV); + oci_env = NULL; udb_query_free (queries, queries_num); queries = NULL;