diff --git a/Plan/src/main/java/com/djrapitops/plan/Permissions.java b/Plan/src/main/java/com/djrapitops/plan/Permissions.java index 448d88572..1f38dfcd8 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Permissions.java +++ b/Plan/src/main/java/com/djrapitops/plan/Permissions.java @@ -43,9 +43,7 @@ public enum Permissions { } /** - * Returns the permission node in plugin.yml. - *

- * Same as getPermission. + * Same as {@link #getPermission()}. * * @return permission node eg. plan.inspect */ diff --git a/Plan/src/main/java/com/djrapitops/plan/Plan.java b/Plan/src/main/java/com/djrapitops/plan/Plan.java index de7d1b2d0..846cb63eb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Plan.java +++ b/Plan/src/main/java/com/djrapitops/plan/Plan.java @@ -72,7 +72,7 @@ public class Plan extends BukkitPlugin { private HookHandler hookHandler; // Manages 3rd party data sources private Database db; - private HashSet databases; + private Set databases; private WebServer uiServer; @@ -85,8 +85,9 @@ public class Plan extends BukkitPlugin { * @return API of the current instance of Plan. * @throws IllegalStateException If onEnable method has not been called on * Plan and the instance is null. + * @throws NoClassDefFoundError If Plan is not installed. */ - public static API getPlanAPI() throws IllegalStateException { + public static API getPlanAPI() throws IllegalStateException, NoClassDefFoundError { Plan instance = getInstance(); if (instance == null) { throw new IllegalStateException("Plugin not enabled properly, Singleton instance is null."); @@ -110,7 +111,7 @@ public class Plan extends BukkitPlugin { */ @Override public void onEnable() { - // Sets the Required variables for RslPlugin instance to function correctly + // Sets the Required variables for BukkitPlugin instance to function correctly setInstance(this); super.setDebugMode(Settings.DEBUG.toString()); super.setColorScheme(new ColorScheme(Phrase.COLOR_MAIN.color(), Phrase.COLOR_SEC.color(), Phrase.COLOR_TER.color())); diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java index ae7ac4455..9de0bcdae 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java @@ -43,7 +43,7 @@ public class WebCheckCommand extends SubCommand { if (!Check.isTrue(table.userExists(user), ChatColor.RED + "[Plan] User Doesn't exist.", sender)) { return; } - WebUser info = table.getSecurityInfo(user); + WebUser info = table.getWebUser(user); sender.sendMessage(info.getName() + ": Permission level: " + info.getPermLevel()); } catch (Exception ex) { Log.toLog(this.getClass().getName(), ex); diff --git a/Plan/src/main/java/com/djrapitops/plan/database/DBUtils.java b/Plan/src/main/java/com/djrapitops/plan/database/DBUtils.java index 1af58eda6..05ea524e1 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/DBUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/DBUtils.java @@ -19,8 +19,6 @@ import java.util.Map.Entry; */ public class DBUtils { - private static final int BATCH_SIZE = 2048; - /** * Constructor used to hide the public constructor */ @@ -28,6 +26,8 @@ public class DBUtils { throw new IllegalStateException("Utility class"); } + private static final int BATCH_SIZE = 10192; + /** * Splits a collection of objects into lists with the size defined by * BATCH_SIZE. diff --git a/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java b/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java index 383beef8a..d357d2f47 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java @@ -30,6 +30,7 @@ import java.util.stream.Collectors; public abstract class SQLDB extends Database { private final boolean supportsModification; + private final boolean usingMySQL; private Connection connection; @@ -40,7 +41,7 @@ public abstract class SQLDB extends Database { public SQLDB(Plan plugin, boolean supportsModification) { super(plugin); this.supportsModification = supportsModification; - boolean usingMySQL = getName().equals("MySQL"); + usingMySQL = getName().equals("MySQL"); usersTable = new UsersTable(this, usingMySQL); gmTimesTable = new GMTimesTable(this, usingMySQL); @@ -153,7 +154,6 @@ public abstract class SQLDB extends Database { Log.error("Failed to create table: " + securityTable.getTableName()); return false; } - Benchmark.stop("Database: Create tables"); if (!newDatabase && getVersion() < 8) { @@ -250,6 +250,7 @@ public abstract class SQLDB extends Database { @Override public void setVersion(int version) throws SQLException { versionTable.setVersion(version); + commit(); } /** @@ -293,7 +294,7 @@ public abstract class SQLDB extends Database { return false; } int userId = usersTable.getUserId(uuid); - return userId != -1 + boolean success = userId != -1 && locationsTable.removeUserLocations(userId) && ipsTable.removeUserIps(userId) && nicknamesTable.removeUserNicknames(userId) @@ -302,6 +303,12 @@ public abstract class SQLDB extends Database { && killsTable.removeUserKillsAndVictims(userId) && worldTimesTable.removeUserWorldTimes(userId) && usersTable.removeUser(uuid); + if (success) { + commit(); + } else { + rollback(); + } + return success; } finally { Benchmark.stop("Database: Remove Account"); setAvailable(); @@ -488,6 +495,7 @@ public abstract class SQLDB extends Database { gmTimesTable.saveGMTimes(gmTimes); worldTable.saveWorlds(worldNames); worldTimesTable.saveWorldTimes(worldTimes); + commit(); userDatas.values().stream() .filter(Objects::nonNull) .filter(UserData::isAccessed) @@ -523,6 +531,7 @@ public abstract class SQLDB extends Database { worldTable.saveWorlds(new HashSet<>(data.getWorldTimes().getTimes().keySet())); worldTimesTable.saveWorldTimes(userId, data.getWorldTimes().getTimes()); data.stopAccessing(); + commit(); setAvailable(); } @@ -547,14 +556,25 @@ public abstract class SQLDB extends Database { */ @Override public boolean removeAllData() { + boolean success = true; setStatus("Clearing all data"); - for (Table table : getAllTablesInRemoveOrder()) { - if (!table.removeAllData()) { - return false; + try { + for (Table table : getAllTablesInRemoveOrder()) { + if (!table.removeAllData()) { + success = false; + break; + } } + if (success) { + commit(); + } else { + rollback(); + } + } catch (SQLException e) { + Log.toLog(this.getClass().getName(), e); } setAvailable(); - return true; + return success; } /** @@ -578,4 +598,26 @@ public abstract class SQLDB extends Database { private void setAvailable() { setStatus("Running"); } + + /** + * Commits changes to the .db file when using SQLite Database. + *

+ * MySQL has Auto Commit enabled. + */ + public void commit() throws SQLException { + if (!usingMySQL) { + getConnection().commit(); + } + } + + /** + * Reverts transaction when using SQLite Database. + *

+ * MySQL has Auto Commit enabled. + */ + public void rollback() throws SQLException { + if (!usingMySQL) { + connection.rollback(); + } + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java index 249625ae5..2fcd5755d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java @@ -105,6 +105,7 @@ public class CommandUseTable extends Table { } updateCommands(updateData); + commit(); Benchmark.stop("Database: Save Commanduse"); } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/SecurityTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/SecurityTable.java index 537e758fc..ec5b68015 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/SecurityTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/SecurityTable.java @@ -77,16 +77,17 @@ public class SecurityTable extends Table { statement.setString(2, saltPassHash); statement.setInt(3, permLevel); statement.execute(); + commit(); } finally { close(statement); } } public boolean userExists(String user) throws SQLException { - return getSecurityInfo(user) != null; + return getWebUser(user) != null; } - public WebUser getSecurityInfo(String user) throws SQLException { + public WebUser getWebUser(String user) throws SQLException { PreparedStatement statement = null; ResultSet set = null; try { diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/TPSTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/TPSTable.java index c63d9f8dc..59d0609da 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/TPSTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/TPSTable.java @@ -115,7 +115,6 @@ public class TPSTable extends Table { /** * @param data - * @throws SQLException */ public void saveTPSData(List data) { List> batches = DBUtils.splitIntoBatches(data); diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/Table.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/Table.java index 9b36d93a2..2022ecd3b 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/Table.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/Table.java @@ -172,4 +172,14 @@ public abstract class Table { public String toString() { return tableName; } + + /** + * Commits changes to .db file when using SQLite databse. + * + * Auto Commit enabled when using MySQL + * @throws SQLException If commit fails or there is nothing to commit. + */ + protected void commit() throws SQLException { + db.commit(); + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/webserver/WebServer.java b/Plan/src/main/java/com/djrapitops/plan/ui/webserver/WebServer.java index 075e19a82..12e36a908 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/webserver/WebServer.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/webserver/WebServer.java @@ -164,7 +164,7 @@ public class WebServer { throw new IllegalArgumentException("User Doesn't exist"); } - WebUser webUser = securityTable.getSecurityInfo(user); + WebUser webUser = securityTable.getWebUser(user); boolean correctPass = PassEncryptUtil.verifyPassword(passwordRaw, webUser.getSaltedPassHash()); if (!correctPass) { diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/webserver/response/PlayersPageResponse.java b/Plan/src/main/java/com/djrapitops/plan/ui/webserver/response/PlayersPageResponse.java index 0cfd72c31..83ed21ccb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/webserver/response/PlayersPageResponse.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/webserver/response/PlayersPageResponse.java @@ -21,22 +21,26 @@ public class PlayersPageResponse extends Response { public static String buildContent(List cached) { StringBuilder html = new StringBuilder("

Cached Players

"); - int size = cached.size(); + html.append(size) .append(" players. Use browser's Search to find players by name. (Chrome Ctrl+F)

"); + cached.sort(new UserDataNameComparator()); + int i = 1; for (UserData userData : cached) { String name = userData.getName(); String link = Html.LINK.parse(HtmlUtils.getRelativeInspectUrl(name), name); + html.append(""); - if (i < size - && i % 8 == 0) { + + if (i < size && i % 8 == 0) { html.append(""); } i++; } + html.append("
").append(link).append("
"); return html.toString(); } diff --git a/Plan/src/main/resources/analysis.html b/Plan/src/main/resources/analysis.html index 113c83217..d0b519f9f 100644 --- a/Plan/src/main/resources/analysis.html +++ b/Plan/src/main/resources/analysis.html @@ -1277,8 +1277,12 @@ } var perc = - 100 / navButtons.length; slideIndex = i; - if (slideIndex > max) {slideIndex = 0}; - if (slideIndex < 0) {slideIndex = max}; + if (slideIndex > max) { + slideIndex = 0 + } + if (slideIndex < 0) { + slideIndex = max + } window.sessionStorage.setItem("AnalysisSlideIndex", slideIndex); var value = slideIndex * perc; x.style.transition = "0.5s"; diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseCommitTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseCommitTest.java index 37f0d4771..92ebaa450 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseCommitTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/database/DatabaseCommitTest.java @@ -3,9 +3,11 @@ package test.java.main.java.com.djrapitops.plan.database; import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.data.TPS; import main.java.com.djrapitops.plan.data.UserData; +import main.java.com.djrapitops.plan.data.WebUser; import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.databases.SQLiteDB; import main.java.com.djrapitops.plan.utilities.MiscUtils; +import main.java.com.djrapitops.plan.utilities.PassEncryptUtil; import org.bukkit.plugin.java.JavaPlugin; import org.junit.After; import org.junit.Before; @@ -125,4 +127,15 @@ public class DatabaseCommitTest { db.init(); assertTrue(!db.getUserDataForUUIDS(uuids).isEmpty()); } + + @Test + public void testCommitToDBFile5() throws SQLException, PassEncryptUtil.CannotPerformOperationException { + db.init(); + List data = RandomData.randomUserData(); + WebUser webUser = new WebUser("Test", PassEncryptUtil.createHash("surprise"), 0); + db.getSecurityTable().addNewUser(webUser); + db.close(); + db.init(); + assertTrue(webUser.equals(db.getSecurityTable().getWebUser("Test"))); + } }