tom

Check-point before refactoring the topology provider stuff.

1 -package org.onlab.onos.cli;
2 -
3 -import org.apache.karaf.shell.commands.Argument;
4 -import org.apache.karaf.shell.commands.Command;
5 -import org.onlab.onos.GreetService;
6 -
7 -/**
8 - * Simple command example to demonstrate use of Karaf shell extensions; shows
9 - * use of an optional parameter as well.
10 - */
11 -@Command(scope = "onos", name = "greet", description = "Issues a greeting")
12 -public class GreetCommand extends AbstractShellCommand {
13 -
14 - @Argument(index = 0, name = "name", description = "Name to greet",
15 - required = false, multiValued = false)
16 - String name = "dude";
17 -
18 - @Override
19 - protected Object doExecute() throws Exception {
20 - print(getService(GreetService.class).yo(name));
21 - return null;
22 - }
23 -}
1 -package org.onlab.onos.cli;
2 -
3 -import org.apache.karaf.shell.console.Completer;
4 -import org.apache.karaf.shell.console.completer.StringsCompleter;
5 -import org.onlab.onos.GreetService;
6 -
7 -import java.util.Iterator;
8 -import java.util.List;
9 -import java.util.SortedSet;
10 -
11 -/**
12 - * Simple example of a command-line parameter completer.
13 - * For a more open-ended sets a more efficient implementation would be required.
14 - */
15 -public class NameCompleter implements Completer {
16 - @Override
17 - public int complete(String buffer, int cursor, List<String> candidates) {
18 - // Delegate string completer
19 - StringsCompleter delegate = new StringsCompleter();
20 -
21 - // Fetch our service and feed it's offerings to the string completer
22 - GreetService greetService = AbstractShellCommand.get(GreetService.class);
23 - Iterator<String> it = greetService.names().iterator();
24 - SortedSet<String> strings = delegate.getStrings();
25 - while (it.hasNext()) {
26 - strings.add(it.next());
27 - }
28 -
29 - // Now let the completer do the work for figuring out what to offer.
30 - return delegate.complete(buffer, cursor, candidates);
31 - }
32 -
33 -}
...@@ -30,18 +30,9 @@ ...@@ -30,18 +30,9 @@
30 <ref component-id="deviceIdCompleter"/> 30 <ref component-id="deviceIdCompleter"/>
31 </completers> 31 </completers>
32 </command> 32 </command>
33 -
34 - <command>
35 - <action class="org.onlab.onos.cli.GreetCommand"/>
36 - <completers>
37 - <ref component-id="nameCompleter"/>
38 - </completers>
39 - </command>
40 </command-bundle> 33 </command-bundle>
41 34
42 <bean id="deviceIdCompleter" class="org.onlab.onos.cli.net.DeviceIdCompleter"/> 35 <bean id="deviceIdCompleter" class="org.onlab.onos.cli.net.DeviceIdCompleter"/>
43 <bean id="roleCompleter" class="org.onlab.onos.cli.net.RoleCompleter"/> 36 <bean id="roleCompleter" class="org.onlab.onos.cli.net.RoleCompleter"/>
44 37
45 - <bean id="nameCompleter" class="org.onlab.onos.cli.NameCompleter"/>
46 -
47 </blueprint> 38 </blueprint>
......
1 package org.onlab.onos.net.topology; 1 package org.onlab.onos.net.topology;
2 2
3 +import com.google.common.collect.ImmutableMap;
4 +import com.google.common.collect.ImmutableSet;
5 +import com.google.common.collect.ImmutableSetMultimap;
3 import org.onlab.graph.Graph; 6 import org.onlab.graph.Graph;
4 -import org.onlab.graph.GraphPathSearch;
5 import org.onlab.onos.net.Description; 7 import org.onlab.onos.net.Description;
6 import org.onlab.onos.net.DeviceId; 8 import org.onlab.onos.net.DeviceId;
7 import org.onlab.onos.net.Link; 9 import org.onlab.onos.net.Link;
8 10
9 -import java.util.Set; 11 +import static org.onlab.graph.GraphPathSearch.Result;
10 12
11 /** 13 /**
12 * Describes attribute(s) of a network topology. 14 * Describes attribute(s) of a network topology.
...@@ -22,50 +24,39 @@ public interface TopologyDescription extends Description { ...@@ -22,50 +24,39 @@ public interface TopologyDescription extends Description {
22 long timestamp(); 24 long timestamp();
23 25
24 /** 26 /**
25 - * Returns the topology graph. 27 + * Returns the topology graph in immutable form.
26 * 28 *
27 * @return network graph 29 * @return network graph
28 */ 30 */
29 Graph<TopoVertex, TopoEdge> graph(); 31 Graph<TopoVertex, TopoEdge> graph();
30 32
31 /** 33 /**
32 - * Returns the results of the path search through the network graph. This 34 + * Returns an immutable map of path search results for each source device.
33 - * is assumed to contain results of seach fro the given device to all
34 - * other devices.
35 * 35 *
36 - * @param srcDeviceId source device identifier 36 + * @return map of path search result for each source node
37 - * @return path search result for the given source node
38 */ 37 */
39 - GraphPathSearch.Result pathResults(DeviceId srcDeviceId); 38 + ImmutableMap<DeviceId, Result<TopoVertex, TopoEdge>> pathsBySource();
40 39
41 /** 40 /**
42 * Returns the set of topology SCC clusters. 41 * Returns the set of topology SCC clusters.
43 * 42 *
44 * @return set of SCC clusters 43 * @return set of SCC clusters
45 */ 44 */
46 - Set<TopologyCluster> clusters(); 45 + ImmutableSet<TopologyCluster> clusters();
47 46
48 /** 47 /**
49 - * Returns the set of devices contained by the specified topology cluster. 48 + * Returns an immutable set multi-map of devices for each cluster.
50 * 49 *
51 - * @return set of devices that belong to the specified cluster 50 + * @return set multi-map of devices that belong to each cluster
52 */ 51 */
53 - Set<DeviceId> clusterDevices(TopologyCluster cluster); 52 + ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster();
54 53
55 /** 54 /**
56 - * Returns the set of infrastructure links contained by the specified cluster. 55 + * Returns an immutable set multi-map of links for each cluster.
57 * 56 *
58 - * @return set of links that form the given cluster 57 + * @return set multi-map of links that belong to each cluster
59 */ 58 */
60 - Set<Link> clusterLinks(TopologyCluster cluster); 59 + ImmutableSetMultimap<TopologyCluster, Link> linksByCluster();
61 -
62 - /**
63 - * Returns the topology SCC cluster which contains the given device.
64 - *
65 - * @param deviceId device identifier
66 - * @return topology cluster that contains the specified device
67 - */
68 - TopologyCluster clusterFor(DeviceId deviceId);
69 60
70 } 61 }
71 62
......
...@@ -21,6 +21,7 @@ public interface TopologyService { ...@@ -21,6 +21,7 @@ public interface TopologyService {
21 21
22 /** 22 /**
23 * Indicates whether the specified topology is the latest or not. 23 * Indicates whether the specified topology is the latest or not.
24 + *
24 * @param topology topology descriptor 25 * @param topology topology descriptor
25 * @return true if the topology is the most recent; false otherwise 26 * @return true if the topology is the most recent; false otherwise
26 */ 27 */
......
1 package org.onlab.onos.net.trivial.topology.impl; 1 package org.onlab.onos.net.trivial.topology.impl;
2 2
3 +import com.google.common.collect.ImmutableMap;
4 +import com.google.common.collect.ImmutableSet;
5 +import com.google.common.collect.ImmutableSetMultimap;
6 +import org.onlab.graph.Graph;
7 +import org.onlab.graph.GraphPathSearch;
3 import org.onlab.onos.net.AbstractModel; 8 import org.onlab.onos.net.AbstractModel;
9 +import org.onlab.onos.net.ConnectPoint;
10 +import org.onlab.onos.net.DeviceId;
11 +import org.onlab.onos.net.Link;
12 +import org.onlab.onos.net.Path;
4 import org.onlab.onos.net.provider.ProviderId; 13 import org.onlab.onos.net.provider.ProviderId;
14 +import org.onlab.onos.net.topology.TopoEdge;
15 +import org.onlab.onos.net.topology.TopoVertex;
5 import org.onlab.onos.net.topology.Topology; 16 import org.onlab.onos.net.topology.Topology;
17 +import org.onlab.onos.net.topology.TopologyCluster;
18 +import org.onlab.onos.net.topology.TopologyDescription;
19 +
20 +import java.util.Set;
6 21
7 /** 22 /**
8 * Default implementation of the topology descriptor. This carries the 23 * Default implementation of the topology descriptor. This carries the
...@@ -11,29 +26,33 @@ import org.onlab.onos.net.topology.Topology; ...@@ -11,29 +26,33 @@ import org.onlab.onos.net.topology.Topology;
11 public class DefaultTopology extends AbstractModel implements Topology { 26 public class DefaultTopology extends AbstractModel implements Topology {
12 27
13 private final long time; 28 private final long time;
14 - private final int clusterCount;
15 - private final int deviceCount;
16 - private final int linkCount;
17 private final int pathCount; 29 private final int pathCount;
18 30
31 + private final Graph<TopoVertex, TopoEdge> graph;
32 + private final ImmutableMap<DeviceId, GraphPathSearch.Result<TopoVertex, TopoEdge>> results;
33 +
34 + private final ImmutableSet<TopologyCluster> clusters;
35 + private final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
36 + private final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
37 + private final ImmutableSet connectPoints;
38 +
19 /** 39 /**
20 * Creates a topology descriptor attributed to the specified provider. 40 * Creates a topology descriptor attributed to the specified provider.
21 * 41 *
22 - * @param providerId identity of the provider 42 + * @param providerId identity of the provider
23 - * @param time creation time in system nanos 43 + * @param description data describing the new topology
24 - * @param clusterCount number of clusters
25 - * @param deviceCount number of devices
26 - * @param linkCount number of links
27 - * @param pathCount number of pre-computed paths
28 */ 44 */
29 - DefaultTopology(ProviderId providerId, long time, int clusterCount, 45 + DefaultTopology(ProviderId providerId, TopologyDescription description) {
30 - int deviceCount, int linkCount, int pathCount) {
31 super(providerId); 46 super(providerId);
32 - this.time = time; 47 + this.time = description.timestamp();
33 - this.clusterCount = clusterCount; 48 + this.graph = description.graph();
34 - this.deviceCount = deviceCount; 49 + this.results = description.pathsBySource();
35 - this.linkCount = linkCount; 50 + this.clusters = description.clusters();
36 - this.pathCount = pathCount; 51 + this.devicesByCluster = description.devicesByCluster();
52 + this.linksByCluster = description.linksByCluster();
53 +
54 + this.connectPoints = ImmutableSet.of();
55 + this.pathCount = 0;
37 } 56 }
38 57
39 @Override 58 @Override
...@@ -43,17 +62,17 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -43,17 +62,17 @@ public class DefaultTopology extends AbstractModel implements Topology {
43 62
44 @Override 63 @Override
45 public int clusterCount() { 64 public int clusterCount() {
46 - return clusterCount; 65 + return clusters.size();
47 } 66 }
48 67
49 @Override 68 @Override
50 public int deviceCount() { 69 public int deviceCount() {
51 - return deviceCount; 70 + return graph.getVertexes().size();
52 } 71 }
53 72
54 @Override 73 @Override
55 public int linkCount() { 74 public int linkCount() {
56 - return linkCount; 75 + return graph.getEdges().size();
57 } 76 }
58 77
59 @Override 78 @Override
...@@ -61,4 +80,23 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -61,4 +80,23 @@ public class DefaultTopology extends AbstractModel implements Topology {
61 return pathCount; 80 return pathCount;
62 } 81 }
63 82
83 + Set<TopologyCluster> getClusters() {
84 + return clusters;
85 + }
86 +
87 + Graph<TopoVertex, TopoEdge> getGraph() {
88 + return graph;
89 + }
90 +
91 + boolean isInfrastructure(ConnectPoint connectPoint) {
92 + return connectPoints.contains(connectPoint);
93 + }
94 +
95 + boolean isInBroadcastTree(ConnectPoint connectPoint) {
96 + return false;
97 + }
98 +
99 + Set<Path> getPaths(DeviceId src, DeviceId dst) {
100 + return null; // pointToPointPaths.get(key(src, dst));
101 + }
64 } 102 }
......
...@@ -79,19 +79,28 @@ public class SimpleTopologyManager ...@@ -79,19 +79,28 @@ public class SimpleTopologyManager
79 @Override 79 @Override
80 public boolean isLatest(Topology topology) { 80 public boolean isLatest(Topology topology) {
81 checkNotNull(topology, TOPOLOGY_NULL); 81 checkNotNull(topology, TOPOLOGY_NULL);
82 - return store.isLatest(topology); 82 + return store.isLatest(defaultTopology(topology));
83 + }
84 +
85 + // Validates the specified topology and returns it as a default
86 + private DefaultTopology defaultTopology(Topology topology) {
87 + if (topology instanceof DefaultTopology) {
88 + return (DefaultTopology) topology;
89 + }
90 + throw new IllegalArgumentException("Topology class " + topology.getClass() +
91 + " not supported");
83 } 92 }
84 93
85 @Override 94 @Override
86 public Set<TopologyCluster> getClusters(Topology topology) { 95 public Set<TopologyCluster> getClusters(Topology topology) {
87 checkNotNull(topology, TOPOLOGY_NULL); 96 checkNotNull(topology, TOPOLOGY_NULL);
88 - return store.getClusters(topology); 97 + return store.getClusters(defaultTopology(topology));
89 } 98 }
90 99
91 @Override 100 @Override
92 public Graph<TopoVertex, TopoEdge> getGraph(Topology topology) { 101 public Graph<TopoVertex, TopoEdge> getGraph(Topology topology) {
93 checkNotNull(topology, TOPOLOGY_NULL); 102 checkNotNull(topology, TOPOLOGY_NULL);
94 - return store.getGraph(topology); 103 + return store.getGraph(defaultTopology(topology));
95 } 104 }
96 105
97 @Override 106 @Override
...@@ -99,7 +108,7 @@ public class SimpleTopologyManager ...@@ -99,7 +108,7 @@ public class SimpleTopologyManager
99 checkNotNull(topology, TOPOLOGY_NULL); 108 checkNotNull(topology, TOPOLOGY_NULL);
100 checkNotNull(src, DEVICE_ID_NULL); 109 checkNotNull(src, DEVICE_ID_NULL);
101 checkNotNull(dst, DEVICE_ID_NULL); 110 checkNotNull(dst, DEVICE_ID_NULL);
102 - return store.getPaths(topology, src, dst); 111 + return store.getPaths(defaultTopology(topology), src, dst);
103 } 112 }
104 113
105 @Override 114 @Override
...@@ -108,21 +117,21 @@ public class SimpleTopologyManager ...@@ -108,21 +117,21 @@ public class SimpleTopologyManager
108 checkNotNull(src, DEVICE_ID_NULL); 117 checkNotNull(src, DEVICE_ID_NULL);
109 checkNotNull(dst, DEVICE_ID_NULL); 118 checkNotNull(dst, DEVICE_ID_NULL);
110 checkNotNull(weight, "Link weight cannot be null"); 119 checkNotNull(weight, "Link weight cannot be null");
111 - return store.getPaths(topology, src, dst, weight); 120 + return store.getPaths(defaultTopology(topology), src, dst, weight);
112 } 121 }
113 122
114 @Override 123 @Override
115 public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { 124 public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) {
116 checkNotNull(topology, TOPOLOGY_NULL); 125 checkNotNull(topology, TOPOLOGY_NULL);
117 checkNotNull(connectPoint, CONNECTION_POINT_NULL); 126 checkNotNull(connectPoint, CONNECTION_POINT_NULL);
118 - return store.isInfrastructure(topology, connectPoint); 127 + return store.isInfrastructure(defaultTopology(topology), connectPoint);
119 } 128 }
120 129
121 @Override 130 @Override
122 public boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) { 131 public boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) {
123 checkNotNull(topology, TOPOLOGY_NULL); 132 checkNotNull(topology, TOPOLOGY_NULL);
124 checkNotNull(connectPoint, CONNECTION_POINT_NULL); 133 checkNotNull(connectPoint, CONNECTION_POINT_NULL);
125 - return store.isInBroadcastTree(topology, connectPoint); 134 + return store.isInBroadcastTree(defaultTopology(topology), connectPoint);
126 } 135 }
127 136
128 @Override 137 @Override
...@@ -156,7 +165,8 @@ public class SimpleTopologyManager ...@@ -156,7 +165,8 @@ public class SimpleTopologyManager
156 165
157 log.info("Topology changed due to: {}", // to be removed soon 166 log.info("Topology changed due to: {}", // to be removed soon
158 reasons == null ? "initial compute" : reasons); 167 reasons == null ? "initial compute" : reasons);
159 - TopologyEvent event = store.updateTopology(topoDescription, reasons); 168 + TopologyEvent event = store.updateTopology(provider().id(),
169 + topoDescription, reasons);
160 if (event != null) { 170 if (event != null) {
161 log.info("Topology changed due to: {}", 171 log.info("Topology changed due to: {}",
162 reasons == null ? "initial compute" : reasons); 172 reasons == null ? "initial compute" : reasons);
......
...@@ -5,6 +5,7 @@ import org.onlab.onos.event.Event; ...@@ -5,6 +5,7 @@ import org.onlab.onos.event.Event;
5 import org.onlab.onos.net.ConnectPoint; 5 import org.onlab.onos.net.ConnectPoint;
6 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
7 import org.onlab.onos.net.Path; 7 import org.onlab.onos.net.Path;
8 +import org.onlab.onos.net.provider.ProviderId;
8 import org.onlab.onos.net.topology.LinkWeight; 9 import org.onlab.onos.net.topology.LinkWeight;
9 import org.onlab.onos.net.topology.TopoEdge; 10 import org.onlab.onos.net.topology.TopoEdge;
10 import org.onlab.onos.net.topology.TopoVertex; 11 import org.onlab.onos.net.topology.TopoVertex;
...@@ -50,8 +51,8 @@ class SimpleTopologyStore { ...@@ -50,8 +51,8 @@ class SimpleTopologyStore {
50 * @param topology topology descriptor 51 * @param topology topology descriptor
51 * @return set of clusters 52 * @return set of clusters
52 */ 53 */
53 - Set<TopologyCluster> getClusters(Topology topology) { 54 + Set<TopologyCluster> getClusters(DefaultTopology topology) {
54 - return null; 55 + return topology.getClusters();
55 } 56 }
56 57
57 /** 58 /**
...@@ -60,8 +61,8 @@ class SimpleTopologyStore { ...@@ -60,8 +61,8 @@ class SimpleTopologyStore {
60 * @param topology topology descriptor 61 * @param topology topology descriptor
61 * @return graph view 62 * @return graph view
62 */ 63 */
63 - Graph<TopoVertex, TopoEdge> getGraph(Topology topology) { 64 + Graph<TopoVertex, TopoEdge> getGraph(DefaultTopology topology) {
64 - return null; 65 + return topology.getGraph();
65 } 66 }
66 67
67 /** 68 /**
...@@ -72,8 +73,8 @@ class SimpleTopologyStore { ...@@ -72,8 +73,8 @@ class SimpleTopologyStore {
72 * @param dst destination device 73 * @param dst destination device
73 * @return set of shortest paths 74 * @return set of shortest paths
74 */ 75 */
75 - Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) { 76 + Set<Path> getPaths(DefaultTopology topology, DeviceId src, DeviceId dst) {
76 - return null; 77 + return topology.getPaths(src, dst);
77 } 78 }
78 79
79 /** 80 /**
...@@ -85,7 +86,7 @@ class SimpleTopologyStore { ...@@ -85,7 +86,7 @@ class SimpleTopologyStore {
85 * @param weight link weight function 86 * @param weight link weight function
86 * @return set of shortest paths 87 * @return set of shortest paths
87 */ 88 */
88 - Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, 89 + Set<Path> getPaths(DefaultTopology topology, DeviceId src, DeviceId dst,
89 LinkWeight weight) { 90 LinkWeight weight) {
90 return null; 91 return null;
91 } 92 }
...@@ -97,8 +98,8 @@ class SimpleTopologyStore { ...@@ -97,8 +98,8 @@ class SimpleTopologyStore {
97 * @param connectPoint connection point 98 * @param connectPoint connection point
98 * @return true if infrastructure; false otherwise 99 * @return true if infrastructure; false otherwise
99 */ 100 */
100 - boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { 101 + boolean isInfrastructure(DefaultTopology topology, ConnectPoint connectPoint) {
101 - return false; 102 + return topology.isInfrastructure(connectPoint);
102 } 103 }
103 104
104 /** 105 /**
...@@ -108,20 +109,34 @@ class SimpleTopologyStore { ...@@ -108,20 +109,34 @@ class SimpleTopologyStore {
108 * @param connectPoint connection point 109 * @param connectPoint connection point
109 * @return true if in broadcast tree; false otherwise 110 * @return true if in broadcast tree; false otherwise
110 */ 111 */
111 - boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) { 112 + boolean isInBroadcastTree(DefaultTopology topology, ConnectPoint connectPoint) {
112 - return false; 113 + return topology.isInBroadcastTree(connectPoint);
113 } 114 }
114 115
115 /** 116 /**
116 * Generates a new topology snapshot from the specified description. 117 * Generates a new topology snapshot from the specified description.
117 * 118 *
119 + * @param providerId provider identification
118 * @param topoDescription topology description 120 * @param topoDescription topology description
119 * @param reasons list of events that triggered the update 121 * @param reasons list of events that triggered the update
120 * @return topology update event or null if the description is old 122 * @return topology update event or null if the description is old
121 */ 123 */
122 - TopologyEvent updateTopology(TopologyDescription topoDescription, 124 + TopologyEvent updateTopology(ProviderId providerId,
125 + TopologyDescription topoDescription,
123 List<Event> reasons) { 126 List<Event> reasons) {
124 - return null; 127 + // First off, make sure that what we're given is indeed newer than
128 + // what we already have.
129 + if (current != null && topoDescription.timestamp() < current.time()) {
130 + return null;
131 + }
132 +
133 + // Have the default topology construct self from the description data.
134 + DefaultTopology newTopology =
135 + new DefaultTopology(providerId, topoDescription);
136 +
137 + // Promote the new topology to current and return a ready-to-send event.
138 + current = newTopology;
139 + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current);
125 } 140 }
126 141
127 } 142 }
......
1 package org.onlab.onos.net.trivial.topology.provider.impl; 1 package org.onlab.onos.net.trivial.topology.provider.impl;
2 2
3 +import com.google.common.collect.ImmutableMap;
3 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
4 import com.google.common.collect.ImmutableSetMultimap; 5 import com.google.common.collect.ImmutableSetMultimap;
5 import com.google.common.collect.Maps; 6 import com.google.common.collect.Maps;
...@@ -26,6 +27,7 @@ import java.util.Map; ...@@ -26,6 +27,7 @@ import java.util.Map;
26 import java.util.Set; 27 import java.util.Set;
27 28
28 import static com.google.common.collect.ImmutableSetMultimap.Builder; 29 import static com.google.common.collect.ImmutableSetMultimap.Builder;
30 +import static com.google.common.collect.ImmutableSetMultimap.builder;
29 import static org.onlab.graph.GraphPathSearch.Result; 31 import static org.onlab.graph.GraphPathSearch.Result;
30 import static org.onlab.graph.TarjanGraphSearch.SCCResult; 32 import static org.onlab.graph.TarjanGraphSearch.SCCResult;
31 import static org.onlab.onos.net.Link.Type.INDIRECT; 33 import static org.onlab.onos.net.Link.Type.INDIRECT;
...@@ -43,13 +45,12 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -43,13 +45,12 @@ class DefaultTopologyDescription implements TopologyDescription {
43 private final long nanos; 45 private final long nanos;
44 private final Map<DeviceId, TopoVertex> vertexesById = Maps.newHashMap(); 46 private final Map<DeviceId, TopoVertex> vertexesById = Maps.newHashMap();
45 private final Graph<TopoVertex, TopoEdge> graph; 47 private final Graph<TopoVertex, TopoEdge> graph;
46 - private final Map<DeviceId, Result<TopoVertex, TopoEdge>> results; 48 + private final ImmutableMap<DeviceId, Result<TopoVertex, TopoEdge>> results;
47 - private final Map<ClusterId, TopologyCluster> clusters;
48 49
49 - // Secondary look-up indexes 50 + // Cluster-related structures
50 - private ImmutableSetMultimap<ClusterId, DeviceId> devicesByCluster; 51 + private final ImmutableSet<TopologyCluster> clusters;
51 - private ImmutableSetMultimap<ClusterId, Link> linksByCluster; 52 + private ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
52 - private Map<DeviceId, TopologyCluster> clustersByDevice = Maps.newHashMap(); 53 + private ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
53 54
54 /** 55 /**
55 * Creates a topology description to carry topology vitals to the core. 56 * Creates a topology description to carry topology vitals to the core.
...@@ -76,31 +77,25 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -76,31 +77,25 @@ class DefaultTopologyDescription implements TopologyDescription {
76 } 77 }
77 78
78 @Override 79 @Override
79 - public Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) { 80 + public ImmutableMap<DeviceId, Result<TopoVertex, TopoEdge>> pathsBySource() {
80 - return results.get(srcDeviceId); 81 + return results;
81 - }
82 -
83 - @Override
84 - public Set<TopologyCluster> clusters() {
85 - return ImmutableSet.copyOf(clusters.values());
86 } 82 }
87 83
88 @Override 84 @Override
89 - public Set<DeviceId> clusterDevices(TopologyCluster cluster) { 85 + public ImmutableSet<TopologyCluster> clusters() {
90 - return devicesByCluster.get(cluster.id()); 86 + return clusters;
91 } 87 }
92 88
93 @Override 89 @Override
94 - public Set<Link> clusterLinks(TopologyCluster cluster) { 90 + public ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster() {
95 - return linksByCluster.get(cluster.id()); 91 + return devicesByCluster;
96 } 92 }
97 93
98 @Override 94 @Override
99 - public TopologyCluster clusterFor(DeviceId deviceId) { 95 + public ImmutableSetMultimap<TopologyCluster, Link> linksByCluster() {
100 - return clustersByDevice.get(deviceId); 96 + return linksByCluster;
101 } 97 }
102 98
103 -
104 // Link weight for measuring link cost as hop count with indirect links 99 // Link weight for measuring link cost as hop count with indirect links
105 // being as expensive as traversing the entire graph to assume the worst. 100 // being as expensive as traversing the entire graph to assume the worst.
106 private static class HopCountLinkWeight implements LinkWeight { 101 private static class HopCountLinkWeight implements LinkWeight {
...@@ -156,29 +151,31 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -156,29 +151,31 @@ class DefaultTopologyDescription implements TopologyDescription {
156 151
157 // Computes the default shortest paths for all source/dest pairs using 152 // Computes the default shortest paths for all source/dest pairs using
158 // the multi-path Dijkstra and hop-count as path cost. 153 // the multi-path Dijkstra and hop-count as path cost.
159 - private Map<DeviceId, Result<TopoVertex, TopoEdge>> computeDefaultPaths() { 154 + private ImmutableMap<DeviceId, Result<TopoVertex, TopoEdge>> computeDefaultPaths() {
160 LinkWeight weight = new HopCountLinkWeight(graph.getVertexes().size()); 155 LinkWeight weight = new HopCountLinkWeight(graph.getVertexes().size());
161 - Map<DeviceId, Result<TopoVertex, TopoEdge>> results = Maps.newHashMap(); 156 + ImmutableMap.Builder<DeviceId, Result<TopoVertex, TopoEdge>> results =
157 + ImmutableMap.builder();
162 158
163 // Search graph paths for each source to all destinations. 159 // Search graph paths for each source to all destinations.
164 for (TopoVertex src : vertexesById.values()) { 160 for (TopoVertex src : vertexesById.values()) {
165 results.put(src.deviceId(), DIJKSTRA.search(graph, src, null, weight)); 161 results.put(src.deviceId(), DIJKSTRA.search(graph, src, null, weight));
166 } 162 }
167 - return results; 163 + return results.build();
168 } 164 }
169 165
170 // Computes topology SCC clusters using Tarjan algorithm. 166 // Computes topology SCC clusters using Tarjan algorithm.
171 - private Map<ClusterId, TopologyCluster> computeClusters() { 167 + private ImmutableSet<TopologyCluster> computeClusters() {
172 - Map<ClusterId, TopologyCluster> clusters = Maps.newHashMap(); 168 + ImmutableSet.Builder<TopologyCluster> clusterBuilder = ImmutableSet.builder();
173 - SCCResult<TopoVertex, TopoEdge> result = TARJAN.search(graph, new NoIndirectLinksWeight()); 169 + SCCResult<TopoVertex, TopoEdge> result =
170 + TARJAN.search(graph, new NoIndirectLinksWeight());
174 171
175 // Extract both vertexes and edges from the results; the lists form 172 // Extract both vertexes and edges from the results; the lists form
176 // pairs along the same index. 173 // pairs along the same index.
177 List<Set<TopoVertex>> clusterVertexes = result.clusterVertexes(); 174 List<Set<TopoVertex>> clusterVertexes = result.clusterVertexes();
178 List<Set<TopoEdge>> clusterEdges = result.clusterEdges(); 175 List<Set<TopoEdge>> clusterEdges = result.clusterEdges();
179 176
180 - Builder<ClusterId, DeviceId> devicesBuilder = ImmutableSetMultimap.builder(); 177 + Builder<TopologyCluster, DeviceId> devicesBuilder = ImmutableSetMultimap.builder();
181 - Builder<ClusterId, Link> linksBuilder = ImmutableSetMultimap.builder(); 178 + Builder<TopologyCluster, Link> linksBuilder = ImmutableSetMultimap.builder();
182 179
183 // Scan over the lists and create a cluster from the results. 180 // Scan over the lists and create a cluster from the results.
184 for (int i = 0, n = result.clusterCount(); i < n; i++) { 181 for (int i = 0, n = result.clusterCount(); i < n; i++) {
...@@ -189,10 +186,11 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -189,10 +186,11 @@ class DefaultTopologyDescription implements TopologyDescription {
189 new DefaultTopologyCluster(ClusterId.clusterId(i), 186 new DefaultTopologyCluster(ClusterId.clusterId(i),
190 vertexSet.size(), edgeSet.size(), 187 vertexSet.size(), edgeSet.size(),
191 findRoot(vertexSet).deviceId()); 188 findRoot(vertexSet).deviceId());
189 + clusterBuilder.add(cluster);
192 findClusterDevices(vertexSet, cluster, devicesBuilder); 190 findClusterDevices(vertexSet, cluster, devicesBuilder);
193 findClusterLinks(edgeSet, cluster, linksBuilder); 191 findClusterLinks(edgeSet, cluster, linksBuilder);
194 } 192 }
195 - return clusters; 193 + return clusterBuilder.build();
196 } 194 }
197 195
198 // Scans through the set of cluster vertexes and puts their devices in a 196 // Scans through the set of cluster vertexes and puts their devices in a
...@@ -200,11 +198,10 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -200,11 +198,10 @@ class DefaultTopologyDescription implements TopologyDescription {
200 // the cluster. 198 // the cluster.
201 private void findClusterDevices(Set<TopoVertex> vertexSet, 199 private void findClusterDevices(Set<TopoVertex> vertexSet,
202 DefaultTopologyCluster cluster, 200 DefaultTopologyCluster cluster,
203 - Builder<ClusterId, DeviceId> builder) { 201 + Builder<TopologyCluster, DeviceId> builder) {
204 for (TopoVertex vertex : vertexSet) { 202 for (TopoVertex vertex : vertexSet) {
205 DeviceId deviceId = vertex.deviceId(); 203 DeviceId deviceId = vertex.deviceId();
206 - builder.put(cluster.id(), deviceId); 204 + builder.put(cluster, deviceId);
207 - clustersByDevice.put(deviceId, cluster);
208 } 205 }
209 } 206 }
210 207
...@@ -212,9 +209,9 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -212,9 +209,9 @@ class DefaultTopologyDescription implements TopologyDescription {
212 // multi-map associated with the cluster. 209 // multi-map associated with the cluster.
213 private void findClusterLinks(Set<TopoEdge> edgeSet, 210 private void findClusterLinks(Set<TopoEdge> edgeSet,
214 DefaultTopologyCluster cluster, 211 DefaultTopologyCluster cluster,
215 - Builder<ClusterId, Link> builder) { 212 + Builder<TopologyCluster, Link> builder) {
216 for (TopoEdge edge : edgeSet) { 213 for (TopoEdge edge : edgeSet) {
217 - builder.put(cluster.id(), edge.link()); 214 + builder.put(cluster, edge.link());
218 } 215 }
219 } 216 }
220 217
......
...@@ -90,6 +90,8 @@ public class SimpleTopologyProvider extends AbstractProvider ...@@ -90,6 +90,8 @@ public class SimpleTopologyProvider extends AbstractProvider
90 90
91 @Deactivate 91 @Deactivate
92 public synchronized void deactivate() { 92 public synchronized void deactivate() {
93 + isStarted = false;
94 +
93 deviceService.removeListener(deviceListener); 95 deviceService.removeListener(deviceListener);
94 linkService.removeListener(linkListener); 96 linkService.removeListener(linkListener);
95 providerRegistry.unregister(this); 97 providerRegistry.unregister(this);
...@@ -98,7 +100,6 @@ public class SimpleTopologyProvider extends AbstractProvider ...@@ -98,7 +100,6 @@ public class SimpleTopologyProvider extends AbstractProvider
98 executor.shutdownNow(); 100 executor.shutdownNow();
99 executor = null; 101 executor = null;
100 102
101 - isStarted = false;
102 log.info("Stopped"); 103 log.info("Stopped");
103 } 104 }
104 105
...@@ -108,7 +109,7 @@ public class SimpleTopologyProvider extends AbstractProvider ...@@ -108,7 +109,7 @@ public class SimpleTopologyProvider extends AbstractProvider
108 * 109 *
109 * @param reasons events which triggered the topology change 110 * @param reasons events which triggered the topology change
110 */ 111 */
111 - private void triggerTopologyBuild(List<Event> reasons) { 112 + private synchronized void triggerTopologyBuild(List<Event> reasons) {
112 executor.execute(new TopologyBuilderTask(reasons)); 113 executor.execute(new TopologyBuilderTask(reasons));
113 } 114 }
114 115
......