Beispiel #1
0
  /**
   * bad route, so let's remove everything we have so we can start from scratch. We are maintaining
   * a bad route up to DEFAULT_ROUTE experition after that we consider it to be ok to retry the same
   * route We are removing both the route and peer advertisement to force a new route query
   *
   * @param src peer that reply with the NACK route info
   * @param dest original route information
   */
  private void processBadRoute(PeerID badHop, RouteAdvertisement dest) {

    EndpointAddress addr = router.pid2addr(dest.getDestPeerID());

    if (addr == null) {
      if (LOG.isEnabledFor(Level.DEBUG)) {
        LOG.debug("remove bad route has a bad route info - discard");
      }
      return;
    }

    if (LOG.isEnabledFor(Level.DEBUG)) {
      LOG.debug("remove bad route info for dest " + dest.display());
      if (badHop != null) {
        LOG.debug("remove bad route bad hop " + badHop);
      }
    }

    try {

      // check first that we still have the same route, we may already
      // using a new route
      RouteAdvertisement currentRoute = router.getRoute(addr, false);

      if (currentRoute == null) { // we already cleanup the route info
        return;
      }

      // check if we still have the old bad route, we may have
      // already updated the route
      if (!currentRoute.equals(dest)) {

        // check if the bad hop is not the destination
        // if it is then we still have a bad route
        if (!(badHop.equals(router.addr2pid(addr)))) {
          // check if the new route may still contain the bad hop
          // the known bad hop is the hop after the src peer that
          // responded with a NACK route
          // In this case we also consider the route bad
          if (badHop != null) { // this should really not be null
            if (!currentRoute.containsHop(badHop)) {
              return; // we are ok
            } else {
              if (LOG.isEnabledFor(Level.DEBUG)) {
                LOG.debug("current route is bad because it contains known bad hop" + badHop);
              }
            }
          } else { // we could get the bad hop, so consider the route ok
            return;
          }
        } else {
          if (LOG.isEnabledFor(Level.DEBUG)) {
            LOG.debug("current route is bad because it contains known bad destination" + badHop);
          }
        }
      }

      // keep the bad one in a cache table so we don't retry them
      // right away. We use the default route timeout
      BadRoute badRoute = ((BadRoute) router.getBadRoute(addr));

      if (badRoute != null) {

        Long nextTry = badRoute.getExpiration();

        if (nextTry.longValue()
            > System.currentTimeMillis()) { // nothing to do the information is still valid
        } else {
          // It is ancient knowlege update it
          nextTry = new Long(TimeUtils.toAbsoluteTimeMillis(BADROUTE_EXPIRATION));
          badRoute.setExpiration(nextTry);
        }

        List badHops = badRoute.getHops();

        // check if we have to add a new bad hop
        // to our bad route
        if (badHop != null) {
          if (!badHops.contains(badHop)) {
            badHops.add(badHop);
            // new expiration
            nextTry = new Long(TimeUtils.toAbsoluteTimeMillis(BADROUTE_EXPIRATION));
            badRoute.setHops(badHops);
            badRoute.setExpiration(nextTry);
          }
        }

        router.setBadRoute(addr, badRoute);
        return;
      } else {
        // create a new NACK route entry
        Vector badHops = new Vector();

        if (badHop != null) {
          badHops.add(badHop);
        }

        badRoute =
            new BadRoute(
                dest, new Long(TimeUtils.toAbsoluteTimeMillis(BADROUTE_EXPIRATION)), badHops);
        router.setBadRoute(addr, badRoute);
      }

      // remove route from route CM
      routeCM.flushRoute(addr);

      // let's remove the remote route info from the routing table
      // we do this after we removed the entries from the CM
      // to avoid that another thread is putting back the entry
      router.removeRoute(addr);

    } catch (Exception ex) {
      if (LOG.isEnabledFor(Level.WARN)) {
        LOG.warn("exception during bad route removal", ex);
      }
    }
  }
