From 1bd7e5c9c473fb38b86fca88e10e56e9dec91951 Mon Sep 17 00:00:00 2001 From: Luck Date: Fri, 29 Sep 2017 23:21:12 +0100 Subject: [PATCH] Refactor sponge cache invalidation --- .../service/model/LPPermissionService.java | 6 +- .../sponge/service/model/LPSubject.java | 13 ++++ .../luckperms/sponge/LPSpongePlugin.java | 3 +- .../sponge/managers/SpongeGroupManager.java | 13 +--- .../sponge/managers/SpongeUserManager.java | 13 +--- .../luckperms/sponge/model/SpongeGroup.java | 9 ++- .../luckperms/sponge/model/SpongeUser.java | 8 ++- .../sponge/service/LuckPermsService.java | 61 +++---------------- .../calculated/CalculatedSubjectData.java | 28 ++++----- .../service/persisted/PersistedSubject.java | 27 +++++--- 10 files changed, 73 insertions(+), 108 deletions(-) diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPPermissionService.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPPermissionService.java index e8df144b5..5b9103b0d 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPPermissionService.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPPermissionService.java @@ -85,9 +85,5 @@ public interface LPPermissionService { Contexts calculateContexts(ImmutableContextSet contextSet); - void invalidatePermissionCaches(); - - void invalidateParentCaches(); - - void invalidateOptionCaches(); + void invalidateAllCaches(LPSubject.CacheLevel cacheLevel); } diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java index 1b3832057..087fedf5b 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java @@ -86,4 +86,17 @@ public interface LPSubject { } + void invalidateCaches(CacheLevel cacheLevel); + + /** + * The level of cache for invalidation + * + * Invalidating at {@link #PARENT} will also invalidate at + * {@link #PERMISSION} and {@link #OPTION}, and invalidating at + * {@link #PERMISSION} will also invalidate at {@link #OPTION}. + */ + enum CacheLevel { + PARENT, PERMISSION, OPTION + } + } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java index a303b4f65..d3663084d 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java @@ -78,6 +78,7 @@ import me.lucko.luckperms.sponge.managers.SpongeUserManager; import me.lucko.luckperms.sponge.messaging.SpongeMessagingFactory; import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.model.LPPermissionService; +import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.persisted.PersistedCollection; import me.lucko.luckperms.sponge.tasks.ServiceCacheHousekeepingTask; @@ -332,7 +333,7 @@ public class LPSpongePlugin implements LuckPermsPlugin { ((PersistedCollection) collection).loadAll(); } } - service.invalidateParentCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PARENT); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java index 64d1fe76a..44ddf7ff2 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java @@ -27,7 +27,6 @@ package me.lucko.luckperms.sponge.managers; import lombok.Getter; -import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.common.base.Preconditions; @@ -71,17 +70,7 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection { private SubjectCollection spongeProxy = null; private final LoadingCache objects = Caffeine.newBuilder() - .build(new CacheLoader() { - @Override - public SpongeGroup load(String i) { - return apply(i); - } - - @Override - public SpongeGroup reload(String i, SpongeGroup t) { - return t; // Never needs to be refreshed. - } - }); + .build(this::apply); private final LoadingCache subjectLoadingCache = Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.MINUTES) diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java index d07b804cd..99e8ea5ac 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java @@ -27,7 +27,6 @@ package me.lucko.luckperms.sponge.managers; import lombok.Getter; -import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.common.base.Preconditions; @@ -72,17 +71,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection { private SubjectCollection spongeProxy = null; private final LoadingCache objects = Caffeine.newBuilder() - .build(new CacheLoader() { - @Override - public SpongeUser load(UserIdentifier i) { - return apply(i); - } - - @Override - public SpongeUser reload(UserIdentifier i, SpongeUser t) { - return t; // Never needs to be refreshed. - } - }); + .build(this::apply); private final LoadingCache subjectLoadingCache = Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.MINUTES) diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java index 6036bb1e5..97acf7b02 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java @@ -126,10 +126,15 @@ public class SpongeGroup extends Group { this.subjectData = new LuckPermsSubjectData(true, plugin.getService(), parent, this); this.transientSubjectData = new LuckPermsSubjectData(false, plugin.getService(), parent, this); - parent.getStateListeners().add(this::invalidateCaches); + parent.getStateListeners().add(() -> invalidateCaches(CacheLevel.PERMISSION)); } - public void invalidateCaches() { + @Override + public void invalidateCaches(CacheLevel type) { + if (type == CacheLevel.OPTION) { + return; // don't invalidate for option changes + } + permissionCache.invalidateAll(); parentCache.invalidateAll(); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java index 5f4ec4efd..b481dba84 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java @@ -70,7 +70,7 @@ public class SpongeUser extends User { return this.spongeData; } - public static class UserSubject implements LPSubject { + public static final class UserSubject implements LPSubject { private final SpongeUser parent; private final LPSpongePlugin plugin; @@ -187,6 +187,12 @@ public class SpongeUser extends User { public ImmutableContextSet getActiveContextSet() { return plugin.getContextManager().getApplicableContext(this.sponge()); } + + @Override + public void invalidateCaches(CacheLevel cacheLevel) { + // invalidate for all changes + parent.getUserData().invalidateCache(); + } } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java index a51669eac..871ff17fd 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java @@ -34,23 +34,15 @@ import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.MapMaker; import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.common.caching.UserCache; import me.lucko.luckperms.common.model.Group; -import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.contexts.SpongeCalculatorLink; import me.lucko.luckperms.sponge.managers.SpongeGroupManager; import me.lucko.luckperms.sponge.managers.SpongeUserManager; -import me.lucko.luckperms.sponge.model.SpongeGroup; -import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; -import me.lucko.luckperms.sponge.service.calculated.OptionLookup; -import me.lucko.luckperms.sponge.service.calculated.PermissionLookup; import me.lucko.luckperms.sponge.service.legacy.LegacyDataMigrator; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionService; @@ -95,11 +87,6 @@ public class LuckPermsService implements LPPermissionService { private final PersistedCollection defaultSubjects; private final Set descriptionSet; - private final Set> localPermissionCaches; - private final Set>> localParentCaches; - private final Set>> localOptionCaches; - private final Set localDataCaches; - @Getter(value = AccessLevel.NONE) private final LoadingCache collections = Caffeine.newBuilder() .build(s -> new PersistedCollection(this, s)); @@ -108,11 +95,6 @@ public class LuckPermsService implements LPPermissionService { this.plugin = plugin; this.spongeProxy = ProxyFactory.toSponge(this); - localPermissionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); - localParentCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); - localOptionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); - localDataCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); - storage = new SubjectStorage(this, new File(plugin.getDataDirectory(), "sponge-data")); new LegacyDataMigrator(plugin, new File(plugin.getDataDirectory(), "local"), storage).run(); @@ -254,44 +236,15 @@ public class LuckPermsService implements LPPermissionService { } @Override - public void invalidatePermissionCaches() { - for (LoadingCache c : localPermissionCaches) { - c.invalidateAll(); - } - for (CalculatedSubjectData subjectData : localDataCaches) { - subjectData.invalidateLookupCache(); + public void invalidateAllCaches(LPSubject.CacheLevel cacheLevel) { + for (LPSubjectCollection collection : collections.asMap().values()) { + for (LPSubject subject : collection.getLoadedSubjects()) { + subject.invalidateCaches(cacheLevel); + } } - plugin.getCalculatorFactory().invalidateAll(); - - for (User user : plugin.getUserManager().getAll().values()) { - UserCache userCache = user.getUserData(); - userCache.invalidateCache(); - } - - for (SpongeGroup group : plugin.getGroupManager().getAll().values()) { - group.sponge().invalidateCaches(); - } - } - - @Override - public void invalidateParentCaches() { - for (LoadingCache> c : localParentCaches) { - c.invalidateAll(); - } - invalidateOptionCaches(); - invalidatePermissionCaches(); - } - - @Override - public void invalidateOptionCaches() { - for (LoadingCache> c : localOptionCaches) { - c.invalidateAll(); - } - - for (User user : plugin.getUserManager().getAll().values()) { - UserCache userCache = user.getUserData(); - userCache.invalidateCache(); + if (cacheLevel != LPSubject.CacheLevel.OPTION) { + plugin.getCalculatorFactory().invalidateAll(); } } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java index 6866607f3..15a4a6d90 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java @@ -110,7 +110,7 @@ public class CalculatedSubjectData implements LPSubjectData { permissions.put(e.getKey(), new ConcurrentHashMap<>(e.getValue())); } permissionCache.invalidateAll(); - service.invalidatePermissionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PERMISSION); } public void replaceParents(Map> map) { @@ -120,7 +120,7 @@ public class CalculatedSubjectData implements LPSubjectData { set.addAll(e.getValue()); parents.put(e.getKey(), set); } - service.invalidateParentCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PARENT); } public void replaceOptions(Map> map) { @@ -128,7 +128,7 @@ public class CalculatedSubjectData implements LPSubjectData { for (Map.Entry> e : map.entrySet()) { options.put(e.getKey(), new ConcurrentHashMap<>(e.getValue())); } - service.invalidateOptionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.OPTION); } @Override @@ -152,7 +152,7 @@ public class CalculatedSubjectData implements LPSubjectData { } if (b) { permissionCache.invalidateAll(); - service.invalidatePermissionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PERMISSION); } return CompletableFuture.completedFuture(b); } @@ -164,7 +164,7 @@ public class CalculatedSubjectData implements LPSubjectData { } else { permissions.clear(); permissionCache.invalidateAll(); - service.invalidatePermissionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PERMISSION); return CompletableFuture.completedFuture(true); } } @@ -179,7 +179,7 @@ public class CalculatedSubjectData implements LPSubjectData { permissions.remove(contexts); if (!perms.isEmpty()) { permissionCache.invalidateAll(); - service.invalidatePermissionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PERMISSION); return CompletableFuture.completedFuture(true); } return CompletableFuture.completedFuture(false); @@ -199,7 +199,7 @@ public class CalculatedSubjectData implements LPSubjectData { Set set = parents.computeIfAbsent(contexts, c -> ConcurrentHashMap.newKeySet()); boolean b = set.add(parent); if (b) { - service.invalidateParentCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PARENT); } return CompletableFuture.completedFuture(b); } @@ -209,7 +209,7 @@ public class CalculatedSubjectData implements LPSubjectData { Set set = parents.get(contexts); boolean b = set != null && set.remove(parent); if (b) { - service.invalidateParentCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PARENT); } return CompletableFuture.completedFuture(b); } @@ -220,7 +220,7 @@ public class CalculatedSubjectData implements LPSubjectData { return CompletableFuture.completedFuture(false); } else { parents.clear(); - service.invalidateOptionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PARENT); return CompletableFuture.completedFuture(true); } } @@ -233,7 +233,7 @@ public class CalculatedSubjectData implements LPSubjectData { } parents.remove(contexts); - service.invalidateParentCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.PARENT); return CompletableFuture.completedFuture(!set.isEmpty()); } @@ -251,7 +251,7 @@ public class CalculatedSubjectData implements LPSubjectData { Map options = this.options.computeIfAbsent(contexts, c -> new ConcurrentHashMap<>()); boolean b = !stringEquals(options.put(key.toLowerCase(), value), value); if (b) { - service.invalidateOptionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.OPTION); } return CompletableFuture.completedFuture(b); } @@ -261,7 +261,7 @@ public class CalculatedSubjectData implements LPSubjectData { Map options = this.options.get(contexts); boolean b = options != null && options.remove(key.toLowerCase()) != null; if (b) { - service.invalidateOptionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.OPTION); } return CompletableFuture.completedFuture(b); } @@ -272,7 +272,7 @@ public class CalculatedSubjectData implements LPSubjectData { return CompletableFuture.completedFuture(false); } else { options.clear(); - service.invalidateOptionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.OPTION); return CompletableFuture.completedFuture(true); } } @@ -285,7 +285,7 @@ public class CalculatedSubjectData implements LPSubjectData { } options.remove(contexts); - service.invalidateOptionCaches(); + service.invalidateAllCaches(LPSubject.CacheLevel.OPTION); return CompletableFuture.completedFuture(!map.isEmpty()); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java index 81c5a3b34..33714b4a8 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java @@ -98,14 +98,27 @@ public class PersistedSubject implements LPSubject { this.service = service; this.parentCollection = parentCollection; - this.subjectData = new PersistedSubjectData(service, "local:" + parentCollection.getIdentifier() + "/" + identifier + "(p)", this); - this.transientSubjectData = new CalculatedSubjectData(this, service, "local:" + parentCollection.getIdentifier() + "/" + identifier + "(t)"); + this.subjectData = new PersistedSubjectData(service, parentCollection.getIdentifier() + "/" + identifier + "/p", this); + this.transientSubjectData = new CalculatedSubjectData(this, service, parentCollection.getIdentifier() + "/" + identifier + "/t"); + } - service.getLocalDataCaches().add(subjectData); - service.getLocalDataCaches().add(transientSubjectData); - service.getLocalPermissionCaches().add(permissionLookupCache); - service.getLocalParentCaches().add(parentLookupCache); - service.getLocalOptionCaches().add(optionLookupCache); + @Override + public void invalidateCaches(CacheLevel type) { + optionLookupCache.invalidateAll(); + + if (type == CacheLevel.OPTION) { + return; + } + + permissionLookupCache.invalidateAll(); + subjectData.invalidateLookupCache(); + transientSubjectData.invalidateLookupCache(); + + if (type == CacheLevel.PERMISSION) { + return; + } + + parentLookupCache.invalidateAll(); } @Override