ONOS-400 Topology creation and up time formatting fixes
Change-Id: Iaf6d4dbbc1c7eaae9465a2d931d40f07a75ad07d
diff --git a/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java b/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
index 337a1f7..09682a2 100644
--- a/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
@@ -15,7 +15,11 @@
*/
package org.onosproject.cli.net;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.concurrent.TimeUnit;
+
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
@@ -23,18 +27,20 @@
import org.onosproject.net.topology.TopologyProvider;
import org.onosproject.net.topology.TopologyService;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
/**
* Lists summary of the current topology.
*/
@Command(scope = "onos", name = "topology",
- description = "Lists summary of the current topology")
+description = "Lists summary of the current topology")
public class TopologyCommand extends AbstractShellCommand {
- private static final String FMT =
- "time=%s, devices=%d, links=%d, clusters=%d";
+ private static final String FMT = "created=%s, uptime=%s, devices=%d, links=%d, clusters=%d";
- @Option(name = "-r", aliases = "--recompute", description = "Trigger topology re-computation",
- required = false, multiValued = false)
+ @Option(name = "-r", aliases = "--recompute",
+ description = "Trigger topology re-computation", required = false,
+ multiValued = false)
private boolean recompute = false;
protected TopologyService service;
@@ -51,19 +57,75 @@
@Override
protected void execute() {
init();
+ long topologyUptime =
+ Math.max(0, (System.currentTimeMillis() - topology.creationTime()));
if (recompute) {
get(TopologyProvider.class).triggerRecompute();
} else if (outputJson()) {
- print("%s", new ObjectMapper().createObjectNode()
- .put("time", topology.time())
- .put("deviceCount", topology.deviceCount())
- .put("linkCount", topology.linkCount())
- .put("clusterCount", topology.clusterCount()));
+ print("%s",
+ new ObjectMapper()
+ .createObjectNode()
+ .put("time", topology.time())
+ .put("created", formatCreationTime(topology.creationTime()))
+ .put("uptime", formatElapsedTime(topologyUptime))
+ .put("deviceCount", topology.deviceCount())
+ .put("linkCount", topology.linkCount())
+ .put("clusterCount", topology.clusterCount()));
} else {
- print(FMT, topology.time(), topology.deviceCount(), topology.linkCount(),
- topology.clusterCount());
+ print(FMT, formatCreationTime(topology.creationTime()),
+ formatElapsedTime(topologyUptime),
+ topology.deviceCount(), topology.linkCount(),
+ topology.clusterCount());
}
}
+ /**
+ * Converts millis to a formatted elapsed time string.
+ *
+ * @param millis Duration in millis to convert to a string
+ *
+ * @return Formatted string: "D days, H hrs, M mins, S secs".
+ */
+ private static String formatElapsedTime(long millis) {
+ if (millis < 0) {
+ throw new IllegalArgumentException("Interval less than zero. "
+ + "Possible unsynchronized timestamps");
+ }
+
+ final long days = TimeUnit.MILLISECONDS.toDays(millis);
+ millis -= TimeUnit.DAYS.toMillis(days);
+ final long hours = TimeUnit.MILLISECONDS.toHours(millis);
+ millis -= TimeUnit.HOURS.toMillis(hours);
+ final long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
+ millis -= TimeUnit.MINUTES.toMillis(minutes);
+ final long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
+
+ final StringBuilder topologyUptimeString = new StringBuilder(64);
+ topologyUptimeString.append(days);
+ topologyUptimeString.append(" days, ");
+ topologyUptimeString.append(hours);
+ topologyUptimeString.append(" hrs, ");
+ topologyUptimeString.append(minutes);
+ topologyUptimeString.append(" mins, ");
+ topologyUptimeString.append(seconds);
+ topologyUptimeString.append(" secs");
+
+ return (topologyUptimeString.toString());
+ }
+
+ /**
+ * Converts millis to a formatted Date String.
+ *
+ * @param millis Duration in millis to convert to a string
+ *
+ * @return Formatted string: yyyy-MM-dd HH:mm:ss.
+ */
+ private static String formatCreationTime(long millis) {
+ final DateFormat dateFormatter =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(millis);
+ return (dateFormatter.format(calendar.getTime()));
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java b/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java
index 4d60e23..08db92f 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java
@@ -34,30 +34,60 @@
* Default implementation of an immutable topology graph data carrier.
*/
public class DefaultGraphDescription extends AbstractDescription
- implements GraphDescription {
+implements GraphDescription {
private static final Logger log = getLogger(DefaultGraphDescription.class);
private final long nanos;
+ private final long creationTime;
private final ImmutableSet<TopologyVertex> vertexes;
private final ImmutableSet<TopologyEdge> edges;
- private final Map<DeviceId, TopologyVertex> vertexesById = Maps.newHashMap();
+ private final Map<DeviceId, TopologyVertex> vertexesById = Maps
+ .newHashMap();
/**
* Creates a minimal topology graph description to allow core to construct
* and process the topology graph.
*
- * @param nanos time in nanos of when the topology description was created
- * @param devices collection of infrastructure devices
- * @param links collection of infrastructure links
+ * @param nanos time in nanos of when the topology description was created
+ *
+ * @param devices collection of infrastructure devices
+ *
+ * @param links collection of infrastructure links
+ *
* @param annotations optional key/value annotations map
+ *
*/
+ @Deprecated
public DefaultGraphDescription(long nanos, Iterable<Device> devices,
- Iterable<Link> links,
- SparseAnnotations... annotations) {
+ Iterable<Link> links,
+ SparseAnnotations... annotations) {
+ this(nanos, System.currentTimeMillis(), devices, links, annotations);
+ }
+
+ /**
+ * Creates a minimal topology graph description to allow core to construct
+ * and process the topology graph.
+ *
+ * @param nanos time in nanos of when the topology description was created
+ *
+ * @param millis time in millis of when the topology description was created
+ *
+ * @param devices collection of infrastructure devices
+ *
+ * @param links collection of infrastructure links
+ *
+ * @param annotations optional key/value annotations map
+ *
+ */
+ public DefaultGraphDescription(long nanos, long millis,
+ Iterable<Device> devices,
+ Iterable<Link> links,
+ SparseAnnotations... annotations) {
super(annotations);
this.nanos = nanos;
+ this.creationTime = millis;
this.vertexes = buildVertexes(devices);
this.edges = buildEdges(links);
vertexesById.clear();
@@ -69,6 +99,11 @@
}
@Override
+ public long creationTime() {
+ return creationTime;
+ }
+
+ @Override
public ImmutableSet<TopologyVertex> vertexes() {
return vertexes;
}
@@ -79,7 +114,8 @@
}
// Builds a set of topology vertexes from the specified list of devices
- private ImmutableSet<TopologyVertex> buildVertexes(Iterable<Device> devices) {
+ private ImmutableSet<TopologyVertex>
+ buildVertexes(Iterable<Device> devices) {
ImmutableSet.Builder<TopologyVertex> vertexes = ImmutableSet.builder();
for (Device device : devices) {
TopologyVertex vertex = new DefaultTopologyVertex(device.id());
@@ -95,7 +131,8 @@
for (Link link : links) {
try {
edges.add(new DefaultTopologyEdge(vertexOf(link.src()),
- vertexOf(link.dst()), link));
+ vertexOf(link.dst()),
+ link));
} catch (IllegalArgumentException e) {
log.debug("Ignoring {}, missing vertex", link);
}
diff --git a/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java b/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java
index 3a243df..cc22c33 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java
@@ -15,9 +15,10 @@
*/
package org.onosproject.net.topology;
-import com.google.common.collect.ImmutableSet;
import org.onosproject.net.Description;
+import com.google.common.collect.ImmutableSet;
+
/**
* Describes attribute(s) of a network graph.
*/
@@ -32,6 +33,14 @@
long timestamp();
/**
+ * Returns the creation timestamp of the graph description. This is
+ * expressed in system millis to allow proper date and time formatting.
+ *
+ * @return graph description creation timestamp in millis
+ */
+ long creationTime();
+
+ /**
* Returns the set of topology graph vertexes.
*
* @return set of graph vertexes
@@ -46,4 +55,3 @@
ImmutableSet<TopologyEdge> edges();
}
-
diff --git a/core/api/src/main/java/org/onosproject/net/topology/Topology.java b/core/api/src/main/java/org/onosproject/net/topology/Topology.java
index df8d63c..a174219 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/Topology.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/Topology.java
@@ -23,16 +23,24 @@
public interface Topology extends Provided {
/**
- * Returns the time, specified in system nanos of when the topology
- * became available.
+ * Returns the time, specified in system nanos of when the topology became
+ * available.
*
* @return time in system nanos
*/
long time();
/**
- * Returns the time, specified in system nanos of how long the topology
- * took to compute.
+ * Returns the time, specified in system millis of when the topology became
+ * available.
+ *
+ * @return time in system nanos
+ */
+ long creationTime();
+
+ /**
+ * Returns the time, specified in system nanos of how long the topology took
+ * to compute.
*
* @return elapsed time in system nanos
*/
@@ -53,7 +61,6 @@
*/
int deviceCount();
-
/**
* Returns the number of infrastructure links in the topology.
*
diff --git a/core/net/src/main/java/org/onosproject/net/topology/impl/DefaultTopologyProvider.java b/core/net/src/main/java/org/onosproject/net/topology/impl/DefaultTopologyProvider.java
index a331d50..af40595 100644
--- a/core/net/src/main/java/org/onosproject/net/topology/impl/DefaultTopologyProvider.java
+++ b/core/net/src/main/java/org/onosproject/net/topology/impl/DefaultTopologyProvider.java
@@ -15,7 +15,21 @@
*/
package org.onosproject.net.topology.impl;
-import com.google.common.collect.ImmutableList;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Timer;
+import java.util.concurrent.ExecutorService;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -42,28 +56,16 @@
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Timer;
-import java.util.concurrent.ExecutorService;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static java.util.concurrent.Executors.newFixedThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
-import static org.onosproject.net.device.DeviceEvent.Type.*;
-import static org.slf4j.LoggerFactory.getLogger;
+import com.google.common.collect.ImmutableList;
/**
- * Default implementation of a network topology provider that feeds off
- * device and link subsystem events to trigger assembly and computation of
- * new topology snapshots.
+ * Default implementation of a network topology provider that feeds off device
+ * and link subsystem events to trigger assembly and computation of new topology
+ * snapshots.
*/
@Component(immediate = true)
@Service
-public class DefaultTopologyProvider extends AbstractProvider
- implements TopologyProvider {
+public class DefaultTopologyProvider extends AbstractProvider implements TopologyProvider {
private static final int MAX_THREADS = 8;
private static final int DEFAULT_MAX_EVENTS = 1000;
@@ -71,7 +73,8 @@
private static final int DEFAULT_MAX_BATCH_MS = 50;
// FIXME: Replace with a system-wide timer instance;
- // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt
+ // TODO: Convert to use HashedWheelTimer or produce a variant of that; then
+ // decide which we want to adopt
private static final Timer TIMER = new Timer("onos-topo-event-batching");
@Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS,
@@ -100,8 +103,8 @@
private volatile boolean isStarted = false;
private TopologyProviderService providerService;
- private DeviceListener deviceListener = new InternalDeviceListener();
- private LinkListener linkListener = new InternalLinkListener();
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+ private final LinkListener linkListener = new InternalLinkListener();
private Accumulator<Event> accumulator;
private ExecutorService executor;
@@ -115,7 +118,8 @@
@Activate
public synchronized void activate(ComponentContext context) {
- executor = newFixedThreadPool(MAX_THREADS, groupedThreads("onos/topo", "build-%d"));
+ executor = newFixedThreadPool(MAX_THREADS,
+ groupedThreads("onos/topo", "build-%d"));
accumulator = new TopologyChangeAccumulator();
logConfig("Configured");
@@ -171,21 +175,23 @@
newMaxIdleMs = DEFAULT_MAX_IDLE_MS;
}
- if (newMaxEvents != maxEvents || newMaxBatchMs != maxBatchMs || newMaxIdleMs != maxIdleMs) {
+ if ((newMaxEvents != maxEvents) || (newMaxBatchMs != maxBatchMs)
+ || (newMaxIdleMs != maxIdleMs)) {
maxEvents = newMaxEvents;
maxBatchMs = newMaxBatchMs;
maxIdleMs = newMaxIdleMs;
- accumulator = maxEvents > 1 ? new TopologyChangeAccumulator() : null;
+ accumulator = maxEvents > 1 ? new TopologyChangeAccumulator()
+ : null;
logConfig("Reconfigured");
}
}
private void logConfig(String prefix) {
- log.info("{} with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}; accumulator={}",
- prefix, maxEvents, maxBatchMs, maxIdleMs, accumulator != null);
+ log.info(
+ "{} with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}; accumulator={}",
+ prefix, maxEvents, maxBatchMs, maxIdleMs, accumulator != null);
}
-
@Override
public void triggerRecompute() {
triggerTopologyBuild(Collections.<Event>emptyList());
@@ -195,7 +201,8 @@
* Triggers assembly of topology data citing the specified events as the
* reason.
*
- * @param reasons events which triggered the topology change
+ * @param reasons
+ * events which triggered the topology change
*/
private synchronized void triggerTopologyBuild(List<Event> reasons) {
if (executor != null) {
@@ -209,8 +216,9 @@
if (isStarted) {
GraphDescription desc =
new DefaultGraphDescription(System.nanoTime(),
- deviceService.getAvailableDevices(),
- linkService.getActiveLinks());
+ System.currentTimeMillis(),
+ deviceService.getAvailableDevices(),
+ linkService.getActiveLinks());
providerService.topologyChanged(desc, reasons);
}
}
@@ -228,8 +236,8 @@
@Override
public void event(DeviceEvent event) {
DeviceEvent.Type type = event.type();
- if (type == DEVICE_ADDED || type == DEVICE_REMOVED ||
- type == DEVICE_AVAILABILITY_CHANGED) {
+ if ((type == DEVICE_ADDED) || (type == DEVICE_REMOVED) ||
+ (type == DEVICE_AVAILABILITY_CHANGED)) {
processEvent(event);
}
}
@@ -268,7 +276,8 @@
try {
buildTopology(reasons);
} catch (Exception e) {
- log.warn("Unable to compute topology due to: {}", e.getMessage());
+ log.warn("Unable to compute topology due to: {}",
+ e.getMessage());
log.debug("Unable to compute topology", e);
}
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DefaultTopology.java b/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DefaultTopology.java
index 8c15e45..e597449 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DefaultTopology.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DefaultTopology.java
@@ -15,11 +15,18 @@
*/
package org.onosproject.store.topology.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 static com.google.common.base.MoreObjects.toStringHelper;
+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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import org.onlab.graph.DijkstraGraphSearch;
import org.onlab.graph.GraphPathSearch;
import org.onlab.graph.GraphPathSearch.Result;
@@ -43,32 +50,25 @@
import org.onosproject.net.topology.TopologyGraph;
import org.onosproject.net.topology.TopologyVertex;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.collect.ImmutableSetMultimap.Builder;
-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;
+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 com.google.common.collect.ImmutableSetMultimap.Builder;
// FIXME: Move to onos-core-common when ready
/**
- * Default implementation of the topology descriptor. This carries the
- * backing topology data.
+ * Default implementation of the topology descriptor. This carries the backing
+ * topology data.
*/
public class DefaultTopology extends AbstractModel implements Topology {
- private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA =
- new DijkstraGraphSearch<>();
- private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN =
- new TarjanGraphSearch<>();
+ private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
+ private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
private final long time;
+ private final long creationTime;
private final long computeCost;
private final TopologyGraph graph;
@@ -83,16 +83,19 @@
/**
* Creates a topology descriptor attributed to the specified provider.
*
- * @param providerId identity of the provider
- * @param description data describing the new topology
+ * @param providerId
+ * identity of the provider
+ * @param description
+ * data describing the new topology
*/
DefaultTopology(ProviderId providerId, GraphDescription description) {
super(providerId);
this.time = description.timestamp();
+ this.creationTime = description.creationTime();
// Build the graph
this.graph = new DefaultTopologyGraph(description.vertexes(),
- description.edges());
+ description.edges());
this.clusterResults = Suppliers.memoize(() -> searchForClusters());
this.clusters = Suppliers.memoize(() -> buildTopologyClusters());
@@ -101,7 +104,8 @@
this.weight = new HopCountLinkWeight(graph.getVertexes().size());
this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
- this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints());
+ this.infrastructurePoints = Suppliers
+ .memoize(() -> findInfrastructurePoints());
this.computeCost = Math.max(0, System.nanoTime() - time);
}
@@ -111,6 +115,11 @@
}
@Override
+ public long creationTime() {
+ return creationTime;
+ }
+
+ @Override
public long computeCost() {
return computeCost;
}
@@ -164,6 +173,7 @@
* Returns the specified topology cluster.
*
* @param clusterId cluster identifier
+ *
* @return topology cluster
*/
TopologyCluster getCluster(ClusterId clusterId) {
@@ -174,6 +184,7 @@
* Returns the topology cluster that contains the given device.
*
* @param deviceId device identifier
+ *
* @return topology cluster
*/
TopologyCluster getCluster(DeviceId deviceId) {
@@ -184,6 +195,7 @@
* Returns the set of cluster devices.
*
* @param cluster topology cluster
+ *
* @return cluster devices
*/
Set<DeviceId> getClusterDevices(TopologyCluster cluster) {
@@ -194,6 +206,7 @@
* Returns the set of cluster links.
*
* @param cluster topology cluster
+ *
* @return cluster links
*/
Set<Link> getClusterLinks(TopologyCluster cluster) {
@@ -204,6 +217,7 @@
* Indicates whether the given point is an infrastructure link end-point.
*
* @param connectPoint connection point
+ *
* @return true if infrastructure
*/
boolean isInfrastructure(ConnectPoint connectPoint) {
@@ -214,6 +228,7 @@
* Indicates whether the given point is part of a broadcast set.
*
* @param connectPoint connection point
+ *
* @return true if in broadcast set
*/
boolean isBroadcastPoint(ConnectPoint connectPoint) {
@@ -225,19 +240,21 @@
// Find the cluster to which the device belongs.
TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId());
if (cluster == null) {
- throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId());
+ 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().get(cluster.id());
- return points == null || points.isEmpty() || points.contains(connectPoint);
+ return (points == null) || points.isEmpty() || points.contains(connectPoint);
}
/**
* Returns the size of the cluster broadcast set.
*
* @param clusterId cluster identifier
+ *
* @return size of the cluster broadcast set
*/
int broadcastSetSize(ClusterId clusterId) {
@@ -249,7 +266,9 @@
* destination devices.
*
* @param src source device
+ *
* @param dst destination device
+ *
* @return set of shortest paths
*/
Set<Path> getPaths(DeviceId src, DeviceId dst) {
@@ -260,9 +279,12 @@
* Computes on-demand the set of shortest paths between source and
* destination devices.
*
- * @param src source device
- * @param dst destination device
+ * @param src source device
+ *
+ * @param dst destination device
+ *
* @param weight link weight function
+ *
* @return set of shortest paths
*/
Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
@@ -283,7 +305,6 @@
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<>();
@@ -293,7 +314,6 @@
return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
}
-
// Searches for SCC clusters in the network topology graph using Tarjan
// algorithm.
private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() {
@@ -315,9 +335,10 @@
Set<TopologyEdge> edgeSet = clusterEdges.get(i);
ClusterId cid = ClusterId.clusterId(i);
- DefaultTopologyCluster cluster =
- new DefaultTopologyCluster(cid, vertexSet.size(), edgeSet.size(),
- findRoot(vertexSet));
+ DefaultTopologyCluster cluster = new DefaultTopologyCluster(cid,
+ vertexSet.size(),
+ edgeSet.size(),
+ findRoot(vertexSet));
clusterBuilder.put(cid, cluster);
}
return clusterBuilder.build();
@@ -328,9 +349,8 @@
private TopologyVertex findRoot(Set<TopologyVertex> vertexSet) {
TopologyVertex minVertex = null;
for (TopologyVertex vertex : vertexSet) {
- if (minVertex == null ||
- minVertex.deviceId().toString()
- .compareTo(minVertex.deviceId().toString()) < 0) {
+ if ((minVertex == null) || (minVertex.deviceId()
+ .toString().compareTo(minVertex.deviceId().toString()) < 0)) {
minVertex = vertex;
}
}
@@ -339,7 +359,8 @@
// Processes a map of broadcast sets for each cluster.
private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() {
- Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder();
+ Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap
+ .builder();
for (TopologyCluster cluster : clusters.get().values()) {
addClusterBroadcastSet(cluster, builder);
}
@@ -349,11 +370,9 @@
// Finds all broadcast points for the cluster. These are those connection
// points which lie along the shortest paths between the cluster root and
// all other devices within the cluster.
- private void addClusterBroadcastSet(TopologyCluster cluster,
- Builder<ClusterId, ConnectPoint> builder) {
+ private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) {
// Use the graph root search results to build the broadcast set.
- Result<TopologyVertex, TopologyEdge> result =
- DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
+ 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();
@@ -389,9 +408,12 @@
// Builds cluster-devices, cluster-links and device-cluster indexes.
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();
+ 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.get().values()) {
@@ -428,8 +450,9 @@
public double weight(TopologyEdge edge) {
// To force preference to use direct paths first, make indirect
// links as expensive as the linear vertex traversal.
- return edge.link().state() == ACTIVE ?
- (edge.link().type() == INDIRECT ? indirectLinkCost : 1) : -1;
+ return edge.link().state() ==
+ ACTIVE ? (edge.link().type() ==
+ INDIRECT ? indirectLinkCost : 1) : -1;
}
}
@@ -437,7 +460,8 @@
private static class NoIndirectLinksWeight implements LinkWeight {
@Override
public double weight(TopologyEdge edge) {
- return edge.link().state() == INACTIVE || edge.link().type() == INDIRECT ? -1 : 1;
+ return (edge.link().state() == INACTIVE)
+ || (edge.link().type() == INDIRECT) ? -1 : 1;
}
}
@@ -446,9 +470,10 @@
final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
- public ClusterIndexes(ImmutableMap<DeviceId, TopologyCluster> clustersByDevice,
- ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster,
- 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;
@@ -459,10 +484,10 @@
public String toString() {
return toStringHelper(this)
.add("time", time)
+ .add("creationTime", creationTime)
.add("computeCost", computeCost)
.add("clusters", clusterCount())
.add("devices", deviceCount())
- .add("links", linkCount())
- .toString();
+ .add("links", linkCount()).toString();
}
}
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 8dea38b..2b23364 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,11 +15,18 @@
*/
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 static com.google.common.base.MoreObjects.toStringHelper;
+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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import org.onlab.graph.DijkstraGraphSearch;
import org.onlab.graph.GraphPathSearch;
import org.onlab.graph.GraphPathSearch.Result;
@@ -43,32 +50,25 @@
import org.onosproject.net.topology.TopologyGraph;
import org.onosproject.net.topology.TopologyVertex;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.collect.ImmutableSetMultimap.Builder;
-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;
+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 com.google.common.collect.ImmutableSetMultimap.Builder;
// FIXME: Move to onos-core-common when ready
/**
- * Default implementation of the topology descriptor. This carries the
- * backing topology data.
+ * Default implementation of the topology descriptor. This carries the backing
+ * topology data.
*/
public class DefaultTopology extends AbstractModel implements Topology {
- private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA =
- new DijkstraGraphSearch<>();
- private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN =
- new TarjanGraphSearch<>();
+ private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
+ private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
private final long time;
+ private final long creationTime;
private final long computeCost;
private final TopologyGraph graph;
@@ -83,16 +83,19 @@
/**
* Creates a topology descriptor attributed to the specified provider.
*
- * @param providerId identity of the provider
- * @param description data describing the new topology
+ * @param providerId
+ * identity of the provider
+ * @param description
+ * data describing the new topology
*/
DefaultTopology(ProviderId providerId, GraphDescription description) {
super(providerId);
this.time = description.timestamp();
+ this.creationTime = description.creationTime();
// Build the graph
this.graph = new DefaultTopologyGraph(description.vertexes(),
- description.edges());
+ description.edges());
this.clusterResults = Suppliers.memoize(() -> searchForClusters());
this.clusters = Suppliers.memoize(() -> buildTopologyClusters());
@@ -101,7 +104,8 @@
this.weight = new HopCountLinkWeight(graph.getVertexes().size());
this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
- this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints());
+ this.infrastructurePoints = Suppliers
+ .memoize(() -> findInfrastructurePoints());
this.computeCost = Math.max(0, System.nanoTime() - time);
}
@@ -111,6 +115,11 @@
}
@Override
+ public long creationTime() {
+ return creationTime;
+ }
+
+ @Override
public long computeCost() {
return computeCost;
}
@@ -164,6 +173,7 @@
* Returns the specified topology cluster.
*
* @param clusterId cluster identifier
+ *
* @return topology cluster
*/
TopologyCluster getCluster(ClusterId clusterId) {
@@ -174,6 +184,7 @@
* Returns the topology cluster that contains the given device.
*
* @param deviceId device identifier
+ *
* @return topology cluster
*/
TopologyCluster getCluster(DeviceId deviceId) {
@@ -184,6 +195,7 @@
* Returns the set of cluster devices.
*
* @param cluster topology cluster
+ *
* @return cluster devices
*/
Set<DeviceId> getClusterDevices(TopologyCluster cluster) {
@@ -194,6 +206,7 @@
* Returns the set of cluster links.
*
* @param cluster topology cluster
+ *
* @return cluster links
*/
Set<Link> getClusterLinks(TopologyCluster cluster) {
@@ -204,6 +217,7 @@
* Indicates whether the given point is an infrastructure link end-point.
*
* @param connectPoint connection point
+ *
* @return true if infrastructure
*/
boolean isInfrastructure(ConnectPoint connectPoint) {
@@ -214,6 +228,7 @@
* Indicates whether the given point is part of a broadcast set.
*
* @param connectPoint connection point
+ *
* @return true if in broadcast set
*/
boolean isBroadcastPoint(ConnectPoint connectPoint) {
@@ -225,19 +240,21 @@
// Find the cluster to which the device belongs.
TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId());
if (cluster == null) {
- throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId());
+ 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().get(cluster.id());
- return points == null || points.isEmpty() || points.contains(connectPoint);
+ return (points == null) || points.isEmpty() || points.contains(connectPoint);
}
/**
* Returns the size of the cluster broadcast set.
*
* @param clusterId cluster identifier
+ *
* @return size of the cluster broadcast set
*/
int broadcastSetSize(ClusterId clusterId) {
@@ -249,7 +266,9 @@
* destination devices.
*
* @param src source device
+ *
* @param dst destination device
+ *
* @return set of shortest paths
*/
Set<Path> getPaths(DeviceId src, DeviceId dst) {
@@ -260,9 +279,12 @@
* Computes on-demand the set of shortest paths between source and
* destination devices.
*
- * @param src source device
- * @param dst destination device
+ * @param src source device
+ *
+ * @param dst destination device
+ *
* @param weight link weight function
+ *
* @return set of shortest paths
*/
Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
@@ -283,7 +305,6 @@
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<>();
@@ -293,7 +314,6 @@
return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
}
-
// Searches for SCC clusters in the network topology graph using Tarjan
// algorithm.
private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() {
@@ -315,9 +335,10 @@
Set<TopologyEdge> edgeSet = clusterEdges.get(i);
ClusterId cid = ClusterId.clusterId(i);
- DefaultTopologyCluster cluster =
- new DefaultTopologyCluster(cid, vertexSet.size(), edgeSet.size(),
- findRoot(vertexSet));
+ DefaultTopologyCluster cluster = new DefaultTopologyCluster(cid,
+ vertexSet.size(),
+ edgeSet.size(),
+ findRoot(vertexSet));
clusterBuilder.put(cid, cluster);
}
return clusterBuilder.build();
@@ -328,9 +349,8 @@
private TopologyVertex findRoot(Set<TopologyVertex> vertexSet) {
TopologyVertex minVertex = null;
for (TopologyVertex vertex : vertexSet) {
- if (minVertex == null ||
- minVertex.deviceId().toString()
- .compareTo(minVertex.deviceId().toString()) < 0) {
+ if ((minVertex == null) || (minVertex.deviceId().toString()
+ .compareTo(minVertex.deviceId().toString()) < 0)) {
minVertex = vertex;
}
}
@@ -349,8 +369,7 @@
// Finds all broadcast points for the cluster. These are those connection
// points which lie along the shortest paths between the cluster root and
// all other devices within the cluster.
- private void addClusterBroadcastSet(TopologyCluster cluster,
- Builder<ClusterId, ConnectPoint> builder) {
+ private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) {
// Use the graph root search results to build the broadcast set.
Result<TopologyVertex, TopologyEdge> result =
DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
@@ -389,9 +408,12 @@
// Builds cluster-devices, cluster-links and device-cluster indexes.
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();
+ 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.get().values()) {
@@ -411,8 +433,7 @@
// Finalize all indexes.
return new ClusterIndexes(clusterBuilder.build(),
- devicesBuilder.build(),
- linksBuilder.build());
+ devicesBuilder.build(), linksBuilder.build());
}
// Link weight for measuring link cost as hop count with indirect links
@@ -428,8 +449,9 @@
public double weight(TopologyEdge edge) {
// To force preference to use direct paths first, make indirect
// links as expensive as the linear vertex traversal.
- return edge.link().state() == ACTIVE ?
- (edge.link().type() == INDIRECT ? indirectLinkCost : 1) : -1;
+ return edge.link().state() ==
+ ACTIVE ? (edge.link().type() ==
+ INDIRECT ? indirectLinkCost : 1) : -1;
}
}
@@ -437,7 +459,8 @@
private static class NoIndirectLinksWeight implements LinkWeight {
@Override
public double weight(TopologyEdge edge) {
- return edge.link().state() == INACTIVE || edge.link().type() == INDIRECT ? -1 : 1;
+ return (edge.link().state() == INACTIVE)
+ || (edge.link().type() == INDIRECT) ? -1 : 1;
}
}
@@ -446,9 +469,10 @@
final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
- public ClusterIndexes(ImmutableMap<DeviceId, TopologyCluster> clustersByDevice,
- ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster,
- 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;
@@ -459,10 +483,10 @@
public String toString() {
return toStringHelper(this)
.add("time", time)
+ .add("created", creationTime)
.add("computeCost", computeCost)
.add("clusters", clusterCount())
.add("devices", deviceCount())
- .add("links", linkCount())
- .toString();
+ .add("links", linkCount()).toString();
}
}
diff --git a/web/api/src/test/java/org/onosproject/rest/TopologyResourceTest.java b/web/api/src/test/java/org/onosproject/rest/TopologyResourceTest.java
index 745d341..da5f969 100644
--- a/web/api/src/test/java/org/onosproject/rest/TopologyResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/TopologyResourceTest.java
@@ -61,6 +61,11 @@
}
@Override
+ public long creationTime() {
+ return 22222L;
+ }
+
+ @Override
public long computeCost() {
return 0;
}