From d49b3093012d94b66cb5f44a82f3f0b3c4aa5ab6 Mon Sep 17 00:00:00 2001 From: Xephi59 Date: Fri, 31 Jul 2015 03:31:17 +0200 Subject: [PATCH 1/6] Change the MySQL Connection Pool to HikariCP, so fast ! --- pom.xml | 24 +- src/main/java/fr/xephi/authme/AuthMe.java | 14 +- .../datasource/MiniConnectionPoolManager.java | 427 ------------------ .../fr/xephi/authme/datasource/MySQL.java | 133 ++---- .../fr/xephi/authme/datasource/SQLite.java | 34 -- 5 files changed, 65 insertions(+), 567 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/datasource/MiniConnectionPoolManager.java diff --git a/pom.xml b/pom.xml index 97d39eb4..addea73d 100644 --- a/pom.xml +++ b/pom.xml @@ -90,6 +90,8 @@ com.sun.mail:* com.comphenix.attribute:* org.mcstats.*:* + com.zaxxer:* + org.slf4j:* @@ -175,11 +177,27 @@ - mysql - mysql-connector-java - 5.1.36 + org.slf4j + slf4j-simple + 1.7.12 compile + + com.zaxxer + HikariCP + 2.4.0 + compile + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-simple + + + diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index f320e5b5..99cea4a0 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -249,9 +249,9 @@ public class AuthMe extends JavaPlugin { if (!Settings.isForceSingleSessionEnabled) { ConsoleLogger.showError("WARNING!!! By disabling ForceSingleSession, your server protection is inadequate!"); } - + if (Settings.getSessionTimeout == 0 && Settings.isSessionsEnabled) { - ConsoleLogger.showError("WARNING!!! You set session timeout to 0, this may cause security issues!"); + ConsoleLogger.showError("WARNING!!! You set session timeout to 0, this may cause security issues!"); } if (Settings.reloadSupport) { @@ -545,13 +545,17 @@ public class AuthMe extends JavaPlugin { return; ConsoleLogger.info("AutoPurging the Database: " + cleared.size() + " accounts removed!"); if (Settings.purgeEssentialsFile && this.ess != null) - dataManager.purgeEssentials(cleared); // name to UUID convertion needed with latest versions + dataManager.purgeEssentials(cleared); // name to UUID convertion + // needed with latest versions if (Settings.purgePlayerDat) - dataManager.purgeDat(cleared); // name to UUID convertion needed with latest versions of MC + dataManager.purgeDat(cleared); // name to UUID convertion needed + // with latest versions of MC if (Settings.purgeLimitedCreative) dataManager.purgeLimitedCreative(cleared); if (Settings.purgeAntiXray) - dataManager.purgeAntiXray(cleared); // IDK if it uses UUID or names... (Actually it purges only names!) + dataManager.purgeAntiXray(cleared); // IDK if it uses UUID or + // names... (Actually it purges + // only names!) if (Settings.purgePermissions) dataManager.purgePermissions(cleared, permission); } diff --git a/src/main/java/fr/xephi/authme/datasource/MiniConnectionPoolManager.java b/src/main/java/fr/xephi/authme/datasource/MiniConnectionPoolManager.java deleted file mode 100644 index 5a557f19..00000000 --- a/src/main/java/fr/xephi/authme/datasource/MiniConnectionPoolManager.java +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright 2007-2013 Christian d'Heureuse, Inventec Informatik AG, Zurich, -// Switzerland -// www.source-code.biz, www.inventec.ch/chdh -// -// This module is multi-licensed and may be used under the terms -// of any of the following licenses: -// -// EPL, Eclipse Public License, http://www.eclipse.org/legal -// LGPL, GNU Lesser General Public License, -// http://www.gnu.org/licenses/lgpl.html -// MPL, Mozilla Public License 1.1, http://www.mozilla.org/MPL -// -// Please contact the author if you need another license. -// This module is provided "as is", without warranties of any kind. - -package fr.xephi.authme.datasource; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.LinkedList; -import javax.sql.ConnectionEvent; -import javax.sql.ConnectionEventListener; -import javax.sql.ConnectionPoolDataSource; -import javax.sql.PooledConnection; - -/** - * A lightweight standalone JDBC connection pool manager. - * - *

- * The public methods of this class are thread-safe. - * - *

- * Home page: www. - * source-code.biz/miniconnectionpoolmanager
- * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
- * Multi-licensed: EPL / LGPL / MPL. - */ -public class MiniConnectionPoolManager { - - private ConnectionPoolDataSource dataSource; - private int maxConnections; - private long timeoutMs; - private PrintWriter logWriter; - private Semaphore semaphore; - private PoolConnectionEventListener poolConnectionEventListener; - - // The following variables must only be accessed within synchronized blocks. - // @GuardedBy("this") could by used in the future. - private LinkedList recycledConnections; // list of - // inactive - // PooledConnections - private int activeConnections; // number of active (open) connections of - // this pool - private boolean isDisposed; // true if this connection pool has been - // disposed - private boolean doPurgeConnection; // flag to purge the connection currently - // beeing closed instead of recycling it - private PooledConnection connectionInTransition; // a PooledConnection which - // is currently within a - // PooledConnection.getConnection() - // call, or null - - /** - * Thrown in {@link #getConnection()} or {@link #getValidConnection()} when - * no free connection becomes available within timeout seconds. - */ - public static class TimeoutException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public TimeoutException() { - super("Timeout while waiting for a free database connection."); - } - - public TimeoutException(String msg) { - super(msg); - } - } - - /** - * Constructs a MiniConnectionPoolManager object with a timeout of 60 - * seconds. - * - * @param dataSource - * the data source for the connections. - * @param maxConnections - * the maximum number of connections. - */ - public MiniConnectionPoolManager(ConnectionPoolDataSource dataSource, - int maxConnections) { - this(dataSource, maxConnections, 60); - } - - /** - * Constructs a MiniConnectionPoolManager object. - * - * @param dataSource - * the data source for the connections. - * @param maxConnections - * the maximum number of connections. - * @param timeout - * the maximum time in seconds to wait for a free connection. - */ - public MiniConnectionPoolManager(ConnectionPoolDataSource dataSource, - int maxConnections, int timeout) { - this.dataSource = dataSource; - this.maxConnections = maxConnections; - this.timeoutMs = timeout * 1000L; - try { - logWriter = dataSource.getLogWriter(); - } catch (SQLException e) { - } - if (maxConnections < 1) { - throw new IllegalArgumentException("Invalid maxConnections value."); - } - semaphore = new Semaphore(maxConnections, true); - recycledConnections = new LinkedList(); - poolConnectionEventListener = new PoolConnectionEventListener(); - } - - /** - * Closes all unused pooled connections. - */ - public synchronized void dispose() throws SQLException { - if (isDisposed) { - return; - } - isDisposed = true; - SQLException e = null; - while (!recycledConnections.isEmpty()) { - PooledConnection pconn = recycledConnections.remove(); - try { - pconn.close(); - } catch (SQLException e2) { - if (e == null) { - e = e2; - } - } - } - if (e != null) { - throw e; - } - } - - /** - * Retrieves a connection from the connection pool. - * - *

- * If maxConnections connections are already in use, the method - * waits until a connection becomes available or timeout - * seconds elapsed. When the application is finished using the connection, - * it must close it in order to return it to the pool. - * - * @return a new Connection object. - * @throws TimeoutException - * when no connection becomes available within - * timeout seconds. - */ - public Connection getConnection() throws SQLException { - return getConnection2(timeoutMs); - } - - private Connection getConnection2(long timeoutMs) throws SQLException { - // This routine is unsynchronized, because semaphore.tryAcquire() may - // block. - synchronized (this) { - if (isDisposed) { - throw new IllegalStateException("Connection pool has been disposed."); - } - } - try { - if (!semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { - throw new TimeoutException(); - } - } catch (InterruptedException e) { - throw new RuntimeException("Interrupted while waiting for a database connection.", e); - } - boolean ok = false; - try { - Connection conn = getConnection3(); - ok = true; - return conn; - } finally { - if (!ok) { - semaphore.release(); - } - } - } - - private synchronized Connection getConnection3() throws SQLException { - if (isDisposed) { - throw new IllegalStateException("Connection pool has been disposed."); - } - PooledConnection pconn; - if (!recycledConnections.isEmpty()) { - pconn = recycledConnections.remove(); - } else { - pconn = dataSource.getPooledConnection(); - pconn.addConnectionEventListener(poolConnectionEventListener); - } - Connection conn; - try { - // The JDBC driver may call - // ConnectionEventListener.connectionErrorOccurred() - // from within PooledConnection.getConnection(). To detect this - // within - // disposeConnection(), we temporarily set connectionInTransition. - connectionInTransition = pconn; - activeConnections++; - conn = pconn.getConnection(); - } finally { - connectionInTransition = null; - } - assertInnerState(); - return conn; - } - - /** - * Retrieves a connection from the connection pool and ensures that it is - * valid by calling {@link Connection#isValid(int)}. - * - *

- * If a connection is not valid, the method tries to get another connection - * until one is valid (or a timeout occurs). - * - *

- * Pooled connections may become invalid when e.g. the database server is - * restarted. - * - *

- * This method is slower than {@link #getConnection()} because the JDBC - * driver has to send an extra command to the database server to test the - * connection. - * - *

- * This method requires Java 1.6 or newer. - * - * @throws TimeoutException - * when no valid connection becomes available within - * timeout seconds. - */ - public Connection getValidConnection() { - long time = System.currentTimeMillis(); - long timeoutTime = time + timeoutMs; - int triesWithoutDelay = getInactiveConnections() + 1; - while (true) { - Connection conn = getValidConnection2(time, timeoutTime); - if (conn != null) { - return conn; - } - triesWithoutDelay--; - if (triesWithoutDelay <= 0) { - triesWithoutDelay = 0; - try { - Thread.sleep(250); - } catch (InterruptedException e) { - throw new RuntimeException("Interrupted while waiting for a valid database connection.", e); - } - } - time = System.currentTimeMillis(); - if (time >= timeoutTime) { - throw new TimeoutException("Timeout while waiting for a valid database connection."); - } - } - } - - private Connection getValidConnection2(long time, long timeoutTime) { - long rtime = Math.max(1, timeoutTime - time); - Connection conn; - try { - conn = getConnection2(rtime); - } catch (SQLException e) { - return null; - } - rtime = timeoutTime - System.currentTimeMillis(); - int rtimeSecs = Math.max(1, (int) ((rtime + 999) / 1000)); - try { - if (conn.isValid(rtimeSecs)) { - return conn; - } - } catch (SQLException e) { - } - // This Exception should never occur. If it nevertheless occurs, it's - // because of an error in the - // JDBC driver which we ignore and assume that the connection is not - // valid. - // When isValid() returns false, the JDBC driver should have already - // called connectionErrorOccurred() - // and the PooledConnection has been removed from the pool, i.e. the - // PooledConnection will - // not be added to recycledConnections when Connection.close() is - // called. - // But to be sure that this works even with a faulty JDBC driver, we - // call purgeConnection(). - purgeConnection(conn); - return null; - } - - // Purges the PooledConnection associated with the passed Connection from - // the connection pool. - private synchronized void purgeConnection(Connection conn) { - try { - doPurgeConnection = true; - // (A potential problem of this program logic is that setting the - // doPurgeConnection flag - // has an effect only if the JDBC driver calls connectionClosed() - // synchronously within - // Connection.close().) - conn.close(); - } catch (SQLException e) { - } - // ignore exception from close() - finally { - doPurgeConnection = false; - } - } - - private synchronized void recycleConnection(PooledConnection pconn) { - if (isDisposed || doPurgeConnection) { - disposeConnection(pconn); - return; - } - if (activeConnections <= 0) { - throw new AssertionError("AuthMeDatabaseError"); - } - activeConnections--; - semaphore.release(); - recycledConnections.add(pconn); - assertInnerState(); - } - - private synchronized void disposeConnection(PooledConnection pconn) { - pconn.removeConnectionEventListener(poolConnectionEventListener); - if (!recycledConnections.remove(pconn) && pconn != connectionInTransition) { - // If the PooledConnection is not in the recycledConnections list - // and is not currently within a PooledConnection.getConnection() - // call, - // we assume that the connection was active. - if (activeConnections <= 0) { - throw new AssertionError("AuthMeDatabaseError"); - } - activeConnections--; - semaphore.release(); - } - closeConnectionAndIgnoreException(pconn); - assertInnerState(); - } - - private void closeConnectionAndIgnoreException(PooledConnection pconn) { - try { - pconn.close(); - } catch (SQLException e) { - log("Error while closing database connection: " + e.toString()); - } - } - - private void log(String msg) { - String s = "MiniConnectionPoolManager: " + msg; - try { - if (logWriter == null) { - System.err.println(s); - } else { - logWriter.println(s); - } - } catch (Exception e) { - } - } - - private synchronized void assertInnerState() { - if (activeConnections < 0) { - throw new AssertionError("AuthMeDatabaseError"); - } - if (activeConnections + recycledConnections.size() > maxConnections) { - throw new AssertionError("AuthMeDatabaseError"); - } - if (activeConnections + semaphore.availablePermits() > maxConnections) { - throw new AssertionError("AuthMeDatabaseError"); - } - } - - private class PoolConnectionEventListener implements - ConnectionEventListener { - - public void connectionClosed(ConnectionEvent event) { - PooledConnection pconn = (PooledConnection) event.getSource(); - recycleConnection(pconn); - } - - public void connectionErrorOccurred(ConnectionEvent event) { - PooledConnection pconn = (PooledConnection) event.getSource(); - disposeConnection(pconn); - } - } - - /** - * Returns the number of active (open) connections of this pool. - * - *

- * This is the number of Connection objects that have been - * issued by {@link #getConnection()}, for which - * Connection.close() has not yet been called. - * - * @return the number of active connections. - **/ - public synchronized int getActiveConnections() { - return activeConnections; - } - - /** - * Returns the number of inactive (unused) connections in this pool. - * - *

- * This is the number of internally kept recycled connections, for which - * Connection.close() has been called and which have not yet - * been reused. - * - * @return the number of inactive connections. - **/ - public synchronized int getInactiveConnections() { - return recycledConnections.size(); - } - -} // end class MiniConnectionPoolManager diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 4f4f96b5..b637259e 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -8,13 +8,14 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; -import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.datasource.MiniConnectionPoolManager.TimeoutException; import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.settings.Settings; @@ -40,7 +41,7 @@ public class MySQL implements DataSource { private String columnID; private String columnLogged; private List columnOthers; - private MiniConnectionPoolManager conPool; + private HikariDataSource ds; private String columnRealName; public MySQL() { @@ -100,15 +101,14 @@ public class MySQL implements DataSource { private synchronized void connect() throws ClassNotFoundException, SQLException, TimeoutException, NumberFormatException { - Class.forName("com.mysql.jdbc.Driver"); - ConsoleLogger.info("MySQL driver loaded"); - MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource(); - dataSource.setDatabaseName(database); - dataSource.setServerName(host); - dataSource.setPort(Integer.parseInt(port)); - dataSource.setUser(username); - dataSource.setPassword(password); - conPool = new MiniConnectionPoolManager(dataSource, 10); + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database); + config.setUsername(this.username); + config.setPassword(this.password); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + ds = new HikariDataSource(config); ConsoleLogger.info("Connection pool ready"); } @@ -185,9 +185,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(rs); close(pst); @@ -238,9 +235,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return null; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return null; } finally { close(rs); close(pst); @@ -451,9 +445,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -499,9 +490,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -523,9 +511,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -545,9 +530,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return 0; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return 0; } finally { close(pst); close(con); @@ -576,9 +558,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } finally { close(rs); close(pst); @@ -615,9 +594,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -641,9 +617,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -669,9 +642,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return 0; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return 0; } finally { close(rs); close(pst); @@ -692,9 +662,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -718,9 +685,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(pst); close(con); @@ -730,11 +694,8 @@ public class MySQL implements DataSource { @Override public synchronized void close() { - try { - conPool.dispose(); - } catch (SQLException ex) { - ConsoleLogger.showError(ex.getMessage()); - } + if (ds != null) + ds.close(); } @Override @@ -800,9 +761,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } finally { close(rs); close(pst); @@ -828,9 +786,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } finally { close(rs); close(pst); @@ -856,9 +811,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } finally { close(rs); close(pst); @@ -888,7 +840,7 @@ public class MySQL implements DataSource { private synchronized Connection makeSureConnectionIsReady() { Connection con = null; try { - con = conPool.getValidConnection(); + con = ds.getConnection(); } catch (Exception te) { try { con = null; @@ -920,22 +872,31 @@ public class MySQL implements DataSource { AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); } } - if (con == null) - con = conPool.getValidConnection(); + while (con == null) + try { + con = ds.getConnection(); + } catch (SQLException e) { + try { + reconnect(false); + con = ds.getConnection(); + } catch (Exception ex) { + } + } return con; } private synchronized void reconnect(boolean reload) throws ClassNotFoundException, SQLException, TimeoutException { - conPool.dispose(); - Class.forName("com.mysql.jdbc.Driver"); - MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource(); - dataSource.setDatabaseName(database); - dataSource.setServerName(host); - dataSource.setPort(Integer.parseInt(port)); - dataSource.setUser(username); - dataSource.setPassword(password); - conPool = new MiniConnectionPoolManager(dataSource, 10); + if (ds != null) + ds.close(); + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database); + config.setUsername(this.username); + config.setPassword(this.password); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + ds = new HikariDataSource(config); if (!reload) ConsoleLogger.info("ConnectionPool was unavailable... Reconnected!"); } @@ -960,9 +921,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(rs); close(pst); @@ -984,9 +942,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); close(con); @@ -1008,9 +963,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); close(con); @@ -1031,9 +983,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); close(con); @@ -1057,9 +1006,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return result; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return result; } finally { close(pst); close(con); @@ -1080,9 +1026,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); close(con); @@ -1133,9 +1076,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return auths; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return auths; } finally { close(pst); close(con); @@ -1187,9 +1127,6 @@ public class MySQL implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return auths; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return auths; } finally { close(pst); close(rs); diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 27d668e7..a465ddd7 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -12,7 +12,6 @@ import java.util.List; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.datasource.MiniConnectionPoolManager.TimeoutException; import fr.xephi.authme.settings.Settings; public class SQLite implements DataSource { @@ -436,9 +435,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } catch (NullPointerException npe) { return new ArrayList(); } finally { @@ -463,9 +459,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } catch (NullPointerException npe) { return new ArrayList(); } finally { @@ -490,9 +483,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return new ArrayList(); - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return new ArrayList(); } catch (NullPointerException npe) { return new ArrayList(); } finally { @@ -535,9 +525,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return false; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return false; } finally { close(rs); close(pst); @@ -556,9 +543,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); } @@ -577,9 +561,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); } @@ -597,9 +578,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); } @@ -620,9 +598,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return result; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return result; } finally { close(pst); } @@ -640,9 +615,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return; } finally { close(pst); } @@ -674,9 +646,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return auths; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return auths; } finally { close(pst); } @@ -708,9 +677,6 @@ public class SQLite implements DataSource { } catch (SQLException ex) { ConsoleLogger.showError(ex.getMessage()); return auths; - } catch (TimeoutException ex) { - ConsoleLogger.showError(ex.getMessage()); - return auths; } finally { close(pst); } From 6b53afa731f0c248d021e24e1d548481a554eb9f Mon Sep 17 00:00:00 2001 From: Xephi59 Date: Fri, 31 Jul 2015 14:07:14 +0200 Subject: [PATCH 2/6] Add failfast and reconnexion --- src/main/java/fr/xephi/authme/datasource/MySQL.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index b637259e..7ae8b6d5 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -108,6 +108,8 @@ public class MySQL implements DataSource { config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + config.addDataSourceProperty("autoReconnect", true); + config.addDataSourceProperty("initializationFailFast", true); ds = new HikariDataSource(config); ConsoleLogger.info("Connection pool ready"); } @@ -896,6 +898,8 @@ public class MySQL implements DataSource { config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + config.addDataSourceProperty("autoReconnect", true); + config.addDataSourceProperty("initializationFailFast", true); ds = new HikariDataSource(config); if (!reload) ConsoleLogger.info("ConnectionPool was unavailable... Reconnected!"); From 8b9f0ec88254107b10cb57bb2fc5939516921985 Mon Sep 17 00:00:00 2001 From: Xephi59 Date: Fri, 31 Jul 2015 14:22:07 +0200 Subject: [PATCH 3/6] Custom name to pool --- src/main/java/fr/xephi/authme/AuthMe.java | 9 +++++---- src/main/java/fr/xephi/authme/datasource/MySQL.java | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 99cea4a0..98f335d4 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -166,10 +166,11 @@ public class AuthMe extends JavaPlugin { // Set Console Filter if (Settings.removePassword) { - this.getLogger().setFilter(new ConsoleFilter()); - Bukkit.getLogger().setFilter(new ConsoleFilter()); - Logger.getLogger("Minecraft").setFilter(new ConsoleFilter()); - authmeLogger.setFilter(new ConsoleFilter()); + ConsoleFilter filter = new ConsoleFilter(); + this.getLogger().setFilter(filter); + Bukkit.getLogger().setFilter(filter); + Logger.getLogger("Minecraft").setFilter(filter); + authmeLogger.setFilter(filter); // Set Log4J Filter try { Class.forName("org.apache.logging.log4j.core.Filter"); diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 7ae8b6d5..43433be9 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -105,6 +105,7 @@ public class MySQL implements DataSource { config.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database); config.setUsername(this.username); config.setPassword(this.password); + config.setPoolName("AuthMeMYSQLPool"); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); @@ -900,6 +901,7 @@ public class MySQL implements DataSource { config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); config.addDataSourceProperty("autoReconnect", true); config.addDataSourceProperty("initializationFailFast", true); + config.setPoolName("AuthMeMYSQLPool"); ds = new HikariDataSource(config); if (!reload) ConsoleLogger.info("ConnectionPool was unavailable... Reconnected!"); From 84a1227afdc567fcb2283dc28cd798b2fd90f8a1 Mon Sep 17 00:00:00 2001 From: Xephi59 Date: Fri, 31 Jul 2015 14:32:28 +0200 Subject: [PATCH 4/6] Handle misconnection --- .../java/fr/xephi/authme/datasource/MySQL.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 43433be9..e18ef5bc 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -12,6 +12,7 @@ import java.util.concurrent.TimeoutException; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.pool.PoolInitializationException; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; @@ -96,11 +97,21 @@ public class MySQL implements DataSource { if (!Settings.isStopEnabled) AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); return; + } catch (PoolInitializationException e) { + ConsoleLogger.showError(e.getMessage()); + if (Settings.isStopEnabled) { + ConsoleLogger.showError("Can't use MySQL... Please input correct MySQL informations ! SHUTDOWN..."); + AuthMe.getInstance().getServer().shutdown(); + } + if (!Settings.isStopEnabled) + AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); + return; } } - private synchronized void connect() throws ClassNotFoundException, - SQLException, TimeoutException, NumberFormatException { + private synchronized void connect() + throws ClassNotFoundException, SQLException, TimeoutException, + NumberFormatException, PoolInitializationException { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database); config.setUsername(this.username); @@ -889,7 +900,8 @@ public class MySQL implements DataSource { } private synchronized void reconnect(boolean reload) - throws ClassNotFoundException, SQLException, TimeoutException { + throws ClassNotFoundException, SQLException, TimeoutException, + PoolInitializationException { if (ds != null) ds.close(); HikariConfig config = new HikariConfig(); From 4ecbd7b5260206fc0735976a5977b4cc88c5b565 Mon Sep 17 00:00:00 2001 From: Xephi59 Date: Fri, 31 Jul 2015 14:39:49 +0200 Subject: [PATCH 5/6] Try this way to fix quitloc --- .../authme/process/quit/AsyncronousQuit.java | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java b/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java index e60d9719..82ff826b 100644 --- a/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java +++ b/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java @@ -46,16 +46,13 @@ public class AsyncronousQuit { return; } - Location loc = player.getLocation(); String ip = plugin.getIP(player); if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead()) { if (Settings.isSaveQuitLocationEnabled && database.isAuthAvailable(name)) { - final PlayerAuth auth = new PlayerAuth(name, loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName(), player.getName()); - try { - database.updateQuitLoc(auth); - } catch (NullPointerException npe) { - } + Location loc = player.getLocation(); + PlayerAuth auth = new PlayerAuth(name, loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName(), player.getName()); + database.updateQuitLoc(auth); } PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName()); database.updateSession(auth); @@ -78,19 +75,19 @@ public class AsyncronousQuit { LimboCache.getInstance().deleteLimboPlayer(name); } if (Settings.isSessionsEnabled && !isKick) { - if (Settings.getSessionTimeout != 0){ - BukkitTask task = plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - PlayerCache.getInstance().removePlayer(name); - if (database.isLogged(name)) - database.setUnlogged(name); - plugin.sessions.remove(name); - } - - }, Settings.getSessionTimeout * 20 * 60); - plugin.sessions.put(name, task); + if (Settings.getSessionTimeout != 0) { + BukkitTask task = plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + PlayerCache.getInstance().removePlayer(name); + if (database.isLogged(name)) + database.setUnlogged(name); + plugin.sessions.remove(name); + } + + }, Settings.getSessionTimeout * 20 * 60); + plugin.sessions.put(name, task); } } else { PlayerCache.getInstance().removePlayer(name); From 5ed134b172701fa1da748e1dddb55066e34c0436 Mon Sep 17 00:00:00 2001 From: Xephi59 Date: Fri, 31 Jul 2015 14:55:47 +0200 Subject: [PATCH 6/6] Fix SaveQuitLoc, idk why spigot handle quit player as dead player --- src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java b/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java index 82ff826b..585ab6fa 100644 --- a/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java +++ b/src/main/java/fr/xephi/authme/process/quit/AsyncronousQuit.java @@ -48,7 +48,7 @@ public class AsyncronousQuit { String ip = plugin.getIP(player); - if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead()) { + if (PlayerCache.getInstance().isAuthenticated(name)) { if (Settings.isSaveQuitLocationEnabled && database.isAuthAvailable(name)) { Location loc = player.getLocation(); PlayerAuth auth = new PlayerAuth(name, loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName(), player.getName());