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 bf81339f..70051b8e 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 @@ -30,6 +30,7 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.UncheckedExecutionException; import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; @@ -51,6 +52,8 @@ import co.aikar.timings.Timing; import java.util.Collection; import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; public class SpongeGroupManager implements GroupManager, LPSubjectCollection { private final LPSpongePlugin plugin; @@ -68,6 +71,28 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection { } }); + private final LoadingCache subjectLoadingCache = CacheBuilder.newBuilder() + .expireAfterWrite(1, TimeUnit.MINUTES) + .build(new CacheLoader() { + @Override + public LPSubject load(String s) throws Exception { + if (isLoaded(s)) { + return getIfLoaded(s).getSpongeData(); + } + + // Request load + plugin.getStorage().createAndLoadGroup(s).join(); + + SpongeGroup group = getIfLoaded(s); + if (group == null) { + plugin.getLog().severe("Error whilst loading group '" + s + "'."); + throw new RuntimeException(); + } + + return group.getSpongeData(); + } + }); + public SpongeGroupManager(LPSpongePlugin plugin) { this.plugin = plugin; } @@ -138,24 +163,12 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection { return plugin.getService().getFallbackGroupSubjects().get(id); // fallback to transient collection } - // check if the group is loaded in memory. - if (isLoaded(id)) { - return getIfLoaded(id).getSpongeData(); - } else { - - // Group isn't already loaded. hopefully this call is not on the main thread. :( - //plugin.getLog().warn("Group Subject '" + id + "' was requested, but is not loaded in memory. Loading it from storage now."); - long startTime = System.currentTimeMillis(); - plugin.getStorage().createAndLoadGroup(id).join(); - SpongeGroup group = getIfLoaded(id); - - if (group == null) { - plugin.getLog().severe("Error whilst loading group '" + id + "'."); - return plugin.getService().getFallbackGroupSubjects().get(id); - } - - //plugin.getLog().warn("Loading '" + id + "' took " + (System.currentTimeMillis() - startTime) + " ms."); - return group.getSpongeData(); + try { + return subjectLoadingCache.get(id); + } catch (UncheckedExecutionException | ExecutionException e) { + e.printStackTrace(); + plugin.getLog().warn("Couldn't get group subject for id: " + id); + return plugin.getService().getFallbackGroupSubjects().get(id); // fallback to the transient collection } } } 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 19b69e14..1163d19c 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 @@ -30,6 +30,7 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.UncheckedExecutionException; import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; @@ -52,21 +53,15 @@ import org.spongepowered.api.service.permission.PermissionService; import co.aikar.timings.Timing; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; public class SpongeUserManager implements UserManager, LPSubjectCollection { private final LPSpongePlugin plugin; - - private final ReentrantLock loadingLock = new ReentrantLock(); - private final Map loadingLatches = Collections.synchronizedMap(new HashMap<>()); private final LoadingCache objects = CacheBuilder.newBuilder() .build(new CacheLoader() { @@ -81,6 +76,40 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection { } }); + private final LoadingCache subjectLoadingCache = CacheBuilder.newBuilder() + .expireAfterWrite(1, TimeUnit.MINUTES) + .build(new CacheLoader() { + @Override + public LPSubject load(UUID u) throws Exception { + if (isLoaded(UserIdentifier.of(u, null))) { + + SpongeUser user = get(u); + if (user.getUserData() == null) { + user.setupData(false); + } + + return get(u).getSpongeData(); + } + + // Request load + plugin.getStorage().loadUser(u, "null").join(); + + SpongeUser user = get(u); + if (user == null) { + plugin.getLog().severe("Error whilst loading user '" + u + "'."); + throw new RuntimeException(); + } + + user.setupData(false); + + if (user.getUserData() == null) { + plugin.getLog().warn("User data not present for requested user id: " + u); + } + + return user.getSpongeData(); + } + }); + public SpongeUserManager(LPSpongePlugin plugin) { this.plugin = plugin; } @@ -209,69 +238,13 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection { } UUID u = plugin.getUuidCache().getUUID(uuid); - - CountDownLatch latch; - - loadingLock.lock(); try { - boolean loaded = isLoaded(UserIdentifier.of(u, null)); - boolean locked = loadingLatches.containsKey(u); - - if (loaded && !locked) { - return get(u).getSpongeData(); - } - - if (!loaded && !locked) { - latch = new CountDownLatch(1); - loadingLatches.put(u, latch); - - // Request load. - plugin.doAsync(() -> { - try { - plugin.getStorage().loadUser(u, "null").get(); - } catch (Exception e) { - e.printStackTrace(); - } - - SpongeUser user = get(u); - if (user == null) { - plugin.getLog().severe("Error whilst loading user '" + u + "'."); - latch.countDown(); - return; - } - - user.setupData(false); - latch.countDown(); - loadingLatches.remove(u, latch); - }); - - } else { - // wait for the lock, then load. - latch = loadingLatches.get(u); - } - - } finally { - loadingLock.unlock(); - } - - // Wait for the task loading the user. - try { - latch.await(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { + return subjectLoadingCache.get(u); + } catch (UncheckedExecutionException | ExecutionException e) { e.printStackTrace(); - } - - SpongeUser user = get(u); - if (user == null) { - plugin.getLog().warn("Failed to load user subject for id: " + id); + plugin.getLog().warn("Couldn't get user subject for id: " + id); return plugin.getService().getFallbackUserSubjects().get(id); // fallback to the transient collection } - - if (user.getUserData() == null) { - plugin.getLog().warn("User data not present for requested user id: " + id); - } - - return user.getSpongeData(); } } 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 4e3c901c..152db0c4 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 @@ -94,7 +94,12 @@ public class SpongeUser extends User { } private boolean hasData() { - return parent.getUserData() != null; + if (parent.getUserData() != null) { + return true; + } else { + plugin.getLog().warn("User " + parent.getName() + " - " + parent.getUuid() + " does not have any data loaded."); + return false; + } } @Override 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 e37e15c3..f8fda279 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 @@ -250,7 +250,9 @@ public class PersistedSubject implements LPSubject { @Override public Tristate getPermissionValue(@NonNull ContextSet contexts, @NonNull String node) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_PERMISSION_VALUE)) { - return permissionLookupCache.getUnchecked(PermissionLookup.of(node, contexts.makeImmutable())); + Tristate t = permissionLookupCache.getUnchecked(PermissionLookup.of(node, contexts.makeImmutable())); + service.getPlugin().getDebugHandler().offer("local:" + getParentCollection().getCollection() + "/" + identifier, node, t); + return t; } }