From 319d5fa29fae83a85ca939793a7e2e34acfb4948 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 17 Mar 2022 19:44:45 -0700 Subject: [PATCH] Fix state locking for getTopMRUProfiles & getProfileIfCached Also add missing last access update in getProfileIfCached --- .../server/0139-Basic-PlayerProfile-API.patch | 10 ++-- ...locking-from-state-access-in-UserCac.patch | 51 +++++++++++++++---- ...-profile-lookups-to-worldgen-threads.patch | 4 +- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/patches/server/0139-Basic-PlayerProfile-API.patch b/patches/server/0139-Basic-PlayerProfile-API.patch index 625ffbc57..e32473a33 100644 --- a/patches/server/0139-Basic-PlayerProfile-API.patch +++ b/patches/server/0139-Basic-PlayerProfile-API.patch @@ -599,17 +599,21 @@ index b49528d8a2c577def4f74ee694ffd53b481acb32..8f5784ed4df46f3c7d4c6b4ff76ad839 GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index c3e3a9950ee05dc97f15ab128e40854901f38a2f..95974d78196397136179f8d6acf1597c557e5a23 100644 +index c3e3a9950ee05dc97f15ab128e40854901f38a2f..d7eba4190110b92641664c827c6bc50f62d2ae15 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -135,6 +135,13 @@ public class GameProfileCache { +@@ -135,6 +135,17 @@ public class GameProfileCache { return this.operationCount.incrementAndGet(); } + // Paper start + @Nullable public GameProfile getProfileIfCached(String name) { + GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); -+ return entry == null ? null : entry.getProfile(); ++ if (entry == null) { ++ return null; ++ } ++ entry.setLastAccess(this.getNextOperation()); ++ return entry.getProfile(); + } + // Paper end + diff --git a/patches/server/0729-Separate-lookup-locking-from-state-access-in-UserCac.patch b/patches/server/0729-Separate-lookup-locking-from-state-access-in-UserCac.patch index 86c0e502f..0dab846d9 100644 --- a/patches/server/0729-Separate-lookup-locking-from-state-access-in-UserCac.patch +++ b/patches/server/0729-Separate-lookup-locking-from-state-access-in-UserCac.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Separate lookup locking from state access in UserCache Prevent lookups from stalling simple state access/write calls diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e506480108cfbfc1 100644 +index d7eba4190110b92641664c827c6bc50f62d2ae15..534373a1e305942d63ffb0fc97ea3f165eca76b5 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java @@ -62,6 +62,11 @@ public class GameProfileCache { @@ -46,7 +46,18 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); -@@ -142,8 +149,9 @@ public class GameProfileCache { +@@ -137,17 +144,20 @@ public class GameProfileCache { + + // Paper start + @Nullable public GameProfile getProfileIfCached(String name) { ++ try { this.stateLock.lock(); // Paper - allow better concurrency + GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT)); + if (entry == null) { + return null; + } + entry.setLastAccess(this.getNextOperation()); + return entry.getProfile(); ++ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency } // Paper end @@ -57,7 +68,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801 GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); boolean flag = false; -@@ -159,8 +167,12 @@ public class GameProfileCache { +@@ -163,8 +173,12 @@ public class GameProfileCache { if (usercache_usercacheentry != null) { usercache_usercacheentry.setLastAccess(this.getNextOperation()); optional = Optional.of(usercache_usercacheentry.getProfile()); @@ -70,7 +81,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801 if (optional.isPresent()) { this.add((GameProfile) optional.get()); flag = false; -@@ -172,6 +184,7 @@ public class GameProfileCache { +@@ -176,6 +190,7 @@ public class GameProfileCache { } return optional; @@ -78,7 +89,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801 } public void getAsync(String username, Consumer> consumer) { -@@ -198,6 +211,7 @@ public class GameProfileCache { +@@ -202,6 +217,7 @@ public class GameProfileCache { } public Optional get(UUID uuid) { @@ -86,7 +97,7 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801 GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); if (usercache_usercacheentry == null) { -@@ -206,6 +220,7 @@ public class GameProfileCache { +@@ -210,6 +226,7 @@ public class GameProfileCache { usercache_usercacheentry.setLastAccess(this.getNextOperation()); return Optional.of(usercache_usercacheentry.getProfile()); } @@ -94,13 +105,33 @@ index 95974d78196397136179f8d6acf1597c557e5a23..6349b33939909435120fdef5e5064801 } public void setExecutor(Executor executor) { -@@ -326,7 +341,9 @@ public class GameProfileCache { +@@ -290,7 +307,7 @@ public class GameProfileCache { + JsonArray jsonarray = new JsonArray(); + DateFormat dateformat = GameProfileCache.createDateFormat(); + +- this.getTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot ++ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - allow better concurrency + jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat)); + }); + String s = this.gson.toJson(jsonarray); +@@ -330,8 +347,19 @@ public class GameProfileCache { } private Stream getTopMRUProfiles(int limit) { -+ try { this.stateLock.lock(); // Paper - allow better concurrency - return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); -+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency +- return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); ++ // Paper start - allow better concurrency ++ return this.listTopMRUProfiles(limit).stream(); ++ } ++ ++ private List listTopMRUProfiles(int limit) { ++ try { ++ this.stateLock.lock(); ++ return this.profilesByUUID.values().stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit(limit).toList(); ++ } finally { ++ this.stateLock.unlock(); ++ } } ++ // Paper end private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) { + JsonObject jsonobject = new JsonObject(); diff --git a/patches/server/0733-Do-not-submit-profile-lookups-to-worldgen-threads.patch b/patches/server/0733-Do-not-submit-profile-lookups-to-worldgen-threads.patch index 7654abc8b..8ae08b04c 100644 --- a/patches/server/0733-Do-not-submit-profile-lookups-to-worldgen-threads.patch +++ b/patches/server/0733-Do-not-submit-profile-lookups-to-worldgen-threads.patch @@ -37,10 +37,10 @@ index c072819c1ebc772f524649c6c2f8b48d919bf805..bbe69b5b2b1b7ccd3358325c9a65e7e1 public static LongSupplier timeSource = System::nanoTime; public static final Ticker TICKER = new Ticker() { diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java -index 6349b33939909435120fdef5e506480108cfbfc1..ea739fae40e819fd82bc275c0af5c8269e12d656 100644 +index 534373a1e305942d63ffb0fc97ea3f165eca76b5..e3fbada96b530784fa1de63a322b484865ed194f 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java -@@ -200,7 +200,7 @@ public class GameProfileCache { +@@ -206,7 +206,7 @@ public class GameProfileCache { } else { this.requests.put(username, CompletableFuture.supplyAsync(() -> { return this.get(username);