Showing
2 changed files
with
0 additions
and
801 deletions
core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
deleted
100644 → 0
1 | -package org.onlab.onos.store.device.impl; | ||
2 | - | ||
3 | -import static com.google.common.base.Predicates.notNull; | ||
4 | - | ||
5 | -import com.google.common.base.Optional; | ||
6 | -import com.google.common.cache.LoadingCache; | ||
7 | -import com.google.common.collect.FluentIterable; | ||
8 | -import com.google.common.collect.ImmutableList; | ||
9 | -import com.google.common.collect.ImmutableSet; | ||
10 | -import com.google.common.collect.ImmutableSet.Builder; | ||
11 | -import com.hazelcast.core.IMap; | ||
12 | -import com.hazelcast.core.ISet; | ||
13 | - | ||
14 | -import org.apache.felix.scr.annotations.Activate; | ||
15 | -import org.apache.felix.scr.annotations.Component; | ||
16 | -import org.apache.felix.scr.annotations.Deactivate; | ||
17 | -import org.apache.felix.scr.annotations.Service; | ||
18 | -import org.onlab.onos.net.DefaultDevice; | ||
19 | -import org.onlab.onos.net.DefaultPort; | ||
20 | -import org.onlab.onos.net.Device; | ||
21 | -import org.onlab.onos.net.DeviceId; | ||
22 | -import org.onlab.onos.net.Port; | ||
23 | -import org.onlab.onos.net.PortNumber; | ||
24 | -import org.onlab.onos.net.device.DeviceDescription; | ||
25 | -import org.onlab.onos.net.device.DeviceEvent; | ||
26 | -import org.onlab.onos.net.device.DeviceStore; | ||
27 | -import org.onlab.onos.net.device.DeviceStoreDelegate; | ||
28 | -import org.onlab.onos.net.device.PortDescription; | ||
29 | -import org.onlab.onos.net.provider.ProviderId; | ||
30 | -import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache; | ||
31 | -import org.onlab.onos.store.common.AbstractHazelcastStore; | ||
32 | -import org.onlab.onos.store.common.OptionalCacheLoader; | ||
33 | -import org.slf4j.Logger; | ||
34 | - | ||
35 | -import java.util.ArrayList; | ||
36 | -import java.util.Collections; | ||
37 | -import java.util.HashMap; | ||
38 | -import java.util.HashSet; | ||
39 | -import java.util.Iterator; | ||
40 | -import java.util.List; | ||
41 | -import java.util.Map; | ||
42 | -import java.util.Objects; | ||
43 | -import java.util.Set; | ||
44 | - | ||
45 | -import static com.google.common.base.Preconditions.checkArgument; | ||
46 | -import static com.google.common.cache.CacheBuilder.newBuilder; | ||
47 | -import static org.onlab.onos.net.device.DeviceEvent.Type.*; | ||
48 | -import static org.slf4j.LoggerFactory.getLogger; | ||
49 | - | ||
50 | -//TODO: Add support for multiple provider and annotations | ||
51 | -/** | ||
52 | - * Manages inventory of infrastructure devices using Hazelcast-backed map. | ||
53 | - */ | ||
54 | -@Component(immediate = true) | ||
55 | -@Service | ||
56 | -public class DistributedDeviceStore | ||
57 | - extends AbstractHazelcastStore<DeviceEvent, DeviceStoreDelegate> | ||
58 | - implements DeviceStore { | ||
59 | - | ||
60 | - private final Logger log = getLogger(getClass()); | ||
61 | - | ||
62 | - public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; | ||
63 | - | ||
64 | - // private IMap<DeviceId, DefaultDevice> cache; | ||
65 | - private IMap<byte[], byte[]> rawDevices; | ||
66 | - private LoadingCache<DeviceId, Optional<DefaultDevice>> devices; | ||
67 | - | ||
68 | - // private ISet<DeviceId> availableDevices; | ||
69 | - private ISet<byte[]> availableDevices; | ||
70 | - | ||
71 | - // TODO DevicePorts is very inefficient consider restructuring. | ||
72 | - // private IMap<DeviceId, Map<PortNumber, Port>> devicePorts; | ||
73 | - private IMap<byte[], byte[]> rawDevicePorts; | ||
74 | - private LoadingCache<DeviceId, Optional<Map<PortNumber, Port>>> devicePorts; | ||
75 | - | ||
76 | - private String devicesListener; | ||
77 | - | ||
78 | - private String portsListener; | ||
79 | - | ||
80 | - @Override | ||
81 | - @Activate | ||
82 | - public void activate() { | ||
83 | - super.activate(); | ||
84 | - | ||
85 | - // IMap event handler needs value | ||
86 | - final boolean includeValue = true; | ||
87 | - | ||
88 | - // TODO decide on Map name scheme to avoid collision | ||
89 | - rawDevices = theInstance.getMap("devices"); | ||
90 | - final OptionalCacheLoader<DeviceId, DefaultDevice> deviceLoader | ||
91 | - = new OptionalCacheLoader<>(serializer, rawDevices); | ||
92 | - devices = new AbsentInvalidatingLoadingCache<>(newBuilder().build(deviceLoader)); | ||
93 | - // refresh/populate cache based on notification from other instance | ||
94 | - devicesListener = rawDevices.addEntryListener(new RemoteDeviceEventHandler(devices), includeValue); | ||
95 | - | ||
96 | - // TODO cache availableDevices | ||
97 | - availableDevices = theInstance.getSet("availableDevices"); | ||
98 | - | ||
99 | - rawDevicePorts = theInstance.getMap("devicePorts"); | ||
100 | - final OptionalCacheLoader<DeviceId, Map<PortNumber, Port>> devicePortLoader | ||
101 | - = new OptionalCacheLoader<>(serializer, rawDevicePorts); | ||
102 | - devicePorts = new AbsentInvalidatingLoadingCache<>(newBuilder().build(devicePortLoader)); | ||
103 | - // refresh/populate cache based on notification from other instance | ||
104 | - portsListener = rawDevicePorts.addEntryListener(new RemotePortEventHandler(devicePorts), includeValue); | ||
105 | - | ||
106 | - loadDeviceCache(); | ||
107 | - loadDevicePortsCache(); | ||
108 | - | ||
109 | - log.info("Started"); | ||
110 | - } | ||
111 | - | ||
112 | - @Deactivate | ||
113 | - public void deactivate() { | ||
114 | - rawDevicePorts.removeEntryListener(portsListener); | ||
115 | - rawDevices.removeEntryListener(devicesListener); | ||
116 | - log.info("Stopped"); | ||
117 | - } | ||
118 | - | ||
119 | - @Override | ||
120 | - public int getDeviceCount() { | ||
121 | - return devices.asMap().size(); | ||
122 | - } | ||
123 | - | ||
124 | - @Override | ||
125 | - public Iterable<Device> getDevices() { | ||
126 | - // TODO builder v.s. copyOf. Guava semms to be using copyOf? | ||
127 | - Builder<Device> builder = ImmutableSet.builder(); | ||
128 | - for (Optional<DefaultDevice> e : devices.asMap().values()) { | ||
129 | - if (e.isPresent()) { | ||
130 | - builder.add(e.get()); | ||
131 | - } | ||
132 | - } | ||
133 | - return builder.build(); | ||
134 | - } | ||
135 | - | ||
136 | - private void loadDeviceCache() { | ||
137 | - for (byte[] keyBytes : rawDevices.keySet()) { | ||
138 | - final DeviceId id = deserialize(keyBytes); | ||
139 | - devices.refresh(id); | ||
140 | - } | ||
141 | - } | ||
142 | - | ||
143 | - private void loadDevicePortsCache() { | ||
144 | - for (byte[] keyBytes : rawDevicePorts.keySet()) { | ||
145 | - final DeviceId id = deserialize(keyBytes); | ||
146 | - devicePorts.refresh(id); | ||
147 | - } | ||
148 | - } | ||
149 | - | ||
150 | - @Override | ||
151 | - public Device getDevice(DeviceId deviceId) { | ||
152 | - // TODO revisit if ignoring exception is safe. | ||
153 | - return devices.getUnchecked(deviceId).orNull(); | ||
154 | - } | ||
155 | - | ||
156 | - @Override | ||
157 | - public DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId, | ||
158 | - DeviceDescription deviceDescription) { | ||
159 | - DefaultDevice device = devices.getUnchecked(deviceId).orNull(); | ||
160 | - if (device == null) { | ||
161 | - return createDevice(providerId, deviceId, deviceDescription); | ||
162 | - } | ||
163 | - return updateDevice(providerId, device, deviceDescription); | ||
164 | - } | ||
165 | - | ||
166 | - // Creates the device and returns the appropriate event if necessary. | ||
167 | - private DeviceEvent createDevice(ProviderId providerId, DeviceId deviceId, | ||
168 | - DeviceDescription desc) { | ||
169 | - DefaultDevice device = new DefaultDevice(providerId, deviceId, desc.type(), | ||
170 | - desc.manufacturer(), | ||
171 | - desc.hwVersion(), desc.swVersion(), | ||
172 | - desc.serialNumber(), desc.chassisId()); | ||
173 | - | ||
174 | - synchronized (this) { | ||
175 | - final byte[] deviceIdBytes = serialize(deviceId); | ||
176 | - rawDevices.put(deviceIdBytes, serialize(device)); | ||
177 | - devices.put(deviceId, Optional.of(device)); | ||
178 | - | ||
179 | - availableDevices.add(deviceIdBytes); | ||
180 | - } | ||
181 | - return new DeviceEvent(DEVICE_ADDED, device, null); | ||
182 | - } | ||
183 | - | ||
184 | - // Updates the device and returns the appropriate event if necessary. | ||
185 | - private DeviceEvent updateDevice(ProviderId providerId, DefaultDevice device, | ||
186 | - DeviceDescription desc) { | ||
187 | - // We allow only certain attributes to trigger update | ||
188 | - if (!Objects.equals(device.hwVersion(), desc.hwVersion()) || | ||
189 | - !Objects.equals(device.swVersion(), desc.swVersion())) { | ||
190 | - | ||
191 | - DefaultDevice updated = new DefaultDevice(providerId, device.id(), | ||
192 | - desc.type(), | ||
193 | - desc.manufacturer(), | ||
194 | - desc.hwVersion(), | ||
195 | - desc.swVersion(), | ||
196 | - desc.serialNumber(), | ||
197 | - desc.chassisId()); | ||
198 | - synchronized (this) { | ||
199 | - final byte[] deviceIdBytes = serialize(device.id()); | ||
200 | - rawDevices.put(deviceIdBytes, serialize(updated)); | ||
201 | - devices.put(device.id(), Optional.of(updated)); | ||
202 | - availableDevices.add(serialize(device.id())); | ||
203 | - } | ||
204 | - return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, updated, null); | ||
205 | - } | ||
206 | - | ||
207 | - // Otherwise merely attempt to change availability | ||
208 | - synchronized (this) { | ||
209 | - boolean added = availableDevices.add(serialize(device.id())); | ||
210 | - return !added ? null : | ||
211 | - new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null); | ||
212 | - } | ||
213 | - } | ||
214 | - | ||
215 | - @Override | ||
216 | - public DeviceEvent markOffline(DeviceId deviceId) { | ||
217 | - synchronized (this) { | ||
218 | - Device device = devices.getUnchecked(deviceId).orNull(); | ||
219 | - boolean removed = device != null && availableDevices.remove(serialize(deviceId)); | ||
220 | - return !removed ? null : | ||
221 | - new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null); | ||
222 | - } | ||
223 | - } | ||
224 | - | ||
225 | - @Override | ||
226 | - public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId, | ||
227 | - List<PortDescription> portDescriptions) { | ||
228 | - List<DeviceEvent> events = new ArrayList<>(); | ||
229 | - synchronized (this) { | ||
230 | - Device device = devices.getUnchecked(deviceId).orNull(); | ||
231 | - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); | ||
232 | - Map<PortNumber, Port> ports = getPortMap(deviceId); | ||
233 | - | ||
234 | - // Add new ports | ||
235 | - Set<PortNumber> processed = new HashSet<>(); | ||
236 | - for (PortDescription portDescription : portDescriptions) { | ||
237 | - Port port = ports.get(portDescription.portNumber()); | ||
238 | - events.add(port == null ? | ||
239 | - createPort(device, portDescription, ports) : | ||
240 | - updatePort(device, port, portDescription, ports)); | ||
241 | - processed.add(portDescription.portNumber()); | ||
242 | - } | ||
243 | - | ||
244 | - updatePortMap(deviceId, ports); | ||
245 | - | ||
246 | - events.addAll(pruneOldPorts(device, ports, processed)); | ||
247 | - } | ||
248 | - return FluentIterable.from(events).filter(notNull()).toList(); | ||
249 | - } | ||
250 | - | ||
251 | - // Creates a new port based on the port description adds it to the map and | ||
252 | - // Returns corresponding event. | ||
253 | - //@GuardedBy("this") | ||
254 | - private DeviceEvent createPort(Device device, PortDescription portDescription, | ||
255 | - Map<PortNumber, Port> ports) { | ||
256 | - DefaultPort port = new DefaultPort(device, portDescription.portNumber(), | ||
257 | - portDescription.isEnabled()); | ||
258 | - ports.put(port.number(), port); | ||
259 | - updatePortMap(device.id(), ports); | ||
260 | - return new DeviceEvent(PORT_ADDED, device, port); | ||
261 | - } | ||
262 | - | ||
263 | - // Checks if the specified port requires update and if so, it replaces the | ||
264 | - // existing entry in the map and returns corresponding event. | ||
265 | - //@GuardedBy("this") | ||
266 | - private DeviceEvent updatePort(Device device, Port port, | ||
267 | - PortDescription portDescription, | ||
268 | - Map<PortNumber, Port> ports) { | ||
269 | - if (port.isEnabled() != portDescription.isEnabled()) { | ||
270 | - DefaultPort updatedPort = | ||
271 | - new DefaultPort(device, portDescription.portNumber(), | ||
272 | - portDescription.isEnabled()); | ||
273 | - ports.put(port.number(), updatedPort); | ||
274 | - updatePortMap(device.id(), ports); | ||
275 | - return new DeviceEvent(PORT_UPDATED, device, updatedPort); | ||
276 | - } | ||
277 | - return null; | ||
278 | - } | ||
279 | - | ||
280 | - // Prunes the specified list of ports based on which ports are in the | ||
281 | - // processed list and returns list of corresponding events. | ||
282 | - //@GuardedBy("this") | ||
283 | - private List<DeviceEvent> pruneOldPorts(Device device, | ||
284 | - Map<PortNumber, Port> ports, | ||
285 | - Set<PortNumber> processed) { | ||
286 | - List<DeviceEvent> events = new ArrayList<>(); | ||
287 | - Iterator<PortNumber> iterator = ports.keySet().iterator(); | ||
288 | - while (iterator.hasNext()) { | ||
289 | - PortNumber portNumber = iterator.next(); | ||
290 | - if (!processed.contains(portNumber)) { | ||
291 | - events.add(new DeviceEvent(PORT_REMOVED, device, | ||
292 | - ports.get(portNumber))); | ||
293 | - iterator.remove(); | ||
294 | - } | ||
295 | - } | ||
296 | - if (!events.isEmpty()) { | ||
297 | - updatePortMap(device.id(), ports); | ||
298 | - } | ||
299 | - return events; | ||
300 | - } | ||
301 | - | ||
302 | - // Gets the map of ports for the specified device; if one does not already | ||
303 | - // exist, it creates and registers a new one. | ||
304 | - // WARN: returned value is a copy, changes made to the Map | ||
305 | - // needs to be written back using updatePortMap | ||
306 | - //@GuardedBy("this") | ||
307 | - private Map<PortNumber, Port> getPortMap(DeviceId deviceId) { | ||
308 | - Map<PortNumber, Port> ports = devicePorts.getUnchecked(deviceId).orNull(); | ||
309 | - if (ports == null) { | ||
310 | - ports = new HashMap<>(); | ||
311 | - // this probably is waste of time in most cases. | ||
312 | - updatePortMap(deviceId, ports); | ||
313 | - } | ||
314 | - return ports; | ||
315 | - } | ||
316 | - | ||
317 | - //@GuardedBy("this") | ||
318 | - private void updatePortMap(DeviceId deviceId, Map<PortNumber, Port> ports) { | ||
319 | - rawDevicePorts.put(serialize(deviceId), serialize(ports)); | ||
320 | - devicePorts.put(deviceId, Optional.of(ports)); | ||
321 | - } | ||
322 | - | ||
323 | - @Override | ||
324 | - public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId, | ||
325 | - PortDescription portDescription) { | ||
326 | - synchronized (this) { | ||
327 | - Device device = devices.getUnchecked(deviceId).orNull(); | ||
328 | - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); | ||
329 | - Map<PortNumber, Port> ports = getPortMap(deviceId); | ||
330 | - Port port = ports.get(portDescription.portNumber()); | ||
331 | - return updatePort(device, port, portDescription, ports); | ||
332 | - } | ||
333 | - } | ||
334 | - | ||
335 | - @Override | ||
336 | - public List<Port> getPorts(DeviceId deviceId) { | ||
337 | - Map<PortNumber, Port> ports = devicePorts.getUnchecked(deviceId).orNull(); | ||
338 | - return ports == null ? Collections.<Port>emptyList() : ImmutableList.copyOf(ports.values()); | ||
339 | - } | ||
340 | - | ||
341 | - @Override | ||
342 | - public Port getPort(DeviceId deviceId, PortNumber portNumber) { | ||
343 | - Map<PortNumber, Port> ports = devicePorts.getUnchecked(deviceId).orNull(); | ||
344 | - return ports == null ? null : ports.get(portNumber); | ||
345 | - } | ||
346 | - | ||
347 | - @Override | ||
348 | - public boolean isAvailable(DeviceId deviceId) { | ||
349 | - return availableDevices.contains(serialize(deviceId)); | ||
350 | - } | ||
351 | - | ||
352 | - @Override | ||
353 | - public DeviceEvent removeDevice(DeviceId deviceId) { | ||
354 | - synchronized (this) { | ||
355 | - byte[] deviceIdBytes = serialize(deviceId); | ||
356 | - | ||
357 | - // TODO conditional remove? | ||
358 | - Device device = deserialize(rawDevices.remove(deviceIdBytes)); | ||
359 | - devices.invalidate(deviceId); | ||
360 | - return device == null ? null : | ||
361 | - new DeviceEvent(DEVICE_REMOVED, device, null); | ||
362 | - } | ||
363 | - } | ||
364 | - | ||
365 | - private class RemoteDeviceEventHandler extends RemoteCacheEventHandler<DeviceId, DefaultDevice> { | ||
366 | - public RemoteDeviceEventHandler(LoadingCache<DeviceId, Optional<DefaultDevice>> cache) { | ||
367 | - super(cache); | ||
368 | - } | ||
369 | - | ||
370 | - @Override | ||
371 | - protected void onAdd(DeviceId deviceId, DefaultDevice device) { | ||
372 | - notifyDelegate(new DeviceEvent(DEVICE_ADDED, device)); | ||
373 | - } | ||
374 | - | ||
375 | - @Override | ||
376 | - protected void onRemove(DeviceId deviceId, DefaultDevice device) { | ||
377 | - notifyDelegate(new DeviceEvent(DEVICE_REMOVED, device)); | ||
378 | - } | ||
379 | - | ||
380 | - @Override | ||
381 | - protected void onUpdate(DeviceId deviceId, DefaultDevice oldDevice, DefaultDevice device) { | ||
382 | - notifyDelegate(new DeviceEvent(DEVICE_UPDATED, device)); | ||
383 | - } | ||
384 | - } | ||
385 | - | ||
386 | - private class RemotePortEventHandler extends RemoteCacheEventHandler<DeviceId, Map<PortNumber, Port>> { | ||
387 | - public RemotePortEventHandler(LoadingCache<DeviceId, Optional<Map<PortNumber, Port>>> cache) { | ||
388 | - super(cache); | ||
389 | - } | ||
390 | - | ||
391 | - @Override | ||
392 | - protected void onAdd(DeviceId deviceId, Map<PortNumber, Port> ports) { | ||
393 | -// notifyDelegate(new DeviceEvent(PORT_ADDED, getDevice(deviceId))); | ||
394 | - } | ||
395 | - | ||
396 | - @Override | ||
397 | - protected void onRemove(DeviceId deviceId, Map<PortNumber, Port> ports) { | ||
398 | -// notifyDelegate(new DeviceEvent(PORT_REMOVED, getDevice(deviceId))); | ||
399 | - } | ||
400 | - | ||
401 | - @Override | ||
402 | - protected void onUpdate(DeviceId deviceId, Map<PortNumber, Port> oldPorts, Map<PortNumber, Port> ports) { | ||
403 | -// notifyDelegate(new DeviceEvent(PORT_UPDATED, getDevice(deviceId))); | ||
404 | - } | ||
405 | - } | ||
406 | - | ||
407 | - | ||
408 | - // TODO cache serialized DeviceID if we suffer from serialization cost | ||
409 | -} |
1 | -/** | ||
2 | - * | ||
3 | - */ | ||
4 | -package org.onlab.onos.store.device.impl; | ||
5 | - | ||
6 | -import static org.junit.Assert.*; | ||
7 | -import static org.onlab.onos.net.Device.Type.SWITCH; | ||
8 | -import static org.onlab.onos.net.DeviceId.deviceId; | ||
9 | -import static org.onlab.onos.net.device.DeviceEvent.Type.*; | ||
10 | - | ||
11 | -import java.util.Arrays; | ||
12 | -import java.util.HashMap; | ||
13 | -import java.util.List; | ||
14 | -import java.util.Map; | ||
15 | -import java.util.Set; | ||
16 | -import java.util.concurrent.CountDownLatch; | ||
17 | -import java.util.concurrent.TimeUnit; | ||
18 | - | ||
19 | -import org.junit.After; | ||
20 | -import org.junit.AfterClass; | ||
21 | -import org.junit.Before; | ||
22 | -import org.junit.BeforeClass; | ||
23 | -import org.junit.Ignore; | ||
24 | -import org.junit.Test; | ||
25 | -import org.onlab.onos.net.Device; | ||
26 | -import org.onlab.onos.net.DeviceId; | ||
27 | -import org.onlab.onos.net.Port; | ||
28 | -import org.onlab.onos.net.PortNumber; | ||
29 | -import org.onlab.onos.net.device.DefaultDeviceDescription; | ||
30 | -import org.onlab.onos.net.device.DefaultPortDescription; | ||
31 | -import org.onlab.onos.net.device.DeviceDescription; | ||
32 | -import org.onlab.onos.net.device.DeviceEvent; | ||
33 | -import org.onlab.onos.net.device.DeviceStoreDelegate; | ||
34 | -import org.onlab.onos.net.device.PortDescription; | ||
35 | -import org.onlab.onos.net.provider.ProviderId; | ||
36 | -import org.onlab.onos.store.common.StoreManager; | ||
37 | -import org.onlab.onos.store.common.StoreService; | ||
38 | -import org.onlab.onos.store.common.TestStoreManager; | ||
39 | -import com.google.common.collect.Iterables; | ||
40 | -import com.google.common.collect.Sets; | ||
41 | -import com.hazelcast.config.Config; | ||
42 | -import com.hazelcast.core.Hazelcast; | ||
43 | -import org.onlab.packet.ChassisId; | ||
44 | - | ||
45 | -/** | ||
46 | - * Test of the Hazelcast based distributed DeviceStore implementation. | ||
47 | - */ | ||
48 | -public class DistributedDeviceStoreTest { | ||
49 | - | ||
50 | - private static final ProviderId PID = new ProviderId("of", "foo"); | ||
51 | - private static final DeviceId DID1 = deviceId("of:foo"); | ||
52 | - private static final DeviceId DID2 = deviceId("of:bar"); | ||
53 | - private static final String MFR = "whitebox"; | ||
54 | - private static final String HW = "1.1.x"; | ||
55 | - private static final String SW1 = "3.8.1"; | ||
56 | - private static final String SW2 = "3.9.5"; | ||
57 | - private static final String SN = "43311-12345"; | ||
58 | - private static final ChassisId CID = new ChassisId(); | ||
59 | - | ||
60 | - private static final PortNumber P1 = PortNumber.portNumber(1); | ||
61 | - private static final PortNumber P2 = PortNumber.portNumber(2); | ||
62 | - private static final PortNumber P3 = PortNumber.portNumber(3); | ||
63 | - | ||
64 | - private DistributedDeviceStore deviceStore; | ||
65 | - | ||
66 | - private StoreManager storeManager; | ||
67 | - | ||
68 | - | ||
69 | - @BeforeClass | ||
70 | - public static void setUpBeforeClass() throws Exception { | ||
71 | - } | ||
72 | - | ||
73 | - @AfterClass | ||
74 | - public static void tearDownAfterClass() throws Exception { | ||
75 | - } | ||
76 | - | ||
77 | - | ||
78 | - @Before | ||
79 | - public void setUp() throws Exception { | ||
80 | - // TODO should find a way to clean Hazelcast instance without shutdown. | ||
81 | - Config config = TestStoreManager.getTestConfig(); | ||
82 | - | ||
83 | - storeManager = new TestStoreManager(Hazelcast.newHazelcastInstance(config)); | ||
84 | - storeManager.activate(); | ||
85 | - | ||
86 | - deviceStore = new TestDistributedDeviceStore(storeManager); | ||
87 | - deviceStore.activate(); | ||
88 | - } | ||
89 | - | ||
90 | - @After | ||
91 | - public void tearDown() throws Exception { | ||
92 | - deviceStore.deactivate(); | ||
93 | - | ||
94 | - storeManager.deactivate(); | ||
95 | - } | ||
96 | - | ||
97 | - private void putDevice(DeviceId deviceId, String swVersion) { | ||
98 | - DeviceDescription description = | ||
99 | - new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR, | ||
100 | - HW, swVersion, SN, CID); | ||
101 | - deviceStore.createOrUpdateDevice(PID, deviceId, description); | ||
102 | - } | ||
103 | - | ||
104 | - private static void assertDevice(DeviceId id, String swVersion, Device device) { | ||
105 | - assertNotNull(device); | ||
106 | - assertEquals(id, device.id()); | ||
107 | - assertEquals(MFR, device.manufacturer()); | ||
108 | - assertEquals(HW, device.hwVersion()); | ||
109 | - assertEquals(swVersion, device.swVersion()); | ||
110 | - assertEquals(SN, device.serialNumber()); | ||
111 | - } | ||
112 | - | ||
113 | - @Test | ||
114 | - public final void testGetDeviceCount() { | ||
115 | - assertEquals("initialy empty", 0, deviceStore.getDeviceCount()); | ||
116 | - | ||
117 | - putDevice(DID1, SW1); | ||
118 | - putDevice(DID2, SW2); | ||
119 | - putDevice(DID1, SW1); | ||
120 | - | ||
121 | - assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount()); | ||
122 | - } | ||
123 | - | ||
124 | - @Test | ||
125 | - public final void testGetDevices() { | ||
126 | - assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices())); | ||
127 | - | ||
128 | - putDevice(DID1, SW1); | ||
129 | - putDevice(DID2, SW2); | ||
130 | - putDevice(DID1, SW1); | ||
131 | - | ||
132 | - assertEquals("expect 2 uniq devices", | ||
133 | - 2, Iterables.size(deviceStore.getDevices())); | ||
134 | - | ||
135 | - Map<DeviceId, Device> devices = new HashMap<>(); | ||
136 | - for (Device device : deviceStore.getDevices()) { | ||
137 | - devices.put(device.id(), device); | ||
138 | - } | ||
139 | - | ||
140 | - assertDevice(DID1, SW1, devices.get(DID1)); | ||
141 | - assertDevice(DID2, SW2, devices.get(DID2)); | ||
142 | - | ||
143 | - // add case for new node? | ||
144 | - } | ||
145 | - | ||
146 | - @Test | ||
147 | - public final void testGetDevice() { | ||
148 | - | ||
149 | - putDevice(DID1, SW1); | ||
150 | - | ||
151 | - assertDevice(DID1, SW1, deviceStore.getDevice(DID1)); | ||
152 | - assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2)); | ||
153 | - } | ||
154 | - | ||
155 | - @Test | ||
156 | - public final void testCreateOrUpdateDevice() { | ||
157 | - DeviceDescription description = | ||
158 | - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, | ||
159 | - HW, SW1, SN, CID); | ||
160 | - DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description); | ||
161 | - assertEquals(DEVICE_ADDED, event.type()); | ||
162 | - assertDevice(DID1, SW1, event.subject()); | ||
163 | - | ||
164 | - DeviceDescription description2 = | ||
165 | - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, | ||
166 | - HW, SW2, SN, CID); | ||
167 | - DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2); | ||
168 | - assertEquals(DEVICE_UPDATED, event2.type()); | ||
169 | - assertDevice(DID1, SW2, event2.subject()); | ||
170 | - | ||
171 | - assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2)); | ||
172 | - } | ||
173 | - | ||
174 | - @Test | ||
175 | - public final void testMarkOffline() { | ||
176 | - | ||
177 | - putDevice(DID1, SW1); | ||
178 | - assertTrue(deviceStore.isAvailable(DID1)); | ||
179 | - | ||
180 | - DeviceEvent event = deviceStore.markOffline(DID1); | ||
181 | - assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type()); | ||
182 | - assertDevice(DID1, SW1, event.subject()); | ||
183 | - assertFalse(deviceStore.isAvailable(DID1)); | ||
184 | - | ||
185 | - DeviceEvent event2 = deviceStore.markOffline(DID1); | ||
186 | - assertNull("No change, no event", event2); | ||
187 | -} | ||
188 | - | ||
189 | - @Test | ||
190 | - public final void testUpdatePorts() { | ||
191 | - putDevice(DID1, SW1); | ||
192 | - List<PortDescription> pds = Arrays.<PortDescription>asList( | ||
193 | - new DefaultPortDescription(P1, true), | ||
194 | - new DefaultPortDescription(P2, true) | ||
195 | - ); | ||
196 | - | ||
197 | - List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds); | ||
198 | - | ||
199 | - Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); | ||
200 | - for (DeviceEvent event : events) { | ||
201 | - assertEquals(PORT_ADDED, event.type()); | ||
202 | - assertDevice(DID1, SW1, event.subject()); | ||
203 | - assertTrue("PortNumber is one of expected", | ||
204 | - expectedPorts.remove(event.port().number())); | ||
205 | - assertTrue("Port is enabled", event.port().isEnabled()); | ||
206 | - } | ||
207 | - assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty()); | ||
208 | - | ||
209 | - | ||
210 | - List<PortDescription> pds2 = Arrays.<PortDescription>asList( | ||
211 | - new DefaultPortDescription(P1, false), | ||
212 | - new DefaultPortDescription(P2, true), | ||
213 | - new DefaultPortDescription(P3, true) | ||
214 | - ); | ||
215 | - | ||
216 | - events = deviceStore.updatePorts(PID, DID1, pds2); | ||
217 | - assertFalse("event should be triggered", events.isEmpty()); | ||
218 | - for (DeviceEvent event : events) { | ||
219 | - PortNumber num = event.port().number(); | ||
220 | - if (P1.equals(num)) { | ||
221 | - assertEquals(PORT_UPDATED, event.type()); | ||
222 | - assertDevice(DID1, SW1, event.subject()); | ||
223 | - assertFalse("Port is disabled", event.port().isEnabled()); | ||
224 | - } else if (P2.equals(num)) { | ||
225 | - fail("P2 event not expected."); | ||
226 | - } else if (P3.equals(num)) { | ||
227 | - assertEquals(PORT_ADDED, event.type()); | ||
228 | - assertDevice(DID1, SW1, event.subject()); | ||
229 | - assertTrue("Port is enabled", event.port().isEnabled()); | ||
230 | - } else { | ||
231 | - fail("Unknown port number encountered: " + num); | ||
232 | - } | ||
233 | - } | ||
234 | - | ||
235 | - List<PortDescription> pds3 = Arrays.<PortDescription>asList( | ||
236 | - new DefaultPortDescription(P1, false), | ||
237 | - new DefaultPortDescription(P2, true) | ||
238 | - ); | ||
239 | - events = deviceStore.updatePorts(PID, DID1, pds3); | ||
240 | - assertFalse("event should be triggered", events.isEmpty()); | ||
241 | - for (DeviceEvent event : events) { | ||
242 | - PortNumber num = event.port().number(); | ||
243 | - if (P1.equals(num)) { | ||
244 | - fail("P1 event not expected."); | ||
245 | - } else if (P2.equals(num)) { | ||
246 | - fail("P2 event not expected."); | ||
247 | - } else if (P3.equals(num)) { | ||
248 | - assertEquals(PORT_REMOVED, event.type()); | ||
249 | - assertDevice(DID1, SW1, event.subject()); | ||
250 | - assertTrue("Port was enabled", event.port().isEnabled()); | ||
251 | - } else { | ||
252 | - fail("Unknown port number encountered: " + num); | ||
253 | - } | ||
254 | - } | ||
255 | - | ||
256 | - } | ||
257 | - | ||
258 | - @Test | ||
259 | - public final void testUpdatePortStatus() { | ||
260 | - putDevice(DID1, SW1); | ||
261 | - List<PortDescription> pds = Arrays.<PortDescription>asList( | ||
262 | - new DefaultPortDescription(P1, true) | ||
263 | - ); | ||
264 | - deviceStore.updatePorts(PID, DID1, pds); | ||
265 | - | ||
266 | - DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, | ||
267 | - new DefaultPortDescription(P1, false)); | ||
268 | - assertEquals(PORT_UPDATED, event.type()); | ||
269 | - assertDevice(DID1, SW1, event.subject()); | ||
270 | - assertEquals(P1, event.port().number()); | ||
271 | - assertFalse("Port is disabled", event.port().isEnabled()); | ||
272 | - } | ||
273 | - | ||
274 | - @Test | ||
275 | - public final void testGetPorts() { | ||
276 | - putDevice(DID1, SW1); | ||
277 | - putDevice(DID2, SW1); | ||
278 | - List<PortDescription> pds = Arrays.<PortDescription>asList( | ||
279 | - new DefaultPortDescription(P1, true), | ||
280 | - new DefaultPortDescription(P2, true) | ||
281 | - ); | ||
282 | - deviceStore.updatePorts(PID, DID1, pds); | ||
283 | - | ||
284 | - Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); | ||
285 | - List<Port> ports = deviceStore.getPorts(DID1); | ||
286 | - for (Port port : ports) { | ||
287 | - assertTrue("Port is enabled", port.isEnabled()); | ||
288 | - assertTrue("PortNumber is one of expected", | ||
289 | - expectedPorts.remove(port.number())); | ||
290 | - } | ||
291 | - assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty()); | ||
292 | - | ||
293 | - | ||
294 | - assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty()); | ||
295 | - } | ||
296 | - | ||
297 | - @Test | ||
298 | - public final void testGetPort() { | ||
299 | - putDevice(DID1, SW1); | ||
300 | - putDevice(DID2, SW1); | ||
301 | - List<PortDescription> pds = Arrays.<PortDescription>asList( | ||
302 | - new DefaultPortDescription(P1, true), | ||
303 | - new DefaultPortDescription(P2, false) | ||
304 | - ); | ||
305 | - deviceStore.updatePorts(PID, DID1, pds); | ||
306 | - | ||
307 | - Port port1 = deviceStore.getPort(DID1, P1); | ||
308 | - assertEquals(P1, port1.number()); | ||
309 | - assertTrue("Port is enabled", port1.isEnabled()); | ||
310 | - | ||
311 | - Port port2 = deviceStore.getPort(DID1, P2); | ||
312 | - assertEquals(P2, port2.number()); | ||
313 | - assertFalse("Port is disabled", port2.isEnabled()); | ||
314 | - | ||
315 | - Port port3 = deviceStore.getPort(DID1, P3); | ||
316 | - assertNull("P3 not expected", port3); | ||
317 | - } | ||
318 | - | ||
319 | - @Test | ||
320 | - public final void testRemoveDevice() { | ||
321 | - putDevice(DID1, SW1); | ||
322 | - putDevice(DID2, SW1); | ||
323 | - | ||
324 | - assertEquals(2, deviceStore.getDeviceCount()); | ||
325 | - | ||
326 | - DeviceEvent event = deviceStore.removeDevice(DID1); | ||
327 | - assertEquals(DEVICE_REMOVED, event.type()); | ||
328 | - assertDevice(DID1, SW1, event.subject()); | ||
329 | - | ||
330 | - assertEquals(1, deviceStore.getDeviceCount()); | ||
331 | - } | ||
332 | - | ||
333 | - // TODO add test for Port events when we have them | ||
334 | - @Ignore("Ignore until Delegate spec. is clear.") | ||
335 | - @Test | ||
336 | - public final void testEvents() throws InterruptedException { | ||
337 | - final CountDownLatch addLatch = new CountDownLatch(1); | ||
338 | - DeviceStoreDelegate checkAdd = new DeviceStoreDelegate() { | ||
339 | - @Override | ||
340 | - public void notify(DeviceEvent event) { | ||
341 | - assertEquals(DEVICE_ADDED, event.type()); | ||
342 | - assertDevice(DID1, SW1, event.subject()); | ||
343 | - addLatch.countDown(); | ||
344 | - } | ||
345 | - }; | ||
346 | - final CountDownLatch updateLatch = new CountDownLatch(1); | ||
347 | - DeviceStoreDelegate checkUpdate = new DeviceStoreDelegate() { | ||
348 | - @Override | ||
349 | - public void notify(DeviceEvent event) { | ||
350 | - assertEquals(DEVICE_UPDATED, event.type()); | ||
351 | - assertDevice(DID1, SW2, event.subject()); | ||
352 | - updateLatch.countDown(); | ||
353 | - } | ||
354 | - }; | ||
355 | - final CountDownLatch removeLatch = new CountDownLatch(1); | ||
356 | - DeviceStoreDelegate checkRemove = new DeviceStoreDelegate() { | ||
357 | - @Override | ||
358 | - public void notify(DeviceEvent event) { | ||
359 | - assertEquals(DEVICE_REMOVED, event.type()); | ||
360 | - assertDevice(DID1, SW2, event.subject()); | ||
361 | - removeLatch.countDown(); | ||
362 | - } | ||
363 | - }; | ||
364 | - | ||
365 | - DeviceDescription description = | ||
366 | - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, | ||
367 | - HW, SW1, SN, CID); | ||
368 | - deviceStore.setDelegate(checkAdd); | ||
369 | - deviceStore.createOrUpdateDevice(PID, DID1, description); | ||
370 | - assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS)); | ||
371 | - | ||
372 | - | ||
373 | - DeviceDescription description2 = | ||
374 | - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, | ||
375 | - HW, SW2, SN, CID); | ||
376 | - deviceStore.unsetDelegate(checkAdd); | ||
377 | - deviceStore.setDelegate(checkUpdate); | ||
378 | - deviceStore.createOrUpdateDevice(PID, DID1, description2); | ||
379 | - assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS)); | ||
380 | - | ||
381 | - deviceStore.unsetDelegate(checkUpdate); | ||
382 | - deviceStore.setDelegate(checkRemove); | ||
383 | - deviceStore.removeDevice(DID1); | ||
384 | - assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS)); | ||
385 | - } | ||
386 | - | ||
387 | - private class TestDistributedDeviceStore extends DistributedDeviceStore { | ||
388 | - public TestDistributedDeviceStore(StoreService storeService) { | ||
389 | - this.storeService = storeService; | ||
390 | - } | ||
391 | - } | ||
392 | -} |
-
Please register or login to post a comment