All pastes #46252 Raw Edit

L2DatabaseFactory

public text v1 · immutable
#46252 ·published 2006-03-19 16:42 UTC
rendered paste body
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,51 @@
 
 			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.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 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(100);
-			config.setIdleConnectionTestPeriod(0); // test idle connection every 1 minute
-			config.setMaxIdleTime(0); // remove unused connection after 10 minutes
 
+			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 +114,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 +144,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 +181,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 +218,7 @@
 
 	public int getIdleConnectionCount() throws SQLException
 	{
-	    return ((PooledDataSource) _source).getNumIdleConnectionsDefaultUser();
+		return ((PooledDataSource) _source).getNumIdleConnectionsDefaultUser();
 	}
 
     public final ProviderType getProviderType() { return _Provider_Type; }