/// <summary> /// Once the algorithm has finished use the information it has stored to update the routing table. /// </summary> private void UpdateRoutingTable() { IKeyTable <IMLink> oldTable = ForwardingTable; foreach (DijkstraNode target in _confirmed) { if (target.ID != ID) { //Work backwards along the route, starting at the target, until the first hop is found DijkstraNode prev = target; while (prev != null && !Equals(prev.GetPrev(ID))) { prev = prev.GetPrev(ID); } if (prev != null && Links.ContainsKey(prev.ID)) { IMLink l = Links[prev.ID]; SetRoute(Algorithm, target.ID, l, target.GetDistanceFromRoot(ID)); oldTable.Remove(target.ID); } } } //Trigger events for any nodes that can no longer be routed to foreach (IMNodeInternal n in KnownNodes) { if (oldTable.ContainsKey(n.ID)) { RemoveRoute(Algorithm, n.ID); } } }
/// <inhertidoc /> public void AddLink(IMLink link, Parameters parameters) { IMNode neighbour = link.OtherEnd(this); //Add the link referenced by both its own UUID and the ID of the neighbour it connects to lock (_links) { if (!_links.ContainsKey(neighbour.ID)) { _links.Add(neighbour.ID, link); } if (!_links.ContainsKey(link.ID)) { _links.Add(link.ID, link); } } lock (_neighbours) if (!_neighbours.ContainsKey(link.ID)) { _neighbours.Add(link.ID, neighbour); } link.OnWeightChanged += _weightDelegate; if (OnLinkAdded != null) { OnLinkAdded(ID, link, parameters); Logger.Debug(Name + " triggered OnLinkAdded for '" + link.Name + "'."); } }
/// <inhertidoc /> public void TriggerHighlight(string alg, IMNodeInternal target) { if (Equals(_globalHighlightTarget) || Equals(_globalHighlightRoot)) { TriggerHighlightReset(); return; } ClearOld(); _globalTargetKey = target.ID; _globalHighlightTarget = (IMNode)target; _globalHighlightRoot = this; _globalHighlightColour = Colour; _globalHighlightState = HighlghtState.HighlightingSingle; _highlightState = HighlghtState.HighlightingSingle; //If there is a route if (ForwardingTable.ContainsKey(_globalTargetKey)) { lock (HighlightLock) { _highlightedLink = ForwardingTable[_globalTargetKey]; _highlightedLink.Colour = _globalHighlightColour; IMNode node = ForwardingTable[_globalTargetKey].OtherEnd(this); node.Highlight(this); } } else { _highlightedLink = null; } }
/// <summary> /// What to do when a packet relevant to the highlight flooding algorithm is received /// /// If the node has not already received one of the highlight flooding packets flood highlight packets along all links and send a new /// highlight all packet back towards the source of the received packet /// </summary> /// <param name = "packet"></param> public void HighlightAll(IMNodeInternal hop) { if (HighlightingAll) { return; } lock (HighlightLock) { _highlightedLink = ForwardingTable.ContainsKey(_globalTargetKey) ? ForwardingTable[_globalTargetKey] : null; _highlightState = HighlghtState.HighlightingAll; if (_highlightedLink != null) { _highlightedLink.Colour = _globalHighlightColour; } foreach (IMLink l in _links) { IMNode neighbour = l.OtherEnd(this); if (!neighbour.Equals(hop)) { neighbour.HighlightAll(this); } } } }
private void BroadcastUpdate(int TTL, string msg, bool visualise) { if (ShouldPrint(visualise)) { Logger.Info(Name + " DV broadcasting update after '" + msg + "'."); } if (Model.IsPaused && IsCurrentAlgorithm && visualise) { Say("Broadcasting update after " + msg + "."); } foreach (IMNode n in Neighbours) { IMLink l = Links[n.ID]; //Poisoned reverse, don't pass back routes which route via the destination node var v = new DistanceVector(); lock (distanceVector) { foreach (Distance d in distanceVector) { if (!_poison || !d.Link.Equals(l)) //No Poison reverse { v.Add(d.Target.ID, new Distance(d.Target, d.Hop, d.Link, d.Dist)); } else //Poison reverse { v.Add(d.Target.ID, new Distance(d.Target, d.Hop, d.Link, -1f)); } } } v.Add(ID, new Distance(Node, Node, l, 0f)); _forwardMethod(ID, l.ID, new DVPacket(Node, n, v, visualise, TTL)); } }
public void ResetHighlightAll() { _highlightState = HighlghtState.NotHighlighting; if (_highlightedLink != null) { _highlightedLink.Reset(); _highlightedLink = null; } }
protected override void LinkAdded(IMLink link, Parameters parameters, bool visualise) { findShortestPaths(TTL, "'" + link.Name + "' added", visualise); //If there was a packet which was received from the other end of the link that was added before //the link had been added process it. if (_unknownPacket != null && _unknownPacket.S.Equals(link.OtherEnd(ID))) { ProcessPacket(_unknownPacket); _unknownPacket = null; } }
/// <Inheritdoc /> public void Send(IMNodeExternal destination, Parameters parameters) { if (!ForwardingTable.ContainsKey(destination.ID)) { Say("Unable to forward packet to " + destination.Name); return; } IMLink link = ForwardingTable[destination.ID]; SendPacket(ID, link.ID, new MPacket(this, destination, this, parameters)); }
/// <summary> /// Used to specify that the route to a target node is along the specified AddLink /// </summary> /// <param name = "target">The node to map a route to</param> /// <param name = "link">The AddLink along which to pass packets intended for target node</param> public void SetWIPRoute(UUID target, IMLink link) { lock (_wipRoute) { if (_wipRoute.ContainsKey(target)) { _wipRoute[target] = link; } else { _wipRoute.Add(target, link); } } }
protected void RemoveRoute(string alg, UUID target) { if (_table.ContainsKey(target)) { IMLink oldLink = _table[target]; float oldDist = _distances[target]; _table.Remove(target); _distances.Remove(target); if (OnRouteChange != null && IsCurrentAlgorithm) { OnRouteChange(alg, KnownNodes[target], oldLink, null, oldDist, -1f); } } }
/// <summary> /// The main loop which is the body of the algorithm. /// Loops through every neighbour of the current node checking to see if they: /// A. Have been visited before /// B. Have been visited before but are now a shorter route /// </summary> /// <param name="current">The node currently being checked.</param> /// <param name="prev">The previous node that was checked.</param> /// <returns>The last node to be checked.</returns> private void MainLoop(DijkstraNode current, DijkstraNode prev) { while (_cont && current != null && !hitTarget(current)) { //If necessary display text and wait if (_cont && _text && _visualise) { current.Say("4. Iterating through neighbours excluding neighbours in Confirmed"); Pause(); } //Get the current distance to the target float dist = current.GetDistanceFromRoot(ID); foreach (var n in current.Neighbours) { IMLink link = current.Links[n.ID]; if (_visualise) { _links.AddFirst(link); } var neighbour = this.GetAlgNode <DijkstraNode>(n.ID); if (_cont && !_confirmed.Contains(neighbour)) { if (_visualise && _text) { VisualiseCheckNeighbourText(neighbour, current, dist, link); } else if (_visualise) { VisualiseCheckNeighbour(neighbour, current, dist, link); } checkNeighbour(neighbour, current, dist, link); } if (!_cont) { break; } } //Store the old previous node prev = current; if (_cont && _text && _visualise) { Say("Finished iterating through current's (" + current.Name + "'s) neighbours, getting next current from tentative list"); Pause(); } //Get the next node to be checked (the one which has the shortest path to it) current = getNext(current); } FinishedReset(current, prev); }
/// <summary> /// Visualise the process of choosing the next node. Will output text about what is going on if necessary. /// </summary> /// <param name="next">The next node to be current.</param> /// <param name="prev">The node that was previously current.</param> private void VisualiseChooseNext(DijkstraNode next, DijkstraNode prev) { if (_cont && !next.Equals(this)) { if (_cont && _text) { Say("8. There are nodes in the tentative list. Finding the node in tentative with the smallest cost"); Pause(); } Pause(3f); if (_cont && _text) { Say("9. new current = " + next.Name + " with cost " + next.GetDistanceFromRoot(ID)); Pause(); Say("10. Adding link between ct (" + prev.Name + ") and new current (" + next.Name + ") to the shortest path"); Pause(); } } prev.Reset(); IMLink confirmedLink = next.GetWIPRoute(ID); if (_cont && confirmedLink != null) { Pause(6f); confirmedLink.Colour = Color.Red; } if (_cont && _text) { Say((next.Equals(this) ? "2a" : "11a") + ". Adding " + (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ") to Confirmed"); Pause(); Say((next.Equals(this) ? "2b" : "11b") + ". Setting current to " + (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ")"); } next.Reset(); next.Selected = currentGlow; next.Colour = Color.White; if (_cont && _text && !next.Equals(this)) { Pause(); Say("11c. Going to step 4"); Pause(); } }
/// <summary> /// Broadcasts update packets. Iterates through neighbour and as long as the source of the update was not the neighbour sends a flood packet to that neighbour. /// </summary> /// <param name="receivedAlong"></param> /// <param name="msg"></param> /// <param name="evt"></param> /// <param name="visualisePackets"></param> private void BroadcastUpdate(UUID receivedAlong, string msg, int evt, bool visualisePackets) { if (Model.IsPaused && IsCurrentAlgorithm && visualisePackets) { Say("Broadcasting update after " + msg + "."); } foreach (IMNode neighbour in Neighbours) { IMLink link = Links[neighbour.ID]; if (link != null && (!neighbour.ID.Equals(receivedAlong) || !link.IsBidirectional)) { _forwardMethod(ID, link.ID, new LinkStatePacket(Node, Node, neighbour, evt, visualisePackets)); } } }
public Distance(IMNodeInternal target, IMNodeInternal hop, IMLink link, float distance) { if (target == null) throw new Exception("Target node must be set when initialising distance to target"); if (hop == null) throw new Exception("First hop must be set when initialising distance to target"); if (link == null) throw new Exception("First hop link must be set when initialising distance to target"); //if (distance <= 0) // throw new AlgorithmException("Distance must be positive when initialising distance to target"); this.target = target; this.hop = hop; this.link = link; this.distance = distance; }
internal void update(IMNodeInternal hop, IMLink link, float dist) { if (hop == null) { throw new Exception("First hop must be set when updating distance to target"); } if (link == null) { throw new Exception("First hop link must be set when updating distance to target"); } //if (distance <= 0) // throw new AlgorithmException("Distance must be positive when updating distance to target"); this.hop = hop; this.link = link; update(dist); }
private void UpdateRoutes(IMNodeInternal target, IMNodeInternal hop, IMLink link, float dist) { if (target.ID.Equals(ID)) { return; } SetRoute(DV.DV_NAME, target.ID, link, dist); lock (distanceVector) if (!distanceVector.ContainsKey(target.ID)) { distanceVector.Add(target.ID, new Distance(target, hop, link, dist)); } else { distanceVector[target.ID].update(hop, link, dist); } }
private void RouteChangeListener(string alg, IMNodeInternal target, IMLink oldRoute, IMLink newRoute, float oldDist, float dist) { Logger.Debug(Name + " changing route to " + target.Name + ". " + (oldRoute == null ? "No old route" : "Old route: " + oldRoute.Name) + ". " + (newRoute == null ? "No new route" : "New route: " + newRoute.Name)); if (OnForwardingTableChange != null && (oldRoute == null || newRoute == null || !oldRoute.Equals(newRoute) || oldDist != dist)) { OnForwardingTableChange(ID, ForwardingTableList); } //If not highlighting or not highlighting the route that was changed quit if ((oldRoute != null && newRoute != null && oldRoute.Equals(newRoute)) || !GlobalHighlighting || !target.Equals(_globalHighlightTarget) || (GlobalHighlightingSingle && !HighlightingSingle && !Equals(_globalHighlightRoot))) { return; } if (oldRoute != null) { oldRoute.Reset(); if (HighlightingSingle) { oldRoute.OtherEnd(this).ResetHighlight(this); } } if (newRoute != null) { newRoute.Colour = _globalHighlightColour; if (GlobalHighlightingSingle) { _highlightState = HighlghtState.HighlightingSingle; newRoute.OtherEnd(this).Highlight(this); } } else { _highlightState = HighlghtState.NotHighlighting; } _highlightedLink = newRoute; }
/// <summary> /// What to do when notified that it should highlight /// /// Will highlight the link and forward the packet on if necessary /// </summary> /// <param name = "packet">The packet received</param> public void Highlight(IMNodeInternal hop) { _highlightedLink = ForwardingTable.ContainsKey(_globalTargetKey) ? ForwardingTable[_globalTargetKey] : null; if (HighlightingSingle || (_highlightedLink != null && _highlightedLink.OtherEnd(this).Equals(hop))) { return; } lock (HighlightLock) { _highlightState = HighlghtState.HighlightingSingle; if (_highlightedLink != null) { _highlightedLink.Colour = _globalHighlightColour; _highlightedLink.OtherEnd(this).Highlight(this); } } }
public void ResetHighlight(IMNodeInternal hop) { if (Equals(_globalHighlightTarget) || !Highlighting || (_highlightedLink != null && _highlightedLink.OtherEnd(this).Equals(hop))) { return; } lock (HighlightLock) { _highlightState = HighlghtState.NotHighlighting; if (_highlightedLink != null) { _highlightedLink.Reset(); _highlightedLink.OtherEnd(this).ResetHighlight(this); _highlightedLink = null; } } }
public Distance(IMNodeInternal target, IMNodeInternal hop, IMLink link, float distance) { if (target == null) { throw new Exception("Target node must be set when initialising distance to target"); } if (hop == null) { throw new Exception("First hop must be set when initialising distance to target"); } if (link == null) { throw new Exception("First hop link must be set when initialising distance to target"); } //if (distance <= 0) // throw new AlgorithmException("Distance must be positive when initialising distance to target"); this.target = target; this.hop = hop; this.link = link; this.distance = distance; }
protected void SetRoute(string alg, UUID target, IMLink link, float dist) { if (_table.ContainsKey(target)) { IMLink oldLink = _table[target]; float oldDist = _distances[target]; _table[target] = link; _distances[target] = dist; if (OnRouteChange != null && IsCurrentAlgorithm && (!link.Equals(oldLink) || dist != oldDist)) { OnRouteChange(alg, KnownNodes[target], oldLink, link, oldDist, dist); } } else { _table.Add(target, link); _distances.Add(target, dist); if (OnRouteChange != null && IsCurrentAlgorithm) { OnRouteChange(alg, KnownNodes[target], null, link, -1f, dist); } } }
/// <inhertidoc /> public void RemoveLink(UUID l, Parameters parameters) { if (!Neighbours.ContainsKey(l)) { throw new Exception("The link to be remove is not a known link."); } IMNodeInternal neighbour = _neighbours[l]; IMLink link = _links[neighbour.ID]; link.OnWeightChanged -= _weightDelegate; lock (_links) { _links.Remove(neighbour.ID); _links.Remove(l); } lock (_neighbours) _neighbours.Remove(link.ID); if (OnLinkRemoved != null && !parameters.Get <bool>("Clearing")) { OnLinkRemoved(ID, link, parameters); Logger.Debug(Name + " triggered OnLinkRemoved for '" + link.Name + "'."); } }
public void ResetHighlight(IMNodeInternal hop) { if (Equals(_globalHighlightTarget) || !Highlighting || (_highlightedLink != null && _highlightedLink.OtherEnd(this).Equals(hop))) return; lock (HighlightLock) { _highlightState = HighlghtState.NotHighlighting; if (_highlightedLink != null) { _highlightedLink.Reset(); _highlightedLink.OtherEnd(this).ResetHighlight(this); _highlightedLink = null; } } }
public Distance(Distance distance, IMNodeInternal hop, IMLink link, float hopWeight) : this(distance.Target, hop, link, distance.Dist + hopWeight) { }
/// <summary> /// Finds the shortest route to a target. /// /// To start with can be in one of two states: /// A: No route known /// B: There is a route known /// /// Can finish in one of four states /// 1. There was no route originally and one has been found /// 2. There is a new, shorter route along a different link /// 3. The target can no longer be reached but used to be reachable /// 4. The original route is still shortest but is now a different length /// 5. The original route is no longer available but a new route was found /// 6. The original route is still shortest and has not changed /// 7. The target was not reachable before and is still not reachable /// /// 1 = Update distance vector, broadcast update, trigger routing table changed event /// 2 = Update distance vector, broadcast update, trigger routing table changed event /// 3 = Update distance vector, broadcast update, trigger routing table changed event /// 4 = Update distance vector, broadcast update, trigger routing table changed event /// 5 = Update distance vector, broadcast update, trigger routing table changed event /// 6 = No events triggered /// 7 = No events triggered /// </summary> /// <param name="targetNode"></param> /// <returns></returns> private bool findShortestPath(IMNodeInternal targetNode, List <string> changes) { UUID target = targetNode.ID; //oldDist == null indicates initial state A, otherwise initial state B. Distance oldDist; lock (distanceVector) oldDist = distanceVector.ContainsKey(target) ? distanceVector[target].copy() : null; IKeyTable <DistanceVector> tmpNeighbours = neighbourVectors.Copy(); IMLink link = null; float dist = float.MaxValue; if (oldDist != null && oldDist.Link.OtherEnd(ID).Equals(target) && Links.ContainsKey(target)) { //If there was an old route and target is a neighbour and the link was the link between them use the weight of that link as the starting weight link = Links[target]; dist = link.Weight; } else if (oldDist != null && tmpNeighbours.ContainsKey(oldDist.Hop.ID) && tmpNeighbours[oldDist.Hop.ID].ContainsKey(target) && tmpNeighbours[oldDist.Hop.ID][target].Dist > 0f) { //If there was an old route and it involved routing via a neighbour and that neighbour can still route then take the starting weight as the distance to the neighbour + the distance from the neighbour to the target link = Links[oldDist.Hop.ID]; dist = tmpNeighbours[oldDist.Hop.ID][target].Dist + link.Weight; } //Check every neighbour to see if the weight of the link to that neighbour + the distance the neighbour can achieve to the target is shorter . foreach (var neighbour in Neighbours) { var neighbourLink = Links[neighbour.ID]; var neighbourVector = tmpNeighbours.ContainsKey(neighbour.ID) && tmpNeighbours[neighbour.ID].ContainsKey(target) ? tmpNeighbours[neighbour.ID][target] : null; var neighbourDist = neighbourVector != null ? neighbourLink.Weight + neighbourVector.Dist : float.MaxValue; //Neighbour vector distance of 0 or less indicates poison reverse or a link to itself //Also checks to see if the link at the other end is the neighbour and whether the weight of the link is less than the current distance if ((neighbourVector != null && neighbourVector.Dist > 0 && neighbourDist < dist) || neighbour.Equals(targetNode) && neighbourLink.Weight < dist) { link = neighbourLink; dist = neighbour.Equals(targetNode) ? link.Weight : neighbourDist; } } if (link == null && oldDist == null) { //Case 5 + 6 return(false); } if (link != null && oldDist == null) { //1. There was no route originally and one has been found UpdateRoutes(targetNode, link.OtherEnd(Node), link, dist); changes.Add("Distance Vector added route to " + targetNode.Name + " via " + link.OtherEnd(Node).Name + " with distance " + Math.Round(dist, 2) + "."); } else if (link == null && oldDist != null) { //3. The target can no longer be reached but used to be reachable lock (distanceVector) { distanceVector.Remove(target); RemoveRoute(DV.DV_NAME, target); changes.Add("Distance Vector removed route to " + targetNode.Name + ". " + oldDist.Hop.Name + " is no longer a valid first hop and no other route was found."); } } else if (oldDist != null && !link.Equals(oldDist.Link)) { //2. There is a new, shorter route along a different link UpdateRoutes(targetNode, link.OtherEnd(Node), link, dist); changes.Add("Distance Vector changed route to " + targetNode.Name + " from " + oldDist.Hop.Name + " to " + link.OtherEnd(Node).Name + " with distance " + Math.Round(dist, 2) + "."); } else if (oldDist != null && link.Equals(oldDist.Link) && dist != oldDist.Dist) { //4. The original route is still shortest but is now a different length UpdateRoutes(targetNode, link.OtherEnd(Node), link, dist); changes.Add("Distance Vector changed weight of route to " + targetNode.Name + " from " + Math.Round(oldDist.Dist, 2) + " to " + Math.Round(dist, 2) + "."); } else { return(false); } return(true); }
/// <summary> /// Visualises the process of checking a neighbour node. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void VisualiseCheckNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { if (!_visualise) return; if (_cont) { Pause(4f); link.Colour = Color.Blue; Pause(6); } try { if (_cont && !_tentative.Contains(neighbour)) { neighbour.Selected = tentativeGlow; Pause(6); } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) VisualisedNode = null; Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } if (_cont) link.Colour = Color.White; }
protected override void WeightChanged(IMLink link, bool visualise) { OnChange("Link to '" + link.Name + "' changed weight to " + link.Weight, link.ID, Node.Parameters, visualise); }
internal void SetDistanceFromRoot(UUID root, float value, DijkstraNode prevNode, IMLink link) { //if (prevNode != null/* && !Links.ContainsKey(prevNode.ID)*/) // return; lock (_distances) { if (_distances.ContainsKey(root)) { _distances[root] = value; _prev[root] = prevNode; } else { _distances.Add(root, value); _prev.Add(root, prevNode); } } if (prevNode != null) SetWIPRoute(root, link); }
/// <summary> /// What to do when notified that it should highlight /// /// Will highlight the link and forward the packet on if necessary /// </summary> /// <param name = "packet">The packet received</param> public void Highlight(IMNodeInternal hop) { _highlightedLink = ForwardingTable.ContainsKey(_globalTargetKey) ? ForwardingTable[_globalTargetKey] : null; if (HighlightingSingle || (_highlightedLink != null && _highlightedLink.OtherEnd(this).Equals(hop))) return; lock (HighlightLock) { _highlightState = HighlghtState.HighlightingSingle; if (_highlightedLink != null) { _highlightedLink.Colour = _globalHighlightColour; _highlightedLink.OtherEnd(this).Highlight(this); } } }
private void UpdateRoutes(IMNodeInternal target, IMNodeInternal hop, IMLink link, float dist) { if (target.ID.Equals(ID)) return; SetRoute(DV.DV_NAME, target.ID, link, dist); lock (distanceVector) if (!distanceVector.ContainsKey(target.ID)) distanceVector.Add(target.ID, new Distance(target, hop, link, dist)); else distanceVector[target.ID].update(hop, link, dist); }
internal void SetDistanceFromRoot(UUID root, float value, DijkstraNode prevNode, IMLink link) { //if (prevNode != null/* && !Links.ContainsKey(prevNode.ID)*/) // return; lock (_distances) { if (_distances.ContainsKey(root)) { _distances[root] = value; _prev[root] = prevNode; } else { _distances.Add(root, value); _prev.Add(root, prevNode); } } if (prevNode != null) { SetWIPRoute(root, link); } }
protected override void LinkRemoved(IMLink link, Parameters parameters, bool visualise) { OnChange("Link to '" + link.OtherEnd(Node).Name + "' removed", link.ID, parameters, visualise); }
/// <summary> /// Used to specify that the route to a target node is along the specified AddLink /// </summary> /// <param name = "target">The node to map a route to</param> /// <param name = "link">The AddLink along which to pass packets intended for target node</param> public void SetWIPRoute(UUID target, IMLink link) { lock (_wipRoute) { if (_wipRoute.ContainsKey(target)) _wipRoute[target] = link; else _wipRoute.Add(target, link); } }
/// <inhertidoc /> public void TriggerHighlight(string alg, IMNodeInternal target) { if (Equals(_globalHighlightTarget) || Equals(_globalHighlightRoot)) { TriggerHighlightReset(); return; } ClearOld(); _globalTargetKey = target.ID; _globalHighlightTarget = (IMNode)target; _globalHighlightRoot = this; _globalHighlightColour = Colour; _globalHighlightState = HighlghtState.HighlightingSingle; _highlightState = HighlghtState.HighlightingSingle; //If there is a route if (ForwardingTable.ContainsKey(_globalTargetKey)) { lock (HighlightLock) { _highlightedLink = ForwardingTable[_globalTargetKey]; _highlightedLink.Colour = _globalHighlightColour; IMNode node = ForwardingTable[_globalTargetKey].OtherEnd(this); node.Highlight(this); } } else _highlightedLink = null; }
internal void update(IMNodeInternal hop, IMLink link, float dist) { if (hop == null) throw new Exception("First hop must be set when updating distance to target"); if (link == null) throw new Exception("First hop link must be set when updating distance to target"); //if (distance <= 0) // throw new AlgorithmException("Distance must be positive when updating distance to target"); this.hop = hop; this.link = link; update(dist); }
/// <summary> /// Check a neighbour of the current node to see if it needs to be added to the tentative list /// or the shortest route to it needs to be updated. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void checkNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { float newDistance = dist + link.Weight; try { //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour if (_cont && !_tentative.Contains(neighbour)) { _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) VisualisedNode = null; Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } //Incase another thread has modified the distance if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); }
protected override void WeightChanged(IMLink link, bool visualise) { findShortestPaths(TTL, "'" + link.Name + "' weight changed to " + link.Weight, visualise); }
/// <summary> /// Visualises the process of checking a neighbour node and prints out text explaining what is happening. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void VisualiseCheckNeighbourText(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { if (!_visualise && !_text) return; float newDistance = dist + link.Weight; if (_cont) { //if (_cont && _text) // current.Say("Examining neighbour " + neighbour.Name); Pause(4f); link.Colour = Color.Blue; if (_cont && _text) { Pause(); current.Say("5. Test cost to " + neighbour.Name + " = " + dist + " + " + link.Weight + " = " + newDistance); Pause(); } Pause(4f); } try { if (_cont && !_tentative.Contains(neighbour)) { if (_cont && _text) current.Say(neighbour.Name + " is not in tentative list"); _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont) { Pause(4f); neighbour.Selected = tentativeGlow; if (_cont && _text) { current.Say("6a. Adding " + neighbour.Name + " to the tentative list"); Pause(); current.Say("6b. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); } } } //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont && _text) { current.Say(neighbour.Name + ".cost (" + neighbour.GetDistanceFromRoot(ID) + ") > test cost (" + newDistance + ")"); Pause(); current.Say("7. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); Pause(); } } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) VisualisedNode = null; Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); if (_cont) { Pause(4f); link.Colour = Color.White; Pause(6f); } }
protected override void LinkRemoved(IMLink link, Parameters parameters, bool visualise) { lock (neighbourVectors) neighbourVectors.Remove(link.OtherEnd(ID)); findShortestPaths(TTL, "'" + link.Name + "' removed", visualise); }
/// <inhertidoc /> public void AddLink(IMLink link, Parameters parameters) { IMNode neighbour = link.OtherEnd(this); //Add the link referenced by both its own UUID and the ID of the neighbour it connects to lock (_links) { if (!_links.ContainsKey(neighbour.ID)) _links.Add(neighbour.ID, link); if (!_links.ContainsKey(link.ID)) _links.Add(link.ID, link); } lock (_neighbours) if (!_neighbours.ContainsKey(link.ID)) _neighbours.Add(link.ID, neighbour); link.OnWeightChanged += _weightDelegate; if (OnLinkAdded != null) { OnLinkAdded(ID, link, parameters); Logger.Debug(Name + " triggered OnLinkAdded for '" + link.Name + "'."); } }
private void PrintDistanceVector(string msg) { string spacer = "|"; String infinity = "-1"; int colWidth = NAME_WIDTH + spacer.Length + 1; //Column header msg = "\n" + Name + " (DV): " + msg; msg += "\n"; for (int i = 0; i < NAME_WIDTH; i++) { msg += "#"; } msg += spacer + " "; msg += getCol(Name, colWidth); lock (distanceVector) foreach (Distance d in distanceVector) { msg += getCol(d.Target.Name, colWidth); } //Divider msg += "\n"; for (int i = 0; i < colWidth * (distanceVector.Count + 2); i++) { msg += "_"; } //Row for this node msg += "\n" + getCol(Name, NAME_WIDTH) + spacer + " "; msg += getCol("0", colWidth); lock (distanceVector) foreach (Distance d in distanceVector) { msg += getCol(d.Dist + "", colWidth); } //Row for neighbour vectors foreach (IMNodeInternal neighbour in Neighbours) { IMLink l = Links[neighbour.ID]; UUID y = neighbour.ID; if (!neighbourVectors.ContainsKey(y)) { continue; } msg += "\n" + getCol(neighbour.Name, NAME_WIDTH) + spacer + " "; msg += getNeighbourCol(ID, y, colWidth, infinity); lock (distanceVector) foreach (Distance d in distanceVector) { var x = d.Target; if (neighbourVectors[y].ContainsKey(x.ID)) { msg += getNeighbourCol(x.ID, y, colWidth, infinity); } else { msg += getCol("", NAME_WIDTH) + spacer + " "; } } } //Logger.Debug(msg + "\n"); Console.WriteLine(msg); }
/// <summary> /// What to do when a packet relevant to the highlight flooding algorithm is received /// /// If the node has not already received one of the highlight flooding packets flood highlight packets along all links and send a new /// highlight all packet back towards the source of the received packet /// </summary> /// <param name = "packet"></param> public void HighlightAll(IMNodeInternal hop) { if (HighlightingAll) return; lock (HighlightLock) { _highlightedLink = ForwardingTable.ContainsKey(_globalTargetKey) ? ForwardingTable[_globalTargetKey] : null; _highlightState = HighlghtState.HighlightingAll; if (_highlightedLink != null) _highlightedLink.Colour = _globalHighlightColour; foreach (IMLink l in _links) { IMNode neighbour = l.OtherEnd(this); if (!neighbour.Equals(hop)) neighbour.HighlightAll(this); } } }
/// <summary> /// Check a neighbour of the current node to see if it needs to be added to the tentative list /// or the shortest route to it needs to be updated. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void checkNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { float newDistance = dist + link.Weight; try { //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour if (_cont && !_tentative.Contains(neighbour)) { _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) { VisualisedNode = null; } Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } //Incase another thread has modified the distance if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); } }
/// <summary> /// Visualises the process of checking a neighbour node. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void VisualiseCheckNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { if (!_visualise) { return; } if (_cont) { Pause(4f); link.Colour = Color.Blue; Pause(6); } try { if (_cont && !_tentative.Contains(neighbour)) { neighbour.Selected = tentativeGlow; Pause(6); } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) { VisualisedNode = null; } Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } if (_cont) { link.Colour = Color.White; } }
private void RouteChangeListener(string alg, IMNodeInternal target, IMLink oldRoute, IMLink newRoute, float oldDist, float dist) { Logger.Debug(Name + " changing route to " + target.Name + ". " + (oldRoute == null ? "No old route" : "Old route: " + oldRoute.Name) + ". " + (newRoute == null ? "No new route" : "New route: " + newRoute.Name)); if (OnForwardingTableChange != null && (oldRoute == null || newRoute == null || !oldRoute.Equals(newRoute) || oldDist != dist)) OnForwardingTableChange(ID, ForwardingTableList); //If not highlighting or not highlighting the route that was changed quit if ((oldRoute != null && newRoute != null && oldRoute.Equals(newRoute)) || !GlobalHighlighting || !target.Equals(_globalHighlightTarget) || (GlobalHighlightingSingle && !HighlightingSingle && !Equals(_globalHighlightRoot))) return; if (oldRoute != null) { oldRoute.Reset(); if (HighlightingSingle) oldRoute.OtherEnd(this).ResetHighlight(this); } if (newRoute != null) { newRoute.Colour = _globalHighlightColour; if (GlobalHighlightingSingle) { _highlightState = HighlghtState.HighlightingSingle; newRoute.OtherEnd(this).Highlight(this); } } else _highlightState = HighlghtState.NotHighlighting; _highlightedLink = newRoute; }
/// <summary> /// Visualises the process of checking a neighbour node and prints out text explaining what is happening. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void VisualiseCheckNeighbourText(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { if (!_visualise && !_text) { return; } float newDistance = dist + link.Weight; if (_cont) { //if (_cont && _text) // current.Say("Examining neighbour " + neighbour.Name); Pause(4f); link.Colour = Color.Blue; if (_cont && _text) { Pause(); current.Say("5. Test cost to " + neighbour.Name + " = " + dist + " + " + link.Weight + " = " + newDistance); Pause(); } Pause(4f); } try { if (_cont && !_tentative.Contains(neighbour)) { if (_cont && _text) { current.Say(neighbour.Name + " is not in tentative list"); } _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont) { Pause(4f); neighbour.Selected = tentativeGlow; if (_cont && _text) { current.Say("6a. Adding " + neighbour.Name + " to the tentative list"); Pause(); current.Say("6b. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); } } } //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont && _text) { current.Say(neighbour.Name + ".cost (" + neighbour.GetDistanceFromRoot(ID) + ") > test cost (" + newDistance + ")"); Pause(); current.Say("7. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); Pause(); } } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) { VisualisedNode = null; } Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); } if (_cont) { Pause(4f); link.Colour = Color.White; Pause(6f); } }