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

org.infinispan.client.hotrod.impl.operations.ParallelHotRodOperation Maven / Gradle / Ivy

The newest version!
package org.infinispan.client.hotrod.impl.operations;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.infinispan.client.hotrod.DataFormat;
import org.infinispan.client.hotrod.configuration.Configuration;
import org.infinispan.client.hotrod.impl.ClientStatistics;
import org.infinispan.client.hotrod.impl.ClientTopology;
import org.infinispan.client.hotrod.impl.protocol.Codec;
import org.infinispan.client.hotrod.impl.transport.netty.ChannelFactory;
import org.infinispan.client.hotrod.impl.transport.netty.HeaderDecoder;

import io.netty.buffer.ByteBuf;

/**
 * An HotRod operation that span across multiple remote nodes concurrently (like getAll / putAll).
 *
 * @author Guillaume Darmont / [email protected]
 */
public abstract class ParallelHotRodOperation> extends StatsAffectingHotRodOperation {
   protected final ChannelFactory channelFactory;

   protected ParallelHotRodOperation(Codec codec, ChannelFactory channelFactory, byte[] cacheName, AtomicReference
         clientTopology, int flags, Configuration cfg, DataFormat dataFormat, ClientStatistics clientStatistics) {
      super(ILLEGAL_OP_CODE, ILLEGAL_OP_CODE, codec, flags, cfg, cacheName, clientTopology, channelFactory, dataFormat, clientStatistics);
      this.channelFactory = channelFactory;
   }

   @Override
   public CompletableFuture execute() {
      List operations = mapOperations();

      if (operations.isEmpty()) {
         return CompletableFuture.completedFuture(createCollector());
      } else if (operations.size() == 1) {
         // Only one operation to do, we stay in the caller thread
         return operations.get(0).execute();
      } else {
         // Multiple operation, submit to the thread poll
         return executeParallel(operations);
      }
   }

   private CompletableFuture executeParallel(List operations) {
      T collector = createCollector();
      AtomicInteger counter = new AtomicInteger(operations.size());
      for (SUBOP operation : operations) {
         operation.execute().whenComplete((result, throwable) -> {
            if (throwable != null) {
               completeExceptionally(throwable);
            } else {
               if (collector != null) {
                  synchronized (collector) {
                     combine(collector, result);
                  }
               }
               if (counter.decrementAndGet() == 0) {
                  complete(collector);
               }
            }
         });
      }
      this.exceptionally(throwable -> {
         for (SUBOP operation : operations) {
            operation.cancel(true);
         }
         return null;
      });
      return this;
   }

   protected abstract List mapOperations();

   protected abstract T createCollector();

   protected abstract void combine(T collector, T result);

   @Override
   public void acceptResponse(ByteBuf buf, short status, HeaderDecoder decoder) {
      throw new UnsupportedOperationException();
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy