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

org.infinispan.interceptors.distribution.DistributionBulkInterceptor Maven / Gradle / Ivy

package org.infinispan.interceptors.distribution;

import org.infinispan.AdvancedCache;
import org.infinispan.Cache;
import org.infinispan.CacheSet;
import org.infinispan.CacheStream;
import org.infinispan.commands.LocalFlagAffectedCommand;
import org.infinispan.commands.read.AbstractCloseableIteratorCollection;
import org.infinispan.commands.read.EntrySetCommand;
import org.infinispan.commands.read.KeySetCommand;
import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.commons.util.CloseableIteratorMapper;
import org.infinispan.commons.util.CloseableSpliterator;
import org.infinispan.commons.util.Closeables;
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.context.impl.LocalTxInvocationContext;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.ComponentRegistry;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.stream.StreamMarshalling;
import org.infinispan.stream.impl.ClusterStreamManager;
import org.infinispan.stream.impl.DistributedCacheStream;
import org.infinispan.stream.impl.RemovableCloseableIterator;
import org.infinispan.stream.impl.RemovableIterator;
import org.infinispan.stream.impl.tx.TxClusterStreamManager;
import org.infinispan.stream.impl.tx.TxDistributedCacheStream;

import java.util.Iterator;
import java.util.Map;
import java.util.Spliterator;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import static org.infinispan.factories.KnownComponentNames.ASYNC_OPERATIONS_EXECUTOR;

/**
 * Interceptor that handles bulk entrySet and keySet commands when using in a distributed/replicated environment.
 * This interceptor produces backing collections for either method and a distributed stream for either which leverages
 * distributed processing through the cluster.
 * @param  The key type of entries
 * @param  The value type of entries
 * @deprecated Since 8.2, no longer public API.
 */
@Deprecated
public class DistributionBulkInterceptor extends CommandInterceptor {
   private Cache cache;

   @Inject
   public void inject(Cache cache) {
      this.cache = cache;
   }

   @Override
   public CacheSet> visitEntrySetCommand(InvocationContext ctx, EntrySetCommand command) throws Throwable {
      CacheSet> entrySet = (CacheSet>) super.visitEntrySetCommand(ctx, command);
      if (!command.hasFlag(Flag.CACHE_MODE_LOCAL)) {
         if (ctx.isInTxScope()) {
            return new TxBackingEntrySet<>(getCacheWithFlags(cache, command), entrySet, command,
                    (LocalTxInvocationContext) ctx);
         } else {
            return new BackingEntrySet<>(getCacheWithFlags(cache, command), entrySet, command);
         }
      }
      return entrySet;
   }

