com.findwise.hydra.net.RESTServer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hydra-core Show documentation
Show all versions of hydra-core Show documentation
Hydra Core - The main runnable artifact of Hydra
package com.findwise.hydra.net;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpStatus;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.nio.DefaultHttpServerIODispatch;
import org.apache.http.impl.nio.DefaultNHttpServerConnection;
import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.NHttpConnectionFactory;
import org.apache.http.nio.NHttpServerConnection;
import org.apache.http.nio.protocol.BasicAsyncRequestHandler;
import org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry;
import org.apache.http.nio.protocol.HttpAsyncService;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.findwise.hydra.CoreConfiguration;
import com.findwise.tools.HttpConnection;
/**
* Sets up a REST service on the specified port, or 12001 by default.
*
* @author joel.westberg
*/
public class RESTServer extends Thread {
private int port;
private static Logger logger = LoggerFactory.getLogger(RESTServer.class);
private Exception error;
private DefaultListeningIOReactor ioReactor;
private static final int BUFFER_SIZE = 8 * 1024; // Consider increasing this
// for performance?
private boolean shutdownCalled = false;
private boolean executing = false;
private final int dispatcherThreadCount;
private HttpRESTHandler> requestHandler;
private String id;
@SuppressWarnings("rawtypes")
public RESTServer(int port, int restThreadCount, HttpRESTHandler requestHandler) {
this.dispatcherThreadCount = restThreadCount;
this.requestHandler = requestHandler;
id = UUID.randomUUID().toString();
requestHandler.setRestId(id);
this.port = port;
executing = false;
setDaemon(true);
}
@SuppressWarnings("rawtypes")
public RESTServer(CoreConfiguration conf, HttpRESTHandler requestHandler) {
this(conf.getRestPort(), conf.getRestThreadCount(), requestHandler);
}
public boolean isExecuting() {
return executing;
}
public boolean hasError() {
return error!=null;
}
public Exception getError() {
return error;
}
public int getPort() {
return port;
}
/**
* Starts the server, confirming that the the startup process went correctly before returning.
*
* @return false if server could not be started (on that port), true otherwise.
*/
public boolean blockingStart() {
start();
try {
return isWorking(System.currentTimeMillis(), 2000);
}
catch (InterruptedException e) {
error = e;
Thread.currentThread().interrupt();
return false;
}
}
public boolean isWorking(long startTime, long timeout) throws InterruptedException {
if(hasError()) {
return false;
}
if(System.currentTimeMillis()-timeout > startTime) {
return false;
}
if (isExecuting()) {
HttpConnection conn = new HttpConnection("localhost", port);
try {
HttpResponse response = conn.get("/");
String result = EntityUtils.toString(response.getEntity());
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return result.equals(id);
}
}
catch (IOException e) {
logger.error("An IOException occurred during ping operation", e);
}
}
Thread.sleep(50);
return isWorking(startTime, timeout);
}
@Override
public void run() {
try {
HttpParams params = new SyncBasicHttpParams();
params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, BUFFER_SIZE)
.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
.setParameter(CoreProtocolPNames.ORIGIN_SERVER, "Hydra Core (Apache HttpComponents 4.2.1/1.1)");
HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpResponseInterceptor[] {
new ResponseDate(),
new ResponseServer(),
new ResponseContent(),
new ResponseConnControl()
});
HttpAsyncRequestHandlerRegistry registry = new HttpAsyncRequestHandlerRegistry();
registry.register("*", new BasicAsyncRequestHandler(requestHandler));
HttpAsyncService handler = new HttpAsyncService(httpproc, new DefaultConnectionReuseStrategy(), registry, params) {
@Override
public void connected(final NHttpServerConnection conn) {
logger.debug("Connection open: " + conn);
super.connected(conn);
}
@Override
public void closed(final NHttpServerConnection conn) {
logger.debug("Connection closed: " + conn);
super.closed(conn);
}
};
NHttpConnectionFactory connFactory = new DefaultNHttpServerConnectionFactory(params);
IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(handler, connFactory);
IOReactorConfig config = new IOReactorConfig();
config.setIoThreadCount(dispatcherThreadCount);
ioReactor = new DefaultListeningIOReactor(config);
ioReactor.listen(new InetSocketAddress(port));
executing = true;
ioReactor.execute(ioEventDispatch);
if(!shutdownCalled) {
logger.error("Exiting ioReactor exec loop");
}
else {
logger.debug("Exiting ioReactor exec loop");
}
executing = false;
}
catch (IOException e) {
logger.error("I/O error in RESTServer: " + e.getMessage());
error = e;
}
}
public void shutdown() throws IOException {
logger.info("Caught shutdown command to RESTServer");
shutdownCalled = true;
ioReactor.shutdown();
}
public static RESTServer getNewStartedRESTServer(int port, HttpRESTHandler> restHandler) {
RESTServer rest = new RESTServer(port, Runtime.getRuntime().availableProcessors(),
restHandler);
if(!rest.blockingStart()) {
return getNewStartedRESTServer((int)(Math.random()*64000)+1024, restHandler);
}
return rest;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy