Committed by
Gerrit Code Review
Lazily compute SCC, etc. on demand
- TODO computeCost does not correspond to actual computation cost now Change-Id: Iffe3093c81bbb51d5feb46117fae8be092cf9288
Showing
1 changed file
with
70 additions
and
43 deletions
... | @@ -15,12 +15,17 @@ | ... | @@ -15,12 +15,17 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.store.topology.impl; | 16 | package org.onlab.onos.store.topology.impl; |
17 | 17 | ||
18 | +import com.google.common.base.Supplier; | ||
19 | +import com.google.common.base.Suppliers; | ||
18 | import com.google.common.collect.ImmutableMap; | 20 | import com.google.common.collect.ImmutableMap; |
19 | import com.google.common.collect.ImmutableSet; | 21 | import com.google.common.collect.ImmutableSet; |
20 | import com.google.common.collect.ImmutableSetMultimap; | 22 | import com.google.common.collect.ImmutableSetMultimap; |
23 | + | ||
21 | import org.onlab.graph.DijkstraGraphSearch; | 24 | import org.onlab.graph.DijkstraGraphSearch; |
22 | import org.onlab.graph.GraphPathSearch; | 25 | import org.onlab.graph.GraphPathSearch; |
26 | +import org.onlab.graph.GraphPathSearch.Result; | ||
23 | import org.onlab.graph.TarjanGraphSearch; | 27 | import org.onlab.graph.TarjanGraphSearch; |
28 | +import org.onlab.graph.TarjanGraphSearch.SCCResult; | ||
24 | import org.onlab.onos.net.AbstractModel; | 29 | import org.onlab.onos.net.AbstractModel; |
25 | import org.onlab.onos.net.ConnectPoint; | 30 | import org.onlab.onos.net.ConnectPoint; |
26 | import org.onlab.onos.net.DefaultPath; | 31 | import org.onlab.onos.net.DefaultPath; |
... | @@ -46,8 +51,6 @@ import java.util.Set; | ... | @@ -46,8 +51,6 @@ import java.util.Set; |
46 | 51 | ||
47 | import static com.google.common.base.MoreObjects.toStringHelper; | 52 | import static com.google.common.base.MoreObjects.toStringHelper; |
48 | import static com.google.common.collect.ImmutableSetMultimap.Builder; | 53 | import static com.google.common.collect.ImmutableSetMultimap.Builder; |
49 | -import static org.onlab.graph.GraphPathSearch.Result; | ||
50 | -import static org.onlab.graph.TarjanGraphSearch.SCCResult; | ||
51 | import static org.onlab.onos.core.CoreService.CORE_PROVIDER_ID; | 54 | import static org.onlab.onos.core.CoreService.CORE_PROVIDER_ID; |
52 | import static org.onlab.onos.net.Link.State.ACTIVE; | 55 | import static org.onlab.onos.net.Link.State.ACTIVE; |
53 | import static org.onlab.onos.net.Link.State.INACTIVE; | 56 | import static org.onlab.onos.net.Link.State.INACTIVE; |
... | @@ -68,18 +71,15 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -68,18 +71,15 @@ public class DefaultTopology extends AbstractModel implements Topology { |
68 | private final long computeCost; | 71 | private final long computeCost; |
69 | private final TopologyGraph graph; | 72 | private final TopologyGraph graph; |
70 | 73 | ||
71 | - private final SCCResult<TopologyVertex, TopologyEdge> clusterResults; | 74 | + private final Supplier<SCCResult<TopologyVertex, TopologyEdge>> clusterResults; |
72 | - private final ImmutableMap<DeviceId, Result<TopologyVertex, TopologyEdge>> results; | 75 | + private final Supplier<ImmutableMap<DeviceId, Result<TopologyVertex, TopologyEdge>>> results; |
73 | - private final ImmutableSetMultimap<PathKey, Path> paths; | 76 | + private final Supplier<ImmutableSetMultimap<PathKey, Path>> paths; |
74 | - | ||
75 | - private final ImmutableMap<ClusterId, TopologyCluster> clusters; | ||
76 | - private final ImmutableSet<ConnectPoint> infrastructurePoints; | ||
77 | - private final ImmutableSetMultimap<ClusterId, ConnectPoint> broadcastSets; | ||
78 | 77 | ||
79 | - private ImmutableMap<DeviceId, TopologyCluster> clustersByDevice; | 78 | + private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters; |
80 | - private ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster; | 79 | + private final Supplier<ImmutableSet<ConnectPoint>> infrastructurePoints; |
81 | - private ImmutableSetMultimap<TopologyCluster, Link> linksByCluster; | 80 | + private final Supplier<ImmutableSetMultimap<ClusterId, ConnectPoint>> broadcastSets; |
82 | 81 | ||
82 | + private final Supplier<ClusterIndexes> clusterIndexes; | ||
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Creates a topology descriptor attributed to the specified provider. | 85 | * Creates a topology descriptor attributed to the specified provider. |
... | @@ -95,16 +95,17 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -95,16 +95,17 @@ public class DefaultTopology extends AbstractModel implements Topology { |
95 | this.graph = new DefaultTopologyGraph(description.vertexes(), | 95 | this.graph = new DefaultTopologyGraph(description.vertexes(), |
96 | description.edges()); | 96 | description.edges()); |
97 | 97 | ||
98 | - this.results = searchForShortestPaths(); | ||
99 | - this.paths = buildPaths(); | ||
100 | 98 | ||
101 | - this.clusterResults = searchForClusters(); | 99 | + this.results = Suppliers.memoize(() -> searchForShortestPaths()); |
102 | - this.clusters = buildTopologyClusters(); | 100 | + this.paths = Suppliers.memoize(() -> buildPaths()); |
101 | + | ||
102 | + this.clusterResults = Suppliers.memoize(() -> searchForClusters()); | ||
103 | + this.clusters = Suppliers.memoize(() -> buildTopologyClusters()); | ||
103 | 104 | ||
104 | - buildIndexes(); | 105 | + this.clusterIndexes = Suppliers.memoize(() -> buildIndexes()); |
105 | 106 | ||
106 | - this.broadcastSets = buildBroadcastSets(); | 107 | + this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets()); |
107 | - this.infrastructurePoints = findInfrastructurePoints(); | 108 | + this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints()); |
108 | this.computeCost = Math.max(0, System.nanoTime() - time); | 109 | this.computeCost = Math.max(0, System.nanoTime() - time); |
109 | } | 110 | } |
110 | 111 | ||
... | @@ -120,7 +121,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -120,7 +121,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
120 | 121 | ||
121 | @Override | 122 | @Override |
122 | public int clusterCount() { | 123 | public int clusterCount() { |
123 | - return clusters.size(); | 124 | + return clusters.get().size(); |
124 | } | 125 | } |
125 | 126 | ||
126 | @Override | 127 | @Override |
... | @@ -135,7 +136,19 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -135,7 +136,19 @@ public class DefaultTopology extends AbstractModel implements Topology { |
135 | 136 | ||
136 | @Override | 137 | @Override |
137 | public int pathCount() { | 138 | public int pathCount() { |
138 | - return paths.size(); | 139 | + return paths.get().size(); |
140 | + } | ||
141 | + | ||
142 | + private ImmutableMap<DeviceId, TopologyCluster> clustersByDevice() { | ||
143 | + return clusterIndexes.get().clustersByDevice; | ||
144 | + } | ||
145 | + | ||
146 | + private ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster() { | ||
147 | + return clusterIndexes.get().devicesByCluster; | ||
148 | + } | ||
149 | + | ||
150 | + private ImmutableSetMultimap<TopologyCluster, Link> linksByCluster() { | ||
151 | + return clusterIndexes.get().linksByCluster; | ||
139 | } | 152 | } |
140 | 153 | ||
141 | /** | 154 | /** |
... | @@ -153,7 +166,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -153,7 +166,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
153 | * @return set of clusters | 166 | * @return set of clusters |
154 | */ | 167 | */ |
155 | Set<TopologyCluster> getClusters() { | 168 | Set<TopologyCluster> getClusters() { |
156 | - return ImmutableSet.copyOf(clusters.values()); | 169 | + return ImmutableSet.copyOf(clusters.get().values()); |
157 | } | 170 | } |
158 | 171 | ||
159 | /** | 172 | /** |
... | @@ -163,7 +176,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -163,7 +176,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
163 | * @return topology cluster | 176 | * @return topology cluster |
164 | */ | 177 | */ |
165 | TopologyCluster getCluster(ClusterId clusterId) { | 178 | TopologyCluster getCluster(ClusterId clusterId) { |
166 | - return clusters.get(clusterId); | 179 | + return clusters.get().get(clusterId); |
167 | } | 180 | } |
168 | 181 | ||
169 | /** | 182 | /** |
... | @@ -173,7 +186,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -173,7 +186,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
173 | * @return topology cluster | 186 | * @return topology cluster |
174 | */ | 187 | */ |
175 | TopologyCluster getCluster(DeviceId deviceId) { | 188 | TopologyCluster getCluster(DeviceId deviceId) { |
176 | - return clustersByDevice.get(deviceId); | 189 | + return clustersByDevice().get(deviceId); |
177 | } | 190 | } |
178 | 191 | ||
179 | /** | 192 | /** |
... | @@ -183,7 +196,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -183,7 +196,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
183 | * @return cluster devices | 196 | * @return cluster devices |
184 | */ | 197 | */ |
185 | Set<DeviceId> getClusterDevices(TopologyCluster cluster) { | 198 | Set<DeviceId> getClusterDevices(TopologyCluster cluster) { |
186 | - return devicesByCluster.get(cluster); | 199 | + return devicesByCluster().get(cluster); |
187 | } | 200 | } |
188 | 201 | ||
189 | /** | 202 | /** |
... | @@ -193,7 +206,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -193,7 +206,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
193 | * @return cluster links | 206 | * @return cluster links |
194 | */ | 207 | */ |
195 | Set<Link> getClusterLinks(TopologyCluster cluster) { | 208 | Set<Link> getClusterLinks(TopologyCluster cluster) { |
196 | - return linksByCluster.get(cluster); | 209 | + return linksByCluster().get(cluster); |
197 | } | 210 | } |
198 | 211 | ||
199 | /** | 212 | /** |
... | @@ -203,7 +216,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -203,7 +216,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
203 | * @return true if infrastructure | 216 | * @return true if infrastructure |
204 | */ | 217 | */ |
205 | boolean isInfrastructure(ConnectPoint connectPoint) { | 218 | boolean isInfrastructure(ConnectPoint connectPoint) { |
206 | - return infrastructurePoints.contains(connectPoint); | 219 | + return infrastructurePoints.get().contains(connectPoint); |
207 | } | 220 | } |
208 | 221 | ||
209 | /** | 222 | /** |
... | @@ -219,14 +232,14 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -219,14 +232,14 @@ public class DefaultTopology extends AbstractModel implements Topology { |
219 | } | 232 | } |
220 | 233 | ||
221 | // Find the cluster to which the device belongs. | 234 | // Find the cluster to which the device belongs. |
222 | - TopologyCluster cluster = clustersByDevice.get(connectPoint.deviceId()); | 235 | + TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId()); |
223 | if (cluster == null) { | 236 | if (cluster == null) { |
224 | throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId()); | 237 | throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId()); |
225 | } | 238 | } |
226 | 239 | ||
227 | // If the broadcast set is null or empty, or if the point explicitly | 240 | // If the broadcast set is null or empty, or if the point explicitly |
228 | // belongs to it, return true; | 241 | // belongs to it, return true; |
229 | - Set<ConnectPoint> points = broadcastSets.get(cluster.id()); | 242 | + Set<ConnectPoint> points = broadcastSets.get().get(cluster.id()); |
230 | return points == null || points.isEmpty() || points.contains(connectPoint); | 243 | return points == null || points.isEmpty() || points.contains(connectPoint); |
231 | } | 244 | } |
232 | 245 | ||
... | @@ -237,7 +250,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -237,7 +250,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
237 | * @return size of the cluster broadcast set | 250 | * @return size of the cluster broadcast set |
238 | */ | 251 | */ |
239 | int broadcastSetSize(ClusterId clusterId) { | 252 | int broadcastSetSize(ClusterId clusterId) { |
240 | - return broadcastSets.get(clusterId).size(); | 253 | + return broadcastSets.get().get(clusterId).size(); |
241 | } | 254 | } |
242 | 255 | ||
243 | /** | 256 | /** |
... | @@ -249,7 +262,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -249,7 +262,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
249 | * @return set of shortest paths | 262 | * @return set of shortest paths |
250 | */ | 263 | */ |
251 | Set<Path> getPaths(DeviceId src, DeviceId dst) { | 264 | Set<Path> getPaths(DeviceId src, DeviceId dst) { |
252 | - return paths.get(new PathKey(src, dst)); | 265 | + return paths.get().get(new PathKey(src, dst)); |
253 | } | 266 | } |
254 | 267 | ||
255 | /** | 268 | /** |
... | @@ -295,8 +308,8 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -295,8 +308,8 @@ public class DefaultTopology extends AbstractModel implements Topology { |
295 | // Builds network paths from the graph path search results | 308 | // Builds network paths from the graph path search results |
296 | private ImmutableSetMultimap<PathKey, Path> buildPaths() { | 309 | private ImmutableSetMultimap<PathKey, Path> buildPaths() { |
297 | Builder<PathKey, Path> builder = ImmutableSetMultimap.builder(); | 310 | Builder<PathKey, Path> builder = ImmutableSetMultimap.builder(); |
298 | - for (DeviceId deviceId : results.keySet()) { | 311 | + for (DeviceId deviceId : results.get().keySet()) { |
299 | - Result<TopologyVertex, TopologyEdge> result = results.get(deviceId); | 312 | + Result<TopologyVertex, TopologyEdge> result = results.get().get(deviceId); |
300 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { | 313 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { |
301 | builder.put(new PathKey(path.src().deviceId(), path.dst().deviceId()), | 314 | builder.put(new PathKey(path.src().deviceId(), path.dst().deviceId()), |
302 | networkPath(path)); | 315 | networkPath(path)); |
... | @@ -363,7 +376,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -363,7 +376,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
363 | // Processes a map of broadcast sets for each cluster. | 376 | // Processes a map of broadcast sets for each cluster. |
364 | private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() { | 377 | private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() { |
365 | Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder(); | 378 | Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder(); |
366 | - for (TopologyCluster cluster : clusters.values()) { | 379 | + for (TopologyCluster cluster : clusters.get().values()) { |
367 | addClusterBroadcastSet(cluster, builder); | 380 | addClusterBroadcastSet(cluster, builder); |
368 | } | 381 | } |
369 | return builder.build(); | 382 | return builder.build(); |
... | @@ -375,12 +388,12 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -375,12 +388,12 @@ public class DefaultTopology extends AbstractModel implements Topology { |
375 | private void addClusterBroadcastSet(TopologyCluster cluster, | 388 | private void addClusterBroadcastSet(TopologyCluster cluster, |
376 | Builder<ClusterId, ConnectPoint> builder) { | 389 | Builder<ClusterId, ConnectPoint> builder) { |
377 | // Use the graph root search results to build the broadcast set. | 390 | // Use the graph root search results to build the broadcast set. |
378 | - Result<TopologyVertex, TopologyEdge> result = results.get(cluster.root()); | 391 | + Result<TopologyVertex, TopologyEdge> result = results.get().get(cluster.root()); |
379 | for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) { | 392 | for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) { |
380 | TopologyVertex vertex = entry.getKey(); | 393 | TopologyVertex vertex = entry.getKey(); |
381 | 394 | ||
382 | // Ignore any parents that lead outside the cluster. | 395 | // Ignore any parents that lead outside the cluster. |
383 | - if (clustersByDevice.get(vertex.deviceId()) != cluster) { | 396 | + if (clustersByDevice().get(vertex.deviceId()) != cluster) { |
384 | continue; | 397 | continue; |
385 | } | 398 | } |
386 | 399 | ||
... | @@ -409,32 +422,32 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -409,32 +422,32 @@ public class DefaultTopology extends AbstractModel implements Topology { |
409 | } | 422 | } |
410 | 423 | ||
411 | // Builds cluster-devices, cluster-links and device-cluster indexes. | 424 | // Builds cluster-devices, cluster-links and device-cluster indexes. |
412 | - private void buildIndexes() { | 425 | + private ClusterIndexes buildIndexes() { |
413 | // Prepare the index builders | 426 | // Prepare the index builders |
414 | ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder = ImmutableMap.builder(); | 427 | ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder = ImmutableMap.builder(); |
415 | ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder = ImmutableSetMultimap.builder(); | 428 | ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder = ImmutableSetMultimap.builder(); |
416 | ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder = ImmutableSetMultimap.builder(); | 429 | ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder = ImmutableSetMultimap.builder(); |
417 | 430 | ||
418 | // Now scan through all the clusters | 431 | // Now scan through all the clusters |
419 | - for (TopologyCluster cluster : clusters.values()) { | 432 | + for (TopologyCluster cluster : clusters.get().values()) { |
420 | int i = cluster.id().index(); | 433 | int i = cluster.id().index(); |
421 | 434 | ||
422 | // Scan through all the cluster vertexes. | 435 | // Scan through all the cluster vertexes. |
423 | - for (TopologyVertex vertex : clusterResults.clusterVertexes().get(i)) { | 436 | + for (TopologyVertex vertex : clusterResults.get().clusterVertexes().get(i)) { |
424 | devicesBuilder.put(cluster, vertex.deviceId()); | 437 | devicesBuilder.put(cluster, vertex.deviceId()); |
425 | clusterBuilder.put(vertex.deviceId(), cluster); | 438 | clusterBuilder.put(vertex.deviceId(), cluster); |
426 | } | 439 | } |
427 | 440 | ||
428 | // Scan through all the cluster edges. | 441 | // Scan through all the cluster edges. |
429 | - for (TopologyEdge edge : clusterResults.clusterEdges().get(i)) { | 442 | + for (TopologyEdge edge : clusterResults.get().clusterEdges().get(i)) { |
430 | linksBuilder.put(cluster, edge.link()); | 443 | linksBuilder.put(cluster, edge.link()); |
431 | } | 444 | } |
432 | } | 445 | } |
433 | 446 | ||
434 | // Finalize all indexes. | 447 | // Finalize all indexes. |
435 | - clustersByDevice = clusterBuilder.build(); | 448 | + return new ClusterIndexes(clusterBuilder.build(), |
436 | - devicesByCluster = devicesBuilder.build(); | 449 | + devicesBuilder.build(), |
437 | - linksByCluster = linksBuilder.build(); | 450 | + linksBuilder.build()); |
438 | } | 451 | } |
439 | 452 | ||
440 | // Link weight for measuring link cost as hop count with indirect links | 453 | // Link weight for measuring link cost as hop count with indirect links |
... | @@ -463,6 +476,20 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -463,6 +476,20 @@ public class DefaultTopology extends AbstractModel implements Topology { |
463 | } | 476 | } |
464 | } | 477 | } |
465 | 478 | ||
479 | + static final class ClusterIndexes { | ||
480 | + final ImmutableMap<DeviceId, TopologyCluster> clustersByDevice; | ||
481 | + final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster; | ||
482 | + final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster; | ||
483 | + | ||
484 | + public ClusterIndexes(ImmutableMap<DeviceId, TopologyCluster> clustersByDevice, | ||
485 | + ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster, | ||
486 | + ImmutableSetMultimap<TopologyCluster, Link> linksByCluster) { | ||
487 | + this.clustersByDevice = clustersByDevice; | ||
488 | + this.devicesByCluster = devicesByCluster; | ||
489 | + this.linksByCluster = linksByCluster; | ||
490 | + } | ||
491 | + } | ||
492 | + | ||
466 | @Override | 493 | @Override |
467 | public String toString() { | 494 | public String toString() { |
468 | return toStringHelper(this) | 495 | return toStringHelper(this) | ... | ... |
-
Please register or login to post a comment