Various performance optimizations
This commit is contained in:
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* 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.common.calculators;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractCalculatorFactory implements PlatformCalculatorFactory {
|
||||
private final Set<PermissionCalculator> calculators = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
|
||||
protected PermissionCalculator registerCalculator(PermissionCalculator calculator) {
|
||||
this.calculators.add(calculator);
|
||||
return calculator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAll() {
|
||||
for (PermissionCalculator calculator : this.calculators) {
|
||||
calculator.invalidateCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -44,7 +44,6 @@ import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
|
||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
@@ -126,7 +125,7 @@ public class ParentInfo extends SharedSubCommand {
|
||||
}
|
||||
|
||||
private static final Comparator<LocalizedNode> ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> {
|
||||
int i = CollationKeyCache.compareStrings(o1.getGroupName(), o2.getGroupName());
|
||||
int i = o1.getGroupName().compareTo(o2.getGroupName());
|
||||
if (i != 0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
+1
-2
@@ -44,7 +44,6 @@ import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
|
||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
||||
import me.lucko.luckperms.common.utils.DurationFormatter;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
@@ -129,7 +128,7 @@ public class PermissionInfo extends SharedSubCommand {
|
||||
}
|
||||
|
||||
private static final Comparator<LocalizedNode> ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> {
|
||||
int i = CollationKeyCache.compareStrings(o1.getPermission(), o2.getPermission());
|
||||
int i = o1.getPermission().compareTo(o2.getPermission());
|
||||
if (i != 0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
package me.lucko.luckperms.common.commands.log;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.actionlog.Log;
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.SubCommand;
|
||||
@@ -54,7 +55,7 @@ public class LogNotify extends SubCommand<Log> {
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<? extends Node> ret = user.getOwnNodes().stream()
|
||||
Optional<? extends Node> ret = user.enduringData().immutable().get(ContextSet.empty()).stream()
|
||||
.filter(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"))
|
||||
.findFirst();
|
||||
|
||||
@@ -74,7 +75,7 @@ public class LogNotify extends SubCommand<Log> {
|
||||
user.setPermission(NodeFactory.make("luckperms.log.notify.ignoring"));
|
||||
} else {
|
||||
// remove the perm
|
||||
user.removeIf(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"));
|
||||
user.removeIf(ContextSet.empty(), n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"));
|
||||
}
|
||||
|
||||
plugin.getStorage().saveUser(user).join();
|
||||
|
||||
@@ -85,7 +85,7 @@ public class ExportCommand extends SingleCommand {
|
||||
Exporter exporter = new Exporter(plugin, sender, path, includeUsers);
|
||||
|
||||
// Run the exporter in its own thread.
|
||||
plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
try {
|
||||
exporter.run();
|
||||
} finally {
|
||||
|
||||
@@ -86,7 +86,7 @@ public class ImportCommand extends SingleCommand {
|
||||
Importer importer = new Importer(plugin.getCommandManager(), sender, commands);
|
||||
|
||||
// Run the importer in its own thread.
|
||||
plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
try {
|
||||
importer.run();
|
||||
} finally {
|
||||
|
||||
@@ -25,34 +25,31 @@
|
||||
|
||||
package me.lucko.luckperms.common.config;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import me.lucko.luckperms.common.api.delegates.misc.ApiConfiguration;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An abstract implementation of {@link LuckPermsConfiguration}, backed by a cache.
|
||||
* An abstract implementation of {@link LuckPermsConfiguration}.
|
||||
*
|
||||
* <p>Values are loaded into memory on init.</p>
|
||||
*/
|
||||
public class AbstractConfiguration implements LuckPermsConfiguration, CacheLoader<ConfigKey<?>, Optional<Object>> {
|
||||
public class AbstractConfiguration implements LuckPermsConfiguration {
|
||||
|
||||
// the loading cache for config keys --> their value
|
||||
// the value is wrapped in an optional as null values don't get cached.
|
||||
private final LoadingCache<ConfigKey<?>, Optional<Object>> cache = Caffeine.newBuilder().build(this);
|
||||
/**
|
||||
* The configurations loaded values.
|
||||
*
|
||||
* <p>The value corresponding to each key is stored at the index defined
|
||||
* by {@link ConfigKey#ordinal()}.</p>
|
||||
*/
|
||||
private Object[] values = null;
|
||||
|
||||
// the plugin instance
|
||||
private final LuckPermsPlugin plugin;
|
||||
// the adapter used to read values
|
||||
private final ConfigurationAdapter adapter;
|
||||
|
||||
// the api delegate
|
||||
private final ApiConfiguration delegate = new ApiConfiguration(this);
|
||||
// the contextsfile handler
|
||||
@@ -61,6 +58,52 @@ public class AbstractConfiguration implements LuckPermsConfiguration, CacheLoade
|
||||
public AbstractConfiguration(LuckPermsPlugin plugin, ConfigurationAdapter adapter) {
|
||||
this.plugin = plugin;
|
||||
this.adapter = adapter;
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T get(ConfigKey<T> key) {
|
||||
return (T) this.values[key.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void load() {
|
||||
// get the map of all keys
|
||||
Map<String, ConfigKey<?>> keys = ConfigKeys.getAllKeys();
|
||||
|
||||
// if this is a reload operation
|
||||
boolean reload = true;
|
||||
|
||||
// if values are null, must be loading for the first time
|
||||
if (this.values == null) {
|
||||
this.values = new Object[keys.size()];
|
||||
reload = false;
|
||||
}
|
||||
|
||||
// load a value for each key.
|
||||
for (ConfigKey<?> key : keys.values()) {
|
||||
// don't reload enduring keys.
|
||||
if (reload && key instanceof EnduringKey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// load the value for the key
|
||||
Object value = key.get(this.adapter);
|
||||
this.values[key.ordinal()] = value;
|
||||
}
|
||||
|
||||
// load the contexts file
|
||||
this.contextsFile.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.adapter.reload();
|
||||
load();
|
||||
|
||||
getPlugin().getEventFactory().handleConfigReload();
|
||||
}
|
||||
|
||||
public ConfigurationAdapter getAdapter() {
|
||||
@@ -81,36 +124,4 @@ public class AbstractConfiguration implements LuckPermsConfiguration, CacheLoade
|
||||
public ContextsFile getContextsFile() {
|
||||
return this.contextsFile;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T get(ConfigKey<T> key) {
|
||||
Optional<Object> ret = this.cache.get(key);
|
||||
if (ret == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) ret.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAll() {
|
||||
ConfigKeys.getAllKeys().values().forEach(this.cache::get);
|
||||
this.contextsFile.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.adapter.reload();
|
||||
|
||||
Set<ConfigKey<?>> toInvalidate = this.cache.asMap().keySet().stream().filter(k -> !(k instanceof EnduringKey)).collect(Collectors.toSet());
|
||||
this.cache.invalidateAll(toInvalidate);
|
||||
|
||||
loadAll();
|
||||
getPlugin().getEventFactory().handleConfigReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Object> load(@Nonnull ConfigKey<?> key) {
|
||||
return Optional.ofNullable(key.get(this.adapter));
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -23,17 +23,17 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.calculators;
|
||||
package me.lucko.luckperms.common.config;
|
||||
|
||||
/**
|
||||
* Extension of {@link CalculatorFactory} which keeps a record of produced
|
||||
* calculators and provides a means to invalidate them all in bulk.
|
||||
*/
|
||||
public interface PlatformCalculatorFactory extends CalculatorFactory {
|
||||
public abstract class BaseConfigKey<T> implements ConfigKey<T> {
|
||||
int ordinal = -1;
|
||||
|
||||
/**
|
||||
* Invalidates all calculators build by this factory
|
||||
*/
|
||||
void invalidateAll();
|
||||
protected BaseConfigKey() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int ordinal() {
|
||||
return this.ordinal;
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,16 @@ import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
*/
|
||||
public interface ConfigKey<T> {
|
||||
|
||||
/**
|
||||
* Gets the position of this key within the {@link ConfigKeys} enum.
|
||||
*
|
||||
* <p>This is lazily set when the configuration is loaded for the first time, during the
|
||||
* execution of {@link ConfigKeys#getAllKeys()}.</p>
|
||||
*
|
||||
* @return the position
|
||||
*/
|
||||
int ordinal();
|
||||
|
||||
/**
|
||||
* Resolves and returns the value mapped to this key using the given config instance.
|
||||
*
|
||||
|
||||
@@ -33,8 +33,8 @@ import me.lucko.luckperms.api.LookupSetting;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
|
||||
import me.lucko.luckperms.common.assignments.AssignmentRule;
|
||||
import me.lucko.luckperms.common.config.keys.AbstractKey;
|
||||
import me.lucko.luckperms.common.config.keys.BooleanKey;
|
||||
import me.lucko.luckperms.common.config.keys.CustomKey;
|
||||
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
||||
import me.lucko.luckperms.common.config.keys.LowercaseStringKey;
|
||||
import me.lucko.luckperms.common.config.keys.MapKey;
|
||||
@@ -64,13 +64,16 @@ import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* All of the {@link ConfigKey}s used by LuckPerms.
|
||||
*
|
||||
* <p>The {@link #getAllKeys()} method and associated behaviour allows this class to behave
|
||||
* a bit like an enum with generics.</p>
|
||||
*/
|
||||
public class ConfigKeys {
|
||||
public final class ConfigKeys {
|
||||
|
||||
/**
|
||||
* The name of the server
|
||||
*/
|
||||
public static final ConfigKey<String> SERVER = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<String> SERVER = CustomKey.of(c -> {
|
||||
if (c.getBoolean("use-server-properties-name", false)) {
|
||||
String serverName = c.getPlugin().getBootstrap().getServerName();
|
||||
if (serverName != null && !serverName.equals("Unknown Server")) {
|
||||
@@ -84,7 +87,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* How many minutes to wait between syncs. A value <= 0 will disable syncing.
|
||||
*/
|
||||
public static final ConfigKey<Integer> SYNC_TIME = EnduringKey.wrap(AbstractKey.of(c -> {
|
||||
public static final ConfigKey<Integer> SYNC_TIME = EnduringKey.wrap(CustomKey.of(c -> {
|
||||
int val = c.getInt("sync-minutes", -1);
|
||||
if (val == -1) {
|
||||
val = c.getInt("data.sync-minutes", -1);
|
||||
@@ -95,7 +98,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The lookup settings for contexts (care should be taken to not mutate this method)
|
||||
*/
|
||||
public static final ConfigKey<EnumSet<LookupSetting>> LOOKUP_SETTINGS = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<EnumSet<LookupSetting>> LOOKUP_SETTINGS = CustomKey.of(c -> {
|
||||
return EnumSet.copyOf(Contexts.of(
|
||||
ContextSet.empty(),
|
||||
c.getBoolean("include-global", true),
|
||||
@@ -130,7 +133,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* Controls how temporary add commands should behave
|
||||
*/
|
||||
public static final ConfigKey<TemporaryModifier> TEMPORARY_ADD_BEHAVIOUR = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<TemporaryModifier> TEMPORARY_ADD_BEHAVIOUR = CustomKey.of(c -> {
|
||||
String option = c.getString("temporary-add-behaviour", "deny").toLowerCase();
|
||||
if (!option.equals("deny") && !option.equals("replace") && !option.equals("accumulate")) {
|
||||
option = "deny";
|
||||
@@ -142,7 +145,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* How primary groups should be calculated.
|
||||
*/
|
||||
public static final ConfigKey<String> PRIMARY_GROUP_CALCULATION_METHOD = EnduringKey.wrap(AbstractKey.of(c -> {
|
||||
public static final ConfigKey<String> PRIMARY_GROUP_CALCULATION_METHOD = EnduringKey.wrap(CustomKey.of(c -> {
|
||||
String option = c.getString("primary-group-calculation", "stored").toLowerCase();
|
||||
if (!option.equals("stored") && !option.equals("parents-by-weight") && !option.equals("all-parents-by-weight")) {
|
||||
option = "stored";
|
||||
@@ -154,7 +157,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* A function to create primary group holder instances based upon the {@link #PRIMARY_GROUP_CALCULATION_METHOD} setting.
|
||||
*/
|
||||
public static final ConfigKey<Function<User, PrimaryGroupHolder>> PRIMARY_GROUP_CALCULATION = EnduringKey.wrap(AbstractKey.of(c -> {
|
||||
public static final ConfigKey<Function<User, PrimaryGroupHolder>> PRIMARY_GROUP_CALCULATION = EnduringKey.wrap(CustomKey.of(c -> {
|
||||
String option = PRIMARY_GROUP_CALCULATION_METHOD.get(c);
|
||||
switch (option) {
|
||||
case "stored":
|
||||
@@ -245,7 +248,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The algorithm LuckPerms should use when traversing the "inheritance tree"
|
||||
*/
|
||||
public static final ConfigKey<TraversalAlgorithm> INHERITANCE_TRAVERSAL_ALGORITHM = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<TraversalAlgorithm> INHERITANCE_TRAVERSAL_ALGORITHM = CustomKey.of(c -> {
|
||||
String value = c.getString("inheritance-traversal-algorithm", "depth-first-pre-order");
|
||||
switch (value.toLowerCase()) {
|
||||
case "breadth-first":
|
||||
@@ -260,7 +263,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The configured group weightings
|
||||
*/
|
||||
public static final ConfigKey<Map<String, Integer>> GROUP_WEIGHTS = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<Map<String, Integer>> GROUP_WEIGHTS = CustomKey.of(c -> {
|
||||
return c.getMap("group-weight", ImmutableMap.of()).entrySet().stream().collect(ImmutableCollectors.toMap(
|
||||
e -> e.getKey().toLowerCase(),
|
||||
e -> {
|
||||
@@ -276,7 +279,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* Creates a new prefix MetaStack element based upon the configured values.
|
||||
*/
|
||||
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
||||
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = CustomKey.of(l -> {
|
||||
List<String> format = l.getList("meta-formatting.prefix.format", new ArrayList<>());
|
||||
if (format.isEmpty()) {
|
||||
format.add("highest");
|
||||
@@ -291,7 +294,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* Creates a new suffix MetaStack element based upon the configured values.
|
||||
*/
|
||||
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
||||
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = CustomKey.of(l -> {
|
||||
List<String> format = l.getList("meta-formatting.suffix.format", new ArrayList<>());
|
||||
if (format.isEmpty()) {
|
||||
format.add("highest");
|
||||
@@ -316,7 +319,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* If server operators should be enabled. Only used by the Bukkit platform.
|
||||
*/
|
||||
public static final ConfigKey<Boolean> OPS_ENABLED = EnduringKey.wrap(AbstractKey.of(c -> !AUTO_OP.get(c) && c.getBoolean("enable-ops", true)));
|
||||
public static final ConfigKey<Boolean> OPS_ENABLED = EnduringKey.wrap(CustomKey.of(c -> !AUTO_OP.get(c) && c.getBoolean("enable-ops", true)));
|
||||
|
||||
/**
|
||||
* If server operators should be able to use LuckPerms commands by default. Only used by the Bukkit platform.
|
||||
@@ -331,7 +334,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The name of the server to use for Vault.
|
||||
*/
|
||||
public static final ConfigKey<String> VAULT_SERVER = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<String> VAULT_SERVER = CustomKey.of(c -> {
|
||||
// default to true for backwards compatibility
|
||||
if (USE_VAULT_SERVER.get(c)) {
|
||||
return c.getString("vault-server", "global").toLowerCase();
|
||||
@@ -358,7 +361,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The world rewrites map
|
||||
*/
|
||||
public static final ConfigKey<Map<String, String>> WORLD_REWRITES = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<Map<String, String>> WORLD_REWRITES = CustomKey.of(c -> {
|
||||
return c.getMap("world-rewrite", ImmutableMap.of()).entrySet().stream()
|
||||
.collect(ImmutableCollectors.toMap(
|
||||
e -> e.getKey().toLowerCase(),
|
||||
@@ -374,7 +377,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The default assignments being applied by the plugin
|
||||
*/
|
||||
public static final ConfigKey<List<AssignmentRule>> DEFAULT_ASSIGNMENTS = AbstractKey.of(c -> {
|
||||
public static final ConfigKey<List<AssignmentRule>> DEFAULT_ASSIGNMENTS = CustomKey.of(c -> {
|
||||
return c.getObjectList("default-assignments", ImmutableList.of()).stream().map(name -> {
|
||||
String hasTrue = c.getString("default-assignments." + name + ".if.has-true", null);
|
||||
String hasFalse = c.getString("default-assignments." + name + ".if.has-false", null);
|
||||
@@ -389,7 +392,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The database settings, username, password, etc for use by any database
|
||||
*/
|
||||
public static final ConfigKey<StorageCredentials> DATABASE_VALUES = EnduringKey.wrap(AbstractKey.of(c -> {
|
||||
public static final ConfigKey<StorageCredentials> DATABASE_VALUES = EnduringKey.wrap(CustomKey.of(c -> {
|
||||
int maxPoolSize = c.getInt("data.pool-settings.maximum-pool-size", c.getInt("data.pool-size", 10));
|
||||
int minIdle = c.getInt("data.pool-settings.minimum-idle", maxPoolSize);
|
||||
int maxLifetime = c.getInt("data.pool-settings.maximum-lifetime", 1800000);
|
||||
@@ -438,7 +441,7 @@ public class ConfigKeys {
|
||||
/**
|
||||
* The options for split storage
|
||||
*/
|
||||
public static final ConfigKey<Map<SplitStorageType, String>> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(AbstractKey.of(c -> {
|
||||
public static final ConfigKey<Map<SplitStorageType, String>> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(CustomKey.of(c -> {
|
||||
EnumMap<SplitStorageType, String> map = new EnumMap<>(SplitStorageType.class);
|
||||
map.put(SplitStorageType.USER, c.getString("split-storage.methods.user", "h2").toLowerCase());
|
||||
map.put(SplitStorageType.GROUP, c.getString("split-storage.methods.group", "h2").toLowerCase());
|
||||
@@ -511,15 +514,25 @@ public class ConfigKeys {
|
||||
|
||||
try {
|
||||
Field[] values = ConfigKeys.class.getFields();
|
||||
int counter = 0;
|
||||
|
||||
for (Field f : values) {
|
||||
// ignore non-static fields
|
||||
if (!Modifier.isStatic(f.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object val = f.get(null);
|
||||
if (val instanceof ConfigKey<?>) {
|
||||
keys.put(f.getName(), (ConfigKey<?>) val);
|
||||
// ignore fields that aren't configkeys
|
||||
if (!ConfigKey.class.equals(f.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the key instance
|
||||
BaseConfigKey<?> key = (BaseConfigKey<?>) f.get(null);
|
||||
// set the ordinal value of the key.
|
||||
key.ordinal = counter++;
|
||||
// add the key to the return map
|
||||
keys.put(f.getName(), key);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -60,9 +60,9 @@ public interface LuckPermsConfiguration {
|
||||
void reload();
|
||||
|
||||
/**
|
||||
* Pre-loads all configuration keys into the cache.
|
||||
* Loads all configuration values.
|
||||
*/
|
||||
void loadAll();
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Gets the value of a given context key.
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
public class BooleanKey implements ConfigKey<Boolean> {
|
||||
public class BooleanKey extends BaseConfigKey<Boolean> {
|
||||
public static BooleanKey of(String path, boolean def) {
|
||||
return new BooleanKey(path, def);
|
||||
}
|
||||
|
||||
+5
-5
@@ -25,19 +25,19 @@
|
||||
|
||||
package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class AbstractKey<T> implements ConfigKey<T> {
|
||||
public static <T> AbstractKey<T> of(Function<ConfigurationAdapter, T> function) {
|
||||
return new AbstractKey<>(function);
|
||||
public class CustomKey<T> extends BaseConfigKey<T> {
|
||||
public static <T> CustomKey<T> of(Function<ConfigurationAdapter, T> function) {
|
||||
return new CustomKey<>(function);
|
||||
}
|
||||
|
||||
private final Function<ConfigurationAdapter, T> function;
|
||||
|
||||
private AbstractKey(Function<ConfigurationAdapter, T> function) {
|
||||
private CustomKey(Function<ConfigurationAdapter, T> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
@@ -32,7 +33,7 @@ import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
* Wrapper class to mark a config key as enduring (doesn't change in the event of a reload)
|
||||
* @param <T>
|
||||
*/
|
||||
public class EnduringKey<T> implements ConfigKey<T> {
|
||||
public class EnduringKey<T> extends BaseConfigKey<T> {
|
||||
|
||||
public static <T> EnduringKey<T> wrap(ConfigKey<T> delegate) {
|
||||
return new EnduringKey<>(delegate);
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
public class IntegerKey implements ConfigKey<Integer> {
|
||||
public class IntegerKey extends BaseConfigKey<Integer> {
|
||||
public static IntegerKey of(String path, int def) {
|
||||
return new IntegerKey(path, def);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
public class LowercaseStringKey implements ConfigKey<String> {
|
||||
public class LowercaseStringKey extends BaseConfigKey<String> {
|
||||
public static LowercaseStringKey of(String path, String def) {
|
||||
return new LowercaseStringKey(path, def);
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class MapKey implements ConfigKey<Map<String, String>> {
|
||||
public class MapKey extends BaseConfigKey<Map<String, String>> {
|
||||
public static MapKey of(String path) {
|
||||
return new MapKey(path);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
package me.lucko.luckperms.common.config.keys;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.BaseConfigKey;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
|
||||
public class StringKey implements ConfigKey<String> {
|
||||
public class StringKey extends BaseConfigKey<String> {
|
||||
public static StringKey of(String path, String def) {
|
||||
return new StringKey(path, def);
|
||||
}
|
||||
|
||||
@@ -221,6 +221,6 @@ public abstract class AbstractEventBus<P> implements EventBus, AutoCloseable {
|
||||
if (event instanceof Cancellable) {
|
||||
throw new IllegalArgumentException("cannot call Cancellable event async");
|
||||
}
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> fireEvent(event));
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> fireEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
+13
-12
@@ -25,9 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.inheritance;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.LookupSetting;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
@@ -38,7 +35,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Provides {@link InheritanceGraph}s.
|
||||
@@ -51,17 +47,15 @@ public class InheritanceHandler {
|
||||
*/
|
||||
private final InheritanceGraph nonContextualGraph;
|
||||
|
||||
/**
|
||||
* Cache of contextual inheritance graph instances
|
||||
*/
|
||||
private final LoadingCache<Contexts, InheritanceGraph> contextualGraphs;
|
||||
// some cached contextual graphs for common Contexts
|
||||
private final InheritanceGraph allowAllContextualGraph;
|
||||
private final InheritanceGraph globalContextualGraph;
|
||||
|
||||
public InheritanceHandler(LuckPermsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.nonContextualGraph = new NonContextualGraph(plugin);
|
||||
this.contextualGraphs = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build(key -> new ContextualGraph(this.plugin, key));
|
||||
this.allowAllContextualGraph = new ContextualGraph(plugin, Contexts.allowAll());
|
||||
this.globalContextualGraph = new ContextualGraph(plugin, Contexts.global());
|
||||
}
|
||||
|
||||
public InheritanceGraph getGraph() {
|
||||
@@ -69,7 +63,14 @@ public class InheritanceHandler {
|
||||
}
|
||||
|
||||
public InheritanceGraph getGraph(Contexts contexts) {
|
||||
return this.contextualGraphs.get(contexts);
|
||||
if (contexts == Contexts.allowAll()) {
|
||||
return this.allowAllContextualGraph;
|
||||
}
|
||||
if (contexts == Contexts.global()) {
|
||||
return this.globalContextualGraph;
|
||||
}
|
||||
|
||||
return new ContextualGraph(this.plugin, contexts);
|
||||
}
|
||||
|
||||
private static final class NonContextualGraph implements InheritanceGraph {
|
||||
|
||||
+2
-1
@@ -37,6 +37,7 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class AbstractUserManager<T extends User> extends AbstractManager<UserIdentifier, User, T> implements UserManager<T> {
|
||||
|
||||
@@ -46,7 +47,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
|
||||
public AbstractUserManager(LuckPermsPlugin plugin, UserHousekeeper.TimeoutSettings timeoutSettings) {
|
||||
this.plugin = plugin;
|
||||
this.housekeeper = new UserHousekeeper(plugin, this, timeoutSettings);
|
||||
this.plugin.getBootstrap().getScheduler().asyncRepeating(this.housekeeper, 200L); // every 10 seconds
|
||||
this.plugin.getBootstrap().getScheduler().asyncRepeating(this.housekeeper, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -102,7 +102,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
|
||||
@Override
|
||||
public void pushUpdate() {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
this.plugin.getLogger().info("[" + getName() + " Messaging] Sending ping with id: " + requestId);
|
||||
this.messenger.sendOutgoingMessage(new UpdateMessageImpl(requestId));
|
||||
@@ -111,7 +111,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
|
||||
@Override
|
||||
public void pushUserUpdate(User user) {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
this.plugin.getLogger().info("[" + getName() + " Messaging] Sending user ping for '" + user.getFriendlyName() + "' with id: " + requestId);
|
||||
this.messenger.sendOutgoingMessage(new UserUpdateMessageImpl(requestId, user.getUuid()));
|
||||
@@ -120,7 +120,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
||||
|
||||
@Override
|
||||
public void pushLog(LogEntry logEntry) {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
UUID requestId = generatePingId();
|
||||
|
||||
if (this.plugin.getEventFactory().handleLogNetworkPublish(!this.plugin.getConfiguration().get(ConfigKeys.PUSH_LOG_ENTRIES), requestId, logEntry)) {
|
||||
|
||||
@@ -65,7 +65,7 @@ public class RedisMessenger implements Messenger {
|
||||
this.jedisPool = new JedisPool(new JedisPoolConfig(), host, port, 0, password);
|
||||
}
|
||||
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
this.sub = new LPSub(this);
|
||||
try (Jedis jedis = this.jedisPool.getResource()) {
|
||||
jedis.subscribe(this.sub, CHANNEL);
|
||||
|
||||
@@ -27,12 +27,13 @@ package me.lucko.luckperms.common.messaging.sql;
|
||||
|
||||
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.storage.dao.sql.SqlDao;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SqlMessenger extends AbstractSqlMessenger {
|
||||
private final LuckPermsPlugin plugin;
|
||||
@@ -57,8 +58,8 @@ public class SqlMessenger extends AbstractSqlMessenger {
|
||||
|
||||
// schedule poll tasks
|
||||
SchedulerAdapter scheduler = this.plugin.getBootstrap().getScheduler();
|
||||
this.pollTask = scheduler.asyncRepeating(this::pollMessages, 20L);
|
||||
this.housekeepingTask = scheduler.asyncRepeating(this::runHousekeeping, 20L * 30);
|
||||
this.pollTask = scheduler.asyncRepeating(this::pollMessages, 1, TimeUnit.SECONDS);
|
||||
this.housekeepingTask = scheduler.asyncRepeating(this::runHousekeeping, 30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package me.lucko.luckperms.common.node.comparator;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@@ -65,6 +64,6 @@ public class NodeComparator implements Comparator<Node> {
|
||||
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
||||
}
|
||||
|
||||
return CollationKeyCache.compareStrings(o1.getPermission(), o2.getPermission()) == 1 ? -1 : 1;
|
||||
return o1.getPermission().compareTo(o2.getPermission()) > 0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-28
@@ -26,7 +26,7 @@
|
||||
package me.lucko.luckperms.common.node.comparator;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.common.utils.CollationKeyCache;
|
||||
import me.lucko.luckperms.common.contexts.ContextSetComparator;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@@ -58,35 +58,16 @@ public class NodeWithContextComparator implements Comparator<Node> {
|
||||
return o1.isOverride() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isServerSpecific() != o2.isServerSpecific()) {
|
||||
return o1.isServerSpecific() ? 1 : -1;
|
||||
int i = ContextSetComparator.normal().compare(
|
||||
o1.getFullContexts().makeImmutable(),
|
||||
o2.getFullContexts().makeImmutable()
|
||||
);
|
||||
|
||||
if (i != 0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
if (o1.isWorldSpecific() != o2.isWorldSpecific()) {
|
||||
return o1.isWorldSpecific() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.getContexts().size() != o2.getContexts().size()) {
|
||||
return o1.getContexts().size() > o2.getContexts().size() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isTemporary() != o2.isTemporary()) {
|
||||
return o1.isTemporary() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isWildcard() != o2.isWildcard()) {
|
||||
return o1.isWildcard() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isTemporary()) {
|
||||
return o1.getSecondsTilExpiry() < o2.getSecondsTilExpiry() ? 1 : -1;
|
||||
}
|
||||
|
||||
if (o1.isWildcard()) {
|
||||
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
||||
}
|
||||
|
||||
return CollationKeyCache.compareStrings(o1.getPermission(), o2.getPermission()) == 1 ? -1 : 1;
|
||||
return NodeComparator.normal().compare(o1, o2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class ForwardingNode implements Node {
|
||||
|
||||
protected abstract Node delegate();
|
||||
public abstract Node delegate();
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public final class ImmutableLocalizedNode extends ForwardingNode implements Loca
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node delegate() {
|
||||
public Node delegate() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@ public final class ImmutableNode implements Node {
|
||||
|
||||
|
||||
// cached state
|
||||
|
||||
private final Optional<String> optServer;
|
||||
private final Optional<String> optWorld;
|
||||
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public final class ImmutableTransientNode<O> extends ForwardingNode implements N
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node delegate() {
|
||||
public Node delegate() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import me.lucko.luckperms.common.api.ApiRegistrationUtil;
|
||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
||||
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
|
||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.command.utils.MessageUtils;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
@@ -61,6 +61,7 @@ import me.lucko.luckperms.common.verbose.VerboseHandler;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
|
||||
@@ -79,7 +80,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
private InternalMessagingService messagingService = null;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
private InheritanceHandler inheritanceHandler;
|
||||
private PlatformCalculatorFactory calculatorFactory;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private LuckPermsApiProvider apiProvider;
|
||||
private EventFactory eventFactory;
|
||||
|
||||
@@ -101,14 +102,13 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
displayBanner(getConsoleSender());
|
||||
|
||||
// load some utilities early
|
||||
this.verboseHandler = new VerboseHandler();
|
||||
this.permissionRegistry = new PermissionRegistry();
|
||||
this.verboseHandler = new VerboseHandler(getBootstrap().getScheduler());
|
||||
this.permissionRegistry = new PermissionRegistry(getBootstrap().getScheduler());
|
||||
this.logDispatcher = new LogDispatcher(this);
|
||||
|
||||
// load configuration
|
||||
getLogger().info("Loading configuration...");
|
||||
this.configuration = new AbstractConfiguration(this, provideConfigurationAdapter());
|
||||
this.configuration.loadAll();
|
||||
|
||||
// load locale
|
||||
this.localeManager = new SimpleLocaleManager();
|
||||
@@ -168,10 +168,9 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
// schedule update tasks
|
||||
int mins = getConfiguration().get(ConfigKeys.SYNC_TIME);
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
getBootstrap().getScheduler().asyncRepeating(() -> this.updateTaskBuffer.request(), ticks);
|
||||
getBootstrap().getScheduler().asyncRepeating(() -> this.updateTaskBuffer.request(), mins, TimeUnit.MINUTES);
|
||||
}
|
||||
getBootstrap().getScheduler().asyncLater(() -> this.updateTaskBuffer.request(), 40L);
|
||||
getBootstrap().getScheduler().asyncLater(() -> this.updateTaskBuffer.request(), 2, TimeUnit.SECONDS);
|
||||
|
||||
// run an update instantly.
|
||||
getLogger().info("Performing initial data load...");
|
||||
@@ -191,9 +190,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
public final void disable() {
|
||||
// perform initial disable tasks
|
||||
performEarlyDisableTasks();
|
||||
|
||||
// shutdown permission vault and verbose handler tasks
|
||||
this.permissionRegistry.stop();
|
||||
this.verboseHandler.stop();
|
||||
@@ -233,7 +229,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
protected abstract MessagingFactory<?> provideMessagingFactory();
|
||||
protected abstract void registerCommands();
|
||||
protected abstract void setupManagers();
|
||||
protected abstract PlatformCalculatorFactory provideCalculatorFactory();
|
||||
protected abstract CalculatorFactory provideCalculatorFactory();
|
||||
protected abstract void setupContextManager();
|
||||
protected abstract void setupPlatformHooks();
|
||||
protected abstract AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider);
|
||||
@@ -241,7 +237,6 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
protected abstract void registerHousekeepingTasks();
|
||||
protected abstract void performFinalSetup();
|
||||
|
||||
protected void performEarlyDisableTasks() {}
|
||||
protected void removePlatformHooks() {}
|
||||
|
||||
@Override
|
||||
@@ -312,7 +307,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformCalculatorFactory getCalculatorFactory() {
|
||||
public CalculatorFactory getCalculatorFactory() {
|
||||
return this.calculatorFactory;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ package me.lucko.luckperms.common.plugin.bootstrap;
|
||||
|
||||
import me.lucko.luckperms.api.platform.PlatformType;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* 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.common.plugin.scheduler;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link SchedulerAdapter} using a {@link ScheduledExecutorService}.
|
||||
*/
|
||||
public abstract class AbstractJavaScheduler implements SchedulerAdapter {
|
||||
private final ScheduledExecutorService asyncExecutor = new AsyncExecutor();
|
||||
|
||||
@Override
|
||||
public Executor async() {
|
||||
return this.asyncExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
|
||||
ScheduledFuture<?> future = this.asyncExecutor.schedule(new WrappedRunnable(task), delay, unit);
|
||||
return () -> future.cancel(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit) {
|
||||
ScheduledFuture<?> future = this.asyncExecutor.scheduleAtFixedRate(new WrappedRunnable(task), interval, interval, unit);
|
||||
return () -> future.cancel(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.asyncExecutor.shutdown();
|
||||
try {
|
||||
this.asyncExecutor.awaitTermination(1, TimeUnit.MINUTES);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class WrappedRunnable implements Runnable {
|
||||
private final Runnable delegate;
|
||||
|
||||
WrappedRunnable(Runnable delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
this.delegate.run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AsyncExecutor extends ScheduledThreadPoolExecutor {
|
||||
AsyncExecutor() {
|
||||
super(4, new ThreadFactoryBuilder().setNameFormat("luckperms-%d").build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
super.execute(new WrappedRunnable(command));
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-33
@@ -23,9 +23,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.plugin;
|
||||
package me.lucko.luckperms.common.plugin.scheduler;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A scheduler for running tasks using the systems provided by the platform
|
||||
@@ -39,10 +42,6 @@ public interface SchedulerAdapter {
|
||||
*/
|
||||
Executor async();
|
||||
|
||||
default Executor platformAsync() {
|
||||
return async();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a sync executor instance
|
||||
*
|
||||
@@ -51,46 +50,42 @@ public interface SchedulerAdapter {
|
||||
Executor sync();
|
||||
|
||||
/**
|
||||
* Executes a runnable async
|
||||
* Executes a task async
|
||||
*
|
||||
* @param runnable the runnable
|
||||
* @param task the task
|
||||
*/
|
||||
void doAsync(Runnable runnable);
|
||||
default void executeAsync(Runnable task) {
|
||||
async().execute(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a runnable sync
|
||||
* Executes a task sync
|
||||
*
|
||||
* @param runnable the runnable
|
||||
* @param task the task
|
||||
*/
|
||||
void doSync(Runnable runnable);
|
||||
default void executeSync(Runnable task) {
|
||||
sync().execute(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a runnable repeatedly until the plugin disables. Will wait for the interval before the first iteration of the task is ran.
|
||||
* @param runnable the runnable
|
||||
* @param intervalTicks the interval in ticks.
|
||||
* Executes the given task with a delay.
|
||||
*
|
||||
* @param task the task
|
||||
* @param delay the delay
|
||||
* @param unit the unit of delay
|
||||
* @return the resultant task instance
|
||||
*/
|
||||
SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks);
|
||||
SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Runs a runnable repeatedly until the plugin disables. Will wait for the interval before the first iteration of the task is ran.
|
||||
* @param runnable the runnable
|
||||
* @param intervalTicks the interval in ticks.
|
||||
* Executes the given task repeatedly at a given interval.
|
||||
*
|
||||
* @param task the task
|
||||
* @param interval the interval
|
||||
* @param unit the unit of interval
|
||||
* @return the resultant task instance
|
||||
*/
|
||||
SchedulerTask syncRepeating(Runnable runnable, long intervalTicks);
|
||||
|
||||
/**
|
||||
* Runs a runnable with a delay
|
||||
* @param runnable the runnable
|
||||
* @param delayTicks the delay in ticks
|
||||
*/
|
||||
SchedulerTask asyncLater(Runnable runnable, long delayTicks);
|
||||
|
||||
/**
|
||||
* Runs a runnable with a delay
|
||||
* @param runnable the runnable
|
||||
* @param delayTicks the delay in ticks
|
||||
*/
|
||||
SchedulerTask syncLater(Runnable runnable, long delayTicks);
|
||||
SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Shuts down this executor instance
|
||||
@@ -61,8 +61,8 @@ public class FileWatcher {
|
||||
this.basePath = basePath;
|
||||
this.watchService = basePath.getFileSystem().newWatchService();
|
||||
|
||||
plugin.getBootstrap().getScheduler().asyncLater(this::initLocations, 25L);
|
||||
plugin.getBootstrap().getScheduler().asyncRepeating(this::tick, 10L);
|
||||
plugin.getBootstrap().getScheduler().asyncLater(this::initLocations, 5, TimeUnit.SECONDS);
|
||||
plugin.getBootstrap().getScheduler().asyncRepeating(this::tick, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public WatchedLocation getWatcher(Path path) {
|
||||
|
||||
@@ -28,6 +28,7 @@ package me.lucko.luckperms.common.treeview;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.utils.RepeatingTask;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -55,8 +56,8 @@ public class PermissionRegistry extends RepeatingTask {
|
||||
// a queue of permission strings to be processed by the tree
|
||||
private final Queue<String> queue;
|
||||
|
||||
public PermissionRegistry() {
|
||||
super(1000, TimeUnit.MILLISECONDS, "luckperms-permission-vault");
|
||||
public PermissionRegistry(SchedulerAdapter scheduler) {
|
||||
super(scheduler, 1, TimeUnit.SECONDS);
|
||||
this.rootNode = new TreeNode();
|
||||
this.knownPermissions = ConcurrentHashMap.newKeySet(3000);
|
||||
this.queue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* 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.common.utils;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import java.text.CollationKey;
|
||||
import java.text.Collator;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class CollationKeyCache implements Comparator<String> {
|
||||
private static final CollationKeyCache INSTANCE = new CollationKeyCache();
|
||||
|
||||
private static final Collator COLLATOR;
|
||||
static {
|
||||
COLLATOR = Collator.getInstance(Locale.ENGLISH);
|
||||
COLLATOR.setStrength(Collator.IDENTICAL);
|
||||
COLLATOR.setDecomposition(Collator.FULL_DECOMPOSITION);
|
||||
}
|
||||
|
||||
private static final LoadingCache<String, CollationKey> CACHE = Caffeine.newBuilder()
|
||||
.maximumSize(5000)
|
||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
||||
.build(COLLATOR::getCollationKey);
|
||||
|
||||
public static Comparator<String> comparator() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private CollationKeyCache() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return compareStrings(o1, o2);
|
||||
}
|
||||
|
||||
public static int compareStrings(String o1, String o2) {
|
||||
//noinspection StringEquality
|
||||
if (o1 == o2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
CollationKey o1c = CACHE.get(o1);
|
||||
CollationKey o2c = CACHE.get(o2);
|
||||
|
||||
if (o1c != null && o2c != null) {
|
||||
int i = o1c.compareTo(o2c);
|
||||
if (i != 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
// fallback to standard string comparison
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,8 @@
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ForwardingSet;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -36,22 +36,22 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A bad expiring set implementation using Caffeine caches
|
||||
* A simple expiring set implementation using Caffeine caches
|
||||
*
|
||||
* @param <E> element type
|
||||
*/
|
||||
public class ExpiringSet<E> extends ForwardingSet<E> {
|
||||
private final LoadingCache<E, Boolean> cache;
|
||||
private final Cache<E, Boolean> cache;
|
||||
private final Set<E> setView;
|
||||
|
||||
public ExpiringSet(long duration, TimeUnit unit) {
|
||||
this.cache = Caffeine.newBuilder().expireAfterAccess(duration, unit).build(key -> Boolean.TRUE);
|
||||
this.cache = Caffeine.newBuilder().expireAfterAccess(duration, unit).build();
|
||||
this.setView = this.cache.asMap().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E element) {
|
||||
this.cache.get(element); // simply requesting the element from the cache is sufficient.
|
||||
this.cache.put(element, Boolean.TRUE);
|
||||
|
||||
// we don't care about the return value
|
||||
return true;
|
||||
|
||||
@@ -69,12 +69,12 @@ public final class PatternCache {
|
||||
private final Pattern instance;
|
||||
private final PatternSyntaxException ex;
|
||||
|
||||
public CachedPattern(Pattern instance) {
|
||||
CachedPattern(Pattern instance) {
|
||||
this.instance = instance;
|
||||
this.ex = null;
|
||||
}
|
||||
|
||||
public CachedPattern(PatternSyntaxException ex) {
|
||||
CachedPattern(PatternSyntaxException ex) {
|
||||
this.instance = null;
|
||||
this.ex = ex;
|
||||
}
|
||||
|
||||
@@ -25,20 +25,16 @@
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class RepeatingTask {
|
||||
private final SchedulerTask task;
|
||||
|
||||
// the executor thread
|
||||
private final ScheduledExecutorService executor;
|
||||
|
||||
protected RepeatingTask(long time, TimeUnit unit, String nameFormat) {
|
||||
this.executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat(nameFormat).build());
|
||||
this.executor.scheduleAtFixedRate(this::run, time, time, unit);
|
||||
protected RepeatingTask(SchedulerAdapter scheduler, long time, TimeUnit unit) {
|
||||
this.task = scheduler.asyncRepeating(this::run, time, unit);
|
||||
}
|
||||
|
||||
private void run() {
|
||||
@@ -52,11 +48,6 @@ public abstract class RepeatingTask {
|
||||
protected abstract void tick();
|
||||
|
||||
public void stop() {
|
||||
this.executor.shutdown();
|
||||
try {
|
||||
this.executor.awaitTermination(10, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ package me.lucko.luckperms.common.verbose;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.utils.RepeatingTask;
|
||||
|
||||
@@ -51,8 +52,8 @@ public class VerboseHandler extends RepeatingTask {
|
||||
// if there are any listeners currently registered
|
||||
private boolean listening = false;
|
||||
|
||||
public VerboseHandler() {
|
||||
super(100, TimeUnit.MILLISECONDS, "luckperms-verbose");
|
||||
public VerboseHandler(SchedulerAdapter scheduler) {
|
||||
super(scheduler, 100, TimeUnit.MILLISECONDS);
|
||||
this.listeners = new ConcurrentHashMap<>();
|
||||
this.queue = new ConcurrentLinkedQueue<>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user