public void deliverToApplication(RouteMessage msg) { PastryAppl appl = dispatch.getDestinationByAddress(msg.getAuxAddress()); if (appl == null) { if (msg.sendFailed(new AppNotRegisteredException(msg.getAuxAddress()))) { if (logger.level <= Logger.CONFIG) logger.log( "Dropping message " + msg + " because the application address " + msg.getAuxAddress() + " is unknown."); } else { if (logger.level <= Logger.WARNING) logger.log( "Dropping message " + msg + " because the application address " + msg.getAuxAddress() + " is unknown."); } return; } appl.receiveMessage(msg); // thePastryNode.receiveMessage(msg); }
protected void sendTheMessage(final RouteMessage rm, final NodeHandle handle) { if (logger.level <= Logger.FINER) logger.log("sendTheMessage(" + rm + "," + handle + ")"); rm.setTLCancellable( thePastryNode.send( handle, rm, new PMessageNotification() { public void sent(PMessageReceipt msg) { rm.sendSuccess(handle); } public void sendFailed(PMessageReceipt msg, Exception reason) { if (rm.sendFailed(reason)) { if (logger.level <= Logger.CONFIG) logger.logException("sendFailed(" + rm + ")=>" + handle, reason); } else { if (logger.level <= Logger.FINE) { logger.logException("sendFailed(" + rm + ")=>" + handle, reason); } else { if (reason instanceof NodeIsFaultyException) { if (logger.level <= Logger.INFO) logger.log("sendFailed(" + rm + ")=>" + handle + " " + reason); } else { if (logger.level <= Logger.WARNING) logger.logException("sendFailed(" + rm + ")=>" + handle, reason); } } } } }, rm.getTLOptions())); }
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... }
/** * Receive and process a route message. Sets a nextHop. * * @param msg the message. */ private void receiveRouteMessage(RouteMessage msg) { if (logger.level <= Logger.FINER) logger.log("receiveRouteMessage(" + msg + ")"); Id target = msg.getTarget(); if (target == null) target = thePastryNode.getNodeId(); int cwSize = thePastryNode.getLeafSet().cwSize(); int ccwSize = thePastryNode.getLeafSet().ccwSize(); int lsPos = thePastryNode.getLeafSet().mostSimilar(target); if (lsPos == 0) { // message is for the local node so deliver it msg.setNextHop(thePastryNode.getLocalHandle()); // don't return, we want to check for routing table hole } else { msg.getOptions().setRerouteIfSuspected(true); Iterator<NodeHandle> i = getBestRoutingCandidates(target); // the next hop NodeHandle nextHop = routerStrategy.pickNextHop(msg, i); if (nextHop == null) { msg.sendFailed(new NoLegalRouteToMakeProgressException(target)); return; } msg.setNextHop(nextHop); } // this wasn't being called often enough in its previous location, moved here Aug 11, 2006 checkForRouteTableHole(msg, msg.getNextHop()); msg.setPrevNode(thePastryNode.getLocalHandle()); // here, we need to deliver the msg to the proper app deliverToApplication(msg); }
/** * 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); } } }
/** * Routes the messages if the next hop has been set up. * * <p>Note, this once lived in the RouteMessaage * * @param localId the node id of the local node. * @return true if the message got routed, false otherwise. */ public boolean routeMessage(RouteMessage rm) { if (logger.level <= Logger.FINER) logger.log("routeMessage(" + rm + ")"); if (rm.getNextHop() == null) return false; rm.setSender(thePastryNode.getLocalHandle()); NodeHandle handle = rm.getNextHop(); rm.setNextHop(null); rm.setPrevNode(thePastryNode.getLocalHandle()); if (thePastryNode.getLocalHandle().equals(handle)) { // the local node is the closest node to the id if (rm.getDestinationHandle() != null && !rm.getDestinationHandle().equals(thePastryNode.getLocalHandle())) { // no idea how to contact the destination, drop if (logger.level <= Logger.FINE) logger.log( "Message " + rm + " has destination " + rm.getDestinationHandle() + " but I'm the root of the id. Dropping. This could happen if the destination has died while the route message was in transit, or if the local node does not yet have logging state because it is boostrapping."); rm.sendFailed(new NoRouteToHostException(rm.getDestinationHandle().toString())); return true; } thePastryNode.receiveMessage(rm.internalMsg); rm.sendSuccess(thePastryNode.getLocalHandle()); } else { sendTheMessage(rm, handle); } return true; }