Implement Sponge timings

This commit is contained in:
Luck 2016-10-30 19:35:11 +00:00
parent 17b06c39e9
commit 36bc1553c0
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
13 changed files with 818 additions and 603 deletions

View File

@ -53,6 +53,7 @@ import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.LogFactory;
import me.lucko.luckperms.sponge.contexts.WorldCalculator;
import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.timings.LPTimings;
import me.lucko.luckperms.sponge.utils.VersionData;
import org.slf4j.Logger;
import org.spongepowered.api.Game;
@ -102,6 +103,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
private Path configDir;
private Scheduler scheduler = Sponge.getScheduler();
private LPTimings timings;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
@ -126,6 +128,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
public void onEnable(GamePreInitializationEvent event) {
log = LogFactory.wrap(logger);
debugHandler = new DebugHandler();
timings = new LPTimings(this);
getLog().info("Loading configuration...");
configuration = new SpongeConfig(this);

View File

@ -22,12 +22,13 @@
package me.lucko.luckperms.sponge;
import co.aikar.timings.Timing;
import com.google.common.base.Splitter;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandManager;
import me.lucko.luckperms.common.commands.Util;
import me.lucko.luckperms.common.constants.Patterns;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.command.CommandCallable;
import org.spongepowered.api.command.CommandException;
import org.spongepowered.api.command.CommandResult;
@ -42,28 +43,37 @@ import java.util.Optional;
@SuppressWarnings("NullableProblems")
class SpongeCommand extends CommandManager implements CommandCallable {
SpongeCommand(LuckPermsPlugin plugin) {
private final LPSpongePlugin plugin;
SpongeCommand(LPSpongePlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public CommandResult process(CommandSource source, String s) throws CommandException {
onCommand(
SpongeSenderFactory.get(getPlugin()).wrap(source),
"perms",
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(s)),
Callback.empty()
);
return CommandResult.success();
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_COMMAND)) {
onCommand(
SpongeSenderFactory.get(getPlugin()).wrap(source),
"perms",
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(s)),
Callback.empty()
);
return CommandResult.success();
}
}
@Override
public List<String> getSuggestions(CommandSource source, String s, @Nullable Location<World> location) throws CommandException {
return onTabComplete(SpongeSenderFactory.get(getPlugin()).wrap(source), Splitter.on(' ').splitToList(s));
try (Timing ignored = plugin.getTimings().time(LPTiming.COMMAND_TAB_COMPLETE)) {
return onTabComplete(SpongeSenderFactory.get(getPlugin()).wrap(source), Splitter.on(' ').splitToList(s));
}
}
public List<String> getSuggestions(CommandSource source, String s) throws CommandException {
return onTabComplete(SpongeSenderFactory.get(getPlugin()).wrap(source), Splitter.on(' ').splitToList(s));
try (Timing ignored = plugin.getTimings().time(LPTiming.COMMAND_TAB_COMPLETE)) {
return onTabComplete(SpongeSenderFactory.get(getPlugin()).wrap(source), Splitter.on(' ').splitToList(s));
}
}
@Override

View File

