/**
* Copyright (C) 2013-2014 Project-Vethrfolnir
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.vethrfolnir.database;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import com.vethrfolnir.logging.MuLogger;
import corvus.corax.Corax;
import corvus.corax.config.CorvusConfig;
import corvus.corax.inject.Inject;
/**
* @author Vlad
*
*/
public class DatabaseFactory {
private static MuLogger log = MuLogger.getLogger(DatabaseFactory.class);
private BoneCP _connectionPool = null;
@Inject
private void load() {
CorvusConfig config = Corax.config(); // TODO: FUGLY
try
{
// load the database driver
Class.forName(config.getProperty("Database.Driver", "com.mysql.jdbc.Driver"));
}
catch (Exception e)
{
log.log(Level.SEVERE, "Failed initializing jdbc driver!", e);
throw new RuntimeException("System critical fail!");
}
try {
BoneCPConfig CPconfig = new BoneCPConfig();
/**
* Sets the JDBC connection URL.
*/
CPconfig.setJdbcUrl(config.getProperty("Database.Url", "jdbc:mysql://localhost/") +
config.getProperty("Database.Name", "vethrfolniremu"));
/**
* Sets username to use for connections.
*/
CPconfig.setUsername(config.getProperty("Database.User", "root"));
/**
* Sets password to use for connections.
*/
CPconfig.setPassword(config.getProperty("Database.Password", ""));
/**
* Sets the acquireIncrement property. When the available connections are about to run
* out, BoneCP will dynamically create new ones in batches. This property controls how
* many new connections to create in one go (up to a maximum of
* maxConnectionsPerPartition). Note: This is a per partition setting.
*/
CPconfig.setAcquireIncrement(2);
/**
* Sets number of partitions to use. In order to reduce lock contention and thus improve
* performance, each incoming connection request picks off a connection from a pool that
* has thread-affinity, i.e. pool[threadId % partition_count]. The higher this number,
* the better your performance will be for the case when you have plenty of short-lived
* threads. Beyond a certain threshold, maintenance of these pools will start to have a
* negative effect on performance (and only for the case when connections on a partition
* start running out). Default: 2, minimum: 1, recommended: 2-4
*/
CPconfig.setPartitionCount(config.getProperty("Database.PartitionCount", 2));
/**
* Sets the minimum number of connections that will be contained in every partition.
*/
CPconfig.setMinConnectionsPerPartition(config.getProperty("Database.MinConnections", 2));
/**
* Sets the maximum number of connections that will be contained in every partition.
* Setting this to 5 with 3 partitions means you will have 15 unique connections to the
* database. Note that the connection pool will not create all these connections in one
* go but rather start off with minConnectionsPerPartition and gradually increase
* connections as required.
*/
CPconfig.setMaxConnectionsPerPartition(config.getProperty("Database.MaxConnections", 10));
/**
* Sets the idleConnectionTestPeriod. This sets the time (in minutes), for a connection
* to remain idle before sending a test query to the DB. This is useful to prevent a DB
* from timing out connections on its end. Do not use aggressive values here! Default:
* 240 min, set to 0 to disable
*/
CPconfig.setIdleConnectionTestPeriodInMinutes(240);
/**
* Sets the idleConnectionTestPeriod. This sets the time (in seconds), for a connection
* to remain idle before sending a test query to the DB. This is useful to prevent a DB
* from timing out connections on its end. Do not use aggressive values here! Default:
* 240 min, set to 0 to disable
*/
CPconfig.setIdleConnectionTestPeriodInSeconds(14400);
/**
* Sets Idle max age (in min). The time (in minutes), for a connection to remain unused
* before it is closed off. Do not use aggressive values here! Default: 60 minutes, set
* to 0 to disable.
*/
//config.setIdleMaxAgeInMinutes(60);
/**
* Sets Idle max age (in seconds). The time (in seconds), for a connection to remain
* unused before it is closed off. Do not use aggressive values here! Default: 60
* minutes, set to 0 to disable.
*/
//config.setIdleMaxAgeInSeconds(3600);
/**
* Sets statementsCacheSize setting. The number of statements to cache.
*/
CPconfig.setStatementsCacheSize(0);
/**
* Sets number of helper threads to create that will handle releasing a connection. When
* this value is set to zero, the application thread is blocked until the pool is able
* to perform all the necessary cleanup to recycle the connection and make it available
* for another thread. When a non-zero value is set, the pool will create threads that
* will take care of recycling a connection when it is closed (the application dumps the
* connection into a temporary queue to be processed asychronously to the application
* via the release helper threads). Useful when your application is doing lots of work
* on each connection (i.e. perform an SQL query, do lots of non-DB stuff and perform
* another query), otherwise will probably slow things down.
*/
//config.setReleaseHelperThreads(3);
/**
* Instruct the pool to create a helper thread to watch over connection acquires that
* are never released (or released twice). This is for debugging purposes only and will
* create a new thread for each call to getConnection(). Enabling this option will have
* a big negative impact on pool performance.
*/
CPconfig.setCloseConnectionWatch(false);
/**
* If enabled, log SQL statements being executed.
*/
CPconfig.setLogStatementsEnabled(false);
/**
* Sets the number of ms to wait before attempting to obtain a connection again after a
* failure.
*/
CPconfig.setAcquireRetryDelayInMs(7000);
/**
* Set to true to force the connection pool to obtain the initial connections lazily.
*/
CPconfig.setLazyInit(false);
/**
* Set to true to enable recording of all transaction activity and replay the
* transaction automatically in case of a connection failure.
*/
CPconfig.setTransactionRecoveryEnabled(false);
/**
* After attempting to acquire a connection and failing, try to connect these many times
* before giving up. Default 5.
*/
CPconfig.setAcquireRetryAttempts(5);
/**
* Queries taking longer than this limit to execute are logged.
*/
CPconfig.setQueryExecuteTimeLimitInMs(0);
/**
* Sets the Pool Watch thread threshold. The pool watch thread attempts to maintain a
* number of connections always available (between minConnections and maxConnections).
* This value sets the percentage value to maintain. For example, setting it to 20 means
* that if the following condition holds: Free Connections / MaxConnections <
* poolAvailabilityThreshold new connections will be created. In other words, it tries
* to keep at least 20% of the pool full of connections. Setting the value to zero will
* make the pool create new connections when it needs them but it also means your
* application may have to wait for new connections to be obtained at times. Default:
* 20.
*/
CPconfig.setPoolAvailabilityThreshold(20);
/**
* If set to true, the pool will not monitor connections for proper closure. Enable this
* option if you only ever obtain your connections via a mechanism that is guaranteed to
* release the connection back to the pool (eg Spring's jdbcTemplate, some kind of
* transaction manager, etc).
*/
CPconfig.setDisableConnectionTracking(false);
/**
* Sets the maximum time (in milliseconds) to wait before a call to getConnection is
* timed out. Setting this to zero is similar to setting it to Long.MAX_VALUE Default: 0
* ( = wait forever )
*/
CPconfig.setConnectionTimeoutInMs(0);
/**
* Sets the no of ms to wait when close connection watch threads are enabled. 0 = wait
* forever.
*/
CPconfig.setCloseConnectionWatchTimeoutInMs(0);
/**
* Sets number of statement helper threads to create that will handle releasing a
* statement. When this value is set to zero, the application thread is blocked until
* the pool and JDBC driver are able to close off the statement. When a non-zero value
* is set, the pool will create threads that will take care of closing off the statement
* asychronously to the application via the release helper threads). Useful when your
* application is opening up lots of statements otherwise will probably slow things
* down.
*/
//config.setStatementReleaseHelperThreads(0);
/**
* Sets the maxConnectionAge in seconds. Any connections older than this setting will be
* closed off whether it is idle or not. Connections currently in use will not be
* affected until they are returned to the pool.
*/
CPconfig.setMaxConnectionAgeInSeconds(0);
CPconfig.setDefaultAutoCommit(true);
_connectionPool = new BoneCP(CPconfig);
}
catch(Exception e) {
log.log(Level.SEVERE, "Failed initializing BoneCP!", e);
throw new RuntimeException("System critical fail!");
}
log.info("Database driver successfully installed");
}
public void shutdown()
{
try
{
_connectionPool.close();
_connectionPool = null;
}
catch (Exception e)
{
log.fatal("Failed shutting down", e);
}
}
public Connection getConnection()
{
Connection con = null;
while (con == null)
{
try {
con = _connectionPool.getConnection();
}
catch (SQLException e) {
log.warning("Failed getting a connection, trying again " + e);
}
}
return con;
}
}