From: scottmk Date: Fri, 6 Aug 2010 15:33:11 +0000 (+0000) Subject: Refine the way we detect loss of the database connection. X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=82d6971d1380e40f14c1ec2c908557b7a5aaba7a;p=evergreen%2Fbjwebb.git Refine the way we detect loss of the database connection. This is a terrible, horrible, no good, very bad kludge. We do an innocuous SELECT 1. If this query succeeds, then we know that the connection is still good. If it fails, well... Sometimes the SELECT 1 query fails, not because the database connection is dead, but because (due to a previous error) the database is ignoring all commands, even innocuous SELECTs, until the current transaction is rolled back. The only known way to detect this condition via the dbi library is by looking at the error message returned by dbi_conn_error(). This approach will break if the language or wording of the message ever changes. Note: the dbi_conn_ping function purports to determine whether the database connection is live. At this writing, it follows the same approach as described above: try a SELECT 1 and see if it works. Consequently it presumably suffers from the same shortcoming: it may erroneously report a dead connection when the database is in fact just ignoring commands due to a previous error. In addition, if it determines (rightly or wrongly) that the connection is dead, it silently tries to reconnect; if the reconnect is succesful, the function reports that the connection is still alive, as if nothing had happened. If you were in the middle of a transaction at the time, you wouldn't know that it got rolled back. M Open-ILS/src/c-apps/oils_sql.c git-svn-id: svn://svn.open-ils.org/ILS/trunk@17118 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/src/c-apps/oils_sql.c b/Open-ILS/src/c-apps/oils_sql.c index cc3147f19..d195bfe55 100644 --- a/Open-ILS/src/c-apps/oils_sql.c +++ b/Open-ILS/src/c-apps/oils_sql.c @@ -239,13 +239,30 @@ void oilsSetDBConnection( dbi_conn conn ) { @return 1 if the connection is alive, or zero if it isn't. */ int oilsIsDBConnected( dbi_conn handle ) { + // Do an innocuous SELECT. If it succeeds, the database connection is still good. dbi_result result = dbi_conn_query( handle, "SELECT 1;" ); if( result ) { dbi_result_free( result ); return 1; } else { - osrfLogError( OSRF_LOG_MARK, "Database connection isn't working" ); - return 0; + // This is a terrible, horrible, no good, very bad kludge. + // Sometimes the SELECT 1 query fails, not because the database connection is dead, + // but because (due to a previous error) the database is ignoring all commands, + // even innocuous SELECTs, until the current transaction is rolled back. The only + // known way to detect this condition via the dbi library is by looking at the error + // message. This approach will break if the language or wording of the message ever + // changes. + // Note: the dbi_conn_ping function purports to determine whether the doatabase + // connection is live, but at this writing this function is unreliable and useless. + static const char* ok_msg = "ERROR: current transaction is aborted, commands " + "ignored until end of transaction block\n"; + const char* msg; + dbi_conn_error( handle, &msg ); + if( strcmp( msg, ok_msg )) { + osrfLogError( OSRF_LOG_MARK, "Database connection isn't working" ); + return 0; + } else + return 1; // ignoring SELECT due to previous error; that's okay } }