From d64d1eed4e8d764263ad78f80c12b6481cec607f Mon Sep 17 00:00:00 2001 From: AlexTheCoder Date: Fri, 3 Nov 2017 19:07:50 -0400 Subject: [PATCH] Fix merge conflicts --- .../core/leaderboard/Leaderboard.java | 4 +- .../leaderboard/LeaderboardRepository.java | 14 +- .../src/mineplex/core/stats/StatsManager.java | 81 ++++++--- .../mineplex/core/stats/StatsRepository.java | 46 ++++- Tools/Stat Conversion/pom.xml | 62 +++++++ .../src/com/mineplex/statconverter/Main.java | 168 ++++++++++++++++++ .../statconverter/database/mysql/DBPool.java | 90 ++++++++++ 7 files changed, 432 insertions(+), 33 deletions(-) create mode 100644 Tools/Stat Conversion/pom.xml create mode 100644 Tools/Stat Conversion/src/com/mineplex/statconverter/Main.java create mode 100644 Tools/Stat Conversion/src/com/mineplex/statconverter/database/mysql/DBPool.java diff --git a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/Leaderboard.java b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/Leaderboard.java index fd72e005b..35ab29376 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/Leaderboard.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/Leaderboard.java @@ -71,14 +71,14 @@ public class Leaderboard return _type; } - public void update(Map names) + public void update(Map names) { deconstruct(); LinkedList display = new LinkedList<>(); display.add(C.cAqua + _display); display.add(C.cRed + " "); int place = _start + 1; - for (Entry entry : names.entrySet()) + for (Entry entry : names.entrySet()) { if (entry.getValue() == 1) { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java index 4ef0e86cf..d16d3e3e6 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java @@ -127,11 +127,11 @@ public class LeaderboardRepository extends RepositoryBase }); } - public void loadLeaderboard(Leaderboard board, Consumer> leaderboard) + public void loadLeaderboard(Leaderboard board, Consumer> leaderboard) { UtilServer.runAsync(() -> { - Map names = new LinkedHashMap<>(); + Map names = new LinkedHashMap<>(); try ( Connection c = getConnection(); Statement s = c.createStatement(); @@ -144,9 +144,9 @@ public class LeaderboardRepository extends RepositoryBase { while (rs.next()) { - names.merge(rs.getString("name"), rs.getInt("value"), Integer::sum); + names.merge(rs.getString("name"), rs.getLong("value"), Long::sum); } - + if (!s.getMoreResults()) { break; @@ -166,11 +166,11 @@ public class LeaderboardRepository extends RepositoryBase } @SuppressWarnings("unchecked") - public void loadLeaderboards(Collection boards, Consumer[]> leaderboard) + public void loadLeaderboards(Collection boards, Consumer[]> leaderboard) { UtilServer.runAsync(() -> { - Map[] leaderboards = new Map[boards.size()]; + Map[] leaderboards = new Map[boards.size()]; StringBuilder queryBuilder = new StringBuilder(); { int i = 0; @@ -199,7 +199,7 @@ public class LeaderboardRepository extends RepositoryBase { while (rs.next()) { - leaderboards[index].merge(rs.getString("name"), rs.getInt("value"), Integer::sum); + leaderboards[index].merge(rs.getString("name"), rs.getLong("value"), Long::sum); } if (!s.getMoreResults()) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java index ef89dd72a..8533477c8 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.Future; @@ -21,12 +22,12 @@ import mineplex.core.account.CoreClient; import mineplex.core.account.CoreClientManager; import mineplex.core.account.permissions.Permission; import mineplex.core.account.permissions.PermissionGroup; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilServer; import mineplex.core.common.util.UtilTasks; import mineplex.core.leaderboard.LeaderboardManager; import mineplex.core.stats.command.GiveStatCommand; -import mineplex.core.stats.command.MasterBuilderUnban; -import mineplex.core.stats.command.SetLevelCommand; import mineplex.core.stats.command.TimeCommand; import mineplex.core.stats.event.StatChangeEvent; import mineplex.core.thread.ThreadPool; @@ -69,12 +70,12 @@ public class StatsManager extends MiniDbClientPlugin { save(_statUploadQueue, map -> { - _repository.saveStats(map); + //_repository.saveStats(map); _leaderboard.handleStatIncrease(map); }, "increment"); save(_statUploadQueueOverRidable, map -> { - _repository.saveStats(map, true); + //_repository.saveStats(map, true); _leaderboard.handleStatIncrease(map); }, "override"); }); @@ -89,7 +90,6 @@ public class StatsManager extends MiniDbClientPlugin private void generatePermissions() { - PermissionGroup.ADMIN.setPermission(Perm.GIVE_STAT_COMMAND, true, true); PermissionGroup.MOD.setPermission(Perm.TIME_COMMAND, true, true); PermissionGroup.ADMIN.setPermission(Perm.SET_LEVEL_COMMAND, true, true); @@ -297,18 +297,22 @@ public class StatsManager extends MiniDbClientPlugin if (callback != null) callback.run(); return; } - - _repository.registerNewStat(statName); - - _stats.clear(); - - for (Stat stat : _repository.retrieveStats()) - { - _stats.put(stat.getName(), stat.getId()); - } - - if (callback != null) callback.run(); } + + _repository.registerNewStat(statName, () -> + { + synchronized(STATS_LOCK) + { + _stats.clear(); + + for (Stat stat : _repository.retrieveStats()) + { + _stats.put(stat.getName(), stat.getId()); + } + + if (callback != null) callback.run(); + } + }); }); } @@ -332,6 +336,43 @@ public class StatsManager extends MiniDbClientPlugin { setStat(event.getPlayer(), stat, 0); }); + + final UUID uuid = event.getPlayer().getUniqueId(); + final int accountId = _coreClientManager.getAccountId(event.getPlayer()); + UtilPlayer.message(event.getPlayer(), F.main(getName(), "We are currently converting to a different stat storage method, please wait a moment if your stats are not all present!")); + runAsync(() -> + { + _repository.loadStatsFromOld(accountId, statMap -> + { + if (Bukkit.getPlayer(uuid) == null) + { + return; + } + boolean conversionOccurred = false; + Map currentMap = Get(event.getPlayer()).getStats(); + for (Entry oldEntry : statMap.entrySet()) + { + if (currentMap.containsKey(oldEntry.getKey())) + { + if (currentMap.get(oldEntry.getKey()) < oldEntry.getValue()) + { + conversionOccurred = true; + Long diff = oldEntry.getValue() - currentMap.get(oldEntry.getKey()); + incrementStat(event.getPlayer(), oldEntry.getKey(), diff); + } + } + else + { + conversionOccurred = true; + incrementStat(event.getPlayer(), oldEntry.getKey(), oldEntry.getValue()); + } + } + if (conversionOccurred) + { + UtilPlayer.message(event.getPlayer(), F.main(getName(), "Your old stats have been converted!")); + } + }); + }); } @Override @@ -339,8 +380,8 @@ public class StatsManager extends MiniDbClientPlugin { addCommand(new TimeCommand(this)); addCommand(new GiveStatCommand(this)); - addCommand(new SetLevelCommand(this)); - addCommand(new MasterBuilderUnban(this)); + //addCommand(new SetLevelCommand(this)); + //addCommand(new MasterBuilderUnban(this)); } @Override @@ -373,6 +414,6 @@ public class StatsManager extends MiniDbClientPlugin @Override public String getQuery(int accountId, String uuid, String name) { - return "SELECT stats.name, value FROM accountStat INNER JOIN stats ON stats.id = accountStat.statId WHERE accountStat.accountId = '" + accountId + "';"; + return "SELECT stats.name, value FROM accountStatsAllTime INNER JOIN stats ON stats.id = accountStatsAllTime.statId WHERE accountStatsAllTime.accountId = '" + accountId + "';"; } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java index 518021120..29fb25b29 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java @@ -1,10 +1,14 @@ package mineplex.core.stats; +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.Consumer; import org.jooq.DSLContext; import org.jooq.Insert; @@ -15,10 +19,11 @@ import org.jooq.Update; import org.jooq.impl.DSL; import org.jooq.types.ULong; -import mineplex.core.database.MinecraftRepository; +import mineplex.core.common.util.UtilServer; import mineplex.database.Tables; import mineplex.serverdata.database.DBPool; import mineplex.serverdata.database.RepositoryBase; +import mineplex.serverdata.database.column.ColumnInt; import mineplex.serverdata.database.column.ColumnVarChar; public class StatsRepository extends RepositoryBase @@ -30,6 +35,20 @@ public class StatsRepository extends RepositoryBase { super(DBPool.getAccount()); } + + public void loadStatsFromOld(int accountId, Consumer> callback) + { + executeQuery("SELECT stats.name, value FROM accountStat INNER JOIN stats ON stats.id = accountStat.statId WHERE accountStat.accountId=?;", rs -> + { + final Map statMap = new HashMap<>(); + while (rs.next()) + { + statMap.put(rs.getString(1), rs.getLong(2)); + } + + UtilServer.runSync(() -> callback.accept(statMap)); + }, new ColumnInt("accountId", accountId)); + } /** * Retrieves all the remote registered stats @@ -56,9 +75,28 @@ public class StatsRepository extends RepositoryBase * * @param name The name of the stat */ - public void registerNewStat(String name) + public void registerNewStat(String name, Runnable onComplete) { - executeUpdate(INSERT_STAT, new ColumnVarChar("name", 100, name)); + try (Connection c = getConnection()) + { + executeInsert(c, "INSERT INTO stats (name) VALUES (?);", rs -> + { + if (rs.next()) + { + final int id = rs.getInt(1); + try (CallableStatement cs = c.prepareCall("{call accountStatsCreateBucketData(?)}")) + { + cs.setInt("stat", id); + cs.execute(); + onComplete.run(); + } + } + }, () -> {}, new ColumnVarChar("name", 100, name)); + } + catch (SQLException e) + { + e.printStackTrace(); + } } /** diff --git a/Tools/Stat Conversion/pom.xml b/Tools/Stat Conversion/pom.xml new file mode 100644 index 000000000..35a7e7c85 --- /dev/null +++ b/Tools/Stat Conversion/pom.xml @@ -0,0 +1,62 @@ + + 4.0.0 + StatConverter + StatConverter + 1.0 + + src + + + src + + **/*.java + + + + + + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + + + package + + shade + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + maven-plugin + + + org.apache.commons + commons-dbcp2 + 2.0.1 + compile + + + mysql + mysql-connector-java + 5.1.14 + compile + + + \ No newline at end of file diff --git a/Tools/Stat Conversion/src/com/mineplex/statconverter/Main.java b/Tools/Stat Conversion/src/com/mineplex/statconverter/Main.java new file mode 100644 index 000000000..9d11e0d62 --- /dev/null +++ b/Tools/Stat Conversion/src/com/mineplex/statconverter/Main.java @@ -0,0 +1,168 @@ +package com.mineplex.statconverter; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.io.Files; +import com.mineplex.statconverter.database.mysql.DBPool; + +public class Main +{ + public static void main(String[] args) + { + new Main(); + } + + private File _info; + + public Main() + { + int start = 0; + try + { + _info = new File(new File(".").getCanonicalPath() + File.separator + "converterInfo.dat"); + System.out.println(_info.getCanonicalPath()); + if (_info.exists()) + { + String startStr = Files.readFirstLine(_info, Charset.defaultCharset()); + if (startStr != null && !startStr.isEmpty()) + { + start = Integer.parseInt(startStr); + } + } + else + { + _info.createNewFile(); + Files.write("0".getBytes(), _info); + } + + convertGroup(start); + } + catch (IOException e) + { + e.printStackTrace(); + return; + } + } + + private void convertGroup(int start) + { + System.out.println("[INFO] Starting " + start + " to " + (start + 9999)); + List accounts = new ArrayList<>(); + try (Connection c = DBPool.getDataSource("ACCOUNT_PC").getConnection()) + { + try (Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT DISTINCT accountId FROM accountStat LIMIT " + start + ",10000;") + ) + { + while (rs.next()) + { + accounts.add(rs.getInt("accountId")); + } + } + + if (!accounts.isEmpty()) + { + for (Integer accountId : accounts) + { + Map oldStats = new HashMap<>(); + Map newStats = new HashMap<>(); + try (Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT statId, value FROM accountStat WHERE accountId=" + accountId + ";") + ) + { + while (rs.next()) + { + oldStats.put(rs.getInt("statId"), rs.getLong("value")); + } + } + try (Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT statId, value FROM accountStatsAllTime WHERE accountId=" + accountId + ";") + ) + { + while (rs.next()) + { + newStats.put(rs.getInt("statId"), rs.getLong("value")); + } + } + + for (Entry oldEntry : oldStats.entrySet()) + { + if (newStats.containsKey(oldEntry.getKey())) + { + if (newStats.get(oldEntry.getKey()) < oldEntry.getValue()) + { + try (Statement s = c.createStatement()) + { + Long diff = oldEntry.getValue() - newStats.get(oldEntry.getKey()); + s.execute("UPDATE accountStatsAllTime SET value=value+" + diff + " WHERE accountId=" + accountId + " AND statId=" + oldEntry.getKey() + ";"); + } + } + } + else + { + try (Statement s = c.createStatement()) + { + s.execute("INSERT INTO accountStatsAllTime (accountId, statId, value) VALUES (" + accountId + ", " + oldEntry.getKey() + ", " + oldEntry.getValue() + ");"); + } + } + } + + try (Statement s = c.createStatement()) + { + s.execute("DELETE FROM accountStat WHERE accountId=" + accountId + ";"); + } + } + complete(start); + } + else + { + System.out.println("[INFO] Conversion complete"); + while (true) + { + try + { + Thread.sleep(3000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + } + } + catch (SQLException e) + { + e.printStackTrace(); + } + } + + private void complete(int start) + { + int nextStart = start + 10000; + if (_info.delete()) + { + try + { + _info.createNewFile(); + Files.write((nextStart + "").getBytes(), _info); + System.out.println("[INFO] Completed " + start + " to " + (nextStart - 1)); + } + catch (IOException e) + { + e.printStackTrace(); + return; + } + } + } +} \ No newline at end of file diff --git a/Tools/Stat Conversion/src/com/mineplex/statconverter/database/mysql/DBPool.java b/Tools/Stat Conversion/src/com/mineplex/statconverter/database/mysql/DBPool.java new file mode 100644 index 000000000..4b15cc82b --- /dev/null +++ b/Tools/Stat Conversion/src/com/mineplex/statconverter/database/mysql/DBPool.java @@ -0,0 +1,90 @@ +package com.mineplex.statconverter.database.mysql; + +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.sql.Connection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.sql.DataSource; + +import org.apache.commons.dbcp2.BasicDataSource; + +public final class DBPool +{ + private static final Map _dataSources = new ConcurrentHashMap<>(); + + public static DataSource getDataSource(String databaseId) + { + if (_dataSources == null || _dataSources.isEmpty()) + { + loadDataSources(); + } + return _dataSources.get(databaseId); + } + + private static DataSource openDataSource(String url, String username, String password) + { + BasicDataSource source = new BasicDataSource(); + source.addConnectionProperty("autoReconnect", "true"); + source.addConnectionProperty("allowMultiQueries", "true"); + source.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); + source.setDriverClassName("com.mysql.jdbc.Driver"); + source.setUrl(url); + source.setUsername(username); + source.setPassword(password); + source.setMaxTotal(3); + source.setMaxIdle(3); + source.setTimeBetweenEvictionRunsMillis(180 * 1000); + source.setSoftMinEvictableIdleTimeMillis(180 * 1000); + + return source; + } + + private static void loadDataSources() + { + Map dataSources = new HashMap<>(); + try + { + File configFile = new File(new File(".").getCanonicalPath() + File.separator + "database-config.dat"); + + if (configFile.exists()) + { + List lines = Files.readAllLines(configFile.toPath(), + Charset.defaultCharset()); + + for (String line : lines) + { + String[] args = line.split(" "); + + if (args.length == 4) + { + String dbId = args[0]; + String dbHost = args[1]; + String userName = args[2]; + String password = args[3]; + + dataSources.put(dbId, openDataSource("jdbc:mysql://" + dbHost, userName, password)); + } + } + } + else + { + System.out.println("database-config.dat not found at " + + configFile.toPath().toString()); + } + } + catch (Exception exception) + { + exception.printStackTrace(); + System.out.println("---Unable To Parse DBPOOL Configuration File---"); + } + + _dataSources.replaceAll((database, source) -> dataSources.getOrDefault(database, source)); + dataSources.forEach((database, source) -> _dataSources.putIfAbsent(database, source)); + _dataSources.entrySet().removeIf(entry -> !dataSources.containsKey(entry.getKey())); + } +} \ No newline at end of file