b8edb0e130
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 6b34da8f SPIGOT-7467: Add getAddress to RemoteConsoleCommandSender CraftBukkit Changes: db4ba2897 SPIGOT-7467: Add getAddress to RemoteConsoleCommandSender 4f7ff4dec PR-1246: Add missing AbstractTestingBase to tests which need them f70a7b68d SPIGOT-7465, MC-264979: Fresh installations print NoSuchFileException for server.properties 8ef7afef6 PR-1240: Call BlockGrowEvent for vines that are growing on additional sides of an existing vine block Spigot Changes: d2eba2c8 Rebuild patches
129 Zeilen
6.2 KiB
Diff
129 Zeilen
6.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
Date: Sat, 11 Jul 2020 05:09:28 -0700
|
|
Subject: [PATCH] Fix GameProfileCache concurrency
|
|
|
|
Separate lookup and state access locks 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 2456edc11b29a92b1648937cd3dd6a9a05706803..b48650c38751a925b83fb4c19ac02f87cb1bef6e 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 {
|
|
@Nullable
|
|
private Executor executor;
|
|
|
|
+ // Paper start
|
|
+ protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock();
|
|
+ protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock();
|
|
+ // Paper end
|
|
+
|
|
public GameProfileCache(GameProfileRepository profileRepository, File cacheFile) {
|
|
this.profileRepository = profileRepository;
|
|
this.file = cacheFile;
|
|
@@ -69,6 +74,7 @@ public class GameProfileCache {
|
|
}
|
|
|
|
private void safeAdd(GameProfileCache.GameProfileInfo entry) {
|
|
+ try { this.stateLock.lock(); // Paper - allow better concurrency
|
|
GameProfile gameprofile = entry.getProfile();
|
|
|
|
entry.setLastAccess(this.getNextOperation());
|
|
@@ -83,6 +89,7 @@ public class GameProfileCache {
|
|
if (uuid != null) {
|
|
this.profilesByUUID.put(uuid, entry);
|
|
}
|
|
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency
|
|
|
|
}
|
|
|
|
@@ -138,17 +145,20 @@ public class GameProfileCache {
|
|
|
|
// Paper start
|
|
public @Nullable 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
|
|
|
|
public Optional<GameProfile> get(String name) {
|
|
String s1 = name.toLowerCase(Locale.ROOT);
|
|
+ boolean stateLocked = true; try { this.stateLock.lock(); // Paper - allow better concurrency
|
|
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
|
|
boolean flag = false;
|
|
|
|
@@ -164,8 +174,12 @@ public class GameProfileCache {
|
|
if (usercache_usercacheentry != null) {
|
|
usercache_usercacheentry.setLastAccess(this.getNextOperation());
|
|
optional = Optional.of(usercache_usercacheentry.getProfile());
|
|
+ stateLocked = false; this.stateLock.unlock(); // Paper - allow better concurrency
|
|
} else {
|
|
+ stateLocked = false; this.stateLock.unlock(); // Paper - allow better concurrency
|
|
+ try { this.lookupLock.lock(); // Paper - allow better concurrency
|
|
optional = GameProfileCache.lookupGameProfile(this.profileRepository, name); // Spigot - use correct case for offline players
|
|
+ } finally { this.lookupLock.unlock(); } // Paper - allow better concurrency
|
|
if (optional.isPresent()) {
|
|
this.add((GameProfile) optional.get());
|
|
flag = false;
|
|
@@ -177,6 +191,7 @@ public class GameProfileCache {
|
|
}
|
|
|
|
return optional;
|
|
+ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - allow better concurrency
|
|
}
|
|
|
|
public void getAsync(String username, Consumer<Optional<GameProfile>> consumer) {
|
|
@@ -203,6 +218,7 @@ public class GameProfileCache {
|
|
}
|
|
|
|
public Optional<GameProfile> get(UUID uuid) {
|
|
+ try { this.stateLock.lock(); // Paper - allow better concurrency
|
|
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid);
|
|
|
|
if (usercache_usercacheentry == null) {
|
|
@@ -211,6 +227,7 @@ public class GameProfileCache {
|
|
usercache_usercacheentry.setLastAccess(this.getNextOperation());
|
|
return Optional.of(usercache_usercacheentry.getProfile());
|
|
}
|
|
+ } finally { this.stateLock.unlock(); } // Paper - allow better concurrency
|
|
}
|
|
|
|
public void setExecutor(Executor executor) {
|
|
@@ -291,7 +308,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);
|
|
@@ -332,8 +349,19 @@ public class GameProfileCache {
|
|
}
|
|
|
|
private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) {
|
|
- 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<GameProfileCache.GameProfileInfo> 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();
|