Fix Sponge subjects from being unloaded and never reinitialized - closes #124

This commit is contained in:
Luck 2017-01-10 19:17:45 +00:00
parent ab0f9bbdbd
commit dd50193c18
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
6 changed files with 82 additions and 56 deletions

View File

@ -41,6 +41,15 @@ import java.util.Map;
*/ */
public abstract class AbstractManager<I, T extends Identifiable<I>> implements Manager<I, T> { public abstract class AbstractManager<I, T extends Identifiable<I>> implements Manager<I, T> {
@SuppressWarnings("unchecked")
private static <I> I lowerCase(I i) {
if (i instanceof String) {
return (I) ((String) i).toLowerCase();
} else {
return i;
}
}
private final LoadingCache<I, T> objects = CacheBuilder.newBuilder() private final LoadingCache<I, T> objects = CacheBuilder.newBuilder()
.build(new CacheLoader<I, T>() { .build(new CacheLoader<I, T>() {
@Override @Override
@ -61,36 +70,30 @@ public abstract class AbstractManager<I, T extends Identifiable<I>> implements M
@Override @Override
public T getOrMake(I id) { public T getOrMake(I id) {
if (id instanceof String) { return objects.getUnchecked(lowerCase(id));
return objects.getUnchecked((I) ((String) id).toLowerCase());
} else {
return objects.getUnchecked(id);
}
} }
@Override @Override
public T getIfLoaded(I id) { public T getIfLoaded(I id) {
if (id instanceof String) { return objects.getIfPresent(lowerCase(id));
return objects.getIfPresent(((String) id).toLowerCase());
} else {
return objects.getIfPresent(id);
}
} }
@Override @Override
public boolean isLoaded(I id) { public boolean isLoaded(I id) {
if (id instanceof String) { return objects.asMap().containsKey(lowerCase(id));
return objects.asMap().containsKey(((String) id).toLowerCase()); }
} else {
return objects.asMap().containsKey(id); @Override
public void unload(I id) {
if (id != null) {
objects.invalidate(lowerCase(id));
} }
} }
@Override @Override
public void unload(T t) { public void unload(T t) {
if (t != null) { if (t != null) {
objects.invalidate(t.getId()); unload(t.getId());
} }
} }

View File

@ -66,6 +66,13 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
*/ */
boolean isLoaded(I id); boolean isLoaded(I id);
/**
* Removes and unloads the object from the manager
*
* @param id The object id to unload
*/
void unload(I id);
/** /**
* Removes and unloads the object from the manager * Removes and unloads the object from the manager
* *

View File

@ -25,6 +25,7 @@ package me.lucko.luckperms.sponge;
import me.lucko.luckperms.api.caching.UserData; import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.utils.AbstractListener; import me.lucko.luckperms.common.utils.AbstractListener;
import me.lucko.luckperms.sponge.timings.LPTiming; import me.lucko.luckperms.sponge.timings.LPTiming;
@ -113,7 +114,15 @@ public class SpongeListener extends AbstractListener {
@Listener(order = Order.LAST) @Listener(order = Order.LAST)
public void onClientLeave(ClientConnectionEvent.Disconnect e) { public void onClientLeave(ClientConnectionEvent.Disconnect e) {
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LEAVE)) { try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LEAVE)) {
onLeave(e.getTargetEntity().getUniqueId()); final UuidCache cache = plugin.getUuidCache();
final User user = plugin.getUserManager().get(cache.getUUID(e.getTargetEntity().getUniqueId()));
if (user != null) {
user.unregisterData();
}
// Unload the user from memory when they disconnect;
cache.clearCache(e.getTargetEntity().getUniqueId());
} }
} }

View File

@ -113,23 +113,30 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
@Override @Override
public SpongeGroup getOrMake(String id) { public SpongeGroup getOrMake(String id) {
return objects.getUnchecked(id); return objects.getUnchecked(id.toLowerCase());
} }
@Override @Override
public SpongeGroup getIfLoaded(String id) { public SpongeGroup getIfLoaded(String id) {
return objects.getIfPresent(id); return objects.getIfPresent(id.toLowerCase());
} }
@Override @Override
public boolean isLoaded(String id) { public boolean isLoaded(String id) {
return objects.asMap().containsKey(id); return objects.asMap().containsKey(id.toLowerCase());
}
@Override
public void unload(String id) {
if (id != null) {
objects.invalidate(id.toLowerCase());
}
} }
@Override @Override
public void unload(Group t) { public void unload(Group t) {
if (t != null) { if (t != null) {
objects.invalidate(t.getId()); unload(t.getId());
} }
} }

View File

@ -125,6 +125,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
Set<UserIdentifier> set = new HashSet<>(); Set<UserIdentifier> set = new HashSet<>();
for (Map.Entry<UserIdentifier, SpongeUser> user : objects.asMap().entrySet()) { for (Map.Entry<UserIdentifier, SpongeUser> user : objects.asMap().entrySet()) {
if (user.getValue().getSpongeData().shouldCleanup()) { if (user.getValue().getSpongeData().shouldCleanup()) {
user.getValue().unregisterData();
set.add(user.getKey()); set.add(user.getKey());
} }
} }
@ -156,10 +157,17 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
return objects.asMap().containsKey(id); return objects.asMap().containsKey(id);
} }
@Override
public void unload(UserIdentifier id) {
if (id != null) {
objects.invalidate(id);
}
}
@Override @Override
public void unload(User t) { public void unload(User t) {
if (t != null) { if (t != null) {
objects.invalidate(t.getId()); unload(t.getId());
} }
} }
@ -194,9 +202,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
@Override @Override
public void cleanup(User user) { public void cleanup(User user) {
if (!plugin.isOnline(plugin.getUuidCache().getExternalUUID(user.getUuid()))) { // Do nothing - this instance uses other means in order to cleanup
unload(user);
}
} }
@Override @Override

View File

@ -93,12 +93,10 @@ public class SpongeUser extends User {
return (now - lastUse) > 600000; return (now - lastUse) > 600000;
} }
private boolean hasData() { private void checkData() {
if (parent.getUserData() != null) { if (parent.getUserData() == null) {
return true;
} else {
plugin.getLog().warn("User " + parent.getName() + " - " + parent.getUuid() + " does not have any data loaded."); plugin.getLog().warn("User " + parent.getName() + " - " + parent.getUuid() + " does not have any data loaded.");
return false; parent.setupData(false);
} }
} }
@ -133,10 +131,7 @@ public class SpongeUser extends User {
public Tristate getPermissionValue(ContextSet contexts, String permission) { public Tristate getPermissionValue(ContextSet contexts, String permission) {
logUsage(); logUsage();
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PERMISSION_VALUE)) { try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PERMISSION_VALUE)) {
if (!hasData()) { checkData();
return Tristate.UNDEFINED;
}
return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission); return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission);
} }
} }
@ -155,16 +150,15 @@ public class SpongeUser extends User {
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PARENTS)) { try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PARENTS)) {
ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder(); ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder();
if (hasData()) { checkData();
for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) { for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) {
if (!perm.startsWith("group.")) { if (!perm.startsWith("group.")) {
continue; continue;
} }
String groupName = perm.substring("group.".length()); String groupName = perm.substring("group.".length());
if (plugin.getGroupManager().isLoaded(groupName)) { if (plugin.getGroupManager().isLoaded(groupName)) {
subjects.add(plugin.getService().getGroupSubjects().get(groupName).toReference()); subjects.add(plugin.getService().getGroupSubjects().get(groupName).toReference());
}
} }
} }
@ -179,25 +173,25 @@ public class SpongeUser extends User {
public Optional<String> getOption(ContextSet contexts, String s) { public Optional<String> getOption(ContextSet contexts, String s) {
logUsage(); logUsage();
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_OPTION)) { try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_OPTION)) {
if (hasData()) { checkData();
MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts));
if (s.equalsIgnoreCase("prefix")) {
if (data.getPrefix() != null) {
return Optional.of(data.getPrefix());
}
}
if (s.equalsIgnoreCase("suffix")) { MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts));
if (data.getSuffix() != null) { if (s.equalsIgnoreCase("prefix")) {
return Optional.of(data.getSuffix()); if (data.getPrefix() != null) {
} return Optional.of(data.getPrefix());
} }
}
if (data.getMeta().containsKey(s)) { if (s.equalsIgnoreCase("suffix")) {
return Optional.of(data.getMeta().get(s)); if (data.getSuffix() != null) {
return Optional.of(data.getSuffix());
} }
} }
if (data.getMeta().containsKey(s)) {
return Optional.of(data.getMeta().get(s));
}
Optional<String> v = plugin.getService().getUserSubjects().getDefaultSubject().resolve(getService()).getOption(contexts, s); Optional<String> v = plugin.getService().getUserSubjects().getDefaultSubject().resolve(getService()).getOption(contexts, s);
if (v.isPresent()) { if (v.isPresent()) {
return v; return v;