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)
@@ -22,12 +22,14 @@
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.sql.PooledConnection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.DataSources;
import com.mchange.v2.c3p0.PoolConfig;
import com.mchange.v2.c3p0.PooledDataSource;
+import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;
public class L2DatabaseFactory
{
@@ -44,7 +46,6 @@
private static L2DatabaseFactory _instance;
private ProviderType _Provider_Type;
private DataSource _source;
-
// =========================================================
// Constructor
public L2DatabaseFactory() throws SQLException
@@ -58,20 +59,55 @@
}
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.setAutomaticTestTable("connection_test_table"); // very very fast test, don't worry
+ config.setTestConnectionOnCheckout(true); // this will *not* make l2j slower in any way
+
+ config.setAutoCommitOnClose(true);
+ config.setAcquireIncrement(8); // if pool exhausted, get 6 more connections
+ // cause there is a "long" delay
+ // so taking more than one connection to pool
+ // will not reduce number of times waiting for
+ // new connection (which is slow)
+
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 +119,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 +149,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 +186,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 +223,7 @@
public int getIdleConnectionCount() throws SQLException
{
- return ((PooledDataSource) _source).getNumIdleConnectionsDefaultUser();
+ return ((PooledDataSource) _source).getNumIdleConnectionsDefaultUser();
}
public final ProviderType getProviderType() { return _Provider_Type; }