diff --git a/Spigot-API-Patches/0150-Performance-Concurrency-Improvements-to-Permissions.patch b/Spigot-API-Patches/0150-Performance-Concurrency-Improvements-to-Permissions.patch new file mode 100644 index 000000000..7665e7095 --- /dev/null +++ b/Spigot-API-Patches/0150-Performance-Concurrency-Improvements-to-Permissions.patch @@ -0,0 +1,114 @@ +From ebe3ab3a42a6d51c060849d75fdaba854bb6dc89 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 13 Sep 2018 20:51:50 -0400 +Subject: [PATCH] Performance & Concurrency Improvements to Permissions + +Modifying of permissions was only half protected, enabling concurrency +issues to occur if permissions were modified async. + +While no plugin really should be doing that, modifying operations +are not heavily called, so they are safe to add synchronization to. + +Now, all modification API's will be synchronized ensuring safety. + +Additionally, hasPermission was victim to a common java newbie mistake +of calling if (containsKey(k)) return get(k), resulting in 2 map lookups. + +Optimized it to simply be a single get call cutting permission map +lookups in half. + +diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java +index d4cb00a82..486f69f86 100644 +--- a/src/main/java/org/bukkit/permissions/PermissibleBase.java ++++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java +@@ -68,8 +68,11 @@ public class PermissibleBase implements Permissible { + + String name = inName.toLowerCase(java.util.Locale.ENGLISH); + +- if (isPermissionSet(name)) { +- return permissions.get(name).getValue(); ++ // Paper start ++ PermissionAttachmentInfo info = permissions.get(name); ++ if (info != null) { ++ return info.getValue(); ++ // Paper end + } else { + Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); + +@@ -88,13 +91,16 @@ public class PermissibleBase implements Permissible { + + String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH); + +- if (isPermissionSet(name)) { +- return permissions.get(name).getValue(); ++ // Paper start ++ PermissionAttachmentInfo info = permissions.get(name); ++ if (info != null) { ++ return info.getValue(); + } ++ // Paper end + return perm.getDefault().getValue(isOp()); + } + +- public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { ++ public synchronized PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { // Paper - synchronized + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } else if (plugin == null) { +@@ -111,7 +117,7 @@ public class PermissibleBase implements Permissible { + return result; + } + +- public PermissionAttachment addAttachment(Plugin plugin) { ++ public synchronized PermissionAttachment addAttachment(Plugin plugin) { // Paper - synchronized + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { +@@ -126,7 +132,7 @@ public class PermissibleBase implements Permissible { + return result; + } + +- public void removeAttachment(PermissionAttachment attachment) { ++ public synchronized void removeAttachment(PermissionAttachment attachment) { // Paper - synchronized + if (attachment == null) { + throw new IllegalArgumentException("Attachment cannot be null"); + } +@@ -145,7 +151,7 @@ public class PermissibleBase implements Permissible { + } + } + +- public void recalculatePermissions() { ++ public synchronized void recalculatePermissions() { // Paper - synchronized + clearPermissions(); + Set defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); + Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent); +@@ -192,7 +198,7 @@ public class PermissibleBase implements Permissible { + } + } + +- public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { ++ public synchronized PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { // Paper - synchronized + if (name == null) { + throw new IllegalArgumentException("Permission name cannot be null"); + } else if (plugin == null) { +@@ -210,7 +216,7 @@ public class PermissibleBase implements Permissible { + return result; + } + +- public PermissionAttachment addAttachment(Plugin plugin, int ticks) { ++ public synchronized PermissionAttachment addAttachment(Plugin plugin, int ticks) { // Paper - synchronized + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } else if (!plugin.isEnabled()) { +@@ -228,7 +234,7 @@ public class PermissibleBase implements Permissible { + } + } + +- public Set getEffectivePermissions() { ++ public synchronized Set getEffectivePermissions() { // Paper - synchronized + return new HashSet(permissions.values()); + } + +-- +2.18.0 +