From 4d951cea20b02f8fcff768d1a56177afd3fab7e7 Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Mon, 11 Feb 2019 17:36:18 +0200 Subject: [PATCH] Optimized ServerPlayerContainersQuery PerServerContainer creation --- .../store/containers/PerServerContainer.java | 94 ++++++++++++++++++- .../containers/AllPlayerContainersQuery.java | 8 +- .../containers/PerServerContainerQuery.java | 20 +--- .../ServerPlayerContainersQuery.java | 52 ++++++++-- .../queries/objects/BaseUserQueries.java | 2 +- 5 files changed, 143 insertions(+), 33 deletions(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/PerServerContainer.java b/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/PerServerContainer.java index 0a925bbf7..537ee8876 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/PerServerContainer.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/PerServerContainer.java @@ -16,8 +16,15 @@ */ package com.djrapitops.plan.data.store.containers; -import java.util.HashMap; -import java.util.UUID; +import com.djrapitops.plan.data.container.Ping; +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.data.container.UserInfo; +import com.djrapitops.plan.data.store.Key; +import com.djrapitops.plan.data.store.keys.PerServerKeys; +import com.djrapitops.plan.data.store.keys.SessionKeys; +import com.djrapitops.plan.data.store.mutators.SessionsMutator; + +import java.util.*; /** * Container for data about a player linked to a single server. @@ -26,4 +33,87 @@ import java.util.UUID; * @see com.djrapitops.plan.data.store.keys.PerServerKeys For Key objects. */ public class PerServerContainer extends HashMap { + + public void putToContainerOfServer(UUID serverUUID, Key key, T value) { + DataContainer container = getOrDefault(serverUUID, new DynamicDataContainer()); + container.putRawData(key, value); + put(serverUUID, container); + } + + public void putUserInfo(UserInfo userInfo) { + UUID serverUUID = userInfo.getServerUUID(); + putToContainerOfServer(serverUUID, PerServerKeys.REGISTERED, userInfo.getRegistered()); + putToContainerOfServer(serverUUID, PerServerKeys.BANNED, userInfo.isBanned()); + putToContainerOfServer(serverUUID, PerServerKeys.OPERATOR, userInfo.isOperator()); + } + + public void putUserInfo(Collection userInformation) { + for (UserInfo userInfo : userInformation) { + putUserInfo(userInfo); + } + } + + public void putCalculatingSuppliers() { + for (DataContainer container : values()) { + container.putSupplier(PerServerKeys.LAST_SEEN, () -> SessionsMutator.forContainer(container).toLastSeen()); + + container.putSupplier(PerServerKeys.WORLD_TIMES, () -> SessionsMutator.forContainer(container).toTotalWorldTimes()); + container.putSupplier(PerServerKeys.PLAYER_DEATHS, () -> SessionsMutator.forContainer(container).toPlayerDeathList()); + container.putSupplier(PerServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList()); + container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PerServerKeys.PLAYER_KILLS).size()); + container.putSupplier(PerServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount()); + container.putSupplier(PerServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount()); + container.putSupplier(PerServerKeys.MOB_DEATH_COUNT, () -> + container.getUnsafe(PerServerKeys.DEATH_COUNT) - container.getUnsafe(PerServerKeys.PLAYER_DEATH_COUNT) + ); + } + } + + public void putSessions(Collection sessions) { + if (sessions == null) { + return; + } + + for (Session session : sessions) { + putSession(session); + } + } + + private void putSession(Session session) { + if (session == null) { + return; + } + + UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID); + DataContainer container = getOrDefault(serverUUID, new DynamicDataContainer()); + if (!container.supports(PerServerKeys.SESSIONS)) { + container.putRawData(PerServerKeys.SESSIONS, new ArrayList<>()); + } + container.getUnsafe(PerServerKeys.SESSIONS).add(session); + put(serverUUID, container); + } + + public void putPing(List pings) { + if (pings == null) { + return; + } + + for (Ping ping : pings) { + putPing(ping); + } + } + + private void putPing(Ping ping) { + if (ping == null) { + return; + } + + UUID serverUUID = ping.getServerUUID(); + DataContainer container = getOrDefault(serverUUID, new DynamicDataContainer()); + if (!container.supports(PerServerKeys.PING)) { + container.putRawData(PerServerKeys.PING, new ArrayList<>()); + } + container.getUnsafe(PerServerKeys.PING).add(ping); + put(serverUUID, container); + } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/AllPlayerContainersQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/AllPlayerContainersQuery.java index 18ace182e..c64c35def 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/AllPlayerContainersQuery.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/AllPlayerContainersQuery.java @@ -53,7 +53,7 @@ public class AllPlayerContainersQuery implements Query> { * @param allPings Map: Player UUID - List of Ping data * @return Map: Player UUID - PerServerContainer */ - static Map getPerServerData( + private Map getPerServerData( Map>> sessions, Map> allUserInfo, Map> allPings @@ -84,8 +84,8 @@ public class AllPlayerContainersQuery implements Query> { Map> serverUserSessions = entry.getValue(); for (Map.Entry> sessionEntry : serverUserSessions.entrySet()) { - UUID uuid = sessionEntry.getKey(); - PerServerContainer perServerContainer = perServerContainers.getOrDefault(uuid, new PerServerContainer()); + UUID playerUUID = sessionEntry.getKey(); + PerServerContainer perServerContainer = perServerContainers.getOrDefault(playerUUID, new PerServerContainer()); DataContainer container = perServerContainer.getOrDefault(serverUUID, new SupplierDataContainer()); List serverSessions = sessionEntry.getValue(); @@ -103,7 +103,7 @@ public class AllPlayerContainersQuery implements Query> { container.getUnsafe(PerServerKeys.DEATH_COUNT) - container.getUnsafe(PerServerKeys.PLAYER_DEATH_COUNT) ); perServerContainer.put(serverUUID, container); - perServerContainers.put(uuid, perServerContainer); + perServerContainers.put(playerUUID, perServerContainer); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java index 0144db0c9..b73cfb83d 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java @@ -23,7 +23,6 @@ import com.djrapitops.plan.data.store.containers.DataContainer; import com.djrapitops.plan.data.store.containers.PerServerContainer; import com.djrapitops.plan.data.store.containers.SupplierDataContainer; import com.djrapitops.plan.data.store.keys.PerServerKeys; -import com.djrapitops.plan.data.store.keys.PlayerKeys; import com.djrapitops.plan.data.store.mutators.SessionsMutator; import com.djrapitops.plan.db.SQLDB; import com.djrapitops.plan.db.access.Query; @@ -108,25 +107,14 @@ public class PerServerContainerQuery implements Query { matchingEntrySet(PerServerKeys.LAST_SEEN, PerServerAggregateQueries.lastSeenOnServers(playerUUID), db, container); } - private void userInformation(SQLDB db, PerServerContainer perServerContainer) { + private void userInformation(SQLDB db, PerServerContainer container) { List userInformation = db.query(UserInfoQueries.fetchUserInformationOfUser(playerUUID)); - for (UserInfo userInfo : userInformation) { - UUID serverUUID = userInfo.getServerUUID(); - placeToPerServerContainer(serverUUID, PlayerKeys.REGISTERED, userInfo.getRegistered(), perServerContainer); - placeToPerServerContainer(serverUUID, PlayerKeys.BANNED, userInfo.isBanned(), perServerContainer); - placeToPerServerContainer(serverUUID, PlayerKeys.OPERATOR, userInfo.isOperator(), perServerContainer); - } + container.putUserInfo(userInformation); } private void matchingEntrySet(Key key, Query> map, SQLDB db, PerServerContainer container) { - for (Map.Entry lastSeen : db.query(map).entrySet()) { - placeToPerServerContainer(lastSeen.getKey(), key, lastSeen.getValue(), container); + for (Map.Entry entry : db.query(map).entrySet()) { + container.putToContainerOfServer(entry.getKey(), key, entry.getValue()); } } - - private void placeToPerServerContainer(UUID serverUUID, Key key, T value, PerServerContainer perServerContainer) { - DataContainer container = perServerContainer.getOrDefault(serverUUID, new SupplierDataContainer()); - container.putRawData(key, value); - perServerContainer.put(serverUUID, container); - } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java index 6088b07ea..5cbc209ec 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java @@ -50,11 +50,41 @@ public class ServerPlayerContainersQuery implements Query> this.serverUUID = serverUUID; } + /** + * Create PerServerContainers for each player. + * + * @param userInformation Map: Player UUID - UserInfo of this server + * @param sessions Map: Player UUID - List of Sessions of this server + * @param ping Map: Player UUID - List of Ping data of this server + * @return Map: Player UUID - PerServerContainer + */ + private static Map getPerServerData( + Map userInformation, + Map> sessions, + Map> ping + ) { + Map perServerContainers = new HashMap<>(); + + for (Map.Entry entry : userInformation.entrySet()) { + UUID playerUUID = entry.getKey(); + PerServerContainer perServerContainer = perServerContainers.getOrDefault(playerUUID, new PerServerContainer()); + + perServerContainer.putUserInfo(entry.getValue()); // Information found withing UserInfo + perServerContainer.putSessions(sessions.get(playerUUID)); // Session list + perServerContainer.putPing(ping.get(playerUUID)); // Ping list + perServerContainer.putCalculatingSuppliers(); // Derivative values + + perServerContainers.put(playerUUID, perServerContainer); + } + + return perServerContainers; + } + @Override public List executeQuery(SQLDB db) { List containers = new ArrayList<>(); - Collection baseUsers = db.query(BaseUserQueries.serverBaseUsers(serverUUID)); + Collection baseUsers = db.query(BaseUserQueries.fetchServerBaseUsers(serverUUID)); Map> geoInformation = db.query(GeoInfoQueries.fetchServerGeoInformation(serverUUID)); Map> nicknames = db.query(NicknameQueries.fetchNicknameDataOfServer(serverUUID)); @@ -66,16 +96,16 @@ public class ServerPlayerContainersQuery implements Query> map.put(serverUUID, sessions); db.getKillsTable().addKillsToSessions(map); // TODO Optimize db.getWorldTimesTable().addWorldTimesToSessions(map); // TODO Optimize - - Map> serverUserInfos = Collections.singletonMap(serverUUID, // TODO Optimize - new ArrayList<>(db.query(UserInfoQueries.fetchUserInformationOfServer(serverUUID)).values()) - ); - Map>> serverSessions = Collections.singletonMap(serverUUID, sessions); - Map perServerInfo = AllPlayerContainersQuery.getPerServerData( - serverSessions, serverUserInfos, pingData - ); // ^ ------------- Needs work + Map userInformation = db.query(UserInfoQueries.fetchUserInformationOfServer(serverUUID)); + + Map perServerInfo = getPerServerData( + userInformation, + sessions, + pingData + ); + for (BaseUser user : baseUsers) { PlayerContainer container = new PlayerContainer(); @@ -95,8 +125,10 @@ public class ServerPlayerContainersQuery implements Query> // Nickname, only used for the raw server JSON. container.putRawData(PlayerKeys.NICKNAMES, nicknames.get(uuid)); - // v ------------- Needs work + // PerServerContainer container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid)); + + // v ------------- Needs work container.putCachingSupplier(PlayerKeys.SESSIONS, () -> { List playerSessions = sessions.getOrDefault(uuid, new ArrayList<>()); container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java index 525d1491f..7a4502cff 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java @@ -67,7 +67,7 @@ public class BaseUserQueries { }; } - public static Query> serverBaseUsers(UUID serverUUID) { + public static Query> fetchServerBaseUsers(UUID serverUUID) { String sql = "SELECT " + UsersTable.TABLE_NAME + "." + UsersTable.USER_UUID + ", " + UsersTable.USER_NAME + ", " +