Abhishek Dwaraki
Committed by Ray Milkey

ONOS-400 Topology creation and up time formatting fixes

Change-Id: Iaf6d4dbbc1c7eaae9465a2d931d40f07a75ad07d
...@@ -15,7 +15,11 @@ ...@@ -15,7 +15,11 @@
15 */ 15 */
16 package org.onosproject.cli.net; 16 package org.onosproject.cli.net;
17 17
18 -import com.fasterxml.jackson.databind.ObjectMapper; 18 +import java.text.DateFormat;
19 +import java.text.SimpleDateFormat;
20 +import java.util.Calendar;
21 +import java.util.concurrent.TimeUnit;
22 +
19 import org.apache.karaf.shell.commands.Command; 23 import org.apache.karaf.shell.commands.Command;
20 import org.apache.karaf.shell.commands.Option; 24 import org.apache.karaf.shell.commands.Option;
21 import org.onosproject.cli.AbstractShellCommand; 25 import org.onosproject.cli.AbstractShellCommand;
...@@ -23,18 +27,20 @@ import org.onosproject.net.topology.Topology; ...@@ -23,18 +27,20 @@ import org.onosproject.net.topology.Topology;
23 import org.onosproject.net.topology.TopologyProvider; 27 import org.onosproject.net.topology.TopologyProvider;
24 import org.onosproject.net.topology.TopologyService; 28 import org.onosproject.net.topology.TopologyService;
25 29
30 +import com.fasterxml.jackson.databind.ObjectMapper;
31 +
26 /** 32 /**
27 * Lists summary of the current topology. 33 * Lists summary of the current topology.
28 */ 34 */
29 @Command(scope = "onos", name = "topology", 35 @Command(scope = "onos", name = "topology",
30 - description = "Lists summary of the current topology") 36 +description = "Lists summary of the current topology")
31 public class TopologyCommand extends AbstractShellCommand { 37 public class TopologyCommand extends AbstractShellCommand {
32 38
33 - private static final String FMT = 39 + private static final String FMT = "created=%s, uptime=%s, devices=%d, links=%d, clusters=%d";
34 - "time=%s, devices=%d, links=%d, clusters=%d";
35 40
36 - @Option(name = "-r", aliases = "--recompute", description = "Trigger topology re-computation", 41 + @Option(name = "-r", aliases = "--recompute",
37 - required = false, multiValued = false) 42 + description = "Trigger topology re-computation", required = false,
43 + multiValued = false)
38 private boolean recompute = false; 44 private boolean recompute = false;
39 45
40 protected TopologyService service; 46 protected TopologyService service;
...@@ -51,19 +57,75 @@ public class TopologyCommand extends AbstractShellCommand { ...@@ -51,19 +57,75 @@ public class TopologyCommand extends AbstractShellCommand {
51 @Override 57 @Override
52 protected void execute() { 58 protected void execute() {
53 init(); 59 init();
60 + long topologyUptime =
61 + Math.max(0, (System.currentTimeMillis() - topology.creationTime()));
54 if (recompute) { 62 if (recompute) {
55 get(TopologyProvider.class).triggerRecompute(); 63 get(TopologyProvider.class).triggerRecompute();
56 64
57 } else if (outputJson()) { 65 } else if (outputJson()) {
58 - print("%s", new ObjectMapper().createObjectNode() 66 + print("%s",
67 + new ObjectMapper()
68 + .createObjectNode()
59 .put("time", topology.time()) 69 .put("time", topology.time())
70 + .put("created", formatCreationTime(topology.creationTime()))
71 + .put("uptime", formatElapsedTime(topologyUptime))
60 .put("deviceCount", topology.deviceCount()) 72 .put("deviceCount", topology.deviceCount())
61 .put("linkCount", topology.linkCount()) 73 .put("linkCount", topology.linkCount())
62 .put("clusterCount", topology.clusterCount())); 74 .put("clusterCount", topology.clusterCount()));
63 } else { 75 } else {
64 - print(FMT, topology.time(), topology.deviceCount(), topology.linkCount(), 76 + print(FMT, formatCreationTime(topology.creationTime()),
77 + formatElapsedTime(topologyUptime),
78 + topology.deviceCount(), topology.linkCount(),
65 topology.clusterCount()); 79 topology.clusterCount());
66 } 80 }
67 } 81 }
68 82
83 + /**
84 + * Converts millis to a formatted elapsed time string.
85 + *
86 + * @param millis Duration in millis to convert to a string
87 + *
88 + * @return Formatted string: "D days, H hrs, M mins, S secs".
89 + */
90 + private static String formatElapsedTime(long millis) {
91 + if (millis < 0) {
92 + throw new IllegalArgumentException("Interval less than zero. "
93 + + "Possible unsynchronized timestamps");
94 + }
95 +
96 + final long days = TimeUnit.MILLISECONDS.toDays(millis);
97 + millis -= TimeUnit.DAYS.toMillis(days);
98 + final long hours = TimeUnit.MILLISECONDS.toHours(millis);
99 + millis -= TimeUnit.HOURS.toMillis(hours);
100 + final long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
101 + millis -= TimeUnit.MINUTES.toMillis(minutes);
102 + final long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
103 +
104 + final StringBuilder topologyUptimeString = new StringBuilder(64);
105 + topologyUptimeString.append(days);
106 + topologyUptimeString.append(" days, ");
107 + topologyUptimeString.append(hours);
108 + topologyUptimeString.append(" hrs, ");
109 + topologyUptimeString.append(minutes);
110 + topologyUptimeString.append(" mins, ");
111 + topologyUptimeString.append(seconds);
112 + topologyUptimeString.append(" secs");
113 +
114 + return (topologyUptimeString.toString());
115 + }
116 +
117 + /**
118 + * Converts millis to a formatted Date String.
119 + *
120 + * @param millis Duration in millis to convert to a string
121 + *
122 + * @return Formatted string: yyyy-MM-dd HH:mm:ss.
123 + */
124 + private static String formatCreationTime(long millis) {
125 + final DateFormat dateFormatter =
126 + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
127 + Calendar calendar = Calendar.getInstance();
128 + calendar.setTimeInMillis(millis);
129 + return (dateFormatter.format(calendar.getTime()));
130 + }
69 } 131 }
......
...@@ -34,30 +34,60 @@ import com.google.common.collect.Maps; ...@@ -34,30 +34,60 @@ import com.google.common.collect.Maps;
34 * Default implementation of an immutable topology graph data carrier. 34 * Default implementation of an immutable topology graph data carrier.
35 */ 35 */
36 public class DefaultGraphDescription extends AbstractDescription 36 public class DefaultGraphDescription extends AbstractDescription
37 - implements GraphDescription { 37 +implements GraphDescription {
38 38
39 private static final Logger log = getLogger(DefaultGraphDescription.class); 39 private static final Logger log = getLogger(DefaultGraphDescription.class);
40 40
41 private final long nanos; 41 private final long nanos;
42 + private final long creationTime;
42 private final ImmutableSet<TopologyVertex> vertexes; 43 private final ImmutableSet<TopologyVertex> vertexes;
43 private final ImmutableSet<TopologyEdge> edges; 44 private final ImmutableSet<TopologyEdge> edges;
44 45
45 - private final Map<DeviceId, TopologyVertex> vertexesById = Maps.newHashMap(); 46 + private final Map<DeviceId, TopologyVertex> vertexesById = Maps
47 + .newHashMap();
46 48
47 /** 49 /**
48 * Creates a minimal topology graph description to allow core to construct 50 * Creates a minimal topology graph description to allow core to construct
49 * and process the topology graph. 51 * and process the topology graph.
50 * 52 *
51 * @param nanos time in nanos of when the topology description was created 53 * @param nanos time in nanos of when the topology description was created
54 + *
52 * @param devices collection of infrastructure devices 55 * @param devices collection of infrastructure devices
56 + *
53 * @param links collection of infrastructure links 57 * @param links collection of infrastructure links
58 + *
54 * @param annotations optional key/value annotations map 59 * @param annotations optional key/value annotations map
60 + *
55 */ 61 */
62 + @Deprecated
56 public DefaultGraphDescription(long nanos, Iterable<Device> devices, 63 public DefaultGraphDescription(long nanos, Iterable<Device> devices,
57 Iterable<Link> links, 64 Iterable<Link> links,
58 SparseAnnotations... annotations) { 65 SparseAnnotations... annotations) {
66 + this(nanos, System.currentTimeMillis(), devices, links, annotations);
67 + }
68 +
69 + /**
70 + * Creates a minimal topology graph description to allow core to construct
71 + * and process the topology graph.
72 + *
73 + * @param nanos time in nanos of when the topology description was created
74 + *
75 + * @param millis time in millis of when the topology description was created
76 + *
77 + * @param devices collection of infrastructure devices
78 + *
79 + * @param links collection of infrastructure links
80 + *
81 + * @param annotations optional key/value annotations map
82 + *
83 + */
84 + public DefaultGraphDescription(long nanos, long millis,
85 + Iterable<Device> devices,
86 + Iterable<Link> links,
87 + SparseAnnotations... annotations) {
59 super(annotations); 88 super(annotations);
60 this.nanos = nanos; 89 this.nanos = nanos;
90 + this.creationTime = millis;
61 this.vertexes = buildVertexes(devices); 91 this.vertexes = buildVertexes(devices);
62 this.edges = buildEdges(links); 92 this.edges = buildEdges(links);
63 vertexesById.clear(); 93 vertexesById.clear();
...@@ -69,6 +99,11 @@ public class DefaultGraphDescription extends AbstractDescription ...@@ -69,6 +99,11 @@ public class DefaultGraphDescription extends AbstractDescription
69 } 99 }
70 100
71 @Override 101 @Override
102 + public long creationTime() {
103 + return creationTime;
104 + }
105 +
106 + @Override
72 public ImmutableSet<TopologyVertex> vertexes() { 107 public ImmutableSet<TopologyVertex> vertexes() {
73 return vertexes; 108 return vertexes;
74 } 109 }
...@@ -79,7 +114,8 @@ public class DefaultGraphDescription extends AbstractDescription ...@@ -79,7 +114,8 @@ public class DefaultGraphDescription extends AbstractDescription
79 } 114 }
80 115
81 // Builds a set of topology vertexes from the specified list of devices 116 // Builds a set of topology vertexes from the specified list of devices
82 - private ImmutableSet<TopologyVertex> buildVertexes(Iterable<Device> devices) { 117 + private ImmutableSet<TopologyVertex>
118 + buildVertexes(Iterable<Device> devices) {
83 ImmutableSet.Builder<TopologyVertex> vertexes = ImmutableSet.builder(); 119 ImmutableSet.Builder<TopologyVertex> vertexes = ImmutableSet.builder();
84 for (Device device : devices) { 120 for (Device device : devices) {
85 TopologyVertex vertex = new DefaultTopologyVertex(device.id()); 121 TopologyVertex vertex = new DefaultTopologyVertex(device.id());
...@@ -95,7 +131,8 @@ public class DefaultGraphDescription extends AbstractDescription ...@@ -95,7 +131,8 @@ public class DefaultGraphDescription extends AbstractDescription
95 for (Link link : links) { 131 for (Link link : links) {
96 try { 132 try {
97 edges.add(new DefaultTopologyEdge(vertexOf(link.src()), 133 edges.add(new DefaultTopologyEdge(vertexOf(link.src()),
98 - vertexOf(link.dst()), link)); 134 + vertexOf(link.dst()),
135 + link));
99 } catch (IllegalArgumentException e) { 136 } catch (IllegalArgumentException e) {
100 log.debug("Ignoring {}, missing vertex", link); 137 log.debug("Ignoring {}, missing vertex", link);
101 } 138 }
......
...@@ -15,9 +15,10 @@ ...@@ -15,9 +15,10 @@
15 */ 15 */
16 package org.onosproject.net.topology; 16 package org.onosproject.net.topology;
17 17
18 -import com.google.common.collect.ImmutableSet;
19 import org.onosproject.net.Description; 18 import org.onosproject.net.Description;
20 19
20 +import com.google.common.collect.ImmutableSet;
21 +
21 /** 22 /**
22 * Describes attribute(s) of a network graph. 23 * Describes attribute(s) of a network graph.
23 */ 24 */
...@@ -32,6 +33,14 @@ public interface GraphDescription extends Description { ...@@ -32,6 +33,14 @@ public interface GraphDescription extends Description {
32 long timestamp(); 33 long timestamp();
33 34
34 /** 35 /**
36 + * Returns the creation timestamp of the graph description. This is
37 + * expressed in system millis to allow proper date and time formatting.
38 + *
39 + * @return graph description creation timestamp in millis
40 + */
41 + long creationTime();
42 +
43 + /**
35 * Returns the set of topology graph vertexes. 44 * Returns the set of topology graph vertexes.
36 * 45 *
37 * @return set of graph vertexes 46 * @return set of graph vertexes
...@@ -46,4 +55,3 @@ public interface GraphDescription extends Description { ...@@ -46,4 +55,3 @@ public interface GraphDescription extends Description {
46 ImmutableSet<TopologyEdge> edges(); 55 ImmutableSet<TopologyEdge> edges();
47 56
48 } 57 }
49 -
......
...@@ -23,16 +23,24 @@ import org.onosproject.net.Provided; ...@@ -23,16 +23,24 @@ import org.onosproject.net.Provided;
23 public interface Topology extends Provided { 23 public interface Topology extends Provided {
24 24
25 /** 25 /**
26 - * Returns the time, specified in system nanos of when the topology 26 + * Returns the time, specified in system nanos of when the topology became
27 - * became available. 27 + * available.
28 * 28 *
29 * @return time in system nanos 29 * @return time in system nanos
30 */ 30 */
31 long time(); 31 long time();
32 32
33 /** 33 /**
34 - * Returns the time, specified in system nanos of how long the topology 34 + * Returns the time, specified in system millis of when the topology became
35 - * took to compute. 35 + * available.
36 + *
37 + * @return time in system nanos
38 + */
39 + long creationTime();
40 +
41 + /**
42 + * Returns the time, specified in system nanos of how long the topology took
43 + * to compute.
36 * 44 *
37 * @return elapsed time in system nanos 45 * @return elapsed time in system nanos
38 */ 46 */
...@@ -53,7 +61,6 @@ public interface Topology extends Provided { ...@@ -53,7 +61,6 @@ public interface Topology extends Provided {
53 */ 61 */
54 int deviceCount(); 62 int deviceCount();
55 63
56 -
57 /** 64 /**
58 * Returns the number of infrastructure links in the topology. 65 * Returns the number of infrastructure links in the topology.
59 * 66 *
......
...@@ -15,7 +15,21 @@ ...@@ -15,7 +15,21 @@
15 */ 15 */
16 package org.onosproject.net.topology.impl; 16 package org.onosproject.net.topology.impl;
17 17
18 -import com.google.common.collect.ImmutableList; 18 +import static com.google.common.base.Strings.isNullOrEmpty;
19 +import static java.util.concurrent.Executors.newFixedThreadPool;
20 +import static org.onlab.util.Tools.groupedThreads;
21 +import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
22 +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
23 +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
24 +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
25 +import static org.slf4j.LoggerFactory.getLogger;
26 +
27 +import java.util.Collections;
28 +import java.util.Dictionary;
29 +import java.util.List;
30 +import java.util.Timer;
31 +import java.util.concurrent.ExecutorService;
32 +
19 import org.apache.felix.scr.annotations.Activate; 33 import org.apache.felix.scr.annotations.Activate;
20 import org.apache.felix.scr.annotations.Component; 34 import org.apache.felix.scr.annotations.Component;
21 import org.apache.felix.scr.annotations.Deactivate; 35 import org.apache.felix.scr.annotations.Deactivate;
...@@ -42,28 +56,16 @@ import org.onosproject.net.topology.TopologyProviderService; ...@@ -42,28 +56,16 @@ import org.onosproject.net.topology.TopologyProviderService;
42 import org.osgi.service.component.ComponentContext; 56 import org.osgi.service.component.ComponentContext;
43 import org.slf4j.Logger; 57 import org.slf4j.Logger;
44 58
45 -import java.util.Collections; 59 +import com.google.common.collect.ImmutableList;
46 -import java.util.Dictionary;
47 -import java.util.List;
48 -import java.util.Timer;
49 -import java.util.concurrent.ExecutorService;
50 -
51 -import static com.google.common.base.Strings.isNullOrEmpty;
52 -import static java.util.concurrent.Executors.newFixedThreadPool;
53 -import static org.onlab.util.Tools.groupedThreads;
54 -import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
55 -import static org.onosproject.net.device.DeviceEvent.Type.*;
56 -import static org.slf4j.LoggerFactory.getLogger;
57 60
58 /** 61 /**
59 - * Default implementation of a network topology provider that feeds off 62 + * Default implementation of a network topology provider that feeds off device
60 - * device and link subsystem events to trigger assembly and computation of 63 + * and link subsystem events to trigger assembly and computation of new topology
61 - * new topology snapshots. 64 + * snapshots.
62 */ 65 */
63 @Component(immediate = true) 66 @Component(immediate = true)
64 @Service 67 @Service
65 -public class DefaultTopologyProvider extends AbstractProvider 68 +public class DefaultTopologyProvider extends AbstractProvider implements TopologyProvider {
66 - implements TopologyProvider {
67 69
68 private static final int MAX_THREADS = 8; 70 private static final int MAX_THREADS = 8;
69 private static final int DEFAULT_MAX_EVENTS = 1000; 71 private static final int DEFAULT_MAX_EVENTS = 1000;
...@@ -71,7 +73,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -71,7 +73,8 @@ public class DefaultTopologyProvider extends AbstractProvider
71 private static final int DEFAULT_MAX_BATCH_MS = 50; 73 private static final int DEFAULT_MAX_BATCH_MS = 50;
72 74
73 // FIXME: Replace with a system-wide timer instance; 75 // FIXME: Replace with a system-wide timer instance;
74 - // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt 76 + // TODO: Convert to use HashedWheelTimer or produce a variant of that; then
77 + // decide which we want to adopt
75 private static final Timer TIMER = new Timer("onos-topo-event-batching"); 78 private static final Timer TIMER = new Timer("onos-topo-event-batching");
76 79
77 @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS, 80 @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS,
...@@ -100,8 +103,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -100,8 +103,8 @@ public class DefaultTopologyProvider extends AbstractProvider
100 private volatile boolean isStarted = false; 103 private volatile boolean isStarted = false;
101 104
102 private TopologyProviderService providerService; 105 private TopologyProviderService providerService;
103 - private DeviceListener deviceListener = new InternalDeviceListener(); 106 + private final DeviceListener deviceListener = new InternalDeviceListener();
104 - private LinkListener linkListener = new InternalLinkListener(); 107 + private final LinkListener linkListener = new InternalLinkListener();
105 108
106 private Accumulator<Event> accumulator; 109 private Accumulator<Event> accumulator;
107 private ExecutorService executor; 110 private ExecutorService executor;
...@@ -115,7 +118,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -115,7 +118,8 @@ public class DefaultTopologyProvider extends AbstractProvider
115 118
116 @Activate 119 @Activate
117 public synchronized void activate(ComponentContext context) { 120 public synchronized void activate(ComponentContext context) {
118 - executor = newFixedThreadPool(MAX_THREADS, groupedThreads("onos/topo", "build-%d")); 121 + executor = newFixedThreadPool(MAX_THREADS,
122 + groupedThreads("onos/topo", "build-%d"));
119 accumulator = new TopologyChangeAccumulator(); 123 accumulator = new TopologyChangeAccumulator();
120 logConfig("Configured"); 124 logConfig("Configured");
121 125
...@@ -171,21 +175,23 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -171,21 +175,23 @@ public class DefaultTopologyProvider extends AbstractProvider
171 newMaxIdleMs = DEFAULT_MAX_IDLE_MS; 175 newMaxIdleMs = DEFAULT_MAX_IDLE_MS;
172 } 176 }
173 177
174 - if (newMaxEvents != maxEvents || newMaxBatchMs != maxBatchMs || newMaxIdleMs != maxIdleMs) { 178 + if ((newMaxEvents != maxEvents) || (newMaxBatchMs != maxBatchMs)
179 + || (newMaxIdleMs != maxIdleMs)) {
175 maxEvents = newMaxEvents; 180 maxEvents = newMaxEvents;
176 maxBatchMs = newMaxBatchMs; 181 maxBatchMs = newMaxBatchMs;
177 maxIdleMs = newMaxIdleMs; 182 maxIdleMs = newMaxIdleMs;
178 - accumulator = maxEvents > 1 ? new TopologyChangeAccumulator() : null; 183 + accumulator = maxEvents > 1 ? new TopologyChangeAccumulator()
184 + : null;
179 logConfig("Reconfigured"); 185 logConfig("Reconfigured");
180 } 186 }
181 } 187 }
182 188
183 private void logConfig(String prefix) { 189 private void logConfig(String prefix) {
184 - log.info("{} with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}; accumulator={}", 190 + log.info(
191 + "{} with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}; accumulator={}",
185 prefix, maxEvents, maxBatchMs, maxIdleMs, accumulator != null); 192 prefix, maxEvents, maxBatchMs, maxIdleMs, accumulator != null);
186 } 193 }
187 194
188 -
189 @Override 195 @Override
190 public void triggerRecompute() { 196 public void triggerRecompute() {
191 triggerTopologyBuild(Collections.<Event>emptyList()); 197 triggerTopologyBuild(Collections.<Event>emptyList());
...@@ -195,7 +201,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -195,7 +201,8 @@ public class DefaultTopologyProvider extends AbstractProvider
195 * Triggers assembly of topology data citing the specified events as the 201 * Triggers assembly of topology data citing the specified events as the
196 * reason. 202 * reason.
197 * 203 *
198 - * @param reasons events which triggered the topology change 204 + * @param reasons
205 + * events which triggered the topology change
199 */ 206 */
200 private synchronized void triggerTopologyBuild(List<Event> reasons) { 207 private synchronized void triggerTopologyBuild(List<Event> reasons) {
201 if (executor != null) { 208 if (executor != null) {
...@@ -209,6 +216,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -209,6 +216,7 @@ public class DefaultTopologyProvider extends AbstractProvider
209 if (isStarted) { 216 if (isStarted) {
210 GraphDescription desc = 217 GraphDescription desc =
211 new DefaultGraphDescription(System.nanoTime(), 218 new DefaultGraphDescription(System.nanoTime(),
219 + System.currentTimeMillis(),
212 deviceService.getAvailableDevices(), 220 deviceService.getAvailableDevices(),
213 linkService.getActiveLinks()); 221 linkService.getActiveLinks());
214 providerService.topologyChanged(desc, reasons); 222 providerService.topologyChanged(desc, reasons);
...@@ -228,8 +236,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -228,8 +236,8 @@ public class DefaultTopologyProvider extends AbstractProvider
228 @Override 236 @Override
229 public void event(DeviceEvent event) { 237 public void event(DeviceEvent event) {
230 DeviceEvent.Type type = event.type(); 238 DeviceEvent.Type type = event.type();
231 - if (type == DEVICE_ADDED || type == DEVICE_REMOVED || 239 + if ((type == DEVICE_ADDED) || (type == DEVICE_REMOVED) ||
232 - type == DEVICE_AVAILABILITY_CHANGED) { 240 + (type == DEVICE_AVAILABILITY_CHANGED)) {
233 processEvent(event); 241 processEvent(event);
234 } 242 }
235 } 243 }
...@@ -268,7 +276,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -268,7 +276,8 @@ public class DefaultTopologyProvider extends AbstractProvider
268 try { 276 try {
269 buildTopology(reasons); 277 buildTopology(reasons);
270 } catch (Exception e) { 278 } catch (Exception e) {
271 - log.warn("Unable to compute topology due to: {}", e.getMessage()); 279 + log.warn("Unable to compute topology due to: {}",
280 + e.getMessage());
272 log.debug("Unable to compute topology", e); 281 log.debug("Unable to compute topology", e);
273 } 282 }
274 } 283 }
......
...@@ -15,11 +15,18 @@ ...@@ -15,11 +15,18 @@
15 */ 15 */
16 package org.onosproject.store.topology.impl; 16 package org.onosproject.store.topology.impl;
17 17
18 -import com.google.common.base.Supplier; 18 +import static com.google.common.base.MoreObjects.toStringHelper;
19 -import com.google.common.base.Suppliers; 19 +import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
20 -import com.google.common.collect.ImmutableMap; 20 +import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
21 -import com.google.common.collect.ImmutableSet; 21 +import static org.onosproject.net.Link.State.ACTIVE;
22 -import com.google.common.collect.ImmutableSetMultimap; 22 +import static org.onosproject.net.Link.State.INACTIVE;
23 +import static org.onosproject.net.Link.Type.INDIRECT;
24 +
25 +import java.util.ArrayList;
26 +import java.util.List;
27 +import java.util.Map;
28 +import java.util.Set;
29 +
23 import org.onlab.graph.DijkstraGraphSearch; 30 import org.onlab.graph.DijkstraGraphSearch;
24 import org.onlab.graph.GraphPathSearch; 31 import org.onlab.graph.GraphPathSearch;
25 import org.onlab.graph.GraphPathSearch.Result; 32 import org.onlab.graph.GraphPathSearch.Result;
...@@ -43,32 +50,25 @@ import org.onosproject.net.topology.TopologyEdge; ...@@ -43,32 +50,25 @@ import org.onosproject.net.topology.TopologyEdge;
43 import org.onosproject.net.topology.TopologyGraph; 50 import org.onosproject.net.topology.TopologyGraph;
44 import org.onosproject.net.topology.TopologyVertex; 51 import org.onosproject.net.topology.TopologyVertex;
45 52
46 -import java.util.ArrayList; 53 +import com.google.common.base.Supplier;
47 -import java.util.List; 54 +import com.google.common.base.Suppliers;
48 -import java.util.Map; 55 +import com.google.common.collect.ImmutableMap;
49 -import java.util.Set; 56 +import com.google.common.collect.ImmutableSet;
50 - 57 +import com.google.common.collect.ImmutableSetMultimap;
51 -import static com.google.common.base.MoreObjects.toStringHelper; 58 +import com.google.common.collect.ImmutableSetMultimap.Builder;
52 -import static com.google.common.collect.ImmutableSetMultimap.Builder;
53 -import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
54 -import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
55 -import static org.onosproject.net.Link.State.ACTIVE;
56 -import static org.onosproject.net.Link.State.INACTIVE;
57 -import static org.onosproject.net.Link.Type.INDIRECT;
58 59
59 // FIXME: Move to onos-core-common when ready 60 // FIXME: Move to onos-core-common when ready
60 /** 61 /**
61 - * Default implementation of the topology descriptor. This carries the 62 + * Default implementation of the topology descriptor. This carries the backing
62 - * backing topology data. 63 + * topology data.
63 */ 64 */
64 public class DefaultTopology extends AbstractModel implements Topology { 65 public class DefaultTopology extends AbstractModel implements Topology {
65 66
66 - private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = 67 + private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
67 - new DijkstraGraphSearch<>(); 68 + private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
68 - private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN =
69 - new TarjanGraphSearch<>();
70 69
71 private final long time; 70 private final long time;
71 + private final long creationTime;
72 private final long computeCost; 72 private final long computeCost;
73 private final TopologyGraph graph; 73 private final TopologyGraph graph;
74 74
...@@ -83,12 +83,15 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -83,12 +83,15 @@ public class DefaultTopology extends AbstractModel implements Topology {
83 /** 83 /**
84 * Creates a topology descriptor attributed to the specified provider. 84 * Creates a topology descriptor attributed to the specified provider.
85 * 85 *
86 - * @param providerId identity of the provider 86 + * @param providerId
87 - * @param description data describing the new topology 87 + * identity of the provider
88 + * @param description
89 + * data describing the new topology
88 */ 90 */
89 DefaultTopology(ProviderId providerId, GraphDescription description) { 91 DefaultTopology(ProviderId providerId, GraphDescription description) {
90 super(providerId); 92 super(providerId);
91 this.time = description.timestamp(); 93 this.time = description.timestamp();
94 + this.creationTime = description.creationTime();
92 95
93 // Build the graph 96 // Build the graph
94 this.graph = new DefaultTopologyGraph(description.vertexes(), 97 this.graph = new DefaultTopologyGraph(description.vertexes(),
...@@ -101,7 +104,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -101,7 +104,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
101 104
102 this.weight = new HopCountLinkWeight(graph.getVertexes().size()); 105 this.weight = new HopCountLinkWeight(graph.getVertexes().size());
103 this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets()); 106 this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
104 - this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints()); 107 + this.infrastructurePoints = Suppliers
108 + .memoize(() -> findInfrastructurePoints());
105 this.computeCost = Math.max(0, System.nanoTime() - time); 109 this.computeCost = Math.max(0, System.nanoTime() - time);
106 } 110 }
107 111
...@@ -111,6 +115,11 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -111,6 +115,11 @@ public class DefaultTopology extends AbstractModel implements Topology {
111 } 115 }
112 116
113 @Override 117 @Override
118 + public long creationTime() {
119 + return creationTime;
120 + }
121 +
122 + @Override
114 public long computeCost() { 123 public long computeCost() {
115 return computeCost; 124 return computeCost;
116 } 125 }
...@@ -164,6 +173,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -164,6 +173,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
164 * Returns the specified topology cluster. 173 * Returns the specified topology cluster.
165 * 174 *
166 * @param clusterId cluster identifier 175 * @param clusterId cluster identifier
176 + *
167 * @return topology cluster 177 * @return topology cluster
168 */ 178 */
169 TopologyCluster getCluster(ClusterId clusterId) { 179 TopologyCluster getCluster(ClusterId clusterId) {
...@@ -174,6 +184,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -174,6 +184,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
174 * Returns the topology cluster that contains the given device. 184 * Returns the topology cluster that contains the given device.
175 * 185 *
176 * @param deviceId device identifier 186 * @param deviceId device identifier
187 + *
177 * @return topology cluster 188 * @return topology cluster
178 */ 189 */
179 TopologyCluster getCluster(DeviceId deviceId) { 190 TopologyCluster getCluster(DeviceId deviceId) {
...@@ -184,6 +195,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -184,6 +195,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
184 * Returns the set of cluster devices. 195 * Returns the set of cluster devices.
185 * 196 *
186 * @param cluster topology cluster 197 * @param cluster topology cluster
198 + *
187 * @return cluster devices 199 * @return cluster devices
188 */ 200 */
189 Set<DeviceId> getClusterDevices(TopologyCluster cluster) { 201 Set<DeviceId> getClusterDevices(TopologyCluster cluster) {
...@@ -194,6 +206,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -194,6 +206,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
194 * Returns the set of cluster links. 206 * Returns the set of cluster links.
195 * 207 *
196 * @param cluster topology cluster 208 * @param cluster topology cluster
209 + *
197 * @return cluster links 210 * @return cluster links
198 */ 211 */
199 Set<Link> getClusterLinks(TopologyCluster cluster) { 212 Set<Link> getClusterLinks(TopologyCluster cluster) {
...@@ -204,6 +217,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -204,6 +217,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
204 * Indicates whether the given point is an infrastructure link end-point. 217 * Indicates whether the given point is an infrastructure link end-point.
205 * 218 *
206 * @param connectPoint connection point 219 * @param connectPoint connection point
220 + *
207 * @return true if infrastructure 221 * @return true if infrastructure
208 */ 222 */
209 boolean isInfrastructure(ConnectPoint connectPoint) { 223 boolean isInfrastructure(ConnectPoint connectPoint) {
...@@ -214,6 +228,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -214,6 +228,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
214 * Indicates whether the given point is part of a broadcast set. 228 * Indicates whether the given point is part of a broadcast set.
215 * 229 *
216 * @param connectPoint connection point 230 * @param connectPoint connection point
231 + *
217 * @return true if in broadcast set 232 * @return true if in broadcast set
218 */ 233 */
219 boolean isBroadcastPoint(ConnectPoint connectPoint) { 234 boolean isBroadcastPoint(ConnectPoint connectPoint) {
...@@ -225,19 +240,21 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -225,19 +240,21 @@ public class DefaultTopology extends AbstractModel implements Topology {
225 // Find the cluster to which the device belongs. 240 // Find the cluster to which the device belongs.
226 TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId()); 241 TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId());
227 if (cluster == null) { 242 if (cluster == null) {
228 - throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId()); 243 + throw new IllegalArgumentException("No cluster found for device "
244 + + connectPoint.deviceId());
229 } 245 }
230 246
231 // If the broadcast set is null or empty, or if the point explicitly 247 // If the broadcast set is null or empty, or if the point explicitly
232 // belongs to it, return true; 248 // belongs to it, return true;
233 Set<ConnectPoint> points = broadcastSets.get().get(cluster.id()); 249 Set<ConnectPoint> points = broadcastSets.get().get(cluster.id());
234 - return points == null || points.isEmpty() || points.contains(connectPoint); 250 + return (points == null) || points.isEmpty() || points.contains(connectPoint);
235 } 251 }
236 252
237 /** 253 /**
238 * Returns the size of the cluster broadcast set. 254 * Returns the size of the cluster broadcast set.
239 * 255 *
240 * @param clusterId cluster identifier 256 * @param clusterId cluster identifier
257 + *
241 * @return size of the cluster broadcast set 258 * @return size of the cluster broadcast set
242 */ 259 */
243 int broadcastSetSize(ClusterId clusterId) { 260 int broadcastSetSize(ClusterId clusterId) {
...@@ -249,7 +266,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -249,7 +266,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
249 * destination devices. 266 * destination devices.
250 * 267 *
251 * @param src source device 268 * @param src source device
269 + *
252 * @param dst destination device 270 * @param dst destination device
271 + *
253 * @return set of shortest paths 272 * @return set of shortest paths
254 */ 273 */
255 Set<Path> getPaths(DeviceId src, DeviceId dst) { 274 Set<Path> getPaths(DeviceId src, DeviceId dst) {
...@@ -261,8 +280,11 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -261,8 +280,11 @@ public class DefaultTopology extends AbstractModel implements Topology {
261 * destination devices. 280 * destination devices.
262 * 281 *
263 * @param src source device 282 * @param src source device
283 + *
264 * @param dst destination device 284 * @param dst destination device
285 + *
265 * @param weight link weight function 286 * @param weight link weight function
287 + *
266 * @return set of shortest paths 288 * @return set of shortest paths
267 */ 289 */
268 Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { 290 Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
...@@ -283,7 +305,6 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -283,7 +305,6 @@ public class DefaultTopology extends AbstractModel implements Topology {
283 return builder.build(); 305 return builder.build();
284 } 306 }
285 307
286 -
287 // Converts graph path to a network path with the same cost. 308 // Converts graph path to a network path with the same cost.
288 private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) { 309 private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
289 List<Link> links = new ArrayList<>(); 310 List<Link> links = new ArrayList<>();
...@@ -293,7 +314,6 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -293,7 +314,6 @@ public class DefaultTopology extends AbstractModel implements Topology {
293 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost()); 314 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
294 } 315 }
295 316
296 -
297 // Searches for SCC clusters in the network topology graph using Tarjan 317 // Searches for SCC clusters in the network topology graph using Tarjan
298 // algorithm. 318 // algorithm.
299 private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() { 319 private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() {
...@@ -315,8 +335,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -315,8 +335,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
315 Set<TopologyEdge> edgeSet = clusterEdges.get(i); 335 Set<TopologyEdge> edgeSet = clusterEdges.get(i);
316 336
317 ClusterId cid = ClusterId.clusterId(i); 337 ClusterId cid = ClusterId.clusterId(i);
318 - DefaultTopologyCluster cluster = 338 + DefaultTopologyCluster cluster = new DefaultTopologyCluster(cid,
319 - new DefaultTopologyCluster(cid, vertexSet.size(), edgeSet.size(), 339 + vertexSet.size(),
340 + edgeSet.size(),
320 findRoot(vertexSet)); 341 findRoot(vertexSet));
321 clusterBuilder.put(cid, cluster); 342 clusterBuilder.put(cid, cluster);
322 } 343 }
...@@ -328,9 +349,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -328,9 +349,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
328 private TopologyVertex findRoot(Set<TopologyVertex> vertexSet) { 349 private TopologyVertex findRoot(Set<TopologyVertex> vertexSet) {
329 TopologyVertex minVertex = null; 350 TopologyVertex minVertex = null;
330 for (TopologyVertex vertex : vertexSet) { 351 for (TopologyVertex vertex : vertexSet) {
331 - if (minVertex == null || 352 + if ((minVertex == null) || (minVertex.deviceId()
332 - minVertex.deviceId().toString() 353 + .toString().compareTo(minVertex.deviceId().toString()) < 0)) {
333 - .compareTo(minVertex.deviceId().toString()) < 0) {
334 minVertex = vertex; 354 minVertex = vertex;
335 } 355 }
336 } 356 }
...@@ -339,7 +359,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -339,7 +359,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
339 359
340 // Processes a map of broadcast sets for each cluster. 360 // Processes a map of broadcast sets for each cluster.
341 private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() { 361 private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() {
342 - Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder(); 362 + Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap
363 + .builder();
343 for (TopologyCluster cluster : clusters.get().values()) { 364 for (TopologyCluster cluster : clusters.get().values()) {
344 addClusterBroadcastSet(cluster, builder); 365 addClusterBroadcastSet(cluster, builder);
345 } 366 }
...@@ -349,11 +370,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -349,11 +370,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
349 // Finds all broadcast points for the cluster. These are those connection 370 // Finds all broadcast points for the cluster. These are those connection
350 // points which lie along the shortest paths between the cluster root and 371 // points which lie along the shortest paths between the cluster root and
351 // all other devices within the cluster. 372 // all other devices within the cluster.
352 - private void addClusterBroadcastSet(TopologyCluster cluster, 373 + private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) {
353 - Builder<ClusterId, ConnectPoint> builder) {
354 // Use the graph root search results to build the broadcast set. 374 // Use the graph root search results to build the broadcast set.
355 - Result<TopologyVertex, TopologyEdge> result = 375 + Result<TopologyVertex, TopologyEdge> result = DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
356 - DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
357 for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) { 376 for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) {
358 TopologyVertex vertex = entry.getKey(); 377 TopologyVertex vertex = entry.getKey();
359 378
...@@ -389,9 +408,12 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -389,9 +408,12 @@ public class DefaultTopology extends AbstractModel implements Topology {
389 // Builds cluster-devices, cluster-links and device-cluster indexes. 408 // Builds cluster-devices, cluster-links and device-cluster indexes.
390 private ClusterIndexes buildIndexes() { 409 private ClusterIndexes buildIndexes() {
391 // Prepare the index builders 410 // Prepare the index builders
392 - ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder = ImmutableMap.builder(); 411 + ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder =
393 - ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder = ImmutableSetMultimap.builder(); 412 + ImmutableMap.builder();
394 - ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder = ImmutableSetMultimap.builder(); 413 + ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder =
414 + ImmutableSetMultimap.builder();
415 + ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder =
416 + ImmutableSetMultimap.builder();
395 417
396 // Now scan through all the clusters 418 // Now scan through all the clusters
397 for (TopologyCluster cluster : clusters.get().values()) { 419 for (TopologyCluster cluster : clusters.get().values()) {
...@@ -428,8 +450,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -428,8 +450,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
428 public double weight(TopologyEdge edge) { 450 public double weight(TopologyEdge edge) {
429 // To force preference to use direct paths first, make indirect 451 // To force preference to use direct paths first, make indirect
430 // links as expensive as the linear vertex traversal. 452 // links as expensive as the linear vertex traversal.
431 - return edge.link().state() == ACTIVE ? 453 + return edge.link().state() ==
432 - (edge.link().type() == INDIRECT ? indirectLinkCost : 1) : -1; 454 + ACTIVE ? (edge.link().type() ==
455 + INDIRECT ? indirectLinkCost : 1) : -1;
433 } 456 }
434 } 457 }
435 458
...@@ -437,7 +460,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -437,7 +460,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
437 private static class NoIndirectLinksWeight implements LinkWeight { 460 private static class NoIndirectLinksWeight implements LinkWeight {
438 @Override 461 @Override
439 public double weight(TopologyEdge edge) { 462 public double weight(TopologyEdge edge) {
440 - return edge.link().state() == INACTIVE || edge.link().type() == INDIRECT ? -1 : 1; 463 + return (edge.link().state() == INACTIVE)
464 + || (edge.link().type() == INDIRECT) ? -1 : 1;
441 } 465 }
442 } 466 }
443 467
...@@ -446,7 +470,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -446,7 +470,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
446 final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster; 470 final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
447 final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster; 471 final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
448 472
449 - public ClusterIndexes(ImmutableMap<DeviceId, TopologyCluster> clustersByDevice, 473 + public ClusterIndexes(
474 + ImmutableMap<DeviceId, TopologyCluster> clustersByDevice,
450 ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster, 475 ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster,
451 ImmutableSetMultimap<TopologyCluster, Link> linksByCluster) { 476 ImmutableSetMultimap<TopologyCluster, Link> linksByCluster) {
452 this.clustersByDevice = clustersByDevice; 477 this.clustersByDevice = clustersByDevice;
...@@ -459,10 +484,10 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -459,10 +484,10 @@ public class DefaultTopology extends AbstractModel implements Topology {
459 public String toString() { 484 public String toString() {
460 return toStringHelper(this) 485 return toStringHelper(this)
461 .add("time", time) 486 .add("time", time)
487 + .add("creationTime", creationTime)
462 .add("computeCost", computeCost) 488 .add("computeCost", computeCost)
463 .add("clusters", clusterCount()) 489 .add("clusters", clusterCount())
464 .add("devices", deviceCount()) 490 .add("devices", deviceCount())
465 - .add("links", linkCount()) 491 + .add("links", linkCount()).toString();
466 - .toString();
467 } 492 }
468 } 493 }
......
...@@ -15,11 +15,18 @@ ...@@ -15,11 +15,18 @@
15 */ 15 */
16 package org.onosproject.store.trivial.impl; 16 package org.onosproject.store.trivial.impl;
17 17
18 -import com.google.common.base.Supplier; 18 +import static com.google.common.base.MoreObjects.toStringHelper;
19 -import com.google.common.base.Suppliers; 19 +import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
20 -import com.google.common.collect.ImmutableMap; 20 +import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
21 -import com.google.common.collect.ImmutableSet; 21 +import static org.onosproject.net.Link.State.ACTIVE;
22 -import com.google.common.collect.ImmutableSetMultimap; 22 +import static org.onosproject.net.Link.State.INACTIVE;
23 +import static org.onosproject.net.Link.Type.INDIRECT;
24 +
25 +import java.util.ArrayList;
26 +import java.util.List;
27 +import java.util.Map;
28 +import java.util.Set;
29 +
23 import org.onlab.graph.DijkstraGraphSearch; 30 import org.onlab.graph.DijkstraGraphSearch;
24 import org.onlab.graph.GraphPathSearch; 31 import org.onlab.graph.GraphPathSearch;
25 import org.onlab.graph.GraphPathSearch.Result; 32 import org.onlab.graph.GraphPathSearch.Result;
...@@ -43,32 +50,25 @@ import org.onosproject.net.topology.TopologyEdge; ...@@ -43,32 +50,25 @@ import org.onosproject.net.topology.TopologyEdge;
43 import org.onosproject.net.topology.TopologyGraph; 50 import org.onosproject.net.topology.TopologyGraph;
44 import org.onosproject.net.topology.TopologyVertex; 51 import org.onosproject.net.topology.TopologyVertex;
45 52
46 -import java.util.ArrayList; 53 +import com.google.common.base.Supplier;
47 -import java.util.List; 54 +import com.google.common.base.Suppliers;
48 -import java.util.Map; 55 +import com.google.common.collect.ImmutableMap;
49 -import java.util.Set; 56 +import com.google.common.collect.ImmutableSet;
50 - 57 +import com.google.common.collect.ImmutableSetMultimap;
51 -import static com.google.common.base.MoreObjects.toStringHelper; 58 +import com.google.common.collect.ImmutableSetMultimap.Builder;
52 -import static com.google.common.collect.ImmutableSetMultimap.Builder;
53 -import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
54 -import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
55 -import static org.onosproject.net.Link.State.ACTIVE;
56 -import static org.onosproject.net.Link.State.INACTIVE;
57 -import static org.onosproject.net.Link.Type.INDIRECT;
58 59
59 // FIXME: Move to onos-core-common when ready 60 // FIXME: Move to onos-core-common when ready
60 /** 61 /**
61 - * Default implementation of the topology descriptor. This carries the 62 + * Default implementation of the topology descriptor. This carries the backing
62 - * backing topology data. 63 + * topology data.
63 */ 64 */
64 public class DefaultTopology extends AbstractModel implements Topology { 65 public class DefaultTopology extends AbstractModel implements Topology {
65 66
66 - private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = 67 + private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
67 - new DijkstraGraphSearch<>(); 68 + private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
68 - private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN =
69 - new TarjanGraphSearch<>();
70 69
71 private final long time; 70 private final long time;
71 + private final long creationTime;
72 private final long computeCost; 72 private final long computeCost;
73 private final TopologyGraph graph; 73 private final TopologyGraph graph;
74 74
...@@ -83,12 +83,15 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -83,12 +83,15 @@ public class DefaultTopology extends AbstractModel implements Topology {
83 /** 83 /**
84 * Creates a topology descriptor attributed to the specified provider. 84 * Creates a topology descriptor attributed to the specified provider.
85 * 85 *
86 - * @param providerId identity of the provider 86 + * @param providerId
87 - * @param description data describing the new topology 87 + * identity of the provider
88 + * @param description
89 + * data describing the new topology
88 */ 90 */
89 DefaultTopology(ProviderId providerId, GraphDescription description) { 91 DefaultTopology(ProviderId providerId, GraphDescription description) {
90 super(providerId); 92 super(providerId);
91 this.time = description.timestamp(); 93 this.time = description.timestamp();
94 + this.creationTime = description.creationTime();
92 95
93 // Build the graph 96 // Build the graph
94 this.graph = new DefaultTopologyGraph(description.vertexes(), 97 this.graph = new DefaultTopologyGraph(description.vertexes(),
...@@ -101,7 +104,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -101,7 +104,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
101 104
102 this.weight = new HopCountLinkWeight(graph.getVertexes().size()); 105 this.weight = new HopCountLinkWeight(graph.getVertexes().size());
103 this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets()); 106 this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
104 - this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints()); 107 + this.infrastructurePoints = Suppliers
108 + .memoize(() -> findInfrastructurePoints());
105 this.computeCost = Math.max(0, System.nanoTime() - time); 109 this.computeCost = Math.max(0, System.nanoTime() - time);
106 } 110 }
107 111
...@@ -111,6 +115,11 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -111,6 +115,11 @@ public class DefaultTopology extends AbstractModel implements Topology {
111 } 115 }
112 116
113 @Override 117 @Override
118 + public long creationTime() {
119 + return creationTime;
120 + }
121 +
122 + @Override
114 public long computeCost() { 123 public long computeCost() {
115 return computeCost; 124 return computeCost;
116 } 125 }
...@@ -164,6 +173,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -164,6 +173,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
164 * Returns the specified topology cluster. 173 * Returns the specified topology cluster.
165 * 174 *
166 * @param clusterId cluster identifier 175 * @param clusterId cluster identifier
176 + *
167 * @return topology cluster 177 * @return topology cluster
168 */ 178 */
169 TopologyCluster getCluster(ClusterId clusterId) { 179 TopologyCluster getCluster(ClusterId clusterId) {
...@@ -174,6 +184,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -174,6 +184,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
174 * Returns the topology cluster that contains the given device. 184 * Returns the topology cluster that contains the given device.
175 * 185 *
176 * @param deviceId device identifier 186 * @param deviceId device identifier
187 + *
177 * @return topology cluster 188 * @return topology cluster
178 */ 189 */
179 TopologyCluster getCluster(DeviceId deviceId) { 190 TopologyCluster getCluster(DeviceId deviceId) {
...@@ -184,6 +195,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -184,6 +195,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
184 * Returns the set of cluster devices. 195 * Returns the set of cluster devices.
185 * 196 *
186 * @param cluster topology cluster 197 * @param cluster topology cluster
198 + *
187 * @return cluster devices 199 * @return cluster devices
188 */ 200 */
189 Set<DeviceId> getClusterDevices(TopologyCluster cluster) { 201 Set<DeviceId> getClusterDevices(TopologyCluster cluster) {
...@@ -194,6 +206,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -194,6 +206,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
194 * Returns the set of cluster links. 206 * Returns the set of cluster links.
195 * 207 *
196 * @param cluster topology cluster 208 * @param cluster topology cluster
209 + *
197 * @return cluster links 210 * @return cluster links
198 */ 211 */
199 Set<Link> getClusterLinks(TopologyCluster cluster) { 212 Set<Link> getClusterLinks(TopologyCluster cluster) {
...@@ -204,6 +217,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -204,6 +217,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
204 * Indicates whether the given point is an infrastructure link end-point. 217 * Indicates whether the given point is an infrastructure link end-point.
205 * 218 *
206 * @param connectPoint connection point 219 * @param connectPoint connection point
220 + *
207 * @return true if infrastructure 221 * @return true if infrastructure
208 */ 222 */
209 boolean isInfrastructure(ConnectPoint connectPoint) { 223 boolean isInfrastructure(ConnectPoint connectPoint) {
...@@ -214,6 +228,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -214,6 +228,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
214 * Indicates whether the given point is part of a broadcast set. 228 * Indicates whether the given point is part of a broadcast set.
215 * 229 *
216 * @param connectPoint connection point 230 * @param connectPoint connection point
231 + *
217 * @return true if in broadcast set 232 * @return true if in broadcast set
218 */ 233 */
219 boolean isBroadcastPoint(ConnectPoint connectPoint) { 234 boolean isBroadcastPoint(ConnectPoint connectPoint) {
...@@ -225,19 +240,21 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -225,19 +240,21 @@ public class DefaultTopology extends AbstractModel implements Topology {
225 // Find the cluster to which the device belongs. 240 // Find the cluster to which the device belongs.
226 TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId()); 241 TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId());
227 if (cluster == null) { 242 if (cluster == null) {
228 - throw new IllegalArgumentException("No cluster found for device " + connectPoint.deviceId()); 243 + throw new IllegalArgumentException("No cluster found for device "
244 + + connectPoint.deviceId());
229 } 245 }
230 246
231 // If the broadcast set is null or empty, or if the point explicitly 247 // If the broadcast set is null or empty, or if the point explicitly
232 // belongs to it, return true; 248 // belongs to it, return true;
233 Set<ConnectPoint> points = broadcastSets.get().get(cluster.id()); 249 Set<ConnectPoint> points = broadcastSets.get().get(cluster.id());
234 - return points == null || points.isEmpty() || points.contains(connectPoint); 250 + return (points == null) || points.isEmpty() || points.contains(connectPoint);
235 } 251 }
236 252
237 /** 253 /**
238 * Returns the size of the cluster broadcast set. 254 * Returns the size of the cluster broadcast set.
239 * 255 *
240 * @param clusterId cluster identifier 256 * @param clusterId cluster identifier
257 + *
241 * @return size of the cluster broadcast set 258 * @return size of the cluster broadcast set
242 */ 259 */
243 int broadcastSetSize(ClusterId clusterId) { 260 int broadcastSetSize(ClusterId clusterId) {
...@@ -249,7 +266,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -249,7 +266,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
249 * destination devices. 266 * destination devices.
250 * 267 *
251 * @param src source device 268 * @param src source device
269 + *
252 * @param dst destination device 270 * @param dst destination device
271 + *
253 * @return set of shortest paths 272 * @return set of shortest paths
254 */ 273 */
255 Set<Path> getPaths(DeviceId src, DeviceId dst) { 274 Set<Path> getPaths(DeviceId src, DeviceId dst) {
...@@ -261,8 +280,11 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -261,8 +280,11 @@ public class DefaultTopology extends AbstractModel implements Topology {
261 * destination devices. 280 * destination devices.
262 * 281 *
263 * @param src source device 282 * @param src source device
283 + *
264 * @param dst destination device 284 * @param dst destination device
285 + *
265 * @param weight link weight function 286 * @param weight link weight function
287 + *
266 * @return set of shortest paths 288 * @return set of shortest paths
267 */ 289 */
268 Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { 290 Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
...@@ -283,7 +305,6 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -283,7 +305,6 @@ public class DefaultTopology extends AbstractModel implements Topology {
283 return builder.build(); 305 return builder.build();
284 } 306 }
285 307
286 -
287 // Converts graph path to a network path with the same cost. 308 // Converts graph path to a network path with the same cost.
288 private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) { 309 private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
289 List<Link> links = new ArrayList<>(); 310 List<Link> links = new ArrayList<>();
...@@ -293,7 +314,6 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -293,7 +314,6 @@ public class DefaultTopology extends AbstractModel implements Topology {
293 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost()); 314 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
294 } 315 }
295 316
296 -
297 // Searches for SCC clusters in the network topology graph using Tarjan 317 // Searches for SCC clusters in the network topology graph using Tarjan
298 // algorithm. 318 // algorithm.
299 private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() { 319 private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() {
...@@ -315,8 +335,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -315,8 +335,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
315 Set<TopologyEdge> edgeSet = clusterEdges.get(i); 335 Set<TopologyEdge> edgeSet = clusterEdges.get(i);
316 336
317 ClusterId cid = ClusterId.clusterId(i); 337 ClusterId cid = ClusterId.clusterId(i);
318 - DefaultTopologyCluster cluster = 338 + DefaultTopologyCluster cluster = new DefaultTopologyCluster(cid,
319 - new DefaultTopologyCluster(cid, vertexSet.size(), edgeSet.size(), 339 + vertexSet.size(),
340 + edgeSet.size(),
320 findRoot(vertexSet)); 341 findRoot(vertexSet));
321 clusterBuilder.put(cid, cluster); 342 clusterBuilder.put(cid, cluster);
322 } 343 }
...@@ -328,9 +349,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -328,9 +349,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
328 private TopologyVertex findRoot(Set<TopologyVertex> vertexSet) { 349 private TopologyVertex findRoot(Set<TopologyVertex> vertexSet) {
329 TopologyVertex minVertex = null; 350 TopologyVertex minVertex = null;
330 for (TopologyVertex vertex : vertexSet) { 351 for (TopologyVertex vertex : vertexSet) {
331 - if (minVertex == null || 352 + if ((minVertex == null) || (minVertex.deviceId().toString()
332 - minVertex.deviceId().toString() 353 + .compareTo(minVertex.deviceId().toString()) < 0)) {
333 - .compareTo(minVertex.deviceId().toString()) < 0) {
334 minVertex = vertex; 354 minVertex = vertex;
335 } 355 }
336 } 356 }
...@@ -349,8 +369,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -349,8 +369,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
349 // Finds all broadcast points for the cluster. These are those connection 369 // Finds all broadcast points for the cluster. These are those connection
350 // points which lie along the shortest paths between the cluster root and 370 // points which lie along the shortest paths between the cluster root and
351 // all other devices within the cluster. 371 // all other devices within the cluster.
352 - private void addClusterBroadcastSet(TopologyCluster cluster, 372 + private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) {
353 - Builder<ClusterId, ConnectPoint> builder) {
354 // Use the graph root search results to build the broadcast set. 373 // Use the graph root search results to build the broadcast set.
355 Result<TopologyVertex, TopologyEdge> result = 374 Result<TopologyVertex, TopologyEdge> result =
356 DIJKSTRA.search(graph, cluster.root(), null, weight, 1); 375 DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
...@@ -389,9 +408,12 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -389,9 +408,12 @@ public class DefaultTopology extends AbstractModel implements Topology {
389 // Builds cluster-devices, cluster-links and device-cluster indexes. 408 // Builds cluster-devices, cluster-links and device-cluster indexes.
390 private ClusterIndexes buildIndexes() { 409 private ClusterIndexes buildIndexes() {
391 // Prepare the index builders 410 // Prepare the index builders
392 - ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder = ImmutableMap.builder(); 411 + ImmutableMap.Builder<DeviceId, TopologyCluster> clusterBuilder =
393 - ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder = ImmutableSetMultimap.builder(); 412 + ImmutableMap.builder();
394 - ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder = ImmutableSetMultimap.builder(); 413 + ImmutableSetMultimap.Builder<TopologyCluster, DeviceId> devicesBuilder =
414 + ImmutableSetMultimap.builder();
415 + ImmutableSetMultimap.Builder<TopologyCluster, Link> linksBuilder =
416 + ImmutableSetMultimap.builder();
395 417
396 // Now scan through all the clusters 418 // Now scan through all the clusters
397 for (TopologyCluster cluster : clusters.get().values()) { 419 for (TopologyCluster cluster : clusters.get().values()) {
...@@ -411,8 +433,7 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -411,8 +433,7 @@ public class DefaultTopology extends AbstractModel implements Topology {
411 433
412 // Finalize all indexes. 434 // Finalize all indexes.
413 return new ClusterIndexes(clusterBuilder.build(), 435 return new ClusterIndexes(clusterBuilder.build(),
414 - devicesBuilder.build(), 436 + devicesBuilder.build(), linksBuilder.build());
415 - linksBuilder.build());
416 } 437 }
417 438
418 // Link weight for measuring link cost as hop count with indirect links 439 // Link weight for measuring link cost as hop count with indirect links
...@@ -428,8 +449,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -428,8 +449,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
428 public double weight(TopologyEdge edge) { 449 public double weight(TopologyEdge edge) {
429 // To force preference to use direct paths first, make indirect 450 // To force preference to use direct paths first, make indirect
430 // links as expensive as the linear vertex traversal. 451 // links as expensive as the linear vertex traversal.
431 - return edge.link().state() == ACTIVE ? 452 + return edge.link().state() ==
432 - (edge.link().type() == INDIRECT ? indirectLinkCost : 1) : -1; 453 + ACTIVE ? (edge.link().type() ==
454 + INDIRECT ? indirectLinkCost : 1) : -1;
433 } 455 }
434 } 456 }
435 457
...@@ -437,7 +459,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -437,7 +459,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
437 private static class NoIndirectLinksWeight implements LinkWeight { 459 private static class NoIndirectLinksWeight implements LinkWeight {
438 @Override 460 @Override
439 public double weight(TopologyEdge edge) { 461 public double weight(TopologyEdge edge) {
440 - return edge.link().state() == INACTIVE || edge.link().type() == INDIRECT ? -1 : 1; 462 + return (edge.link().state() == INACTIVE)
463 + || (edge.link().type() == INDIRECT) ? -1 : 1;
441 } 464 }
442 } 465 }
443 466
...@@ -446,7 +469,8 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -446,7 +469,8 @@ public class DefaultTopology extends AbstractModel implements Topology {
446 final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster; 469 final ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster;
447 final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster; 470 final ImmutableSetMultimap<TopologyCluster, Link> linksByCluster;
448 471
449 - public ClusterIndexes(ImmutableMap<DeviceId, TopologyCluster> clustersByDevice, 472 + public ClusterIndexes(
473 + ImmutableMap<DeviceId, TopologyCluster> clustersByDevice,
450 ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster, 474 ImmutableSetMultimap<TopologyCluster, DeviceId> devicesByCluster,
451 ImmutableSetMultimap<TopologyCluster, Link> linksByCluster) { 475 ImmutableSetMultimap<TopologyCluster, Link> linksByCluster) {
452 this.clustersByDevice = clustersByDevice; 476 this.clustersByDevice = clustersByDevice;
...@@ -459,10 +483,10 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -459,10 +483,10 @@ public class DefaultTopology extends AbstractModel implements Topology {
459 public String toString() { 483 public String toString() {
460 return toStringHelper(this) 484 return toStringHelper(this)
461 .add("time", time) 485 .add("time", time)
486 + .add("created", creationTime)
462 .add("computeCost", computeCost) 487 .add("computeCost", computeCost)
463 .add("clusters", clusterCount()) 488 .add("clusters", clusterCount())
464 .add("devices", deviceCount()) 489 .add("devices", deviceCount())
465 - .add("links", linkCount()) 490 + .add("links", linkCount()).toString();
466 - .toString();
467 } 491 }
468 } 492 }
......
...@@ -61,6 +61,11 @@ public class TopologyResourceTest extends ResourceTest { ...@@ -61,6 +61,11 @@ public class TopologyResourceTest extends ResourceTest {
61 } 61 }
62 62
63 @Override 63 @Override
64 + public long creationTime() {
65 + return 22222L;
66 + }
67 +
68 + @Override
64 public long computeCost() { 69 public long computeCost() {
65 return 0; 70 return 0;
66 } 71 }
......