@ -22,11 +22,13 @@
package me.lucko.luckperms.sponge;
import co.aikar.timings.Timing;
import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.AbstractListener;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
@ -63,36 +65,38 @@ public class SpongeListener extends AbstractListener {
@SuppressWarnings("deprecation")
@Listener(order = Order.EARLY)
public void onClientLogin(ClientConnectionEvent.Login e) {
final GameProfile player = e.getProfile();
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LOGIN)) {
final GameProfile player = e.getProfile();
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
// Check if the user was loaded successfully.
if (user == null) {
e.setCancelled(true);
e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.toString()));
return;
}
// Check if the user was loaded successfully.
if (user == null) {
e.setCancelled(true);
e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.toString()));
return;
}
// Attempt to pre-process some permissions for the user to save time later. Might not work, but it's better than nothing.
Optional<Player> p = e.getCause().first(Player.class);
if (p.isPresent()) {
MutableContextSet context = MutableContextSet.fromSet(plugin.getContextManager().getApplicableContext(p.get()));
// Attempt to pre-process some permissions for the user to save time later. Might not work, but it's better than nothing.
Optional<Player> p = e.getCause().first(Player.class);
if (p.isPresent()) {
MutableContextSet context = MutableContextSet.fromSet(plugin.getContextManager().getApplicableContext(p.get()));
List<String> worlds = plugin.getGame().getServer().getWorlds().stream()
.map(World::getName)
.collect(Collectors.toList());
List<String> worlds = plugin.getGame().getServer().getWorlds().stream()
.map(World::getName)
.collect(Collectors.toList());
plugin.doAsync(() -> {
UserData data = user.getUserData();
data.preCalculate(plugin.getService().calculateContexts(context));
plugin.doAsync(() -> {
UserData data = user.getUserData();
data.preCalculate(plugin.getService().calculateContexts(context));
for (String world : worlds) {
MutableContextSet modified = MutableContextSet.fromSet(context);
modified.removeAll("world");
modified.add("world", world);
data.preCalculate(plugin.getService().calculateContexts(modified));
}
});
for (String world : worlds) {
MutableContextSet modified = MutableContextSet.fromSet(context);
modified.removeAll("world");
modified.add("world", world);
data.preCalculate(plugin.getService().calculateContexts(modified));
}
});
}
}
}
@ -104,7 +108,9 @@ public class SpongeListener extends AbstractListener {
@Listener(order = Order.LAST)
public void onClientLeave(ClientConnectionEvent.Disconnect e) {
onLeave(e.getTargetEntity().getUniqueId());
plugin.getService().getUserSubjects().unload(plugin.getUuidCache().getUUID(e.getTargetEntity().getUniqueId()));
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LEAVE)) {
onLeave(e.getTargetEntity().getUniqueId());
plugin.getService().getUserSubjects().unload(plugin.getUuidCache().getUUID(e.getTargetEntity().getUniqueId()));
}
}
}

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.sponge.service;
import co.aikar.timings.Timing;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
@ -30,6 +31,7 @@ import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.permission.NodeTree;
import org.spongepowered.api.service.permission.Subject;
@ -81,72 +83,82 @@ public class LuckPermsGroupSubject extends LuckPermsSubject {
@Override
public Tristate getPermissionValue(ContextSet contexts, String permission) {
Map<String, Boolean> permissions = group.getAllNodesFiltered(service.calculateContexts(contexts)).stream()
.map(LocalizedNode::getNode)
.collect(Collectors.toMap(Node::getPermission, Node::getValue));
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.GROUP_GET_PERMISSION_VALUE)) {
Map<String, Boolean> permissions = group.getAllNodesFiltered(service.calculateContexts(contexts)).stream()
.map(LocalizedNode::getNode)
.collect(Collectors.toMap(Node::getPermission, Node::getValue));
Tristate t = NodeTree.of(permissions).get(permission);
if (t != Tristate.UNDEFINED) {
Tristate t = NodeTree.of(permissions).get(permission);
if (t != Tristate.UNDEFINED) {
return t;
}
t = service.getGroupSubjects().getDefaults().getPermissionValue(LuckPermsService.convertContexts(contexts), permission);
if (t != Tristate.UNDEFINED) {
return t;
}
t = service.getDefaults().getPermissionValue(LuckPermsService.convertContexts(contexts), permission);
return t;
}
t = service.getGroupSubjects().getDefaults().getPermissionValue(LuckPermsService.convertContexts(contexts), permission);
if (t != Tristate.UNDEFINED) {
return t;
}
t = service.getDefaults().getPermissionValue(LuckPermsService.convertContexts(contexts), permission);
return t;
}
@Override
public boolean isChildOf(ContextSet contexts, Subject parent) {
return parent instanceof LuckPermsGroupSubject && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean();
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.GROUP_IS_CHILD_OF)) {
return parent instanceof LuckPermsGroupSubject && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean();
}
}
@Override
public List<Subject> getParents(ContextSet contexts) {
List<Subject> subjects = group.getAllNodesFiltered(service.calculateContexts(contexts)).stream()
.map(LocalizedNode::getNode)
.filter(Node::isGroupNode)
.map(Node::getGroupName)
.map(s -> service.getGroupSubjects().get(s))
.collect(Collectors.toList());
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.GROUP_GET_PARENTS)) {
List<Subject> subjects = group.getAllNodesFiltered(service.calculateContexts(contexts)).stream()
.map(LocalizedNode::getNode)
.filter(Node::isGroupNode)
.map(Node::getGroupName)
.map(s -> service.getGroupSubjects().get(s))
.collect(Collectors.toList());
subjects.addAll(service.getGroupSubjects().getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
subjects.addAll(service.getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
subjects.addAll(service.getGroupSubjects().getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
subjects.addAll(service.getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
return ImmutableList.copyOf(subjects);
return ImmutableList.copyOf(subjects);
}
}
@Override
public Optional<String> getOption(ContextSet contexts, String s) {
Optional<String> option;
if (s.equalsIgnoreCase("prefix")) {
option = getChatMeta(contexts, true);
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.GROUP_GET_OPTION)) {
Optional<String> option;
if (s.equalsIgnoreCase("prefix")) {
option = getChatMeta(contexts, true);
} else if (s.equalsIgnoreCase("suffix")) {
option = getChatMeta(contexts, false);
} else if (s.equalsIgnoreCase("suffix")) {
option = getChatMeta(contexts, false);
} else {
option = getMeta(contexts, s);
} else {
option = getMeta(contexts, s);
}
if (option.isPresent()) {
return option;
}
option = service.getGroupSubjects().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
if (option.isPresent()) {
return option;
}
return service.getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
}
if (option.isPresent()) {
return option;
}
option = service.getGroupSubjects().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
if (option.isPresent()) {
return option;
}
return service.getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
}
@Override
public ContextSet getActiveContextSet() {
return service.getPlugin().getContextManager().getApplicableContext(this);
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.GROUP_GET_ACTIVE_CONTEXTS)) {
return service.getPlugin().getContextManager().getApplicableContext(this);
}
}
private Optional<String> getChatMeta(ContextSet contexts, boolean prefix) {

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.sponge.service;
import co.aikar.timings.Timing;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@ -38,6 +39,7 @@ import me.lucko.luckperms.sponge.service.collections.UserCollection;
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
import me.lucko.luckperms.sponge.service.persisted.SubjectStorage;
import me.lucko.luckperms.sponge.service.simple.SimpleCollection;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.context.ContextCalculator;
@ -101,7 +103,9 @@ public class LuckPermsService implements PermissionService {
@Override
public SubjectCollection getSubjects(String s) {
return collections.getUnchecked(s.toLowerCase());
try (Timing ignored = plugin.getTimings().time(LPTiming.GET_SUBJECTS)) {
return collections.getUnchecked(s.toLowerCase());
}
}
@Override

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.sponge.service;
import co.aikar.timings.Timing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@ -34,6 +35,7 @@ import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectData;
@ -63,437 +65,448 @@ public class LuckPermsSubjectData implements SubjectData {
@Override
public Map<Set<Context>, Map<String, Boolean>> getAllPermissions() {
Map<Set<Context>, Map<String, Boolean>> perms = new HashMap<>();
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PERMISSIONS)) {
Map<Set<Context>, Map<String, Boolean>> perms = new HashMap<>();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (!perms.containsKey(contexts)) {
perms.put(contexts, new HashMap<>());
}
perms.get(contexts).put(n.getPermission(), n.getValue());
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
ImmutableMap.Builder<Set<Context>, Map<String, Boolean>> map = ImmutableMap.builder();
for (Map.Entry<Set<Context>, Map<String, Boolean>> e : perms.entrySet()) {
map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue()));
}
if (!perms.containsKey(contexts)) {
perms.put(contexts, new HashMap<>());
}
perms.get(contexts).put(n.getPermission(), n.getValue());
return map.build();
}
ImmutableMap.Builder<Set<Context>, Map<String, Boolean>> map = ImmutableMap.builder();
for (Map.Entry<Set<Context>, Map<String, Boolean>> e : perms.entrySet()) {
map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue()));
}
return map.build();
}
@Override
public Map<String, Boolean> getPermissions(Set<Context> contexts) {
ImmutableMap.Builder<String, Boolean> permissions = ImmutableMap.builder();
(enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(n -> n.shouldApplyWithContext(LuckPermsService.convertContexts(contexts), true))
.forEach(n -> permissions.put(n.getKey(), n.getValue()));
return permissions.build();
return getAllPermissions().getOrDefault(contexts, ImmutableMap.of());
}
@Override
public boolean setPermission(Set<Context> set, String s, Tristate tristate) {
if (tristate == Tristate.UNDEFINED) {
// Unset
Node.Builder builder = new me.lucko.luckperms.common.core.Node.Builder(s);
public boolean setPermission(Set<Context> contexts, String permission, Tristate tristate) {
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_PERMISSION)) {
if (tristate == Tristate.UNDEFINED) {
// Unset
Node.Builder builder = new me.lucko.luckperms.common.core.Node.Builder(permission);
for (Context ct : set) {
for (Context ct : contexts) {
builder.withExtraContext(ct.getKey(), ct.getValue());
}
try {
if (enduring) {
holder.unsetPermission(builder.build());
} else {
holder.unsetTransientPermission(builder.build());
}
} catch (ObjectLacksException ignored) {}
objectSave(holder);
return true;
}
Node.Builder builder = new me.lucko.luckperms.common.core.Node.Builder(permission)
.setValue(tristate.asBoolean());
for (Context ct : contexts) {
builder.withExtraContext(ct.getKey(), ct.getValue());
}
try {
if (enduring) {
holder.unsetPermission(builder.build());
holder.setPermission(builder.build());
} else {
holder.unsetTransientPermission(builder.build());
}
} catch (ObjectLacksException ignored) {}
objectSave(holder);
return true;
}
Node.Builder builder = new me.lucko.luckperms.common.core.Node.Builder(s)
.setValue(tristate.asBoolean());
for (Context ct : set) {
builder.withExtraContext(ct.getKey(), ct.getValue());
}
try {
if (enduring) {
holder.setPermission(builder.build());
} else {
holder.setTransientPermission(builder.build());
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(holder);
return true;
}
@Override
public boolean clearPermissions() {
if (enduring) {
holder.clearNodes();
} else {
holder.clearTransientNodes();
}
objectSave(holder);
return true;
}
@Override
public boolean clearPermissions(Set<Context> contexts) {
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(node -> node.shouldApplyWithContext(LuckPermsService.convertContexts(contexts)))
.collect(Collectors.toList());
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
if (holder instanceof User) {
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
}
objectSave(holder);
return !toRemove.isEmpty();
}
@Override
public Map<Set<Context>, List<Subject>> getAllParents() {
Map<Set<Context>, List<Subject>> parents = new HashMap<>();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.isGroupNode()) {
continue;
}
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (!parents.containsKey(contexts)) {
parents.put(contexts, new ArrayList<>());
}
parents.get(contexts).add(service.getGroupSubjects().get(n.getGroupName()));
}
ImmutableMap.Builder<Set<Context>, List<Subject>> map = ImmutableMap.builder();
for (Map.Entry<Set<Context>, List<Subject>> e : parents.entrySet()) {
map.put(ImmutableSet.copyOf(e.getKey()), ImmutableList.copyOf(e.getValue()));
}
return map.build();
}
@Override
public List<Subject> getParents(Set<Context> contexts) {
ImmutableList.Builder<Subject> parents = ImmutableList.builder();
(enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(Node::isGroupNode)
.filter(n -> n.shouldApplyWithContext(LuckPermsService.convertContexts(contexts), true))
.forEach(n -> parents.add(service.getGroupSubjects().get(n.getGroupName())));
return parents.build();
}
@Override
public boolean addParent(Set<Context> set, Subject subject) {
if (subject instanceof LuckPermsGroupSubject) {
LuckPermsGroupSubject permsSubject = ((LuckPermsGroupSubject) subject);
ContextSet contexts = LuckPermsService.convertContexts(set);
try {
if (enduring) {
holder.setPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
} else {
holder.setTransientPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
holder.setTransientPermission(builder.build());
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(holder);
return true;
}
return false;
}
@Override
public boolean clearPermissions() {
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) {
if (enduring) {
holder.clearNodes();
} else {
holder.clearTransientNodes();
}
objectSave(holder);
return true;
}
}
@Override
public boolean clearPermissions(Set<Context> c) {
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) {
List<Node> toRemove = new ArrayList<>();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (contexts.equals(c)) {
toRemove.add(n);
}
}
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
if (holder instanceof User) {
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
}
objectSave(holder);
return !toRemove.isEmpty();
}
}
@Override
public Map<Set<Context>, List<Subject>> getAllParents() {
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PARENTS)) {
Map<Set<Context>, List<Subject>> parents = new HashMap<>();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.isGroupNode()) {
continue;
}
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (!parents.containsKey(contexts)) {
parents.put(contexts, new ArrayList<>());
}
parents.get(contexts).add(service.getGroupSubjects().get(n.getGroupName()));
}
ImmutableMap.Builder<Set<Context>, List<Subject>> map = ImmutableMap.builder();
for (Map.Entry<Set<Context>, List<Subject>> e : parents.entrySet()) {
map.put(ImmutableSet.copyOf(e.getKey()), ImmutableList.copyOf(e.getValue()));
}
return map.build();
}
}
@Override
public List<Subject> getParents(Set<Context> contexts) {
return getAllParents().getOrDefault(contexts, ImmutableList.of());
}
@Override
public boolean addParent(Set<Context> set, Subject subject) {
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_ADD_PARENT)) {
if (subject instanceof LuckPermsGroupSubject) {
LuckPermsGroupSubject permsSubject = ((LuckPermsGroupSubject) subject);
ContextSet contexts = LuckPermsService.convertContexts(set);
try {
if (enduring) {
holder.setPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
} else {
holder.setTransientPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(holder);
return true;
}
return false;
}
}
@Override
public boolean removeParent(Set<Context> set, Subject subject) {
if (subject instanceof LuckPermsGroupSubject) {
LuckPermsGroupSubject permsSubject = ((LuckPermsGroupSubject) subject);
ContextSet contexts = LuckPermsService.convertContexts(set);
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_REMOVE_PARENT)) {
if (subject instanceof LuckPermsGroupSubject) {
LuckPermsGroupSubject permsSubject = ((LuckPermsGroupSubject) subject);
ContextSet contexts = LuckPermsService.convertContexts(set);
try {
if (enduring) {
holder.unsetPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
} else {
holder.unsetTransientPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
}
} catch (ObjectLacksException ignored) {}
try {
if (enduring) {
holder.unsetPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
} else {
holder.unsetTransientPermission(new me.lucko.luckperms.common.core.Node.Builder("group." + permsSubject.getIdentifier())
.withExtraContext(contexts)
.build());
}
} catch (ObjectLacksException ignored) {}
objectSave(holder);
return true;
objectSave(holder);
return true;
}
return false;
}
return false;
}
@Override
public boolean clearParents() {
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(Node::isGroupNode)
.collect(Collectors.toList());
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) {
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(Node::isGroupNode)
.collect(Collectors.toList());
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
if (holder instanceof User) {
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
if (holder instanceof User) {
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
}
objectSave(holder);
return !toRemove.isEmpty();
}
objectSave(holder);
return !toRemove.isEmpty();
}
@Override
public boolean clearParents(Set<Context> set) {
ContextSet context = LuckPermsService.convertContexts(set);
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(Node::isGroupNode)
.filter(node -> node.shouldApplyWithContext(context))
.collect(Collectors.toList());
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) {
List<Node> toRemove = new ArrayList<>();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.isGroupNode()) {
continue;
}
} catch (ObjectLacksException ignored) {}
});
if (holder instanceof User) {
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (contexts.equals(set)) {
toRemove.add(n);
}
}
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
if (holder instanceof User) {
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
}
objectSave(holder);
return !toRemove.isEmpty();
}
objectSave(holder);
return !toRemove.isEmpty();
}
@Override
public Map<Set<Context>, Map<String, String>> getAllOptions() {
Map<Set<Context>, Map<String, String>> options = new HashMap<>();
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_OPTIONS)) {
Map<Set<Context>, Map<String, String>> options = new HashMap<>();
int prefixPriority = Integer.MIN_VALUE;
int suffixPriority = Integer.MIN_VALUE;
int prefixPriority = Integer.MIN_VALUE;
int suffixPriority = Integer.MIN_VALUE;
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.getValue()) {
continue;
}
if (!n.isMeta() || !n.isPrefix() || n.isSuffix()) {
continue;
}
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (!options.containsKey(contexts)) {
options.put(contexts, new HashMap<>());
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
if (value.getKey() > prefixPriority) {
options.get(contexts).put("prefix", value.getValue());
prefixPriority = value.getKey();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.getValue()) {
continue;
}
continue;
}
if (n.isSuffix()) {
Map.Entry<Integer, String> value = n.getSuffix();
if (value.getKey() > suffixPriority) {
options.get(contexts).put("suffix", value.getValue());
suffixPriority = value.getKey();
if (!n.isMeta() || !n.isPrefix() || n.isSuffix()) {
continue;
}
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (!options.containsKey(contexts)) {
options.put(contexts, new HashMap<>());
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
if (value.getKey() > prefixPriority) {
options.get(contexts).put("prefix", value.getValue());
prefixPriority = value.getKey();
}
continue;
}
if (n.isSuffix()) {
Map.Entry<Integer, String> value = n.getSuffix();
if (value.getKey() > suffixPriority) {
options.get(contexts).put("suffix", value.getValue());
suffixPriority = value.getKey();
}
continue;
}
if (n.isMeta()) {
Map.Entry<String, String> meta = n.getMeta();
options.get(contexts).put(meta.getKey(), meta.getValue());
}
continue;
}
if (n.isMeta()) {
Map.Entry<String, String> meta = n.getMeta();
options.get(contexts).put(meta.getKey(), meta.getValue());
ImmutableMap.Builder<Set<Context>, Map<String, String>> map = ImmutableMap.builder();
for (Map.Entry<Set<Context>, Map<String, String>> e : options.entrySet()) {
map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue()));
}
return map.build();
}
ImmutableMap.Builder<Set<Context>, Map<String, String>> map = ImmutableMap.builder();
for (Map.Entry<Set<Context>, Map<String, String>> e : options.entrySet()) {
map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue()));
}
return map.build();
}
@Override
public Map<String, String> getOptions(Set<Context> set) {
ImmutableMap.Builder<String, String> options = ImmutableMap.builder();
ContextSet contexts = LuckPermsService.convertContexts(set);
int prefixPriority = Integer.MIN_VALUE;
int suffixPriority = Integer.MIN_VALUE;
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.getValue()) {
continue;
}
if (!n.isMeta() || !n.isPrefix() || n.isSuffix()) {
continue;
}
if (!n.shouldApplyWithContext(contexts, true)) {
continue;
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
if (value.getKey() > prefixPriority) {
options.put("prefix", value.getValue());
prefixPriority = value.getKey();
}
continue;
}
if (n.isSuffix()) {
Map.Entry<Integer, String> value = n.getSuffix();
if (value.getKey() > suffixPriority) {
options.put("suffix", value.getValue());
suffixPriority = value.getKey();
}
continue;
}
if (n.isMeta()) {
Map.Entry<String, String> meta = n.getMeta();
options.put(meta.getKey(), meta.getValue());
}
}
return options.build();
return getAllOptions().getOrDefault(set, ImmutableMap.of());
}
@Override
public boolean setOption(Set<Context> set, String key, String value) {
ContextSet context = LuckPermsService.convertContexts(set);
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) {
ContextSet context = LuckPermsService.convertContexts(set);
key = escapeCharacters(key);
value = escapeCharacters(value);
key = escapeCharacters(key);
value = escapeCharacters(value);
try {
if (enduring) {
holder.setPermission(new me.lucko.luckperms.common.core.Node.Builder("meta." + key + "." + value)
.withExtraContext(context)
.build()
);
} else {
holder.setTransientPermission(new me.lucko.luckperms.common.core.Node.Builder("meta." + key + "." + value)
.withExtraContext(context)
.build()
);
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(holder);
return true;
try {
if (enduring) {
holder.setPermission(new me.lucko.luckperms.common.core.Node.Builder("meta." + key + "." + value)
.withExtraContext(context)
.build()
);
} else {
holder.setTransientPermission(new me.lucko.luckperms.common.core.Node.Builder("meta." + key + "." + value)
.withExtraContext(context)
.build()
);
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(holder);
return true;
}
}
@Override
public boolean clearOptions(Set<Context> set) {
ContextSet context = LuckPermsService.convertContexts(set);
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
.filter(node -> node.shouldApplyWithContext(context))
.collect(Collectors.toList());
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) {
List<Node> toRemove = new ArrayList<>();
for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) {
if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) {
continue;
}
} catch (ObjectLacksException ignored) {}
});
objectSave(holder);
return !toRemove.isEmpty();
Set<Context> contexts = LuckPermsService.convertContexts(n.getContexts());
if (n.isServerSpecific()) {
contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get()));
}
if (n.isWorldSpecific()) {
contexts.add(new Context(Context.WORLD_KEY, n.getWorld().get()));
}
if (contexts.equals(set)) {
toRemove.add(n);
}
}
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
objectSave(holder);
return !toRemove.isEmpty();
}
}
@Override
public boolean clearOptions() {
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
.collect(Collectors.toList());
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) {
List<Node> toRemove = (enduring ? holder.getNodes() : holder.getTransientNodes()).stream()
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
.collect(Collectors.toList());
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
toRemove.forEach(n -> {
try {
if (enduring) {
holder.unsetPermission(n);
} else {
holder.unsetTransientPermission(n);
}
} catch (ObjectLacksException ignored) {}
});
objectSave(holder);
return !toRemove.isEmpty();
objectSave(holder);
return !toRemove.isEmpty();
}
}
}

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.sponge.service;
import co.aikar.timings.Timing;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
@ -29,6 +30,7 @@ import lombok.Getter;
import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.entity.living.player.Player;
@ -61,15 +63,6 @@ public class LuckPermsUserSubject extends LuckPermsSubject {
this.transientSubjectData = new LuckPermsSubjectData(false, service, user);
}
public void deprovision() {
/* For some reason, Sponge holds onto User instances in a cache, which in turn, prevents LuckPerms data from being GCed.
As well as unloading, we also remove all references to the User instances. */
user = null;
service = null;
subjectData = null;
transientSubjectData = null;
}
private boolean hasData() {
return user.getUserData() != null;
}
@ -98,70 +91,82 @@ public class LuckPermsUserSubject extends LuckPermsSubject {
@Override
public Tristate getPermissionValue(ContextSet contexts, String permission) {
return !hasData() ?
Tristate.UNDEFINED :
LuckPermsService.convertTristate(user.getUserData().getPermissionData(service.calculateContexts(contexts)).getPermissionValue(permission));
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.USER_GET_PERMISSION_VALUE)) {
return !hasData() ?
Tristate.UNDEFINED :
LuckPermsService.convertTristate(
user.getUserData().getPermissionData(service.calculateContexts(contexts)).getPermissionValue(permission)
);
}
}
@Override
public boolean isChildOf(ContextSet contexts, Subject parent) {
return parent instanceof LuckPermsGroupSubject && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean();
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.USER_IS_CHILD_OF)) {
return parent instanceof LuckPermsGroupSubject && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean();
}
}
@Override
public List<Subject> getParents(ContextSet contexts) {
ImmutableList.Builder<Subject> subjects = ImmutableList.builder();
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.USER_GET_PARENTS)) {
ImmutableList.Builder<Subject> subjects = ImmutableList.builder();
if (hasData()) {
for (String perm : user.getUserData().getPermissionData(service.calculateContexts(contexts)).getImmutableBacking().keySet()) {
if (!perm.startsWith("group.")) {
continue;
}
if (hasData()) {
for (String perm : user.getUserData().getPermissionData(service.calculateContexts(contexts)).getImmutableBacking().keySet()) {
if (!perm.startsWith("group.")) {
continue;
}
String groupName = perm.substring("group.".length());
if (service.getPlugin().getGroupManager().isLoaded(groupName)) {
subjects.add(service.getGroupSubjects().get(groupName));
String groupName = perm.substring("group.".length());
if (service.getPlugin().getGroupManager().isLoaded(groupName)) {
subjects.add(service.getGroupSubjects().get(groupName));
}
}
}
subjects.addAll(service.getUserSubjects().getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
subjects.addAll(service.getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
return subjects.build();
}
subjects.addAll(service.getUserSubjects().getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
subjects.addAll(service.getDefaults().getParents(LuckPermsService.convertContexts(contexts)));
return subjects.build();
}
@Override
public Optional<String> getOption(ContextSet contexts, String s) {
if (hasData()) {
MetaData data = user.getUserData().getMetaData(service.calculateContexts(contexts));
if (s.equalsIgnoreCase("prefix")) {
if (data.getPrefix() != null) {
return Optional.of(data.getPrefix());
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.USER_GET_OPTION)) {
if (hasData()) {
MetaData data = user.getUserData().getMetaData(service.calculateContexts(contexts));
if (s.equalsIgnoreCase("prefix")) {
if (data.getPrefix() != null) {
return Optional.of(data.getPrefix());
}
}
if (s.equalsIgnoreCase("suffix")) {
if (data.getSuffix() != null) {
return Optional.of(data.getSuffix());
}
}
if (data.getMeta().containsKey(s)) {
return Optional.of(data.getMeta().get(s));
}
}
if (s.equalsIgnoreCase("suffix")) {
if (data.getSuffix() != null) {
return Optional.of(data.getSuffix());
}
Optional<String> v = service.getUserSubjects().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
if (v.isPresent()) {
return v;
}
if (data.getMeta().containsKey(s)) {
return Optional.of(data.getMeta().get(s));
}
return service.getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
}
Optional<String> v = service.getUserSubjects().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
if (v.isPresent()) {
return v;
}
return service.getDefaults().getOption(LuckPermsService.convertContexts(contexts), s);
}
@Override
public ContextSet getActiveContextSet() {
return service.getPlugin().getContextManager().getApplicableContext(this);
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.USER_GET_ACTIVE_CONTEXTS)) {
return service.getPlugin().getContextManager().getApplicableContext(this);
}
}
}

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.sponge.service.collections;
import co.aikar.timings.Timing;
import lombok.NonNull;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.groups.GroupManager;
@ -29,6 +30,7 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.LuckPermsGroupSubject;
import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.simple.SimpleCollection;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
@ -58,11 +60,13 @@ public class GroupCollection implements SubjectCollection {
@Override
public Subject get(@NonNull String id) {
if (manager.isLoaded(id)) {
return LuckPermsGroupSubject.wrapGroup(manager.get(id), service);
}
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.GROUP_COLLECTION_GET)) {
if (manager.isLoaded(id)) {
return LuckPermsGroupSubject.wrapGroup(manager.get(id), service);
}
return fallback.get(id);
return fallback.get(id);
}
}
@Override

View File

@ -22,11 +22,13 @@
package me.lucko.luckperms.sponge.service.collections;
import co.aikar.timings.Timing;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import lombok.NonNull;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.commands.Util;
@ -36,6 +38,7 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.LuckPermsUserSubject;
import me.lucko.luckperms.sponge.service.simple.SimpleCollection;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
@ -71,7 +74,7 @@ public class UserCollection implements SubjectCollection {
public LuckPermsUserSubject load(UUID uuid) throws Exception {
User user = manager.get(uuid);
if (user == null) {
throw new IllegalStateException("user not loaded");
throw new IllegalStateException("User not loaded");
}
return LuckPermsUserSubject.wrapUser(user, service);
@ -100,13 +103,15 @@ public class UserCollection implements SubjectCollection {
@Override
public Subject get(@NonNull String id) {
Optional<Subject> s = getIfLoaded(id);
if (s.isPresent()) {
return s.get();
}
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.USER_COLLECTION_GET)) {
Optional<Subject> s = getIfLoaded(id);
if (s.isPresent()) {
return s.get();
}
// Fallback to the other collection. This Subject instance will never be persisted.
return fallback.get(id);
// Fallback to the other collection. This Subject instance will never be persisted.
return fallback.get(id);
}
}
private Optional<Subject> getIfLoaded(String id) {
@ -135,7 +140,7 @@ public class UserCollection implements SubjectCollection {
UUID internal = service.getPlugin().getUuidCache().getUUID(uuid);
try {
return Optional.of(users.get(internal));
} catch (ExecutionException e) {
} catch (ExecutionException | UncheckedExecutionException e) {
return Optional.empty();
}
}

View File

@ -22,11 +22,13 @@
package me.lucko.luckperms.sponge.service.persisted;
import co.aikar.timings.Timing;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.MemorySubjectData;
@ -95,96 +97,106 @@ public class PersistedSubject implements Subject {
@Override
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String node) {
Tristate res = subjectData.getNodeTree(contexts).get(node);
if (res != Tristate.UNDEFINED) {
return res;
}
res = transientSubjectData.getNodeTree(contexts).get(node);
if (res != Tristate.UNDEFINED) {
return res;
}
for (Subject parent : getParents(contexts)) {
Tristate tempRes = parent.getPermissionValue(contexts, node);
if (tempRes != Tristate.UNDEFINED) {
return tempRes;
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_PERMISSION_VALUE)) {
Tristate res = subjectData.getNodeTree(contexts).get(node);
if (res != Tristate.UNDEFINED) {
return res;
}
}
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Tristate.UNDEFINED;
}
res = transientSubjectData.getNodeTree(contexts).get(node);
if (res != Tristate.UNDEFINED) {
return res;
}
res = service.getGroupSubjects().getDefaults().getPermissionValue(contexts, node);
if (res != Tristate.UNDEFINED) {
for (Subject parent : getParents(contexts)) {
Tristate tempRes = parent.getPermissionValue(contexts, node);
if (tempRes != Tristate.UNDEFINED) {
return tempRes;
}
}
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Tristate.UNDEFINED;
}
res = service.getGroupSubjects().getDefaults().getPermissionValue(contexts, node);
if (res != Tristate.UNDEFINED) {
return res;
}
res = service.getDefaults().getPermissionValue(contexts, node);
return res;
}
res = service.getDefaults().getPermissionValue(contexts, node);
return res;
}
@Override
public boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject subject) {
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return subjectData.getParents(contexts).contains(subject) ||
transientSubjectData.getParents(contexts).contains(subject);
} else {
return subjectData.getParents(contexts).contains(subject) ||
transientSubjectData.getParents(contexts).contains(subject) ||
getContainingCollection().getDefaults().getParents(contexts).contains(subject) ||
service.getDefaults().getParents(contexts).contains(subject);
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_IS_CHILD_OF)) {
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return subjectData.getParents(contexts).contains(subject) ||
transientSubjectData.getParents(contexts).contains(subject);
} else {
return subjectData.getParents(contexts).contains(subject) ||
transientSubjectData.getParents(contexts).contains(subject) ||
getContainingCollection().getDefaults().getParents(contexts).contains(subject) ||
service.getDefaults().getParents(contexts).contains(subject);
}
}
}
@Override
public List<Subject> getParents(@NonNull Set<Context> contexts) {
List<Subject> s = new ArrayList<>();
s.addAll(subjectData.getParents(contexts));
s.addAll(transientSubjectData.getParents(contexts));
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_PARENTS)) {
List<Subject> s = new ArrayList<>();
s.addAll(subjectData.getParents(contexts));
s.addAll(transientSubjectData.getParents(contexts));
if (!getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
s.addAll(getContainingCollection().getDefaults().getParents(contexts));
s.addAll(service.getDefaults().getParents(contexts));
if (!getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
s.addAll(getContainingCollection().getDefaults().getParents(contexts));
s.addAll(service.getDefaults().getParents(contexts));
}
return ImmutableList.copyOf(s);
}
return ImmutableList.copyOf(s);
}
@Override
public Optional<String> getOption(Set<Context> set, String key) {
Optional<String> res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key));
if (res.isPresent()) {
return res;
}
res = Optional.ofNullable(transientSubjectData.getOptions(getActiveContexts()).get(key));
if (res.isPresent()) {
return res;
}
for (Subject parent : getParents(getActiveContexts())) {
Optional<String> tempRes = parent.getOption(getActiveContexts(), key);
if (tempRes.isPresent()) {
return tempRes;
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_OPTION)) {
Optional<String> res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key));
if (res.isPresent()) {
return res;
}
}
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Optional.empty();
}
res = Optional.ofNullable(transientSubjectData.getOptions(getActiveContexts()).get(key));
if (res.isPresent()) {
return res;
}
res = getContainingCollection().getDefaults().getOption(set, key);
if (res.isPresent()) {
return res;
}
for (Subject parent : getParents(getActiveContexts())) {
Optional<String> tempRes = parent.getOption(getActiveContexts(), key);
if (tempRes.isPresent()) {
return tempRes;
}
}
return service.getDefaults().getOption(set, key);
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Optional.empty();
}
res = getContainingCollection().getDefaults().getOption(set, key);
if (res.isPresent()) {
return res;
}
return service.getDefaults().getOption(set, key);
}
}
@Override
public Set<Context> getActiveContexts() {
return LuckPermsService.convertContexts(service.getPlugin().getContextManager().getApplicableContext(this));
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_ACTIVE_CONTEXTS)) {
return LuckPermsService.convertContexts(service.getPlugin().getContextManager().getApplicableContext(this));
}
}
}

