/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with 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.
 */
package org.apache.hama.ipc;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.ReferenceCountUtil;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.net.SocketFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.DataOutputBuffer;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hama.util.BSPNetUtils;

/**
 * A client for an IPC service using netty. IPC calls take a single
 * {@link Writable} as a parameter, and return a {@link Writable} as their
 * value. A service runs on a port and is defined by a parameter class and a
 * value class.
 * 
 * @see AsyncClient
 */
public class AsyncClient {
  private static final String IPC_CLIENT_CONNECT_MAX_RETRIES_KEY = "ipc.client.connect.max.retries";
  private static final int IPC_CLIENT_CONNECT_MAX_RETRIES_DEFAULT = 10;
  private static final Log LOG = LogFactory.getLog(AsyncClient.class);
  private Hashtable<ConnectionId, Connection> connections = new Hashtable<ConnectionId, Connection>();

  private Class<? extends Writable> valueClass; // class of call values
  private int counter = 0; // counter for call ids
  private AtomicBoolean running = new AtomicBoolean(true); // if client runs
  final private Configuration conf; // configuration obj

  private SocketFactory socketFactory; // only use in order to meet the
                                       // consistency with other clients
  private int refCount = 1;

  final private static String PING_INTERVAL_NAME = "ipc.ping.interval";
  final static int DEFAULT_PING_INTERVAL = 60000; // 1 min

  /**
   * set the ping interval value in configuration
   * 
   * @param conf Configuration
   * @param pingInterval the ping interval
   */
  final public static void setPingInterval(Configuration conf, int pingInterval) {
    conf.setInt(PING_INTERVAL_NAME, pingInterval);
  }

  /**
   * Get the ping interval from configuration; If not set in the configuration,
   * return the default value.
   * 
   * @param conf Configuration
   * @return the ping interval
   */
  final static int getPingInterval(Configuration conf) {
    return conf.getInt(PING_INTERVAL_NAME, DEFAULT_PING_INTERVAL);
  }

  /**
   * The time after which a RPC will timeout. If ping is not enabled (via
   * ipc.client.ping), then the timeout value is the same as the pingInterval.
   * If ping is enabled, then there is no timeout value.
   * 
   * @param conf Configuration
   * @return the timeout period in milliseconds. -1 if no timeout value is set
   */
  final public static int getTimeout(Configuration conf) {
    if (!conf.getBoolean("ipc.client.ping", true)) {
      return getPingInterval(conf);
    }
    return -1;
  }

  /**
   * Increment this client's reference count
   * 
   */
  synchronized void incCount() {
    refCount++;
  }

  /**
   * Decrement this client's reference count
   * 
   */
  synchronized void decCount() {
    refCount--;
  }

  /**
   * Return if this client has no reference
   * 
   * @return true if this client has no reference; false otherwise
   */
  synchronized boolean isZeroReference() {
    return refCount == 0;
  }

  /**
   * Thread that reads responses and notifies callers. Each connection owns a
   * socket connected to a remote address. Calls are multiplexed through this
   * socket: responses may be delivered out of order.
   */
  private class Connection {
    private InetSocketAddress serverAddress; // server ip:port
    private ConnectionHeader header; // connection header
    private final ConnectionId remoteId; // connection id
    private AuthMethod authMethod; // authentication method

    private EventLoopGroup group;
    private Bootstrap bootstrap;
    private Channel channel;
    private int rpcTimeout;
    private int maxIdleTime; // connections will be culled if it was idle

    private final RetryPolicy connectionRetryPolicy;
    private boolean tcpNoDelay; // if T then disable Nagle's Algorithm
    private int pingInterval; // how often sends ping to the server in msecs

    // currently active calls
    private Hashtable<Integer, Call> calls = new Hashtable<Integer, Call>();
    private AtomicBoolean shouldCloseConnection = new AtomicBoolean(); // indicate
    private IOException closeException; // if the connection is closed, close
                                        // reason

