Index: C:/workspace/c4/java/net/sf/l2j/L2DatabaseFactory.java =================================================================== --- C:/workspace/c4/java/net/sf/l2j/L2DatabaseFactory.java (revision 1654) +++ C:/workspace/c4/java/net/sf/l2j/L2DatabaseFactory.java (working copy) @@ -44,10 +44,9 @@ private static L2DatabaseFactory _instance; private ProviderType _Provider_Type; private DataSource _source; - // ========================================================= // Constructor - public L2DatabaseFactory() throws SQLException + public L2DatabaseFactory() // throws SQLException { try { @@ -59,19 +58,52 @@ PoolConfig config = new PoolConfig(); config.setAutoCommitOnClose(true); - config.setInitialPoolSize(1); + config.setInitialPoolSize(3); // 3 is the default for c3p0 anyway + // if > MaxPoolSize, it will be ignored - no worry + // (as said in c3p0 docs, it's only a suggestion + // how many connections to acquire to start with) + config.setMinPoolSize(1); config.setMaxPoolSize(Config.DATABASE_MAX_CONNECTIONS); - config.setMaxStatements(100); - config.setIdleConnectionTestPeriod(0); // test idle connection every 1 minute - config.setMaxIdleTime(0); // remove unused connection after 10 minutes + + + config.setAcquireRetryAttempts(0); // try to obtain connections indefinitely (0 = never quit) + config.setAcquireRetryDelay(500); // 500 miliseconds wait before try to acquire connection again + config.setCheckoutTimeout(0); // 0 = wait indefinitely for new connection + // if pool is exhausted + config.setAcquireIncrement(5); // if pool is exhausted, get 5 more connections at a time + // 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.setTestConnectionOnCheckin(true); // this will *not* make l2j slower in any way + + // testing OnCheckin used with IdleConnectionTestPeriod is faster than testing on checkout + + 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'd prefer to disconnect all connections + // not used for more than 1 hour + // enables statement caching, there is a "semi-bug" in c3p0 0.9.0 but in 0.9.0.2 and later it's fixed + //config.setMaxStatements(0); // till c3p0 fixes bug with "possible threadlock" + //config.setMaxStatementsPerConnection(500); + + 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,14 +115,14 @@ } catch (SQLException x) { - if (Config.DEBUG) _log.fine("Database Connection FAILED"); - // rethrow the exception - throw x; + if (Config.DEBUG) _log.warning("Database Connection FAILED"); + // do not rethrow the exception - no point, it will crash server anyway + // throw x; } catch (Exception e) { - if (Config.DEBUG) _log.fine("Database Connection FAILED"); - throw new SQLException("could not init DB connection:"+e); + if (Config.DEBUG) _log.warning("Database Connection FAILED - could not init DB connection: "+e); + // throw new SQLException("could not init DB connection:"+e); } } @@ -113,10 +145,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) @@ -141,7 +173,7 @@ // ========================================================= // Property - Public - public static L2DatabaseFactory getInstance() throws SQLException + public static L2DatabaseFactory getInstance() // throws SQLException { if (_instance == null) { @@ -150,11 +182,31 @@ return _instance; } - public Connection getConnection() throws SQLException + public Connection getConnection(boolean use_transactions) //throws SQLException { - return _source.getConnection(); + Connection con=null; + + while(con==null) + { + try + { + con=_source.getConnection(); + con.setAutoCommit(!use_transactions); + } catch (SQLException e) + { + _log.warning("L2DatabaseFactory: getConnection() failed with error "+e+ ", trying again"); + } + }; + return con; } + public Connection getConnection() // for compatibility and transparent switch to transactions + // old method defaults to no-transactions + { + Connection con=getConnection(false); + return con; + } + public int getBusyConnectionCount() throws SQLException { return ((PooledDataSource) _source).getNumBusyConnectionsDefaultUser();