Committed by
Ray Milkey
NullLinkProvider restructured with a CachedThreadPool. This should in theory
allow more LinkDescriptions to be generated. - patch 3/4: Some cleanup/sanity checks added. Reference: ONOS-1033 Change-Id: I0b35585d5fdec3f7e6c921172f39f67dd6723dec
Showing
1 changed file
with
96 additions
and
35 deletions
... | @@ -22,13 +22,16 @@ import static org.onlab.util.Tools.toHex; | ... | @@ -22,13 +22,16 @@ import static org.onlab.util.Tools.toHex; |
22 | import static org.onosproject.net.MastershipRole.MASTER; | 22 | import static org.onosproject.net.MastershipRole.MASTER; |
23 | 23 | ||
24 | import java.util.Dictionary; | 24 | import java.util.Dictionary; |
25 | +import java.util.Iterator; | ||
25 | import java.util.List; | 26 | import java.util.List; |
27 | +import java.util.Set; | ||
26 | import java.util.Objects; | 28 | import java.util.Objects; |
27 | import java.util.concurrent.ConcurrentMap; | 29 | import java.util.concurrent.ConcurrentMap; |
28 | import java.util.concurrent.ExecutorService; | 30 | import java.util.concurrent.ExecutorService; |
29 | import java.util.concurrent.Executors; | 31 | import java.util.concurrent.Executors; |
30 | import java.util.concurrent.TimeUnit; | 32 | import java.util.concurrent.TimeUnit; |
31 | 33 | ||
34 | +import org.apache.commons.lang3.concurrent.ConcurrentUtils; | ||
32 | import org.apache.felix.scr.annotations.Activate; | 35 | import org.apache.felix.scr.annotations.Activate; |
33 | import org.apache.felix.scr.annotations.Component; | 36 | import org.apache.felix.scr.annotations.Component; |
34 | import org.apache.felix.scr.annotations.Deactivate; | 37 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -62,6 +65,7 @@ import org.slf4j.Logger; | ... | @@ -62,6 +65,7 @@ import org.slf4j.Logger; |
62 | 65 | ||
63 | import com.google.common.collect.Lists; | 66 | import com.google.common.collect.Lists; |
64 | import com.google.common.collect.Maps; | 67 | import com.google.common.collect.Maps; |
68 | +import com.google.common.collect.Sets; | ||
65 | 69 | ||
66 | /** | 70 | /** |
67 | * Provider which advertises fake/nonexistent links to the core. To be used for | 71 | * Provider which advertises fake/nonexistent links to the core. To be used for |
... | @@ -95,8 +99,12 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -95,8 +99,12 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
95 | private final InternalLinkProvider linkProvider = new InternalLinkProvider(); | 99 | private final InternalLinkProvider linkProvider = new InternalLinkProvider(); |
96 | private final InternalLinkListener listener = new InternalLinkListener(); | 100 | private final InternalLinkListener listener = new InternalLinkListener(); |
97 | 101 | ||
102 | + // True for device with Driver, false otherwise. | ||
103 | + private final ConcurrentMap<DeviceId, Boolean> driverMap = Maps | ||
104 | + .newConcurrentMap(); | ||
105 | + | ||
98 | // Link descriptions | 106 | // Link descriptions |
99 | - private final ConcurrentMap<ConnectPoint, LinkDescription> descriptions = Maps | 107 | + private final ConcurrentMap<DeviceId, Set<LinkDescription>> linkDescrs = Maps |
100 | .newConcurrentMap(); | 108 | .newConcurrentMap(); |
101 | 109 | ||
102 | // Local Device ID's that have been seen so far | 110 | // Local Device ID's that have been seen so far |
... | @@ -104,20 +112,24 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -104,20 +112,24 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
104 | // tail ends of other islands | 112 | // tail ends of other islands |
105 | private final List<ConnectPoint> tails = Lists.newArrayList(); | 113 | private final List<ConnectPoint> tails = Lists.newArrayList(); |
106 | 114 | ||
107 | - private ExecutorService linkDriver = Executors.newFixedThreadPool(1, | 115 | + private final int checkRateDuration = 10; |
108 | - namedThreads("onos-null-link-driver")); | 116 | + |
117 | + private ExecutorService linkDriver = Executors.newCachedThreadPool( | ||
118 | + namedThreads("onos-null-link-driver-%d")); | ||
109 | 119 | ||
110 | // For flicker = true, duration between events in msec. | 120 | // For flicker = true, duration between events in msec. |
111 | @Property(name = "eventRate", value = "0", | 121 | @Property(name = "eventRate", value = "0", |
112 | label = "Duration between Link Event") | 122 | label = "Duration between Link Event") |
113 | private int eventRate = DEFAULT_RATE; | 123 | private int eventRate = DEFAULT_RATE; |
114 | - private int checkRateDuration = 10; | ||
115 | 124 | ||
116 | // For flicker = true, duration between events in msec. | 125 | // For flicker = true, duration between events in msec. |
117 | @Property(name = "neighbors", value = "", | 126 | @Property(name = "neighbors", value = "", |
118 | label = "Node ID of instance for neighboring island ") | 127 | label = "Node ID of instance for neighboring island ") |
119 | private String neighbor = ""; | 128 | private String neighbor = ""; |
120 | 129 | ||
130 | + // flag checked to create a LinkDriver, if rate is non-zero. | ||
131 | + private boolean flicker = false; | ||
132 | + | ||
121 | public NullLinkProvider() { | 133 | public NullLinkProvider() { |
122 | super(new ProviderId("null", "org.onosproject.provider.nil")); | 134 | super(new ProviderId("null", "org.onosproject.provider.nil")); |
123 | } | 135 | } |
... | @@ -126,20 +138,20 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -126,20 +138,20 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
126 | public void activate(ComponentContext context) { | 138 | public void activate(ComponentContext context) { |
127 | providerService = providerRegistry.register(this); | 139 | providerService = providerRegistry.register(this); |
128 | linkService = (LinkService) providerRegistry; | 140 | linkService = (LinkService) providerRegistry; |
141 | + modified(context); | ||
129 | linkService.addListener(listener); | 142 | linkService.addListener(listener); |
130 | deviceService.addListener(linkProvider); | 143 | deviceService.addListener(linkProvider); |
131 | - modified(context); | 144 | + |
132 | log.info("started"); | 145 | log.info("started"); |
133 | } | 146 | } |
134 | 147 | ||
135 | @Deactivate | 148 | @Deactivate |
136 | public void deactivate(ComponentContext context) { | 149 | public void deactivate(ComponentContext context) { |
137 | - if (eventRate != 0) { | 150 | + linkDriver.shutdown(); |
138 | try { | 151 | try { |
139 | linkDriver.awaitTermination(1000, TimeUnit.MILLISECONDS); | 152 | linkDriver.awaitTermination(1000, TimeUnit.MILLISECONDS); |
140 | } catch (InterruptedException e) { | 153 | } catch (InterruptedException e) { |
141 | log.error("LinkBuilder did not terminate"); | 154 | log.error("LinkBuilder did not terminate"); |
142 | - } | ||
143 | linkDriver.shutdownNow(); | 155 | linkDriver.shutdownNow(); |
144 | } | 156 | } |
145 | deviceService.removeListener(linkProvider); | 157 | deviceService.removeListener(linkProvider); |
... | @@ -175,10 +187,23 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -175,10 +187,23 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
175 | if (newNbor != neighbor) { | 187 | if (newNbor != neighbor) { |
176 | neighbor = newNbor; | 188 | neighbor = newNbor; |
177 | } | 189 | } |
178 | - | ||
179 | if (newRate != 0 & eventRate != newRate) { | 190 | if (newRate != 0 & eventRate != newRate) { |
180 | eventRate = newRate; | 191 | eventRate = newRate; |
181 | - linkDriver.submit(new LinkDriver()); | 192 | + flicker = true; |
193 | + // try to find and add drivers for current devices | ||
194 | + for (Device dev : deviceService.getDevices()) { | ||
195 | + DeviceId did = dev.id(); | ||
196 | + synchronized (this) { | ||
197 | + if (driverMap.get(did) == null || !driverMap.get(did)) { | ||
198 | + driverMap.put(dev.id(), true); | ||
199 | + linkDriver.submit(new LinkDriver(dev)); | ||
200 | + } | ||
201 | + } | ||
202 | + } | ||
203 | + } else if (newRate == 0) { | ||
204 | + driverMap.replaceAll((k, v) -> false); | ||
205 | + } else { | ||
206 | + log.warn("Invalid link flicker rate {}", newRate); | ||
182 | } | 207 | } |
183 | 208 | ||
184 | log.info("Using new settings: eventRate={}", eventRate); | 209 | log.info("Using new settings: eventRate={}", eventRate); |
... | @@ -213,24 +238,10 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -213,24 +238,10 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
213 | return ""; | 238 | return ""; |
214 | } | 239 | } |
215 | 240 | ||
216 | - /** | 241 | + private boolean addLdesc(DeviceId did, LinkDescription ldesc) { |
217 | - * Adds links as devices are found, and generates LinkEvents. | 242 | + Set<LinkDescription> ldescs = ConcurrentUtils.putIfAbsent( |
218 | - */ | 243 | + linkDescrs, did, Sets.newConcurrentHashSet()); |
219 | - private class InternalLinkProvider implements DeviceListener { | 244 | + return ldescs.add(ldesc); |
220 | - | ||
221 | - @Override | ||
222 | - public void event(DeviceEvent event) { | ||
223 | - Device dev = event.subject(); | ||
224 | - switch (event.type()) { | ||
225 | - case DEVICE_ADDED: | ||
226 | - addLink(dev); | ||
227 | - break; | ||
228 | - case DEVICE_REMOVED: | ||
229 | - removeLink(dev); | ||
230 | - break; | ||
231 | - default: | ||
232 | - break; | ||
233 | - } | ||
234 | } | 245 | } |
235 | 246 | ||
236 | private void addLink(Device current) { | 247 | private void addLink(Device current) { |
... | @@ -261,8 +272,8 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -261,8 +272,8 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
261 | Link.Type.DIRECT); | 272 | Link.Type.DIRECT); |
262 | LinkDescription rdesc = new DefaultLinkDescription(dst, src, | 273 | LinkDescription rdesc = new DefaultLinkDescription(dst, src, |
263 | Link.Type.DIRECT); | 274 | Link.Type.DIRECT); |
264 | - descriptions.put(src, fdesc); | 275 | + addLdesc(prev, fdesc); |
265 | - descriptions.put(dst, rdesc); | 276 | + addLdesc(did, rdesc); |
266 | 277 | ||
267 | providerService.linkDetected(fdesc); | 278 | providerService.linkDetected(fdesc); |
268 | providerService.linkDetected(rdesc); | 279 | providerService.linkDetected(rdesc); |
... | @@ -281,7 +292,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -281,7 +292,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
281 | } | 292 | } |
282 | LinkDescription ld = new DefaultLinkDescription(cp, first, | 293 | LinkDescription ld = new DefaultLinkDescription(cp, first, |
283 | Link.Type.DIRECT); | 294 | Link.Type.DIRECT); |
284 | - descriptions.put(cp, ld); | 295 | + addLdesc(cp.deviceId(), ld); |
285 | providerService.linkDetected(ld); | 296 | providerService.linkDetected(ld); |
286 | added = true; | 297 | added = true; |
287 | break; | 298 | break; |
... | @@ -291,12 +302,52 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -291,12 +302,52 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
291 | } | 302 | } |
292 | } | 303 | } |
293 | 304 | ||
305 | + /** | ||
306 | + * Adds links as devices are found, and generates LinkEvents. | ||
307 | + */ | ||
308 | + private class InternalLinkProvider implements DeviceListener { | ||
309 | + | ||
310 | + @Override | ||
311 | + public void event(DeviceEvent event) { | ||
312 | + Device dev = event.subject(); | ||
313 | + switch (event.type()) { | ||
314 | + case DEVICE_ADDED: | ||
315 | + synchronized (this) { | ||
316 | + if (flicker && !driverMap.getOrDefault(dev.id(), false)) { | ||
317 | + driverMap.put(dev.id(), true); | ||
318 | + linkDriver.submit(new LinkDriver(dev)); | ||
319 | + } | ||
320 | + } | ||
321 | + addLink(dev); | ||
322 | + break; | ||
323 | + case DEVICE_REMOVED: | ||
324 | + driverMap.put(dev.id(), false); | ||
325 | + removeLink(dev); | ||
326 | + break; | ||
327 | + default: | ||
328 | + break; | ||
329 | + } | ||
330 | + } | ||
331 | + | ||
294 | private void removeLink(Device device) { | 332 | private void removeLink(Device device) { |
295 | if (!MASTER.equals(roleService.getLocalRole(device.id()))) { | 333 | if (!MASTER.equals(roleService.getLocalRole(device.id()))) { |
296 | return; | 334 | return; |
297 | } | 335 | } |
298 | providerService.linksVanished(device.id()); | 336 | providerService.linksVanished(device.id()); |
299 | devices.remove(device.id()); | 337 | devices.remove(device.id()); |
338 | + synchronized (linkDescrs) { | ||
339 | + Set<LinkDescription> lds = linkDescrs.remove(device.id()); | ||
340 | + for (LinkDescription ld : lds) { | ||
341 | + ConnectPoint src = ld.src(); | ||
342 | + DeviceId dst = ld.dst().deviceId(); | ||
343 | + Iterator<LinkDescription> it = linkDescrs.get(dst).iterator(); | ||
344 | + while (it.hasNext()) { | ||
345 | + if (it.next().dst().equals(src)) { | ||
346 | + it.remove(); | ||
347 | + } | ||
348 | + } | ||
349 | + } | ||
350 | + } | ||
300 | } | 351 | } |
301 | 352 | ||
302 | } | 353 | } |
... | @@ -317,7 +368,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -317,7 +368,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
317 | LinkDescription ld = new DefaultLinkDescription(event | 368 | LinkDescription ld = new DefaultLinkDescription(event |
318 | .subject().dst(), event.subject().src(), | 369 | .subject().dst(), event.subject().src(), |
319 | Link.Type.DIRECT); | 370 | Link.Type.DIRECT); |
320 | - descriptions.put(event.subject().dst(), ld); | 371 | + addLdesc(event.subject().dst().deviceId(), ld); |
321 | providerService.linkDetected(ld); | 372 | providerService.linkDetected(ld); |
322 | } | 373 | } |
323 | return; | 374 | return; |
... | @@ -334,18 +385,26 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -334,18 +385,26 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
334 | * Generates link events using fake links. | 385 | * Generates link events using fake links. |
335 | */ | 386 | */ |
336 | private class LinkDriver implements Runnable { | 387 | private class LinkDriver implements Runnable { |
388 | + Device myDev; | ||
389 | + LinkDriver(Device dev) { | ||
390 | + myDev = dev; | ||
391 | + } | ||
337 | 392 | ||
338 | @Override | 393 | @Override |
339 | public void run() { | 394 | public void run() { |
395 | + log.info("Thread started for dev {}", myDev.id()); | ||
340 | long startTime = System.currentTimeMillis(); | 396 | long startTime = System.currentTimeMillis(); |
341 | long countEvent = 0; | 397 | long countEvent = 0; |
342 | float effLoad = 0; | 398 | float effLoad = 0; |
343 | 399 | ||
344 | - while (!linkDriver.isShutdown()) { | 400 | + while (!linkDriver.isShutdown() && driverMap.get(myDev.id())) { |
401 | + if (linkDescrs.get(myDev.id()) == null) { | ||
402 | + addLink(myDev); | ||
403 | + } | ||
345 | 404 | ||
346 | //Assuming eventRate is in microsecond unit | 405 | //Assuming eventRate is in microsecond unit |
347 | if (countEvent <= checkRateDuration * 1000000 / eventRate) { | 406 | if (countEvent <= checkRateDuration * 1000000 / eventRate) { |
348 | - for (LinkDescription desc : descriptions.values()) { | 407 | + for (LinkDescription desc : linkDescrs.get(myDev.id())) { |
349 | providerService.linkVanished(desc); | 408 | providerService.linkVanished(desc); |
350 | countEvent++; | 409 | countEvent++; |
351 | try { | 410 | try { |
... | @@ -363,8 +422,10 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -363,8 +422,10 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
363 | } | 422 | } |
364 | } else { | 423 | } else { |
365 | // log in WARN the effective load generation rate in events/sec, every 10 seconds | 424 | // log in WARN the effective load generation rate in events/sec, every 10 seconds |
366 | - effLoad = (float) (countEvent * 1000 / (System.currentTimeMillis() - startTime)); | 425 | + effLoad = (float) (countEvent * 1000.0 / |
367 | - log.warn("Effective Loading is {} events/second", String.valueOf(effLoad)); | 426 | + (System.currentTimeMillis() - startTime)); |
427 | + log.warn("Effective Loading for thread is {} events/second", | ||
428 | + String.valueOf(effLoad)); | ||
368 | countEvent = 0; | 429 | countEvent = 0; |
369 | startTime = System.currentTimeMillis(); | 430 | startTime = System.currentTimeMillis(); |
370 | } | 431 | } | ... | ... |
-
Please register or login to post a comment