   protected static class BackingEntrySet extends AbstractCloseableIteratorCollection, K, V>
           implements CacheSet> {
      protected final CacheSet> entrySet;
      protected final LocalFlagAffectedCommand command;

      private BackingEntrySet(Cache cache, CacheSet> entrySet, LocalFlagAffectedCommand command) {
         super(cache);
         this.entrySet = entrySet;
         this.command = command;
      }

      @Override
      public CloseableIterator> iterator() {
         return new CloseableIteratorMapper<>(new RemovableCloseableIterator<>(Closeables.iterator(stream()), cache,
                 CacheEntry::getKey), e -> new EntryWrapper<>(cache, e));
      }

      @Override
      public CloseableSpliterator> spliterator() {
         return Closeables.spliterator(stream());
      }

      @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);
         if (entry != null) {
            return cache.remove(entry.getKey(), entry.getValue());
         }
         return false;
      }

      private Map.Entry toEntry(Object obj) {
         if (obj instanceof Map.Entry) {
            return (Map.Entry) obj;
         } else {
            return null;
         }
      }

      @Override
      public CacheStream> stream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         CacheStream> cacheStream = new DistributedCacheStream>(
                 cache.getCacheManager().getAddress(), false, advancedCache.getDistributionManager(),
                 () -> entrySet.stream(), registry.getComponent(ClusterStreamManager.class),
                 !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry) {
            @Override
            public Iterator> iterator() {
               if (intermediateOperations.isEmpty()) {
                  return new RemovableIterator<>(super.iterator(), cache, e -> e.getKey());
               }
               return super.iterator();
            }
         };
         return applyTimeOut(cacheStream, cache);
      }

      @Override
      public CacheStream> parallelStream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         CacheStream> cacheStream = new DistributedCacheStream<>(cache.getCacheManager().getAddress(),
                 true, advancedCache.getDistributionManager(), () -> entrySet.parallelStream(),
                 registry.getComponent(ClusterStreamManager.class), !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry);
         return applyTimeOut(cacheStream, cache);
      }
   }

   protected static class TxBackingEntrySet extends BackingEntrySet {
      private final LocalTxInvocationContext ctx;

      private TxBackingEntrySet(Cache cache, CacheSet> entrySet, LocalFlagAffectedCommand command,
                                LocalTxInvocationContext ctx) {
         super(cache, entrySet, command);
         this.ctx = ctx;
      }

      @Override
      public CacheStream> stream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         DistributionManager dm = advancedCache.getDistributionManager();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         ClusterStreamManager realManager = registry.getComponent(ClusterStreamManager.class);
         TxClusterStreamManager txManager = new TxClusterStreamManager<>(realManager, ctx, dm.getConsistentHash());

         CacheStream> cacheStream = new TxDistributedCacheStream<>(cache.getCacheManager().getAddress(),
                 false, dm, () -> entrySet.stream(), txManager, !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry, ctx);
         return applyTimeOut(cacheStream, cache);
      }

      @Override
      public CacheStream> parallelStream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         DistributionManager dm = advancedCache.getDistributionManager();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         ClusterStreamManager realManager = registry.getComponent(ClusterStreamManager.class);
         TxClusterStreamManager txManager = new TxClusterStreamManager<>(realManager, ctx, dm.getConsistentHash());

         CacheStream> cacheStream = new TxDistributedCacheStream<>(cache.getCacheManager().getAddress(),
                 true, dm, () -> entrySet.parallelStream(), txManager, !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry, ctx);
         return applyTimeOut(cacheStream, cache);
      }
   }

   private static  CacheStream applyTimeOut(CacheStream stream, Cache cache) {
      return stream.timeout(cache.getCacheConfiguration().clustering().sync().replTimeout(),
              TimeUnit.MILLISECONDS);
   }

   /**
    * 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);
      }
   }

   @Override
   public CacheSet visitKeySetCommand(InvocationContext ctx, KeySetCommand command) throws Throwable {
      if (!command.hasFlag(Flag.CACHE_MODE_LOCAL)) {
         if (ctx.isInTxScope()) {
            return new TxBackingKeySet<>(getCacheWithFlags(cache, command), cache.getAdvancedCache().withFlags(
                    Flag.CACHE_MODE_LOCAL).cacheEntrySet(), command, (LocalTxInvocationContext) ctx);
         } else {
            return new BackingKeySet<>(getCacheWithFlags(cache, command), cache.getAdvancedCache().withFlags(
                    Flag.CACHE_MODE_LOCAL).cacheEntrySet(), command);
         }
      }
      return (CacheSet) super.visitKeySetCommand(ctx, command);
   }

   protected static class BackingKeySet extends AbstractCloseableIteratorCollection
           implements CacheSet {
      protected final CacheSet> entrySet;
      protected final LocalFlagAffectedCommand command;

      public BackingKeySet(Cache cache, CacheSet> entrySet, LocalFlagAffectedCommand command) {
         super(cache);
         this.entrySet = entrySet;
         this.command = command;
      }

      @Override
      public CloseableIterator iterator() {
         return new RemovableCloseableIterator(Closeables.iterator(stream()), cache, Function.identity());
      }

      @Override
      public boolean contains(Object o) {
         return cache.containsKey(o);
      }

      @Override
      public boolean remove(Object o) {
         return cache.remove(o) != null;
      }

      @Override
      public CloseableSpliterator spliterator() {
         return Closeables.spliterator(iterator(), Long.MAX_VALUE,
                 Spliterator.CONCURRENT | Spliterator.DISTINCT | Spliterator.NONNULL);
      }

      @Override
      public CacheStream stream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         return new DistributedCacheStream(cache.getCacheManager().getAddress(), false,
                 advancedCache.getDistributionManager(), () -> entrySet.stream(),
                 registry.getComponent(ClusterStreamManager.class), !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry,
                 StreamMarshalling.entryToKeyFunction()) {
            @Override
            public Iterator iterator() {
               // The act of mapping to key requires 1 intermediate operation
               if (intermediateOperations.size() == 1) {
                  return new RemovableIterator<>(super.iterator(), cache, Function.identity());
               }
               return super.iterator();
            }
         };
      }

      @Override
      public CacheStream parallelStream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         return new DistributedCacheStream<>(cache.getCacheManager().getAddress(), true,
                 advancedCache.getDistributionManager(), () -> entrySet.parallelStream(),
                 registry.getComponent(ClusterStreamManager.class), !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry,
                 StreamMarshalling.entryToKeyFunction());
      }
   }

   private static class TxBackingKeySet extends BackingKeySet {
      private final LocalTxInvocationContext ctx;

      public TxBackingKeySet(Cache cache, CacheSet> entrySet, LocalFlagAffectedCommand command,
                             LocalTxInvocationContext ctx) {
         super(cache, entrySet, command);
         this.ctx = ctx;
      }

      @Override
      public CacheStream stream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         DistributionManager dm = advancedCache.getDistributionManager();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         ClusterStreamManager realManager = registry.getComponent(ClusterStreamManager.class);
         TxClusterStreamManager txManager = new TxClusterStreamManager<>(realManager, ctx, dm.getConsistentHash());

         return new TxDistributedCacheStream<>(cache.getCacheManager().getAddress(), false,
                 dm, () -> entrySet.stream(), txManager, !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry,
                 StreamMarshalling.entryToKeyFunction(), ctx);
      }

      @Override
      public CacheStream parallelStream() {
         AdvancedCache advancedCache = cache.getAdvancedCache();
         DistributionManager dm = advancedCache.getDistributionManager();
         ComponentRegistry registry = advancedCache.getComponentRegistry();
         ClusterStreamManager realManager = registry.getComponent(ClusterStreamManager.class);
         TxClusterStreamManager txManager = new TxClusterStreamManager<>(realManager, ctx, dm.getConsistentHash());

         return new TxDistributedCacheStream<>(cache.getCacheManager().getAddress(), true,
                 dm, () -> entrySet.parallelStream(), txManager, !command.hasFlag(Flag.SKIP_CACHE_LOAD),
                 cache.getCacheConfiguration().clustering().stateTransfer().chunkSize(),
                 registry.getComponent(Executor.class, ASYNC_OPERATIONS_EXECUTOR), registry,
                 StreamMarshalling.entryToKeyFunction(), ctx);
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy