Package com.walmartlabs.mupd8.network.client

Source Code of com.walmartlabs.mupd8.network.client.Client$Endpoint

/**
* Copyright 2011-2012 @WalmartLabs, a division of Wal-Mart Stores, Inc.
*
* Licensed 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 com.walmartlabs.mupd8.network.client;

import java.net.InetSocketAddress;
import java.util.concurrent.*;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

import com.walmartlabs.mupd8.network.common.*;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Client {

  private class Endpoint {
    public String _host;
    public int    _port;

    public Endpoint(String host, int port) {
      _host = host;
      _port = port;
    }
   
    @Override
    public String toString() {
      return "(" + _host + ", " + _port + ")";
    }
  }

  private final Listener listener;
  private ClientBootstrap bootstrap;
  private ClientHandler handler;
  // Store connections to all hosts in cluster
  private ConcurrentHashMap<String, Channel> connectors;
  // Store endpoints for all hosts in cluster
  private ConcurrentHashMap<String, Endpoint> endpoints;
  private Executor bossPool;
  private ThreadPoolExecutor workerPool;
  private OneToOneEncoder encoder;
  private Callable<ReplayingDecoder<Decoder.DecodingState>> decoderFactory;
  private static final Logger logger = LoggerFactory.getLogger(Client.class);

  public Client(Listener listener, OneToOneEncoder pencoder, Callable<ReplayingDecoder<Decoder.DecodingState>> pdecoderFactory) {
    this.listener = listener;
    this.encoder = pencoder;
    this.decoderFactory = pdecoderFactory;
    connectors = new ConcurrentHashMap<String, Channel>();
    endpoints = new ConcurrentHashMap<String, Endpoint>();
  }

  public void init() {
    // Standard netty bootstrapping stuff.
    bossPool = Executors.newCachedThreadPool();
    workerPool = (ThreadPoolExecutor)Executors.newCachedThreadPool();
    ChannelFactory factory =
      new NioClientSocketChannelFactory(bossPool, workerPool);

    handler = new ClientHandler(listener);
    bootstrap = new ClientBootstrap(factory);

    bootstrap.setOption("reuseAddress", true);
    bootstrap.setOption("tcpNoDelay", true);
    bootstrap.setOption("keepAlive", true);
    bootstrap.setOption("sendBufferSize", 1048576);
    bootstrap.setOption("receiveBufferSize", 1048576);
    bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

        @Override
        public ChannelPipeline getPipeline() throws Exception {
          ChannelPipeline pipeline = Channels.pipeline();
          pipeline.addLast("encoder", encoder);
          pipeline.addLast("decoder", decoderFactory.call());
          pipeline.addLast("handler", handler);
          return pipeline;
        }
      });
  }

  public void addEndpoint(String host, int port) {
    endpoints.put(host, this.new Endpoint(host, port));
  }

  public void removeEndpoint(String host) {
    if (endpoints.containsKey(host)) {
      endpoints.remove(host);
    }
    disconnect(host);
  }

  private boolean connect(String host, int port) {
    InetSocketAddress remoteAddr = new InetSocketAddress(host, port);

    ChannelFuture future = null;
    // retry 3 times for now
    int i = 0;
    for (; i < 3; i++) {
      future= bootstrap.connect(remoteAddr);
      if (!future.awaitUninterruptibly().isSuccess()) {
        logger.error("CLIENT - Failed to connect to server at " +
                    remoteAddr.getHostName() + ":" + remoteAddr.getPort());
        try {
          Thread.sleep(500);
        } catch (InterruptedException e) {
        }
      } else break;
    }
    if (i >= 3) return false;
    logger.info("CLIENT - Connected to " + remoteAddr.getHostName() + ":" + remoteAddr.getPort());

    Channel connector = future.getChannel();
    connectors.put(host, connector);
    return connector.isConnected();
  }

  public boolean isConnected(String connId) {
    if (connectors.containsKey(connId))
      return connectors.get(connId).isConnected();
    else
      return false;
  }

  private void disconnect(String host) {
    if (connectors.containsKey(host)) {
      Channel connector = connectors.get(host);
      if (connector != null) {
        connector.close().awaitUninterruptibly();
      }
      connectors.remove(host);
    }
  }

  // close all the connections and shut down the client
  public void stop() {
    int largestPoolSize = workerPool.getLargestPoolSize();
    logger.info("Largest pool size for client worker pool: " + largestPoolSize);
    for (Channel connector : connectors.values()) {
      if (connector != null)
        connector.close().awaitUninterruptibly();
    }

    connectors.clear();
    this.bootstrap.releaseExternalResources();
    logger.info("CLIENT stopped...");
  }

  public boolean send(String connId, Object packet) {
    if (!endpoints.containsKey(connId)) {
      logger.warn("CLIENT - endpoint of " + connId + " doesn't exist.");
      return false;
    }

    // Make connect only when it is used.
    if (!connectors.containsKey(connId)) {
      logger.warn("CLIENT - connection to (" + connId + ", " + endpoints.get(connId) + ") doesn't exist; going to make connection.");
      if (!connect(endpoints.get(connId)._host, endpoints.get(connId)._port)) {
        logger.error("CLIENT - connecting to " + connId + " failed.");
        return false;
      }
    }

    Channel connector = connectors.get(connId);
    if (connector.isConnected()) {
      connector.write(packet);
      return true;
    } else {
      logger.error("CLIENT - " + connId + " is not connected!");
      if (!connect(endpoints.get(connId)._host, endpoints.get(connId)._port)) {
        logger.error("CLIENT - reconnecting to " + connId + " failed.");
        return false;
      }
      connector = connectors.get(connId);
      if (connector.isConnected()) {
        connector.write(packet);
        return true;
      } else {
        logger.error("CLIENT - " + connId + " still is not connected!");
        return false;
      }
    }
  }

}
TOP

Related Classes of com.walmartlabs.mupd8.network.client.Client$Endpoint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.