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

io.hyperfoil.hotrod.connection.HotRodRemoteCachePoolImpl Maven / Gradle / Ivy

There is a newer version: 0.26
Show newest version
package io.hyperfoil.hotrod.connection;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.infinispan.client.hotrod.impl.ConfigurationProperties;
import org.infinispan.client.hotrod.impl.HotRodURI;
import org.infinispan.client.hotrod.impl.transport.netty.ChannelFactory;

import io.hyperfoil.hotrod.api.HotRodRemoteCachePool;
import io.hyperfoil.hotrod.config.HotRodCluster;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;

public class HotRodRemoteCachePoolImpl implements HotRodRemoteCachePool {

   private final HotRodCluster[] clusters;
   private final EventLoop eventLoop;

   private final Map remoteCacheManagers = new HashMap<>();
   private final Map> remoteCaches = new HashMap<>();

   public HotRodRemoteCachePoolImpl(HotRodCluster[] clusters, EventLoop eventLoop) {
      this.clusters = clusters;
      this.eventLoop = eventLoop;
   }

   @Override
   public void start() {
      for (HotRodCluster cluster : clusters) {
         ConfigurationBuilder cb = HotRodURI.create(cluster.uri()).toConfigurationBuilder();
         Properties properties = new Properties();
         properties.setProperty(ConfigurationProperties.DEFAULT_EXECUTOR_FACTORY_POOL_SIZE, "1");
         cb.asyncExecutorFactory().withExecutorProperties(properties);
         cb.asyncExecutorFactory().factory(p -> eventLoop);
         RemoteCacheManager remoteCacheManager = new RemoteCacheManager(cb.build());
         this.remoteCacheManagers.put(cluster.uri(), remoteCacheManager);
         validateEventLoop(remoteCacheManager);
         for (String cache : cluster.caches()) {
            remoteCaches.put(cache, remoteCacheManager.getCache(cache));
         }
      }
   }

   private void validateEventLoop(RemoteCacheManager remoteCacheManager) {
      ChannelFactory channelFactory = remoteCacheManager.getChannelFactory();
      try {
         Field eventLoopField = ChannelFactory.class.getDeclaredField("eventLoopGroup");
         eventLoopField.setAccessible(true);
         EventLoopGroup actualEventLoop = (EventLoopGroup) eventLoopField.get(channelFactory);
         if (actualEventLoop != eventLoop) {
            throw new IllegalStateException("Event loop was not injected correctly. This is a classpath issue.");
         }
      } catch (NoSuchFieldException | IllegalAccessException e) {
         throw new IllegalStateException(e);
      }
      ExecutorService asyncExecutorService = remoteCacheManager.getAsyncExecutorService();
      if (asyncExecutorService != eventLoop) {
         throw new IllegalStateException("Event loop was not configured correctly.");
      }
   }

   @Override
   public void shutdown() {
      this.remoteCacheManagers.values().forEach(RemoteCacheManager::stop);
   }

   @Override
   public RemoteCacheWithoutToString getRemoteCache(String cacheName) {
      return new RemoteCacheWithoutToString(this.remoteCaches.get(cacheName));
   }

   /*
    * While debugging, the toString method of RemoteCache will do a block call
    *  at org.infinispan.client.hotrod.impl.RemoteCacheSupport.size(RemoteCacheSupport.java:397)
    *  at org.infinispan.client.hotrod.impl.RemoteCacheImpl.isEmpty(RemoteCacheImpl.java:275)
    * This prevent us of configuring each IDE in order to debug a code
    */
   public static class RemoteCacheWithoutToString {
      private RemoteCache remoteCache;
      public RemoteCacheWithoutToString(RemoteCache remoteCache) {
         this.remoteCache = remoteCache;
      }

      public CompletableFuture putAsync(K key, V value) {
         return remoteCache.putAsync(key, value);
      }

      public CompletableFuture getAsync(K key) {
         return remoteCache.getAsync(key);
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy