diff options
Diffstat (limited to 'patches/server/0230-Use-ConcurrentHashMap-in-JsonList.patch')
-rw-r--r-- | patches/server/0230-Use-ConcurrentHashMap-in-JsonList.patch | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/patches/server/0230-Use-ConcurrentHashMap-in-JsonList.patch b/patches/server/0230-Use-ConcurrentHashMap-in-JsonList.patch new file mode 100644 index 0000000000..f2227d0d63 --- /dev/null +++ b/patches/server/0230-Use-ConcurrentHashMap-in-JsonList.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: egg82 <[email protected]> +Date: Tue, 7 Aug 2018 01:24:23 -0600 +Subject: [PATCH] Use ConcurrentHashMap in JsonList + +This is specifically aimed at fixing #471 + +Using a ConcurrentHashMap because thread safety +The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove +Even without considering the use-case the benefits are still negligable + +Original ideas for the system included an expiration policy and/or handler +The simpler solution was to use a computeIfPresent in the get method +This will simultaneously have an O(1) lookup time and automatically expire any values +Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful +Meaning the original function expired values unrelated to the current value without actually having any explicit need to + +The h method was heavily modified to be much more efficient in its processing +Also instead of being called on every get, it's now called just before a save +This will eliminate stale values being flushed to disk + +Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 +The point of this is readability, but does have a side-benefit of a small microptimization + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 3273c3f06c142d4e3c947ca846459f4a8e5eefd8..940896725c32981ddd2d5a23d72a87ba3e5e0fee 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -634,7 +634,7 @@ public abstract class PlayerList { + } else if (!this.isWhiteListed(gameprofile, event)) { // Paper - ProfileWhitelistVerifyEvent + //ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - moved to isWhitelisted +- } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { ++ } else if (this.getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !this.getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + + ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 7e81907bfdca225413e8191e37969990e6f4cf2c..c038da20b76c0b7b1c18471b20be01e849d29f3a 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -30,7 +30,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); + private final File file; +- private final Map<String, V> map = Maps.newHashMap(); ++ private final Map<String, V> map = Maps.newConcurrentMap(); // Paper - Use ConcurrentHashMap in JsonList + + public StoredUserList(File file) { + this.file = file; +@@ -53,8 +53,11 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> { + + @Nullable + public V get(K key) { +- this.removeExpired(); +- return (V) this.map.get(this.getKeyForUser(key)); // CraftBukkit - fix decompile error ++ // Paper start - Use ConcurrentHashMap in JsonList ++ return (V) this.map.computeIfPresent(this.getKeyForUser(key), (k, v) -> { ++ return v.hasExpired() ? null : v; ++ }); ++ // Paper end - Use ConcurrentHashMap in JsonList + } + + public void remove(K key) { +@@ -77,7 +80,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> { + } + + public boolean isEmpty() { +- return this.map.size() < 1; ++ return this.map.isEmpty(); // Paper - Use ConcurrentHashMap in JsonList + } + + protected String getKeyForUser(K profile) { +@@ -90,25 +93,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> { + } + + private void removeExpired() { +- List<K> list = Lists.newArrayList(); +- Iterator iterator = this.map.values().iterator(); +- +- while (iterator.hasNext()) { +- V v0 = (V) iterator.next(); // CraftBukkit - decompile error +- +- if (v0.hasExpired()) { +- list.add(v0.getUser()); +- } +- } +- +- iterator = list.iterator(); +- +- while (iterator.hasNext()) { +- K k0 = (K) iterator.next(); // CraftBukkit - decompile error +- +- this.map.remove(this.getKeyForUser(k0)); +- } +- ++ this.map.values().removeIf(StoredUserEntry::hasExpired); // Paper - Use ConcurrentHashMap in JsonList + } + + protected abstract StoredUserEntry<K> createEntry(JsonObject json); +@@ -118,6 +103,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> { + } + + public void save() throws IOException { ++ this.removeExpired(); // Paper - remove expired values before saving + JsonArray jsonarray = new JsonArray(); + Stream<JsonObject> stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error + JsonObject jsonobject = new JsonObject(); |