diff --git a/Plan/common/src/main/java/com/djrapitops/plan/ShutdownHook.java b/Plan/common/src/main/java/com/djrapitops/plan/ShutdownHook.java index e35e874c1..2dc0ff29d 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/ShutdownHook.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/ShutdownHook.java @@ -22,6 +22,7 @@ import com.djrapitops.plan.api.exceptions.database.DBOpException; import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.store.keys.SessionKeys; import com.djrapitops.plan.db.Database; +import com.djrapitops.plan.db.access.transactions.events.ServerShutdownTransaction; import com.djrapitops.plan.system.cache.SessionCache; import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plugin.logging.L; @@ -77,39 +78,49 @@ public class ShutdownHook extends Thread { try { Map activeSessions = SessionCache.getActiveSessions(); long now = System.currentTimeMillis(); - saveActiveSessions(activeSessions, now); + prepareSessionsForStorage(activeSessions, System.currentTimeMillis()); + saveActiveSessions(activeSessions); } catch (IllegalStateException ignored) { /* Database is not initialized */ } catch (DBInitException e) { errorHandler.log(L.ERROR, this.getClass(), e); } finally { - try { - dbSystem.getDatabase().close(); - } catch (DBException e) { - errorHandler.log(L.ERROR, this.getClass(), e); - } + closeDatabase(dbSystem.getDatabase()); } } - private void saveActiveSessions(Map activeSessions, long now) throws DBInitException { - for (Map.Entry entry : activeSessions.entrySet()) { - UUID uuid = entry.getKey(); - Session session = entry.getValue(); + private void saveActiveSessions(Map activeSessions) throws DBInitException { + Database database = dbSystem.getDatabase(); + if (!database.isOpen()) { + // Ensure that database is not closed when performing the transaction. + database.init(); + } + + saveSessions(activeSessions, database); + } + + private void prepareSessionsForStorage(Map activeSessions, long now) { + for (Session session : activeSessions.values()) { Optional end = session.getValue(SessionKeys.END); if (!end.isPresent()) { session.endSession(now); } - Database database = dbSystem.getDatabase(); - if (!database.isOpen()) { - database.init(); - } - // TODO Create a server shutdown transaction. - try { - database.save().session(uuid, session); - } catch (DBOpException e) { - errorHandler.log(L.ERROR, this.getClass(), e); - } } - activeSessions.clear(); + } + + private void saveSessions(Map activeSessions, Database database) { + try { + database.executeTransaction(new ServerShutdownTransaction(activeSessions.values())); + } catch (DBOpException e) { + errorHandler.log(L.ERROR, this.getClass(), e); + } + } + + private void closeDatabase(Database database) { + try { + database.close(); + } catch (DBException e) { + errorHandler.log(L.ERROR, this.getClass(), e); + } } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java index 57356678a..5d3bd6cee 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java @@ -329,7 +329,7 @@ public class LargeStoreQueries { }; } - public static Executable storeAllSessionsWithoutKillOrWorldData(List sessions) { + public static Executable storeAllSessionsWithoutKillOrWorldData(Collection sessions) { if (Verify.isEmpty(sessions)) { return Executable.empty(); } @@ -351,7 +351,7 @@ public class LargeStoreQueries { }; } - public static Executable storeAllSessionsWithKillAndWorldData(List sessions) { + public static Executable storeAllSessionsWithKillAndWorldData(Collection sessions) { return connection -> { storeAllSessionsWithoutKillOrWorldData(sessions).execute(connection); storeSessionKillData(sessions).execute(connection); @@ -359,7 +359,7 @@ public class LargeStoreQueries { }; } - private static Executable storeSessionKillData(List sessions) { + private static Executable storeSessionKillData(Collection sessions) { if (Verify.isEmpty(sessions)) { return Executable.empty(); } @@ -374,7 +374,7 @@ public class LargeStoreQueries { }; } - private static Executable storeSessionWorldTimeData(List sessions) { + private static Executable storeSessionWorldTimeData(Collection sessions) { if (Verify.isEmpty(sessions)) { return Executable.empty(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/transactions/events/ServerShutdownTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/transactions/events/ServerShutdownTransaction.java new file mode 100644 index 000000000..21cf21b87 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/transactions/events/ServerShutdownTransaction.java @@ -0,0 +1,42 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.db.access.transactions.events; + +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.db.access.queries.LargeStoreQueries; +import com.djrapitops.plan.db.access.transactions.Transaction; + +import java.util.Collection; + +/** + * Transaction to store sessions on server shutdown. + * + * @author Rsl1122 + */ +public class ServerShutdownTransaction extends Transaction { + + private final Collection unsavedSessions; + + public ServerShutdownTransaction(Collection unsavedSessions) { + this.unsavedSessions = unsavedSessions; + } + + @Override + protected void performOperations() { + execute(LargeStoreQueries.storeAllSessionsWithKillAndWorldData(unsavedSessions)); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/operation/SaveOperations.java b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/operation/SaveOperations.java index c2cac6b15..fa1e738d5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/operation/SaveOperations.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/operation/SaveOperations.java @@ -16,14 +16,8 @@ */ package com.djrapitops.plan.system.database.databases.operation; -import com.djrapitops.plan.data.container.GeoInfo; import com.djrapitops.plan.data.container.Session; -import com.djrapitops.plan.data.container.TPS; -import com.djrapitops.plan.data.container.UserInfo; -import com.djrapitops.plan.data.store.objects.Nickname; -import java.util.List; -import java.util.Map; import java.util.UUID; /** @@ -38,30 +32,6 @@ public interface SaveOperations { // Bulk save - @Deprecated - void insertTPS(Map> ofServers); - - @Deprecated - void insertCommandUsage(Map> ofServers); - - @Deprecated - void insertUsers(Map ofServers); - - @Deprecated - void insertSessions(Map>> ofServers, boolean containsExtraData); - - @Deprecated - void kickAmount(Map ofUsers); - - @Deprecated - void insertUserInfo(Map> ofServers); - - @Deprecated - void insertNicknames(Map>> ofServers); - - @Deprecated - void insertAllGeoInfo(Map> ofUsers); - // Single data point @Deprecated diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLSaveOps.java b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLSaveOps.java index db50a23f4..ead5b6bf2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLSaveOps.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLSaveOps.java @@ -16,19 +16,13 @@ */ package com.djrapitops.plan.system.database.databases.sql.operation; -import com.djrapitops.plan.data.container.*; -import com.djrapitops.plan.data.store.objects.Nickname; +import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.db.SQLDB; import com.djrapitops.plan.db.access.queries.DataStoreQueries; -import com.djrapitops.plan.db.access.queries.LargeStoreQueries; import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.system.database.databases.operation.SaveOperations; -import java.util.Collection; -import java.util.List; -import java.util.Map; import java.util.UUID; -import java.util.stream.Collectors; /** * SaveOperations implementation for SQL databases. @@ -41,90 +35,6 @@ public class SQLSaveOps extends SQLOps implements SaveOperations { super(db); } - @Override - public void insertTPS(Map> ofServers) { - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storeAllTPSData(ofServers)); - } - }); - } - - @Override - public void insertCommandUsage(Map> ofServers) { - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storeAllCommandUsageData(ofServers)); - } - }); - } - - @Override - public void insertUsers(Map ofUsers) { - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - Collection users = ofUsers.values().stream() - .map(user -> new BaseUser(user.getPlayerUuid(), user.getPlayerUuid().toString(), user.getRegistered(), 0)) - .collect(Collectors.toSet()); - execute(LargeStoreQueries.storeAllCommonUserInformation(users)); - } - }); - } - - @Override - public void insertSessions(Map>> ofServers, boolean containsExtraData) { - List sessions = ofServers.values().stream() - .map(Map::values) - .flatMap(Collection::stream) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(containsExtraData ? LargeStoreQueries.storeAllSessionsWithKillAndWorldData(sessions) - : LargeStoreQueries.storeAllSessionsWithoutKillOrWorldData(sessions)); - } - }); - } - - @Override - public void kickAmount(Map ofUsers) { - // Moved to BaseUser storage methods - } - - @Override - public void insertUserInfo(Map> ofServers) { - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storePerServerUserInformation(ofServers)); - } - }); - } - - @Override - public void insertNicknames(Map>> ofServers) { - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storeAllNicknameData(ofServers)); - } - }); - } - - @Override - public void insertAllGeoInfo(Map> ofUsers) { - db.executeTransaction(new Transaction() { - @Override - protected void performOperations() { - execute(LargeStoreQueries.storeAllGeoInformation(ofUsers)); - } - }); - } - @Override public void banStatus(UUID uuid, boolean banned) { userInfoTable.updateBanStatus(uuid, banned);