|
From: <lk...@us...> - 2004-08-10 19:00:14
|
Update of /cvsroot/openorb/PersistentStateService/src/main/org/openorb/pss/connector/database In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7930/src/main/org/openorb/pss/connector/database Modified Files: DatabaseSession.java Log Message: Fixed memory leak in Database connector that occured when DB went down. Patch provided by Thomas Haug and Matthias Grosam (Siemens) After an SQL Exception the DB Connection is now tested. Index: DatabaseSession.java =================================================================== RCS file: /cvsroot/openorb/PersistentStateService/src/main/org/openorb/pss/connector/database/DatabaseSession.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- DatabaseSession.java 10 Feb 2004 21:19:15 -0000 1.11 +++ DatabaseSession.java 10 Aug 2004 19:00:05 -0000 1.12 @@ -17,6 +17,12 @@ public class DatabaseSession extends org.openorb.pss.connector.database.DatabaseCatalog implements org.omg.CosPersistentState.Session, org.openorb.pss.connector.database.DatabaseCatalogBase { + + /** + * time to wait until next check of database connection. + */ + private static final long CHECK_CONNECTION_RETRY_TIME = 5000; + /** * Tables list */ @@ -110,14 +116,14 @@ { String sql_type = getParameter( "sql_type" ); - org.openorb.pss.util.debug.print( "sql_type in configuration is " + sql_type ); + org.openorb.pss.util.debug.print( "sql_type in configuration is " + sql_type ); if ( sql_type != null ) _binary_type = sql_type; } catch ( Throwable throwable ) { - throwable.printStackTrace(); + throwable.printStackTrace(); } // Here we have to open a simple connection to a database @@ -312,8 +318,8 @@ org.omg.CosPersistentState.Parameter [] params = parameters(); // Is the parameter provided from the source code ? - if ( null != params ) - { + if ( null != params ) + { for ( int i = 0; i < params.length; i++ ) { if ( params[ i ].name.equalsIgnoreCase( parameter_name ) ) @@ -321,11 +327,11 @@ return params[ i ].val.extract_string(); } } - } - else - { - org.openorb.pss.util.debug.print( "Params is null." ); - } + } + else + { + org.openorb.pss.util.debug.print( "Params is null." ); + } // In this case, the parameter must be found in the configuration file org.openorb.orb.config.ORBLoader cfg = ( ( org.openorb.orb.core.ORB ) ( ( ( org.openorb.orb.pi.OpenORBInitInfo ) _info ).orb() ) ).getLoader(); @@ -348,25 +354,26 @@ private boolean tableExist( String table_name ) { org.openorb.pss.util.debug.print( "Check if a table exist [ " + table_name + " ]" ); - + java.sql.ResultSet result = null; + boolean returnValue = false; try { - java.sql.DatabaseMetaData meta_data = _datastore.getMetaData(); - java.sql.ResultSet result = meta_data.getTables( null, null, table_name, null ); - - if ( result.next() == false ) - return false; - - return true; + result = meta_data.getTables( null, null, table_name, null ); + returnValue = result.next(); } catch ( java.sql.SQLException ex ) { // TODO: change this to an exception or log as a warning System.out.println( "OpenORB CosPSS error : Unable to get information about tables... : " + ex.toString() ); + this.checkConnection(); + } + finally + { + this.closeResources( result, null ); } - return false; + return returnValue; } /** @@ -390,10 +397,10 @@ private void createTable( String table_name, org.openorb.pss.connector.database.PersistentObjectHome home ) { org.openorb.pss.util.debug.print( "Create a new table [ " + table_name + " ]" ); - + java.sql.Statement stmt = null; try { - java.sql.Statement stmt = _datastore.createStatement(); + stmt = _datastore.createStatement(); String [] members = home.getHomeMembers(); @@ -405,13 +412,16 @@ order = order + " )"; stmt.executeUpdate( order ); - - stmt.close(); } catch ( java.sql.SQLException ex ) { ex.printStackTrace(); System.out.println( "openORB CosPSS error : Unable to create a table..." ); + this.checkConnection(); + } + finally + { + this.closeResources( null, stmt ); } } @@ -428,20 +438,24 @@ org.openorb.pss.util.debug.print( "Remove a table [ " + table_name + " ]" ); + java.sql.Statement stmt = null; try { - java.sql.Statement stmt = _datastore.createStatement(); + stmt = _datastore.createStatement(); String order = "DROP TABLE " + table_name; stmt.executeUpdate( order ); - - stmt.close(); } catch ( java.sql.SQLException ex ) { ex.printStackTrace(); System.out.println( "OpenORB CosPSS error : Unable to delete a table..." ); + this.checkConnection(); + } + finally + { + this.closeResources( null, stmt ); } } @@ -455,20 +469,22 @@ String table = ( String ) _tables.get( home_pid.catalog_value_str() ); java.sql.ResultSet res = getLine( table, type_pid ); - + boolean returnValue = false; try { - if ( res.next() == false ) - return false; - - return true; + returnValue = res.next(); } catch ( java.sql.SQLException ex ) { ex.printStackTrace(); + this.checkConnection(); + } + finally + { + this.closeResources( res, null ); } - return false; + return returnValue; } /** @@ -635,7 +651,7 @@ } catch ( java.lang.Exception ex ) { - ex.printStackTrace(); + ex.printStackTrace(); } } @@ -646,13 +662,16 @@ pstmt.executeUpdate(); - pstmt.close(); } catch ( java.sql.SQLException ex ) { - ex.printStackTrace(); + ex.printStackTrace(); + this.checkConnection(); + } + finally + { + this.closeResources( null, pstmt ); } - } /** @@ -684,10 +703,15 @@ pstmt.executeUpdate(); - pstmt.close(); } catch ( java.sql.SQLException ex ) - {} + { + this.checkConnection(); + } + finally + { + this.closeResources( null, pstmt ); + } } @@ -734,18 +758,24 @@ res = pstmt.executeQuery(); - if ( res.next() == false ) + if ( !res.next() ) + { + this.closeResources( res, pstmt ); throw new org.openorb.pss.connector.database.NotFoundException(); - + } byte [] pid = res.getBytes( 1 ); - pstmt.close(); - _pid = org.openorb.pss.connector.database.PIDFactory.pid_byte_to_pid( pid ); } catch ( java.lang.Exception ex ) - { } + { + this.checkConnection(); + } + finally + { + this.closeResources( res, pstmt ); + } if ( _pid == null ) throw new org.openorb.pss.connector.database.NotFoundException(); @@ -780,11 +810,16 @@ list.addElement( org.openorb.pss.connector.database.PIDFactory.pid_byte_to_pid( pid ) ); } - pstmt.close(); } catch ( java.lang.Exception ex ) - { } + { + this.checkConnection(); + } + finally + { + this.closeResources( res, pstmt ); + } org.openorb.pss.connector.PID [] pids = new org.openorb.pss.connector.PID[ list.size() ]; @@ -920,10 +955,10 @@ private java.sql.ResultSet getLine( String table_name, org.openorb.pss.connector.PID pid ) { java.sql.ResultSet res = null; - + java.sql.PreparedStatement pstmt = null; try { - java.sql.PreparedStatement pstmt = _datastore.prepareStatement( "SELECT * from " + table_name + " WHERE pid=?" ); + pstmt = _datastore.prepareStatement( "SELECT * from " + table_name + " WHERE pid=?" ); pstmt.setBytes( 1, pid.value() ); @@ -935,6 +970,11 @@ catch ( java.sql.SQLException ex ) { System.out.println( "openORB CosPSS error : Unable to get a table entry !" ); + this.checkConnection(); + } + finally + { + this.closeResources( res, pstmt ); } return res; @@ -948,6 +988,112 @@ return ( System.currentTimeMillis() * 32 ); //+ org.openorb.orb.core.ORBSingleton.oa.get_listener()._get_port(); } + /** + * Helper method for closing resources (result set, sql statement). + * This method is called from finally clauses and is necessary for + * avoiding memory leaks. + * + * @param result The result set of sql query. + * @param statement The sql statement. + */ + private void closeResources( java.sql.ResultSet result, java.sql.Statement statement ) + { + if ( result != null ) + { + try + { + result.close(); + } + catch ( java.sql.SQLException e ) + { + e.printStackTrace(); + System.out.println( "Error while closing SQL result." ); + } + } + if ( statement != null ) + { + try + { + statement.close(); + } + catch( java.sql.SQLException e ) + { + e.printStackTrace(); + System.out.println("Error while closing SQL statement." ); + } + } + } + + /** + * If a <code>SQLException</code> has occured this method is called for + * checking the connection to the database. If the connection is broken, this + * method tries to create a new connection till it succeeds. + */ + private void checkConnection() + { + // TODO: Prevent executing this code from multiple threads simultaniously + while( !executeCheckQuery() ) + { + try + { + Thread.sleep( CHECK_CONNECTION_RETRY_TIME ); + } + catch( InterruptedException e ) + { + e.printStackTrace(); + } + } + } + + /** + * Executes a simple query for checking database connection. If + * it fails a new connection is created. + * + * @return true, if connection works + * false, if connection is broken + */ + private boolean executeCheckQuery() + { + org.openorb.pss.util.debug.print( "Checking database connection" ); + String testStatement = getParameter( "ConnectionTestSQL" ); + if ( testStatement == null ) + { + // select without from clause, works with MySql, Sybase and maybe others. + // Oracle requires a from clause, so Oracle users should provide + // a statement in ConnectionTestSQL that refers to an existing table. + testStatement = "SELECT 1 + 1"; + } + + java.sql.Statement stmt = null; + boolean isOK = false; + try + { + stmt = this._datastore.createStatement(); + stmt.execute( testStatement ); + isOK = true; + } + catch( Exception e ) + { + e.printStackTrace(); + System.out.println("Database connection is broken. Try to create a new connection..."); + try + { + this._datastore = this.connectToDatabase(); + } + catch ( Exception exc ) + { + exc.printStackTrace(); + System.out.println("Error while creating a new database connection."); + } + } + finally + { + this.closeResources( null, stmt ); + } + return isOK; + } + + /*private org.openorb.orb.iiop.CDROutputStream getCDROutputStream() { org.openorb.orb.io.MarshalBuffer marshal = new org.openorb.orb.io.MarshalBuffer(); |