org.infinispan.commands.read.EntrySetCommand Maven / Gradle / Ivy
package org.infinispan.commands.read;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Spliterator;
import org.infinispan.Cache;
import org.infinispan.CacheSet;
import org.infinispan.CacheStream;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.commands.Visitor;
import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.commons.util.CloseableSpliterator;
import org.infinispan.commons.util.Closeables;
import org.infinispan.commons.util.EnumUtil;
import org.infinispan.container.DataContainer;
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.container.entries.ForwardingCacheEntry;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.stream.impl.local.EntryStreamSupplier;
import org.infinispan.stream.impl.local.LocalCacheStream;
import org.infinispan.util.DataContainerRemoveIterator;
/**
* Command implementation for {@link java.util.Map#entrySet()} functionality.
*
* @author Galder Zamarreño
* @author Trustin Lee
* @author William Burns
* @since 4.0
*/
public class EntrySetCommand extends AbstractLocalCommand implements VisitableCommand {
private final Cache cache;
public EntrySetCommand(Cache cache, long flagsBitSet) {
setFlagsBitSet(flagsBitSet);
if (flagsBitSet != EnumUtil.EMPTY_BIT_SET) {
this.cache = cache.getAdvancedCache().withFlags(EnumUtil.enumArrayOf(flagsBitSet, Flag.class));
} else {
this.cache = cache;
}
}
@Override
public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable {
return visitor.visitEntrySetCommand(ctx, this);
}
@Override
public LoadType loadType() {
throw new UnsupportedOperationException();
}
@Override
public Set> perform(InvocationContext ctx) throws Throwable {
return new BackingEntrySet<>(cache);
}
@Override
public String toString() {
return "EntrySetCommand{" +
"cache=" + cache.getName() +
'}';
}
static class BackingEntrySet extends AbstractCloseableIteratorCollection, K, V>
implements CacheSet> {
BackingEntrySet(Cache cache) {
super(cache);
}
@Override
public CloseableIterator> iterator() {
Iterator> iterator = new DataContainerRemoveIterator<>(cache);
return new EntryWrapperIterator<>(cache, iterator);
}
@Override
public CloseableSpliterator> spliterator() {
DataContainer dc = cache.getAdvancedCache().getDataContainer();
return Closeables.spliterator(Closeables.iterator(new DataContainerRemoveIterator<>(cache, dc)), dc.size(),
Spliterator.CONCURRENT | Spliterator.NONNULL | Spliterator.DISTINCT);
}
@Override
public int size() {
return cache.getAdvancedCache().getDataContainer().size();
}
@Override
public boolean contains(Object o) {
Map.Entry entry = toEntry(o);
if (entry != null) {
V value = cache.get(entry.getKey());
return value != null && value.equals(entry.getValue());
}
return false;
}
@Override
public boolean remove(Object o) {
Map.Entry entry = toEntry(o);
return entry != null && cache.remove(entry.getKey(), entry.getValue());
}
@Override
public boolean add(CacheEntry internalCacheEntry) {
/**
* {@link Map#entrySet()} defines no support for add or addAll methods
*/
throw new UnsupportedOperationException();
}
private Map.Entry toEntry(Object obj) {
if (obj instanceof Map.Entry) {
return (Map.Entry) obj;
} else {
return null;
}
}
private ConsistentHash getConsistentHash(Cache cache) {
DistributionManager dm = cache.getAdvancedCache().getDistributionManager();
if (dm != null) {
return dm.getReadConsistentHash();
}
return null;
}
@Override
public CacheStream> stream() {
return new LocalCacheStream<>(new EntryStreamSupplier<>(cache, getConsistentHash(cache),
() -> super.stream()), false, cache.getAdvancedCache().getComponentRegistry());
}
@Override
public CacheStream> parallelStream() {
return new LocalCacheStream<>(new EntryStreamSupplier<>(cache, getConsistentHash(cache),
() -> super.stream()), true, cache.getAdvancedCache().getComponentRegistry());
}
}
/**
* Wrapper for iterator that produces CacheEntry instances that allow for updating the cache when
* the cache entry's value is updated
* @param The key type
* @param The value type
*/
private static class EntryWrapperIterator implements CloseableIterator> {
private final Cache cache;
private final Iterator> iterator;
public EntryWrapperIterator(Cache cache, Iterator> iterator) {
this.cache = cache;
this.iterator = iterator;
}
@Override
public void close() {
// Does nothing because data container iterator doesn't need to be closed
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public CacheEntry next() {
CacheEntry entry = iterator.next();
return new EntryWrapper<>(cache, entry);
}
@Override
public void remove() {
iterator.remove();
}
}
/**
* Wrapper for CacheEntry(s) that can be used to update the cache when it's value is set.
* @param The key type
* @param The value type
*/
private static class EntryWrapper extends ForwardingCacheEntry {
private final Cache cache;
private final CacheEntry entry;
public EntryWrapper(Cache cache, CacheEntry entry) {
this.cache = cache;
this.entry = entry;
}
@Override
protected CacheEntry delegate() {
return entry;
}
@Override
public V setValue(V value) {
cache.put(entry.getKey(), value);
return super.setValue(value);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy