Store all accumulated meta values in MetaCache

This commit is contained in:
Luck 2017-06-19 21:39:46 +01:00
parent 8766e3b408
commit e50fa17f7c
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
4 changed files with 55 additions and 20 deletions

View File

@ -25,6 +25,8 @@
package me.lucko.luckperms.api.caching;
import com.google.common.collect.ListMultimap;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import java.util.Map;
@ -38,7 +40,24 @@ import java.util.SortedMap;
public interface MetaData {
/**
* Gets an immutable copy of the meta this user has
* Gets an immutable copy of the meta this user has.
*
* <p>A list multimap is used because when inherited values are included, each key can be
* mapped to multiple values.</p>
*
* <p>The first value to be accumulated (and used to represent the key in {@link #getMeta()} is at index 0
* in the list. Any additional values are stored in order of accumulation.</p>
*
* @return an immutable multimap of meta
* @since 3.3
*/
ListMultimap<String, String> getMetaMultimap();
/**
* Gets an immutable copy of the meta this user has.
*
* <p>This map is formed by taking the entries in {@link #getMetaMultimap()}, and mapping each key
* to the value at index 0 in the corresponding list.</p>
*
* @return an immutable map of meta
*/

View File

@ -30,6 +30,9 @@ import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.config.ConfigKeys;
@ -38,7 +41,6 @@ import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
@ -57,7 +59,7 @@ public class MetaAccumulator {
}
@Getter(AccessLevel.NONE)
private final Map<String, String> meta;
private final ListMultimap<String, String> meta;
private final SortedMap<Integer, String> prefixes;
private final SortedMap<Integer, String> suffixes;
private int weight = 0;
@ -66,7 +68,7 @@ public class MetaAccumulator {
private final MetaStack suffixStack;
public MetaAccumulator(@NonNull MetaStack prefixStack, @NonNull MetaStack suffixStack) {
this.meta = new HashMap<>();
this.meta = ArrayListMultimap.create();
this.prefixes = new TreeMap<>(Comparator.reverseOrder());
this.suffixes = new TreeMap<>(Comparator.reverseOrder());
this.prefixStack = prefixStack;
@ -76,9 +78,7 @@ public class MetaAccumulator {
public void accumulateNode(LocalizedNode n) {
if (n.isMeta()) {
Map.Entry<String, String> entry = n.getMeta();
if (!meta.containsKey(entry.getKey())) {
meta.put(entry.getKey(), entry.getValue());
}
meta.put(entry.getKey(), entry.getValue());
}
if (n.isPrefix()) {
@ -106,7 +106,7 @@ public class MetaAccumulator {
// We can assume that if this method is being called, this holder is effectively finalized. (it's not going to accumulate more nodes)
// Therefore, it should be ok to set the weight meta key, if not already present.
public Map<String, String> getMeta() {
public ListMultimap<String, String> getMeta() {
if (!this.meta.containsKey("weight") && this.weight != 0) {
this.meta.put("weight", String.valueOf(this.weight));
}

View File

@ -25,16 +25,20 @@
package me.lucko.luckperms.common.caching;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ListMultimap;
import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.metastacking.MetaStack;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.locks.ReadWriteLock;
@ -43,29 +47,38 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Holds a user's cached meta for a given context
*/
@Getter
@NoArgsConstructor
public class MetaCache implements MetaData {
@Getter(AccessLevel.NONE)
private final ReadWriteLock lock = new ReentrantReadWriteLock();
@Getter
private ListMultimap<String, String> metaMultimap = ImmutableListMultimap.of();
private Map<String, String> meta = ImmutableMap.of();
@Getter
private SortedMap<Integer, String> prefixes = ImmutableSortedMap.of();
@Getter
private SortedMap<Integer, String> suffixes = ImmutableSortedMap.of();
@Getter
private MetaStack prefixStack = null;
@Getter
private MetaStack suffixStack = null;
public void loadMeta(MetaAccumulator meta) {
lock.writeLock().lock();
try {
this.meta = ImmutableMap.copyOf(meta.getMeta());
this.metaMultimap = ImmutableListMultimap.copyOf(meta.getMeta());
//noinspection unchecked
Map<String, List<String>> metaMap = (Map) this.metaMultimap.asMap();
ImmutableMap.Builder<String, String> metaMapBuilder = ImmutableMap.builder();
for (Map.Entry<String, List<String>> e : metaMap.entrySet()) {
if (e.getValue().isEmpty()) {
continue;
}
// take the value which was accumulated first
metaMapBuilder.put(e.getKey(), e.getValue().get(0));
}
this.meta = metaMapBuilder.build();
this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes());
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
this.prefixStack = meta.getPrefixStack();

View File

@ -30,6 +30,7 @@ import lombok.Getter;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode;
@ -54,6 +55,7 @@ import org.spongepowered.api.service.permission.PermissionService;
import co.aikar.timings.Timing;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@ -238,8 +240,9 @@ public class SpongeGroup extends Group {
private Optional<String> getMeta(ImmutableContextSet contexts, String key) {
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, ExtractedContexts.generate(plugin.getService().calculateContexts(contexts)));
Map<String, String> meta = metaAccumulator.getMeta();
return Optional.ofNullable(meta.get(key));
ListMultimap<String, String> meta = metaAccumulator.getMeta();
List<String> ret = meta.get(key);
return ret.isEmpty() ? Optional.empty() : Optional.of(ret.get(0));
}
}
}