Bug fixes/improvements:
1. DeviceManager must not have a dependency on DeviceClockService. Clocks and Timestamps are purely distribution concerns. 2. Eliminated DeviceClockProviderService which merely served as a cache for mastership terms thereby introducing a source of staleness. Now we directly query mastership service which is already optimized for high volume reads. 3. DistributedLeadershipManager fix to ensure election won by local node immediately reflects in the local leaderboard. This is to ensure a subsequent read does not return a stale value. Change-Id: I774b64923e382b788df5f8bde2a9fafc0294bad0
Showing
11 changed files
with
138 additions
and
198 deletions
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.mastership; | 16 | package org.onosproject.mastership; |
17 | 17 | ||
18 | +import static org.onosproject.net.MastershipRole.MASTER; | ||
19 | + | ||
18 | import java.util.Set; | 20 | import java.util.Set; |
19 | import java.util.concurrent.CompletableFuture; | 21 | import java.util.concurrent.CompletableFuture; |
20 | 22 | ||
... | @@ -43,6 +45,16 @@ public interface MastershipService | ... | @@ -43,6 +45,16 @@ public interface MastershipService |
43 | MastershipRole getLocalRole(DeviceId deviceId); | 45 | MastershipRole getLocalRole(DeviceId deviceId); |
44 | 46 | ||
45 | /** | 47 | /** |
48 | + * Returns true if the local controller is the Master for the specified deviceId. | ||
49 | + * | ||
50 | + * @param deviceId the the identifier of the device | ||
51 | + * @return true if local node is master; false otherwise | ||
52 | + */ | ||
53 | + default boolean isLocalMaster(DeviceId deviceId) { | ||
54 | + return getLocalRole(deviceId) == MASTER; | ||
55 | + } | ||
56 | + | ||
57 | + /** | ||
46 | * Returns the mastership status of the local controller for a given | 58 | * Returns the mastership status of the local controller for a given |
47 | * device forcing master selection if necessary. | 59 | * device forcing master selection if necessary. |
48 | * | 60 | * | ... | ... |
core/api/src/main/java/org/onosproject/net/device/DeviceClockProviderService.java
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright 2014 Open Networking Laboratory | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.onosproject.net.device; | ||
17 | - | ||
18 | -import org.onosproject.mastership.MastershipTerm; | ||
19 | -import org.onosproject.net.DeviceId; | ||
20 | - | ||
21 | -/** | ||
22 | -* Interface for feeding term information to a logical clock service | ||
23 | -* that vends per device timestamps. | ||
24 | -*/ | ||
25 | -public interface DeviceClockProviderService { | ||
26 | - | ||
27 | - /** | ||
28 | - * Checks if this service can issue Timestamp for specified device. | ||
29 | - * | ||
30 | - * @param deviceId device identifier. | ||
31 | - * @return true if timestamp can be issued for specified device | ||
32 | - */ | ||
33 | - boolean isTimestampAvailable(DeviceId deviceId); | ||
34 | - | ||
35 | - /** | ||
36 | - * Updates the mastership term for the specified deviceId. | ||
37 | - * | ||
38 | - * @param deviceId device identifier. | ||
39 | - * @param term mastership term. | ||
40 | - */ | ||
41 | - void setMastershipTerm(DeviceId deviceId, MastershipTerm term); | ||
42 | -} |
1 | +package org.onosproject.net.device; | ||
2 | + | ||
3 | +import org.onosproject.net.DeviceId; | ||
4 | +import org.onosproject.store.Timestamp; | ||
5 | + | ||
6 | +/** | ||
7 | + * Test adapter for device clock service. | ||
8 | + */ | ||
9 | +public class DeviceClockServiceAdapter implements DeviceClockService { | ||
10 | + | ||
11 | + @Override | ||
12 | + public boolean isTimestampAvailable(DeviceId deviceId) { | ||
13 | + return false; | ||
14 | + } | ||
15 | + | ||
16 | + @Override | ||
17 | + public Timestamp getTimestamp(DeviceId deviceId) { | ||
18 | + return null; | ||
19 | + } | ||
20 | + | ||
21 | +} |
core/common/src/test/java/org/onosproject/store/trivial/NoOpClockProviderService.java
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright 2014 Open Networking Laboratory | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.onosproject.store.trivial; | ||
17 | - | ||
18 | -import java.util.Set; | ||
19 | - | ||
20 | -import org.apache.felix.scr.annotations.Component; | ||
21 | -import org.apache.felix.scr.annotations.Service; | ||
22 | -import org.onosproject.mastership.MastershipTerm; | ||
23 | -import org.onosproject.net.DeviceId; | ||
24 | -import org.onosproject.net.device.DeviceClockProviderService; | ||
25 | - | ||
26 | -import com.google.common.collect.Sets; | ||
27 | - | ||
28 | -/** | ||
29 | - * Dummy implementation of {@link DeviceClockProviderService}. | ||
30 | - */ | ||
31 | -@Component(immediate = true) | ||
32 | -@Service | ||
33 | -public class NoOpClockProviderService implements DeviceClockProviderService { | ||
34 | - | ||
35 | - private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet(); | ||
36 | - | ||
37 | - @Override | ||
38 | - public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { | ||
39 | - registerdBefore.add(deviceId); | ||
40 | - } | ||
41 | - | ||
42 | - @Override | ||
43 | - public boolean isTimestampAvailable(DeviceId deviceId) { | ||
44 | - return registerdBefore.contains(deviceId); | ||
45 | - } | ||
46 | -} |
... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
16 | package org.onosproject.net.device.impl; | 16 | package org.onosproject.net.device.impl; |
17 | 17 | ||
18 | import com.google.common.collect.Lists; | 18 | import com.google.common.collect.Lists; |
19 | +import com.google.common.util.concurrent.Futures; | ||
20 | + | ||
19 | import org.apache.felix.scr.annotations.Activate; | 21 | import org.apache.felix.scr.annotations.Activate; |
20 | import org.apache.felix.scr.annotations.Component; | 22 | import org.apache.felix.scr.annotations.Component; |
21 | import org.apache.felix.scr.annotations.Deactivate; | 23 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -46,7 +48,6 @@ import org.onosproject.net.SparseAnnotations; | ... | @@ -46,7 +48,6 @@ import org.onosproject.net.SparseAnnotations; |
46 | import org.onosproject.net.device.DefaultDeviceDescription; | 48 | import org.onosproject.net.device.DefaultDeviceDescription; |
47 | import org.onosproject.net.device.DefaultPortDescription; | 49 | import org.onosproject.net.device.DefaultPortDescription; |
48 | import org.onosproject.net.device.DeviceAdminService; | 50 | import org.onosproject.net.device.DeviceAdminService; |
49 | -import org.onosproject.net.device.DeviceClockProviderService; | ||
50 | import org.onosproject.net.device.DeviceDescription; | 51 | import org.onosproject.net.device.DeviceDescription; |
51 | import org.onosproject.net.device.DeviceEvent; | 52 | import org.onosproject.net.device.DeviceEvent; |
52 | import org.onosproject.net.device.DeviceListener; | 53 | import org.onosproject.net.device.DeviceListener; |
... | @@ -118,12 +119,8 @@ public class DeviceManager | ... | @@ -118,12 +119,8 @@ public class DeviceManager |
118 | protected MastershipTermService termService; | 119 | protected MastershipTermService termService; |
119 | 120 | ||
120 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 121 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
121 | - protected DeviceClockProviderService deviceClockProviderService; | ||
122 | - | ||
123 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
124 | protected NetworkConfigService networkConfigService; | 122 | protected NetworkConfigService networkConfigService; |
125 | 123 | ||
126 | - | ||
127 | @Activate | 124 | @Activate |
128 | public void activate() { | 125 | public void activate() { |
129 | backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos/device", "manager-background")); | 126 | backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos/device", "manager-background")); |
... | @@ -316,31 +313,13 @@ public class DeviceManager | ... | @@ -316,31 +313,13 @@ public class DeviceManager |
316 | checkValidity(); | 313 | checkValidity(); |
317 | deviceDescription = validateDevice(deviceDescription, deviceId); | 314 | deviceDescription = validateDevice(deviceDescription, deviceId); |
318 | 315 | ||
319 | - // check my Role | 316 | + // Establish my Role |
320 | - CompletableFuture<MastershipRole> role = mastershipService.requestRoleFor(deviceId); | 317 | + Futures.getUnchecked(mastershipService.requestRoleFor(deviceId) |
321 | - try { | 318 | + .thenAccept(role -> { |
322 | - // Device subsystem must wait for role assignment | 319 | + log.info("Local role is {} for {}", role, deviceId); |
323 | - // to avoid losing Device information. | 320 | + applyRole(deviceId, role); |
324 | - // (This node could be the only Node connected to the Device.) | 321 | + })); |
325 | - role.get(); | ||
326 | - } catch (InterruptedException e) { | ||
327 | - log.warn("Interrupted while waiting role-assignment for {}", deviceId); | ||
328 | - Thread.currentThread().interrupt(); | ||
329 | - } catch (ExecutionException e) { | ||
330 | - log.error("Exception thrown while waiting role-assignment for {}", | ||
331 | - deviceId, e); | ||
332 | - } | ||
333 | 322 | ||
334 | - final MastershipTerm term = termService.getMastershipTerm(deviceId); | ||
335 | - if (term == null || !localNodeId.equals(term.master())) { | ||
336 | - log.info("Role of this node is STANDBY for {}", deviceId); | ||
337 | - applyRole(deviceId, MastershipRole.STANDBY); | ||
338 | - } else { | ||
339 | - log.info("Role of this node is MASTER for {}", deviceId); | ||
340 | - // tell clock provider if this instance is the master | ||
341 | - deviceClockProviderService.setMastershipTerm(deviceId, term); | ||
342 | - applyRole(deviceId, MastershipRole.MASTER); | ||
343 | - } | ||
344 | DeviceEvent event = store.createOrUpdateDevice(provider().id(), deviceId, | 323 | DeviceEvent event = store.createOrUpdateDevice(provider().id(), deviceId, |
345 | deviceDescription); | 324 | deviceDescription); |
346 | if (event != null) { | 325 | if (event != null) { |
... | @@ -383,7 +362,7 @@ public class DeviceManager | ... | @@ -383,7 +362,7 @@ public class DeviceManager |
383 | port.portSpeed()))); | 362 | port.portSpeed()))); |
384 | store.updatePorts(this.provider().id(), deviceId, descs); | 363 | store.updatePorts(this.provider().id(), deviceId, descs); |
385 | try { | 364 | try { |
386 | - if (mastershipService.getLocalRole(deviceId) == MASTER) { | 365 | + if (mastershipService.isLocalMaster(deviceId)) { |
387 | post(store.markOffline(deviceId)); | 366 | post(store.markOffline(deviceId)); |
388 | } | 367 | } |
389 | } catch (IllegalStateException e) { | 368 | } catch (IllegalStateException e) { |
... | @@ -405,7 +384,6 @@ public class DeviceManager | ... | @@ -405,7 +384,6 @@ public class DeviceManager |
405 | // TODO: Move this type of check inside device clock manager, etc. | 384 | // TODO: Move this type of check inside device clock manager, etc. |
406 | if (term != null && localNodeId.equals(term.master())) { | 385 | if (term != null && localNodeId.equals(term.master())) { |
407 | log.info("Retry marking {} offline", deviceId); | 386 | log.info("Retry marking {} offline", deviceId); |
408 | - deviceClockProviderService.setMastershipTerm(deviceId, term); | ||
409 | post(store.markOffline(deviceId)); | 387 | post(store.markOffline(deviceId)); |
410 | } else { | 388 | } else { |
411 | log.info("Failed again marking {} offline. {}", deviceId, role); | 389 | log.info("Failed again marking {} offline. {}", deviceId, role); |
... | @@ -431,7 +409,7 @@ public class DeviceManager | ... | @@ -431,7 +409,7 @@ public class DeviceManager |
431 | checkNotNull(portDescriptions, | 409 | checkNotNull(portDescriptions, |
432 | "Port descriptions list cannot be null"); | 410 | "Port descriptions list cannot be null"); |
433 | checkValidity(); | 411 | checkValidity(); |
434 | - if (!deviceClockProviderService.isTimestampAvailable(deviceId)) { | 412 | + if (!mastershipService.isLocalMaster(deviceId)) { |
435 | // Never been a master for this device | 413 | // Never been a master for this device |
436 | // any update will be ignored. | 414 | // any update will be ignored. |
437 | log.trace("Ignoring {} port updates on standby node. {}", deviceId, portDescriptions); | 415 | log.trace("Ignoring {} port updates on standby node. {}", deviceId, portDescriptions); |
... | @@ -452,7 +430,7 @@ public class DeviceManager | ... | @@ -452,7 +430,7 @@ public class DeviceManager |
452 | checkNotNull(portDescription, PORT_DESCRIPTION_NULL); | 430 | checkNotNull(portDescription, PORT_DESCRIPTION_NULL); |
453 | checkValidity(); | 431 | checkValidity(); |
454 | 432 | ||
455 | - if (!deviceClockProviderService.isTimestampAvailable(deviceId)) { | 433 | + if (!mastershipService.isLocalMaster(deviceId)) { |
456 | // Never been a master for this device | 434 | // Never been a master for this device |
457 | // any update will be ignored. | 435 | // any update will be ignored. |
458 | log.trace("Ignoring {} port update on standby node. {}", deviceId, | 436 | log.trace("Ignoring {} port update on standby node. {}", deviceId, |
... | @@ -664,7 +642,6 @@ public class DeviceManager | ... | @@ -664,7 +642,6 @@ public class DeviceManager |
664 | MastershipTerm term = termService.getMastershipTerm(did); | 642 | MastershipTerm term = termService.getMastershipTerm(did); |
665 | final boolean iHaveControl = term != null && localNodeId.equals(term.master()); | 643 | final boolean iHaveControl = term != null && localNodeId.equals(term.master()); |
666 | if (iHaveControl) { | 644 | if (iHaveControl) { |
667 | - deviceClockProviderService.setMastershipTerm(did, term); | ||
668 | myNextRole = MASTER; | 645 | myNextRole = MASTER; |
669 | } else { | 646 | } else { |
670 | myNextRole = STANDBY; | 647 | myNextRole = STANDBY; | ... | ... |
... | @@ -39,7 +39,6 @@ import org.onosproject.net.PortNumber; | ... | @@ -39,7 +39,6 @@ import org.onosproject.net.PortNumber; |
39 | import org.onosproject.net.device.DefaultDeviceDescription; | 39 | import org.onosproject.net.device.DefaultDeviceDescription; |
40 | import org.onosproject.net.device.DefaultPortDescription; | 40 | import org.onosproject.net.device.DefaultPortDescription; |
41 | import org.onosproject.net.device.DeviceAdminService; | 41 | import org.onosproject.net.device.DeviceAdminService; |
42 | -import org.onosproject.net.device.DeviceClockProviderService; | ||
43 | import org.onosproject.net.device.DeviceDescription; | 42 | import org.onosproject.net.device.DeviceDescription; |
44 | import org.onosproject.net.device.DeviceEvent; | 43 | import org.onosproject.net.device.DeviceEvent; |
45 | import org.onosproject.net.device.DeviceListener; | 44 | import org.onosproject.net.device.DeviceListener; |
... | @@ -106,7 +105,6 @@ public class DeviceManagerTest { | ... | @@ -106,7 +105,6 @@ public class DeviceManagerTest { |
106 | mgr.mastershipService = mastershipManager; | 105 | mgr.mastershipService = mastershipManager; |
107 | mgr.termService = mastershipManager; | 106 | mgr.termService = mastershipManager; |
108 | mgr.clusterService = new TestClusterService(); | 107 | mgr.clusterService = new TestClusterService(); |
109 | - mgr.deviceClockProviderService = new TestClockProviderService(); | ||
110 | mgr.networkConfigService = new TestNetworkConfigService(); | 108 | mgr.networkConfigService = new TestNetworkConfigService(); |
111 | mgr.activate(); | 109 | mgr.activate(); |
112 | 110 | ||
... | @@ -328,22 +326,6 @@ public class DeviceManagerTest { | ... | @@ -328,22 +326,6 @@ public class DeviceManagerTest { |
328 | 326 | ||
329 | } | 327 | } |
330 | 328 | ||
331 | - private final class TestClockProviderService implements | ||
332 | - DeviceClockProviderService { | ||
333 | - | ||
334 | - private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet(); | ||
335 | - | ||
336 | - @Override | ||
337 | - public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { | ||
338 | - registerdBefore.add(deviceId); | ||
339 | - } | ||
340 | - | ||
341 | - @Override | ||
342 | - public boolean isTimestampAvailable(DeviceId deviceId) { | ||
343 | - return registerdBefore.contains(deviceId); | ||
344 | - } | ||
345 | - } | ||
346 | - | ||
347 | private class TestNetworkConfigService extends NetworkConfigServiceAdapter { | 329 | private class TestNetworkConfigService extends NetworkConfigServiceAdapter { |
348 | } | 330 | } |
349 | } | 331 | } | ... | ... |
... | @@ -374,6 +374,10 @@ public class DistributedLeadershipManager implements LeadershipService { | ... | @@ -374,6 +374,10 @@ public class DistributedLeadershipManager implements LeadershipService { |
374 | leader.value(), | 374 | leader.value(), |
375 | leader.version(), | 375 | leader.version(), |
376 | leader.creationTime()); | 376 | leader.creationTime()); |
377 | + // Since reads only go through the local copy of leader board, we ought to update it | ||
378 | + // first before returning from this method. | ||
379 | + // This is to ensure a subsequent read will not read a stale value. | ||
380 | + onLeadershipEvent(new LeadershipEvent(LeadershipEvent.Type.LEADER_ELECTED, newLeadership)); | ||
377 | return newLeadership; | 381 | return newLeadership; |
378 | } | 382 | } |
379 | } catch (Exception e) { | 383 | } catch (Exception e) { | ... | ... |
... | @@ -17,17 +17,19 @@ package org.onosproject.store.device.impl; | ... | @@ -17,17 +17,19 @@ package org.onosproject.store.device.impl; |
17 | 17 | ||
18 | import static org.slf4j.LoggerFactory.getLogger; | 18 | import static org.slf4j.LoggerFactory.getLogger; |
19 | 19 | ||
20 | -import java.util.concurrent.ConcurrentHashMap; | ||
21 | -import java.util.concurrent.ConcurrentMap; | ||
22 | import java.util.concurrent.atomic.AtomicLong; | 20 | import java.util.concurrent.atomic.AtomicLong; |
23 | 21 | ||
24 | import org.apache.felix.scr.annotations.Activate; | 22 | import org.apache.felix.scr.annotations.Activate; |
25 | import org.apache.felix.scr.annotations.Component; | 23 | import org.apache.felix.scr.annotations.Component; |
26 | import org.apache.felix.scr.annotations.Deactivate; | 24 | import org.apache.felix.scr.annotations.Deactivate; |
25 | +import org.apache.felix.scr.annotations.Reference; | ||
26 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
27 | import org.apache.felix.scr.annotations.Service; | 27 | import org.apache.felix.scr.annotations.Service; |
28 | +import org.onosproject.cluster.ClusterService; | ||
29 | +import org.onosproject.cluster.NodeId; | ||
28 | import org.onosproject.mastership.MastershipTerm; | 30 | import org.onosproject.mastership.MastershipTerm; |
31 | +import org.onosproject.mastership.MastershipTermService; | ||
29 | import org.onosproject.net.DeviceId; | 32 | import org.onosproject.net.DeviceId; |
30 | -import org.onosproject.net.device.DeviceClockProviderService; | ||
31 | import org.onosproject.net.device.DeviceClockService; | 33 | import org.onosproject.net.device.DeviceClockService; |
32 | import org.onosproject.store.Timestamp; | 34 | import org.onosproject.store.Timestamp; |
33 | import org.onosproject.store.impl.MastershipBasedTimestamp; | 35 | import org.onosproject.store.impl.MastershipBasedTimestamp; |
... | @@ -38,16 +40,23 @@ import org.slf4j.Logger; | ... | @@ -38,16 +40,23 @@ import org.slf4j.Logger; |
38 | */ | 40 | */ |
39 | @Component(immediate = true) | 41 | @Component(immediate = true) |
40 | @Service | 42 | @Service |
41 | -public class DeviceClockManager implements DeviceClockService, DeviceClockProviderService { | 43 | +public class DeviceClockManager implements DeviceClockService { |
42 | 44 | ||
43 | private final Logger log = getLogger(getClass()); | 45 | private final Logger log = getLogger(getClass()); |
44 | 46 | ||
45 | - // TODO: Implement per device ticker that is reset to 0 at the beginning of a new term. | 47 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
48 | + protected MastershipTermService mastershipTermService; | ||
49 | + | ||
50 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
51 | + protected ClusterService clusterService; | ||
52 | + | ||
53 | + protected NodeId localNodeId; | ||
54 | + | ||
46 | private final AtomicLong ticker = new AtomicLong(0); | 55 | private final AtomicLong ticker = new AtomicLong(0); |
47 | - private ConcurrentMap<DeviceId, MastershipTerm> deviceMastershipTerms = new ConcurrentHashMap<>(); | ||
48 | 56 | ||
49 | @Activate | 57 | @Activate |
50 | public void activate() { | 58 | public void activate() { |
59 | + localNodeId = clusterService.getLocalNode().id(); | ||
51 | log.info("Started"); | 60 | log.info("Started"); |
52 | } | 61 | } |
53 | 62 | ||
... | @@ -58,23 +67,16 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid | ... | @@ -58,23 +67,16 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid |
58 | 67 | ||
59 | @Override | 68 | @Override |
60 | public Timestamp getTimestamp(DeviceId deviceId) { | 69 | public Timestamp getTimestamp(DeviceId deviceId) { |
61 | - MastershipTerm term = deviceMastershipTerms.get(deviceId); | 70 | + MastershipTerm term = mastershipTermService.getMastershipTerm(deviceId); |
62 | - log.trace("term info for {} is: {}", deviceId, term); | 71 | + if (term == null || !localNodeId.equals(term.master())) { |
63 | - | ||
64 | - if (term == null) { | ||
65 | throw new IllegalStateException("Requesting timestamp for " + deviceId + " without mastership"); | 72 | throw new IllegalStateException("Requesting timestamp for " + deviceId + " without mastership"); |
66 | } | 73 | } |
67 | return new MastershipBasedTimestamp(term.termNumber(), ticker.incrementAndGet()); | 74 | return new MastershipBasedTimestamp(term.termNumber(), ticker.incrementAndGet()); |
68 | } | 75 | } |
69 | 76 | ||
70 | @Override | 77 | @Override |
71 | - public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { | ||
72 | - log.debug("adding term info {} {}", deviceId, term.master()); | ||
73 | - deviceMastershipTerms.put(deviceId, term); | ||
74 | - } | ||
75 | - | ||
76 | - @Override | ||
77 | public boolean isTimestampAvailable(DeviceId deviceId) { | 78 | public boolean isTimestampAvailable(DeviceId deviceId) { |
78 | - return deviceMastershipTerms.containsKey(deviceId); | 79 | + MastershipTerm term = mastershipTermService.getMastershipTerm(deviceId); |
80 | + return term != null && localNodeId.equals(term.master()); | ||
79 | } | 81 | } |
80 | } | 82 | } | ... | ... |
... | @@ -32,7 +32,6 @@ import org.onosproject.cluster.ControllerNode; | ... | @@ -32,7 +32,6 @@ import org.onosproject.cluster.ControllerNode; |
32 | import org.onosproject.cluster.DefaultControllerNode; | 32 | import org.onosproject.cluster.DefaultControllerNode; |
33 | import org.onosproject.cluster.NodeId; | 33 | import org.onosproject.cluster.NodeId; |
34 | import org.onosproject.mastership.MastershipServiceAdapter; | 34 | import org.onosproject.mastership.MastershipServiceAdapter; |
35 | -import org.onosproject.mastership.MastershipTerm; | ||
36 | import org.onosproject.net.Annotations; | 35 | import org.onosproject.net.Annotations; |
37 | import org.onosproject.net.DefaultAnnotations; | 36 | import org.onosproject.net.DefaultAnnotations; |
38 | import org.onosproject.net.Device; | 37 | import org.onosproject.net.Device; |
... | @@ -44,18 +43,21 @@ import org.onosproject.net.SparseAnnotations; | ... | @@ -44,18 +43,21 @@ import org.onosproject.net.SparseAnnotations; |
44 | import org.onosproject.net.device.DefaultDeviceDescription; | 43 | import org.onosproject.net.device.DefaultDeviceDescription; |
45 | import org.onosproject.net.device.DefaultPortDescription; | 44 | import org.onosproject.net.device.DefaultPortDescription; |
46 | import org.onosproject.net.device.DeviceClockService; | 45 | import org.onosproject.net.device.DeviceClockService; |
46 | +import org.onosproject.net.device.DeviceClockServiceAdapter; | ||
47 | import org.onosproject.net.device.DeviceDescription; | 47 | import org.onosproject.net.device.DeviceDescription; |
48 | import org.onosproject.net.device.DeviceEvent; | 48 | import org.onosproject.net.device.DeviceEvent; |
49 | import org.onosproject.net.device.DeviceStore; | 49 | import org.onosproject.net.device.DeviceStore; |
50 | import org.onosproject.net.device.DeviceStoreDelegate; | 50 | import org.onosproject.net.device.DeviceStoreDelegate; |
51 | import org.onosproject.net.device.PortDescription; | 51 | import org.onosproject.net.device.PortDescription; |
52 | import org.onosproject.net.provider.ProviderId; | 52 | import org.onosproject.net.provider.ProviderId; |
53 | +import org.onosproject.store.Timestamp; | ||
53 | import org.onosproject.store.cluster.StaticClusterService; | 54 | import org.onosproject.store.cluster.StaticClusterService; |
54 | import org.onosproject.store.cluster.messaging.ClusterCommunicationService; | 55 | import org.onosproject.store.cluster.messaging.ClusterCommunicationService; |
55 | import org.onosproject.store.cluster.messaging.ClusterMessage; | 56 | import org.onosproject.store.cluster.messaging.ClusterMessage; |
56 | import org.onosproject.store.cluster.messaging.ClusterMessageHandler; | 57 | import org.onosproject.store.cluster.messaging.ClusterMessageHandler; |
57 | import org.onosproject.store.cluster.messaging.MessageSubject; | 58 | import org.onosproject.store.cluster.messaging.MessageSubject; |
58 | import org.onosproject.store.consistent.impl.DatabaseManager; | 59 | import org.onosproject.store.consistent.impl.DatabaseManager; |
60 | +import org.onosproject.store.impl.MastershipBasedTimestamp; | ||
59 | 61 | ||
60 | import java.io.IOException; | 62 | import java.io.IOException; |
61 | import java.util.Arrays; | 63 | import java.util.Arrays; |
... | @@ -68,6 +70,7 @@ import java.util.concurrent.CompletableFuture; | ... | @@ -68,6 +70,7 @@ import java.util.concurrent.CompletableFuture; |
68 | import java.util.concurrent.CountDownLatch; | 70 | import java.util.concurrent.CountDownLatch; |
69 | import java.util.concurrent.ExecutorService; | 71 | import java.util.concurrent.ExecutorService; |
70 | import java.util.concurrent.TimeUnit; | 72 | import java.util.concurrent.TimeUnit; |
73 | +import java.util.concurrent.atomic.AtomicLong; | ||
71 | import java.util.function.Function; | 74 | import java.util.function.Function; |
72 | 75 | ||
73 | import static java.util.Arrays.asList; | 76 | import static java.util.Arrays.asList; |
... | @@ -134,8 +137,7 @@ public class GossipDeviceStoreTest { | ... | @@ -134,8 +137,7 @@ public class GossipDeviceStoreTest { |
134 | private GossipDeviceStore gossipDeviceStore; | 137 | private GossipDeviceStore gossipDeviceStore; |
135 | private DeviceStore deviceStore; | 138 | private DeviceStore deviceStore; |
136 | 139 | ||
137 | - private DeviceClockManager deviceClockManager; | 140 | + private DeviceClockService deviceClockService = new TestDeviceClockService(); |
138 | - private DeviceClockService deviceClockService; | ||
139 | private ClusterCommunicationService clusterCommunicator; | 141 | private ClusterCommunicationService clusterCommunicator; |
140 | 142 | ||
141 | @BeforeClass | 143 | @BeforeClass |
... | @@ -149,13 +151,6 @@ public class GossipDeviceStoreTest { | ... | @@ -149,13 +151,6 @@ public class GossipDeviceStoreTest { |
149 | 151 | ||
150 | @Before | 152 | @Before |
151 | public void setUp() throws Exception { | 153 | public void setUp() throws Exception { |
152 | - deviceClockManager = new DeviceClockManager(); | ||
153 | - deviceClockManager.activate(); | ||
154 | - deviceClockService = deviceClockManager; | ||
155 | - | ||
156 | - deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(NID1, 1)); | ||
157 | - deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(NID1, 2)); | ||
158 | - | ||
159 | clusterCommunicator = createNiceMock(ClusterCommunicationService.class); | 154 | clusterCommunicator = createNiceMock(ClusterCommunicationService.class); |
160 | clusterCommunicator.addSubscriber(anyObject(MessageSubject.class), | 155 | clusterCommunicator.addSubscriber(anyObject(MessageSubject.class), |
161 | anyObject(ClusterMessageHandler.class), anyObject(ExecutorService.class)); | 156 | anyObject(ClusterMessageHandler.class), anyObject(ExecutorService.class)); |
... | @@ -169,6 +164,7 @@ public class GossipDeviceStoreTest { | ... | @@ -169,6 +164,7 @@ public class GossipDeviceStoreTest { |
169 | TestDatabaseManager testDatabaseManager = new TestDatabaseManager(); | 164 | TestDatabaseManager testDatabaseManager = new TestDatabaseManager(); |
170 | testDatabaseManager.init(clusterService, clusterCommunicator); | 165 | testDatabaseManager.init(clusterService, clusterCommunicator); |
171 | testGossipDeviceStore.storageService = testDatabaseManager; | 166 | testGossipDeviceStore.storageService = testDatabaseManager; |
167 | + testGossipDeviceStore.deviceClockService = deviceClockService; | ||
172 | 168 | ||
173 | gossipDeviceStore = testGossipDeviceStore; | 169 | gossipDeviceStore = testGossipDeviceStore; |
174 | gossipDeviceStore.activate(); | 170 | gossipDeviceStore.activate(); |
... | @@ -180,7 +176,6 @@ public class GossipDeviceStoreTest { | ... | @@ -180,7 +176,6 @@ public class GossipDeviceStoreTest { |
180 | @After | 176 | @After |
181 | public void tearDown() throws Exception { | 177 | public void tearDown() throws Exception { |
182 | gossipDeviceStore.deactivate(); | 178 | gossipDeviceStore.deactivate(); |
183 | - deviceClockManager.deactivate(); | ||
184 | } | 179 | } |
185 | 180 | ||
186 | private void putDevice(DeviceId deviceId, String swVersion, | 181 | private void putDevice(DeviceId deviceId, String swVersion, |
... | @@ -891,6 +886,27 @@ public class GossipDeviceStoreTest { | ... | @@ -891,6 +886,27 @@ public class GossipDeviceStoreTest { |
891 | } | 886 | } |
892 | } | 887 | } |
893 | 888 | ||
889 | + private final class TestDeviceClockService extends DeviceClockServiceAdapter { | ||
890 | + | ||
891 | + private final AtomicLong ticker = new AtomicLong(); | ||
892 | + | ||
893 | + @Override | ||
894 | + public Timestamp getTimestamp(DeviceId deviceId) { | ||
895 | + if (DID1.equals(deviceId)) { | ||
896 | + return new MastershipBasedTimestamp(1, ticker.getAndIncrement()); | ||
897 | + } else if (DID2.equals(deviceId)) { | ||
898 | + return new MastershipBasedTimestamp(2, ticker.getAndIncrement()); | ||
899 | + } else { | ||
900 | + throw new IllegalStateException(); | ||
901 | + } | ||
902 | + } | ||
903 | + | ||
904 | + @Override | ||
905 | + public boolean isTimestampAvailable(DeviceId deviceId) { | ||
906 | + return DID1.equals(deviceId) || DID2.equals(deviceId); | ||
907 | + } | ||
908 | + } | ||
909 | + | ||
894 | private class TestDatabaseManager extends DatabaseManager { | 910 | private class TestDatabaseManager extends DatabaseManager { |
895 | void init(ClusterService clusterService, | 911 | void init(ClusterService clusterService, |
896 | ClusterCommunicationService clusterCommunicator) { | 912 | ClusterCommunicationService clusterCommunicator) { | ... | ... |
... | @@ -29,7 +29,6 @@ import org.onosproject.cluster.ControllerNode; | ... | @@ -29,7 +29,6 @@ import org.onosproject.cluster.ControllerNode; |
29 | import org.onosproject.cluster.DefaultControllerNode; | 29 | import org.onosproject.cluster.DefaultControllerNode; |
30 | import org.onosproject.cluster.NodeId; | 30 | import org.onosproject.cluster.NodeId; |
31 | import org.onosproject.mastership.MastershipServiceAdapter; | 31 | import org.onosproject.mastership.MastershipServiceAdapter; |
32 | -import org.onosproject.mastership.MastershipTerm; | ||
33 | import org.onosproject.net.ConnectPoint; | 32 | import org.onosproject.net.ConnectPoint; |
34 | import org.onosproject.net.DefaultAnnotations; | 33 | import org.onosproject.net.DefaultAnnotations; |
35 | import org.onosproject.net.DeviceId; | 34 | import org.onosproject.net.DeviceId; |
... | @@ -39,17 +38,19 @@ import org.onosproject.net.LinkKey; | ... | @@ -39,17 +38,19 @@ import org.onosproject.net.LinkKey; |
39 | import org.onosproject.net.PortNumber; | 38 | import org.onosproject.net.PortNumber; |
40 | import org.onosproject.net.SparseAnnotations; | 39 | import org.onosproject.net.SparseAnnotations; |
41 | import org.onosproject.net.device.DeviceClockService; | 40 | import org.onosproject.net.device.DeviceClockService; |
41 | +import org.onosproject.net.device.DeviceClockServiceAdapter; | ||
42 | import org.onosproject.net.link.DefaultLinkDescription; | 42 | import org.onosproject.net.link.DefaultLinkDescription; |
43 | import org.onosproject.net.link.LinkDescription; | 43 | import org.onosproject.net.link.LinkDescription; |
44 | import org.onosproject.net.link.LinkEvent; | 44 | import org.onosproject.net.link.LinkEvent; |
45 | import org.onosproject.net.link.LinkStore; | 45 | import org.onosproject.net.link.LinkStore; |
46 | import org.onosproject.net.link.LinkStoreDelegate; | 46 | import org.onosproject.net.link.LinkStoreDelegate; |
47 | import org.onosproject.net.provider.ProviderId; | 47 | import org.onosproject.net.provider.ProviderId; |
48 | +import org.onosproject.store.Timestamp; | ||
48 | import org.onosproject.store.cluster.StaticClusterService; | 49 | import org.onosproject.store.cluster.StaticClusterService; |
49 | import org.onosproject.store.cluster.messaging.ClusterCommunicationService; | 50 | import org.onosproject.store.cluster.messaging.ClusterCommunicationService; |
50 | import org.onosproject.store.cluster.messaging.ClusterMessageHandler; | 51 | import org.onosproject.store.cluster.messaging.ClusterMessageHandler; |
51 | import org.onosproject.store.cluster.messaging.MessageSubject; | 52 | import org.onosproject.store.cluster.messaging.MessageSubject; |
52 | -import org.onosproject.store.device.impl.DeviceClockManager; | 53 | +import org.onosproject.store.impl.MastershipBasedTimestamp; |
53 | 54 | ||
54 | import java.util.HashMap; | 55 | import java.util.HashMap; |
55 | import java.util.Map; | 56 | import java.util.Map; |
... | @@ -57,6 +58,7 @@ import java.util.Set; | ... | @@ -57,6 +58,7 @@ import java.util.Set; |
57 | import java.util.concurrent.CountDownLatch; | 58 | import java.util.concurrent.CountDownLatch; |
58 | import java.util.concurrent.ExecutorService; | 59 | import java.util.concurrent.ExecutorService; |
59 | import java.util.concurrent.TimeUnit; | 60 | import java.util.concurrent.TimeUnit; |
61 | +import java.util.concurrent.atomic.AtomicLong; | ||
60 | import java.util.function.Function; | 62 | import java.util.function.Function; |
61 | 63 | ||
62 | import static org.easymock.EasyMock.*; | 64 | import static org.easymock.EasyMock.*; |
... | @@ -115,7 +117,7 @@ public class GossipLinkStoreTest { | ... | @@ -115,7 +117,7 @@ public class GossipLinkStoreTest { |
115 | private GossipLinkStore linkStoreImpl; | 117 | private GossipLinkStore linkStoreImpl; |
116 | private LinkStore linkStore; | 118 | private LinkStore linkStore; |
117 | 119 | ||
118 | - private DeviceClockManager deviceClockManager; | 120 | + private final AtomicLong ticker = new AtomicLong(); |
119 | private DeviceClockService deviceClockService; | 121 | private DeviceClockService deviceClockService; |
120 | private ClusterCommunicationService clusterCommunicator; | 122 | private ClusterCommunicationService clusterCommunicator; |
121 | 123 | ||
... | @@ -129,14 +131,6 @@ public class GossipLinkStoreTest { | ... | @@ -129,14 +131,6 @@ public class GossipLinkStoreTest { |
129 | 131 | ||
130 | @Before | 132 | @Before |
131 | public void setUp() throws Exception { | 133 | public void setUp() throws Exception { |
132 | - deviceClockManager = new DeviceClockManager(); | ||
133 | - deviceClockManager.activate(); | ||
134 | - deviceClockService = deviceClockManager; | ||
135 | - | ||
136 | - // set initial terms | ||
137 | - deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(NID1, 1)); | ||
138 | - deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(NID1, 2)); | ||
139 | - | ||
140 | // TODO mock clusterCommunicator | 134 | // TODO mock clusterCommunicator |
141 | clusterCommunicator = createNiceMock(ClusterCommunicationService.class); | 135 | clusterCommunicator = createNiceMock(ClusterCommunicationService.class); |
142 | clusterCommunicator.addSubscriber(anyObject(MessageSubject.class), | 136 | clusterCommunicator.addSubscriber(anyObject(MessageSubject.class), |
... | @@ -149,6 +143,7 @@ public class GossipLinkStoreTest { | ... | @@ -149,6 +143,7 @@ public class GossipLinkStoreTest { |
149 | linkStoreImpl.deviceClockService = deviceClockService; | 143 | linkStoreImpl.deviceClockService = deviceClockService; |
150 | linkStoreImpl.clusterCommunicator = clusterCommunicator; | 144 | linkStoreImpl.clusterCommunicator = clusterCommunicator; |
151 | linkStoreImpl.clusterService = new TestClusterService(); | 145 | linkStoreImpl.clusterService = new TestClusterService(); |
146 | + linkStoreImpl.deviceClockService = new TestDeviceClockService(); | ||
152 | linkStoreImpl.mastershipService = new TestMastershipService(); | 147 | linkStoreImpl.mastershipService = new TestMastershipService(); |
153 | linkStoreImpl.activate(); | 148 | linkStoreImpl.activate(); |
154 | linkStore = linkStoreImpl; | 149 | linkStore = linkStoreImpl; |
... | @@ -607,6 +602,27 @@ public class GossipLinkStoreTest { | ... | @@ -607,6 +602,27 @@ public class GossipLinkStoreTest { |
607 | } | 602 | } |
608 | } | 603 | } |
609 | 604 | ||
605 | + private final class TestDeviceClockService extends DeviceClockServiceAdapter { | ||
606 | + | ||
607 | + private final AtomicLong ticker = new AtomicLong(); | ||
608 | + | ||
609 | + @Override | ||
610 | + public Timestamp getTimestamp(DeviceId deviceId) { | ||
611 | + if (DID1.equals(deviceId)) { | ||
612 | + return new MastershipBasedTimestamp(1, ticker.getAndIncrement()); | ||
613 | + } else if (DID2.equals(deviceId)) { | ||
614 | + return new MastershipBasedTimestamp(2, ticker.getAndIncrement()); | ||
615 | + } else { | ||
616 | + throw new IllegalStateException(); | ||
617 | + } | ||
618 | + } | ||
619 | + | ||
620 | + @Override | ||
621 | + public boolean isTimestampAvailable(DeviceId deviceId) { | ||
622 | + return DID1.equals(deviceId) || DID2.equals(deviceId); | ||
623 | + } | ||
624 | + } | ||
625 | + | ||
610 | private final class TestMastershipService extends MastershipServiceAdapter { | 626 | private final class TestMastershipService extends MastershipServiceAdapter { |
611 | @Override | 627 | @Override |
612 | public NodeId getMasterFor(DeviceId deviceId) { | 628 | public NodeId getMasterFor(DeviceId deviceId) { | ... | ... |
... | @@ -15,6 +15,21 @@ | ... | @@ -15,6 +15,21 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.provider.lldp.impl; | 16 | package org.onosproject.provider.lldp.impl; |
17 | 17 | ||
18 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | +import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||
20 | +import static org.onosproject.net.PortNumber.portNumber; | ||
21 | +import static org.onosproject.net.flow.DefaultTrafficTreatment.builder; | ||
22 | +import static org.slf4j.LoggerFactory.getLogger; | ||
23 | + | ||
24 | +import java.nio.ByteBuffer; | ||
25 | +import java.util.Collections; | ||
26 | +import java.util.HashMap; | ||
27 | +import java.util.HashSet; | ||
28 | +import java.util.Iterator; | ||
29 | +import java.util.Map; | ||
30 | +import java.util.Set; | ||
31 | +import java.util.concurrent.atomic.AtomicInteger; | ||
32 | + | ||
18 | import org.jboss.netty.util.Timeout; | 33 | import org.jboss.netty.util.Timeout; |
19 | import org.jboss.netty.util.TimerTask; | 34 | import org.jboss.netty.util.TimerTask; |
20 | import org.onlab.packet.Ethernet; | 35 | import org.onlab.packet.Ethernet; |
... | @@ -36,22 +51,6 @@ import org.onosproject.net.packet.PacketContext; | ... | @@ -36,22 +51,6 @@ import org.onosproject.net.packet.PacketContext; |
36 | import org.onosproject.net.packet.PacketService; | 51 | import org.onosproject.net.packet.PacketService; |
37 | import org.slf4j.Logger; | 52 | import org.slf4j.Logger; |
38 | 53 | ||
39 | -import java.nio.ByteBuffer; | ||
40 | -import java.util.Collections; | ||
41 | -import java.util.HashMap; | ||
42 | -import java.util.HashSet; | ||
43 | -import java.util.Iterator; | ||
44 | -import java.util.Map; | ||
45 | -import java.util.Set; | ||
46 | -import java.util.concurrent.atomic.AtomicInteger; | ||
47 | - | ||
48 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
49 | -import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||
50 | -import static org.onosproject.net.MastershipRole.MASTER; | ||
51 | -import static org.onosproject.net.PortNumber.portNumber; | ||
52 | -import static org.onosproject.net.flow.DefaultTrafficTreatment.builder; | ||
53 | -import static org.slf4j.LoggerFactory.getLogger; | ||
54 | - | ||
55 | // TODO: add 'fast discovery' mode: drop LLDPs in destination switch but listen for flow_removed messages | 54 | // TODO: add 'fast discovery' mode: drop LLDPs in destination switch but listen for flow_removed messages |
56 | 55 | ||
57 | /** | 56 | /** |
... | @@ -149,7 +148,7 @@ public class LinkDiscovery implements TimerTask { | ... | @@ -149,7 +148,7 @@ public class LinkDiscovery implements TimerTask { |
149 | } | 148 | } |
150 | } | 149 | } |
151 | 150 | ||
152 | - boolean isMaster = mastershipService.getLocalRole(device.id()) == MASTER; | 151 | + boolean isMaster = mastershipService.isLocalMaster(device.id()); |
153 | if (newPort && isMaster) { | 152 | if (newPort && isMaster) { |
154 | this.log.debug("Sending init probe to port {}@{}", | 153 | this.log.debug("Sending init probe to port {}@{}", |
155 | port.number().toLong(), device.id()); | 154 | port.number().toLong(), device.id()); |
... | @@ -258,8 +257,7 @@ public class LinkDiscovery implements TimerTask { | ... | @@ -258,8 +257,7 @@ public class LinkDiscovery implements TimerTask { |
258 | if (isStopped()) { | 257 | if (isStopped()) { |
259 | return; | 258 | return; |
260 | } | 259 | } |
261 | - boolean isMaster = mastershipService.getLocalRole(device.id()) == MASTER; | 260 | + if (!mastershipService.isLocalMaster(device.id())) { |
262 | - if (!isMaster) { | ||
263 | if (!isStopped()) { | 261 | if (!isStopped()) { |
264 | // reschedule timer | 262 | // reschedule timer |
265 | timeout = Timer.getTimer().newTimeout(this, this.probeRate, MILLISECONDS); | 263 | timeout = Timer.getTimer().newTimeout(this, this.probeRate, MILLISECONDS); | ... | ... |
-
Please register or login to post a comment