Fixed a defect that allowed ancillary device providers to overwrite primary provider's data.
Showing
2 changed files
with
27 additions
and
19 deletions
... | @@ -290,12 +290,17 @@ public class GossipDeviceStore | ... | @@ -290,12 +290,17 @@ public class GossipDeviceStore |
290 | private DeviceEvent updateDevice(ProviderId providerId, | 290 | private DeviceEvent updateDevice(ProviderId providerId, |
291 | Device oldDevice, | 291 | Device oldDevice, |
292 | Device newDevice, Timestamp newTimestamp) { | 292 | Device newDevice, Timestamp newTimestamp) { |
293 | - | ||
294 | // We allow only certain attributes to trigger update | 293 | // We allow only certain attributes to trigger update |
295 | - if (!Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || | 294 | + boolean propertiesChanged = |
296 | - !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()) || | 295 | + !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || |
297 | - !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations())) { | 296 | + !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()); |
298 | - | 297 | + boolean annotationsChanged = |
298 | + !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations()); | ||
299 | + | ||
300 | + // Primary providers can respond to all changes, but ancillary ones | ||
301 | + // should respond only to annotation changes. | ||
302 | + if ((providerId.isAncillary() && annotationsChanged) || | ||
303 | + (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) { | ||
299 | boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); | 304 | boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); |
300 | if (!replaced) { | 305 | if (!replaced) { |
301 | verify(replaced, | 306 | verify(replaced, | ... | ... |
... | @@ -70,15 +70,16 @@ public class SimpleDeviceStore | ... | @@ -70,15 +70,16 @@ public class SimpleDeviceStore |
70 | 70 | ||
71 | public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; | 71 | public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; |
72 | 72 | ||
73 | - // collection of Description given from various providers | 73 | + // Collection of Description given from various providers |
74 | private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>> | 74 | private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>> |
75 | deviceDescs = Maps.newConcurrentMap(); | 75 | deviceDescs = Maps.newConcurrentMap(); |
76 | 76 | ||
77 | - // cache of Device and Ports generated by compositing descriptions from providers | 77 | + // Cache of Device and Ports generated by compositing descriptions from providers |
78 | private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); | 78 | private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); |
79 | - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); | 79 | + private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> |
80 | + devicePorts = Maps.newConcurrentMap(); | ||
80 | 81 | ||
81 | - // available(=UP) devices | 82 | + // Available (=UP) devices |
82 | private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); | 83 | private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); |
83 | 84 | ||
84 | 85 | ||
... | @@ -115,13 +116,11 @@ public class SimpleDeviceStore | ... | @@ -115,13 +116,11 @@ public class SimpleDeviceStore |
115 | public DeviceEvent createOrUpdateDevice(ProviderId providerId, | 116 | public DeviceEvent createOrUpdateDevice(ProviderId providerId, |
116 | DeviceId deviceId, | 117 | DeviceId deviceId, |
117 | DeviceDescription deviceDescription) { | 118 | DeviceDescription deviceDescription) { |
118 | - | ||
119 | Map<ProviderId, DeviceDescriptions> providerDescs | 119 | Map<ProviderId, DeviceDescriptions> providerDescs |
120 | = getOrCreateDeviceDescriptions(deviceId); | 120 | = getOrCreateDeviceDescriptions(deviceId); |
121 | 121 | ||
122 | synchronized (providerDescs) { | 122 | synchronized (providerDescs) { |
123 | // locking per device | 123 | // locking per device |
124 | - | ||
125 | DeviceDescriptions descs | 124 | DeviceDescriptions descs |
126 | = getOrCreateProviderDeviceDescriptions(providerDescs, | 125 | = getOrCreateProviderDeviceDescriptions(providerDescs, |
127 | providerId, | 126 | providerId, |
... | @@ -145,7 +144,6 @@ public class SimpleDeviceStore | ... | @@ -145,7 +144,6 @@ public class SimpleDeviceStore |
145 | // Creates the device and returns the appropriate event if necessary. | 144 | // Creates the device and returns the appropriate event if necessary. |
146 | // Guarded by deviceDescs value (=Device lock) | 145 | // Guarded by deviceDescs value (=Device lock) |
147 | private DeviceEvent createDevice(ProviderId providerId, Device newDevice) { | 146 | private DeviceEvent createDevice(ProviderId providerId, Device newDevice) { |
148 | - | ||
149 | // update composed device cache | 147 | // update composed device cache |
150 | Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice); | 148 | Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice); |
151 | verify(oldDevice == null, | 149 | verify(oldDevice == null, |
... | @@ -162,14 +160,21 @@ public class SimpleDeviceStore | ... | @@ -162,14 +160,21 @@ public class SimpleDeviceStore |
162 | // Updates the device and returns the appropriate event if necessary. | 160 | // Updates the device and returns the appropriate event if necessary. |
163 | // Guarded by deviceDescs value (=Device lock) | 161 | // Guarded by deviceDescs value (=Device lock) |
164 | private DeviceEvent updateDevice(ProviderId providerId, Device oldDevice, Device newDevice) { | 162 | private DeviceEvent updateDevice(ProviderId providerId, Device oldDevice, Device newDevice) { |
165 | - | ||
166 | // We allow only certain attributes to trigger update | 163 | // We allow only certain attributes to trigger update |
167 | - if (!Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || | 164 | + boolean propertiesChanged = |
168 | - !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()) || | 165 | + !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || |
169 | - !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations())) { | 166 | + !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()); |
167 | + boolean annotationsChanged = | ||
168 | + !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations()); | ||
169 | + | ||
170 | + // Primary providers can respond to all changes, but ancillary ones | ||
171 | + // should respond only to annotation changes. | ||
172 | + if ((providerId.isAncillary() && annotationsChanged) || | ||
173 | + (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) { | ||
170 | 174 | ||
171 | boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); | 175 | boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); |
172 | if (!replaced) { | 176 | if (!replaced) { |
177 | + // FIXME: Is the enclosing if required here? | ||
173 | verify(replaced, | 178 | verify(replaced, |
174 | "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]", | 179 | "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]", |
175 | providerId, oldDevice, devices.get(newDevice.id()) | 180 | providerId, oldDevice, devices.get(newDevice.id()) |
... | @@ -214,7 +219,6 @@ public class SimpleDeviceStore | ... | @@ -214,7 +219,6 @@ public class SimpleDeviceStore |
214 | public List<DeviceEvent> updatePorts(ProviderId providerId, | 219 | public List<DeviceEvent> updatePorts(ProviderId providerId, |
215 | DeviceId deviceId, | 220 | DeviceId deviceId, |
216 | List<PortDescription> portDescriptions) { | 221 | List<PortDescription> portDescriptions) { |
217 | - | ||
218 | Device device = devices.get(deviceId); | 222 | Device device = devices.get(deviceId); |
219 | checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); | 223 | checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); |
220 | 224 | ||
... | @@ -327,7 +331,6 @@ public class SimpleDeviceStore | ... | @@ -327,7 +331,6 @@ public class SimpleDeviceStore |
327 | private DeviceDescriptions getOrCreateProviderDeviceDescriptions( | 331 | private DeviceDescriptions getOrCreateProviderDeviceDescriptions( |
328 | Map<ProviderId, DeviceDescriptions> device, | 332 | Map<ProviderId, DeviceDescriptions> device, |
329 | ProviderId providerId, DeviceDescription deltaDesc) { | 333 | ProviderId providerId, DeviceDescription deltaDesc) { |
330 | - | ||
331 | synchronized (device) { | 334 | synchronized (device) { |
332 | DeviceDescriptions r = device.get(providerId); | 335 | DeviceDescriptions r = device.get(providerId); |
333 | if (r == null) { | 336 | if (r == null) { |
... | @@ -447,7 +450,7 @@ public class SimpleDeviceStore | ... | @@ -447,7 +450,7 @@ public class SimpleDeviceStore |
447 | annotations = merge(annotations, e.getValue().getDeviceDesc().annotations()); | 450 | annotations = merge(annotations, e.getValue().getDeviceDesc().annotations()); |
448 | } | 451 | } |
449 | 452 | ||
450 | - return new DefaultDevice(primary, deviceId , type, manufacturer, | 453 | + return new DefaultDevice(primary, deviceId, type, manufacturer, |
451 | hwVersion, swVersion, serialNumber, | 454 | hwVersion, swVersion, serialNumber, |
452 | chassisId, annotations); | 455 | chassisId, annotations); |
453 | } | 456 | } | ... | ... |
-
Please register or login to post a comment