Committed by
Gerrit Code Review
Prevent link event type aliasing and proper switching between flicker = on/off.
Also scale number of threads with number of available cores. Change-Id: I438d92ab9c3df5c478f451c353135a9a64f5183e
Showing
1 changed file
with
70 additions
and
69 deletions
... | @@ -49,7 +49,6 @@ import org.osgi.service.component.ComponentContext; | ... | @@ -49,7 +49,6 @@ import org.osgi.service.component.ComponentContext; |
49 | import org.slf4j.Logger; | 49 | import org.slf4j.Logger; |
50 | 50 | ||
51 | import java.util.Dictionary; | 51 | import java.util.Dictionary; |
52 | -import java.util.Iterator; | ||
53 | import java.util.List; | 52 | import java.util.List; |
54 | import java.util.Set; | 53 | import java.util.Set; |
55 | import java.util.concurrent.ConcurrentMap; | 54 | import java.util.concurrent.ConcurrentMap; |
... | @@ -65,7 +64,6 @@ import java.net.URISyntaxException; | ... | @@ -65,7 +64,6 @@ import java.net.URISyntaxException; |
65 | import static com.google.common.base.Strings.isNullOrEmpty; | 64 | import static com.google.common.base.Strings.isNullOrEmpty; |
66 | import static org.onlab.util.Tools.groupedThreads; | 65 | import static org.onlab.util.Tools.groupedThreads; |
67 | import static org.onlab.util.Tools.toHex; | 66 | import static org.onlab.util.Tools.toHex; |
68 | -import static org.onosproject.net.MastershipRole.MASTER; | ||
69 | import static org.onosproject.net.Link.Type.DIRECT; | 67 | import static org.onosproject.net.Link.Type.DIRECT; |
70 | import static org.slf4j.LoggerFactory.getLogger; | 68 | import static org.slf4j.LoggerFactory.getLogger; |
71 | 69 | ||
... | @@ -83,11 +81,12 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -83,11 +81,12 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
83 | // default topology file location and name. | 81 | // default topology file location and name. |
84 | private static final String CFG_PATH = "/opt/onos/apache-karaf-3.0.2/etc/linkGraph.cfg"; | 82 | private static final String CFG_PATH = "/opt/onos/apache-karaf-3.0.2/etc/linkGraph.cfg"; |
85 | // default number of workers. Eventually make this tunable | 83 | // default number of workers. Eventually make this tunable |
86 | - private static final int THREADS = 8; | 84 | + private static final int THREADS = (int) Math.max(1, Runtime.getRuntime().availableProcessors() * 0.8); |
87 | 85 | ||
88 | - private static final int CHECK_DURATION = 10; | 86 | + private static final int CHECK_DURATION = 10; // sec |
89 | - private static final int DEFAULT_RATE = 0; // usec | 87 | + private static final int DEFAULT_RATE = 0; // usec |
90 | - private static final int REFRESH_RATE = 3; // sec | 88 | + private static final int REFRESH_RATE = 3; // sec |
89 | + // Fake device used for non-flickering thread in deviceMap | ||
91 | private static final DeviceId DEFAULT = DeviceId.deviceId("null:ffffffffffffffff"); | 90 | private static final DeviceId DEFAULT = DeviceId.deviceId("null:ffffffffffffffff"); |
92 | 91 | ||
93 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 92 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
... | @@ -109,14 +108,14 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -109,14 +108,14 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
109 | 108 | ||
110 | private final InternalLinkProvider linkProvider = new InternalLinkProvider(); | 109 | private final InternalLinkProvider linkProvider = new InternalLinkProvider(); |
111 | 110 | ||
112 | - // True for device with Driver, false otherwise. | 111 | + // Mapping between device and drivers that advertise links from device |
113 | private final ConcurrentMap<DeviceId, Set<LinkDriver>> driverMap = Maps | 112 | private final ConcurrentMap<DeviceId, Set<LinkDriver>> driverMap = Maps |
114 | .newConcurrentMap(); | 113 | .newConcurrentMap(); |
115 | 114 | ||
116 | // Link descriptions | 115 | // Link descriptions |
117 | private final List<LinkDescription> linkDescrs = Lists.newArrayList(); | 116 | private final List<LinkDescription> linkDescrs = Lists.newArrayList(); |
118 | 117 | ||
119 | - // Thread to description map | 118 | + // Thread to description map for dividing links amongst threads in flicker mode |
120 | private final List<List<LinkDescription>> linkTasks = Lists.newArrayList(); | 119 | private final List<List<LinkDescription>> linkTasks = Lists.newArrayList(); |
121 | 120 | ||
122 | private ScheduledExecutorService linkDriver = | 121 | private ScheduledExecutorService linkDriver = |
... | @@ -131,7 +130,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -131,7 +130,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
131 | private String cfgFile = CFG_PATH; | 130 | private String cfgFile = CFG_PATH; |
132 | 131 | ||
133 | // flag checked to create a LinkDriver, if rate is non-zero. | 132 | // flag checked to create a LinkDriver, if rate is non-zero. |
134 | - private boolean flicker = false; | 133 | + private volatile boolean flicker = false; |
135 | 134 | ||
136 | public NullLinkProvider() { | 135 | public NullLinkProvider() { |
137 | super(new ProviderId("null", "org.onosproject.provider.nil")); | 136 | super(new ProviderId("null", "org.onosproject.provider.nil")); |
... | @@ -142,28 +141,6 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -142,28 +141,6 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
142 | cfgService.registerProperties(getClass()); | 141 | cfgService.registerProperties(getClass()); |
143 | providerService = providerRegistry.register(this); | 142 | providerService = providerRegistry.register(this); |
144 | modified(context); | 143 | modified(context); |
145 | - | ||
146 | - if (flicker) { | ||
147 | - for (int i = 0; i < linkTasks.size(); i++) { | ||
148 | - List<LinkDescription> links = linkTasks.get(i); | ||
149 | - LinkDriver driver = new LinkDriver(links); | ||
150 | - links.forEach(v -> { | ||
151 | - DeviceId d = v.src().deviceId(); | ||
152 | - Set<LinkDriver> s = driverMap.getOrDefault(d, Sets.newConcurrentHashSet()); | ||
153 | - s.add(driver); | ||
154 | - driverMap.put(d, s); | ||
155 | - }); | ||
156 | - try { | ||
157 | - linkDriver.schedule(driver, eventRate, TimeUnit.MICROSECONDS); | ||
158 | - } catch (Exception e) { | ||
159 | - log.warn(e.getMessage()); | ||
160 | - } | ||
161 | - } | ||
162 | - } else { | ||
163 | - LinkDriver driver = new LinkDriver(linkDescrs); | ||
164 | - driverMap.put(DEFAULT, Sets.newHashSet(driver)); | ||
165 | - linkDriver.schedule(driver, 3, TimeUnit.SECONDS); | ||
166 | - } | ||
167 | log.info("started"); | 144 | log.info("started"); |
168 | } | 145 | } |
169 | 146 | ||
... | @@ -195,7 +172,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -195,7 +172,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
195 | String newPath; | 172 | String newPath; |
196 | try { | 173 | try { |
197 | String s = (String) properties.get("eventRate"); | 174 | String s = (String) properties.get("eventRate"); |
198 | - newRate = isNullOrEmpty(s) ? eventRate : Integer.parseInt(s.trim()); | 175 | + newRate = isNullOrEmpty(s) ? DEFAULT_RATE : Integer.parseInt(s.trim()); |
199 | s = (String) properties.get("cfgFile"); | 176 | s = (String) properties.get("cfgFile"); |
200 | newPath = s.trim(); | 177 | newPath = s.trim(); |
201 | } catch (NumberFormatException | ClassCastException e) { | 178 | } catch (NumberFormatException | ClassCastException e) { |
... | @@ -209,17 +186,45 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -209,17 +186,45 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
209 | cfgFile = newPath; | 186 | cfgFile = newPath; |
210 | } | 187 | } |
211 | readGraph(cfgFile, nodeService.getLocalNode().id()); | 188 | readGraph(cfgFile, nodeService.getLocalNode().id()); |
212 | - | 189 | + if (newRate != eventRate) { |
213 | - // test mode configuration | 190 | + if (eventRate < 0) { |
214 | - if (eventRate != newRate && newRate > 0) { | 191 | + log.warn("Invalid rate, ignoring and using default"); |
215 | - eventRate = newRate; | 192 | + eventRate = DEFAULT_RATE; |
216 | - flicker = true; | 193 | + } else { |
217 | - allocateLinks(); | 194 | + eventRate = newRate; |
218 | - } else if (newRate == 0) { | 195 | + } |
196 | + } | ||
197 | + if (eventRate > 0) { | ||
198 | + if (!flicker) { // previously not flickering | ||
199 | + flicker = true; | ||
200 | + allocateLinks(); | ||
201 | + driverMap.remove(DEFAULT); | ||
202 | + for (int i = 0; i < linkTasks.size(); i++) { | ||
203 | + List<LinkDescription> links = linkTasks.get(i); | ||
204 | + LinkDriver driver = new LinkDriver(links); | ||
205 | + links.forEach(v -> { | ||
206 | + DeviceId sd = v.src().deviceId(); | ||
207 | + DeviceId dd = v.src().deviceId(); | ||
208 | + driverMap.computeIfAbsent(sd, k -> Sets.newConcurrentHashSet()).add(driver); | ||
209 | + driverMap.computeIfAbsent(dd, k -> Sets.newConcurrentHashSet()).add(driver); | ||
210 | + }); | ||
211 | + try { | ||
212 | + linkDriver.schedule(driver, eventRate, TimeUnit.MICROSECONDS); | ||
213 | + } catch (Exception e) { | ||
214 | + log.warn(e.getMessage()); | ||
215 | + } | ||
216 | + } | ||
217 | + } | ||
218 | + } else { | ||
219 | + if (flicker) { | ||
220 | + driverMap.forEach((dev, lds) -> lds.forEach(l -> l.deviceRemoved(dev))); | ||
221 | + driverMap.clear(); | ||
222 | + linkTasks.clear(); | ||
223 | + } | ||
219 | flicker = false; | 224 | flicker = false; |
220 | - // reconfigure driver - dumb but should work. | 225 | + LinkDriver driver = new LinkDriver(linkDescrs); |
221 | - driverMap.getOrDefault(DEFAULT, Sets.newHashSet()).forEach( | 226 | + driverMap.put(DEFAULT, Sets.newHashSet(driver)); |
222 | - v -> v.setTasks(linkDescrs)); | 227 | + linkDriver.schedule(driver, REFRESH_RATE, TimeUnit.SECONDS); |
223 | } | 228 | } |
224 | 229 | ||
225 | log.info("Using settings: eventRate={}, topofile={}", eventRate, cfgFile); | 230 | log.info("Using settings: eventRate={}, topofile={}", eventRate, cfgFile); |
... | @@ -374,10 +379,8 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -374,10 +379,8 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
374 | // TODO: wait for all devices to stop core from balking | 379 | // TODO: wait for all devices to stop core from balking |
375 | break; | 380 | break; |
376 | case DEVICE_REMOVED: | 381 | case DEVICE_REMOVED: |
377 | - if (MASTER.equals(roleService.getLocalRole(dev.id()))) { | 382 | + for (LinkDriver d : driverMap.get(dev.id())) { |
378 | - for (LinkDriver d : driverMap.get(dev.id())) { | 383 | + d.deviceRemoved(dev.id()); |
379 | - d.deviceRemoved(dev.id()); | ||
380 | - } | ||
381 | } | 384 | } |
382 | providerService.linksVanished(dev.id()); | 385 | providerService.linksVanished(dev.id()); |
383 | break; | 386 | break; |
... | @@ -393,10 +396,11 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -393,10 +396,11 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
393 | */ | 396 | */ |
394 | private class LinkDriver implements Runnable { | 397 | private class LinkDriver implements Runnable { |
395 | // List to actually work off of | 398 | // List to actually work off of |
396 | - List<LinkDescription> tasks = Lists.newArrayList(); | 399 | + List<LinkDescription> tasks = Lists.newCopyOnWriteArrayList(); |
397 | float effLoad = 0; | 400 | float effLoad = 0; |
398 | Long counter = 0L; | 401 | Long counter = 0L; |
399 | int next = 0; | 402 | int next = 0; |
403 | + boolean up = true; | ||
400 | 404 | ||
401 | long startTime; | 405 | long startTime; |
402 | 406 | ||
... | @@ -416,15 +420,16 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -416,15 +420,16 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
416 | 420 | ||
417 | private void flicker() { | 421 | private void flicker() { |
418 | if ((!linkDriver.isShutdown() || !tasks.isEmpty())) { | 422 | if ((!linkDriver.isShutdown() || !tasks.isEmpty())) { |
419 | - log.info("next: {}, count: {}", next, counter); | 423 | + log.trace("next: {}, count: {}", next, counter); |
420 | - if (counter <= CHECK_DURATION * 1000000 / eventRate) { | 424 | + if (counter <= CHECK_DURATION * 1_000_000 / eventRate) { |
421 | - if ((counter % 2) == 0) { | 425 | + if (up) { |
422 | - providerService.linkVanished(tasks.get(next++)); | ||
423 | - } else { | ||
424 | providerService.linkDetected(tasks.get(next++)); | 426 | providerService.linkDetected(tasks.get(next++)); |
427 | + } else { | ||
428 | + providerService.linkVanished(tasks.get(next++)); | ||
425 | } | 429 | } |
426 | - if (next == tasks.size()) { | 430 | + if (next >= tasks.size()) { |
427 | next = 0; | 431 | next = 0; |
432 | + up = !up; | ||
428 | } | 433 | } |
429 | counter++; | 434 | counter++; |
430 | } else { | 435 | } else { |
... | @@ -442,7 +447,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -442,7 +447,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
442 | 447 | ||
443 | private void refresh() { | 448 | private void refresh() { |
444 | if (!linkDriver.isShutdown() || !tasks.isEmpty()) { | 449 | if (!linkDriver.isShutdown() || !tasks.isEmpty()) { |
445 | - log.info("iter {} refresh_links", counter); | 450 | + log.trace("iter {} refresh_links", counter); |
446 | 451 | ||
447 | for (LinkDescription desc : tasks) { | 452 | for (LinkDescription desc : tasks) { |
448 | providerService.linkDetected(desc); | 453 | providerService.linkDetected(desc); |
... | @@ -454,31 +459,27 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -454,31 +459,27 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { |
454 | } | 459 | } |
455 | 460 | ||
456 | public void deviceRemoved(DeviceId did) { | 461 | public void deviceRemoved(DeviceId did) { |
457 | - synchronized (tasks) { | 462 | + List<LinkDescription> rm = Lists.newArrayList(); |
458 | - Iterator<LinkDescription> it = tasks.iterator(); | 463 | + for (LinkDescription ld : tasks) { |
459 | - while (it.hasNext()) { | 464 | + if (did.equals(ld.dst().deviceId()) |
460 | - LinkDescription ld = it.next(); | 465 | + || (did.equals(ld.src().deviceId()))) { |
461 | - if (did.equals(ld.dst().deviceId()) | 466 | + rm.add(ld); |
462 | - || (did.equals(ld.src().deviceId()))) { | ||
463 | - it.remove(); | ||
464 | - } | ||
465 | } | 467 | } |
466 | } | 468 | } |
469 | + tasks.removeAll(rm); | ||
467 | } | 470 | } |
468 | 471 | ||
469 | public void setTasks(List<LinkDescription> links) { | 472 | public void setTasks(List<LinkDescription> links) { |
470 | HashMultimap<ConnectPoint, ConnectPoint> nm = HashMultimap.create(); | 473 | HashMultimap<ConnectPoint, ConnectPoint> nm = HashMultimap.create(); |
471 | links.forEach(v -> nm.put(v.src(), v.dst())); | 474 | links.forEach(v -> nm.put(v.src(), v.dst())); |
472 | // remove and send linkVanished for stale links. | 475 | // remove and send linkVanished for stale links. |
473 | - synchronized (this) { | 476 | + for (LinkDescription l : tasks) { |
474 | - for (LinkDescription l : tasks) { | 477 | + if (!nm.containsEntry(l.src(), l.dst())) { |
475 | - if (!nm.containsEntry(l.src(), l.dst())) { | 478 | + providerService.linkVanished(l); |
476 | - providerService.linkVanished(l); | ||
477 | - } | ||
478 | } | 479 | } |
479 | - tasks.clear(); | ||
480 | - tasks.addAll(links); | ||
481 | } | 480 | } |
481 | + tasks.clear(); | ||
482 | + tasks.addAll(links); | ||
482 | } | 483 | } |
483 | } | 484 | } |
484 | 485 | ... | ... |
-
Please register or login to post a comment