tom

Working on simple topology manager and provider

1 +package org.onlab.onos.event;
2 +
3 +import com.google.common.collect.Lists;
4 +
5 +import java.util.List;
6 +import java.util.Timer;
7 +import java.util.TimerTask;
8 +
9 +import static com.google.common.base.Preconditions.checkArgument;
10 +import static com.google.common.base.Preconditions.checkNotNull;
11 +
12 +/**
13 + * Base implementation of an event accumulator. It allows triggering based on
14 + * event inter-arrival time threshold, maximum batch life threshold and maximum
15 + * batch size.
16 + */
17 +public abstract class AbstractEventAccumulator implements EventAccumulator {
18 +
19 + private final Timer timer;
20 + private final int maxEvents;
21 + private final int maxBatchMillis;
22 + private final int maxIdleMillis;
23 +
24 + private TimerTask idleTask = new ProcessorTask();
25 + private TimerTask maxTask = new ProcessorTask();
26 +
27 + private List<Event> events = Lists.newArrayList();
28 +
29 + /**
30 + * Creates an event accumulator capable of triggering on the specified
31 + * thresholds.
32 + *
33 + * @param timer timer to use for scheduling check-points
34 + * @param maxEvents maximum number of events to accumulate before
35 + * processing is triggered
36 + * @param maxBatchMillis maximum number of millis allowed since the first
37 + * event before processing is triggered
38 + * @param maxIdleMillis maximum number millis between events before
39 + * processing is triggered
40 + */
41 + protected AbstractEventAccumulator(Timer timer, int maxEvents,
42 + int maxBatchMillis, int maxIdleMillis) {
43 + this.timer = checkNotNull(timer, "Timer cannot be null");
44 +
45 + checkArgument(maxEvents > 1, "Maximum number of events must be > 1");
46 + checkArgument(maxBatchMillis > 0, "Maximum millis must be positive");
47 + checkArgument(maxIdleMillis > 0, "Maximum idle millis must be positive");
48 +
49 + this.maxEvents = maxEvents;
50 + this.maxBatchMillis = maxBatchMillis;
51 + this.maxIdleMillis = maxIdleMillis;
52 + }
53 +
54 + @Override
55 + public void add(Event event) {
56 + idleTask = cancelIfActive(idleTask);
57 + events.add(event);
58 +
59 + // Did we hit the max event threshold?
60 + if (events.size() == maxEvents) {
61 + maxTask = cancelIfActive(maxTask);
62 + schedule(1);
63 + } else {
64 + // Otherwise, schedule idle task and if this is a first event
65 + // also schedule the max batch age task.
66 + idleTask = schedule(maxIdleMillis);
67 + if (events.size() == 1) {
68 + maxTask = schedule(maxBatchMillis);
69 + }
70 + }
71 + }
72 +
73 + // Schedules a new processor task given number of millis in the future.
74 + private TimerTask schedule(int millis) {
75 + TimerTask task = new ProcessorTask();
76 + timer.schedule(task, millis);
77 + return task;
78 + }
79 +
80 + // Cancels the specified task if it is active.
81 + private TimerTask cancelIfActive(TimerTask task) {
82 + if (task != null) {
83 + task.cancel();
84 + }
85 + return task;
86 + }
87 +
88 + // Task for triggering processing of accumulated events
89 + private class ProcessorTask extends TimerTask {
90 + @Override
91 + public void run() {
92 + idleTask = cancelIfActive(idleTask);
93 + maxTask = cancelIfActive(maxTask);
94 + processEvents(finalizeCurrentBatch());
95 + }
96 + }
97 +
98 + // Demotes and returns the current batch of events and promotes a new one.
99 + private synchronized List<Event> finalizeCurrentBatch() {
100 + List<Event> toBeProcessed = events;
101 + events = Lists.newArrayList();
102 + return toBeProcessed;
103 + }
104 +
105 + /**
106 + * Returns the backing timer.
107 + *
108 + * @return backing timer
109 + */
110 + public Timer timer() {
111 + return timer;
112 + }
113 +
114 + /**
115 + * Returns the maximum number of events allowed to accumulate before
116 + * processing is triggered.
117 + *
118 + * @return max number of events
119 + */
120 + public int maxEvents() {
121 + return maxEvents;
122 + }
123 +
124 + /**
125 + * Returns the maximum number of millis allowed to expire since the first
126 + * event before processing is triggered.
127 + *
128 + * @return max number of millis a batch is allowed to last
129 + */
130 + public int maxBatchMillis() {
131 + return maxBatchMillis;
132 + }
133 +
134 + /**
135 + * Returns the maximum number of millis allowed to expire since the last
136 + * event arrival before processing is triggered.
137 + *
138 + * @return max number of millis since the last event
139 + */
140 + public int maxIdleMillis() {
141 + return maxIdleMillis;
142 + }
143 +}
1 +package org.onlab.onos.event;
2 +
3 +import java.util.List;
4 +
5 +/**
6 + * Abstraction of an accumulator capable of collecting events and at some
7 + * point in time triggers processing of all previously accumulated events.
8 + */
9 +public interface EventAccumulator {
10 +
11 + /**
12 + * Adds an event to the current batch. This operation may, or may not
13 + * trigger processing of the current batch of events.
14 + *
15 + * @param event event to be added to the current batch
16 + */
17 + void add(Event event);
18 +
19 + /**
20 + * Processes the specified list of accumulated events.
21 + *
22 + * @param events list of accumulated events
23 + */
24 + void processEvents(List<Event> events);
25 +
26 +}
1 package org.onlab.onos.net.trivial.impl; 1 package org.onlab.onos.net.trivial.impl;
2 2
3 import com.google.common.collect.ImmutableSet; 3 import com.google.common.collect.ImmutableSet;
4 -import com.google.common.collect.Multimap; 4 +import com.google.common.collect.Maps;
5 +import com.google.common.collect.Sets;
6 +import org.onlab.graph.AdjacencyListsGraph;
7 +import org.onlab.graph.DijkstraGraphSearch;
5 import org.onlab.graph.Graph; 8 import org.onlab.graph.Graph;
6 import org.onlab.graph.GraphPathSearch; 9 import org.onlab.graph.GraphPathSearch;
10 +import org.onlab.onos.net.ConnectPoint;
11 +import org.onlab.onos.net.Device;
7 import org.onlab.onos.net.DeviceId; 12 import org.onlab.onos.net.DeviceId;
8 import org.onlab.onos.net.Link; 13 import org.onlab.onos.net.Link;
9 import org.onlab.onos.net.topology.ClusterId; 14 import org.onlab.onos.net.topology.ClusterId;
15 +import org.onlab.onos.net.topology.LinkWeight;
10 import org.onlab.onos.net.topology.TopoEdge; 16 import org.onlab.onos.net.topology.TopoEdge;
11 import org.onlab.onos.net.topology.TopoVertex; 17 import org.onlab.onos.net.topology.TopoVertex;
12 import org.onlab.onos.net.topology.TopologyCluster; 18 import org.onlab.onos.net.topology.TopologyCluster;
13 import org.onlab.onos.net.topology.TopologyDescription; 19 import org.onlab.onos.net.topology.TopologyDescription;
14 20
15 import java.util.Map; 21 import java.util.Map;
22 +import java.util.Objects;
16 import java.util.Set; 23 import java.util.Set;
17 24
25 +import static com.google.common.base.MoreObjects.toStringHelper;
26 +import static org.onlab.graph.GraphPathSearch.Result;
27 +import static org.onlab.onos.net.Link.Type.INDIRECT;
28 +
18 /** 29 /**
19 * Default implementation of an immutable topology data carrier. 30 * Default implementation of an immutable topology data carrier.
20 */ 31 */
21 -public class DefaultTopologyDescription implements TopologyDescription { 32 +class DefaultTopologyDescription implements TopologyDescription {
33 +
34 + private static final GraphPathSearch<TopoVertex, TopoEdge> DIJKSTRA =
35 + new DijkstraGraphSearch<>();
22 36
23 private final long nanos; 37 private final long nanos;
38 + private final Map<DeviceId, TopoVertex> vertexesById = Maps.newHashMap();
24 private final Graph<TopoVertex, TopoEdge> graph; 39 private final Graph<TopoVertex, TopoEdge> graph;
25 - private final Map<DeviceId, GraphPathSearch.Result<TopoVertex, TopoEdge>> results; 40 + private final Map<DeviceId, Result<TopoVertex, TopoEdge>> results;
26 private final Map<ClusterId, TopologyCluster> clusters; 41 private final Map<ClusterId, TopologyCluster> clusters;
27 - private final Multimap<ClusterId, DeviceId> clusterDevices; 42 +// private final Multimap<ClusterId, DeviceId> clusterDevices;
28 - private final Multimap<ClusterId, Link> clusterLinks; 43 +// private final Multimap<ClusterId, Link> clusterLinks;
29 - private final Map<DeviceId, TopologyCluster> deviceClusters; 44 +// private final Map<DeviceId, TopologyCluster> deviceClusters;
30 - 45 +
31 - public DefaultTopologyDescription(long nanos, Graph<TopoVertex, TopoEdge> graph, 46 +
32 - Map<DeviceId, GraphPathSearch.Result<TopoVertex, TopoEdge>> results, 47 + DefaultTopologyDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) {
33 - Map<ClusterId, TopologyCluster> clusters,
34 - Multimap<ClusterId, DeviceId> clusterDevices,
35 - Multimap<ClusterId, Link> clusterLinks,
36 - Map<DeviceId, TopologyCluster> deviceClusters) {
37 this.nanos = nanos; 48 this.nanos = nanos;
38 - this.graph = graph; 49 + this.graph = buildGraph(devices, links);
39 - this.results = results; 50 + this.results = computeDefaultPaths();
40 - this.clusters = clusters; 51 + this.clusters = computeClusters();
41 - this.clusterDevices = clusterDevices; 52 +// this.clusterDevices = clusterDevices;
42 - this.clusterLinks = clusterLinks; 53 +// this.clusterLinks = clusterLinks;
43 - this.deviceClusters = deviceClusters; 54 +// this.deviceClusters = deviceClusters;
55 + }
56 +
57 + // Constructs the topology graph using the supplied devices and links.
58 + private Graph<TopoVertex, TopoEdge> buildGraph(Iterable<Device> devices,
59 + Iterable<Link> links) {
60 + Graph<TopoVertex, TopoEdge> graph =
61 + new AdjacencyListsGraph<>(buildVertexes(devices),
62 + buildEdges(links));
63 + return graph;
64 + }
65 +
66 + // Builds a set of topology vertexes from the specified list of devices
67 + private Set<TopoVertex> buildVertexes(Iterable<Device> devices) {
68 + Set<TopoVertex> vertexes = Sets.newHashSet();
69 + for (Device device : devices) {
70 + TopoVertex vertex = new TVertex(device.id());
71 + vertexesById.put(vertex.deviceId(), vertex);
72 + vertexes.add(vertex);
73 + }
74 + return vertexes;
75 + }
76 +
77 + // Builds a set of topology vertexes from the specified list of links
78 + private Set<TopoEdge> buildEdges(Iterable<Link> links) {
79 + Set<TopoEdge> edges = Sets.newHashSet();
80 + for (Link link : links) {
81 + edges.add(new TEdge(vertexOf(link.src()), vertexOf(link.dst()), link));
82 + }
83 + return edges;
84 + }
85 +
86 + // Computes the default shortest paths for all source/dest pairs using
87 + // the multi-path Dijkstra and hop-count as path cost.
88 + private Map<DeviceId, Result<TopoVertex, TopoEdge>> computeDefaultPaths() {
89 + LinkWeight weight = new HopCountLinkWeight(graph.getVertexes().size());
90 + Map<DeviceId, Result<TopoVertex, TopoEdge>> results = Maps.newHashMap();
91 +
92 + // Search graph paths for each source to all destinations.
93 + for (TopoVertex src : vertexesById.values()) {
94 + results.put(src.deviceId(), DIJKSTRA.search(graph, src, null, weight));
95 + }
96 + return results;
97 + }
98 +
99 + // Computes topology SCC clusters using Tarjan algorithm.
100 + private Map<ClusterId, TopologyCluster> computeClusters() {
101 + Map<ClusterId, TopologyCluster> clusters = Maps.newHashMap();
102 + return clusters;
103 + }
104 +
105 + // Fetches a vertex corresponding to the given connection point device.
106 + private TopoVertex vertexOf(ConnectPoint connectPoint) {
107 + DeviceId id = connectPoint.deviceId();
108 + TopoVertex vertex = vertexesById.get(id);
109 + if (vertex == null) {
110 + // If vertex does not exist, create one and register it.
111 + vertex = new TVertex(id);
112 + vertexesById.put(id, vertex);
113 + }
114 + return vertex;
44 } 115 }
45 116
46 @Override 117 @Override
...@@ -54,7 +125,7 @@ public class DefaultTopologyDescription implements TopologyDescription { ...@@ -54,7 +125,7 @@ public class DefaultTopologyDescription implements TopologyDescription {
54 } 125 }
55 126
56 @Override 127 @Override
57 - public GraphPathSearch.Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) { 128 + public Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) {
58 return results.get(srcDeviceId); 129 return results.get(srcDeviceId);
59 } 130 }
60 131
...@@ -75,6 +146,105 @@ public class DefaultTopologyDescription implements TopologyDescription { ...@@ -75,6 +146,105 @@ public class DefaultTopologyDescription implements TopologyDescription {
75 146
76 @Override 147 @Override
77 public TopologyCluster clusterFor(DeviceId deviceId) { 148 public TopologyCluster clusterFor(DeviceId deviceId) {
78 - return deviceClusters.get(deviceId); 149 + return null; // deviceClusters.get(deviceId);
150 + }
151 +
152 + // Implementation of the topology vertex backed by a device id
153 + private static class TVertex implements TopoVertex {
154 +
155 + private final DeviceId deviceId;
156 +
157 + public TVertex(DeviceId deviceId) {
158 + this.deviceId = deviceId;
159 + }
160 +
161 + @Override
162 + public DeviceId deviceId() {
163 + return deviceId;
164 + }
165 +
166 + @Override
167 + public int hashCode() {
168 + return Objects.hash(deviceId);
169 + }
170 +
171 + @Override
172 + public boolean equals(Object obj) {
173 + if (obj instanceof TVertex) {
174 + final TVertex other = (TVertex) obj;
175 + return Objects.equals(this.deviceId, other.deviceId);
176 + }
177 + return false;
178 + }
179 +
180 + @Override
181 + public String toString() {
182 + return deviceId.toString();
183 + }
184 + }
185 +
186 + // Implementation of the topology edge backed by a link
187 + private class TEdge implements TopoEdge {
188 + private final Link link;
189 + private final TopoVertex src;
190 + private final TopoVertex dst;
191 +
192 + public TEdge(TopoVertex src, TopoVertex dst, Link link) {
193 + this.src = src;
194 + this.dst = dst;
195 + this.link = link;
196 + }
197 +
198 + @Override
199 + public Link link() {
200 + return link;
201 + }
202 +
203 + @Override
204 + public TopoVertex src() {
205 + return src;
206 + }
207 +
208 + @Override
209 + public TopoVertex dst() {
210 + return dst;
211 + }
212 +
213 + @Override
214 + public int hashCode() {
215 + return Objects.hash(link);
216 + }
217 +
218 + @Override
219 + public boolean equals(Object obj) {
220 + if (obj instanceof TEdge) {
221 + final TEdge other = (TEdge) obj;
222 + return Objects.equals(this.link, other.link);
223 + }
224 + return false;
225 + }
226 +
227 + @Override
228 + public String toString() {
229 + return toStringHelper(this).add("src", src).add("dst", dst).toString();
230 + }
79 } 231 }
232 +
233 + // Link weight for measuring link cost as hop count with indirect links
234 + // being as expensive as traversing the entire graph to assume the worst.
235 + private class HopCountLinkWeight implements LinkWeight {
236 + private final int indirectLinkCost;
237 +
238 + public HopCountLinkWeight(int indirectLinkCost) {
239 + this.indirectLinkCost = indirectLinkCost;
240 + }
241 +
242 + @Override
243 + public double weight(TopoEdge edge) {
244 + // To force preference to use direct paths first, make indirect
245 + // links as expensive as the linear vertex traversal.
246 + return edge.link().type() == INDIRECT ? indirectLinkCost : 1;
247 + }
248 + }
249 +
80 } 250 }
......
...@@ -28,7 +28,8 @@ import static com.google.common.base.Preconditions.checkArgument; ...@@ -28,7 +28,8 @@ import static com.google.common.base.Preconditions.checkArgument;
28 import static org.onlab.onos.net.device.DeviceEvent.Type.*; 28 import static org.onlab.onos.net.device.DeviceEvent.Type.*;
29 29
30 /** 30 /**
31 - 31 + * Manages inventory of infrastructure DEVICES using trivial in-memory
32 + * structures implementation.
32 */ 33 */
33 class SimpleDeviceStore { 34 class SimpleDeviceStore {
34 35
......
...@@ -25,7 +25,7 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; ...@@ -25,7 +25,7 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
25 import static org.onlab.onos.net.link.LinkEvent.Type.LINK_UPDATED; 25 import static org.onlab.onos.net.link.LinkEvent.Type.LINK_UPDATED;
26 26
27 /** 27 /**
28 - * Manages inventory of infrastructure links using trivial in-memory link 28 + * Manages inventory of infrastructure links using trivial in-memory structures
29 * implementation. 29 * implementation.
30 */ 30 */
31 class SimpleLinkStore { 31 class SimpleLinkStore {
......
...@@ -153,6 +153,9 @@ public class SimpleTopologyManager ...@@ -153,6 +153,9 @@ public class SimpleTopologyManager
153 public void topologyChanged(TopologyDescription topoDescription, 153 public void topologyChanged(TopologyDescription topoDescription,
154 List<Event> reasons) { 154 List<Event> reasons) {
155 checkNotNull(topoDescription, "Topology description cannot be null"); 155 checkNotNull(topoDescription, "Topology description cannot be null");
156 +
157 + log.info("Topology changed due to: {}", // to be removed soon
158 + reasons == null ? "initial compute" : reasons);
156 TopologyEvent event = store.updateTopology(topoDescription, reasons); 159 TopologyEvent event = store.updateTopology(topoDescription, reasons);
157 if (event != null) { 160 if (event != null) {
158 log.info("Topology changed due to: {}", 161 log.info("Topology changed due to: {}",
......
1 +package org.onlab.onos.net.trivial.impl;
2 +
3 +import org.apache.felix.scr.annotations.Activate;
4 +import org.apache.felix.scr.annotations.Component;
5 +import org.apache.felix.scr.annotations.Deactivate;
6 +import org.apache.felix.scr.annotations.Reference;
7 +import org.apache.felix.scr.annotations.ReferenceCardinality;
8 +import org.onlab.onos.event.AbstractEventAccumulator;
9 +import org.onlab.onos.event.Event;
10 +import org.onlab.onos.event.EventAccumulator;
11 +import org.onlab.onos.net.device.DeviceEvent;
12 +import org.onlab.onos.net.device.DeviceListener;
13 +import org.onlab.onos.net.device.DeviceService;
14 +import org.onlab.onos.net.link.LinkEvent;
15 +import org.onlab.onos.net.link.LinkListener;
16 +import org.onlab.onos.net.link.LinkService;
17 +import org.onlab.onos.net.provider.AbstractProvider;
18 +import org.onlab.onos.net.provider.ProviderId;
19 +import org.onlab.onos.net.topology.TopologyDescription;
20 +import org.onlab.onos.net.topology.TopologyProvider;
21 +import org.onlab.onos.net.topology.TopologyProviderRegistry;
22 +import org.onlab.onos.net.topology.TopologyProviderService;
23 +import org.slf4j.Logger;
24 +
25 +import java.util.List;
26 +import java.util.Timer;
27 +import java.util.concurrent.ExecutorService;
28 +
29 +import static java.util.concurrent.Executors.newFixedThreadPool;
30 +import static org.onlab.onos.net.device.DeviceEvent.Type.*;
31 +import static org.onlab.util.Tools.namedThreads;
32 +import static org.slf4j.LoggerFactory.getLogger;
33 +
34 +/**
35 + * Simple implementation of a network topology provider/computor.
36 + */
37 +@Component(immediate = true)
38 +public class SimpleTopologyProvider extends AbstractProvider
39 + implements TopologyProvider {
40 +
41 + // TODO: make these configurable
42 + private static final int MAX_EVENTS = 100;
43 + private static final int MAX_IDLE_MS = 50;
44 + private static final int MAX_BATCH_MS = 200;
45 + private static final int MAX_THREADS = 8;
46 +
47 + // FIXME: Replace with a system-wide timer instance
48 + private static final Timer TIMER = new Timer();
49 +
50 + private final Logger log = getLogger(getClass());
51 +
52 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 + protected TopologyProviderRegistry providerRegistry;
54 +
55 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 + protected DeviceService deviceService;
57 +
58 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 + protected LinkService linkService;
60 +
61 + private volatile boolean isStarted = false;
62 +
63 + private TopologyProviderService providerService;
64 + private DeviceListener deviceListener = new InnerDeviceListener();
65 + private LinkListener linkListener = new InnerLinkListener();
66 +
67 + private EventAccumulator accumulator;
68 + private ExecutorService executor;
69 +
70 + /**
71 + * Creates a provider with the supplier identifier.
72 + */
73 + public SimpleTopologyProvider() {
74 + super(new ProviderId("org.onlab.onos.provider.topology"));
75 + }
76 +
77 + @Activate
78 + public synchronized void activate() {
79 + executor = newFixedThreadPool(MAX_THREADS, namedThreads("topo-compute-%d"));
80 + accumulator = new TopologyChangeAccumulator();
81 +
82 + providerService = providerRegistry.register(this);
83 + deviceService.addListener(deviceListener);
84 + linkService.addListener(linkListener);
85 +
86 + isStarted = true;
87 + triggerTopologyBuild(null);
88 + log.info("Started");
89 + }
90 +
91 + @Deactivate
92 + public synchronized void deactivate() {
93 + deviceService.removeListener(deviceListener);
94 + linkService.removeListener(linkListener);
95 + providerRegistry.unregister(this);
96 + providerService = null;
97 +
98 + executor.shutdownNow();
99 + executor = null;
100 +
101 + isStarted = false;
102 + log.info("Stopped");
103 + }
104 +
105 + /**
106 + * Triggers assembly of topology data citing the specified events as the
107 + * reason.
108 + *
109 + * @param reasons events which triggered the topology change
110 + */
111 + private void triggerTopologyBuild(List<Event> reasons) {
112 + executor.execute(new TopologyBuilderTask(reasons));
113 + }
114 +
115 + // Builds the topology using the latest device and link information
116 + // and citing the specified events as reasons for the change.
117 + private void buildTopology(List<Event> reasons) {
118 + log.info("YO! Computing topology");
119 + if (isStarted) {
120 + TopologyDescription desc =
121 + new DefaultTopologyDescription(System.nanoTime(),
122 + deviceService.getDevices(),
123 + linkService.getLinks());
124 + providerService.topologyChanged(desc, reasons);
125 + }
126 + }
127 +
128 + // Callback for device events
129 + private class InnerDeviceListener implements DeviceListener {
130 + @Override
131 + public void event(DeviceEvent event) {
132 + DeviceEvent.Type type = event.type();
133 + if (type == DEVICE_ADDED || type == DEVICE_REMOVED ||
134 + type == DEVICE_AVAILABILITY_CHANGED) {
135 + accumulator.add(event);
136 + }
137 + }
138 + }
139 +
140 + // Callback for link events
141 + private class InnerLinkListener implements LinkListener {
142 + @Override
143 + public void event(LinkEvent event) {
144 + accumulator.add(event);
145 + }
146 + }
147 +
148 + // Event accumulator for paced triggering of topology assembly.
149 + private class TopologyChangeAccumulator
150 + extends AbstractEventAccumulator implements EventAccumulator {
151 +
152 + TopologyChangeAccumulator() {
153 + super(TIMER, MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
154 + }
155 +
156 + @Override
157 + public void processEvents(List<Event> events) {
158 + triggerTopologyBuild(events);
159 + }
160 +
161 + }
162 +
163 + // Task for building topology data in a separate thread.
164 + private class TopologyBuilderTask implements Runnable {
165 + private final List<Event> reasons;
166 +
167 + public TopologyBuilderTask(List<Event> reasons) {
168 + this.reasons = reasons;
169 + }
170 +
171 + @Override
172 + public void run() {
173 + buildTopology(reasons);
174 + }
175 + }
176 +
177 +}
...@@ -18,9 +18,9 @@ import java.util.Set; ...@@ -18,9 +18,9 @@ import java.util.Set;
18 18
19 /** 19 /**
20 * Manages inventory of topology snapshots using trivial in-memory 20 * Manages inventory of topology snapshots using trivial in-memory
21 - * implementation. 21 + * structures implementation.
22 */ 22 */
23 -public class SimpleTopologyStore { 23 +class SimpleTopologyStore {
24 24
25 private volatile DefaultTopology current; 25 private volatile DefaultTopology current;
26 26
...@@ -35,10 +35,12 @@ public class SimpleTopologyStore { ...@@ -35,10 +35,12 @@ public class SimpleTopologyStore {
35 35
36 /** 36 /**
37 * Indicates whether the topology is the latest. 37 * Indicates whether the topology is the latest.
38 + *
38 * @param topology topology descriptor 39 * @param topology topology descriptor
39 * @return true if topology is the most recent one 40 * @return true if topology is the most recent one
40 */ 41 */
41 boolean isLatest(Topology topology) { 42 boolean isLatest(Topology topology) {
43 + // Topology is current only if it is the same as our current topology
42 return topology == current; 44 return topology == current;
43 } 45 }
44 46
...@@ -117,7 +119,8 @@ public class SimpleTopologyStore { ...@@ -117,7 +119,8 @@ public class SimpleTopologyStore {
117 * @param reasons list of events that triggered the update 119 * @param reasons list of events that triggered the update
118 * @return topology update event or null if the description is old 120 * @return topology update event or null if the description is old
119 */ 121 */
120 - TopologyEvent updateTopology(TopologyDescription topoDescription, List<Event> reasons) { 122 + TopologyEvent updateTopology(TopologyDescription topoDescription,
123 + List<Event> reasons) {
121 return null; 124 return null;
122 } 125 }
123 126
......
...@@ -15,7 +15,8 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -15,7 +15,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
15 * @param <V> vertex type 15 * @param <V> vertex type
16 * @param <E> edge type 16 * @param <E> edge type
17 */ 17 */
18 -public class AdjacencyListsGraph<V extends Vertex, E extends Edge<V>> implements Graph<V, E> { 18 +public class AdjacencyListsGraph<V extends Vertex, E extends Edge<V>>
19 + implements Graph<V, E> {
19 20
20 private final Set<V> vertexes; 21 private final Set<V> vertexes;
21 private final Set<E> edges; 22 private final Set<E> edges;
......