    /**
     * Setup Connection Configuration
     * 
     * @param remoteId remote connection Id
     * @throws IOException
     */
    public Connection(ConnectionId remoteId) throws IOException {
      group = new NioEventLoopGroup();
      bootstrap = new Bootstrap();
      this.remoteId = remoteId;
      this.serverAddress = remoteId.getAddress();
      if (serverAddress.isUnresolved()) {
        throw new UnknownHostException("unknown host: "
            + remoteId.getAddress().getHostName());
      }
      this.maxIdleTime = remoteId.getMaxIdleTime();
      this.connectionRetryPolicy = remoteId.connectionRetryPolicy;
      this.tcpNoDelay = remoteId.getTcpNoDelay();
      this.pingInterval = remoteId.getPingInterval();
      if (LOG.isDebugEnabled()) {
        LOG.debug("The ping interval is" + this.pingInterval + "ms.");
      }
      this.rpcTimeout = remoteId.getRpcTimeout();
      Class<?> protocol = remoteId.getProtocol();

      authMethod = AuthMethod.SIMPLE;
      header = new ConnectionHeader(protocol == null ? null
          : protocol.getName(), null, authMethod);
    }

    /**
     * Add a call to this connection's call queue and notify a listener;
     * synchronized. Returns false if called during shutdown.
     * 
     * @param call to add
     * @return true if the call was added.
     */
    private synchronized boolean addCall(Call call) {
      if (shouldCloseConnection.get())
        return false;
      calls.put(call.id, call);
      notify();
      return true;
    }

    /**
     * Update the server address if the address corresponding to the host name
     * has changed.
     */
    private synchronized boolean updateAddress() throws IOException {
      // Do a fresh lookup with the old host name.
      InetSocketAddress currentAddr = BSPNetUtils.makeSocketAddr(
          serverAddress.getHostName(), serverAddress.getPort());

      if (!serverAddress.equals(currentAddr)) {
        LOG.warn("Address change detected. Old: " + serverAddress.toString()
            + " New: " + currentAddr.toString());
        serverAddress = currentAddr;
        return true;
      }
      return false;
    }

    /**
     * Connect to the server and set up the I/O streams. It then sends a header
     * to the server.
     */
    private void setupIOstreams() throws InterruptedException {
      if (channel != null && channel.isActive()) {
        return;
      }
      try {
        if (LOG.isDebugEnabled()) {
          LOG.debug("Connecting to " + serverAddress);
        }

        setupConnection();
        writeHeader();
      } catch (Throwable t) {
        if (t instanceof IOException) {
          markClosed((IOException) t);
        } else {
          markClosed(new IOException("Couldn't set up IO streams", t));
        }
        close();
      }
    }

    /**
     * Configure the client and connect to server
     */
    private void setupConnection() throws Exception {
      while (true) {
        short ioFailures = 0;
        try {
          // rpcTimeout overwrites pingInterval
          if (rpcTimeout > 0) {
            pingInterval = rpcTimeout;
          }

          // Configure the client.
          // NioEventLoopGroup is a multithreaded event loop that handles I/O
          // operation
          group = new NioEventLoopGroup();
          // Bootstrap is a helper class that sets up a client
          bootstrap = new Bootstrap();
          bootstrap.group(group).channel(NioSocketChannel.class)
              .option(ChannelOption.TCP_NODELAY, this.tcpNoDelay)
              .option(ChannelOption.SO_KEEPALIVE, true)
              .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, pingInterval)
              .option(ChannelOption.SO_SNDBUF, 30 * 1024 * 1024)
              .handler(new LoggingHandler(LogLevel.INFO))
              .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                  ChannelPipeline p = ch.pipeline();
                  p.addLast(new IdleStateHandler(0, 0, maxIdleTime));
                  // Register message processing handler
                  p.addLast(new NioClientInboundHandler());
                }
              });

