📄 .#meednode.java.1.41
字号:
return false; } /** Process incoming topology messages. */ public boolean acceptMessage(ProtocolStackMessage msg, Contact contact, int size) { if (size < msg.getLength() || msg.getProtocolID() != PROTO_MEED_ID) return false; if (msg.isRoutingMessage()) { return receivedProtocolMessage(msg, contact); } return false; } /** * Record contact statistics when the link comes up. */ public void contactUp(Contact ct) { // It might be only contact directed FROM this node! if (ct.getSource() != parent) return; assert !connectedContacts.contains(ct); metric.contactUp(ct, network.getCurrentTime()); // See if our link state has changed and needs to be updated HashMap<Contact, Double> linkState = metric.contactWeights(network.getCurrentTime()); if (contactStateChanged(linkState)) { topologyChanged(); // invalidate routing cache // Put the routing update into an object selfSequence += 1; RoutingUpdate r = new RoutingUpdate(); r.node = this.parent; r.sequenceNumber = selfSequence; r.contactWeights = linkState; boolean updated = topology.processUpdate(r); if (network.vShouldLog(Verbose.DEBUG1)) network.vprint("MEED ProcessedUpdate (self) for linkState: " + linkState + ": " + updated); if (!updated) return; // Flood this local topology update to all other nodes for (Iterator<Contact> i = connectedContacts.iterator(); i.hasNext();) { Contact c = i.next(); assert c != ct; // Package this up in an update message // base size is 16 bytes (number of updates, node id, // sequence number, length, then 8 bytes per link (node id, // contact weight)) int size = 16 + 8 * linkState.size(); ArrayList<RoutingUpdate> temp = new ArrayList<RoutingUpdate>(); temp.add(r); ProtocolStackMessage updateMsg = new ProtocolStackMessage(network.getNextRoutingMessageId(), network.getCurrentTime(), parent, c.getDest(), 0, size, true); updateMsg.setProtocolID(PROTO_MEED_ID); updateMsg.storeData(routingUpdateKey, temp); getMsgsToSend(c).add(updateMsg); } } } /** * Exchange link state information when the link first becomes * available. */ public boolean contactIdle(Contact ct) { if (super.contactIdle(ct)) { return true; } if (!connectedContacts.contains(ct)) { connectedContacts.add(ct); // Invalidate the routing state now that the link is available topologyChanged(); if (network.vShouldLog(Verbose.DEBUG1)) network.vprint("MEED " + this.parent + " - routing state invalidated."); // This is a newly connected node: send the routing table // summary HashMap routingSummary = topology.getRoutingSummary(); // 4 bytes per node id, 4 bytes per weight, 4 bytes for the // length int size = routingSummary.size() * 8 + 4; ProtocolStackMessage msg = new ProtocolStackMessage(network.getNextRoutingMessageId(), network .getCurrentTime(), parent, ct.getDest(), 0, size, true); msg.setProtocolID(PROTO_MEED_ID); msg.storeData(routingSummaryKey, routingSummary); ct.sendMessage(msg); return true; } if (network.vShouldLog(Verbose.DEBUG1)) network.vprint("MEED " + this.parent + " TopologyIdleContact for " + ct + " returns " + (!isGettingUpdates()) + "; GettingUpdates: " + gettingUpdates); // We force the queue to go idle if we *are* getting updates return isGettingUpdates(); } public void contactDown(Contact ct) { super.contactDown(ct); connectedContacts.remove(ct); gettingUpdates.remove(ct); // Metrics only care about contacts that go FROM this node if (ct.getSource() == this.parent) { metric.contactDown(ct, network.getCurrentTime()); } // Contacts going up and down mean that the routing state changes: // invalidate the cached routing topologyChanged(); } /** * The topology of the current DTN. */ protected class DTNTopology implements Dijkstra.Graph<Node, Contact, ProtocolStackMessage> { TreeSet<Node> forbiddenNodes = null; public void setForbiddenNodes(TreeSet<Node> nodes) { forbiddenNodes = nodes; } public void clearForbiddenNodes() { forbiddenNodes = null; } public DTNTopology() { } /** Maps contacts to their most recent weights. */ protected HashMap<Contact, Double> contactWeights = new HashMap<Contact, Double>(); /** Maps nodes to their most recent sequence numbers. */ protected HashMap<Node, Integer> nodeSequenceNumbers = new HashMap<Node, Integer>(); /** Maps nodes to their contacts. */ protected HashMap<Node, ArrayList<Contact>> nodeContacts = new HashMap<Node, ArrayList<Contact>>(); /** * Returns the weight for the specified link object. The time and * obj are used so the graph can define weights that depend on the * context. */ public double getWeight(Contact ofContact, double time, ProtocolStackMessage contextMsg) // public double linkWeight(Graph.Link link, double time, Object // obj) { double weight = 0; // If the specified contact is currently up, then the weight for // local routing is zero if (connectedContacts.contains(ofContact)) weight = 0; else weight = contactWeights.get(ofContact).doubleValue(); // ~ System.out.println( Simulator.time() + " Contact " + link + // " weight " + weight ); return weight; } /** * Returns an Iterator over all the Contacts that leave 'fromNode' * Node. */ public Iterator<? extends Contact> getArcsOut(Node fromNode) { ArrayList<Contact> contacts = nodeContacts.get(fromNode); if (contacts == null) { return (new ArrayList<Contact>()).iterator(); } if (forbiddenNodes == null) { return contacts.iterator(); } int s = contacts.size(); Iterator<Contact> it = contacts.iterator(); if (s < 1) { return it; } ArrayList<Contact> ret = new ArrayList<Contact>(s); while (it.hasNext()) { Contact c = it.next(); if (!forbiddenNodes.contains(c.getDest())) { ret.add(c); } } return ret.iterator(); } /** Returns the source node for arc. */ public Node getSource(Contact arc) { return arc.getSource(); } /** Returns the destination node for arc. */ public Node getDest(Contact arc) { return arc.getDest(); } public int compareNodes(Node a, Node b) { return a.compareTo(b); } public HashMap<? extends Node, ? extends Integer> getRoutingSummary() { return new HashMap<Node, Integer>(nodeSequenceNumbers); } public boolean processUpdate(RoutingUpdate update) { return this.processUpdate(update.node, update.sequenceNumber, update.contactWeights); } public boolean processUpdate(Node node, int sequenceNumber, HashMap<Contact, Double> updatedContactWeights) { // Verify that this update is more recent than the previous one if (nodeSequenceNumbers.get(node) != null && nodeSequenceNumbers.get(node).intValue() >= sequenceNumber) { // This update is the same or older than our current state: // ignore it return false; } // Update the sequence number nodeSequenceNumbers.put(node, new Integer(sequenceNumber)); // Remove current contacts, in case the new update has *fewer* // contacts than the // previous update (a contact has expired due to being down for // too long) ArrayList<Contact> oldContacts = nodeContacts.get(node); nodeContacts.put(node, new ArrayList<Contact>()); if (oldContacts != null) { for (Iterator<Contact> i = oldContacts.iterator(); i.hasNext();) { Contact c = i.next(); assert c.getSource() == node; assert contactWeights.containsKey(c); contactWeights.remove(c); } } // Add all the new contacts contactWeights.putAll(updatedContactWeights); ArrayList<Contact> cToAdd = new ArrayList<Contact>(updatedContactWeights.keySet()); nodeContacts.put(node, cToAdd); // Add "invalid" sequence numbers for any nodes which we have // just discovered // This assures that routing will still work, even though we // don't have a sequence number // for those nodes yet Integer invalidSequence = new Integer(-1); for (Iterator<Contact> i = updatedContactWeights.keySet().iterator(); i.hasNext();) { Contact c = i.next(); assert c.getSource() == node; if (!nodeSequenceNumbers.containsKey(c.getDest())) { nodeSequenceNumbers.put(c.getDest(), invalidSequence); } if (network.vShouldLog(Verbose.DEBUG1)) network.vprint("MEED Update contact: Weight of " + c + " = " + updatedContactWeights.get(c)); // ~ if ( id() == 0 ) System.out.println( Simulator.time() + // " update contact: " + c.src() + " -> " + c.dst() + " = " // + updatedContactWeights.get( c ) ); } // We actually did process an update return true; } /** * Create an array of routing updates that are more accurate than * the ones represented by the routingSummary. */ public ArrayList<RoutingUpdate> getRoutingUpdates(HashMap<? extends Node, ? extends Integer> routingSummary) { ArrayList<RoutingUpdate> updates = new ArrayList<RoutingUpdate>(); for (Iterator<Map.Entry<Node, Integer>> i = nodeSequenceNumbers.entrySet().iterator(); i.hasNext();) { Map.Entry<Node, Integer> entry = i.next(); Node node = entry.getKey(); Integer ourSequence = entry.getValue(); // A -1 indicates that our topology is currently not // complete, and we actually // have no information about that node, but we know it // exists because we have // a contact to it if (ourSequence.intValue() == -1) continue; Integer otherSequence = routingSummary.get(node); if (otherSequence == null || otherSequence.intValue() < ourSequence.intValue()) { // TIf they are missing the information, or if their // information is out of date, // send them the information about this node RoutingUpdate update = new RoutingUpdate(); update.node = node; update.sequenceNumber = ourSequence.intValue(); // Copy the contact weights from our topology state update.contactWeights = new HashMap<Contact, Double>(); for (Iterator j = nodeContacts.get(node).iterator(); j.hasNext();) { Contact c = (Contact) j.next(); update.contactWeights.put(c, contactWeights.get(c)); } updates.add(update); } } return updates; } /** Tests if we need any of the updates in the routing summary. */ // TODO: Can this be combined with the previous test somehow? public boolean needRoutingUpdates(HashMap<? extends Node, ? extends Integer> routingSummary) { for (Iterator i = routingSummary.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); Node node = (Node) entry.getKey(); Integer otherSequence = (Integer) entry.getValue(); Integer ourSequence = nodeSequenceNumbers.get(node); if (ourSequence == null || ourSequence.intValue() < otherSequence.intValue()) { // They have a more recent update that we need return true; } } return false; } } protected class TreeNode { public MEEDDijkstra routing = null; public HashMap<Node, TreeNode> down = null; } } /** Routes messages based on the topology provided. */ public static class TopologyRoutingEventHandler extends EventHandler implements MEEDTopologyObserver { private static int myID = getHandlerID(); protected MEEDNode parent = null; protected Collection<ProtocolStackMessage> buffer = null; protected MEEDTopologyEventHandler topology = null; protected FinalDestinationEventHandler finalAgent; public TopologyRoutingEventHandler(MEEDNode node, MEEDTopologyEventHandler topology, FinalDestinationEventHandler finalA, Collection<ProtocolStackMessage> buffer) { super(myID); this.parent = node; this.buffer = buffer; this.topology = topology; this.finalAgent = finalA; topology.addObserver(this); } public TopologyRoutingEventHandler(int setID, MEEDNode node, MEEDTopologyEventHandler topology, FinalDestinationEventHandler finalA, Collection<ProtocolStackMessage> buffer) { super(setID); this.parent = node; this.buffer = buffer; this.topology = topology; this.finalAgent = finalA; topology.addObserver(this); } /** * Records the contacts that have already received all messages we could * have sent to them. This set contains contacts directed FROM this Node * (this node is their source) */ HashSet<Contact> finishedWithDestinations = new HashSet<Contact>(); public boolean contactIdle(Contact ct) { if (this.parent.getNetwork().vShouldLog(Verbose.DEBUG1)) this.parent.getNetwork().vprint("MEED " + this.parent + " MEEDRouting idleContact: " + ct); // The MEED topology agent should prevent us from getting // idleContact if it is busy getting updates assert !topology.isGettingUpdates(); // If we are not busy getting updates from anyone, and we have not // yet finished with this destination, // place an iterator if (!finishedWithDestinations.contains(ct)) { Iterator<ProtocolStackMessage> i = buffer.iterator(); while (i.hasNext()) { ProtocolStackMessage m = i.next(); Node dest = m.getDestNode(); MEEDDijkstra routing = (MEEDDijkstra) m.getData(MSG_ROUTING); if (routing == null) { routing = topology.routingCache(m); if (parent.routingPolicy != ROUTING_POLICY_TOPOLOGY) { m.storeData(MSG_ROUTING, routing); } } ArrayList<Contact> route = routing.routeTo(dest); // System.out.println("Route: " + route); // If this route uses our contact as the next hop, // ~ System.out.println( "route size " + route.size() ); // ~ if ( route.size() > 0 ) System.out.println( "next // hop = " + route.get(0) + " cost = " + // routingCache().getCost( m.dstNode() ) ); if (route != null && route.size() > 0 && route.get(0) == ct && parent.allowSend(m, ct)) { i.remove(); // Store predicted delivery time (not to be used by // other nodes, but maybe by other protocols/layers // of this node. And statistics. Double cost = routing.getCost(dest); if (m.getSourceNode() == parent && m.getData(MSG_LEFT_SOURCE) == null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -