From d8ad519cd005970447886f17d9a3fce85fb5b513 Mon Sep 17 00:00:00 2001 From: t00thpick1 Date: Tue, 19 Aug 2014 17:57:52 -0400 Subject: [PATCH] Seperate pools for essential tasks like profile loading and profile saving. --- .../java/com/gmail/nossr50/config/Config.java | 15 +++- .../nossr50/database/SQLDatabaseManager.java | 90 +++++++++++++------ src/main/resources/config.yml | 10 ++- 3 files changed, 85 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/gmail/nossr50/config/Config.java b/src/main/java/com/gmail/nossr50/config/Config.java index ef3213b36..3aa8d1706 100644 --- a/src/main/java/com/gmail/nossr50/config/Config.java +++ b/src/main/java/com/gmail/nossr50/config/Config.java @@ -9,6 +9,7 @@ import org.bukkit.TreeSpecies; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; +import com.gmail.nossr50.database.SQLDatabaseManager.PoolIdentifier; import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.party.PartyFeature; import com.gmail.nossr50.datatypes.skills.AbilityType; @@ -41,6 +42,16 @@ public class Config extends AutoUpdateConfigLoader { reason.add("General.Save_Interval should be greater than 0!"); } + /* MySQL Settings */ + for (PoolIdentifier identifier : PoolIdentifier.values()) { + if (getMySQLMaxConnections(identifier) <= 0) { + reason.add("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()) + " should be greater than 0!"); + } + if (getMySQLMaxPoolSize(identifier) <= 0) { + reason.add("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()) + " should be greater than 0!"); + } + } + /* Mob Healthbar */ if (getMobHealthbarTime() == 0) { reason.add("Mob_Healthbar.Display_Time cannot be 0! Set to -1 to disable or set a valid value."); @@ -315,8 +326,8 @@ public class Config extends AutoUpdateConfigLoader { public int getMySQLServerPort() { return config.getInt("MySQL.Server.Port", 3306); } public String getMySQLServerName() { return config.getString("MySQL.Server.Address", "localhost"); } public String getMySQLUserPassword() { return getStringIncludingInts("MySQL.Database.User_Password"); } - public int getMySQLMaxConnections() { return config.getInt("MySQL.Database.MaxConnections", 30); } - public int getMySQLMaxPoolSize() { return config.getInt("MySQL.Database.MaxPoolSize", 20); } + public int getMySQLMaxConnections(PoolIdentifier identifier) { return config.getInt("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()), 30); } + public int getMySQLMaxPoolSize(PoolIdentifier identifier) { return config.getInt("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()), 10); } private String getStringIncludingInts(String key) { String str = config.getString(key); diff --git a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java index ce5eb34e7..c9d901fe7 100644 --- a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java @@ -33,14 +33,15 @@ import snaq.db.ConnectionPool; public final class SQLDatabaseManager implements DatabaseManager { private static final String ALL_QUERY_VERSION = "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy"; - private static final String S_ALL_QUERY_STRING = "s.taming+s.mining+s.woodcutting+s.repair+s.unarmed+s.herbalism+s.excavation+s.archery+s.swords+s.axes+s.acrobatics+s.fishing+s.alchemy"; private String tablePrefix = Config.getInstance().getMySQLTablePrefix(); private final int POOL_FETCH_TIMEOUT = 360000; private final Map cachedUserIDs = new HashMap(); - private ConnectionPool connectionPool; + private ConnectionPool miscPool; + private ConnectionPool loadPool; + private ConnectionPool savePool; private ReentrantLock massUpdateLock = new ReentrantLock(); @@ -65,15 +66,33 @@ public final class SQLDatabaseManager implements DatabaseManager { connectionProperties.put("prepStmtCacheSize", "64"); connectionProperties.put("prepStmtCacheSqlLimit", "2048"); connectionProperties.put("useServerPrepStmts", "true"); - connectionPool = new ConnectionPool("mcMMO-Pool", - 1 /*Minimum of one*/, - Config.getInstance().getMySQLMaxPoolSize() /*max pool size */, - Config.getInstance().getMySQLMaxConnections() /*max num connections*/, + miscPool = new ConnectionPool("mcMMO-Misc-Pool", + 0 /*No Minimum really needed*/, + Config.getInstance().getMySQLMaxPoolSize(PoolIdentifier.MISC) /*max pool size */, + Config.getInstance().getMySQLMaxConnections(PoolIdentifier.MISC) /*max num connections*/, 0 /* idle timeout of connections */, connectionString, connectionProperties); - connectionPool.init(); // Init first connection - connectionPool.registerShutdownHook(); // Auto release on jvm exit just in case + loadPool = new ConnectionPool("mcMMO-Load-Pool", + 1 /*Minimum of one*/, + Config.getInstance().getMySQLMaxPoolSize(PoolIdentifier.LOAD) /*max pool size */, + Config.getInstance().getMySQLMaxConnections(PoolIdentifier.LOAD) /*max num connections*/, + 0 /* idle timeout of connections */, + connectionString, + connectionProperties); + savePool = new ConnectionPool("mcMMO-Save-Pool", + 1 /*Minimum of one*/, + Config.getInstance().getMySQLMaxPoolSize(PoolIdentifier.SAVE) /*max pool size */, + Config.getInstance().getMySQLMaxConnections(PoolIdentifier.SAVE) /*max num connections*/, + 0 /* idle timeout of connections */, + connectionString, + connectionProperties); + miscPool.init(); // Init first connection + miscPool.registerShutdownHook(); // Auto release on jvm exit just in case + loadPool.init(); + loadPool.registerShutdownHook(); + savePool.init(); + savePool.registerShutdownHook(); checkStructure(); @@ -88,7 +107,7 @@ public final class SQLDatabaseManager implements DatabaseManager { int purged = 0; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.createStatement(); purged = statement.executeUpdate("DELETE FROM " + tablePrefix + "skills WHERE " @@ -137,7 +156,7 @@ public final class SQLDatabaseManager implements DatabaseManager { int purged = 0; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.createStatement(); purged = statement.executeUpdate("DELETE FROM u, e, h, s, c USING " + tablePrefix + "users u " + @@ -179,7 +198,7 @@ public final class SQLDatabaseManager implements DatabaseManager { PreparedStatement statement = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.prepareStatement("DELETE FROM u, e, h, s, c " + "USING " + tablePrefix + "users u " + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " + @@ -227,7 +246,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.SAVE); int id = getUserID(connection, profile.getPlayerName(), profile.getUniqueId()); @@ -342,7 +361,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.prepareStatement("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT ?, ?"); statement.setInt(1, (pageNumber * statsPerPage) - statsPerPage); statement.setInt(2, statsPerPage); @@ -399,7 +418,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); for (SkillType skillType : SkillType.NON_CHILD_SKILLS) { String skillName = skillType.name().toLowerCase(); String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " + @@ -510,7 +529,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); newUser(connection, playerName, uuid); } catch (SQLException ex) { @@ -590,7 +609,7 @@ public final class SQLDatabaseManager implements DatabaseManager { ResultSet resultSet = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.LOAD); int id = getUserID(connection, playerName, uuid); if (id == -1) { @@ -696,7 +715,7 @@ public final class SQLDatabaseManager implements DatabaseManager { ResultSet resultSet = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.prepareStatement( "SELECT " + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, " @@ -764,7 +783,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.prepareStatement( "UPDATE `" + tablePrefix + "users` SET " + " uuid = ? WHERE user = ?"); @@ -804,7 +823,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.prepareStatement("UPDATE " + tablePrefix + "users SET uuid = ? WHERE user = ?"); for (Map.Entry entry : fetchedUUIDs.entrySet()) { @@ -859,7 +878,7 @@ public final class SQLDatabaseManager implements DatabaseManager { ResultSet resultSet = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.createStatement(); resultSet = statement.executeQuery("SELECT user FROM " + tablePrefix + "users"); while (resultSet.next()) { @@ -910,7 +929,7 @@ public final class SQLDatabaseManager implements DatabaseManager { Connection connection = null; try { - connection = getConnection(); + connection = getConnection(PoolIdentifier.MISC); statement = connection.prepareStatement("SELECT table_name FROM INFORMATION_SCHEMA.TABLES" + " WHERE table_schema = ?" + " AND table_name = ?"); @@ -1070,10 +1089,21 @@ public final class SQLDatabaseManager implements DatabaseManager { } - private Connection getConnection() throws SQLException { - Connection connection = connectionPool.getConnection(POOL_FETCH_TIMEOUT); + private Connection getConnection(PoolIdentifier identifier) throws SQLException { + Connection connection = null; + switch (identifier) { + case LOAD: + connection = loadPool.getConnection(POOL_FETCH_TIMEOUT); + break; + case MISC: + connection = miscPool.getConnection(POOL_FETCH_TIMEOUT); + break; + case SAVE: + connection = savePool.getConnection(POOL_FETCH_TIMEOUT); + break; + } if (connection == null) { - throw new RuntimeException("getConnection() timed out. Increase max connections settings."); + throw new RuntimeException("getConnection() for " + identifier.name().toLowerCase() + " pool timed out. Increase max connections settings."); } return connection; } @@ -1399,7 +1429,7 @@ public final class SQLDatabaseManager implements DatabaseManager { ResultSet resultSet = null; try { try { - connection = connectionPool.getConnection(); + connection = miscPool.getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery("SELECT `user` FROM `" + tablePrefix + "users` WHERE `uuid` IS NULL"); @@ -1563,6 +1593,14 @@ public final class SQLDatabaseManager implements DatabaseManager { @Override public void onDisable() { mcMMO.p.debug("Releasing connection pool resource..."); - connectionPool.release(); + miscPool.release(); + loadPool.release(); + savePool.release(); + } + + public enum PoolIdentifier { + MISC, + LOAD, + SAVE; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3923da078..a0ace507a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -131,10 +131,16 @@ MySQL: TablePrefix: mcmmo_ # This setting is the max simultaneous mysql connections allowed at a time, needs to be # high enough to support multiple player logins in quick succession - MaxConnections: 30 + MaxConnections: + Misc: 30 + Load: 30 + Save: 30 # This setting is the max size of the pool of cached connections that we hold available # at any given time - MaxPoolSize: 20 + MaxPoolSize: + Misc: 10 + Load: 20 + Save: 20 Server: Port: 3306 Address: localhost