Package net.sf.katta.client

Source Code of net.sf.katta.client.NodeProxyManager

/**
* Copyright 2011 the original author or authors.
*
* 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 net.sf.katta.client;

import java.io.EOFException;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.VersionedProtocol;
import org.apache.log4j.Logger;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;

public class NodeProxyManager implements INodeProxyManager {

  private final static Logger LOG = Logger.getLogger(NodeProxyManager.class);
  private final Class<? extends VersionedProtocol> _serverClass;
  private final Configuration _hadoopConf;
  private final Map<String, VersionedProtocol> _node2ProxyMap = new ConcurrentHashMap<String, VersionedProtocol>();
  private final INodeSelectionPolicy _selectionPolicy;

  private int _successiveProxyFailuresBeforeReestablishing = 3;
  private final Multiset<String> _failedNodeInteractions = HashMultiset.create();

  public NodeProxyManager(Class<? extends VersionedProtocol> serverClass, Configuration hadoopConf,
          INodeSelectionPolicy selectionPolicy) {
    _serverClass = serverClass;
    _hadoopConf = hadoopConf;
    _selectionPolicy = selectionPolicy;
  }

  /**
   * @return how many successive proxy invocation errors must happen before the
   *         proxy is re-established.
   */
  public int getSuccessiveProxyFailuresBeforeReestablishing() {
    return _successiveProxyFailuresBeforeReestablishing;
  }

  public void setSuccessiveProxyFailuresBeforeReestablishing(int successiveProxyFailuresBeforeReestablishing) {
    _successiveProxyFailuresBeforeReestablishing = successiveProxyFailuresBeforeReestablishing;
  }

  public VersionedProtocol createNodeProxy(final String nodeName) throws IOException {
    LOG.debug("creating proxy for node: " + nodeName);

    String[] hostName_port = nodeName.split(":");
    if (hostName_port.length != 2) {
      throw new RuntimeException("invalid node name format '" + nodeName
              + "' (It should be a host name with a port number devided by a ':')");
    }
    final String hostName = hostName_port[0];
    final String port = hostName_port[1];
    final InetSocketAddress inetSocketAddress = new InetSocketAddress(hostName, Integer.parseInt(port));
    VersionedProtocol proxy = RPC.getProxy(_serverClass, 0L, inetSocketAddress, _hadoopConf);
    LOG.debug(String.format("Created a proxy %s for %s:%s %s", Proxy.getInvocationHandler(proxy), hostName, port,
            inetSocketAddress));
    return proxy;
  }

  @Override
  public VersionedProtocol getProxy(String nodeName, boolean establishIfNoExists) {
    VersionedProtocol versionedProtocol = _node2ProxyMap.get(nodeName);
    if (versionedProtocol == null && establishIfNoExists) {
      synchronized (nodeName.intern()) {
        if (!_node2ProxyMap.containsKey(nodeName)) {
          try {
            versionedProtocol = createNodeProxy(nodeName);
            _node2ProxyMap.put(nodeName, versionedProtocol);
          } catch (Exception e) {
            LOG.warn("Could not create proxy for node '" + nodeName + "' - " + e.getClass().getSimpleName() + ": "
                    + e.getMessage());
          }
        }
      }
    }
    return versionedProtocol;
  }

  @Override
  public Map<String, List<String>> createNode2ShardsMap(Collection<String> shards) throws ShardAccessException {
    return _selectionPolicy.createNode2ShardsMap(shards);
  }

  @SuppressWarnings("unchecked")
  @Override
  public void reportNodeCommunicationFailure(String nodeName, Throwable t) {
    // TODO jz: not sure if there are cases a proxy is getting invalid and
    // re-establishing it would fix the communication. If so, we should check
    // the for the exception which occurs in such cases and re-establish the
    // proxy.
    _failedNodeInteractions.add(nodeName);
    int failureCount = _failedNodeInteractions.count(nodeName);
    if (failureCount >= _successiveProxyFailuresBeforeReestablishing
            || exceptionContains(t, ConnectException.class, EOFException.class)) {
      dropNodeProxy(nodeName, failureCount);
    }
  }

  private boolean exceptionContains(Throwable t, Class<? extends Throwable>... exceptionClasses) {
    while (t != null) {
      for (Class<? extends Throwable> exceptionClass : exceptionClasses) {
        if (t.getClass().equals(exceptionClass)) {
          return true;
        }
      }
      t = t.getCause();
    }
    return false;
  }

  private void dropNodeProxy(String nodeName, int failureCount) {
    synchronized (nodeName.intern()) {
      if (_node2ProxyMap.containsKey(nodeName)) {
        LOG.warn("removing proxy for node '" + nodeName + "' after " + failureCount + " proxy-invocation errors");
        _failedNodeInteractions.remove(nodeName, Integer.MAX_VALUE);
        _selectionPolicy.removeNode(nodeName);
        VersionedProtocol proxy = _node2ProxyMap.remove(nodeName);
        RPC.stopProxy(proxy);
      }
    }
  }

  @Override
  public void reportNodeCommunicationSuccess(String node) {
    _failedNodeInteractions.remove(node, Integer.MAX_VALUE);
  }

  @Override
  public void shutdown() {
    Collection<VersionedProtocol> proxies = _node2ProxyMap.values();
    for (VersionedProtocol search : proxies) {
      RPC.stopProxy(search);
    }
  }

}
TOP

Related Classes of net.sf.katta.client.NodeProxyManager

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.