code.google.nfs.rpc.client.AbstractClient.java Source code

Java tutorial

Introduction

Here is the source code for code.google.nfs.rpc.client.AbstractClient.java

Source

package code.google.nfs.rpc.client;

/**
 * nfs-rpc
 *   Apache License
 *   
 *   http://code.google.com/p/nfs-rpc (c) 2011
 */
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import code.google.nfs.rpc.Codecs;
import code.google.nfs.rpc.RequestWrapper;
import code.google.nfs.rpc.ResponseWrapper;

/**
 * Common Client,support sync invoke
 * 
 * @author <a href="mailto:bluedavy@gmail.com">bluedavy</a>
 */
public abstract class AbstractClient implements Client {

    private static final Log LOGGER = LogFactory.getLog(AbstractClient.class);

    private static final boolean isDebugEnabled = LOGGER.isDebugEnabled();

    private static final boolean isWarnEnabled = LOGGER.isWarnEnabled();

    private static final long PRINT_CONSUME_MINTIME = Long
            .parseLong(System.getProperty("nfs.rpc.print.consumetime", "0"));

    protected static ConcurrentHashMap<Integer, ArrayBlockingQueue<Object>> responses = new ConcurrentHashMap<Integer, ArrayBlockingQueue<Object>>();

    public Object invokeSync(Object message, int timeout, int codecType, int protocolType) throws Exception {
        RequestWrapper wrapper = new RequestWrapper(message, timeout, codecType, protocolType);
        return invokeSyncIntern(wrapper);
    }

    public Object invokeSync(String targetInstanceName, String methodName, String[] argTypes, Object[] args,
            int timeout, int codecType, int protocolType) throws Exception {
        byte[][] argTypeBytes = new byte[argTypes.length][];
        for (int i = 0; i < argTypes.length; i++) {
            argTypeBytes[i] = argTypes[i].getBytes();
        }
        RequestWrapper wrapper = new RequestWrapper(targetInstanceName.getBytes(), methodName.getBytes(),
                argTypeBytes, args, timeout, codecType, protocolType);
        return invokeSyncIntern(wrapper);
    }

    private Object invokeSyncIntern(RequestWrapper wrapper) throws Exception {
        long beginTime = System.currentTimeMillis();
        ArrayBlockingQueue<Object> responseQueue = new ArrayBlockingQueue<Object>(1);
        responses.put(wrapper.getId(), responseQueue);
        ResponseWrapper responseWrapper = null;
        try {
            if (isDebugEnabled) {
                // for performance trace
                LOGGER.debug("client ready to send message,request id: " + wrapper.getId());
            }
            getClientFactory().checkSendLimit();
            sendRequest(wrapper, wrapper.getTimeout());
            if (isDebugEnabled) {
                // for performance trace
                LOGGER.debug(
                        "client write message to send buffer,wait for response,request id: " + wrapper.getId());
            }
        } catch (Exception e) {
            responses.remove(wrapper.getId());
            responseQueue = null;
            LOGGER.error("send request to os sendbuffer error", e);
            throw e;
        }
        Object result = null;
        try {
            result = responseQueue.poll(wrapper.getTimeout() - (System.currentTimeMillis() - beginTime),
                    TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            responses.remove(wrapper.getId());
            LOGGER.error("Get response error", e);
            throw new Exception("Get response error", e);
        }
        responses.remove(wrapper.getId());

        if (PRINT_CONSUME_MINTIME > 0 && isWarnEnabled) {
            long consumeTime = System.currentTimeMillis() - beginTime;
            if (consumeTime > PRINT_CONSUME_MINTIME) {
                LOGGER.warn("client.invokeSync consume time: " + consumeTime + " ms, server is: " + getServerIP()
                        + ":" + getServerPort() + " request id is:" + wrapper.getId());
            }
        }
        if (result == null) {
            String errorMsg = "receive response timeout(" + wrapper.getTimeout() + " ms),server is: "
                    + getServerIP() + ":" + getServerPort() + " request id is:" + wrapper.getId();
            throw new Exception(errorMsg);
        }

        if (result instanceof ResponseWrapper) {
            responseWrapper = (ResponseWrapper) result;
        } else if (result instanceof List) {
            @SuppressWarnings("unchecked")
            List<ResponseWrapper> responseWrappers = (List<ResponseWrapper>) result;
            for (ResponseWrapper response : responseWrappers) {
                if (response.getRequestId() == wrapper.getId()) {
                    responseWrapper = response;
                } else {
                    putResponse(response);
                }
            }
        } else {
            throw new Exception("only receive ResponseWrapper or List as response");
        }
        try {
            // do deserialize in business threadpool
            if (responseWrapper.getResponse() instanceof byte[]) {
                String responseClassName = null;
                if (responseWrapper.getResponseClassName() != null) {
                    responseClassName = new String(responseWrapper.getResponseClassName());
                }
                // avoid server no return object
                if (((byte[]) responseWrapper.getResponse()).length == 0) {
                    responseWrapper.setResponse(null);
                } else {
                    Object responseObject = Codecs.getDecoder(responseWrapper.getCodecType())
                            .decode(responseClassName, (byte[]) responseWrapper.getResponse());
                    if (responseObject instanceof Throwable) {
                        responseWrapper.setException((Throwable) responseObject);
                    } else {
                        responseWrapper.setResponse(responseObject);
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("Deserialize response object error", e);
            throw new Exception("Deserialize response object error", e);
        }
        if (responseWrapper.isError()) {
            Throwable t = responseWrapper.getException();
            t.fillInStackTrace();
            String errorMsg = "server error,server is: " + getServerIP() + ":" + getServerPort() + " request id is:"
                    + wrapper.getId();
            LOGGER.error(errorMsg, t);
            throw new Exception(errorMsg, t);
        }
        return responseWrapper.getResponse();
    }

    /**
     * receive response
     */
    public void putResponse(ResponseWrapper wrapper) throws Exception {
        if (!responses.containsKey(wrapper.getRequestId())) {
            LOGGER.warn("give up the response,request id is:" + wrapper.getRequestId() + ",maybe because timeout!");
            return;
        }
        try {
            ArrayBlockingQueue<Object> queue = responses.get(wrapper.getRequestId());
            if (queue != null) {
                queue.put(wrapper);
            } else {
                LOGGER.warn(
                        "give up the response,request id is:" + wrapper.getRequestId() + ",because queue is null");
            }
        } catch (InterruptedException e) {
            LOGGER.error("put response error,request id is:" + wrapper.getRequestId(), e);
        }
    }

    /**
     * receive responses
     */
    public void putResponses(List<ResponseWrapper> wrappers) throws Exception {
        for (ResponseWrapper wrapper : wrappers) {
            if (!responses.containsKey(wrapper.getRequestId())) {
                LOGGER.warn(
                        "give up the response,request id is:" + wrapper.getRequestId() + ",maybe because timeout!");
                continue;
            }
            try {
                ArrayBlockingQueue<Object> queue = responses.get(wrapper.getRequestId());
                if (queue != null) {
                    queue.put(wrappers);
                    break;
                } else {
                    LOGGER.warn("give up the response,request id is:" + wrapper.getRequestId()
                            + ",because queue is null");
                }
            } catch (InterruptedException e) {
                LOGGER.error("put response error,request id is:" + wrapper.getRequestId(), e);
            }
        }
    }

    /**
     * send request to os sendbuffer,must ensure write result
     */
    public abstract void sendRequest(RequestWrapper wrapper, int timeout) throws Exception;

}