package org.radargun.service;
import java.lang.reflect.Field;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport;
import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory;
import org.radargun.Service;
import org.radargun.config.Property;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
import org.radargun.traits.InternalsExposition;
import org.radargun.traits.Lifecycle;
import org.radargun.traits.ProvidesTrait;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
@Service(doc = InfinispanHotrodService.SERVICE_DESCRIPTION)
public class InfinispanHotrodService implements Lifecycle, InternalsExposition {
protected static final Log log = LogFactory.getLog(InfinispanHotrodService.class);
protected static final String SERVICE_DESCRIPTION = "HotRod client";
@Property(name = "cache", doc = "Default cache name. By default, it's the default cache as retrived with getCache().")
protected String cacheName;
@Property(doc = "List of server addresses the clients should connect to, separated by semicolons (;).")
protected String servers;
// due to a bug in RCM, we have to duplicate the managers
protected RemoteCacheManager managerNoReturn;
protected RemoteCacheManager managerForceReturn;
private volatile Field transportFactoryField = null;
@ProvidesTrait
public HotRodOperations createOperations() {
return new HotRodOperations(this);
}
@ProvidesTrait
public Lifecycle createLifecycle() {
return this;
}
@ProvidesTrait
public InternalsExposition createExposition() {
return this;
}
@Override
public void start() {
managerNoReturn = new RemoteCacheManager(servers, true);
managerForceReturn = new RemoteCacheManager(servers, true);
}
@Override
public void stop() {
managerNoReturn.stop();
managerNoReturn = null;
managerForceReturn.stop();
managerForceReturn = null;
}
@Override
public boolean isRunning() {
return managerNoReturn != null && managerNoReturn.isStarted();
}
protected TcpTransportFactory getTransportFactory(RemoteCacheManager manager) {
try {
if (transportFactoryField == null) {
Field tf = manager.getClass().getDeclaredField("transportFactory");
tf.setAccessible(true);
transportFactoryField = tf;
}
Object factory = transportFactoryField.get(manager);
if (factory == null) {
log.debug("Transport factory is null");
return null;
} else if (factory instanceof TcpTransportFactory) {
return (TcpTransportFactory) factory;
} else {
log.errorf("Transport factory is '%s' (%s)", factory, factory.getClass().getName());
return null;
}
} catch (Exception e) {
log.error("Failed to retrieve transport factory", e);
return null;
}
}
@Override
public Map<String, Number> getValues() {
Map<String, Number> values = new HashMap<>();
TcpTransportFactory nrFactory = getTransportFactory(managerNoReturn);
TcpTransportFactory frFactory = getTransportFactory(managerForceReturn);
if (nrFactory != null) {
GenericKeyedObjectPool<SocketAddress, TcpTransport> nrConnectionPool = nrFactory.getConnectionPool();
values.put("NR ConnectionPool Active", nrConnectionPool.getNumActive());
values.put("NR ConnectionPool Idle", nrConnectionPool.getNumIdle());
}
if (frFactory != null) {
GenericKeyedObjectPool<SocketAddress, TcpTransport> frConnectionPool = frFactory.getConnectionPool();
values.put("FR ConnectionPool Active", frConnectionPool.getNumActive());
values.put("FR ConnectionPool Idle", frConnectionPool.getNumIdle());
}
return values;
}
@Override
public String getCustomStatistics(String type) {
return null;
}
@Override
public void resetCustomStatistics(String type) {
}
public String getCacheName() {
return cacheName;
}
public RemoteCacheManager getManagerNoReturn() {
return managerNoReturn;
}
public RemoteCacheManager getManagerForceReturn() {
return managerForceReturn;
}
}