Package tahrir.io.net.sessions

Source Code of tahrir.io.net.sessions.TopologyMaintenanceSessionImpl

package tahrir.io.net.sessions;

import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tahrir.TrConstants;
import tahrir.TrNode;
import tahrir.io.net.PhysicalNetworkLocation;
import tahrir.io.net.RemoteNodeAddress;
import tahrir.io.net.TrPeerManager.Capabilities;
import tahrir.io.net.TrSessionImpl;
import tahrir.io.net.TrSessionManager;
import tahrir.tools.TrUtils;

import java.util.LinkedList;

/**
* Class for carrying out maintenance on topology in hopes of forming a small world network.
*
* @author Kieran Donegan <kdonegan.92@gmail.com>
*/

public class TopologyMaintenanceSessionImpl extends TrSessionImpl implements TopologyMaintenanceSession {
  private final Logger logger;

  private boolean initator = false;

  private PhysicalNetworkLocation receivedProbeFrom;

  private LinkedList<RemoteNodeAddress> willConnectTo;

  /**
   * A acceptor is the node where the search for a location ends, they will try accept as many
   * forwarders as possible.
   */
  private boolean acceptor = false;
  private RemoteNodeAddress acceptorAddress;

  public TopologyMaintenanceSessionImpl(final Integer sessionId, final TrNode node, final TrSessionManager sessionMgr) {
    super(sessionId, node, sessionMgr);
    logger = LoggerFactory.getLogger(TopologyMaintenanceSessionImpl.class.getName()+" ("+sessionId+")");
  }

  public void startTopologyMaintenance(final int locationToFind) {
    if (logger.isDebugEnabled()) {
      logger.debug("Starting maintenance from {} with locationToFind {}", node.getRemoteNodeAddress(), locationToFind);
    }

    initator = true;
    final LinkedList<RemoteNodeAddress> forwarders = Lists.newLinkedList();
    final int hopsToLive = TrConstants.MAINTENANCE_HOPS_TO_LIVE;

    probeForLocation(locationToFind, hopsToLive, forwarders);
  }

  public void probeForLocation(final int locationToFind, int hopsToLive, final LinkedList<RemoteNodeAddress> forwarders) {
    if (!initator) {
      receivedProbeFrom = sender();
      hopsToLive--;
      node.getPeerManager().hasForwardedRecently = true;
    }

    final RemoteNodeAddress closestPeerAddress = node.getPeerManager().getClosestPeer(locationToFind);

    if (logger.isDebugEnabled()) {
      logger.debug("The closest peer found was {}, with a location of {}", node.getRemoteNodeAddress().physicalLocation, node.getPeerManager().getLocInfo().getLocation());
    }

    if (hopsToLive == 0 || closestPeerAddress.equals(node.getRemoteNodeAddress()) || (!initator && closestPeerAddress.physicalLocation.equals(sender()))) {
      // the current node is the closest to what we're looking for or we've given up
      acceptor = true;
      sendResponses(forwarders);
    } else {
      if (hopsToLive > TrConstants.MAINTENANCE_HOPS_TO_LIVE) {
        hopsToLive = TrConstants.HOPS_TO_LIVE_RESET;
      }

      node.getPeerManager().updateTimeLastUsed(closestPeerAddress.physicalLocation);

      forwarders.add(node.getRemoteNodeAddress());

      // get next location
      final TopologyMaintenanceSession closestPeerSession = this.remoteSession(TopologyMaintenanceSession.class, this.connection(closestPeerAddress));
      closestPeerSession.probeForLocation(locationToFind, hopsToLive, forwarders);
    }
  }

  private void sendResponses(final LinkedList<RemoteNodeAddress> forwarders) {
    int peersToAccept = getNumPeerToAccept(forwarders);

    willConnectTo = Lists.newLinkedList();

    // get nodes we're going to connect to
    while (peersToAccept > 0 && forwarders.size() > 0) {
      final int randomNum = TrUtils.rand.nextInt(forwarders.size());
      final RemoteNodeAddress randomForwarder = forwarders.remove(randomNum);

      // check to see if connected
      if (!node.getPeerManager().peers.containsKey(randomForwarder.physicalLocation)) {
        willConnectTo.add(randomForwarder);
        peersToAccept--;
      }
    }

    // trace back so that then can accept us
    if (!initator && willConnectTo.size() > 0) {
      final TopologyMaintenanceSession senderSess = this.remoteSession(TopologyMaintenanceSession.class, connection(receivedProbeFrom));
      senderSess.sendAcceptInfo(node.getRemoteNodeAddress(), willConnectTo);
    }

    // tell them we're trying to connect
    for (final RemoteNodeAddress nodeToConnect : willConnectTo) {

      final TopologyMaintenanceSession forwarderSess = this.remoteSession(TopologyMaintenanceSession.class, connection(nodeToConnect));
      forwarderSess.myCapabilitiesAre(node.getConfig().capabilities, node.getPeerManager().getLocInfo().getLocation());
    }
  }

    private int backOff(int attempt){
        return ((2^attempt - 1)/2);
    }

  public void sendAcceptInfo(final RemoteNodeAddress acceptor, final LinkedList<RemoteNodeAddress> willConnectTo) {
    if (willConnectTo.contains(node.getRemoteNodeAddress())) {
      final TopologyMaintenanceSession acceptorSess = this.remoteSession(TopologyMaintenanceSession.class, connection(acceptor));
      acceptorAddress = acceptor;
      acceptorSess.myCapabilitiesAre(node.getConfig().capabilities, node.getPeerManager().getLocInfo().getLocation());
    }

    if (!initator) {
      final TopologyMaintenanceSession senderSess = this.remoteSession(TopologyMaintenanceSession.class, connection(receivedProbeFrom));
      senderSess.sendAcceptInfo(acceptor, willConnectTo);
    }
  }

  public void myCapabilitiesAre(final Capabilities myCapabilities, final int topologyLocation) {
    if (!acceptor) {
      node.getPeerManager().addByReplacement(acceptorAddress, myCapabilities, topologyLocation);
    } else {
      RemoteNodeAddress forwarderAddress = null;
      // find the remote address corresponding to sender()
      for (RemoteNodeAddress address : willConnectTo) {
        if (address.physicalLocation.equals(sender())) {
          forwarderAddress = address;
          break;
        }
      }
      node.getPeerManager().addByReplacement(forwarderAddress, myCapabilities, topologyLocation);
    }
  }

  private int getNumPeerToAccept(final LinkedList<RemoteNodeAddress> forwarders) {
    return forwarders.size() <= node.getPeerManager().getNumFreePeerSlots()
        ? forwarders.size()
            : TrConstants.TOPOLOGY_MAINTENANCE_PEERS_TO_REPLACE;
  }
}
TOP

Related Classes of tahrir.io.net.sessions.TopologyMaintenanceSessionImpl

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.