Madan Jampani

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
...@@ -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 *
......
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 +}
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);
......