All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.commands.read.EntrySetCommand Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
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