Beispiel #2
0
  /**
   * issue a new route discovery resolver request
   *
   * @param peer the destination as a logical enpoint address
   */
  protected void findRoute(EndpointAddress peer) {

    RouteAdvertisement myRoute = router.getMyLocalRoute();

    // No need to pursue further if we haven't
    // initialize our own route as responding
    // peers are not going to be able to respond to us.
    if (myRoute == null) {
      if (LOG.isEnabledFor(Level.DEBUG)) {
        LOG.debug("Cannot issue a find route if we don't know our own route");
      }
      return;
    }

    if (LOG.isEnabledFor(Level.DEBUG)) {
      LOG.debug("Find route for peer = " + peer);
    }

    try {
      // create a new RouteQuery message
      RouteQuery doc = null;

      // check if we have some bad route information
      // for that peer, in that case pass the bad hop count
      BadRoute badRoute;

      badRoute = (BadRoute) router.getBadRoute(peer);

      if (badRoute != null) {
        // ok we have a bad route
        // pass the bad hops info as part of the query
        if (LOG.isEnabledFor(Level.DEBUG)) {
          LOG.debug("findRoute sends query: known bad Hops" + badRoute.display());
        }
        doc = new RouteQuery(router.addr2pid(peer), myRoute, badRoute.getHops());
      } else {
        doc = new RouteQuery(router.addr2pid(peer), myRoute, null);
      }

      if (LOG.isEnabledFor(Level.DEBUG)) {
        LOG.debug("Sending query for peer : " + peer);
      }

      ResolverQuery query =
          new ResolverQuery(
              routerSName, credentialDoc, localPeerId.toString(), doc.toString(), qid++);

      // only run SRDI if we are a rendezvous
      if (group.isRendezvous()) {

        // check where to send the query via SRDI
        Vector results = null;

        if (srdiIndex != null) {
          // try to find a least 10 entries, will pick up one
          // randomly. This will protect against retry. It is
          // likely that a number of RDV will know about a route
          results = srdiIndex.query("route", "DstPID", router.addr2pid(peer).toString(), 10);

          if (results != null && results.size() > 0) {
            // use SRDI to send the query
            // remove any non rdv peers from the candidate list
            // and garbage collect the index in the process
            Vector clean = cleanupAnyEdges(query.getSrc(), results);

            if (clean.size() > 0) {
              // The purpose of incrementing the hopcount
              // when an SRDI index match is found (we got a
              // pointer to a rdv that should have the route) is to
              // restrict any further forwarding. The increment
              // count is only done when a matching SRDI index is
              // found. Not when the replica is selected as we
              // still need to forward the query.  This restriction
              // is purposelly done to avoid too many longjumps
              // within a walk.
              query.incrementHopCount();

              srdi.forwardQuery(clean, query, 1);
              if (LOG.isEnabledFor(Level.DEBUG)) {
                LOG.debug("found an srdi entry forwarding query to SRDI peer");
              }
              return;
            }
          } else {
            // it is not in our cache, look for the replica peer
            // we need to send the query
            PeerID destPeer = srdi.getReplicaPeer(router.addr2pid(peer).toString());

            if (destPeer != null && !destPeer.equals(localPeerId)) {
              // don't push anywhere if we do not have a replica
              // or we are trying to push to ourself
              if (LOG.isEnabledFor(Level.DEBUG)) {
                LOG.debug("processQuery srdiIndex DHT forward :" + destPeer);
              }

              srdi.forwardQuery(destPeer.toString(), query);
              return;
            }
          }
        }
      }

      // if we reach that point then we just use the resolver walk
      resolver = group.getResolverService();
      if (resolver != null) {
        resolver.sendQuery(null, query);
        if (LOG.isEnabledFor(Level.DEBUG)) {
          LOG.debug("find route query sent");
        }
      } else {
        if (LOG.isEnabledFor(Level.WARN)) {
          LOG.warn("cannot get the resolver service");
        }
      }

    } catch (Exception ee) {
      if (LOG.isEnabledFor(Level.WARN)) {
        LOG.warn("Exception in findRoute", ee);
      }
    }
  }