package org.radargun.service;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.infinispan.client.hotrod.Search;
import org.infinispan.protostream.SerializationContext;
import org.infinispan.query.dsl.QueryFactory;
import org.infinispan.query.remote.ProtobufMetadataManager;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
import org.radargun.traits.Query;
import org.radargun.utils.Utils;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
public class InfinispanHotrodQueryable extends AbstractInfinispanQueryable {
private static final String REMOTING_JMX_SERVICE_URL_TEMPLATE = "service:jmx:remoting-jmx://%s:%d";
protected static final Log log = LogFactory.getLog(InfinispanHotrodQueryable.class);
protected final Infinispan60HotrodService service;
public InfinispanHotrodQueryable(Infinispan60HotrodService service) {
this.service = service;
}
@Override
public Query.Builder getBuilder(String cacheName, Class<?> clazz) {
if (cacheName == null) {
cacheName = service.cacheName;
}
QueryFactory factory = Search.getQueryFactory(
cacheName == null ? service.managerForceReturn.getCache() : service.managerForceReturn.getCache(cacheName));
return new QueryBuilderImpl(factory, clazz);
}
@Override
public void reindex(String containerName) {
// We should rather throw an exception because if the cache is configured
// with manual index we cannot make sure that the cache will be reindexed.
throw new UnsupportedOperationException();
}
protected void registerProtofilesLocal(SerializationContext context) {
for (String protofile : service.protofiles) {
try {
context.registerProtofile(protofile);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to read protofile " + protofile, e);
}
}
}
protected void registerProtofilesRemote() {
JMXConnector connector = null;
MBeanServerConnection connection = null;
for (String host : service.serverHostnames) {
JMXServiceURL serviceURL;
try {
serviceURL = new JMXServiceURL(String.format(getRemotingJmxUrlTemplate(), host, service.jmxPort));
} catch (MalformedURLException e) {
log.error("Failed to form JMX URL", e);
continue;
}
try {
connector = JMXConnectorFactory.newJMXConnector(serviceURL, null);
connector.connect();
connection = connector.getMBeanServerConnection();
log.info("Connected via JMX to " + host + " (" + serviceURL + ")");
} catch (IOException e) {
log.error("Failed to connect to " + serviceURL, e);
closeConnector(connector);
continue;
}
break;
}
if (connection == null) {
throw new IllegalStateException("Cannot connect to any server.");
}
try {
doJmxRegistration(connection);
} finally {
closeConnector(connector);
}
}
protected String getRemotingJmxUrlTemplate() {
return REMOTING_JMX_SERVICE_URL_TEMPLATE;
}
protected void doJmxRegistration(MBeanServerConnection connection) {
ObjectName objName = null;
try {
objName = new ObjectName(service.jmxDomain + ":type=RemoteQuery,name="
+ ObjectName.quote(service.clusterName)
+ ",component=" + ProtobufMetadataManager.OBJECT_NAME);
} catch (MalformedObjectNameException e) {
throw new IllegalStateException("Failed to register protofiles", e);
}
for (String protofile : service.protofiles) {
byte[] descriptor;
try (InputStream inputStream = getClass().getResourceAsStream(protofile)) {
descriptor = Utils.readAsBytes(inputStream);
} catch (IOException e) {
throw new IllegalStateException("Failed to read protofile " + protofile, e);
}
try {
connection.invoke(objName, "registerProtofile", new Object[] {descriptor}, new String[] {byte[].class.getName()});
log.info("Protofile " + protofile + " registered.");
} catch (Exception e) {
throw new IllegalStateException("Failed to register protofile " + protofile, e);
}
}
}
private void closeConnector(JMXConnector connector) {
if (connector != null) {
try {
connector.close();
} catch (IOException e) {
log.error("Failed to close connector ", e);
}
}
}
@Override
public Query.Context createContext(String containerName) {
return new RemoteQueryContext();
}
protected static class RemoteQueryContext implements Query.Context {
@Override
public void close() {
}
}
}