          // Bind and start to accept incoming connections.
          ChannelFuture channelFuture = bootstrap.connect(
              serverAddress.getAddress(), serverAddress.getPort()).sync();
          // Get io channel
          channel = channelFuture.channel();
          LOG.info("AsyncClient startup");
          break;
        } catch (Exception ie) {
          /*
           * Check for an address change and update the local reference. Reset
           * the failure counter if the address was changed
           */

          if (updateAddress()) {
            ioFailures = 0;
          }
          handleConnectionFailure(ioFailures++, ie);
        }
      }
    }

    /**
     * Write the header protocol header for each connection Out is not
     * synchronized because only the first thread does this.
     * 
     * @param channel
     */
    private void writeHeader() {
      DataOutputBuffer rpcBuff = null;
      DataOutputBuffer headerBuf = null;
      try {
        ByteBuf buf = channel.alloc().buffer();
        rpcBuff = new DataOutputBuffer();
        authMethod.write(rpcBuff);

        headerBuf = new DataOutputBuffer();
        header.write(headerBuf);
        byte[] data = headerBuf.getData();
        int dataLength = headerBuf.getLength();
        // write rpcheader
        buf.writeInt(AsyncServer.HEADER_LENGTH + dataLength);
        buf.writeBytes(AsyncServer.HEADER.array());
        buf.writeByte(AsyncServer.CURRENT_VERSION);
        buf.writeByte(rpcBuff.getData()[0]);
        // write header
        buf.writeInt(dataLength);
        buf.writeBytes(data, 0, dataLength);

        channel.writeAndFlush(buf);
      } catch (Exception e) {
        LOG.error("Couldn't send header" + e);
      } finally {
        IOUtils.closeStream(rpcBuff);
        IOUtils.closeStream(headerBuf);
      }
    }

    /**
     * close the current connection gracefully.
     */
    private void closeConnection() {
      try {
        if (!this.group.isTerminated()) {
          this.group.shutdownGracefully();
          LOG.info("client gracefully shutdown");
        }
      } catch (Exception e) {
        LOG.warn("Not able to close a client", e);
      }
    }

    /**
     * This class process received response message from server.
     */
    private class NioClientInboundHandler extends ChannelInboundHandlerAdapter {

      /**
       * Receive a response. This method is called with the received response
       * message, whenever new data is received from a server.
       * 
       * @param ctx
       * @param cause
       */
      @Override
      public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf byteBuf = (ByteBuf) msg;
        ByteBufInputStream byteBufInputStream = new ByteBufInputStream(byteBuf);
        DataInputStream in = new DataInputStream(byteBufInputStream);
        while (true) {
          try {
            if (in.available() <= 0)
              break;
            // try to read an id
            int id = in.readInt();

            if (LOG.isDebugEnabled())
              LOG.debug(serverAddress.getHostName() + " got value #" + id);

            Call call = calls.get(id);

            // read call status
            int state = in.readInt();
            if (state == Status.SUCCESS.state) {
              Writable value = ReflectionUtils.newInstance(valueClass, conf);
              value.readFields(in); // read value
              call.setValue(value);
              calls.remove(id);
            } else if (state == Status.ERROR.state) {
              String className = WritableUtils.readString(in);
              byte[] errorBytes = new byte[in.available()];
              in.readFully(errorBytes);
              call.setException(new RemoteException(className, new String(
                  errorBytes)));
              calls.remove(id);
            } else if (state == Status.FATAL.state) {
              // Close the connection
              markClosed(new RemoteException(WritableUtils.readString(in),
                  WritableUtils.readString(in)));
            } else {
              byte[] garbageBytes = new byte[in.available()];
              in.readFully(garbageBytes);
            }
          } catch (IOException e) {
            markClosed(e);
          }
        }
        IOUtils.closeStream(in);
        IOUtils.closeStream(byteBufInputStream);
        ReferenceCountUtil.release(msg);
      }

      /**
       * Ths event handler method is called with a Throwable due to an I/O
       * error. Then, exception is logged and its associated channel is closed
       * here
       * 
       * @param ctx
       * @param cause
       */
      @Override
      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LOG.error("Occured I/O Error : " + cause.getMessage());
        ctx.close();
      }

      /**
       * this method is triggered after a long reading/writing/idle time, it is
       * marked as to be closed, or the client is marked as not running.
       * 
       * @param ctx
       * @param evt
       */
      @Override
      public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
          IdleStateEvent e = (IdleStateEvent) evt;
          if (e.state() != IdleState.ALL_IDLE) {
            if (!calls.isEmpty() && !shouldCloseConnection.get()
                && running.get()) {
              return;
            } else if (shouldCloseConnection.get()) {
              markClosed(null);
            } else if (calls.isEmpty()) { // idle connection closed or stopped
              markClosed(null);
            } else { // get stopped but there are still pending requests
              markClosed((IOException) new IOException()
                  .initCause(new InterruptedException()));
            }
            closeConnection();
          }
        }

      }
    }

    /**
     * Handle connection failures If the current number of retries is equal to
     * the max number of retries, stop retrying and throw the exception;
     * Otherwise backoff 1 second and try connecting again. This Method is only
     * called from inside setupIOstreams(), which is synchronized. Hence the
     * sleep is synchronized; the locks will be retained.
     * 
     * @param curRetries current number of retries
     * @param maxRetries max number of retries allowed
     * @param ioe failure reason
     * @throws IOException if max number of retries is reached
     */
    @SuppressWarnings("unused")
    private void handleConnectionFailure(int curRetries, int maxRetries,
        IOException ioe) throws IOException {

      closeConnection();

      // throw the exception if the maximum number of retries is reached
      if (curRetries >= maxRetries) {
        throw ioe;
      }

      // otherwise back off and retry
      try {
        Thread.sleep(1000);
      } catch (InterruptedException ignored) {
      }

      LOG.info("Retrying connect to server: " + serverAddress
          + ". Already tried " + curRetries + " time(s); maxRetries="
          + maxRetries);
    }

    /*
     * Handle connection failures If the current number of retries, stop
     * retrying and throw the exception; Otherwise backoff 1 second and try
     * connecting again. This Method is only called from inside
     * setupIOstreams(), which is synchronized. Hence the sleep is synchronized;
     * the locks will be retained.
     * @param curRetries current number of retries
     * @param ioe failure reason
     * @throws Exception if max number of retries is reached
     */
    private void handleConnectionFailure(int curRetries, Exception ioe)
        throws Exception {
      closeConnection();

      final boolean retry;
      try {
        retry = connectionRetryPolicy.shouldRetry(ioe, curRetries);
      } catch (Exception e) {
        throw e instanceof IOException ? (IOException) e : new IOException(e);
      }
      if (!retry) {
        throw ioe;
      }

      LOG.info("Retrying connect to server: " + serverAddress
          + ". Already tried " + curRetries + " time(s); retry policy is "
          + connectionRetryPolicy);
    }

    /**
     * Return the remote address of server
     * 
     * @return remote server address
     */
    public InetSocketAddress getRemoteAddress() {
      return serverAddress;
    }

    /**
     * Initiates a call by sending the parameter to the remote server.
     * 
     * @param sendCall
     */
    public void sendParam(Call sendCall) {
      if (LOG.isDebugEnabled())
        LOG.debug(this.getClass().getName() + " sending #" + sendCall.id);
      DataOutputBuffer buff = null;
      try {
        buff = new DataOutputBuffer();
        buff.writeInt(sendCall.id);
        sendCall.param.write(buff);
        byte[] data = buff.getData();
        int dataLength = buff.getLength();
        ByteBuf buf = channel.alloc().buffer();

        buf.writeInt(dataLength);
        buf.writeBytes(data, 0, dataLength);
        ChannelFuture channelFuture = channel.writeAndFlush(buf);
        if (channelFuture.cause() != null) {
          throw channelFuture.cause();
        }
      } catch (IOException ioe) {
        markClosed(ioe);
      } catch (Throwable t) {
        markClosed(new IOException(t));
      } finally {
        // the buffer is just an in-memory buffer, but it is still
        // polite to close early
        IOUtils.closeStream(buff);
      }
    }

    /**
     * Mark the connection to be closed
     * 
     * @param ioe
     **/
    private synchronized void markClosed(IOException ioe) {
      if (shouldCloseConnection.compareAndSet(false, true)) {
        closeException = ioe;
        notifyAll();
      }
    }

    /** Close the connection. */
    private synchronized void close() {
      if (!shouldCloseConnection.get()) {
        LOG.error("The connection is not in the closed state");
        return;
      }

      // release the resources
      // first thing to do;take the connection out of the connection list
      synchronized (connections) {
        if (connections.get(remoteId) == this) {
          Connection connection = connections.remove(remoteId);
          connection.closeConnection();
        }
      }

      // clean up all calls
      if (closeException == null) {
        if (!calls.isEmpty()) {
          LOG.warn("A connection is closed for no cause and calls are not empty");

          // clean up calls anyway
          closeException = new IOException("Unexpected closed connection");
          cleanupCalls();
        }
      } else {
        // log the info
        if (LOG.isDebugEnabled()) {
          LOG.debug("closing ipc connection to " + serverAddress + ": "
              + closeException.getMessage(), closeException);
        }

        // cleanup calls
        cleanupCalls();
      }
      if (LOG.isDebugEnabled())
        LOG.debug(serverAddress.getHostName() + ": closed");
    }

    /** Cleanup all calls and mark them as done */
    private void cleanupCalls() {
      Iterator<Entry<Integer, Call>> itor = calls.entrySet().iterator();
      while (itor.hasNext()) {
        Call c = itor.next().getValue();
        c.setException(closeException); // local exception
        itor.remove();
      }
    }
  }

  /** A call waiting for a value. */
  private class Call {
    int id; // call id
    Writable param; // parameter
    Writable value; // value, null if error
    IOException error; // exception, null if value
    boolean done; // true when call is done

    protected Call(Writable param) {
      this.param = param;
      synchronized (AsyncClient.this) {
        this.id = counter++;
      }
    }

    /**
     * Indicate when the call is complete and the value or error are available.
     * Notifies by default.
     */
    protected synchronized void callComplete() {
      this.done = true;
      notify(); // notify caller
    }

    /**
     * Set the exception when there is an error. Notify the caller the call is
     * done.
     * 
     * @param error exception thrown by the call; either local or remote
     */
    public synchronized void setException(IOException error) {
      this.error = error;
      this.callComplete();
    }

    /**
     * Set the return value when there is no error. Notify the caller the call
     * is done.
     * 
     * @param value return value of the call.
     */
    public synchronized void setValue(Writable value) {
      this.value = value;
      callComplete();
    }
  }

  /** Call implementation used for parallel calls. */
  private class ParallelCall extends Call {
    private ParallelResults results;
    private int index;

    public ParallelCall(Writable param, ParallelResults results, int index) {
      super(param);
      this.results = results;
      this.index = index;
    }

    @Override
    /** Deliver result to result collector. */
    protected void callComplete() {
      results.callComplete(this);
    }
  }

  /** Result collector for parallel calls. */
  private static class ParallelResults {
    private Writable[] values;
    private int size;
    private int count;

    public ParallelResults(int size) {
      this.values = new Writable[size];
      this.size = size;
    }

    /**
     * Collect a result.
     * 
     * @param call
     */
    public synchronized void callComplete(ParallelCall call) {
      values[call.index] = call.value; // store the value
      count++; // count it
      if (count == size) // if all values are in
        notify(); // then notify waiting caller
    }
  }

  /**
   * Construct an IPC client whose values are of the given {@link Writable}
   * class.
   * 
   * @param valueClass
   * @param conf
   * @param factory
   */
  public AsyncClient(Class<? extends Writable> valueClass, Configuration conf,
      SocketFactory factory) {
    this.valueClass = valueClass;
    this.conf = conf;
    // SocketFactory only use in order to meet the consistency with other
    // clients
    this.socketFactory = factory;
  }

  /**
   * Construct an IPC client with the default SocketFactory
   * 
   * @param valueClass
   * @param conf
   */
  public AsyncClient(Class<? extends Writable> valueClass, Configuration conf) {
    // SocketFactory only use in order to meet the consistency with other
    // clients
    this(valueClass, conf, BSPNetUtils.getDefaultSocketFactory(conf));
  }

  /**
   * Return the socket factory of this client
   * 
   * @return this client's socket factory
   */
  SocketFactory getSocketFactory() {
    // SocketFactory only use in order to meet the consistency with other
    // clients
    return socketFactory;
  }

  /**
   * Stop all threads related to this client. No further calls may be made using
   * this client.
   */
  public void stop() {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Stopping client");
    }

    if (!running.compareAndSet(true, false)) {
      return;
    }

    // wake up all connections
    synchronized (connections) {
      for (Connection conn : connections.values()) {
        conn.closeConnection();
      }
    }
  }

  /**
   * Make a call, passing <code>param</code>, to the IPC server running at
   * <code>address</code> which is servicing the <code>protocol</code> protocol,
   * with the <code>ticket</code> credentials, <code>rpcTimeout</code> as
   * timeout and <code>conf</code> as configuration for this connection,
   * returning the value. Throws exceptions if there are network problems or if
   * the remote code threw an exception.
   * 
   * @param param
   * @param addr
   * @param protocol
   * @param ticket
   * @param rpcTimeout
   * @param conf
   * @return Response Writable value
   * @throws InterruptedException
   * @throws IOException
   */
  public Writable call(Writable param, InetSocketAddress addr,
      Class<?> protocol, UserGroupInformation ticket, int rpcTimeout,
      Configuration conf) throws InterruptedException, IOException {
    ConnectionId remoteId = ConnectionId.getConnectionId(addr, protocol,
        ticket, rpcTimeout, conf);
    return call(param, remoteId);
  }

  /**
   * Make a call, passing <code>param</code>, to the IPC server defined by
   * <code>remoteId</code>, returning the value. Throws exceptions if there are
   * network problems or if the remote code threw an exception.
   * 
   * @param param
   * @param remoteId
   * @return Response Writable value
   * @throws InterruptedException
   * @throws IOException
   */
  public Writable call(Writable param, ConnectionId remoteId)
      throws InterruptedException, IOException {
    Call call = new Call(param);

    Connection connection = getConnection(remoteId, call);

    connection.sendParam(call); // send the parameter
    boolean interrupted = false;

    synchronized (call) {
      int callFailCount = 0;
      while (!call.done) {
        try {
          call.wait(1000); // wait for the result
          // prevent client hang from response error
          if (callFailCount++ == IPC_CLIENT_CONNECT_MAX_RETRIES_DEFAULT)
            break;
        } catch (InterruptedException ie) {
          interrupted = true;
        }
      }

      if (interrupted) {
        // set the interrupt flag now that we are done waiting
        Thread.currentThread().interrupt();

      }

      if (call.error != null) {
        if (call.error instanceof RemoteException) {
          call.error.fillInStackTrace();
          throw call.error;
        } else { // local exception
          // use the connection because it will reflect an ip change,
          // unlike
          // the remoteId
          throw wrapException(connection.getRemoteAddress(), call.error);
        }
      } else {
        return call.value;
      }
    }
  }

  /**
   * Take an IOException and the address we were trying to connect to and return
   * an IOException with the input exception as the cause. The new exception
   * provides the stack trace of the place where the exception is thrown and
   * some extra diagnostics information. If the exception is ConnectException or
   * SocketTimeoutException, return a new one of the same type; Otherwise return
   * an IOException.
   * 
   * @param addr target address
   * @param exception the relevant exception
   * @return an exception to throw
   */
  private IOException wrapException(InetSocketAddress addr,
      IOException exception) {
    if (exception instanceof ConnectException) {
      // connection refused; include the host:port in the error
      return (ConnectException) new ConnectException("Call to " + addr
          + " failed on connection exception: " + exception)
          .initCause(exception);
    } else if (exception instanceof SocketTimeoutException) {
      return (SocketTimeoutException) new SocketTimeoutException("Call to "
          + addr + " failed on socket timeout exception: " + exception)
          .initCause(exception);
    } else {
      return (IOException) new IOException("Call to " + addr
          + " failed on local exception: " + exception).initCause(exception);

    }
  }

  /**
   * Makes a set of calls in parallel. Each parameter is sent to the
   * corresponding address. When all values are available, or have timed out or
   * errored, the collected results are returned in an array. The array contains
   * nulls for calls that timed out or errored.
   * 
   * @param params
   * @param addresses
   * @param protocol
   * @param ticket
   * @param conf
   * @return Response Writable value array
   * @throws IOException
   * @throws InterruptedException
   */
  public Writable[] call(Writable[] params, InetSocketAddress[] addresses,
      Class<?> protocol, UserGroupInformation ticket, Configuration conf)
      throws IOException, InterruptedException {
    if (addresses.length == 0)
      return new Writable[0];

    ParallelResults results = new ParallelResults(params.length);
    ConnectionId remoteId[] = new ConnectionId[addresses.length];
    synchronized (results) {
      for (int i = 0; i < params.length; i++) {
        ParallelCall call = new ParallelCall(params[i], results, i);
        try {
          remoteId[i] = ConnectionId.getConnectionId(addresses[i], protocol,
              ticket, 0, conf);
          Connection connection = getConnection(remoteId[i], call);
          connection.sendParam(call); // send each parameter
        } catch (IOException e) {
          // log errors
          LOG.info("Calling " + addresses[i] + " caught: " + e.getMessage(), e);
          results.size--; // wait for one fewer result
        }
      }

      while (results.count != results.size) {
        try {
          results.wait(); // wait for all results
        } catch (InterruptedException e) {
        }
      }

      return results.values;
    }
  }

  // for unit testing only
  Set<ConnectionId> getConnectionIds() {
    synchronized (connections) {
      return connections.keySet();
    }
  }

  /**
   * Get a connection from the pool, or create a new one and add it to the pool.
   * Connections to a given ConnectionId are reused.
   * 
   * @param remoteId
   * @param call
   * @return connection
   * @throws IOException
   * @throws InterruptedException
   */
  private synchronized Connection getConnection(ConnectionId remoteId, Call call)
      throws IOException, InterruptedException {
    if (!running.get()) {
      // the client is stopped
      throw new IOException("The client is stopped");
    }
    Connection connection;
    /*
     * we could avoid this allocation for each RPC by having a connectionsId
     * object and with set() method. We need to manage the refs for keys in
     * HashMap properly. For now its ok
     */
    do {
      connection = connections.get(remoteId);
      if (connection == null) {
        connection = new Connection(remoteId);
        connections.put(remoteId, connection);
      } else if (!connection.channel.isWritable()
          || !connection.channel.isActive()) {
        connection = new Connection(remoteId);
        connections.remove(remoteId);
        connections.put(remoteId, connection);
      }
    } while (!connection.addCall(call));
    // we don't invoke the method below inside "synchronized (connections)"
    // block above. The reason for that is if the server happens to be slow,
    // it will take longer to establish a connection and that will slow the
    // entire system down.

    connection.setupIOstreams();
    return connection;
  }

  /**
   * This class holds the address and the user ticket. The client connections to
   * servers are uniquely identified by <remoteAddress, protocol, ticket>
   */
  static class ConnectionId {
    InetSocketAddress address;
    UserGroupInformation ticket;
    Class<?> protocol;
    private static final int PRIME = 16777619;
    private int rpcTimeout;
    private String serverPrincipal;
    private int maxIdleTime; // connections will be culled if it was idle for
                             // maxIdleTime msecs
    private final RetryPolicy connectionRetryPolicy;
    private boolean tcpNoDelay; // if T then disable Nagle's Algorithm
    private int pingInterval; // how often sends ping to the server in msecs

    ConnectionId(InetSocketAddress address, Class<?> protocol,
        UserGroupInformation ticket, int rpcTimeout, String serverPrincipal,
        int maxIdleTime, RetryPolicy connectionRetryPolicy, boolean tcpNoDelay,
        int pingInterval) {
      this.protocol = protocol;
      this.address = address;
      this.ticket = ticket;
      this.rpcTimeout = rpcTimeout;
      this.serverPrincipal = serverPrincipal;
      this.maxIdleTime = maxIdleTime;
      this.connectionRetryPolicy = connectionRetryPolicy;
      this.tcpNoDelay = tcpNoDelay;
      this.pingInterval = pingInterval;
    }

    InetSocketAddress getAddress() {
      return address;
    }

    Class<?> getProtocol() {
      return protocol;
    }

    private int getRpcTimeout() {
      return rpcTimeout;
    }

    String getServerPrincipal() {
      return serverPrincipal;
    }

    int getMaxIdleTime() {
      return maxIdleTime;
    }

    boolean getTcpNoDelay() {
      return tcpNoDelay;
    }

    int getPingInterval() {
      return pingInterval;
    }

    static ConnectionId getConnectionId(InetSocketAddress addr,
        Class<?> protocol, UserGroupInformation ticket, Configuration conf)
        throws IOException {
      return getConnectionId(addr, protocol, ticket, 0, conf);
    }

    static ConnectionId getConnectionId(InetSocketAddress addr,
        Class<?> protocol, UserGroupInformation ticket, int rpcTimeout,
        Configuration conf) throws IOException {
      return getConnectionId(addr, protocol, ticket, rpcTimeout, null, conf);
    }

    static ConnectionId getConnectionId(InetSocketAddress addr,
        Class<?> protocol, UserGroupInformation ticket, int rpcTimeout,
        RetryPolicy connectionRetryPolicy, Configuration conf)
        throws IOException {

      if (connectionRetryPolicy == null) {
        final int max = conf.getInt(IPC_CLIENT_CONNECT_MAX_RETRIES_KEY,
            IPC_CLIENT_CONNECT_MAX_RETRIES_DEFAULT);
        connectionRetryPolicy = RetryPolicies
            .retryUpToMaximumCountWithFixedSleep(max, 1, TimeUnit.SECONDS);
      }

      return new ConnectionId(addr, protocol, ticket, rpcTimeout,
          null,
          conf.getInt("ipc.client.connection.maxidletime", 10000), // 10s
          connectionRetryPolicy,
          conf.getBoolean("ipc.client.tcpnodelay", true),
          AsyncClient.getPingInterval(conf));
    }

    static boolean isEqual(Object a, Object b) {
      return a == null ? b == null : a.equals(b);
    }

    @Override
    public boolean equals(Object obj) {
      if (obj == this) {
        return true;
      }
      if (obj instanceof ConnectionId) {
        ConnectionId that = (ConnectionId) obj;
        return isEqual(this.address, that.address)
            && this.maxIdleTime == that.maxIdleTime
            && isEqual(this.connectionRetryPolicy, that.connectionRetryPolicy)
            && this.pingInterval == that.pingInterval
            && isEqual(this.protocol, that.protocol)
            && this.rpcTimeout == that.rpcTimeout
            && isEqual(this.serverPrincipal, that.serverPrincipal)
            && this.tcpNoDelay == that.tcpNoDelay
            && isEqual(this.ticket, that.ticket);
      }
      return false;
    }

    @Override
    public int hashCode() {
      int result = connectionRetryPolicy.hashCode();
      result = PRIME * result + ((address == null) ? 0 : address.hashCode());
      result = PRIME * result + maxIdleTime;
      result = PRIME * result + pingInterval;
      result = PRIME * result + ((protocol == null) ? 0 : protocol.hashCode());
      result = PRIME * rpcTimeout;
      result = PRIME * result
          + ((serverPrincipal == null) ? 0 : serverPrincipal.hashCode());
      result = PRIME * result + (tcpNoDelay ? 1231 : 1237);
      result = PRIME * result + ((ticket == null) ? 0 : ticket.hashCode());
      return result;
    }
  }
}
