| // Copyright 2012 Citrix Systems, Inc. Licensed under the |
| // Apache License, Version 2.0 (the "License"); you may not use this |
| // file except in compliance with the License. Citrix Systems, Inc. |
| // reserves all rights not expressly granted by the License. |
| // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // Automatically generated by addcopyright.py at 04/03/2012 |
| package com.cloud.cluster;
|
|
|
| import java.io.IOException;
|
| import java.net.ServerSocket;
|
| import java.net.Socket;
|
| import java.util.concurrent.ExecutorService;
|
| import java.util.concurrent.Executors;
|
|
|
| import org.apache.http.ConnectionClosedException;
|
| import org.apache.http.HttpException;
|
| import org.apache.http.impl.DefaultConnectionReuseStrategy;
|
| import org.apache.http.impl.DefaultHttpResponseFactory;
|
| import org.apache.http.impl.DefaultHttpServerConnection;
|
| import org.apache.http.params.BasicHttpParams;
|
| import org.apache.http.params.CoreConnectionPNames;
|
| import org.apache.http.params.CoreProtocolPNames;
|
| import org.apache.http.params.HttpParams;
|
| import org.apache.http.protocol.BasicHttpContext;
|
| import org.apache.http.protocol.BasicHttpProcessor;
|
| import org.apache.http.protocol.HttpContext;
|
| import org.apache.http.protocol.HttpRequestHandler;
|
| import org.apache.http.protocol.HttpRequestHandlerRegistry;
|
| import org.apache.http.protocol.HttpService;
|
| 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.log4j.Logger;
|
|
|
| import com.cloud.utils.concurrency.NamedThreadFactory;
|
|
|
| public class ClusterServiceServletContainer {
|
| private static final Logger s_logger = Logger.getLogger(ClusterServiceServletContainer.class);
|
|
|
| private ListenerThread listenerThread; |
|
|
| public ClusterServiceServletContainer() {
|
| }
|
|
|
| public boolean start(HttpRequestHandler requestHandler, int port) {
|
|
|
| listenerThread = new ListenerThread(requestHandler, port);
|
| listenerThread.start();
|
|
|
| return true;
|
| }
|
|
|
| public void stop() { |
| if(listenerThread != null) { |
| listenerThread.stopRunning();
|
| }
|
| }
|
|
|
| static class ListenerThread extends Thread {
|
| private HttpService _httpService = null;
|
| private volatile ServerSocket _serverSocket = null;
|
| private HttpParams _params = null;
|
| private ExecutorService _executor;
|
|
|
| public ListenerThread(HttpRequestHandler requestHandler, int port) {
|
| _executor = Executors.newCachedThreadPool(new NamedThreadFactory("Cluster-Listener"));
|
|
|
| try {
|
| _serverSocket = new ServerSocket(port);
|
| } catch (IOException ioex) {
|
| s_logger.error("error initializing cluster service servlet container", ioex);
|
| return;
|
| }
|
|
|
| _params = new BasicHttpParams();
|
| _params
|
| .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
|
| .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
|
| .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
|
| .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
|
| .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
|
|
|
| // Set up the HTTP protocol processor
|
| BasicHttpProcessor httpproc = new BasicHttpProcessor();
|
| httpproc.addInterceptor(new ResponseDate());
|
| httpproc.addInterceptor(new ResponseServer());
|
| httpproc.addInterceptor(new ResponseContent());
|
| httpproc.addInterceptor(new ResponseConnControl());
|
|
|
| // Set up request handlers
|
| HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
|
| reqistry.register("/clusterservice", requestHandler);
|
|
|
| // Set up the HTTP service
|
| _httpService = new HttpService(httpproc, new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory());
|
| _httpService.setParams(_params);
|
| _httpService.setHandlerResolver(reqistry);
|
| } |
| |
| public void stopRunning() { |
| if(_serverSocket != null) { |
| try { |
| _serverSocket.close(); |
| } catch (IOException e) { |
| } |
| _serverSocket = null; |
| } |
| }
|
|
|
| public void run() {
|
| if(s_logger.isInfoEnabled())
|
| s_logger.info("Cluster service servlet container listening on port " + _serverSocket.getLocalPort());
|
|
|
| while (_serverSocket != null) {
|
| try {
|
| // Set up HTTP connection
|
| Socket socket = _serverSocket.accept();
|
| final DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
|
| conn.bind(socket, _params);
|
|
|
| _executor.execute(new Runnable() {
|
| public void run() {
|
| HttpContext context = new BasicHttpContext(null);
|
| try { |
| while(!Thread.interrupted() && conn.isOpen()) {
|
| if(s_logger.isTraceEnabled())
|
| s_logger.trace("dispatching cluster request from " + conn.getRemoteAddress().toString());
|
|
|
| _httpService.handleRequest(conn, context);
|
|
|
| if(s_logger.isTraceEnabled())
|
| s_logger.trace("Cluster request from " + conn.getRemoteAddress().toString() + " is processed"); |
| }
|
| } catch (ConnectionClosedException ex) { |
| // client close and read time out exceptions are expected |
| // when KEEP-AVLIE is enabled
|
| s_logger.trace("Client closed connection", ex);
|
| } catch (IOException ex) {
|
| s_logger.trace("I/O error", ex);
|
| } catch (HttpException ex) {
|
| s_logger.error("Unrecoverable HTTP protocol violation", ex);
|
| } finally {
|
| try {
|
| conn.shutdown(); |
| } catch (IOException ignore) { |
| s_logger.error("unexpected exception", ignore); |
| }
|
| }
|
| } |
| });
|
|
|
| } catch (Throwable e) { |
| s_logger.error("Unexpected exception ", e); |
| |
| // back off to avoid spinning if the exception condition keeps coming back |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e1) { |
| }
|
| }
|
| }
|
|
|
| _executor.shutdown();
|
| if(s_logger.isInfoEnabled())
|
| s_logger.info("Cluster service servlet container shutdown");
|
| }
|
| }
|
| }
|