View File

@ -22,10 +22,12 @@
package me.lucko.luckperms.sponge.service.simple;
import co.aikar.timings.Timing;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.timings.LPTiming;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.MemorySubjectData;
@ -74,83 +76,93 @@ public class SimpleSubject implements Subject {
@Override
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String node) {
Tristate res = subjectData.getNodeTree(contexts).get(node);
if (res != Tristate.UNDEFINED) {
return res;
}
for (Subject parent : getParents(contexts)) {
Tristate tempRes = parent.getPermissionValue(contexts, node);
if (tempRes != Tristate.UNDEFINED) {
return tempRes;
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_PERMISSION_VALUE)) {
Tristate res = subjectData.getNodeTree(contexts).get(node);
if (res != Tristate.UNDEFINED) {
return res;
}
}
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Tristate.UNDEFINED;
}
for (Subject parent : getParents(contexts)) {
Tristate tempRes = parent.getPermissionValue(contexts, node);
if (tempRes != Tristate.UNDEFINED) {
return tempRes;
}
}
res = service.getGroupSubjects().getDefaults().getPermissionValue(contexts, node);
if (res != Tristate.UNDEFINED) {
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Tristate.UNDEFINED;
}
res = service.getGroupSubjects().getDefaults().getPermissionValue(contexts, node);
if (res != Tristate.UNDEFINED) {
return res;
}
res = service.getDefaults().getPermissionValue(contexts, node);
return res;
}
res = service.getDefaults().getPermissionValue(contexts, node);
return res;
}
@Override
public boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject subject) {
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return subjectData.getParents(contexts).contains(subject);
} else {
return subjectData.getParents(contexts).contains(subject) ||
getContainingCollection().getDefaults().getParents(contexts).contains(subject) ||
service.getDefaults().getParents(contexts).contains(subject);
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_IS_CHILD_OF)) {
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return subjectData.getParents(contexts).contains(subject);
} else {
return subjectData.getParents(contexts).contains(subject) ||
getContainingCollection().getDefaults().getParents(contexts).contains(subject) ||
service.getDefaults().getParents(contexts).contains(subject);
}
}
}
@Override
public List<Subject> getParents(@NonNull Set<Context> contexts) {
List<Subject> s = new ArrayList<>();
s.addAll(subjectData.getParents(contexts));
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_PARENTS)) {
List<Subject> s = new ArrayList<>();
s.addAll(subjectData.getParents(contexts));
if (!getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")){
s.addAll(getContainingCollection().getDefaults().getParents(contexts));
s.addAll(service.getDefaults().getParents(contexts));
if (!getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")){
s.addAll(getContainingCollection().getDefaults().getParents(contexts));
s.addAll(service.getDefaults().getParents(contexts));
}
return ImmutableList.copyOf(s);
}
return ImmutableList.copyOf(s);
}
@Override
public Optional<String> getOption(Set<Context> set, String key) {
Optional<String> res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key));
if (res.isPresent()) {
return res;
}
for (Subject parent : getParents(getActiveContexts())) {
Optional<String> tempRes = parent.getOption(getActiveContexts(), key);
if (tempRes.isPresent()) {
return tempRes;
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_OPTION)) {
Optional<String> res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key));
if (res.isPresent()) {
return res;
}
}
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Optional.empty();
}
for (Subject parent : getParents(getActiveContexts())) {
Optional<String> tempRes = parent.getOption(getActiveContexts(), key);
if (tempRes.isPresent()) {
return tempRes;
}
}
res = getContainingCollection().getDefaults().getOption(set, key);
if (res.isPresent()) {
return res;
}
if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) {
return Optional.empty();
}
return service.getDefaults().getOption(set, key);
res = getContainingCollection().getDefaults().getOption(set, key);
if (res.isPresent()) {
return res;
}
return service.getDefaults().getOption(set, key);
}
}
@Override
public Set<Context> getActiveContexts() {
return LuckPermsService.convertContexts(service.getPlugin().getContextManager().getApplicableContext(this));
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_ACTIVE_CONTEXTS)) {
return LuckPermsService.convertContexts(service.getPlugin().getContextManager().getApplicableContext(this));
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.sponge.timings;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum LPTiming {
GET_SUBJECTS("getSubjects"),
USER_COLLECTION_GET("userCollectionGet"),
GROUP_COLLECTION_GET("groupCollectionGet"),
USER_GET_PERMISSION_VALUE("userGetPermissionValue"),
USER_GET_PARENTS("userGetParents"),
USER_IS_CHILD_OF("userIsChildOf"),
USER_GET_OPTION("userGetOption"),
USER_GET_ACTIVE_CONTEXTS("userGetActiveContexts"),
GROUP_GET_PERMISSION_VALUE("groupGetPermissionValue"),
GROUP_GET_PARENTS("groupGetParents"),
GROUP_IS_CHILD_OF("groupIsChildOf"),
GROUP_GET_OPTION("groupGetOption"),
GROUP_GET_ACTIVE_CONTEXTS("groupGetActiveContexts"),
LP_SUBJECT_GET_PERMISSIONS("lpSubjectGetPermissions"),
LP_SUBJECT_SET_PERMISSION("lpSubjectSetPermission"),
LP_SUBJECT_CLEAR_PERMISSIONS("lpSubjectClearPermissions"),
LP_SUBJECT_GET_PARENTS("lpSubjectGetParents"),
LP_SUBJECT_ADD_PARENT("lpSubjectAddParent"),
LP_SUBJECT_REMOVE_PARENT("lpSubjectRemoveParent"),
LP_SUBJECT_CLEAR_PARENTS("lpSubjectClearParents"),
LP_SUBJECT_GET_OPTIONS("lpSubjectGetOptions"),
LP_SUBJECT_SET_OPTION("lpSubjectSetOption"),
LP_SUBJECT_CLEAR_OPTIONS("lpSubjectClearOptions"),
SIMPLE_SUBJECT_GET_PERMISSION_VALUE("simpleSubjectGetPermissionValue"),
SIMPLE_SUBJECT_IS_CHILD_OF("simpleSubjectIsChildOf"),
SIMPLE_SUBJECT_GET_PARENTS("simpleSubjectGetParents"),
SIMPLE_SUBJECT_GET_OPTION("simpleSubjectGetOption"),
SIMPLE_SUBJECT_GET_ACTIVE_CONTEXTS("simpleSubjectGetActiveContexts"),
PERSISTED_SUBJECT_GET_PERMISSION_VALUE("persistedSubjectGetPermissionValue"),
PERSISTED_SUBJECT_IS_CHILD_OF("persistedSubjectIsChildOf"),
PERSISTED_SUBJECT_GET_PARENTS("persistedSubjectGetParents"),
PERSISTED_SUBJECT_GET_OPTION("persistedSubjectGetOption"),
PERSISTED_SUBJECT_GET_ACTIVE_CONTEXTS("persistedSubjectGetActiveContexts"),
ON_COMMAND("onCommand"),
COMMAND_TAB_COMPLETE("commandTabComplete"),
ON_CLIENT_LOGIN("onClientLogin"),
ON_CLIENT_LEAVE("onClientLeave");
private final String id;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.sponge.timings;
import co.aikar.timings.Timing;
import co.aikar.timings.Timings;
import com.google.common.collect.ImmutableMap;
import lombok.NonNull;
import me.lucko.luckperms.sponge.LPSpongePlugin;
import java.util.Map;
public class LPTimings {
private final Map<LPTiming, Timing> timings;
public LPTimings(LPSpongePlugin plugin) {
ImmutableMap.Builder<LPTiming, Timing> map = ImmutableMap.builder();
for (LPTiming t : LPTiming.values()) {
map.put(t, Timings.of(plugin, t.getId()));
}
timings = map.build();
}
public Timing time(@NonNull LPTiming timing) {
Timing t = timings.get(timing);
t.startTimingIfSync();
return t;
}
}