forked from LogBlock/LogBlock
Use HikariCP for connection pooling
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@
|
||||
|
||||
# maven
|
||||
/target
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
# vim
|
||||
.*.sw[a-p]
|
||||
|
29
pom.xml
29
pom.xml
@ -43,6 +43,7 @@
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.7.2-R0.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
@ -55,6 +56,7 @@
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldedit</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
@ -62,8 +64,13 @@
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP-java6</artifactId>
|
||||
<version>2.3.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>repobo-snap</id>
|
||||
@ -117,7 +124,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.5.1</version>
|
||||
<version>3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
@ -143,7 +150,21 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
@ -135,7 +135,7 @@ public class Config
|
||||
if (!config.contains(e.getKey()))
|
||||
config.set(e.getKey(), e.getValue());
|
||||
logblock.saveConfig();
|
||||
url = "jdbc:mysql://" + config.getString("mysql.host") + ":" + config.getInt("mysql.port") + "/" + getStringIncludingInts(config, "mysql.database") + "?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true";
|
||||
url = "jdbc:mysql://" + config.getString("mysql.host") + ":" + config.getInt("mysql.port") + "/" + getStringIncludingInts(config, "mysql.database");
|
||||
user = getStringIncludingInts(config, "mysql.user");
|
||||
password = getStringIncludingInts(config, "mysql.password");
|
||||
delayBetweenRuns = config.getInt("consumer.delayBetweenRuns", 2);
|
||||
|
@ -1,437 +1,43 @@
|
||||
package de.diddiz.util;
|
||||
|
||||
import static de.diddiz.LogBlock.config.Config.mb4;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import de.diddiz.LogBlock.config.Config;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.NClob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLClientInfoException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.SQLXML;
|
||||
import java.sql.Savepoint;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Struct;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class MySQLConnectionPool implements Closeable
|
||||
{
|
||||
private final static int poolSize = 10;
|
||||
private final static long timeToLive = 300000;
|
||||
private final Vector<JDCConnection> connections;
|
||||
private final String url, user, password;
|
||||
private final Lock lock = new ReentrantLock();
|
||||
|
||||
private final HikariDataSource ds;
|
||||
|
||||
public MySQLConnectionPool(String url, String user, String password) throws ClassNotFoundException {
|
||||
Class.forName("com.mysql.jdbc.Driver");
|
||||
this.url = url;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
connections = new Vector<JDCConnection>(poolSize);
|
||||
ConnectionReaper reaper = new ConnectionReaper();
|
||||
new Thread(reaper, "MySQL Connection Reaper Thread - LogBlock").start();
|
||||
this.ds = new HikariDataSource();
|
||||
ds.setJdbcUrl(url);
|
||||
ds.setUsername(user);
|
||||
ds.setPassword(password);
|
||||
|
||||
ds.addDataSourceProperty("useUnicode", "true");
|
||||
ds.addDataSourceProperty("characterEncoding", "utf-8");
|
||||
ds.addDataSourceProperty("rewriteBatchedStatements", "true");
|
||||
|
||||
ds.addDataSourceProperty("cachePrepStmts", "true");
|
||||
ds.addDataSourceProperty("prepStmtCacheSize", "250");
|
||||
ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
lock.lock();
|
||||
final Enumeration<JDCConnection> conns = connections.elements();
|
||||
while (conns.hasMoreElements()) {
|
||||
final JDCConnection conn = conns.nextElement();
|
||||
connections.remove(conn);
|
||||
conn.terminate();
|
||||
}
|
||||
lock.unlock();
|
||||
ds.close();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
lock.lock();
|
||||
try {
|
||||
final Enumeration<JDCConnection> conns = connections.elements();
|
||||
while (conns.hasMoreElements()) {
|
||||
final JDCConnection conn = conns.nextElement();
|
||||
if (conn.lease()) {
|
||||
if (conn.isValid())
|
||||
return conn;
|
||||
connections.remove(conn);
|
||||
conn.terminate();
|
||||
}
|
||||
}
|
||||
final JDCConnection conn = new JDCConnection(DriverManager.getConnection(url, user, password));
|
||||
conn.lease();
|
||||
if (!conn.isValid()) {
|
||||
conn.terminate();
|
||||
throw new SQLException("Failed to validate a brand new connection");
|
||||
}
|
||||
connections.add(conn);
|
||||
if (mb4) conn.createStatement().executeQuery("SET NAMES utf8mb4");
|
||||
return conn;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
Connection connection = ds.getConnection();
|
||||
if (Config.mb4) {
|
||||
connection.createStatement().executeQuery("SET NAMES utf8mb4");
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
private void reapConnections() {
|
||||
lock.lock();
|
||||
final long stale = System.currentTimeMillis() - timeToLive;
|
||||
final Iterator<JDCConnection> itr = connections.iterator();
|
||||
while (itr.hasNext()) {
|
||||
final JDCConnection conn = itr.next();
|
||||
if (conn.inUse() && stale > conn.getLastUse() && !conn.isValid())
|
||||
itr.remove();
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
private class ConnectionReaper implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(300000);
|
||||
} catch (final InterruptedException e) {
|
||||
}
|
||||
reapConnections();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class JDCConnection implements Connection
|
||||
{
|
||||
private final Connection conn;
|
||||
private boolean inUse;
|
||||
private long timestamp;
|
||||
private int networkTimeout;
|
||||
private String schema;
|
||||
|
||||
JDCConnection(Connection conn) {
|
||||
this.conn = conn;
|
||||
inUse = false;
|
||||
timestamp = 0;
|
||||
networkTimeout = 30;
|
||||
schema = "default";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWarnings() throws SQLException {
|
||||
conn.clearWarnings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
inUse = false;
|
||||
try {
|
||||
if (!conn.getAutoCommit())
|
||||
conn.setAutoCommit(true);
|
||||
} catch (final SQLException ex) {
|
||||
connections.remove(this);
|
||||
terminate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() throws SQLException {
|
||||
conn.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
|
||||
return conn.createArrayOf(typeName, elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Blob createBlob() throws SQLException {
|
||||
return conn.createBlob();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clob createClob() throws SQLException {
|
||||
return conn.createClob();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NClob createNClob() throws SQLException {
|
||||
return conn.createNClob();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLXML createSQLXML() throws SQLException {
|
||||
return conn.createSQLXML();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement createStatement() throws SQLException {
|
||||
return conn.createStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
|
||||
return conn.createStatement(resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
|
||||
return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
|
||||
return conn.createStruct(typeName, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAutoCommit() throws SQLException {
|
||||
return conn.getAutoCommit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCatalog() throws SQLException {
|
||||
return conn.getCatalog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getClientInfo() throws SQLException {
|
||||
return conn.getClientInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientInfo(String name) throws SQLException {
|
||||
return conn.getClientInfo(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHoldability() throws SQLException {
|
||||
return conn.getHoldability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseMetaData getMetaData() throws SQLException {
|
||||
return conn.getMetaData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransactionIsolation() throws SQLException {
|
||||
return conn.getTransactionIsolation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Class<?>> getTypeMap() throws SQLException {
|
||||
return conn.getTypeMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return conn.getWarnings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() throws SQLException {
|
||||
return conn.isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() throws SQLException {
|
||||
return conn.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(int timeout) throws SQLException {
|
||||
return conn.isValid(timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return conn.isWrapperFor(iface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nativeSQL(String sql) throws SQLException {
|
||||
return conn.nativeSQL(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallableStatement prepareCall(String sql) throws SQLException {
|
||||
return conn.prepareCall(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
|
||||
return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
|
||||
return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
return conn.prepareStatement(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
|
||||
return conn.prepareStatement(sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
|
||||
return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
|
||||
return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
|
||||
return conn.prepareStatement(sql, columnIndexes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
|
||||
return conn.prepareStatement(sql, columnNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
|
||||
conn.releaseSavepoint(savepoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() throws SQLException {
|
||||
conn.rollback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback(Savepoint savepoint) throws SQLException {
|
||||
conn.rollback(savepoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoCommit(boolean autoCommit) throws SQLException {
|
||||
conn.setAutoCommit(autoCommit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCatalog(String catalog) throws SQLException {
|
||||
conn.setCatalog(catalog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientInfo(Properties properties) throws SQLClientInfoException {
|
||||
conn.setClientInfo(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientInfo(String name, String value) throws SQLClientInfoException {
|
||||
conn.setClientInfo(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHoldability(int holdability) throws SQLException {
|
||||
conn.setHoldability(holdability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) throws SQLException {
|
||||
conn.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Savepoint setSavepoint() throws SQLException {
|
||||
return conn.setSavepoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Savepoint setSavepoint(String name) throws SQLException {
|
||||
return conn.setSavepoint(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransactionIsolation(int level) throws SQLException {
|
||||
conn.setTransactionIsolation(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
|
||||
conn.setTypeMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
return conn.unwrap(iface);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public int getNetworkTimeout() throws SQLException {
|
||||
return networkTimeout;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setNetworkTimeout(Executor exec, int timeout) throws SQLException {
|
||||
networkTimeout = timeout;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void abort(Executor exec) throws SQLException {
|
||||
// Not implemented really...
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public String getSchema() throws SQLException {
|
||||
return schema;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setSchema(String str) throws SQLException {
|
||||
schema = str;
|
||||
}
|
||||
|
||||
long getLastUse() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
boolean inUse() {
|
||||
return inUse;
|
||||
}
|
||||
|
||||
boolean isValid() {
|
||||
try {
|
||||
return conn.isValid(1);
|
||||
} catch (final SQLException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized boolean lease() {
|
||||
if (inUse)
|
||||
return false;
|
||||
inUse = true;
|
||||
timestamp = System.currentTimeMillis();
|
||||
return true;
|
||||
}
|
||||
|
||||
void terminate() {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (final SQLException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user