blob: ce65fe18e87affaa07f0892a4fd8440e3f66d8bb [file] [log] [blame]
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.cluster;
import java.io.IOException;
import java.rmi.RemoteException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.log4j.Logger;
import com.cloud.serializer.GsonHelper;
import com.google.gson.Gson;
public class ClusterServiceServletImpl implements ClusterService {
private static final long serialVersionUID = 4574025200012566153L;
private static final Logger s_logger = Logger.getLogger(ClusterServiceServletImpl.class);
private String _serviceUrl;
private final Gson _gson;
private int _requestTimeoutSeconds;
public ClusterServiceServletImpl() {
_gson = GsonHelper.getGson();
}
public ClusterServiceServletImpl(String serviceUrl, int requestTimeoutSeconds) {
s_logger.info("Setup cluster service servlet. service url: " + serviceUrl + ", request timeout: " + requestTimeoutSeconds + " seconds");
this._serviceUrl = serviceUrl;
this._requestTimeoutSeconds = requestTimeoutSeconds;
_gson = GsonHelper.getGson();
}
@Override
public String execute(String callingPeer, long agentId, String gsonPackage, boolean stopOnError) throws RemoteException {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Post (sync-call) " + gsonPackage + " to " + _serviceUrl + " for agent " + agentId + " from " + callingPeer);
}
HttpClient client = getHttpClient();
PostMethod method = new PostMethod(_serviceUrl);
method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_EXECUTE));
method.addParameter("agentId", Long.toString(agentId));
method.addParameter("gsonPackage", gsonPackage);
method.addParameter("stopOnError", stopOnError ? "1" : "0");
return executePostMethod(client, method);
}
@Override
public long executeAsync(String callingPeer, long agentId, String gsonPackage, boolean stopOnError) throws RemoteException {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Post (Async-call) " + gsonPackage + " to " + _serviceUrl + " for agent " + agentId + " from " + callingPeer);
}
HttpClient client = getHttpClient();
PostMethod method = new PostMethod(_serviceUrl);
method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_EXECUTE_ASYNC));
method.addParameter("agentId", Long.toString(agentId));
method.addParameter("gsonPackage", gsonPackage);
method.addParameter("stopOnError", stopOnError ? "1" : "0");
method.addParameter("caller", callingPeer);
String result = executePostMethod(client, method);
if(result == null) {
s_logger.error("Empty return from remote async-execution on " + _serviceUrl);
throw new RemoteException("Invalid result returned from async-execution on peer : " + _serviceUrl);
}
try {
return _gson.fromJson(result, Long.class);
} catch(Throwable e) {
s_logger.error("Unable to parse executeAsync return : " + result);
throw new RemoteException("Invalid result returned from async-execution on peer : " + _serviceUrl);
}
}
@Override
public boolean onAsyncResult(String executingPeer, long agentId, long seq, String gsonPackage) throws RemoteException {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Forward Async-call answer to remote listener, agent: " + agentId
+ ", excutingPeer: " + executingPeer
+ ", seq: " + seq + ", gsonPackage: " + gsonPackage);
}
HttpClient client = getHttpClient();
PostMethod method = new PostMethod(_serviceUrl);
method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_ASYNC_RESULT));
method.addParameter("agentId", Long.toString(agentId));
method.addParameter("gsonPackage", gsonPackage);
method.addParameter("seq", Long.toString(seq));
method.addParameter("executingPeer", executingPeer);
String result = executePostMethod(client, method);
if(result.contains("recurring=true")) {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Remote listener returned recurring=true");
}
return true;
}
if(s_logger.isDebugEnabled()) {
s_logger.debug("Remote listener returned recurring=false");
}
return false;
}
@Override
public boolean ping(String callingPeer) throws RemoteException {
if(s_logger.isDebugEnabled()) {
s_logger.debug("Ping at " + _serviceUrl);
}
HttpClient client = getHttpClient();
PostMethod method = new PostMethod(_serviceUrl);
method.addParameter("method", Integer.toString(RemoteMethodConstants.METHOD_PING));
method.addParameter("callingPeer", callingPeer);
String returnVal = executePostMethod(client, method);
if("true".equalsIgnoreCase(returnVal)) {
return true;
}
return false;
}
private String executePostMethod(HttpClient client, PostMethod method) {
int response = 0;
String result = null;
try {
long startTick = System.currentTimeMillis();
response = client.executeMethod(method);
if(response == HttpStatus.SC_OK) {
result = method.getResponseBodyAsString();
if(s_logger.isDebugEnabled()) {
s_logger.debug("POST " + _serviceUrl + " response :" + result + ", responding time: "
+ (System.currentTimeMillis() - startTick) + " ms");
}
} else {
s_logger.error("Invalid response code : " + response + ", from : "
+ _serviceUrl + ", method : " + method.getParameter("method")
+ " responding time: " + (System.currentTimeMillis() - startTick));
}
} catch (HttpException e) {
s_logger.error("HttpException from : " + _serviceUrl + ", method : " + method.getParameter("method"));
} catch (IOException e) {
s_logger.error("IOException from : " + _serviceUrl + ", method : " + method.getParameter("method"));
} catch(Throwable e) {
s_logger.error("Exception from : " + _serviceUrl + ", method : " + method.getParameter("method") + ", exception :", e);
}
return result;
}
private HttpClient getHttpClient() {
HttpClient client = new HttpClient();
HttpClientParams clientParams = new HttpClientParams();
clientParams.setSoTimeout(this._requestTimeoutSeconds * 1000);
client.setParams(clientParams);
return client;
}
// for test purpose only
public static void main(String[] args) {
ClusterServiceServletImpl service = new ClusterServiceServletImpl("http://localhost:9090/clusterservice", 300);
try {
String result = service.execute("test", 1, "{ p1:v1, p2:v2 }", true);
System.out.println(result);
} catch (RemoteException e) {
}
}
}