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.NautHashMap;
import mineplex.core.common.util.UUIDFetcher;
import mineplex.core.database.DBPool;
import mineplex.core.database.DatabaseRunnable;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
@ -44,7 +43,7 @@ public class AccountRepository extends RepositoryBase
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;

View File

@ -3,7 +3,6 @@ package mineplex.core.benefit;
import java.sql.ResultSet;
import java.sql.SQLException;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnVarChar;
@ -17,7 +16,7 @@ public class BenefitManagerRepository extends RepositoryBase
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

View File

@ -22,29 +22,58 @@ import org.bukkit.plugin.java.JavaPlugin;
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 NautHashMap<DatabaseRunnable, String> _failedQueue = new NautHashMap<DatabaseRunnable, String>();
private DataSource _dataSource; // Connection pool
protected JavaPlugin Plugin; // Plugin responsible for this repository
private String _connectionString;
private String _userName;
private String _password;
/**
* Constructor
* @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, DataSource dataSource)
protected JavaPlugin Plugin;
protected DataSource DataSource;
public RepositoryBase(JavaPlugin plugin, String connectionString, String username, String password)
{
Plugin = plugin;
_dataSource = dataSource;
_connectionString = connectionString;
_userName = username;
_password = password;
Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable()
{
public void run()
{
initialize();
update();
synchronized (_connectionLock)
{
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();
/**
* @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()
{
try
{
return _dataSource.getConnection();
}
catch (SQLException e)
{
e.printStackTrace();
// TODO: Log connection failures?
return null;
}
return getConnection(false);
}
protected Connection getConnection(boolean validate)
{
synchronized (_connectionLock)
{
try
{
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)
{
return executeInsert(query, null, columns);
@ -95,14 +119,16 @@ public abstract class RepositoryBase implements Listener
protected int executeInsert(String query, ResultSetCallable callable, Column<?>...columns)
{
PreparedStatement preparedStatement = null;
int affectedRows = 0;
// Automatic resource management for handling/closing objects.
try (
Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)
)
try
{
getConnection(false);
preparedStatement = _connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
for (int i=0; i < columns.length; i++)
{
columns[i].setValue(preparedStatement, i+1);
@ -111,66 +137,168 @@ public abstract class RepositoryBase implements Listener
affectedRows = preparedStatement.executeUpdate();
if (callable != null)
{
callable.processResultSet(preparedStatement.getGeneratedKeys());
}
}
catch (SQLException exception)
{
getConnection(true);
executeInsert(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();
}
}
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;
}
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)
{
Thread asyncThread = new Thread(new Runnable()
@ -216,7 +344,19 @@ public abstract class RepositoryBase implements Listener
@EventHandler
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()

View File

@ -8,7 +8,6 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.common.util.Callback;
import mineplex.core.database.DBPool;
import mineplex.core.database.DatabaseRunnable;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt;
@ -34,7 +33,7 @@ public class DonationRepository extends RepositoryBase
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;
}

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnInt;
@ -32,7 +31,7 @@ public class InventoryRepository extends RepositoryBase
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

View File

@ -1,6 +1,5 @@
package mineplex.core.leaderboard;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt;
import mineplex.core.database.column.ColumnVarChar;
@ -36,7 +35,7 @@ public class StatEventsRepository extends RepositoryBase
*/
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

View File

@ -7,7 +7,6 @@ import java.util.UUID;
import java.util.Map.Entry;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
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)
{
super(plugin, DBPool.ACCOUNT);
super(plugin, connectionString, "root", "tAbechAk3wR7tuTh"); // TODO: Config file for host/pass?
}
@Override

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnVarChar;
@ -23,7 +22,8 @@ public class SpawnRepository extends RepositoryBase
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;
}

View File

@ -9,7 +9,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnVarChar;
@ -19,7 +18,6 @@ import org.jooq.DSLContext;
import org.jooq.Insert;
import org.jooq.Record2;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.Update;
import org.jooq.impl.DSL;
@ -33,7 +31,7 @@ public class StatsRepository extends RepositoryBase
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
@ -81,7 +79,8 @@ public class StatsRepository extends RepositoryBase
{
try
{
DSLContext context = DSL.using(getConnectionPool(), SQLDialect.MYSQL);
DSLContext context = DSL.using(getConnection(true));
List<Update> updates = new ArrayList<>();
List<Insert> inserts = new ArrayList<>();
@ -134,7 +133,7 @@ public class StatsRepository extends RepositoryBase
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)

View File

@ -2,7 +2,6 @@ package mineplex.enjinTranslator;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt;
import mineplex.core.database.column.ColumnVarChar;
@ -13,7 +12,7 @@ public class TempRepository extends RepositoryBase
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)

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnByte;
@ -32,7 +31,7 @@ public class FieldRepository extends RepositoryBase
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)

View File

@ -6,11 +6,9 @@ import java.util.UUID;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.database.Tables;
import mineplex.database.tables.records.MailRecord;
import org.jooq.DSLContext;
import org.jooq.Result;
import org.jooq.impl.DSL;
@ -21,8 +19,8 @@ public class MailRepository extends RepositoryBase
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;
}

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.database.DBPool;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.ResultSetCallable;
import mineplex.core.database.column.ColumnVarChar;
@ -24,7 +23,8 @@ public class PasswordRepository extends RepositoryBase
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;
}