Ayaka Koshibe
Committed by Gerrit Code Review

Refactoring of NullProviders (device, host, and link)

  - Handling reading of integral properties
  - Setting change handling
  - Null Host ID generation fix

Change-Id: Id000bafe08d7d9e7db2f4eceaede11a29e43eca9
...@@ -150,13 +150,13 @@ public class NullDeviceProvider extends AbstractProvider implements DeviceProvid ...@@ -150,13 +150,13 @@ public class NullDeviceProvider extends AbstractProvider implements DeviceProvid
150 int newDevNum = DEF_NUMDEVICES; 150 int newDevNum = DEF_NUMDEVICES;
151 int newPortNum = DEF_NUMPORTS; 151 int newPortNum = DEF_NUMPORTS;
152 try { 152 try {
153 - String s = (String) properties.get("devConfigs"); 153 + String s = get(properties, "devConfigs");
154 if (!isNullOrEmpty(s)) { 154 if (!isNullOrEmpty(s)) {
155 newDevNum = getDevicesConfig(s); 155 newDevNum = getDevicesConfig(s);
156 } 156 }
157 - s = (String) properties.get("numPorts"); 157 + s = get(properties, "numPorts");
158 newPortNum = isNullOrEmpty(s) ? DEF_NUMPORTS : Integer.parseInt(s.trim()); 158 newPortNum = isNullOrEmpty(s) ? DEF_NUMPORTS : Integer.parseInt(s.trim());
159 - } catch (NumberFormatException | ClassCastException e) { 159 + } catch (NumberFormatException e) {
160 log.warn(e.getMessage()); 160 log.warn(e.getMessage());
161 newDevNum = numDevices; 161 newDevNum = numDevices;
162 newPortNum = numPorts; 162 newPortNum = numPorts;
......
...@@ -111,7 +111,7 @@ public class NullHostProvider extends AbstractProvider implements HostProvider { ...@@ -111,7 +111,7 @@ public class NullHostProvider extends AbstractProvider implements HostProvider {
111 public void triggerProbe(Host host) {} 111 public void triggerProbe(Host host) {}
112 112
113 private void addHosts(Device device) { 113 private void addHosts(Device device) {
114 - String nhash = toHex(nodeService.getLocalNode().hashCode()); 114 + String nhash = toHex(nodeService.getLocalNode().id().hashCode());
115 String dhash = device.id().toString(); 115 String dhash = device.id().toString();
116 // make sure this instance owns the device. 116 // make sure this instance owns the device.
117 if (!nhash.substring(nhash.length() - 3) 117 if (!nhash.substring(nhash.length() - 3)
......
...@@ -15,10 +15,13 @@ ...@@ -15,10 +15,13 @@
15 */ 15 */
16 package org.onosproject.provider.nil.link.impl; 16 package org.onosproject.provider.nil.link.impl;
17 17
18 +import com.google.common.base.Charsets;
18 import com.google.common.collect.HashMultimap; 19 import com.google.common.collect.HashMultimap;
19 import com.google.common.collect.Lists; 20 import com.google.common.collect.Lists;
20 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
21 import com.google.common.collect.Sets; 22 import com.google.common.collect.Sets;
23 +import com.google.common.io.Files;
24 +
22 import org.apache.felix.scr.annotations.Activate; 25 import org.apache.felix.scr.annotations.Activate;
23 import org.apache.felix.scr.annotations.Component; 26 import org.apache.felix.scr.annotations.Component;
24 import org.apache.felix.scr.annotations.Deactivate; 27 import org.apache.felix.scr.annotations.Deactivate;
...@@ -26,7 +29,6 @@ import org.apache.felix.scr.annotations.Modified; ...@@ -26,7 +29,6 @@ import org.apache.felix.scr.annotations.Modified;
26 import org.apache.felix.scr.annotations.Property; 29 import org.apache.felix.scr.annotations.Property;
27 import org.apache.felix.scr.annotations.Reference; 30 import org.apache.felix.scr.annotations.Reference;
28 import org.apache.felix.scr.annotations.ReferenceCardinality; 31 import org.apache.felix.scr.annotations.ReferenceCardinality;
29 -import org.onlab.util.Tools;
30 import org.onosproject.cfg.ComponentConfigService; 32 import org.onosproject.cfg.ComponentConfigService;
31 import org.onosproject.cluster.ClusterService; 33 import org.onosproject.cluster.ClusterService;
32 import org.onosproject.cluster.NodeId; 34 import org.onosproject.cluster.NodeId;
...@@ -49,7 +51,7 @@ import org.osgi.service.component.ComponentContext; ...@@ -49,7 +51,7 @@ import org.osgi.service.component.ComponentContext;
49 import org.slf4j.Logger; 51 import org.slf4j.Logger;
50 52
51 import java.io.BufferedReader; 53 import java.io.BufferedReader;
52 -import java.io.FileReader; 54 +import java.io.File;
53 import java.io.IOException; 55 import java.io.IOException;
54 import java.net.URI; 56 import java.net.URI;
55 import java.net.URISyntaxException; 57 import java.net.URISyntaxException;
...@@ -61,11 +63,12 @@ import java.util.concurrent.Executors; ...@@ -61,11 +63,12 @@ import java.util.concurrent.Executors;
61 import java.util.concurrent.ScheduledExecutorService; 63 import java.util.concurrent.ScheduledExecutorService;
62 import java.util.concurrent.TimeUnit; 64 import java.util.concurrent.TimeUnit;
63 65
64 -import static com.google.common.base.Strings.isNullOrEmpty;
65 import static org.onlab.util.Tools.groupedThreads; 66 import static org.onlab.util.Tools.groupedThreads;
67 +import static org.onlab.util.Tools.get;
66 import static org.onlab.util.Tools.toHex; 68 import static org.onlab.util.Tools.toHex;
67 import static org.onosproject.net.Link.Type.DIRECT; 69 import static org.onosproject.net.Link.Type.DIRECT;
68 import static org.slf4j.LoggerFactory.getLogger; 70 import static org.slf4j.LoggerFactory.getLogger;
71 +import static com.google.common.base.Strings.isNullOrEmpty;
69 72
70 /** 73 /**
71 * Provider which advertises fake/nonexistent links to the core. To be used for 74 * Provider which advertises fake/nonexistent links to the core. To be used for
...@@ -171,21 +174,21 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -171,21 +174,21 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
171 int newRate; 174 int newRate;
172 String newPath; 175 String newPath;
173 try { 176 try {
174 - String s = (String) properties.get("eventRate"); 177 + String s = get(properties, "eventRate");
175 newRate = isNullOrEmpty(s) ? DEFAULT_RATE : Integer.parseInt(s.trim()); 178 newRate = isNullOrEmpty(s) ? DEFAULT_RATE : Integer.parseInt(s.trim());
176 s = (String) properties.get("cfgFile"); 179 s = (String) properties.get("cfgFile");
177 - newPath = s.trim(); 180 + newPath = isNullOrEmpty(s) ? CFG_PATH : s.trim();
178 - } catch (NumberFormatException | ClassCastException e) { 181 + } catch (NumberFormatException e) {
179 log.warn(e.getMessage()); 182 log.warn(e.getMessage());
180 newRate = eventRate; 183 newRate = eventRate;
181 newPath = cfgFile; 184 newPath = cfgFile;
182 } 185 }
183 - 186 + // find/read topology file.
184 - // topology file configuration
185 if (!newPath.equals(cfgFile)) { 187 if (!newPath.equals(cfgFile)) {
186 cfgFile = newPath; 188 cfgFile = newPath;
187 } 189 }
188 readGraph(cfgFile, nodeService.getLocalNode().id()); 190 readGraph(cfgFile, nodeService.getLocalNode().id());
191 + // check for new eventRate settings.
189 if (newRate != eventRate) { 192 if (newRate != eventRate) {
190 if (eventRate < 0) { 193 if (eventRate < 0) {
191 log.warn("Invalid rate, ignoring and using default"); 194 log.warn("Invalid rate, ignoring and using default");
...@@ -194,11 +197,22 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -194,11 +197,22 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
194 eventRate = newRate; 197 eventRate = newRate;
195 } 198 }
196 } 199 }
200 + configureWorkers();
201 + log.info("Using settings: eventRate={}, topofile={}", eventRate, cfgFile);
202 + }
203 +
204 + // Configures and schedules worker threads based on settings.
205 + private void configureWorkers() {
197 if (eventRate > 0) { 206 if (eventRate > 0) {
198 - if (!flicker) { // previously not flickering 207 + // now set to 'flicker', previously not flickering
208 + if (!flicker) {
199 flicker = true; 209 flicker = true;
200 allocateLinks(); 210 allocateLinks();
201 - driverMap.remove(DEFAULT); 211 + // kill off refresh worker for symmetry
212 + if (driverMap.containsKey(DEFAULT)) {
213 + driverMap.get(DEFAULT).forEach(d -> d.setTasks(Lists.newArrayList()));
214 + driverMap.remove(DEFAULT);
215 + }
202 for (int i = 0; i < linkTasks.size(); i++) { 216 for (int i = 0; i < linkTasks.size(); i++) {
203 List<LinkDescription> links = linkTasks.get(i); 217 List<LinkDescription> links = linkTasks.get(i);
204 LinkDriver driver = new LinkDriver(links); 218 LinkDriver driver = new LinkDriver(links);
...@@ -208,26 +222,31 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -208,26 +222,31 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
208 driverMap.computeIfAbsent(sd, k -> Sets.newConcurrentHashSet()).add(driver); 222 driverMap.computeIfAbsent(sd, k -> Sets.newConcurrentHashSet()).add(driver);
209 driverMap.computeIfAbsent(dd, k -> Sets.newConcurrentHashSet()).add(driver); 223 driverMap.computeIfAbsent(dd, k -> Sets.newConcurrentHashSet()).add(driver);
210 }); 224 });
211 - try { 225 + linkDriver.schedule(driver, eventRate, TimeUnit.MICROSECONDS);
212 - linkDriver.schedule(driver, eventRate, TimeUnit.MICROSECONDS);
213 - } catch (Exception e) {
214 - log.warn(e.getMessage());
215 - }
216 } 226 }
217 } 227 }
228 + // no need for was flicker since eventRate will be read by workers
218 } else { 229 } else {
230 + // now set to 'refresh' was 'flicker' before
219 if (flicker) { 231 if (flicker) {
220 driverMap.forEach((dev, lds) -> lds.forEach(l -> l.deviceRemoved(dev))); 232 driverMap.forEach((dev, lds) -> lds.forEach(l -> l.deviceRemoved(dev)));
221 driverMap.clear(); 233 driverMap.clear();
222 linkTasks.clear(); 234 linkTasks.clear();
235 + flicker = false;
236 + LinkDriver driver = new LinkDriver(linkDescrs);
237 + driverMap.computeIfAbsent(DEFAULT, k -> Sets.newConcurrentHashSet()).add(driver);
238 + linkDriver.schedule(driver, DEFAULT_RATE, TimeUnit.SECONDS);
239 + // was 'refresh' - something changed or we're just starting.
240 + } else {
241 + if (driverMap.containsKey(DEFAULT)) {
242 + driverMap.forEach((dev, ld) -> ld.forEach(d -> d.setTasks(linkDescrs)));
243 + return;
244 + }
245 + LinkDriver driver = new LinkDriver(linkDescrs);
246 + driverMap.computeIfAbsent(DEFAULT, k -> Sets.newConcurrentHashSet()).add(driver);
247 + linkDriver.schedule(driver, DEFAULT_RATE, TimeUnit.SECONDS);
223 } 248 }
224 - flicker = false;
225 - LinkDriver driver = new LinkDriver(linkDescrs);
226 - driverMap.put(DEFAULT, Sets.newHashSet(driver));
227 - linkDriver.schedule(driver, REFRESH_RATE, TimeUnit.SECONDS);
228 } 249 }
229 -
230 - log.info("Using settings: eventRate={}, topofile={}", eventRate, cfgFile);
231 } 250 }
232 251
233 // parse simplified dot-like topology graph 252 // parse simplified dot-like topology graph
...@@ -236,7 +255,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -236,7 +255,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
236 Set<LinkDescription> read = Sets.newHashSet(); 255 Set<LinkDescription> read = Sets.newHashSet();
237 BufferedReader br = null; 256 BufferedReader br = null;
238 try { 257 try {
239 - br = new BufferedReader(new FileReader(path)); 258 + br = Files.newReader(new File(path), Charsets.US_ASCII);
240 String cur = br.readLine(); 259 String cur = br.readLine();
241 while (cur != null) { 260 while (cur != null) {
242 if (cur.startsWith("#")) { 261 if (cur.startsWith("#")) {
...@@ -280,18 +299,12 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -280,18 +299,12 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
280 log.warn("Could not close topology file: {}", e); 299 log.warn("Could not close topology file: {}", e);
281 } 300 }
282 } 301 }
283 - Set<LinkDescription> removedLinks = null;
284 synchronized (linkDescrs) { 302 synchronized (linkDescrs) {
285 if (!read.isEmpty()) { 303 if (!read.isEmpty()) {
286 - removedLinks = Sets.difference(Sets.newHashSet(linkDescrs), read);
287 linkDescrs.clear(); 304 linkDescrs.clear();
288 linkDescrs.addAll(read); 305 linkDescrs.addAll(read);
289 } 306 }
290 } 307 }
291 - if (!Tools.isNullOrEmpty(removedLinks)) {
292 - log.info("Removing {} old link(s)", removedLinks.size());
293 - removedLinks.forEach(providerService::linkVanished);
294 - }
295 } 308 }
296 309
297 // parses a link descriptor to make a LinkDescription 310 // parses a link descriptor to make a LinkDescription
...@@ -348,7 +361,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -348,7 +361,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
348 // recover DeviceId from configs and NodeID 361 // recover DeviceId from configs and NodeID
349 private DeviceId recover(String base, NodeId node) { 362 private DeviceId recover(String base, NodeId node) {
350 long hash = node.hashCode() << 16; 363 long hash = node.hashCode() << 16;
351 - int dev = Integer.valueOf(base); 364 + int dev = Integer.parseInt(base);
352 try { 365 try {
353 return DeviceId.deviceId(new URI("null", toHex(hash | dev), null)); 366 return DeviceId.deviceId(new URI("null", toHex(hash | dev), null));
354 } catch (URISyntaxException e) { 367 } catch (URISyntaxException e) {
...@@ -360,6 +373,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -360,6 +373,7 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
360 // adds a LinkDescription to a worker's to-be queue, for flickering 373 // adds a LinkDescription to a worker's to-be queue, for flickering
361 private void allocateLinks() { 374 private void allocateLinks() {
362 int index, lcount = 0; 375 int index, lcount = 0;
376 + linkTasks.clear();
363 for (LinkDescription ld : linkDescrs) { 377 for (LinkDescription ld : linkDescrs) {
364 index = (lcount % THREADS); 378 index = (lcount % THREADS);
365 log.info("allocation: total={}, index={}", linkDescrs.size(), lcount, index); 379 log.info("allocation: total={}, index={}", linkDescrs.size(), lcount, index);
...@@ -477,15 +491,17 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -477,15 +491,17 @@ public class NullLinkProvider extends AbstractProvider implements LinkProvider {
477 491
478 public void setTasks(List<LinkDescription> links) { 492 public void setTasks(List<LinkDescription> links) {
479 HashMultimap<ConnectPoint, ConnectPoint> nm = HashMultimap.create(); 493 HashMultimap<ConnectPoint, ConnectPoint> nm = HashMultimap.create();
494 + List<LinkDescription> rm = Lists.newArrayList();
480 links.forEach(v -> nm.put(v.src(), v.dst())); 495 links.forEach(v -> nm.put(v.src(), v.dst()));
481 // remove and send linkVanished for stale links. 496 // remove and send linkVanished for stale links.
482 for (LinkDescription l : tasks) { 497 for (LinkDescription l : tasks) {
483 if (!nm.containsEntry(l.src(), l.dst())) { 498 if (!nm.containsEntry(l.src(), l.dst())) {
484 - providerService.linkVanished(l); 499 + rm.add(l);
485 } 500 }
486 } 501 }
487 tasks.clear(); 502 tasks.clear();
488 tasks.addAll(links); 503 tasks.addAll(links);
504 + rm.forEach(l -> providerService.linkVanished(l));
489 } 505 }
490 } 506 }
491 507
......