Remove NodeMap immutable cache

This commit is contained in:
Luck 2020-07-02 12:06:37 +01:00
parent b460e282b1
commit cc08390abe
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
26 changed files with 165 additions and 164 deletions

View File

@ -174,7 +174,7 @@ public class ApiPermissionHolder implements net.luckperms.api.model.PermissionHo
@Override
public @NonNull Map<ImmutableContextSet, Collection<Node>> toMap() {
return ApiPermissionHolder.this.handle.getData(this.dataType).immutable().asMap();
return ApiPermissionHolder.this.handle.getData(this.dataType).asMap();
}
@Override

View File

@ -167,7 +167,7 @@ public class CommandManager {
}
Collection<? extends Group> groups = this.plugin.getGroupManager().getAll().values();
if (groups.size() <= 1 && groups.stream().allMatch(g -> g.normalData().immutable().isEmpty())) {
if (groups.size() <= 1 && groups.stream().allMatch(g -> g.normalData().isEmpty())) {
Message.FIRST_TIME_SETUP.send(sender, label, sender.getName());
} else {
Message.NO_PERMISSION_FOR_SUBCOMMANDS.send(sender);

View File

@ -90,7 +90,7 @@ public class MetaClear extends GenericChildCommand {
type = NodeType.META_OR_CHAT_META;
}
int before = target.normalData().immutable().size();
int before = target.normalData().size();
MutableContextSet context = args.getContextOrDefault(0, plugin);
@ -106,7 +106,7 @@ public class MetaClear extends GenericChildCommand {
target.removeIf(DataType.NORMAL, context, type::matches, false);
}
int changed = before - target.normalData().immutable().size();
int changed = before - target.normalData().size();
if (changed == 1) {
Message.META_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), type.name().toLowerCase(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
} else {

View File

@ -62,7 +62,7 @@ public class HolderClear<T extends PermissionHolder> extends ChildCommand<T> {
return CommandResult.NO_PERMISSION;
}
int before = target.normalData().immutable().size();
int before = target.normalData().size();
MutableContextSet context = args.getContextOrDefault(0, plugin);
@ -78,7 +78,7 @@ public class HolderClear<T extends PermissionHolder> extends ChildCommand<T> {
target.clearNodes(DataType.NORMAL, context, true);
}
int changed = before - target.normalData().immutable().size();
int changed = before - target.normalData().size();
if (changed == 1) {
Message.CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
} else {

View File

@ -84,7 +84,7 @@ public class HolderEditor<T extends PermissionHolder> extends ChildCommand<T> {
Map<UUID, User> users = new LinkedHashMap<>(plugin.getUserManager().getAll());
// only include online players who are in the group
users.values().removeIf(user -> user.normalData().immutable().values().stream().noneMatch(matcher));
users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher));
// fill up with other matching users
if (users.size() < EditorCommand.MAX_USERS) {

View File

@ -77,7 +77,7 @@ public class HolderShowTracks<T extends PermissionHolder> extends ChildCommand<T
if (target.getType() == HolderType.USER) {
// if the holder is a user, we want to query parent groups for tracks
Set<InheritanceNode> nodes = target.normalData().immutableInheritance().values().stream()
Set<InheritanceNode> nodes = target.normalData().inheritanceAsList().stream()
.filter(Node::getValue)
.filter(n -> !n.hasExpiry())
.collect(Collectors.toSet());

View File

@ -62,7 +62,7 @@ public class ParentClear extends GenericChildCommand {
return CommandResult.NO_PERMISSION;
}
int before = target.normalData().immutable().size();
int before = target.normalData().size();
MutableContextSet context = args.getContextOrDefault(0, plugin);
@ -77,7 +77,7 @@ public class ParentClear extends GenericChildCommand {
target.removeIf(DataType.NORMAL, context, NodeType.INHERITANCE::matches, true);
}
int changed = before - target.normalData().immutable().size();
int changed = before - target.normalData().size();
if (changed == 1) {
Message.PARENT_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
} else {

View File

@ -82,7 +82,7 @@ public class ParentClearTrack extends GenericChildCommand {
return CommandResult.STATE_ERROR;
}
int before = target.normalData().immutable().size();
int before = target.normalData().size();
ImmutableContextSet context = args.getContextOrDefault(1, plugin).immutableCopy();
@ -99,7 +99,7 @@ public class ParentClearTrack extends GenericChildCommand {
plugin.getUserManager().giveDefaultIfNeeded(((User) target), false);
}
int changed = before - target.normalData().immutable().size();
int changed = before - target.normalData().size();
if (changed == 1) {
Message.PARENT_CLEAR_TRACK_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), track.getName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);

View File

@ -62,7 +62,7 @@ public class PermissionClear extends GenericChildCommand {
return CommandResult.NO_PERMISSION;
}
int before = target.normalData().immutable().size();
int before = target.normalData().size();
MutableContextSet context = args.getContextOrDefault(0, plugin);
@ -74,7 +74,7 @@ public class PermissionClear extends GenericChildCommand {
target.removeIf(DataType.NORMAL, context.isEmpty() ? null : context, NodeType.PERMISSION::matches, false);
int changed = before - target.normalData().immutable().size();
int changed = before - target.normalData().size();
if (changed == 1) {
Message.PERMISSION_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
} else {

View File

@ -73,7 +73,7 @@ public class GroupClone extends ChildCommand<Group> {
return CommandResult.NO_PERMISSION;
}
newGroup.setNodes(DataType.NORMAL, target.normalData().immutable());
newGroup.setNodes(DataType.NORMAL, target.normalData().asList());
Message.CLONE_SUCCESS.send(sender, target.getName(), newGroup.getName());

View File

@ -79,7 +79,7 @@ public class GroupRename extends ChildCommand<Group> {
return CommandResult.FAILURE;
}
newGroup.setNodes(DataType.NORMAL, target.normalData().immutable());
newGroup.setNodes(DataType.NORMAL, target.normalData().asList());
Message.RENAME_SUCCESS.send(sender, target.getName(), newGroup.getName());

View File

@ -67,7 +67,7 @@ public class GroupSetDisplayName extends ChildCommand<Group> {
String name = args.get(0);
ImmutableContextSet context = args.getContextOrDefault(1, plugin).immutableCopy();
String previousName = target.normalData().immutable().get(context).stream()
String previousName = target.normalData().nodesSetInContext(context).stream()
.filter(NodeType.DISPLAY_NAME::matches)
.map(NodeType.DISPLAY_NAME::cast)
.findFirst()

View File

@ -59,7 +59,7 @@ public class LogNotify extends ChildCommand<Log> {
return false;
}
Optional<? extends Node> node = user.normalData().immutable().get(ImmutableContextSetImpl.EMPTY).stream()
Optional<? extends Node> node = user.normalData().nodesSetInContext(ImmutableContextSetImpl.EMPTY).stream()
.filter(n -> n.getKey().equalsIgnoreCase(IGNORE_NODE))
.findFirst();

View File

@ -176,7 +176,7 @@ public class ApplyEditsCommand extends SingleCommand {
return false;
}
Set<Node> before = new HashSet<>(holder.normalData().immutable().values());
Set<Node> before = holder.normalData().asSet();
Set<Node> after = new HashSet<>(NodeJsonSerializer.deserializeNodes(data.getAsJsonArray("nodes")));
Set<Node> diffAdded = getAdded(before, after);

View File

@ -110,7 +110,7 @@ public class EditorCommand extends SingleCommand {
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.keyStartsWith(filter);
// only include online players matching the permission
users.values().removeIf(user -> user.normalData().immutable().values().stream().noneMatch(matcher));
users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher));
// fill up with other matching users
if (type.includingOffline && users.size() < MAX_USERS) {

View File

@ -72,7 +72,7 @@ public class UserClone extends ChildCommand<User> {
return CommandResult.NO_PERMISSION;
}
otherUser.setNodes(DataType.NORMAL, target.normalData().immutable());
otherUser.setNodes(DataType.NORMAL, target.normalData().asList());
Message.CLONE_SUCCESS.send(sender, target.getFormattedDisplayName(), otherUser.getFormattedDisplayName());

View File

@ -160,7 +160,7 @@ public final class EventDispatcher {
}
public void dispatchGroupDelete(Group group, DeletionCause cause) {
post(GroupDeleteEvent.class, () -> generate(GroupDeleteEvent.class, group.getName(), ImmutableSet.copyOf(group.normalData().immutable().values()), cause));
post(GroupDeleteEvent.class, () -> generate(GroupDeleteEvent.class, group.getName(), ImmutableSet.copyOf(group.normalData().asSet()), cause));
}
public void dispatchGroupLoadAll() {

View File

@ -25,16 +25,12 @@
package me.lucko.luckperms.common.model;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import me.lucko.luckperms.common.cache.Cache;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.context.ContextSetComparator;
import me.lucko.luckperms.common.node.comparator.NodeComparator;
import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
import me.lucko.luckperms.common.query.QueryOptionsImpl;
import net.luckperms.api.context.ContextSatisfyMode;
import net.luckperms.api.context.ContextSet;
@ -48,15 +44,14 @@ import net.luckperms.api.node.types.InheritanceNode;
import net.luckperms.api.query.Flag;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@ -104,40 +99,78 @@ public final class NodeMap {
*/
private final SortedMap<ImmutableContextSet, SortedSet<InheritanceNode>> inheritanceMap = new ConcurrentSkipListMap<>(ContextSetComparator.reverse());
/**
* A cache which holds an immutable copy of the backing map
*/
private final ImmutableSetMultimapCache<ImmutableContextSet, Node> mapCache = new ImmutableSetMultimapCache<>(this.map);
private final ImmutableSetMultimapCache<ImmutableContextSet, InheritanceNode> inheritanceMapCache = new ImmutableSetMultimapCache<>(this.inheritanceMap);
NodeMap(PermissionHolder holder) {
this.holder = holder;
}
public boolean isEmpty() {
return this.map.isEmpty();
}
public int size() {
return this.map.size();
}
public List<Node> asList() {
List<Node> list = new ArrayList<>();
copyTo(list);
return list;
}
public LinkedHashSet<Node> asSet() {
LinkedHashSet<Node> set = new LinkedHashSet<>();
copyTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
copyTo(set);
return set;
}
public SortedSet<Node> asSortedSet() {
SortedSet<Node> set = new TreeSet<>(NodeWithContextComparator.reverse());
copyTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
copyTo(set);
return set;
}
public ImmutableSet<Node> asImmutableSet() {
ImmutableSet.Builder<Node> builder = ImmutableSet.builder();
for (SortedSet<Node> values : this.map.values()) {
builder.addAll(values);
}
return builder.build();
}
public Map<ImmutableContextSet, Collection<Node>> asMap() {
Map<ImmutableContextSet, Collection<Node>> map = new HashMap<>();
for (Map.Entry<ImmutableContextSet, SortedSet<Node>> e : this.map.entrySet()) {
map.put(e.getKey(), new ArrayList<>(e.getValue()));
}
return map;
}
public List<InheritanceNode> inheritanceAsList() {
List<InheritanceNode> set = new ArrayList<>();
copyInheritanceNodesTo(set);
return set;
}
public LinkedHashSet<InheritanceNode> inheritanceAsSet() {
LinkedHashSet<InheritanceNode> set = new LinkedHashSet<>();
copyInheritanceNodesTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
copyInheritanceNodesTo(set);
return set;
}
public SortedSet<InheritanceNode> inheritanceAsSortedSet() {
SortedSet<InheritanceNode> set = new TreeSet<>(NodeWithContextComparator.reverse());
copyInheritanceNodesTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
copyInheritanceNodesTo(set);
return set;
}
public Map<ImmutableContextSet, Collection<InheritanceNode>> inheritanceAsMap() {
Map<ImmutableContextSet, Collection<InheritanceNode>> map = new HashMap<>();
for (Map.Entry<ImmutableContextSet, SortedSet<InheritanceNode>> e : this.inheritanceMap.entrySet()) {
map.put(e.getKey(), new ArrayList<>(e.getValue()));
}
return map;
}
private static boolean flagExcludeTest(Flag flag, String contextKey, QueryOptions filter, ImmutableContextSet contextSet) {
// return true (negative result) if the explicit *include* flag is not set, and if the context set doesn't contain the required context key.
return !filter.flag(flag) && !contextSet.containsKey(contextKey);
@ -159,6 +192,12 @@ public final class NodeMap {
return this.holder.getPlugin().getConfiguration().get(ConfigKeys.CONTEXT_SATISFY_MODE);
}
public void forEach(Consumer<? super Node> consumer) {
for (SortedSet<Node> values : this.map.values()) {
values.forEach(consumer);
}
}
public void forEach(QueryOptions filter, Consumer<? super Node> consumer) {
for (Map.Entry<ImmutableContextSet, SortedSet<Node>> e : this.map.entrySet()) {
if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) {
@ -179,6 +218,12 @@ public final class NodeMap {
}
}
public void copyTo(Collection<? super Node> collection) {
for (SortedSet<Node> values : this.map.values()) {
collection.addAll(values);
}
}
public void copyTo(Collection<? super Node> collection, QueryOptions filter) {
for (Map.Entry<ImmutableContextSet, SortedSet<Node>> e : this.map.entrySet()) {
if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) {
@ -227,6 +272,12 @@ public final class NodeMap {
}
}
public void copyInheritanceNodesTo(Collection<? super InheritanceNode> collection) {
for (SortedSet<InheritanceNode> values : this.inheritanceMap.values()) {
collection.addAll(values);
}
}
public void copyInheritanceNodesTo(Collection<? super InheritanceNode> collection, QueryOptions filter) {
for (Map.Entry<ImmutableContextSet, SortedSet<InheritanceNode>> e : this.inheritanceMap.entrySet()) {
if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) {
@ -239,25 +290,20 @@ public final class NodeMap {
}
}
/**
* Returns an immutable representation of the maps current state.
*
* @return an immutable copy
*/
public ImmutableSetMultimap<ImmutableContextSet, Node> immutable() {
return this.mapCache.get();
public Collection<Node> nodesSetInContext(ContextSet context) {
final SortedSet<Node> values = this.map.get(context.immutableCopy());
if (values == null) {
return ImmutableSet.of();
}
return new ArrayList<>(values);
}
public ImmutableSetMultimap<ImmutableContextSet, InheritanceNode> immutableInheritance() {
return this.inheritanceMapCache.get();
}
/**
* Invalidates the cache
*/
void invalidate() {
this.mapCache.invalidate();
this.inheritanceMapCache.invalidate();
public Collection<InheritanceNode> inheritanceNodesSetInContext(ContextSet context) {
final SortedSet<InheritanceNode> values = this.inheritanceMap.get(context.immutableCopy());
if (values == null) {
return ImmutableSet.of();
}
return new ArrayList<>(values);
}
private Node localise(Node node) {
@ -414,45 +460,4 @@ public final class NodeMap {
return work;
}
private static final class ImmutableSetMultimapCache<K, V> extends Cache<ImmutableSetMultimap<K, V>> {
@SuppressWarnings("rawtypes")
private static final Constructor<ImmutableSetMultimap> IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR;
static {
try {
IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR = ImmutableSetMultimap.class.getDeclaredConstructor(ImmutableMap.class, int.class, Comparator.class);
IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
private final Map<K, ? extends Collection<V>> handle;
private ImmutableSetMultimapCache(Map<K, ? extends Collection<V>> handle) {
this.handle = handle;
}
@Override
protected @NonNull ImmutableSetMultimap<K, V> supply() {
ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
int size = 0;
for (Map.Entry<K, ? extends Collection<V>> entry : this.handle.entrySet()) {
K key = entry.getKey();
ImmutableSet<V> values = ImmutableSet.copyOf(entry.getValue());
if (!values.isEmpty()) {
builder.put(key, values);
size += values.size();
}
}
try {
//noinspection unchecked
return IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR.newInstance(builder.build(), size, null);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
}

View File

@ -25,10 +25,9 @@
package me.lucko.luckperms.common.model;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import me.lucko.luckperms.common.cacheddata.HolderCachedDataManager;
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
@ -39,7 +38,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.query.DataSelector;
import net.luckperms.api.context.ContextSet;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.model.data.DataMutateResult;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
@ -234,9 +232,6 @@ public abstract class PermissionHolder {
public abstract HolderType getType();
protected void invalidateCache() {
this.normalNodes.invalidate();
this.transientNodes.invalidate();
getCachedData().invalidate();
getPlugin().getEventDispatcher().dispatchDataRecalculate(this);
}
@ -251,11 +246,6 @@ public abstract class PermissionHolder {
invalidateCache();
}
public void setNodes(DataType type, Multimap<ImmutableContextSet, ? extends Node> multimap) {
getData(type).setContent(multimap.values());
invalidateCache();
}
public void mergeNodes(DataType type, Iterable<? extends Node> set) {
getData(type).mergeContent(set);
invalidateCache();
@ -446,19 +436,19 @@ public abstract class PermissionHolder {
}
private boolean auditTemporaryNodes(DataType dataType) {
ImmutableCollection<? extends Node> before = getData(dataType).immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
Set<Node> removed = new HashSet<>();
boolean work = getData(dataType).auditTemporaryNodes(removed);
if (work) {
// invalidate
invalidateCache();
// call event
ImmutableCollection<? extends Node> after = getData(dataType).immutable().values();
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
for (Node r : removed) {
this.plugin.getEventDispatcher().dispatchNodeRemove(r, this, dataType, before, after);
}
// invalidate
invalidateCache();
}
return work;
}
@ -468,7 +458,7 @@ public abstract class PermissionHolder {
return Tristate.TRUE;
}
return getData(type).immutable().values().stream()
return getData(type).asList().stream()
.filter(equalityPredicate.equalTo(node))
.findFirst()
.map(n -> Tristate.of(n.getValue())).orElse(Tristate.UNDEFINED);
@ -481,22 +471,23 @@ public abstract class PermissionHolder {
NodeMap data = getData(dataType);
ImmutableCollection<? extends Node> before = data.immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
data.add(node);
invalidateCache();
ImmutableCollection<? extends Node> after = data.immutable().values();
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
if (callEvent) {
this.plugin.getEventDispatcher().dispatchNodeAdd(node, this, dataType, before, after);
}
invalidateCache();
return DataMutateResult.SUCCESS;
}
public DataMutateResult.WithMergedNode setNode(DataType dataType, Node node, TemporaryNodeMergeStrategy mergeStrategy) {
if (node.getExpiry() != null && mergeStrategy != TemporaryNodeMergeStrategy.NONE) {
Node otherMatch = getData(dataType).immutable().values().stream()
Node otherMatch = getData(dataType).asList().stream()
.filter(NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE.equalTo(node))
.findFirst().orElse(null);
@ -522,14 +513,15 @@ public abstract class PermissionHolder {
if (newNode != null) {
// Remove the old Node & add the new one.
ImmutableCollection<? extends Node> before = data.immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
data.replace(newNode, otherMatch);
invalidateCache();
ImmutableCollection<? extends Node> after = data.immutable().values();
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
this.plugin.getEventDispatcher().dispatchNodeAdd(newNode, this, dataType, before, after);
invalidateCache();
return new MergedNodeResult(DataMutateResult.SUCCESS, newNode);
}
}
@ -544,20 +536,21 @@ public abstract class PermissionHolder {
return DataMutateResult.FAIL_LACKS;
}
ImmutableCollection<? extends Node> before = getData(dataType).immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
getData(dataType).remove(node);
invalidateCache();
ImmutableCollection<? extends Node> after = getData(dataType).immutable().values();
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
this.plugin.getEventDispatcher().dispatchNodeRemove(node, this, dataType, before, after);
invalidateCache();
return DataMutateResult.SUCCESS;
}
public DataMutateResult.WithMergedNode unsetNode(DataType dataType, Node node, @Nullable Duration duration) {
if (node.getExpiry() != null && duration != null) {
Node otherMatch = getData(dataType).immutable().values().stream()
Node otherMatch = getData(dataType).asList().stream()
.filter(NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE.equalTo(node))
.findFirst().orElse(null);
@ -570,15 +563,16 @@ public abstract class PermissionHolder {
Node newNode = node.toBuilder().expiry(newExpiry).build();
// Remove the old Node & add the new one.
ImmutableCollection<? extends Node> before = data.immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
data.replace(newNode, otherMatch);
invalidateCache();
ImmutableCollection<? extends Node> after = data.immutable().values();
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
this.plugin.getEventDispatcher().dispatchNodeRemove(otherMatch, this, dataType, before, after);
this.plugin.getEventDispatcher().dispatchNodeAdd(newNode, this, dataType, before, after);
invalidateCache();
return new MergedNodeResult(DataMutateResult.SUCCESS, newNode);
}
}
@ -590,7 +584,7 @@ public abstract class PermissionHolder {
public boolean removeIf(DataType dataType, @Nullable ContextSet contextSet, Predicate<? super Node> predicate, boolean giveDefault) {
NodeMap data = getData(dataType);
ImmutableCollection<? extends Node> before = data.immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
if (contextSet == null) {
if (!data.removeIf(predicate)) {
@ -606,17 +600,17 @@ public abstract class PermissionHolder {
getPlugin().getUserManager().giveDefaultIfNeeded((User) this, false);
}
invalidateCache();
ImmutableCollection<? extends Node> after = data.immutable().values();
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after);
invalidateCache();
return true;
}
public boolean clearNodes(DataType dataType, ContextSet contextSet, boolean giveDefault) {
NodeMap data = getData(dataType);
ImmutableCollection<? extends Node> before = data.immutable().values();
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
if (contextSet == null) {
data.clear();
@ -628,15 +622,11 @@ public abstract class PermissionHolder {
getPlugin().getUserManager().giveDefaultIfNeeded((User) this, false);
}
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after);
invalidateCache();
ImmutableCollection<? extends Node> after = data.immutable().values();
if (before.size() == after.size()) {
return false;
}
this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after);
return true;
}

View File

@ -275,7 +275,7 @@ public final class Track {
}
// find all groups that are inherited by the user in the exact contexts given and applicable to this track
List<InheritanceNode> nodes = user.normalData().immutableInheritance().get(context.immutableCopy()).stream()
List<InheritanceNode> nodes = user.normalData().inheritanceNodesSetInContext(context).stream()
.filter(Node::getValue)
.filter(node -> containsGroup(node.getGroupName()))
.distinct()
@ -340,7 +340,7 @@ public final class Track {
}
// find all groups that are inherited by the user in the exact contexts given and applicable to this track
List<InheritanceNode> nodes = user.normalData().immutableInheritance().get(context.immutableCopy()).stream()
List<InheritanceNode> nodes = user.normalData().inheritanceNodesSetInContext(context).stream()
.filter(Node::getValue)
.filter(node -> containsGroup(node.getGroupName()))
.distinct()

View File

@ -25,8 +25,6 @@
package me.lucko.luckperms.common.model.manager.user;
import com.google.common.collect.ImmutableCollection;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
import me.lucko.luckperms.common.model.User;
@ -40,7 +38,9 @@ import net.luckperms.api.model.data.DataType;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.types.InheritanceNode;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -82,12 +82,14 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
public boolean giveDefaultIfNeeded(User user, boolean save) {
boolean work = false;
Collection<InheritanceNode> globalGroups = user.normalData().inheritanceNodesSetInContext(ImmutableContextSetImpl.EMPTY);
// check that they are actually a member of their primary group, otherwise remove it
if (this.plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION_METHOD).equals("stored")) {
String primaryGroup = user.getCachedData().getMetaData(this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS)).getPrimaryGroup(MetaCheckEvent.Origin.INTERNAL);
boolean memberOfPrimaryGroup = false;
for (InheritanceNode node : user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY)) {
for (InheritanceNode node : globalGroups) {
if (node.getGroupName().equalsIgnoreCase(primaryGroup)) {
memberOfPrimaryGroup = true;
break;
@ -96,7 +98,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
// need to find a new primary group for the user.
if (!memberOfPrimaryGroup) {
String group = user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY).stream()
String group = globalGroups.stream()
.findFirst()
.map(InheritanceNode::getGroupName)
.orElse(null);
@ -112,7 +114,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
// check that all users are member of at least one group
boolean hasGroup = false;
if (user.getPrimaryGroup().getStoredValue().isPresent()) {
hasGroup = !user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY).isEmpty();
hasGroup = !globalGroups.isEmpty();
}
if (!hasGroup) {
@ -163,7 +165,11 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
*/
@Override
public boolean shouldSave(User user) {
ImmutableCollection<Node> nodes = user.normalData().immutable().values();
if (user.normalData().size() != 1) {
return true;
}
List<Node> nodes = user.normalData().asList();
if (nodes.size() != 1) {
return true;
}

View File

@ -245,7 +245,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
data.getNode("name").setValue(user.getUsername().orElse("null"));
data.getNode(this.loader instanceof JsonLoader ? "primaryGroup" : "primary-group").setValue(user.getPrimaryGroup().getStoredValue().orElse(GroupManager.DEFAULT_GROUP_NAME));
writeNodes(data, user.normalData().immutable().values());
writeNodes(data, user.normalData().asList());
saveFile(StorageLocation.USER, user.getUniqueId().toString(), data);
}
} catch (Exception e) {
@ -270,7 +270,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
data.getNode("name").setValue(group.getName());
}
writeNodes(data, group.normalData().immutable().values());
writeNodes(data, group.normalData().asList());
saveFile(StorageLocation.GROUP, name, data);
}
} catch (Exception e) {
@ -321,7 +321,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
data.getNode("name").setValue(group.getName());
}
writeNodes(data, group.normalData().immutable().values());
writeNodes(data, group.normalData().asList());
saveFile(StorageLocation.GROUP, group.getName(), data);
} catch (Exception e) {
throw reportException(group.getName(), e);

View File

@ -650,7 +650,7 @@ public class MongoStorage implements StorageImplementation {
}
private static Document userToDoc(User user) {
List<Document> nodes = user.normalData().immutable().values().stream()
List<Document> nodes = user.normalData().asList().stream()
.map(MongoStorage::nodeToDoc)
.collect(Collectors.toList());
@ -673,7 +673,7 @@ public class MongoStorage implements StorageImplementation {
}
private static Document groupToDoc(Group group) {
List<Document> nodes = group.normalData().immutable().values().stream()
List<Document> nodes = group.normalData().asList().stream()
.map(MongoStorage::nodeToDoc)
.collect(Collectors.toList());

View File

@ -331,7 +331,7 @@ public class SqlStorage implements StorageImplementation {
remote = selectUserPermissions(new HashSet<>(), c, user.getUniqueId());
}
Set<SqlNode> local = user.normalData().immutable().values().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
Set<SqlNode> local = user.normalData().asList().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
Set<SqlNode> missingFromRemote = getMissingFromRemote(local, remote);
Set<SqlNode> missingFromLocal = getMissingFromLocal(local, remote);
@ -463,7 +463,7 @@ public class SqlStorage implements StorageImplementation {
public void saveGroup(Group group) throws SQLException {
group.getIoLock().lock();
try {
if (group.normalData().immutable().isEmpty()) {
if (group.normalData().isEmpty()) {
try (Connection c = this.connectionFactory.getConnection()) {
deleteGroupPermissions(c, group.getName());
}
@ -475,7 +475,7 @@ public class SqlStorage implements StorageImplementation {
remote = selectGroupPermissions(new HashSet<>(), c, group.getName());
}
Set<SqlNode> local = group.normalData().immutable().values().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
Set<SqlNode> local = group.normalData().asList().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
Set<SqlNode> missingFromRemote = getMissingFromRemote(local, remote);
Set<SqlNode> missingFromLocal = getMissingFromLocal(local, remote);

View File

@ -73,7 +73,7 @@ public final class WebEditor {
.add("type", holder.getType().toString())
.add("id", holder.getObjectName())
.add("displayName", holder.getPlainDisplayName())
.add("nodes", NodeJsonSerializer.serializeNodes(holder.normalData().immutable().values()));
.add("nodes", NodeJsonSerializer.serializeNodes(holder.normalData().asList()));
}
private static JObject writeData(Track track) {

View File

@ -98,7 +98,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
@Override
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, Boolean>> getAllPermissions() {
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, Boolean>> permissions = ImmutableMap.builder();
for (Map.Entry<ImmutableContextSet, ? extends Collection<? extends Node>> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) {
for (Map.Entry<ImmutableContextSet, Collection<Node>> entry : this.holder.getData(this.type).asMap().entrySet()) {
ImmutableMap.Builder<String, Boolean> builder = ImmutableMap.builder();
for (Node n : entry.getValue()) {
builder.put(n.getKey(), n.getValue());
@ -111,7 +111,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
@Override
public ImmutableMap<String, Boolean> getPermissions(ImmutableContextSet contexts) {
ImmutableMap.Builder<String, Boolean> builder = ImmutableMap.builder();
for (Node n : this.holder.getData(this.type).immutable().get(contexts)) {
for (Node n : this.holder.getData(this.type).nodesSetInContext(contexts)) {
builder.put(n.getKey(), n.getValue());
}
return builder.build();
@ -159,7 +159,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
@Override
public ImmutableMap<ImmutableContextSet, ImmutableList<LPSubjectReference>> getAllParents() {
ImmutableMap.Builder<ImmutableContextSet, ImmutableList<LPSubjectReference>> parents = ImmutableMap.builder();
for (Map.Entry<ImmutableContextSet, ? extends Collection<? extends InheritanceNode>> entry : this.holder.getData(this.type).immutableInheritance().asMap().entrySet()) {
for (Map.Entry<ImmutableContextSet, Collection<InheritanceNode>> entry : this.holder.getData(this.type).inheritanceAsMap().entrySet()) {
ImmutableList.Builder<LPSubjectReference> builder = ImmutableList.builder();
for (InheritanceNode n : entry.getValue()) {
builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
@ -172,7 +172,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
@Override
public ImmutableList<LPSubjectReference> getParents(ImmutableContextSet contexts) {
ImmutableList.Builder<LPSubjectReference> builder = ImmutableList.builder();
for (InheritanceNode n : this.holder.getData(this.type).immutableInheritance().get(contexts)) {
for (InheritanceNode n : this.holder.getData(this.type).inheritanceNodesSetInContext(contexts)) {
builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
}
return builder.build();
@ -241,7 +241,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
@Override
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, String>> getAllOptions() {
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, String>> options = ImmutableMap.builder();
for (Map.Entry<ImmutableContextSet, ? extends Collection<? extends Node>> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) {
for (Map.Entry<ImmutableContextSet, Collection<Node>> entry : this.holder.getData(this.type).asMap().entrySet()) {
options.put(entry.getKey(), nodesToOptions(entry.getValue()));
}
return options.build();
@ -249,7 +249,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
@Override
public ImmutableMap<String, String> getOptions(ImmutableContextSet contexts) {
return nodesToOptions(this.holder.getData(this.type).immutable().get(contexts));
return nodesToOptions(this.holder.getData(this.type).nodesSetInContext(contexts));
}
private static ImmutableMap<String, String> nodesToOptions(Iterable<? extends Node> nodes) {