Revert "Implement usage of SQL connection pooling in RepositoryBase to prevent unnecessary idle connections."

This reverts commit adfe5fb74e.
This commit is contained in:
Ty Sayers 2015-03-07 19:38:06 -05:00
parent adfe5fb74e
commit 215ec7b00d
13 changed files with 251 additions and 122 deletions

View File

@ -19,7 +19,6 @@ import mineplex.core.common.Rank;
import mineplex.core.common.util.Callback; import mineplex.core.common.util.Callback;
import mineplex.core.common.util.NautHashMap; import mineplex.core.common.util.NautHashMap;
import mineplex.core.common.util.UUIDFetcher; import mineplex.core.common.util.UUIDFetcher;
import mineplex.core.database.DBPool;
import mineplex.core.database.DatabaseRunnable; import mineplex.core.database.DatabaseRunnable;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
@ -44,7 +43,7 @@ public class AccountRepository extends RepositoryBase
public AccountRepository(JavaPlugin plugin, String webAddress) public AccountRepository(JavaPlugin plugin, String webAddress)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true", "root", "tAbechAk3wR7tuTh");
_webAddress = webAddress; _webAddress = webAddress;

View File

@ -3,7 +3,6 @@ package mineplex.core.benefit;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnVarChar; import mineplex.core.database.column.ColumnVarChar;
@ -17,7 +16,7 @@ public class BenefitManagerRepository extends RepositoryBase
public BenefitManagerRepository(JavaPlugin plugin) public BenefitManagerRepository(JavaPlugin plugin)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
} }
@Override @Override

View File

