Yuta HIGUCHI
Committed by Yuta HIGUCHI

Allow reading PortDescription from DeviceStore

DeviceManager had to reverse-engineer PortDescription
in order to mark port off-line, etc.
which required domain specific knowledge.
(e.g., OpticalPortOperatorr#descriptionOf)

required work for ONOS-4691

Change-Id: I954f5f2db2cb7db938f498ead4c8e3f84212a53f
...@@ -24,6 +24,7 @@ import org.onosproject.store.Store; ...@@ -24,6 +24,7 @@ import org.onosproject.store.Store;
24 24
25 import java.util.Collection; 25 import java.util.Collection;
26 import java.util.List; 26 import java.util.List;
27 +import java.util.stream.Stream;
27 28
28 /** 29 /**
29 * Manages inventory of infrastructure devices; not intended for direct use. 30 * Manages inventory of infrastructure devices; not intended for direct use.
...@@ -115,6 +116,15 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -115,6 +116,15 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
115 List<Port> getPorts(DeviceId deviceId); 116 List<Port> getPorts(DeviceId deviceId);
116 117
117 /** 118 /**
119 + * Returns the stream of port descriptions that belong to the specified device.
120 + *
121 + * @param providerId provider identifier
122 + * @param deviceId device identifier
123 + * @return stream of device portdescriptions
124 + */
125 + Stream<PortDescription> getPortDescriptions(ProviderId providerId, DeviceId deviceId);
126 +
127 + /**
118 * Updates the port statistics of the specified device using the give port 128 * Updates the port statistics of the specified device using the give port
119 * statistics. 129 * statistics.
120 * 130 *
...@@ -152,6 +162,16 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -152,6 +162,16 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
152 Port getPort(DeviceId deviceId, PortNumber portNumber); 162 Port getPort(DeviceId deviceId, PortNumber portNumber);
153 163
154 /** 164 /**
165 + * Returns the specified device port description.
166 + *
167 + * @param providerId provider identifier
168 + * @param deviceId device identifier
169 + * @param portNumber port number
170 + * @return device port description
171 + */
172 + PortDescription getPortDescription(ProviderId providerId, DeviceId deviceId, PortNumber portNumber);
173 +
174 + /**
155 * Indicates whether the specified device is available/online. 175 * Indicates whether the specified device is available/online.
156 * 176 *
157 * @param deviceId device identifier 177 * @param deviceId device identifier
......
...@@ -24,6 +24,7 @@ import org.onosproject.net.provider.ProviderId; ...@@ -24,6 +24,7 @@ import org.onosproject.net.provider.ProviderId;
24 24
25 import java.util.Collection; 25 import java.util.Collection;
26 import java.util.List; 26 import java.util.List;
27 +import java.util.stream.Stream;
27 28
28 /** 29 /**
29 * Test adapter for the DeviceStore API. 30 * Test adapter for the DeviceStore API.
...@@ -78,6 +79,12 @@ public class DeviceStoreAdapter implements DeviceStore { ...@@ -78,6 +79,12 @@ public class DeviceStoreAdapter implements DeviceStore {
78 } 79 }
79 80
80 @Override 81 @Override
82 + public Stream<PortDescription> getPortDescriptions(ProviderId providerId,
83 + DeviceId deviceId) {
84 + return Stream.empty();
85 + }
86 +
87 + @Override
81 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, 88 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId,
82 Collection<PortStatistics> portStats) { 89 Collection<PortStatistics> portStats) {
83 return null; 90 return null;
...@@ -99,6 +106,13 @@ public class DeviceStoreAdapter implements DeviceStore { ...@@ -99,6 +106,13 @@ public class DeviceStoreAdapter implements DeviceStore {
99 } 106 }
100 107
101 @Override 108 @Override
109 + public PortDescription getPortDescription(ProviderId providerId,
110 + DeviceId deviceId,
111 + PortNumber portNumber) {
112 + return null;
113 + }
114 +
115 + @Override
102 public boolean isAvailable(DeviceId deviceId) { 116 public boolean isAvailable(DeviceId deviceId) {
103 return false; 117 return false;
104 } 118 }
......
...@@ -59,11 +59,13 @@ import java.util.List; ...@@ -59,11 +59,13 @@ import java.util.List;
59 import java.util.Map; 59 import java.util.Map;
60 import java.util.Map.Entry; 60 import java.util.Map.Entry;
61 import java.util.Objects; 61 import java.util.Objects;
62 +import java.util.Optional;
62 import java.util.Set; 63 import java.util.Set;
63 import java.util.concurrent.ConcurrentHashMap; 64 import java.util.concurrent.ConcurrentHashMap;
64 import java.util.concurrent.ConcurrentMap; 65 import java.util.concurrent.ConcurrentMap;
65 import java.util.concurrent.TimeUnit; 66 import java.util.concurrent.TimeUnit;
66 import java.util.concurrent.atomic.AtomicReference; 67 import java.util.concurrent.atomic.AtomicReference;
68 +import java.util.stream.Stream;
67 69
68 import static com.google.common.base.Preconditions.checkArgument; 70 import static com.google.common.base.Preconditions.checkArgument;
69 import static com.google.common.base.Preconditions.checkNotNull; 71 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -416,6 +418,15 @@ public class SimpleDeviceStore ...@@ -416,6 +418,15 @@ public class SimpleDeviceStore
416 } 418 }
417 419
418 @Override 420 @Override
421 + public Stream<PortDescription> getPortDescriptions(ProviderId providerId,
422 + DeviceId deviceId) {
423 + return Optional.ofNullable(deviceDescs.get(deviceId))
424 + .map(m -> m.get(providerId))
425 + .map(descs -> descs.portDescs.values().stream())
426 + .orElse(Stream.empty());
427 + }
428 +
429 + @Override
419 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, 430 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId,
420 Collection<PortStatistics> newStatsCollection) { 431 Collection<PortStatistics> newStatsCollection) {
421 432
...@@ -480,6 +491,16 @@ public class SimpleDeviceStore ...@@ -480,6 +491,16 @@ public class SimpleDeviceStore
480 } 491 }
481 492
482 @Override 493 @Override
494 + public PortDescription getPortDescription(ProviderId providerId,
495 + DeviceId deviceId,
496 + PortNumber portNumber) {
497 + return Optional.ofNullable(deviceDescs.get(deviceId))
498 + .map(m -> m.get(providerId))
499 + .map(descs -> descs.getPortDesc(portNumber))
500 + .orElse(null);
501 + }
502 +
503 + @Override
483 public List<PortStatistics> getPortStatistics(DeviceId deviceId) { 504 public List<PortStatistics> getPortStatistics(DeviceId deviceId) {
484 Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); 505 Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId);
485 if (portStats == null) { 506 if (portStats == null) {
......
...@@ -86,6 +86,7 @@ import org.onosproject.net.optical.device.OmsPortHelper; ...@@ -86,6 +86,7 @@ import org.onosproject.net.optical.device.OmsPortHelper;
86 import org.onosproject.net.optical.device.OtuPortHelper; 86 import org.onosproject.net.optical.device.OtuPortHelper;
87 import org.onosproject.net.provider.AbstractListenerProviderRegistry; 87 import org.onosproject.net.provider.AbstractListenerProviderRegistry;
88 import org.onosproject.net.provider.AbstractProviderService; 88 import org.onosproject.net.provider.AbstractProviderService;
89 +import org.onosproject.net.provider.Provider;
89 import org.slf4j.Logger; 90 import org.slf4j.Logger;
90 91
91 import com.google.common.util.concurrent.Futures; 92 import com.google.common.util.concurrent.Futures;
...@@ -367,6 +368,17 @@ public class DeviceManager ...@@ -367,6 +368,17 @@ public class DeviceManager
367 368
368 } 369 }
369 370
371 + private PortDescription ensurePortEnabledState(PortDescription desc, boolean enabled) {
372 + if (desc.isEnabled() != enabled) {
373 + return new DefaultPortDescription(desc.portNumber(),
374 + enabled,
375 + desc.type(),
376 + desc.portSpeed(),
377 + desc.annotations());
378 + }
379 + return desc;
380 + }
381 +
370 @Override 382 @Override
371 public void deviceDisconnected(DeviceId deviceId) { 383 public void deviceDisconnected(DeviceId deviceId) {
372 checkNotNull(deviceId, DEVICE_ID_NULL); 384 checkNotNull(deviceId, DEVICE_ID_NULL);
...@@ -374,17 +386,9 @@ public class DeviceManager ...@@ -374,17 +386,9 @@ public class DeviceManager
374 386
375 log.info("Device {} disconnected from this node", deviceId); 387 log.info("Device {} disconnected from this node", deviceId);
376 388
377 - List<Port> ports = store.getPorts(deviceId); 389 + List<PortDescription> descs = store.getPortDescriptions(provider().id(), deviceId)
378 - final Device device = getDevice(deviceId); 390 + .map(desc -> ensurePortEnabledState(desc, false))
379 - 391 + .collect(Collectors.toList());
380 - List<PortDescription> descs = ports.stream().map(
381 - port -> (!(Device.Type.ROADM.equals(device.type()) ||
382 - (Device.Type.OTN.equals(device.type())) ||
383 - (Device.Type.FIBER_SWITCH.equals(device.type())))) ?
384 - new DefaultPortDescription(port.number(), false,
385 - port.type(), port.portSpeed()) :
386 - OpticalPortOperator.descriptionOf(port, false)
387 - ).collect(Collectors.toList());
388 392
389 store.updatePorts(this.provider().id(), deviceId, descs); 393 store.updatePorts(this.provider().id(), deviceId, descs);
390 try { 394 try {
...@@ -524,9 +528,12 @@ public class DeviceManager ...@@ -524,9 +528,12 @@ public class DeviceManager
524 Device device = nullIsNotFound(getDevice(deviceId), "Device not found"); 528 Device device = nullIsNotFound(getDevice(deviceId), "Device not found");
525 if ((Device.Type.ROADM.equals(device.type())) || 529 if ((Device.Type.ROADM.equals(device.type())) ||
526 (Device.Type.OTN.equals(device.type()))) { 530 (Device.Type.OTN.equals(device.type()))) {
527 - Port port = getPort(deviceId, portDescription.portNumber());
528 // FIXME This is ignoring all other info in portDescription given as input?? 531 // FIXME This is ignoring all other info in portDescription given as input??
529 - portDescription = OpticalPortOperator.descriptionOf(port, portDescription.isEnabled()); 532 + PortDescription storedPortDesc = store.getPortDescription(provider().id(),
533 + deviceId,
534 + portDescription.portNumber());
535 + portDescription = ensurePortEnabledState(storedPortDesc,
536 + portDescription.isEnabled());
530 } 537 }
531 538
532 portDescription = consolidate(deviceId, portDescription); 539 portDescription = consolidate(deviceId, portDescription);
...@@ -847,13 +854,14 @@ public class DeviceManager ...@@ -847,13 +854,14 @@ public class DeviceManager
847 if (event.configClass().equals(OpticalPortConfig.class)) { 854 if (event.configClass().equals(OpticalPortConfig.class)) {
848 ConnectPoint cpt = (ConnectPoint) event.subject(); 855 ConnectPoint cpt = (ConnectPoint) event.subject();
849 DeviceId did = cpt.deviceId(); 856 DeviceId did = cpt.deviceId();
857 + Provider provider = getProvider(did);
850 Port dpt = getPort(did, cpt.port()); 858 Port dpt = getPort(did, cpt.port());
851 859
852 - if (dpt != null) { 860 + if (dpt != null && provider != null) {
853 OpticalPortConfig opc = networkConfigService.getConfig(cpt, OpticalPortConfig.class); 861 OpticalPortConfig opc = networkConfigService.getConfig(cpt, OpticalPortConfig.class);
854 - PortDescription desc = OpticalPortOperator.descriptionOf(dpt); 862 + PortDescription desc = store.getPortDescription(provider.id(), did, cpt.port());
855 desc = OpticalPortOperator.combine(opc, desc); 863 desc = OpticalPortOperator.combine(opc, desc);
856 - if (desc != null && getProvider(did) != null) { 864 + if (desc != null) {
857 de = store.updatePortStatus(getProvider(did).id(), did, desc); 865 de = store.updatePortStatus(getProvider(did).id(), did, desc);
858 } 866 }
859 } 867 }
......
...@@ -20,13 +20,10 @@ import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDesc ...@@ -20,13 +20,10 @@ import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDesc
20 import static org.onosproject.net.optical.device.OmsPortHelper.omsPortDescription; 20 import static org.onosproject.net.optical.device.OmsPortHelper.omsPortDescription;
21 import static org.onosproject.net.optical.device.OtuPortHelper.otuPortDescription; 21 import static org.onosproject.net.optical.device.OtuPortHelper.otuPortDescription;
22 import static org.slf4j.LoggerFactory.getLogger; 22 import static org.slf4j.LoggerFactory.getLogger;
23 -import static com.google.common.base.Preconditions.checkNotNull;
24 -
25 import org.onosproject.net.config.ConfigOperator; 23 import org.onosproject.net.config.ConfigOperator;
26 import org.onosproject.net.config.basics.OpticalPortConfig; 24 import org.onosproject.net.config.basics.OpticalPortConfig;
27 import org.onosproject.net.AnnotationKeys; 25 import org.onosproject.net.AnnotationKeys;
28 import org.onosproject.net.DefaultAnnotations; 26 import org.onosproject.net.DefaultAnnotations;
29 -import org.onosproject.net.Port;
30 import org.onosproject.net.PortNumber; 27 import org.onosproject.net.PortNumber;
31 import org.onosproject.net.SparseAnnotations; 28 import org.onosproject.net.SparseAnnotations;
32 import org.onosproject.net.device.DefaultPortDescription; 29 import org.onosproject.net.device.DefaultPortDescription;
...@@ -35,11 +32,6 @@ import org.onosproject.net.device.OduCltPortDescription; ...@@ -35,11 +32,6 @@ import org.onosproject.net.device.OduCltPortDescription;
35 import org.onosproject.net.device.OmsPortDescription; 32 import org.onosproject.net.device.OmsPortDescription;
36 import org.onosproject.net.device.OtuPortDescription; 33 import org.onosproject.net.device.OtuPortDescription;
37 import org.onosproject.net.device.PortDescription; 34 import org.onosproject.net.device.PortDescription;
38 -import org.onosproject.net.optical.OchPort;
39 -import org.onosproject.net.optical.OduCltPort;
40 -import org.onosproject.net.optical.OmsPort;
41 -import org.onosproject.net.optical.OpticalDevice;
42 -import org.onosproject.net.optical.OtuPort;
43 import org.slf4j.Logger; 35 import org.slf4j.Logger;
44 36
45 /** 37 /**
...@@ -184,98 +176,4 @@ public final class OpticalPortOperator implements ConfigOperator { ...@@ -184,98 +176,4 @@ public final class OpticalPortOperator implements ConfigOperator {
184 return DefaultAnnotations.union(an, b.build()); 176 return DefaultAnnotations.union(an, b.build());
185 } 177 }
186 178
187 - /**
188 - * Returns a description built from an existing port.
189 - *
190 - * @param port the device port
191 - * @return a PortDescription based on the port
192 - */
193 - public static PortDescription descriptionOf(Port port) {
194 - checkNotNull(port, "Must supply non-null Port");
195 - final boolean isUp = port.isEnabled();
196 - return descriptionOfPort(port, isUp);
197 - }
198 -
199 - /**
200 - * Returns a description built from an existing port and reported status.
201 - *
202 - * @param port port
203 - * @param isEnabled true if enabled
204 - * @return a PortDescription based on the port
205 - */
206 - static PortDescription descriptionOf(Port port, boolean isEnabled) {
207 - checkNotNull(port, "Must supply non-null Port");
208 - final boolean isup = isEnabled;
209 - return descriptionOfPort(port, isup);
210 - }
211 -
212 - private static PortDescription descriptionOfPort(Port port, final boolean isup) {
213 - final PortNumber ptn = port.number();
214 - final SparseAnnotations an = (SparseAnnotations) port.annotations();
215 - switch (port.type()) {
216 - case OMS:
217 - if (port instanceof org.onosproject.net.OmsPort) {
218 - // remove if-block once deprecation is complete
219 - org.onosproject.net.OmsPort oms = (org.onosproject.net.OmsPort) port;
220 - return omsPortDescription(ptn, isup, oms.minFrequency(),
221 - oms.maxFrequency(), oms.grid(), an);
222 - }
223 - if (port.element().is(OpticalDevice.class)) {
224 - OpticalDevice optDevice = port.element().as(OpticalDevice.class);
225 - if (optDevice.portIs(port, OmsPort.class)) {
226 - OmsPort oms = optDevice.portAs(port, OmsPort.class).get();
227 - return omsPortDescription(ptn, isup, oms.minFrequency(),
228 - oms.maxFrequency(), oms.grid(), an);
229 - }
230 - }
231 - return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
232 - case OCH:
233 - if (port instanceof org.onosproject.net.OchPort) {
234 - // remove if-block once old OchPort deprecation is complete
235 - org.onosproject.net.OchPort och = (org.onosproject.net.OchPort) port;
236 - return ochPortDescription(ptn, isup, och.signalType(),
237 - och.isTunable(), och.lambda(), an);
238 - }
239 - if (port.element().is(OpticalDevice.class)) {
240 - OpticalDevice optDevice = port.element().as(OpticalDevice.class);
241 - if (optDevice.portIs(port, OchPort.class)) {
242 - OchPort och = optDevice.portAs(port, OchPort.class).get();
243 - return ochPortDescription(ptn, isup, och.signalType(),
244 - och.isTunable(), och.lambda(), an);
245 - }
246 - }
247 - return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
248 -
249 - case ODUCLT:
250 - if (port instanceof org.onosproject.net.OduCltPort) {
251 - // remove if-block once deprecation is complete
252 - org.onosproject.net.OduCltPort odu = (org.onosproject.net.OduCltPort) port;
253 - return oduCltPortDescription(ptn, isup, odu.signalType(), an);
254 - }
255 - if (port.element().is(OpticalDevice.class)) {
256 - OpticalDevice optDevice = port.element().as(OpticalDevice.class);
257 - if (optDevice.portIs(port, OduCltPort.class)) {
258 - OduCltPort odu = (OduCltPort) port;
259 - return oduCltPortDescription(ptn, isup, odu.signalType(), an);
260 - }
261 - }
262 - return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
263 - case OTU:
264 - if (port instanceof org.onosproject.net.OtuPort) {
265 - // remove if-block once deprecation is complete
266 - org.onosproject.net.OtuPort otu = (org.onosproject.net.OtuPort) port;
267 - return otuPortDescription(ptn, isup, otu.signalType(), an);
268 - }
269 - if (port.element().is(OpticalDevice.class)) {
270 - OpticalDevice optDevice = port.element().as(OpticalDevice.class);
271 - if (optDevice.portIs(port, OtuPort.class)) {
272 - OtuPort otu = (OtuPort) port;
273 - return otuPortDescription(ptn, isup, otu.signalType(), an);
274 - }
275 - }
276 - return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
277 - default:
278 - return new DefaultPortDescription(ptn, isup, port.type(), port.portSpeed(), an);
279 - }
280 - }
281 } 179 }
......
...@@ -87,6 +87,7 @@ import java.util.Set; ...@@ -87,6 +87,7 @@ import java.util.Set;
87 import java.util.concurrent.TimeUnit; 87 import java.util.concurrent.TimeUnit;
88 import java.util.concurrent.atomic.AtomicReference; 88 import java.util.concurrent.atomic.AtomicReference;
89 import java.util.stream.Collectors; 89 import java.util.stream.Collectors;
90 +import java.util.stream.Stream;
90 91
91 import static com.google.common.base.Preconditions.checkArgument; 92 import static com.google.common.base.Preconditions.checkArgument;
92 import static com.google.common.base.Verify.verify; 93 import static com.google.common.base.Verify.verify;
...@@ -575,11 +576,27 @@ public class ECDeviceStore ...@@ -575,11 +576,27 @@ public class ECDeviceStore
575 } 576 }
576 577
577 @Override 578 @Override
579 + public Stream<PortDescription> getPortDescriptions(ProviderId pid,
580 + DeviceId deviceId) {
581 +
582 + return portDescriptions.entrySet().stream()
583 + .filter(e -> e.getKey().providerId().equals(pid))
584 + .map(Map.Entry::getValue);
585 + }
586 +
587 + @Override
578 public Port getPort(DeviceId deviceId, PortNumber portNumber) { 588 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
579 return devicePorts.getOrDefault(deviceId, Maps.newHashMap()).get(portNumber); 589 return devicePorts.getOrDefault(deviceId, Maps.newHashMap()).get(portNumber);
580 } 590 }
581 591
582 @Override 592 @Override
593 + public PortDescription getPortDescription(ProviderId pid,
594 + DeviceId deviceId,
595 + PortNumber portNumber) {
596 + return portDescriptions.get(new PortKey(pid, deviceId, portNumber));
597 + }
598 +
599 + @Override
583 public DeviceEvent updatePortStatistics(ProviderId providerId, 600 public DeviceEvent updatePortStatistics(ProviderId providerId,
584 DeviceId deviceId, 601 DeviceId deviceId,
585 Collection<PortStatistics> newStatsCollection) { 602 Collection<PortStatistics> newStatsCollection) {
......
...@@ -93,11 +93,13 @@ import java.util.List; ...@@ -93,11 +93,13 @@ import java.util.List;
93 import java.util.Map; 93 import java.util.Map;
94 import java.util.Map.Entry; 94 import java.util.Map.Entry;
95 import java.util.Objects; 95 import java.util.Objects;
96 +import java.util.Optional;
96 import java.util.Set; 97 import java.util.Set;
97 import java.util.concurrent.ConcurrentMap; 98 import java.util.concurrent.ConcurrentMap;
98 import java.util.concurrent.ExecutorService; 99 import java.util.concurrent.ExecutorService;
99 import java.util.concurrent.ScheduledExecutorService; 100 import java.util.concurrent.ScheduledExecutorService;
100 import java.util.concurrent.TimeUnit; 101 import java.util.concurrent.TimeUnit;
102 +import java.util.stream.Stream;
101 103
102 import static com.google.common.base.Preconditions.checkArgument; 104 import static com.google.common.base.Preconditions.checkArgument;
103 import static com.google.common.base.Predicates.notNull; 105 import static com.google.common.base.Predicates.notNull;
...@@ -835,6 +837,25 @@ public class GossipDeviceStore ...@@ -835,6 +837,25 @@ public class GossipDeviceStore
835 } 837 }
836 838
837 @Override 839 @Override
840 + public Stream<PortDescription> getPortDescriptions(ProviderId pid,
841 + DeviceId deviceId) {
842 + Map<ProviderId, DeviceDescriptions> descs = this.deviceDescs.get(deviceId);
843 + if (descs == null) {
844 + return null;
845 + }
846 + // inner-Map(=descs) is HashMap, thus requires synchronization even for reads
847 + final Optional<DeviceDescriptions> devDescs;
848 + synchronized (descs) {
849 + devDescs = Optional.ofNullable(descs.get(pid));
850 + }
851 + // DeviceDescriptions is concurrent access-safe
852 + return devDescs
853 + .map(dd -> dd.getPortDescs().values().stream()
854 + .map(Timestamped::value))
855 + .orElse(Stream.empty());
856 + }
857 +
858 + @Override
838 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, 859 public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId,
839 Collection<PortStatistics> newStatsCollection) { 860 Collection<PortStatistics> newStatsCollection) {
840 861
...@@ -926,6 +947,26 @@ public class GossipDeviceStore ...@@ -926,6 +947,26 @@ public class GossipDeviceStore
926 } 947 }
927 948
928 @Override 949 @Override
950 + public PortDescription getPortDescription(ProviderId pid,
951 + DeviceId deviceId,
952 + PortNumber portNumber) {
953 + Map<ProviderId, DeviceDescriptions> descs = this.deviceDescs.get(deviceId);
954 + if (descs == null) {
955 + return null;
956 + }
957 + // inner-Map(=descs) is HashMap, thus requires synchronization even for reads
958 + final Optional<DeviceDescriptions> devDescs;
959 + synchronized (descs) {
960 + devDescs = Optional.ofNullable(descs.get(pid));
961 + }
962 + // DeviceDescriptions is concurrent access-safe
963 + return devDescs
964 + .map(deviceDescriptions -> deviceDescriptions.getPortDesc(portNumber))
965 + .map(Timestamped::value)
966 + .orElse(null);
967 + }
968 +
969 + @Override
929 public boolean isAvailable(DeviceId deviceId) { 970 public boolean isAvailable(DeviceId deviceId) {
930 return availableDevices.contains(deviceId); 971 return availableDevices.contains(deviceId);
931 } 972 }
......