public NodeHandle pickNextHop(RouteMessage msg, Iterator<NodeHandle> i) { NodeHandle first = i.next(); if (first.getLiveness() < NodeHandle.LIVENESS_SUSPECTED) { return first; } while (i.hasNext()) { NodeHandle nh = i.next(); if (nh.getLiveness() < NodeHandle.LIVENESS_SUSPECTED) { return nh; } // do this in case first is dead, and we find a suspected node to pass it to if (first.getLiveness() > nh.getLiveness()) first = nh; } if (first.getLiveness() >= NodeHandle.LIVENESS_DEAD) { // drop the message, this would happen if we gave a lease to this node // but found him faulty. return null; } msg.getOptions().setRerouteIfSuspected(false); return first; // always want to return someone... }
/** * checks to see if the previous node along the path was missing a RT entry if so, we send the * previous node the corresponding RT row to patch the hole * * @param msg the RouteMessage being routed * @param handle the next hop handle */ private void checkForRouteTableHole(RouteMessage msg, NodeHandle handle) { if (logger.level <= Logger.FINEST) logger.log("checkForRouteTableHole(" + msg + "," + handle + ")"); NodeHandle prevNode = msg.getPrevNode(); if (prevNode == null) { if (logger.level <= Logger.FINER) logger.log("No prevNode defined in " + msg); return; } if (prevNode.equals(getNodeHandle())) { if (logger.level <= Logger.FINER) logger.log("prevNode is me in " + msg); return; } // we don't want to send the repair if they just routed in the leafset LeafSet ls = thePastryNode.getLeafSet(); if (ls.overlaps()) return; // small network, don't bother if (ls.member(prevNode)) { // ok, it's in my leafset, so I'm in his, but make sure that it's not on the edge int index = ls.getIndex(prevNode); if ((index == ls.cwSize()) || (index == -ls.ccwSize())) { // it is the edge... continue with repair } else { return; } } Id prevId = prevNode.getNodeId(); Id key = msg.getTarget(); int diffDigit = prevId.indexOfMSDD(key, thePastryNode.getRoutingTable().baseBitLength()); // if we both have the same prefix (in other words the previous node didn't make a prefix of // progress) if (diffDigit >= 0 && diffDigit == thePastryNode .getNodeId() .indexOfMSDD(key, thePastryNode.getRoutingTable().baseBitLength())) { synchronized (lastTimeSentRouteTablePatch) { if (lastTimeSentRouteTablePatch.containsKey(prevNode)) { long lastTime = lastTimeSentRouteTablePatch.get(prevNode); if (lastTime > (thePastryNode.getEnvironment().getTimeSource().currentTimeMillis() - ROUTE_TABLE_PATCH_THROTTLE)) { if (logger.level <= Logger.INFO) logger.log( "not sending route table patch to " + prevNode + " because throttled. Last Time:" + lastTime); return; } } lastTimeSentRouteTablePatch.put( prevNode, thePastryNode.getEnvironment().getTimeSource().currentTimeMillis()); } // the previous node is missing a RT entry, send the row // for now, we send the entire row for simplicity RouteSet[] row = thePastryNode.getRoutingTable().getRow(diffDigit); BroadcastRouteRow brr = new BroadcastRouteRow(thePastryNode.getLocalHandle(), row); if (prevNode.isAlive()) { if (logger.level <= Logger.FINE) { logger.log( "Found hole in " + prevNode + "'s routing table. Sending " + brr.toStringFull()); } thePastryNode.send(prevNode, brr, null, options); } } }