@ -22,29 +22,58 @@ import org.bukkit.plugin.java.JavaPlugin;
public abstract class RepositoryBase implements Listener public abstract class RepositoryBase implements Listener
{ {
// Queue for failed processes protected static Object _connectionLock = new Object();
private Connection _connection = null;
private static Object _queueLock = new Object(); private static Object _queueLock = new Object();
private NautHashMap<DatabaseRunnable, String> _failedQueue = new NautHashMap<DatabaseRunnable, String>(); private NautHashMap<DatabaseRunnable, String> _failedQueue = new NautHashMap<DatabaseRunnable, String>();
private DataSource _dataSource; // Connection pool private String _connectionString;
protected JavaPlugin Plugin; // Plugin responsible for this repository private String _userName;
private String _password;
/** protected JavaPlugin Plugin;
* Constructor protected DataSource DataSource;
* @param plugin - the {@link JavaPlugin} module responsible for this repository.
* @param dataSource - the {@link DataSource} responsible for providing the connection pool to this repository. public RepositoryBase(JavaPlugin plugin, String connectionString, String username, String password)
*/
public RepositoryBase(JavaPlugin plugin, DataSource dataSource)
{ {
Plugin = plugin; Plugin = plugin;
_dataSource = dataSource;
_connectionString = connectionString;
_userName = username;
_password = password;
Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable()
{ {
public void run() public void run()
{ {
initialize(); synchronized (_connectionLock)
update(); {
initialize();
update();
}
}
});
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
public RepositoryBase(JavaPlugin plugin, DataSource dataSource)
{
Plugin = plugin;
DataSource = dataSource;
Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable()
{
public void run()
{
synchronized (_connectionLock)
{
initialize();
update();
}
} }
}); });
@ -55,39 +84,34 @@ public abstract class RepositoryBase implements Listener
protected abstract void update(); protected abstract void update();
/**
* @return the {@link DataSource} used by the repository for connection pooling.
*/
protected DataSource getConnectionPool()
{
return _dataSource;
}
/**
* Requirements: {@link Connection}s must be closed after usage so they may be returned to the pool!
* @see Connection#close()
* @return a newly fetched {@link Connection} from the connection pool, if a connection can be made, null otherwise.
*/
protected Connection getConnection() protected Connection getConnection()
{ {
try return getConnection(false);
{ }
return _dataSource.getConnection();
} protected Connection getConnection(boolean validate)
catch (SQLException e) {
{ synchronized (_connectionLock)
e.printStackTrace(); {
// TODO: Log connection failures? try
return null; {
} if (_connection == null || (validate && !_connection.isValid(2)))
{
if (DataSource != null)
_connection = DataSource.getConnection();
else
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
return _connection;
} }
/**
* Execute a query against the repository.
* @param query - the concatenated query to execute in string form.
* @param columns - the column data values used for insertion into the query.
* @return the number of rows affected by this query in the repository.
*/
protected int executeUpdate(String query, Column<?>...columns) protected int executeUpdate(String query, Column<?>...columns)
{ {
return executeInsert(query, null, columns); return executeInsert(query, null, columns);
@ -95,14 +119,16 @@ public abstract class RepositoryBase implements Listener
protected int executeInsert(String query, ResultSetCallable callable, Column<?>...columns) protected int executeInsert(String query, ResultSetCallable callable, Column<?>...columns)
{ {
PreparedStatement preparedStatement = null;
int affectedRows = 0; int affectedRows = 0;
// Automatic resource management for handling/closing objects. try
try (
Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)
)
{ {
getConnection(false);
preparedStatement = _connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
for (int i=0; i < columns.length; i++) for (int i=0; i < columns.length; i++)
{ {
columns[i].setValue(preparedStatement, i+1); columns[i].setValue(preparedStatement, i+1);
@ -111,66 +137,168 @@ public abstract class RepositoryBase implements Listener
affectedRows = preparedStatement.executeUpdate(); affectedRows = preparedStatement.executeUpdate();
if (callable != null) if (callable != null)
{
callable.processResultSet(preparedStatement.getGeneratedKeys()); callable.processResultSet(preparedStatement.getGeneratedKeys());
}
} }
catch (SQLException exception) catch (SQLException exception)
{ {
getConnection(true);
executeInsert(query, callable, columns); executeInsert(query, callable, columns);
} }
catch (Exception exception) catch (Exception exception)
{ {
exception.printStackTrace(); exception.printStackTrace();
} }
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
try
{
if (DataSource != null)
_connection.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
return affectedRows;
}
protected void executeQuery(PreparedStatement statement, ResultSetCallable callable, Column<?>...columns)
{
ResultSet resultSet = null;
try
{
for (int i=0; i < columns.length; i++)
{
columns[i].setValue(statement, i+1);
}
resultSet = statement.executeQuery();
callable.processResultSet(resultSet);
}
catch (SQLException exception)
{
getConnection(true);
executeQuery(statement, callable, columns);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (resultSet != null)
{
try
{
resultSet.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
try
{
if (DataSource != null)
_connection.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
protected void executeQuery(String query, ResultSetCallable callable, Column<?>...columns)
{
PreparedStatement preparedStatement = null;
try
{
getConnection(false);
preparedStatement = _connection.prepareStatement(query);
executeQuery(preparedStatement, callable, columns);
}
catch (SQLException exception)
{
getConnection(true);
executeQuery(query, callable, columns);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
try
{
if (DataSource != null)
_connection.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
protected int executeUpdate(PreparedStatement preparedStatement, Column<?>...columns)
{
int affectedRows = 0;
try
{
for (int i=0; i < columns.length; i++)
{
columns[i].setValue(preparedStatement, i+1);
}
affectedRows = preparedStatement.executeUpdate();
}
catch (SQLException exception)
{
getConnection(true);
executeUpdate(preparedStatement, columns);
}
catch (Exception exception)
{
exception.printStackTrace();
}
return affectedRows; return affectedRows;
} }
protected void executeQuery(PreparedStatement statement, ResultSetCallable callable, Column<?>...columns)
{
try
{
for (int i=0; i < columns.length; i++)
{
columns[i].setValue(statement, i+1);
}
try (ResultSet resultSet = statement.executeQuery())
{
callable.processResultSet(resultSet);
}
}
catch (SQLException exception)
{
executeQuery(statement, callable, columns);
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
protected void executeQuery(String query, ResultSetCallable callable, Column<?>...columns)
{
// Automatic resource management for handling/closing objects.
try (
Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)
)
{
executeQuery(preparedStatement, callable, columns);
}
catch (SQLException exception)
{
executeQuery(query, callable, columns);
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
protected void handleDatabaseCall(final DatabaseRunnable databaseRunnable, final String errorMessage) protected void handleDatabaseCall(final DatabaseRunnable databaseRunnable, final String errorMessage)
{ {
Thread asyncThread = new Thread(new Runnable() Thread asyncThread = new Thread(new Runnable()
@ -216,7 +344,19 @@ public abstract class RepositoryBase implements Listener
@EventHandler @EventHandler
public void validateConnection(UpdateEvent event) public void validateConnection(UpdateEvent event)
{ {
// Utilizes DataSource connection pools, so there is no connection to validate. if (event.getType() != UpdateType.MIN_02 || DataSource != null)
return;
Bukkit.getScheduler().runTaskAsynchronously(Plugin, new Runnable()
{
public void run()
{
synchronized (_connectionLock)
{
getConnection(true);
}
}
});
} }
private void processFailedQueue() private void processFailedQueue()

View File

@ -8,7 +8,6 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.common.util.Callback; import mineplex.core.common.util.Callback;
import mineplex.core.database.DBPool;
import mineplex.core.database.DatabaseRunnable; import mineplex.core.database.DatabaseRunnable;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt; import mineplex.core.database.column.ColumnInt;
@ -34,7 +33,7 @@ public class DonationRepository extends RepositoryBase
public DonationRepository(JavaPlugin plugin, String webAddress) public DonationRepository(JavaPlugin plugin, String webAddress)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
_webAddress = webAddress; _webAddress = webAddress;
} }

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnInt; import mineplex.core.database.column.ColumnInt;
@ -32,7 +31,7 @@ public class InventoryRepository extends RepositoryBase
public InventoryRepository(JavaPlugin plugin) public InventoryRepository(JavaPlugin plugin)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
} }
@Override @Override

View File

@ -1,6 +1,5 @@
package mineplex.core.leaderboard; package mineplex.core.leaderboard;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt; import mineplex.core.database.column.ColumnInt;
import mineplex.core.database.column.ColumnVarChar; import mineplex.core.database.column.ColumnVarChar;
@ -36,7 +35,7 @@ public class StatEventsRepository extends RepositoryBase
*/ */
public StatEventsRepository(JavaPlugin plugin) public StatEventsRepository(JavaPlugin plugin)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
} }
@Override @Override

View File

@ -7,7 +7,6 @@ import java.util.UUID;
import java.util.Map.Entry; import java.util.Map.Entry;
import mineplex.core.common.util.NautHashMap; import mineplex.core.common.util.NautHashMap;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnInt; import mineplex.core.database.column.ColumnInt;
@ -41,7 +40,7 @@ This will be used to determine if staff are handling
public ReportRepository(JavaPlugin plugin, String connectionString) public ReportRepository(JavaPlugin plugin, String connectionString)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, connectionString, "root", "tAbechAk3wR7tuTh"); // TODO: Config file for host/pass?
} }
@Override @Override

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnVarChar; import mineplex.core.database.column.ColumnVarChar;
@ -23,7 +22,8 @@ public class SpawnRepository extends RepositoryBase
public SpawnRepository(JavaPlugin plugin, String serverName) public SpawnRepository(JavaPlugin plugin, String serverName)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
_serverName = serverName; _serverName = serverName;
} }

View File

@ -9,7 +9,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.common.util.NautHashMap; import mineplex.core.common.util.NautHashMap;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnVarChar; import mineplex.core.database.column.ColumnVarChar;
@ -19,7 +18,6 @@ import org.jooq.DSLContext;
import org.jooq.Insert; import org.jooq.Insert;
import org.jooq.Record2; import org.jooq.Record2;
import org.jooq.Result; import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.Update; import org.jooq.Update;
import org.jooq.impl.DSL; import org.jooq.impl.DSL;
@ -33,7 +31,7 @@ public class StatsRepository extends RepositoryBase
public StatsRepository(JavaPlugin plugin) public StatsRepository(JavaPlugin plugin)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
} }
@Override @Override
@ -81,7 +79,8 @@ public class StatsRepository extends RepositoryBase
{ {
try try
{ {
DSLContext context = DSL.using(getConnectionPool(), SQLDialect.MYSQL);
DSLContext context = DSL.using(getConnection(true));
List<Update> updates = new ArrayList<>(); List<Update> updates = new ArrayList<>();
List<Insert> inserts = new ArrayList<>(); List<Insert> inserts = new ArrayList<>();
@ -134,7 +133,7 @@ public class StatsRepository extends RepositoryBase
synchronized (this) synchronized (this)
{ {
context = DSL.using(getConnectionPool(), SQLDialect.MYSQL); context = DSL.using(getConnection());
} }
Result<Record2<String, Integer>> result = context.select(Tables.stats.name, Tables.accountStats.value).from(Tables.accountStats) Result<Record2<String, Integer>> result = context.select(Tables.stats.name, Tables.accountStats.value).from(Tables.accountStats)

View File

@ -2,7 +2,6 @@ package mineplex.enjinTranslator;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt; import mineplex.core.database.column.ColumnInt;
import mineplex.core.database.column.ColumnVarChar; import mineplex.core.database.column.ColumnVarChar;
@ -13,7 +12,7 @@ public class TempRepository extends RepositoryBase
public TempRepository(JavaPlugin plugin) public TempRepository(JavaPlugin plugin)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
} }
public void addGemBooster(String name, int amount) public void addGemBooster(String name, int amount)

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnByte; import mineplex.core.database.column.ColumnByte;
@ -32,7 +31,7 @@ public class FieldRepository extends RepositoryBase
public FieldRepository(JavaPlugin plugin) public FieldRepository(JavaPlugin plugin)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
} }
public List<FieldBlockToken> getFieldBlocks(String server) public List<FieldBlockToken> getFieldBlocks(String server)

View File

@ -6,11 +6,9 @@ import java.util.UUID;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.database.Tables; import mineplex.database.Tables;
import mineplex.database.tables.records.MailRecord; import mineplex.database.tables.records.MailRecord;
import org.jooq.DSLContext; import org.jooq.DSLContext;
import org.jooq.Result; import org.jooq.Result;
import org.jooq.impl.DSL; import org.jooq.impl.DSL;
@ -21,8 +19,8 @@ public class MailRepository extends RepositoryBase
public MailRepository(JavaPlugin plugin, MailManager manager) public MailRepository(JavaPlugin plugin, MailManager manager)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
_manager = manager; _manager = manager;
} }

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase; import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable; import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnVarChar; import mineplex.core.database.column.ColumnVarChar;
@ -24,7 +23,8 @@ public class PasswordRepository extends RepositoryBase
public PasswordRepository(JavaPlugin plugin, String serverName) public PasswordRepository(JavaPlugin plugin, String serverName)
{ {
super(plugin, DBPool.ACCOUNT); super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
_serverName = serverName; _serverName = serverName;
} }