Thomas Vachuska
Committed by Gerrit Code Review

Adding configurability to the even accumulator for the topology provider.

Change-Id: I35ede9a62782dc6a2e55b8895aeec6ece8836960
...@@ -58,6 +58,11 @@ ...@@ -58,6 +58,11 @@
58 </dependency> 58 </dependency>
59 59
60 <dependency> 60 <dependency>
61 + <groupId>org.osgi</groupId>
62 + <artifactId>org.osgi.compendium</artifactId>
63 + </dependency>
64 +
65 + <dependency>
61 <groupId>org.apache.felix</groupId> 66 <groupId>org.apache.felix</groupId>
62 <artifactId>org.apache.felix.scr.annotations</artifactId> 67 <artifactId>org.apache.felix.scr.annotations</artifactId>
63 </dependency> 68 </dependency>
......
...@@ -15,9 +15,12 @@ ...@@ -15,9 +15,12 @@
15 */ 15 */
16 package org.onlab.onos.net.topology.impl; 16 package org.onlab.onos.net.topology.impl;
17 17
18 +import com.google.common.collect.ImmutableList;
18 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
19 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Modified;
23 +import org.apache.felix.scr.annotations.Property;
21 import org.apache.felix.scr.annotations.Reference; 24 import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 25 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.apache.felix.scr.annotations.Service; 26 import org.apache.felix.scr.annotations.Service;
...@@ -36,13 +39,16 @@ import org.onlab.onos.net.topology.GraphDescription; ...@@ -36,13 +39,16 @@ import org.onlab.onos.net.topology.GraphDescription;
36 import org.onlab.onos.net.topology.TopologyProvider; 39 import org.onlab.onos.net.topology.TopologyProvider;
37 import org.onlab.onos.net.topology.TopologyProviderRegistry; 40 import org.onlab.onos.net.topology.TopologyProviderRegistry;
38 import org.onlab.onos.net.topology.TopologyProviderService; 41 import org.onlab.onos.net.topology.TopologyProviderService;
42 +import org.osgi.service.component.ComponentContext;
39 import org.slf4j.Logger; 43 import org.slf4j.Logger;
40 44
41 import java.util.Collections; 45 import java.util.Collections;
46 +import java.util.Dictionary;
42 import java.util.List; 47 import java.util.List;
43 import java.util.Timer; 48 import java.util.Timer;
44 import java.util.concurrent.ExecutorService; 49 import java.util.concurrent.ExecutorService;
45 50
51 +import static com.google.common.base.Strings.isNullOrEmpty;
46 import static java.util.concurrent.Executors.newFixedThreadPool; 52 import static java.util.concurrent.Executors.newFixedThreadPool;
47 import static org.onlab.onos.core.CoreService.CORE_PROVIDER_ID; 53 import static org.onlab.onos.core.CoreService.CORE_PROVIDER_ID;
48 import static org.onlab.onos.net.device.DeviceEvent.Type.*; 54 import static org.onlab.onos.net.device.DeviceEvent.Type.*;
...@@ -59,16 +65,27 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -59,16 +65,27 @@ import static org.slf4j.LoggerFactory.getLogger;
59 public class DefaultTopologyProvider extends AbstractProvider 65 public class DefaultTopologyProvider extends AbstractProvider
60 implements TopologyProvider { 66 implements TopologyProvider {
61 67
62 - // TODO: make these configurable
63 - private static final int MAX_EVENTS = 100;
64 - private static final int MAX_IDLE_MS = 5;
65 - private static final int MAX_BATCH_MS = 50;
66 private static final int MAX_THREADS = 8; 68 private static final int MAX_THREADS = 8;
69 + private static final int DEFAULT_MAX_EVENTS = 100;
70 + private static final int DEFAULT_MAX_BATCH_MS = 50;
71 + private static final int DEFAULT_MAX_IDLE_MS = 5;
67 72
68 // FIXME: Replace with a system-wide timer instance; 73 // FIXME: Replace with a system-wide timer instance;
69 // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt 74 // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt
70 private static final Timer TIMER = new Timer(); 75 private static final Timer TIMER = new Timer();
71 76
77 + @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS,
78 + label = "Maximum number of events to accumulate")
79 + private int maxEvents = DEFAULT_MAX_EVENTS;
80 +
81 + @Property(name = "maxIdleMs", intValue = DEFAULT_MAX_IDLE_MS,
82 + label = "Maximum number of millis between events")
83 + private int maxIdleMs = DEFAULT_MAX_IDLE_MS;
84 +
85 + @Property(name = "maxBatchMs", intValue = DEFAULT_MAX_BATCH_MS,
86 + label = "Maximum number of millis for whole batch")
87 + private int maxBatchMs = DEFAULT_MAX_BATCH_MS;
88 +
72 private final Logger log = getLogger(getClass()); 89 private final Logger log = getLogger(getClass());
73 90
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -97,9 +114,9 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -97,9 +114,9 @@ public class DefaultTopologyProvider extends AbstractProvider
97 } 114 }
98 115
99 @Activate 116 @Activate
100 - public synchronized void activate() { 117 + public synchronized void activate(ComponentContext context) {
101 executor = newFixedThreadPool(MAX_THREADS, namedThreads("topo-build-%d")); 118 executor = newFixedThreadPool(MAX_THREADS, namedThreads("topo-build-%d"));
102 - accumulator = new TopologyChangeAccumulator(); 119 + modified(context);
103 120
104 providerService = providerRegistry.register(this); 121 providerService = providerRegistry.register(this);
105 deviceService.addListener(deviceListener); 122 deviceService.addListener(deviceListener);
...@@ -111,7 +128,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -111,7 +128,7 @@ public class DefaultTopologyProvider extends AbstractProvider
111 } 128 }
112 129
113 @Deactivate 130 @Deactivate
114 - public synchronized void deactivate() { 131 + public synchronized void deactivate(ComponentContext context) {
115 isStarted = false; 132 isStarted = false;
116 133
117 deviceService.removeListener(deviceListener); 134 deviceService.removeListener(deviceListener);
...@@ -125,6 +142,41 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -125,6 +142,41 @@ public class DefaultTopologyProvider extends AbstractProvider
125 log.info("Stopped"); 142 log.info("Stopped");
126 } 143 }
127 144
145 + @Modified
146 + public void modified(ComponentContext context) {
147 + if (context == null) {
148 + accumulator = new TopologyChangeAccumulator();
149 + return;
150 + }
151 +
152 + Dictionary properties = context.getProperties();
153 + int newMaxEvents, newMaxBatchMs, newMaxIdleMs;
154 + try {
155 + String s = (String) properties.get("maxEvents");
156 + newMaxEvents = isNullOrEmpty(s) ? maxEvents : Integer.parseInt(s);
157 +
158 + s = (String) properties.get("maxBatchMs");
159 + newMaxBatchMs = isNullOrEmpty(s) ? maxBatchMs : Integer.parseInt(s);
160 +
161 + s = (String) properties.get("maxIdleMs");
162 + newMaxIdleMs = isNullOrEmpty(s) ? maxIdleMs : Integer.parseInt(s);
163 + } catch (Exception e) {
164 + newMaxEvents = DEFAULT_MAX_EVENTS;
165 + newMaxBatchMs = DEFAULT_MAX_BATCH_MS;
166 + newMaxIdleMs = DEFAULT_MAX_IDLE_MS;
167 + }
168 +
169 + if (newMaxEvents != maxEvents || newMaxBatchMs != maxBatchMs || newMaxIdleMs != maxIdleMs) {
170 + maxEvents = newMaxEvents;
171 + maxBatchMs = newMaxBatchMs;
172 + maxIdleMs = newMaxIdleMs;
173 + accumulator = maxEvents > 1 ? new TopologyChangeAccumulator() : null;
174 + log.info("Reconfigured with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}",
175 + maxEvents, maxBatchMs, maxIdleMs);
176 + }
177 + }
178 +
179 +
128 @Override 180 @Override
129 public void triggerRecompute() { 181 public void triggerRecompute() {
130 triggerTopologyBuild(Collections.<Event>emptyList()); 182 triggerTopologyBuild(Collections.<Event>emptyList());
...@@ -154,6 +206,14 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -154,6 +206,14 @@ public class DefaultTopologyProvider extends AbstractProvider
154 } 206 }
155 } 207 }
156 208
209 + private void processEvent(Event event) {
210 + if (accumulator != null) {
211 + accumulator.add(event);
212 + } else {
213 + triggerTopologyBuild(ImmutableList.of(event));
214 + }
215 + }
216 +
157 // Callback for device events 217 // Callback for device events
158 private class InternalDeviceListener implements DeviceListener { 218 private class InternalDeviceListener implements DeviceListener {
159 @Override 219 @Override
...@@ -161,7 +221,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -161,7 +221,7 @@ public class DefaultTopologyProvider extends AbstractProvider
161 DeviceEvent.Type type = event.type(); 221 DeviceEvent.Type type = event.type();
162 if (type == DEVICE_ADDED || type == DEVICE_REMOVED || 222 if (type == DEVICE_ADDED || type == DEVICE_REMOVED ||
163 type == DEVICE_AVAILABILITY_CHANGED) { 223 type == DEVICE_AVAILABILITY_CHANGED) {
164 - accumulator.add(event); 224 + processEvent(event);
165 } 225 }
166 } 226 }
167 } 227 }
...@@ -170,7 +230,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -170,7 +230,7 @@ public class DefaultTopologyProvider extends AbstractProvider
170 private class InternalLinkListener implements LinkListener { 230 private class InternalLinkListener implements LinkListener {
171 @Override 231 @Override
172 public void event(LinkEvent event) { 232 public void event(LinkEvent event) {
173 - accumulator.add(event); 233 + processEvent(event);
174 } 234 }
175 } 235 }
176 236
...@@ -179,7 +239,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -179,7 +239,7 @@ public class DefaultTopologyProvider extends AbstractProvider
179 extends AbstractEventAccumulator implements EventAccumulator { 239 extends AbstractEventAccumulator implements EventAccumulator {
180 240
181 TopologyChangeAccumulator() { 241 TopologyChangeAccumulator() {
182 - super(TIMER, MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS); 242 + super(TIMER, maxEvents, maxBatchMs, maxIdleMs);
183 } 243 }
184 244
185 @Override 245 @Override
......
...@@ -67,12 +67,12 @@ public class DefaultTopologyProviderTest { ...@@ -67,12 +67,12 @@ public class DefaultTopologyProviderTest {
67 provider.deviceService = deviceService; 67 provider.deviceService = deviceService;
68 provider.linkService = linkService; 68 provider.linkService = linkService;
69 provider.providerRegistry = topologyService; 69 provider.providerRegistry = topologyService;
70 - provider.activate(); 70 + provider.activate(null);
71 } 71 }
72 72
73 @After 73 @After
74 public void tearDown() { 74 public void tearDown() {
75 - provider.deactivate(); 75 + provider.deactivate(null);
76 provider.providerRegistry = null; 76 provider.providerRegistry = null;
77 provider.deviceService = null; 77 provider.deviceService = null;
78 provider.linkService = null; 78 provider.linkService = null;
......