ONOS-745 Refactoring topology to compute only broadcast tree and not pre-compute paths.
ONOS-744 Refactoring graph search to allow requesting max number of paths.
Change-Id: I28467246b92df32ebb3155c45774ecc051fdd3dd
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/DefaultTopology.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/DefaultTopology.java
index f010de4..8dea38b 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/DefaultTopology.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/DefaultTopology.java
@@ -15,12 +15,16 @@
*/
package org.onosproject.store.trivial.impl;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import org.onlab.graph.DijkstraGraphSearch;
import org.onlab.graph.GraphPathSearch;
+import org.onlab.graph.GraphPathSearch.Result;
import org.onlab.graph.TarjanGraphSearch;
+import org.onlab.graph.TarjanGraphSearch.SCCResult;
import org.onosproject.net.AbstractModel;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultPath;
@@ -46,13 +50,13 @@
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.collect.ImmutableSetMultimap.Builder;
-import static org.onlab.graph.GraphPathSearch.Result;
-import static org.onlab.graph.TarjanGraphSearch.SCCResult;
+import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.Link.State.INACTIVE;
import static org.onosproject.net.Link.Type.INDIRECT;
+// FIXME: Move to onos-core-common when ready
/**
* Default implementation of the topology descriptor. This carries the
* backing topology data.
@@ -68,18 +72,13 @@
private final long computeCost;
private final TopologyGraph graph;
- private final SCCResult<TopologyVertex, TopologyEdge> clusterResults;
- private final ImmutableMap<DeviceId, Result<TopologyVertex, TopologyEdge>> results;
- private final ImmutableSetMultimap<PathKey, Path> paths;
+ private final LinkWeight weight;
+ private final Supplier<SCCResult<TopologyVertex, TopologyEdge>> clusterResults;
+ private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters;
+ private final Supplier<ImmutableSet<ConnectPoint>> infrastructurePoints;
+ private final Supplier<ImmutableSetMultimap<ClusterId, ConnectPoint>> broadcastSets;
- private final ImmutableMap<ClusterId, TopologyCluster> clusters;
- private final ImmutableSet<ConnectPoint> infrastructurePoints;
- private final ImmutableSetMultimap<ClusterId, ConnectPoint> broadcastSets;
-
- private ImmutableMap<DeviceId, TopologyCluster> clustersByDevice;
- private ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
- private ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
-
+ private final Supplier<ClusterIndexes> clusterIndexes;
/**
* Creates a topology descriptor attributed to the specified provider.
@@ -95,16 +94,14 @@
this.graph = new DefaultTopologyGraph(description.vertexes(),
description.edges());
- this.results = searchForShortestPaths();
- this.paths = buildPaths();
+ this.clusterResults = Suppliers.memoize(() -> searchForClusters());
+ this.clusters = Suppliers.memoize(() -> buildTopologyClusters());
- this.clusterResults = searchForClusters();
- this.clusters = buildTopologyClusters();
+ this.clusterIndexes = Suppliers.memoize(() -> buildIndexes());
- buildIndexes();
-
- this.broadcastSets = buildBroadcastSets();
- this.infrastructurePoints = findInfrastructurePoints();
+ this.weight = new HopCountLinkWeight(graph.getVertexes().size());
+ this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
+ this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints());
this.computeCost = Math.max(0, System.nanoTime() - time);
}
@@ -120,7 +117,7 @@
@Override
public int clusterCount() {
- return clusters.size();
+ return clusters.get().size();
}
@Override
@@ -133,9 +130,16 @@
return graph.getEdges().size();
}
- @Override
- public int pathCount() {
- return paths.size();
+ private ImmutableMap<DeviceId, TopologyCluster> clustersByDevice() {
+ return clusterIndexes.get().clustersByDevice;
+ }
+
+ private ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster() {
+ return clusterIndexes.get().devicesByCluster;
+ }
+
+ private ImmutableSetMultimap<TopologyCluster, Link> linksByCluster() {
+ return clusterIndexes.get().linksByCluster;
}
/**
@@ -153,7 +157,7 @@
* @return set of clusters
*/
Set<TopologyCluster> getClusters() {
- return ImmutableSet.copyOf(clusters.values());
+ return ImmutableSet.copyOf(clusters.get().values());
}
/**
@@ -163,7 +167,7 @@
* @return topology cluster
*/
TopologyCluster getCluster(ClusterId clusterId) {
- return clusters.get(clusterId);
+ return clusters.get().get(clusterId);
}
/**
@@ -173,7 +177,7 @@
* @return topology cluster
*/
TopologyCluster getCluster(DeviceId deviceId) {
- return clustersByDevice.get(deviceId);
+ return clustersByDevice().get(deviceId);
}
/**
@@ -183,7 +187,7 @@
* @return cluster devices
*/
Set<DeviceId> getClusterDevices(TopologyCluster cluster) {
- return devicesByCluster.get(cluster);
+ return devicesByCluster().get(cluster);
}
/**
@@ -193,7 +197,7 @@
* @return cluster links
*/
Set<Link> getClusterLinks(TopologyCluster cluster) {
- return linksByCluster.get(cluster);
+ return linksByCluster().get(cluster);
}
/**
@@ -203,7 +207,7 @@
* @return true if infrastructure
*/
boolean isInfrastructure(ConnectPoint connectPoint) {
- return infrastructurePoints.contains(connectPoint);
+ return infrastructurePoints.get().contains(connectPoint);
}
/**
@@ -219,14 +223,14 @@
}
// Find the cluster to which the device belongs.
- TopologyCluster cluster = clustersByDevice.get(connectPoint.deviceId());
+ TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId());
if (cluster == null) {
throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId());
}
// If the broadcast set is null or empty, or if the point explicitly
// belongs to it, return true;
- Set<ConnectPoint> points = broadcastSets.get(cluster.id());
+ Set<ConnectPoint> points = broadcastSets.get().get(cluster.id());
return points == null || points.isEmpty() || points.contains(connectPoint);
}
@@ -237,7 +241,7 @@
* @return size of the cluster broadcast set
*/
int broadcastSetSize(ClusterId clusterId) {
- return broadcastSets.get(clusterId).size();
+ return broadcastSets.get().get(clusterId).size();
}
/**
@@ -249,7 +253,7 @@
* @return set of shortest paths
*/
Set<Path> getPaths(DeviceId src, DeviceId dst) {
- return paths.get(new PathKey(src, dst));
+ return getPaths(src, dst, null);
}
/**
@@ -258,7 +262,7 @@
*
* @param src source device
* @param dst destination device
- * @param weight edge weight function
+ * @param weight link weight function
* @return set of shortest paths
*/
Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
@@ -271,7 +275,7 @@
}
GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
- DIJKSTRA.search(graph, srcV, dstV, weight);
+ DIJKSTRA.search(graph, srcV, dstV, weight, ALL_PATHS);
ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
builder.add(networkPath(path));
@@ -280,31 +284,6 @@
}
- // Searches the graph for all shortest paths and returns the search results.
- private ImmutableMap<DeviceId, Result<TopologyVertex, TopologyEdge>> searchForShortestPaths() {
- ImmutableMap.Builder<DeviceId, Result<TopologyVertex, TopologyEdge>> builder = ImmutableMap.builder();
-
- // Search graph paths for each source to all destinations.
- LinkWeight weight = new HopCountLinkWeight(graph.getVertexes().size());
- for (TopologyVertex src : graph.getVertexes()) {
- builder.put(src.deviceId(), DIJKSTRA.search(graph, src, null, weight));
- }
- return builder.build();
- }
-
- // Builds network paths from the graph path search results
- private ImmutableSetMultimap<PathKey, Path> buildPaths() {
- Builder<PathKey, Path> builder = ImmutableSetMultimap.builder();
- for (DeviceId deviceId : results.keySet()) {
- Result<TopologyVertex, TopologyEdge> result = results.get(deviceId);
- for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
- builder.put(new PathKey(path.src().deviceId(), path.dst().deviceId()),
- networkPath(path));
- }
- }
- return builder.build();
- }
-
// Converts graph path to a network path with the same cost.
private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
List<Link> links = new ArrayList<>();
@@ -324,23 +303,21 @@
// Builds the topology clusters and returns the id-cluster bindings.
private ImmutableMap<ClusterId, TopologyCluster> buildTopologyClusters() {
ImmutableMap.Builder<ClusterId, TopologyCluster> clusterBuilder = ImmutableMap.builder();
- SCCResult<TopologyVertex, TopologyEdge> result =
- TARJAN.search(graph, new NoIndirectLinksWeight());
-
+ SCCResult<TopologyVertex, TopologyEdge> results = clusterResults.get();
// Extract both vertexes and edges from the results; the lists form
// pairs along the same index.
- List<Set<TopologyVertex>> clusterVertexes = result.clusterVertexes();
- List<Set<TopologyEdge>> clusterEdges = result.clusterEdges();
+ List<Set<TopologyVertex>> clusterVertexes = results.clusterVertexes();
+ List<Set<TopologyEdge>> clusterEdges = results.clusterEdges();
// Scan over the lists and create a cluster from the results.
- for (int i = 0, n = result.clusterCount(); i < n; i++) {
+ for (int i = 0, n = results.clusterCount(); i < n; i++) {
Set<TopologyVertex> vertexSet = clusterVertexes.get(i);
Set<TopologyEdge> edgeSet = clusterEdges.get(i);
ClusterId cid = ClusterId.clusterId(i);
DefaultTopologyCluster cluster =
new DefaultTopologyCluster(cid, vertexSet.size(), edgeSet.size(),
- findRoot(vertexSet).deviceId());
+ findRoot(vertexSet));
clusterBuilder.put(cid, cluster);
}
return clusterBuilder.build();
@@ -363,7 +340,7 @@
// Processes a map of broadcast sets for each cluster.
private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() {
Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder();
- for (TopologyCluster cluster : clusters.values()) {
+ for (TopologyCluster cluster : clusters.get().values()) {
addClusterBroadcastSet(cluster, builder);
}
return builder.build();
@@ -375,12 +352,13 @@
private void addClusterBroadcastSet(TopologyCluster cluster,
Builder<ClusterId, ConnectPoint> builder) {
// Use the graph root search results to build the broadcast set.
- Result<TopologyVertex, TopologyEdge> result = results.get(cluster.root());
+ Result<TopologyVertex, TopologyEdge> result =
+ DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) {
TopologyVertex vertex = entry.getKey();
// Ignore any parents that lead outside the cluster.
- if (clustersByDevice.get(vertex.deviceId()) != cluster) {
+ if (clustersByDevice().get(vertex.deviceId()) != cluster) {
continue;
}
@@ -409,32 +387,32 @@
}
// Builds cluster-devices, cluster-links and device-cluster indexes.
- private void buildIndexes() {
+ private ClusterIndexes buildIndexes() {
// Prepare the index builders
ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder = ImmutableMap.builder();
ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder = ImmutableSetMultimap.builder();
ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder = ImmutableSetMultimap.builder();
// Now scan through all the clusters
- for (TopologyCluster cluster : clusters.values()) {
+ for (TopologyCluster cluster : clusters.get().values()) {
int i = cluster.id().index();
// Scan through all the cluster vertexes.
- for (TopologyVertex vertex : clusterResults.clusterVertexes().get(i)) {
+ for (TopologyVertex vertex : clusterResults.get().clusterVertexes().get(i)) {
devicesBuilder.put(cluster, vertex.deviceId());
clusterBuilder.put(vertex.deviceId(), cluster);
}
// Scan through all the cluster edges.
- for (TopologyEdge edge : clusterResults.clusterEdges().get(i)) {
+ for (TopologyEdge edge : clusterResults.get().clusterEdges().get(i)) {
linksBuilder.put(cluster, edge.link());
}
}
// Finalize all indexes.
- clustersByDevice = clusterBuilder.build();
- devicesByCluster = devicesBuilder.build();
- linksByCluster = linksBuilder.build();
+ return new ClusterIndexes(clusterBuilder.build(),
+ devicesBuilder.build(),
+ linksBuilder.build());
}
// Link weight for measuring link cost as hop count with indirect links
@@ -463,6 +441,20 @@
}
}
+ static final class ClusterIndexes {
+ final ImmutableMap<DeviceId, TopologyCluster> clustersByDevice;
+ final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
+ final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
+
+ public ClusterIndexes(ImmutableMap<DeviceId, TopologyCluster> clustersByDevice,
+ ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster,
+ ImmutableSetMultimap<TopologyCluster, Link> linksByCluster) {
+ this.clustersByDevice = clustersByDevice;
+ this.devicesByCluster = devicesByCluster;
+ this.linksByCluster = linksByCluster;
+ }
+ }
+
@Override
public String toString() {
return toStringHelper(this)
@@ -471,7 +463,6 @@
.add("clusters", clusterCount())
.add("devices", deviceCount())
.add("links", linkCount())
- .add("pathCount", pathCount())
.toString();
}
}