Improve performance of resolve methods in PermissionHolder, other cleanup
This commit is contained in:
parent
055dfb000d
commit
e68fc7c558
@ -114,6 +114,20 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
*/
|
||||
boolean hasSpecificContext();
|
||||
|
||||
/**
|
||||
* Returns if this node is able to apply in the given context
|
||||
*
|
||||
* @param includeGlobal if global server values should apply
|
||||
* @param includeGlobalWorld if global world values should apply
|
||||
* @param server the server being checked against, or null
|
||||
* @param world the world being checked against, or null
|
||||
* @param context the context being checked against, or null
|
||||
* @param applyRegex if regex should be applied
|
||||
* @return true if the node should apply, otherwise false
|
||||
* @since 3.1
|
||||
*/
|
||||
boolean shouldApply(boolean includeGlobal, boolean includeGlobalWorld, String server, String world, ContextSet context, boolean applyRegex);
|
||||
|
||||
/**
|
||||
* If this node should apply on a specific server
|
||||
*
|
||||
|
@ -74,7 +74,7 @@ public class Injector {
|
||||
existing.clearPermissions();
|
||||
|
||||
lpPermissible.getActive().set(true);
|
||||
lpPermissible.recalculatePermissions();
|
||||
lpPermissible.recalculatePermissions(false);
|
||||
lpPermissible.setOldPermissible(existing);
|
||||
|
||||
lpPermissible.updateSubscriptionsAsync();
|
||||
|
@ -271,6 +271,10 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
recalculatePermissions(true);
|
||||
}
|
||||
|
||||
public void recalculatePermissions(boolean invalidate) {
|
||||
if (attachmentPermissions == null) {
|
||||
return;
|
||||
}
|
||||
@ -281,7 +285,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
calculateChildPermissions(attachment.getPermissions(), false, attachment);
|
||||
}
|
||||
|
||||
if (hasData()) {
|
||||
if (hasData() && invalidate) {
|
||||
user.getUserData().invalidatePermissionCalculators();
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ import java.util.function.Consumer;
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class UserReference implements HolderReference<UserIdentifier> {
|
||||
public final class UserReference implements HolderReference<UserIdentifier> {
|
||||
private final UserIdentifier id;
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +41,7 @@ import java.util.UUID;
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode(of = "uuid")
|
||||
public class AbstractSender<T> implements Sender {
|
||||
public final class AbstractSender<T> implements Sender {
|
||||
private final LuckPermsPlugin platform;
|
||||
private final SenderFactory<T> factory;
|
||||
private final WeakReference<T> ref;
|
||||
|
@ -171,6 +171,14 @@ public class ArgumentUtils {
|
||||
set.add(key, value);
|
||||
}
|
||||
|
||||
// remove any potential "global" context mappings
|
||||
set.remove("server", "global");
|
||||
set.remove("world", "global");
|
||||
set.remove("server", "null");
|
||||
set.remove("world", "null");
|
||||
set.remove("server", "*");
|
||||
set.remove("world", "*");
|
||||
|
||||
// remove excess entries from the set.
|
||||
// (it can only have one server and one world.)
|
||||
List<String> servers = new ArrayList<>(set.getValues("server"));
|
||||
|
@ -40,7 +40,7 @@ import java.util.Optional;
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class InheritanceInfo {
|
||||
public final class InheritanceInfo {
|
||||
public static InheritanceInfo of(@NonNull LocalizedNode node) {
|
||||
return new InheritanceInfo(node.getTristate(), node.getLocation());
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import java.util.UUID;
|
||||
@ToString
|
||||
@EqualsAndHashCode(of = "uuid")
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class UserIdentifier implements Identifiable<UUID> {
|
||||
public final class UserIdentifier implements Identifiable<UUID> {
|
||||
public static UserIdentifier of(UUID uuid, String username) {
|
||||
return new UserIdentifier(uuid, username);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ import java.util.stream.Collectors;
|
||||
@SuppressWarnings("OptionalGetWithoutIsPresent")
|
||||
@ToString(of = {"permission", "value", "override", "server", "world", "expireAt", "contexts"})
|
||||
@EqualsAndHashCode(of = {"permission", "value", "override", "server", "world", "expireAt", "contexts"})
|
||||
public class ImmutableNode implements Node {
|
||||
public final class ImmutableNode implements Node {
|
||||
|
||||
private static boolean shouldApply(String str, boolean applyRegex, String thisStr) {
|
||||
if (str.equalsIgnoreCase(thisStr)) {
|
||||
@ -389,6 +389,11 @@ public class ImmutableNode implements Node {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApply(boolean includeGlobal, boolean includeGlobalWorld, String server, String world, ContextSet context, boolean applyRegex) {
|
||||
return shouldApplyOnServer(server, includeGlobal, applyRegex) && shouldApplyOnWorld(world, includeGlobalWorld, applyRegex) && shouldApplyWithContext(context, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyOnServer(String server, boolean includeGlobal, boolean applyRegex) {
|
||||
if (server == null || server.equals("") || server.equalsIgnoreCase("global")) {
|
||||
|
@ -117,10 +117,6 @@ public abstract class PermissionHolder {
|
||||
/**
|
||||
* The holders persistent nodes.
|
||||
*
|
||||
* <p>These are nodes which are never stored or persisted to a file, and only
|
||||
* last until the end of the objects lifetime. (for a group, that's when the server stops, and for a user, it's when
|
||||
* they log out, or get unloaded.)</p>
|
||||
*
|
||||
* <p>Nodes are mapped by the result of {@link Node#getFullContexts()}, and keys are sorted by the weight of the
|
||||
* ContextSet. ContextSets are ordered first by the presence of a server key, then by the presence of a world
|
||||
* key, and finally by the overall size of the set. Nodes are ordered according to the priority rules
|
||||
@ -345,6 +341,25 @@ public abstract class PermissionHolder {
|
||||
}
|
||||
}
|
||||
|
||||
public LinkedHashSet<Node> flattenAndMergeNodes(ContextSet filter) {
|
||||
LinkedHashSet<Node> set = new LinkedHashSet<>();
|
||||
synchronized (transientNodes) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : transientNodes.asMap().entrySet()) {
|
||||
if (e.getKey().isSatisfiedBy(filter)) {
|
||||
set.addAll(e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (nodes) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : nodes.asMap().entrySet()) {
|
||||
if (e.getKey().isSatisfiedBy(filter)) {
|
||||
set.addAll(e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
public List<Node> flattenNodesToList() {
|
||||
synchronized (nodes) {
|
||||
return new ArrayList<>(nodes.values());
|
||||
@ -387,6 +402,25 @@ public abstract class PermissionHolder {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Node> flattenAndMergeNodesToList(ContextSet filter) {
|
||||
List<Node> set = new ArrayList<>();
|
||||
synchronized (transientNodes) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : transientNodes.asMap().entrySet()) {
|
||||
if (e.getKey().isSatisfiedBy(filter)) {
|
||||
set.addAll(e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (nodes) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : nodes.asMap().entrySet()) {
|
||||
if (e.getKey().isSatisfiedBy(filter)) {
|
||||
set.addAll(e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<Node> predicate) {
|
||||
boolean result;
|
||||
ImmutableSet<Node> before = ImmutableSet.copyOf(flattenNodes());
|
||||
@ -439,28 +473,26 @@ public abstract class PermissionHolder {
|
||||
excludedGroups.add(getObjectName().toLowerCase());
|
||||
}
|
||||
|
||||
// get the objects own nodes
|
||||
flattenTransientNodesToList(context.getContextSet()).stream()
|
||||
.map(n -> ImmutableLocalizedNode.of(n, getObjectName()))
|
||||
.forEach(accumulator::add);
|
||||
|
||||
flattenNodesToList(context.getContextSet()).stream()
|
||||
// get and add the objects own nodes
|
||||
List<Node> nodes = flattenAndMergeNodesToList(context.getContextSet());
|
||||
nodes.stream()
|
||||
.map(n -> ImmutableLocalizedNode.of(n, getObjectName()))
|
||||
.forEach(accumulator::add);
|
||||
|
||||
Contexts contexts = context.getContexts();
|
||||
String server = context.getServer();
|
||||
String world = context.getWorld();
|
||||
|
||||
// screw effectively final
|
||||
Set<String> finalExcludedGroups = excludedGroups;
|
||||
List<LocalizedNode> finalAccumulator = accumulator;
|
||||
mergePermissions().stream()
|
||||
|
||||
// this allows you to negate parent permissions lower down the inheritance tree.
|
||||
// there's no way to distinct the stream below based on a custom comparator.
|
||||
NodeTools.removeIgnoreValue(nodes.iterator());
|
||||
|
||||
nodes.stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyOnServer(server, contexts.isApplyGlobalGroups(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)))
|
||||
.filter(n -> n.shouldApplyOnWorld(world, contexts.isApplyGlobalWorldGroups(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)))
|
||||
.filter(n -> n.shouldApplyWithContext(contexts.getContexts(), false))
|
||||
.filter(n -> !(!contexts.isApplyGlobalGroups() && !n.isServerSpecific()) && !(!contexts.isApplyGlobalWorldGroups() && !n.isWorldSpecific()))
|
||||
.map(Node::getGroupName)
|
||||
.distinct()
|
||||
.map(n -> Optional.ofNullable(plugin.getGroupManager().getIfLoaded(n)))
|
||||
@ -498,8 +530,6 @@ public abstract class PermissionHolder {
|
||||
|
||||
public SortedSet<LocalizedNode> getAllNodes(ExtractedContexts context) {
|
||||
Contexts contexts = context.getContexts();
|
||||
String server = context.getServer();
|
||||
String world = context.getWorld();
|
||||
|
||||
List<LocalizedNode> entries;
|
||||
if (contexts.isApplyGroups()) {
|
||||
@ -508,13 +538,12 @@ public abstract class PermissionHolder {
|
||||
entries = flattenNodesToList(context.getContextSet()).stream().map(n -> ImmutableLocalizedNode.of(n, getObjectName())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
entries.removeIf(node ->
|
||||
!node.isGroupNode() && (
|
||||
!node.shouldApplyOnServer(server, contexts.isIncludeGlobal(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) ||
|
||||
!node.shouldApplyOnWorld(world, contexts.isIncludeGlobalWorld(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) ||
|
||||
!node.shouldApplyWithContext(context.getContextSet(), false)
|
||||
)
|
||||
);
|
||||
if (!contexts.isIncludeGlobal()) {
|
||||
entries.removeIf(n -> !n.isGroupNode() && !n.isServerSpecific());
|
||||
}
|
||||
if (!contexts.isApplyGlobalWorldGroups()) {
|
||||
entries.removeIf(n -> !n.isGroupNode() && !n.isWorldSpecific());
|
||||
}
|
||||
|
||||
NodeTools.removeSamePermission(entries.iterator());
|
||||
SortedSet<LocalizedNode> ret = new TreeSet<>(PriorityComparator.reverse());
|
||||
@ -524,8 +553,6 @@ public abstract class PermissionHolder {
|
||||
|
||||
public Map<String, Boolean> exportNodes(ExtractedContexts context, boolean lowerCase) {
|
||||
Contexts contexts = context.getContexts();
|
||||
String server = context.getServer();
|
||||
String world = context.getWorld();
|
||||
|
||||
List<? extends Node> entries;
|
||||
if (contexts.isApplyGroups()) {
|
||||
@ -534,27 +561,22 @@ public abstract class PermissionHolder {
|
||||
entries = flattenNodesToList(context.getContextSet());
|
||||
}
|
||||
|
||||
entries.removeIf(node ->
|
||||
!node.isGroupNode() && (
|
||||
!node.shouldApplyOnServer(server, contexts.isIncludeGlobal(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) ||
|
||||
!node.shouldApplyOnWorld(world, contexts.isIncludeGlobalWorld(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)) ||
|
||||
!node.shouldApplyWithContext(context.getContextSet(), false)
|
||||
)
|
||||
);
|
||||
if (!contexts.isIncludeGlobal()) {
|
||||
entries.removeIf(n -> !n.isGroupNode() && !n.isServerSpecific());
|
||||
}
|
||||
if (!contexts.isApplyGlobalWorldGroups()) {
|
||||
entries.removeIf(n -> !n.isGroupNode() && !n.isWorldSpecific());
|
||||
}
|
||||
|
||||
Map<String, Boolean> perms = new HashMap<>();
|
||||
|
||||
for (Node node : entries) {
|
||||
String perm = lowerCase ? node.getPermission().toLowerCase() : node.getPermission();
|
||||
if (!perms.containsKey(perm)) {
|
||||
perms.put(perm, node.getValue());
|
||||
|
||||
if (perms.putIfAbsent(perm, node.getValue()) == null) {
|
||||
if (plugin.getConfiguration().get(ConfigKeys.APPLYING_SHORTHAND)) {
|
||||
List<String> sh = node.resolveShorthand();
|
||||
if (!sh.isEmpty()) {
|
||||
sh.stream().map(s -> lowerCase ? s.toLowerCase() : s)
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
sh.stream().map(s -> lowerCase ? s.toLowerCase() : s).forEach(s -> perms.putIfAbsent(s, node.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -580,27 +602,17 @@ public abstract class PermissionHolder {
|
||||
}
|
||||
|
||||
Contexts contexts = context.getContexts();
|
||||
String server = context.getServer();
|
||||
String world = context.getWorld();
|
||||
|
||||
// screw effectively final
|
||||
Set<String> finalExcludedGroups = excludedGroups;
|
||||
MetaAccumulator finalAccumulator = accumulator;
|
||||
|
||||
flattenTransientNodesToList(context.getContextSet()).stream()
|
||||
// get and add the objects own nodes
|
||||
List<Node> nodes = flattenAndMergeNodesToList(context.getContextSet());
|
||||
nodes.stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
|
||||
.filter(n -> n.shouldApplyOnServer(server, contexts.isIncludeGlobal(), false))
|
||||
.filter(n -> n.shouldApplyOnWorld(world, contexts.isIncludeGlobalWorld(), false))
|
||||
.filter(n -> n.shouldApplyWithContext(context.getContextSet(), false))
|
||||
.forEach(n -> finalAccumulator.accumulateNode(ImmutableLocalizedNode.of(n, getObjectName())));
|
||||
|
||||
flattenNodesToList(context.getContextSet()).stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
|
||||
.filter(n -> n.shouldApplyOnServer(server, contexts.isIncludeGlobal(), false))
|
||||
.filter(n -> n.shouldApplyOnWorld(world, contexts.isIncludeGlobalWorld(), false))
|
||||
.filter(n -> n.shouldApplyWithContext(context.getContextSet(), false))
|
||||
.filter(n -> !(!contexts.isIncludeGlobal() && !n.isServerSpecific()) && !(!contexts.isIncludeGlobalWorld() && !n.isWorldSpecific()))
|
||||
.forEach(n -> finalAccumulator.accumulateNode(ImmutableLocalizedNode.of(n, getObjectName())));
|
||||
|
||||
OptionalInt w = getWeight();
|
||||
@ -608,12 +620,14 @@ public abstract class PermissionHolder {
|
||||
accumulator.accumulateWeight(w.getAsInt());
|
||||
}
|
||||
|
||||
mergePermissions().stream()
|
||||
// this allows you to negate parent permissions lower down the inheritance tree.
|
||||
// there's no way to distinct the stream below based on a custom comparator.
|
||||
NodeTools.removeIgnoreValue(nodes.iterator());
|
||||
|
||||
nodes.stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyOnServer(server, contexts.isApplyGlobalGroups(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)))
|
||||
.filter(n -> n.shouldApplyOnWorld(world, contexts.isApplyGlobalWorldGroups(), plugin.getConfiguration().get(ConfigKeys.APPLYING_REGEX)))
|
||||
.filter(n -> n.shouldApplyWithContext(contexts.getContexts(), false))
|
||||
.filter(n -> !(!contexts.isApplyGlobalGroups() && !n.isServerSpecific()) && !(!contexts.isApplyGlobalWorldGroups() && !n.isWorldSpecific()))
|
||||
.map(Node::getGroupName)
|
||||
.distinct()
|
||||
.map(n -> Optional.ofNullable(plugin.getGroupManager().getIfLoaded(n)))
|
||||
|
@ -47,7 +47,7 @@ import java.util.Map;
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class NodeDataHolder {
|
||||
public final class NodeDataHolder {
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
public static NodeDataHolder fromNode(Node node) {
|
||||
|
@ -38,7 +38,7 @@ import java.util.OptionalLong;
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class NodeHeldPermission<T> implements HeldPermission<T> {
|
||||
public final class NodeHeldPermission<T> implements HeldPermission<T> {
|
||||
public static <T> NodeHeldPermission<T> of(T holder, NodeDataHolder nodeDataHolder) {
|
||||
return of(holder, nodeDataHolder.toNode());
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ public abstract class Buffer<T, R> implements Runnable {
|
||||
@Getter
|
||||
@EqualsAndHashCode(of = "object")
|
||||
@AllArgsConstructor
|
||||
private static class BufferedObject<T, R> {
|
||||
private static final class BufferedObject<T, R> {
|
||||
|
||||
@Setter
|
||||
private long bufferTime;
|
||||
|
@ -38,7 +38,7 @@ import me.lucko.luckperms.api.Node;
|
||||
@Getter
|
||||
@ToString
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ImmutableLocalizedNode implements LocalizedNode {
|
||||
public final class ImmutableLocalizedNode implements LocalizedNode {
|
||||
public static ImmutableLocalizedNode of(@NonNull Node node, @NonNull String location) {
|
||||
return new ImmutableLocalizedNode(node, location);
|
||||
}
|
||||
|
@ -311,7 +311,7 @@ public class LuckPermsService implements PermissionService {
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
public static class DescriptionBuilder implements PermissionDescription.Builder {
|
||||
public static final class DescriptionBuilder implements PermissionDescription.Builder {
|
||||
private final LuckPermsService service;
|
||||
private final PluginContainer container;
|
||||
private final Map<String, Tristate> roles = new HashMap<>();
|
||||
@ -365,7 +365,7 @@ public class LuckPermsService implements PermissionService {
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
public static class Description implements PermissionDescription {
|
||||
public static final class Description implements PermissionDescription {
|
||||
private final LuckPermsService service;
|
||||
private final PluginContainer owner;
|
||||
private final String id;
|
||||
|
@ -33,7 +33,7 @@ import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class OptionLookup {
|
||||
public final class OptionLookup {
|
||||
|
||||
private final String key;
|
||||
private final ImmutableContextSet contexts;
|
||||
|
@ -33,7 +33,7 @@ import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class PermissionLookup {
|
||||
public final class PermissionLookup {
|
||||
|
||||
private final String node;
|
||||
private final ImmutableContextSet contexts;
|
||||
|
@ -35,7 +35,7 @@ import java.lang.ref.WeakReference;
|
||||
@ToString(of = "collection")
|
||||
@EqualsAndHashCode(of = "collection")
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
public class SubjectCollectionReference {
|
||||
public final class SubjectCollectionReference {
|
||||
|
||||
@Getter
|
||||
private final String collection;
|
||||
|
@ -40,7 +40,7 @@ import java.util.List;
|
||||
@ToString(of = {"collection", "identifier"})
|
||||
@EqualsAndHashCode(of = {"collection", "identifier"})
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
public class SubjectReference {
|
||||
public final class SubjectReference {
|
||||
public static SubjectReference deserialize(String s) {
|
||||
List<String> parts = Splitter.on('/').limit(2).splitToList(s);
|
||||
return of(parts.get(0), parts.get(1));
|
||||
|
Loading…
Reference in New Issue
Block a user