Index: C:/workspace/c4/java/net/sf/l2j/L2DatabaseFactory.java =================================================================== --- C:/workspace/c4/java/net/sf/l2j/L2DatabaseFactory.java (revision 1605) +++ C:/workspace/c4/java/net/sf/l2j/L2DatabaseFactory.java (working copy) @@ -44,7 +44,6 @@ private static L2DatabaseFactory _instance; private ProviderType _Provider_Type; private DataSource _source; - // ========================================================= // Constructor public L2DatabaseFactory() throws SQLException @@ -59,19 +58,53 @@ PoolConfig config = new PoolConfig(); config.setAutoCommitOnClose(true); - config.setInitialPoolSize(1); + config.setInitialPoolSize(8); // 8 connections is nothing for sql, + // please don't setup server without at least + // 50 connections allowed at same time + // sql is server software that is designed + // to handle thousands of connections + // if > MaxPoolSize, it will be ignored - no worry + // (as said in c3p0 docs, it's only a suggestion + // how many connections to open at the beginning) + config.setMinPoolSize(1); config.setMaxPoolSize(Config.DATABASE_MAX_CONNECTIONS); + + + config.setAcquireRetryAttempts(0); // try to obtain connections indefinitely + config.setAcquireRetryDelay(1); // retry once per second + config.setCheckoutTimeout(0); // 0 = wait indefinitely for new connection + // if pool is exhausted + config.setAcquireIncrement(8); // if pool is exhausted, get 8 more connections + // cause there is a "long" delay on acquire connection + // so taking more than one connection at once will make connection pooling + // more effective. + + // this "connection_test_table" is automatically created if not already there + config.setAutomaticTestTable("connection_test_table"); // very very fast test, don't worry + config.setTestConnectionOnCheckout(true); // this will *not* make l2j slower in any way + + config.setMaxStatements(100); - config.setIdleConnectionTestPeriod(0); // test idle connection every 1 minute - config.setMaxIdleTime(0); // remove unused connection after 10 minutes - + + config.setIdleConnectionTestPeriod(60); // test idle connection every 60 sec + config.setMaxIdleTime(60*60); // 0 = idle connections never expire + // *THANKS* to connection testing configured above + // but I prefer to disconnect all connections not used + // for more than 1 hour + + config.setBreakAfterAcquireFailure(false); // never fail if any way possible + // setting this to true will make + // c3p0 "crash" and refuse to work + // till restart thus making acquire + // errors "FATAL" ... we don't want that + // it should be possible to recover + Class.forName(Config.DATABASE_DRIVER).newInstance(); if (Config.DEBUG) _log.fine("Database Connection Working"); - DataSource unpooled = DataSources.unpooledDataSource(Config.DATABASE_URL, Config.DATABASE_LOGIN, Config.DATABASE_PASSWORD); - _source = DataSources.pooledDataSource( unpooled, config); + _source=DataSources.pooledDataSource( unpooled, config); /* Test the connection */ _source.getConnection().close(); @@ -83,13 +116,13 @@ } catch (SQLException x) { - if (Config.DEBUG) _log.fine("Database Connection FAILED"); + if (Config.DEBUG) _log.warning("Database Connection FAILED"); // rethrow the exception throw x; } catch (Exception e) { - if (Config.DEBUG) _log.fine("Database Connection FAILED"); + if (Config.DEBUG) _log.warning("Database Connection FAILED"); throw new SQLException("could not init DB connection:"+e); } } @@ -113,10 +146,10 @@ { try { ((PooledDataSource) _source).close(); - } catch (SQLException e) {_log.log(Level.INFO, "", e);} + } catch (SQLException e) {_log.log(Level.WARNING, "", e);} try { DataSources.destroy(_source); - } catch (SQLException e) {_log.log(Level.INFO, "", e);} + } catch (SQLException e) {_log.log(Level.WARNING, "", e);} } public final String safetyString(String[] whatToCheck) @@ -150,9 +183,34 @@ return _instance; } - public Connection getConnection() throws SQLException + public Connection getConnection() //throws SQLException { - return _source.getConnection(); + Connection con=null; + + try + { + con=_source.getConnection(); + } catch (SQLException e) + { + _log.warning("L2DatabaseFactory: getConnection() failed, trying again "+e); + + try + { + con=_source.getConnection(); + } catch (SQLException e2) + { + _log.warning("L2DatabaseFactory: getConnection() failed again :( "+e2); + } + } + + if (con==null) { + // any ideas what could be done here to "recover" from db errors ? + // maybe sleep 15 seconds and try again ? maybe make loop that will not quit + // till con!=null ? if we do that here, we can remove all if(con==null) checks + // elsewhere and assume we always have valid and tested connection (good idea) + _log.severe("L2DatabaseFactory: getConnection() failed completely please edit L2DatabaseFactory.java on line 213 - add some smart code to avoid this"); + } + return con; } public int getBusyConnectionCount() throws SQLException @@ -162,7 +220,7 @@ public int getIdleConnectionCount() throws SQLException { - return ((PooledDataSource) _source).getNumIdleConnectionsDefaultUser(); + return ((PooledDataSource) _source).getNumIdleConnectionsDefaultUser(); } public final ProviderType getProviderType() { return _Provider_Type; }