Madan Jampani
Committed by Gerrit Code Review

Code clean up: Removed unused code. Fixed comments. Renamed some files.

Change-Id: I78ca1f4a973c3b5356f749680ebe0f4ccde01279
Showing 37 changed files with 78 additions and 2765 deletions
1 -/*
2 - * Copyright 2015-present 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.cfg;
17 -
18 -import org.apache.felix.scr.annotations.Activate;
19 -import org.apache.felix.scr.annotations.Component;
20 -import org.apache.felix.scr.annotations.Deactivate;
21 -import org.apache.felix.scr.annotations.Reference;
22 -import org.apache.felix.scr.annotations.ReferenceCardinality;
23 -import org.apache.felix.scr.annotations.Service;
24 -import org.onlab.util.KryoNamespace;
25 -import org.onosproject.cfg.ComponentConfigEvent;
26 -import org.onosproject.cfg.ComponentConfigStore;
27 -import org.onosproject.cfg.ComponentConfigStoreDelegate;
28 -import org.onosproject.store.AbstractStore;
29 -import org.onosproject.store.serializers.KryoNamespaces;
30 -import org.onosproject.store.service.EventuallyConsistentMap;
31 -import org.onosproject.store.service.EventuallyConsistentMapEvent;
32 -import org.onosproject.store.service.EventuallyConsistentMapListener;
33 -import org.onosproject.store.service.LogicalClockService;
34 -import org.onosproject.store.service.StorageService;
35 -import org.slf4j.Logger;
36 -
37 -import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_SET;
38 -import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_UNSET;
39 -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
40 -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
41 -import static org.slf4j.LoggerFactory.getLogger;
42 -
43 -/**
44 - * Manages inventory of component configurations in a distributed data store
45 - * that uses optimistic replication and gossip based anti-entropy techniques.
46 - */
47 -@Component(immediate = true, enabled = false)
48 -@Service
49 -public class GossipComponentConfigStore
50 - extends AbstractStore<ComponentConfigEvent, ComponentConfigStoreDelegate>
51 - implements ComponentConfigStore {
52 -
53 - private static final String SEP = "#";
54 -
55 - private final Logger log = getLogger(getClass());
56 -
57 - private EventuallyConsistentMap<String, String> properties;
58 -
59 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 - protected StorageService storageService;
61 -
62 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 - protected LogicalClockService clockService;
64 -
65 - @Activate
66 - public void activate() {
67 - KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
68 - .register(KryoNamespaces.API);
69 -
70 - properties = storageService.<String, String>eventuallyConsistentMapBuilder()
71 - .withName("cfg")
72 - .withSerializer(serializer)
73 - .withTimestampProvider((k, v) -> clockService.getTimestamp())
74 - .build();
75 -
76 - properties.addListener(new InternalPropertiesListener());
77 - log.info("Started");
78 - }
79 -
80 - @Deactivate
81 - public void deactivate() {
82 - properties.destroy();
83 - log.info("Stopped");
84 - }
85 -
86 - @Override
87 - public void setProperty(String componentName, String name, String value) {
88 - properties.put(key(componentName, name), value);
89 -
90 - }
91 -
92 - @Override
93 - public void unsetProperty(String componentName, String name) {
94 - properties.remove(key(componentName, name));
95 - }
96 -
97 - /**
98 - * Listener to component configuration properties distributed map changes.
99 - */
100 - private final class InternalPropertiesListener
101 - implements EventuallyConsistentMapListener<String, String> {
102 -
103 - @Override
104 - public void event(EventuallyConsistentMapEvent<String, String> event) {
105 - String[] keys = event.key().split(SEP);
106 - String value = event.value();
107 - if (event.type() == PUT) {
108 - delegate.notify(new ComponentConfigEvent(PROPERTY_SET, keys[0], keys[1], value));
109 - } else if (event.type() == REMOVE) {
110 - delegate.notify(new ComponentConfigEvent(PROPERTY_UNSET, keys[0], keys[1], null));
111 - }
112 - }
113 - }
114 -
115 - // Generates a key from component name and property name.
116 - private String key(String componentName, String name) {
117 - return componentName + SEP + name;
118 - }
119 -
120 -}
1 -/*
2 - * Copyright 2014-present 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.cluster.impl;
17 -
18 -import org.onosproject.store.cluster.messaging.MessageSubject;
19 -
20 -//Not used right now
21 -public final class ClusterManagementMessageSubjects {
22 - // avoid instantiation
23 - private ClusterManagementMessageSubjects() {}
24 -
25 - public static final MessageSubject CLUSTER_MEMBERSHIP_EVENT = new MessageSubject("CLUSTER_MEMBERSHIP_EVENT");
26 -}
1 -/*
2 - * Copyright 2014-present 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.cluster.impl;
17 -
18 -import org.onosproject.cluster.ControllerNode;
19 -
20 -//Not used right now
21 -/**
22 - * Contains information that will be published when a cluster membership event occurs.
23 - */
24 -public class ClusterMembershipEvent {
25 -
26 - private final ClusterMembershipEventType type;
27 - private final ControllerNode node;
28 -
29 - public ClusterMembershipEvent(ClusterMembershipEventType type, ControllerNode node) {
30 - this.type = type;
31 - this.node = node;
32 - }
33 -
34 - public ClusterMembershipEventType type() {
35 - return type;
36 - }
37 -
38 - public ControllerNode node() {
39 - return node;
40 - }
41 -}
1 -/*
2 - * Copyright 2014-present 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.cluster.impl;
17 -
18 -//Not used right now
19 -public enum ClusterMembershipEventType {
20 - NEW_MEMBER,
21 - LEAVING_MEMBER,
22 - UNREACHABLE_MEMBER,
23 - HEART_BEAT,
24 -}
1 -/*
2 - * Copyright 2014-present 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.cluster.impl;
17 -
18 -import org.onosproject.cluster.DefaultControllerNode;
19 -import org.onosproject.cluster.NodeId;
20 -import org.onlab.packet.IpAddress;
21 -
22 -// Not used right now
23 -/**
24 - * Simple back interface through which connection manager can interact with
25 - * the cluster store.
26 - */
27 -public interface ClusterNodesDelegate {
28 -
29 - /**
30 - * Notifies about cluster node coming online.
31 - *
32 - * @param nodeId newly detected cluster node id
33 - * @param ip node IP listen address
34 - * @param tcpPort node TCP listen port
35 - * @return the controller node
36 - */
37 - DefaultControllerNode nodeDetected(NodeId nodeId, IpAddress ip,
38 - int tcpPort);
39 -
40 - /**
41 - * Notifies about cluster node going offline.
42 - *
43 - * @param nodeId identifier of the cluster node that vanished
44 - */
45 - void nodeVanished(NodeId nodeId);
46 -
47 - /**
48 - * Notifies about remote request to remove node from cluster.
49 - *
50 - * @param nodeId identifier of the cluster node that was removed
51 - */
52 - void nodeRemoved(NodeId nodeId);
53 -
54 -}
...@@ -17,10 +17,9 @@ package org.onosproject.store.cluster.impl; ...@@ -17,10 +17,9 @@ package org.onosproject.store.cluster.impl;
17 17
18 import static org.slf4j.LoggerFactory.getLogger; 18 import static org.slf4j.LoggerFactory.getLogger;
19 19
20 -import java.util.ArrayList;
21 -import java.util.List;
22 import java.util.Map; 20 import java.util.Map;
23 -import java.util.stream.Collectors; 21 +import java.util.Objects;
22 +import java.util.function.Consumer;
24 23
25 import org.apache.felix.scr.annotations.Activate; 24 import org.apache.felix.scr.annotations.Activate;
26 import org.apache.felix.scr.annotations.Component; 25 import org.apache.felix.scr.annotations.Component;
...@@ -29,39 +28,28 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -29,39 +28,28 @@ import org.apache.felix.scr.annotations.Reference;
29 import org.apache.felix.scr.annotations.ReferenceCardinality; 28 import org.apache.felix.scr.annotations.ReferenceCardinality;
30 import org.apache.felix.scr.annotations.Service; 29 import org.apache.felix.scr.annotations.Service;
31 import org.onosproject.cluster.ClusterService; 30 import org.onosproject.cluster.ClusterService;
32 -import org.onosproject.cluster.Leader;
33 import org.onosproject.cluster.Leadership; 31 import org.onosproject.cluster.Leadership;
34 import org.onosproject.cluster.LeadershipEvent; 32 import org.onosproject.cluster.LeadershipEvent;
35 import org.onosproject.cluster.LeadershipStore; 33 import org.onosproject.cluster.LeadershipStore;
36 import org.onosproject.cluster.LeadershipStoreDelegate; 34 import org.onosproject.cluster.LeadershipStoreDelegate;
37 import org.onosproject.cluster.NodeId; 35 import org.onosproject.cluster.NodeId;
36 +import org.onosproject.event.Change;
38 import org.onosproject.store.AbstractStore; 37 import org.onosproject.store.AbstractStore;
39 -import org.onosproject.store.serializers.KryoNamespaces; 38 +import org.onosproject.store.service.LeaderElector;
40 -import org.onosproject.store.service.ConsistentMap;
41 -import org.onosproject.store.service.MapEventListener;
42 -import org.onosproject.store.service.Serializer;
43 import org.onosproject.store.service.StorageService; 39 import org.onosproject.store.service.StorageService;
44 -import org.onosproject.store.service.Versioned;
45 import org.slf4j.Logger; 40 import org.slf4j.Logger;
46 41
47 -import com.google.common.base.MoreObjects;
48 -import com.google.common.base.Objects;
49 -import com.google.common.collect.ImmutableList;
50 -import com.google.common.collect.ImmutableMap;
51 -import com.google.common.collect.ImmutableSet;
52 -import com.google.common.collect.Maps;
53 -import com.google.common.collect.Sets;
54 -
55 /** 42 /**
56 - * Implementation of {@code LeadershipStore} backed by {@link ConsistentMap}. 43 + * Implementation of {@code LeadershipStore} that makes use of a {@link LeaderElector}
44 + * primitive.
57 */ 45 */
58 @Service 46 @Service
59 -@Component(immediate = true, enabled = false) 47 +@Component(immediate = true, enabled = true)
60 public class DistributedLeadershipStore 48 public class DistributedLeadershipStore
61 extends AbstractStore<LeadershipEvent, LeadershipStoreDelegate> 49 extends AbstractStore<LeadershipEvent, LeadershipStoreDelegate>
62 implements LeadershipStore { 50 implements LeadershipStore {
63 51
64 - private static final Logger log = getLogger(DistributedLeadershipStore.class); 52 + private final Logger log = getLogger(getClass());
65 53
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected ClusterService clusterService; 55 protected ClusterService clusterService;
...@@ -69,20 +57,15 @@ public class DistributedLeadershipStore ...@@ -69,20 +57,15 @@ public class DistributedLeadershipStore
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected StorageService storageService; 58 protected StorageService storageService;
71 59
72 - protected NodeId localNodeId; 60 + private NodeId localNodeId;
73 - protected ConsistentMap<String, InternalLeadership> leadershipMap; 61 + private LeaderElector leaderElector;
74 - protected Map<String, Versioned<InternalLeadership>> leadershipCache = Maps.newConcurrentMap();
75 62
76 - private final MapEventListener<String, InternalLeadership> leadershipChangeListener = 63 + private final Consumer<Change<Leadership>> leadershipChangeListener =
77 - event -> { 64 + change -> {
78 - Leadership oldValue = InternalLeadership.toLeadership(Versioned.valueOrNull(event.oldValue())); 65 + Leadership oldValue = change.oldValue();
79 - Leadership newValue = InternalLeadership.toLeadership(Versioned.valueOrNull(event.newValue())); 66 + Leadership newValue = change.newValue();
80 - boolean leaderChanged = 67 + boolean leaderChanged = !Objects.equals(oldValue.leader(), newValue.leader());
81 - !Objects.equal(oldValue == null ? null : oldValue.leader(), newValue.leader()); 68 + boolean candidatesChanged = !Objects.equals(oldValue.candidates(), newValue.candidates());
82 - boolean candidatesChanged =
83 - !Sets.symmetricDifference(Sets.newHashSet(oldValue == null ?
84 - ImmutableSet.<NodeId>of() : oldValue.candidates()),
85 - Sets.newHashSet(newValue.candidates())).isEmpty();
86 LeadershipEvent.Type eventType = null; 69 LeadershipEvent.Type eventType = null;
87 if (leaderChanged && candidatesChanged) { 70 if (leaderChanged && candidatesChanged) {
88 eventType = LeadershipEvent.Type.LEADER_AND_CANDIDATES_CHANGED; 71 eventType = LeadershipEvent.Type.LEADER_AND_CANDIDATES_CHANGED;
...@@ -93,193 +76,58 @@ public class DistributedLeadershipStore ...@@ -93,193 +76,58 @@ public class DistributedLeadershipStore
93 if (!leaderChanged && candidatesChanged) { 76 if (!leaderChanged && candidatesChanged) {
94 eventType = LeadershipEvent.Type.CANDIDATES_CHANGED; 77 eventType = LeadershipEvent.Type.CANDIDATES_CHANGED;
95 } 78 }
96 - leadershipCache.compute(event.key(), (k, v) -> { 79 + notifyDelegate(new LeadershipEvent(eventType, change.newValue()));
97 - if (v == null || v.version() < event.newValue().version()) {
98 - return event.newValue();
99 - }
100 - return v;
101 - });
102 - notifyDelegate(new LeadershipEvent(eventType, newValue));
103 }; 80 };
104 81
105 @Activate 82 @Activate
106 public void activate() { 83 public void activate() {
107 localNodeId = clusterService.getLocalNode().id(); 84 localNodeId = clusterService.getLocalNode().id();
108 - leadershipMap = storageService.<String, InternalLeadership>consistentMapBuilder() 85 + leaderElector = storageService.leaderElectorBuilder()
109 - .withName("onos-leadership") 86 + .withName("onos-leadership-elections")
110 - .withPartitionsDisabled() 87 + .build()
111 - .withRelaxedReadConsistency() 88 + .asLeaderElector();
112 - .withSerializer(Serializer.using(KryoNamespaces.API, InternalLeadership.class)) 89 + leaderElector.addChangeListener(leadershipChangeListener);
113 - .build();
114 - leadershipMap.entrySet().forEach(e -> leadershipCache.put(e.getKey(), e.getValue()));
115 - leadershipMap.addListener(leadershipChangeListener);
116 log.info("Started"); 90 log.info("Started");
117 } 91 }
118 92
119 @Deactivate 93 @Deactivate
120 public void deactivate() { 94 public void deactivate() {
121 - leadershipMap.removeListener(leadershipChangeListener); 95 + leaderElector.removeChangeListener(leadershipChangeListener);
122 log.info("Stopped"); 96 log.info("Stopped");
123 } 97 }
124 98
125 @Override 99 @Override
126 public Leadership addRegistration(String topic) { 100 public Leadership addRegistration(String topic) {
127 - Versioned<InternalLeadership> internalLeadership = leadershipMap.computeIf(topic, 101 + return leaderElector.run(topic, localNodeId);
128 - v -> v == null || !v.candidates().contains(localNodeId),
129 - (k, v) -> {
130 - if (v == null || v.candidates().isEmpty()) {
131 - return new InternalLeadership(topic,
132 - localNodeId,
133 - v == null ? 1 : v.term() + 1,
134 - System.currentTimeMillis(),
135 - ImmutableList.of(localNodeId));
136 - }
137 - List<NodeId> newCandidates = new ArrayList<>(v.candidates());
138 - newCandidates.add(localNodeId);
139 - return new InternalLeadership(topic, v.leader(), v.term(), v.termStartTime(), newCandidates);
140 - });
141 - return InternalLeadership.toLeadership(Versioned.valueOrNull(internalLeadership));
142 } 102 }
143 103
144 @Override 104 @Override
145 public void removeRegistration(String topic) { 105 public void removeRegistration(String topic) {
146 - removeRegistration(topic, localNodeId); 106 + leaderElector.withdraw(topic);
147 - }
148 -
149 - private void removeRegistration(String topic, NodeId nodeId) {
150 - leadershipMap.computeIf(topic,
151 - v -> v != null && v.candidates().contains(nodeId),
152 - (k, v) -> {
153 - List<NodeId> newCandidates = v.candidates()
154 - .stream()
155 - .filter(id -> !nodeId.equals(id))
156 - .collect(Collectors.toList());
157 - NodeId newLeader = nodeId.equals(v.leader()) ?
158 - newCandidates.size() > 0 ? newCandidates.get(0) : null : v.leader();
159 - long newTerm = newLeader == null || Objects.equal(newLeader, v.leader()) ?
160 - v.term() : v.term() + 1;
161 - long newTermStartTime = newLeader == null || Objects.equal(newLeader, v.leader()) ?
162 - v.termStartTime() : System.currentTimeMillis();
163 - return new InternalLeadership(topic, newLeader, newTerm, newTermStartTime, newCandidates);
164 - });
165 } 107 }
166 108
167 @Override 109 @Override
168 public void removeRegistration(NodeId nodeId) { 110 public void removeRegistration(NodeId nodeId) {
169 - leadershipMap.entrySet() 111 + leaderElector.evict(nodeId);
170 - .stream()
171 - .filter(e -> e.getValue().value().candidates().contains(nodeId))
172 - .map(e -> e.getKey())
173 - .forEach(topic -> this.removeRegistration(topic, nodeId));
174 } 112 }
175 113
176 @Override 114 @Override
177 public boolean moveLeadership(String topic, NodeId toNodeId) { 115 public boolean moveLeadership(String topic, NodeId toNodeId) {
178 - Versioned<InternalLeadership> internalLeadership = leadershipMap.computeIf(topic, 116 + return leaderElector.anoint(topic, toNodeId);
179 - v -> v != null &&
180 - v.candidates().contains(toNodeId) &&
181 - !Objects.equal(v.leader(), toNodeId),
182 - (k, v) -> {
183 - List<NodeId> newCandidates = new ArrayList<>();
184 - newCandidates.add(toNodeId);
185 - newCandidates.addAll(v.candidates()
186 - .stream()
187 - .filter(id -> !toNodeId.equals(id))
188 - .collect(Collectors.toList()));
189 - return new InternalLeadership(topic,
190 - toNodeId,
191 - v.term() + 1,
192 - System.currentTimeMillis(),
193 - newCandidates);
194 - });
195 - return Objects.equal(toNodeId, Versioned.valueOrNull(internalLeadership).leader());
196 } 117 }
197 118
198 @Override 119 @Override
199 public boolean makeTopCandidate(String topic, NodeId nodeId) { 120 public boolean makeTopCandidate(String topic, NodeId nodeId) {
200 - Versioned<InternalLeadership> internalLeadership = leadershipMap.computeIf(topic, 121 + return leaderElector.promote(topic, nodeId);
201 - v -> v != null &&
202 - v.candidates().contains(nodeId) &&
203 - !v.candidates().get(0).equals(nodeId),
204 - (k, v) -> {
205 - List<NodeId> newCandidates = new ArrayList<>();
206 - newCandidates.add(nodeId);
207 - newCandidates.addAll(v.candidates()
208 - .stream()
209 - .filter(id -> !nodeId.equals(id))
210 - .collect(Collectors.toList()));
211 - return new InternalLeadership(topic,
212 - v.leader(),
213 - v.term(),
214 - System.currentTimeMillis(),
215 - newCandidates);
216 - });
217 - return internalLeadership != null && nodeId.equals(internalLeadership.value().candidates().get(0));
218 } 122 }
219 123
220 @Override 124 @Override
221 public Leadership getLeadership(String topic) { 125 public Leadership getLeadership(String topic) {
222 - InternalLeadership internalLeadership = Versioned.valueOrNull(leadershipMap.get(topic)); 126 + return leaderElector.getLeadership(topic);
223 - return internalLeadership == null ? null : internalLeadership.asLeadership();
224 } 127 }
225 128
226 @Override 129 @Override
227 public Map<String, Leadership> getLeaderships() { 130 public Map<String, Leadership> getLeaderships() {
228 - return ImmutableMap.copyOf(Maps.transformValues(leadershipCache, v -> v.value().asLeadership())); 131 + return leaderElector.getLeaderships();
229 - }
230 -
231 - private static class InternalLeadership {
232 - private final String topic;
233 - private final NodeId leader;
234 - private final long term;
235 - private final long termStartTime;
236 - private final List<NodeId> candidates;
237 -
238 - public InternalLeadership(String topic,
239 - NodeId leader,
240 - long term,
241 - long termStartTime,
242 - List<NodeId> candidates) {
243 - this.topic = topic;
244 - this.leader = leader;
245 - this.term = term;
246 - this.termStartTime = termStartTime;
247 - this.candidates = ImmutableList.copyOf(candidates);
248 - }
249 -
250 - public NodeId leader() {
251 - return this.leader;
252 - }
253 -
254 - public long term() {
255 - return term;
256 - }
257 -
258 - public long termStartTime() {
259 - return termStartTime;
260 - }
261 -
262 - public List<NodeId> candidates() {
263 - return candidates;
264 - }
265 -
266 - public Leadership asLeadership() {
267 - return new Leadership(topic, leader == null ?
268 - null : new Leader(leader, term, termStartTime), candidates);
269 - }
270 -
271 - public static Leadership toLeadership(InternalLeadership internalLeadership) {
272 - return internalLeadership == null ? null : internalLeadership.asLeadership();
273 - }
274 -
275 - @Override
276 - public String toString() {
277 - return MoreObjects.toStringHelper(getClass())
278 - .add("leader", leader)
279 - .add("term", term)
280 - .add("termStartTime", termStartTime)
281 - .add("candidates", candidates)
282 - .toString();
283 - }
284 } 132 }
285 } 133 }
......
1 -/*
2 - * Copyright 2016-present 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.cluster.impl;
17 -
18 -import static org.slf4j.LoggerFactory.getLogger;
19 -
20 -import java.util.Map;
21 -import java.util.Objects;
22 -import java.util.function.Consumer;
23 -
24 -import org.apache.felix.scr.annotations.Activate;
25 -import org.apache.felix.scr.annotations.Component;
26 -import org.apache.felix.scr.annotations.Deactivate;
27 -import org.apache.felix.scr.annotations.Reference;
28 -import org.apache.felix.scr.annotations.ReferenceCardinality;
29 -import org.apache.felix.scr.annotations.Service;
30 -import org.onosproject.cluster.ClusterService;
31 -import org.onosproject.cluster.Leadership;
32 -import org.onosproject.cluster.LeadershipEvent;
33 -import org.onosproject.cluster.LeadershipStore;
34 -import org.onosproject.cluster.LeadershipStoreDelegate;
35 -import org.onosproject.cluster.NodeId;
36 -import org.onosproject.event.Change;
37 -import org.onosproject.store.AbstractStore;
38 -import org.onosproject.store.service.LeaderElector;
39 -import org.onosproject.store.service.StorageService;
40 -import org.slf4j.Logger;
41 -
42 -/**
43 - * Implementation of {@code LeadershipStore} that makes use of a {@link LeaderElector}
44 - * primitive.
45 - */
46 -@Service
47 -@Component(immediate = true, enabled = true)
48 -public class NewDistributedLeadershipStore
49 - extends AbstractStore<LeadershipEvent, LeadershipStoreDelegate>
50 - implements LeadershipStore {
51 -
52 - private final Logger log = getLogger(getClass());
53 -
54 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 - protected ClusterService clusterService;
56 -
57 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 - protected StorageService storageService;
59 -
60 - private NodeId localNodeId;
61 - private LeaderElector leaderElector;
62 -
63 - private final Consumer<Change<Leadership>> leadershipChangeListener =
64 - change -> {
65 - Leadership oldValue = change.oldValue();
66 - Leadership newValue = change.newValue();
67 - boolean leaderChanged = !Objects.equals(oldValue.leader(), newValue.leader());
68 - boolean candidatesChanged = !Objects.equals(oldValue.candidates(), newValue.candidates());
69 - LeadershipEvent.Type eventType = null;
70 - if (leaderChanged && candidatesChanged) {
71 - eventType = LeadershipEvent.Type.LEADER_AND_CANDIDATES_CHANGED;
72 - }
73 - if (leaderChanged && !candidatesChanged) {
74 - eventType = LeadershipEvent.Type.LEADER_CHANGED;
75 - }
76 - if (!leaderChanged && candidatesChanged) {
77 - eventType = LeadershipEvent.Type.CANDIDATES_CHANGED;
78 - }
79 - notifyDelegate(new LeadershipEvent(eventType, change.newValue()));
80 - };
81 -
82 - @Activate
83 - public void activate() {
84 - localNodeId = clusterService.getLocalNode().id();
85 - leaderElector = storageService.leaderElectorBuilder()
86 - .withName("onos-leadership-elections")
87 - .build()
88 - .asLeaderElector();
89 - leaderElector.addChangeListener(leadershipChangeListener);
90 - log.info("Started");
91 - }
92 -
93 - @Deactivate
94 - public void deactivate() {
95 - leaderElector.removeChangeListener(leadershipChangeListener);
96 - log.info("Stopped");
97 - }
98 -
99 - @Override
100 - public Leadership addRegistration(String topic) {
101 - return leaderElector.run(topic, localNodeId);
102 - }
103 -
104 - @Override
105 - public void removeRegistration(String topic) {
106 - leaderElector.withdraw(topic);
107 - }
108 -
109 - @Override
110 - public void removeRegistration(NodeId nodeId) {
111 - leaderElector.evict(nodeId);
112 - }
113 -
114 - @Override
115 - public boolean moveLeadership(String topic, NodeId toNodeId) {
116 - return leaderElector.anoint(topic, toNodeId);
117 - }
118 -
119 - @Override
120 - public boolean makeTopCandidate(String topic, NodeId nodeId) {
121 - return leaderElector.promote(topic, nodeId);
122 - }
123 -
124 - @Override
125 - public Leadership getLeadership(String topic) {
126 - return leaderElector.getLeadership(topic);
127 - }
128 -
129 - @Override
130 - public Map<String, Leadership> getLeaderships() {
131 - return leaderElector.getLeaderships();
132 - }
133 -}
1 -/*
2 - * Copyright 2015-present 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.cluster.impl;
17 -
18 -import static com.google.common.base.MoreObjects.toStringHelper;
19 -
20 -import java.util.Objects;
21 -
22 -import org.onosproject.cluster.ControllerNode;
23 -
24 -/**
25 - * Node info read from configuration files during bootstrap.
26 - */
27 -public final class NodeInfo {
28 - private final String id;
29 - private final String ip;
30 - private final int tcpPort;
31 -
32 - private NodeInfo(String id, String ip, int port) {
33 - this.id = id;
34 - this.ip = ip;
35 - this.tcpPort = port;
36 - }
37 -
38 - /*
39 - * Needed for serialization.
40 - */
41 - private NodeInfo() {
42 - id = null;
43 - ip = null;
44 - tcpPort = 0;
45 - }
46 -
47 - /**
48 - * Creates a new instance.
49 - * @param id node id
50 - * @param ip node ip address
51 - * @param port tcp port
52 - * @return NodeInfo
53 - */
54 - public static NodeInfo from(String id, String ip, int port) {
55 - NodeInfo node = new NodeInfo(id, ip, port);
56 - return node;
57 - }
58 -
59 - /**
60 - * Returns the NodeInfo for a controller node.
61 - * @param node controller node
62 - * @return NodeInfo
63 - */
64 - public static NodeInfo of(ControllerNode node) {
65 - return NodeInfo.from(node.id().toString(), node.ip().toString(), node.tcpPort());
66 - }
67 -
68 - /**
69 - * Returns node id.
70 - * @return node id
71 - */
72 - public String getId() {
73 - return id;
74 - }
75 -
76 - /**
77 - * Returns node ip.
78 - * @return node ip
79 - */
80 - public String getIp() {
81 - return ip;
82 - }
83 -
84 - /**
85 - * Returns node port.
86 - * @return port
87 - */
88 - public int getTcpPort() {
89 - return tcpPort;
90 - }
91 -
92 - @Override
93 - public int hashCode() {
94 - return Objects.hash(id, ip, tcpPort);
95 - }
96 -
97 - @Override
98 - public boolean equals(Object o) {
99 - if (this == o) {
100 - return true;
101 - }
102 - if (o instanceof NodeInfo) {
103 - NodeInfo that = (NodeInfo) o;
104 - return Objects.equals(this.id, that.id) &&
105 - Objects.equals(this.ip, that.ip) &&
106 - Objects.equals(this.tcpPort, that.tcpPort);
107 - }
108 - return false;
109 - }
110 -
111 - @Override
112 - public String toString() {
113 - return toStringHelper(this)
114 - .add("id", id)
115 - .add("ip", ip)
116 - .add("tcpPort", tcpPort).toString();
117 - }
118 -}
...\ No newline at end of file ...\ No newline at end of file
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Implementation of a distributed cluster node store using Hazelcast. 18 + * Implementation of a distributed cluster membership store and failure detector.
19 */ 19 */
20 package org.onosproject.store.cluster.impl; 20 package org.onosproject.store.cluster.impl;
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Implementation of the network configuration distributed store. 18 + * Implementation of the distributed network configuration store.
19 */ 19 */
20 package org.onosproject.store.config.impl; 20 package org.onosproject.store.config.impl;
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -17,28 +17,31 @@ package org.onosproject.store.core.impl; ...@@ -17,28 +17,31 @@ package org.onosproject.store.core.impl;
17 17
18 import static org.slf4j.LoggerFactory.getLogger; 18 import static org.slf4j.LoggerFactory.getLogger;
19 19
20 +
20 import java.util.Map; 21 import java.util.Map;
21 import java.util.Set; 22 import java.util.Set;
23 +
24 +
22 import org.apache.felix.scr.annotations.Activate; 25 import org.apache.felix.scr.annotations.Activate;
23 import org.apache.felix.scr.annotations.Component; 26 import org.apache.felix.scr.annotations.Component;
24 import org.apache.felix.scr.annotations.Deactivate; 27 import org.apache.felix.scr.annotations.Deactivate;
25 import org.apache.felix.scr.annotations.Reference; 28 import org.apache.felix.scr.annotations.Reference;
26 import org.apache.felix.scr.annotations.ReferenceCardinality; 29 import org.apache.felix.scr.annotations.ReferenceCardinality;
27 import org.apache.felix.scr.annotations.Service; 30 import org.apache.felix.scr.annotations.Service;
28 -import org.onlab.util.KryoNamespace;
29 -import org.onlab.util.Tools;
30 import org.onosproject.core.ApplicationId; 31 import org.onosproject.core.ApplicationId;
31 import org.onosproject.core.ApplicationIdStore; 32 import org.onosproject.core.ApplicationIdStore;
32 import org.onosproject.core.DefaultApplicationId; 33 import org.onosproject.core.DefaultApplicationId;
33 import org.onosproject.store.serializers.KryoNamespaces; 34 import org.onosproject.store.serializers.KryoNamespaces;
34 import org.onosproject.store.service.AtomicCounter; 35 import org.onosproject.store.service.AtomicCounter;
35 import org.onosproject.store.service.ConsistentMap; 36 import org.onosproject.store.service.ConsistentMap;
37 +import org.onosproject.store.service.MapEvent;
38 +import org.onosproject.store.service.MapEventListener;
36 import org.onosproject.store.service.Serializer; 39 import org.onosproject.store.service.Serializer;
37 -import org.onosproject.store.service.StorageException;
38 import org.onosproject.store.service.StorageService; 40 import org.onosproject.store.service.StorageService;
39 import org.onosproject.store.service.Versioned; 41 import org.onosproject.store.service.Versioned;
40 import org.slf4j.Logger; 42 import org.slf4j.Logger;
41 43
44 +
42 import com.google.common.collect.ImmutableSet; 45 import com.google.common.collect.ImmutableSet;
43 import com.google.common.collect.Maps; 46 import com.google.common.collect.Maps;
44 47
...@@ -48,7 +51,7 @@ import com.google.common.collect.Maps; ...@@ -48,7 +51,7 @@ import com.google.common.collect.Maps;
48 */ 51 */
49 @Component(immediate = true, enabled = true) 52 @Component(immediate = true, enabled = true)
50 @Service 53 @Service
51 -public class ConsistentApplicationIdStore implements ApplicationIdStore { 54 +public class DistributedApplicationIdStore implements ApplicationIdStore {
52 55
53 private final Logger log = getLogger(getClass()); 56 private final Logger log = getLogger(getClass());
54 57
...@@ -57,13 +60,12 @@ public class ConsistentApplicationIdStore implements ApplicationIdStore { ...@@ -57,13 +60,12 @@ public class ConsistentApplicationIdStore implements ApplicationIdStore {
57 60
58 private AtomicCounter appIdCounter; 61 private AtomicCounter appIdCounter;
59 private ConsistentMap<String, ApplicationId> registeredIds; 62 private ConsistentMap<String, ApplicationId> registeredIds;
60 - private Map<String, ApplicationId> nameToAppIdCache = Maps.newConcurrentMap();
61 private Map<Short, ApplicationId> idToAppIdCache = Maps.newConcurrentMap(); 63 private Map<Short, ApplicationId> idToAppIdCache = Maps.newConcurrentMap();
62 - 64 + private MapEventListener<String, ApplicationId> mapEventListener = event -> {
63 - private static final Serializer SERIALIZER = Serializer.using(new KryoNamespace.Builder() 65 + if (event.type() == MapEvent.Type.INSERT) {
64 - .register(KryoNamespaces.API) 66 + idToAppIdCache.put(event.newValue().value().id(), event.newValue().value());
65 - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) 67 + }
66 - .build()); 68 + };
67 69
68 @Activate 70 @Activate
69 public void activate() { 71 public void activate() {
...@@ -71,75 +73,50 @@ public class ConsistentApplicationIdStore implements ApplicationIdStore { ...@@ -71,75 +73,50 @@ public class ConsistentApplicationIdStore implements ApplicationIdStore {
71 73
72 registeredIds = storageService.<String, ApplicationId>consistentMapBuilder() 74 registeredIds = storageService.<String, ApplicationId>consistentMapBuilder()
73 .withName("onos-app-ids") 75 .withName("onos-app-ids")
74 - .withSerializer(SERIALIZER) 76 + .withSerializer(Serializer.using(KryoNamespaces.API))
77 + .withRelaxedReadConsistency()
75 .build(); 78 .build();
76 79
77 - primeAppIds(); 80 + primeIdToAppIdCache();
81 + registeredIds.addListener(mapEventListener);
78 82
79 log.info("Started"); 83 log.info("Started");
80 } 84 }
81 85
82 @Deactivate 86 @Deactivate
83 public void deactivate() { 87 public void deactivate() {
88 + registeredIds.removeListener(mapEventListener);
84 log.info("Stopped"); 89 log.info("Stopped");
85 } 90 }
86 91
87 @Override 92 @Override
88 public Set<ApplicationId> getAppIds() { 93 public Set<ApplicationId> getAppIds() {
89 - // TODO: Rework this when we have notification support in ConsistentMap. 94 + return ImmutableSet.copyOf(registeredIds.asJavaMap().values());
90 - primeAppIds();
91 - return ImmutableSet.copyOf(nameToAppIdCache.values());
92 } 95 }
93 96
94 @Override 97 @Override
95 public ApplicationId getAppId(Short id) { 98 public ApplicationId getAppId(Short id) {
96 if (!idToAppIdCache.containsKey(id)) { 99 if (!idToAppIdCache.containsKey(id)) {
97 - primeAppIds(); 100 + primeIdToAppIdCache();
98 } 101 }
99 return idToAppIdCache.get(id); 102 return idToAppIdCache.get(id);
100 } 103 }
101 104
102 @Override 105 @Override
103 public ApplicationId getAppId(String name) { 106 public ApplicationId getAppId(String name) {
104 - ApplicationId appId = nameToAppIdCache.computeIfAbsent(name, key -> { 107 + return registeredIds.asJavaMap().get(name);
105 - Versioned<ApplicationId> existingAppId = registeredIds.get(key);
106 - return existingAppId != null ? existingAppId.value() : null;
107 - });
108 - if (appId != null) {
109 - idToAppIdCache.putIfAbsent(appId.id(), appId);
110 - }
111 - return appId;
112 } 108 }
113 109
114 @Override 110 @Override
115 public ApplicationId registerApplication(String name) { 111 public ApplicationId registerApplication(String name) {
116 - ApplicationId appId = nameToAppIdCache.computeIfAbsent(name, key -> { 112 + return Versioned.valueOrNull(registeredIds.computeIfAbsent(name,
117 - Versioned<ApplicationId> existingAppId = registeredIds.get(name); 113 + key -> new DefaultApplicationId((int) appIdCounter.incrementAndGet(), name)));
118 - if (existingAppId == null) {
119 - int id = Tools.retryable(appIdCounter::incrementAndGet, StorageException.class, 1, 2000)
120 - .get()
121 - .intValue();
122 - DefaultApplicationId newAppId = new DefaultApplicationId(id, name);
123 - existingAppId = registeredIds.putIfAbsent(name, newAppId);
124 - if (existingAppId != null) {
125 - return existingAppId.value();
126 - } else {
127 - return newAppId;
128 - }
129 - } else {
130 - return existingAppId.value();
131 - }
132 - });
133 - idToAppIdCache.putIfAbsent(appId.id(), appId);
134 - return appId;
135 } 114 }
136 115
137 - private void primeAppIds() { 116 + private void primeIdToAppIdCache() {
138 - registeredIds.values() 117 + registeredIds.asJavaMap()
139 - .stream() 118 + .values()
140 - .map(Versioned::value)
141 .forEach(appId -> { 119 .forEach(appId -> {
142 - nameToAppIdCache.putIfAbsent(appId.name(), appId);
143 idToAppIdCache.putIfAbsent(appId.id(), appId); 120 idToAppIdCache.putIfAbsent(appId.id(), appId);
144 }); 121 });
145 } 122 }
......
...@@ -38,7 +38,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -38,7 +38,7 @@ import static org.slf4j.LoggerFactory.getLogger;
38 */ 38 */
39 @Component(immediate = true, enabled = true) 39 @Component(immediate = true, enabled = true)
40 @Service 40 @Service
41 -public class ConsistentIdBlockStore implements IdBlockStore { 41 +public class DistributedIdBlockStore implements IdBlockStore {
42 42
43 private final Logger log = getLogger(getClass()); 43 private final Logger log = getLogger(getClass());
44 private final Map<String, AtomicCounter> topicCounters = Maps.newConcurrentMap(); 44 private final Map<String, AtomicCounter> topicCounters = Maps.newConcurrentMap();
......
...@@ -34,7 +34,7 @@ import static org.onosproject.security.AppGuard.checkPermission; ...@@ -34,7 +34,7 @@ import static org.onosproject.security.AppGuard.checkPermission;
34 import static org.onosproject.security.AppPermission.Type.CLOCK_WRITE; 34 import static org.onosproject.security.AppPermission.Type.CLOCK_WRITE;
35 35
36 /** 36 /**
37 - * LogicalClockService implementation based on a AtomicCounter. 37 + * LogicalClockService implementation based on a {@link AtomicCounter}.
38 */ 38 */
39 @Component(immediate = true, enabled = true) 39 @Component(immediate = true, enabled = true)
40 @Service 40 @Service
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Implementation of a distributed application ID registry store using Hazelcast. 18 + * Implementation of a distributed application registry.
19 */ 19 */
20 package org.onosproject.store.core.impl; 20 package org.onosproject.store.core.impl;
......
...@@ -14,6 +14,6 @@ ...@@ -14,6 +14,6 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 /** 16 /**
17 - * Implementation of the group store. 17 + * Implementation of a distributed group store.
18 */ 18 */
19 package org.onosproject.store.group.impl; 19 package org.onosproject.store.group.impl;
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Implementation of the distributed host store using p2p synchronization protocol. 18 + * Implementation of a distributed host store.
19 */ 19 */
20 package org.onosproject.store.host.impl; 20 package org.onosproject.store.host.impl;
......
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 -import java.io.IOException;
19 -import java.util.Collections;
20 -import java.util.HashMap;
21 -import java.util.HashSet;
22 -import java.util.Map;
23 -import java.util.Map.Entry;
24 -import java.util.Set;
25 -import java.util.concurrent.ConcurrentHashMap;
26 -import java.util.concurrent.ConcurrentMap;
27 -import java.util.concurrent.ExecutorService;
28 -import java.util.concurrent.Executors;
29 -import java.util.concurrent.ScheduledExecutorService;
30 -import java.util.concurrent.TimeUnit;
31 -
32 -import org.apache.commons.lang3.RandomUtils;
33 -import org.apache.felix.scr.annotations.Activate;
34 -import org.apache.felix.scr.annotations.Deactivate;
35 -import org.apache.felix.scr.annotations.Reference;
36 -import org.apache.felix.scr.annotations.ReferenceCardinality;
37 -import org.apache.felix.scr.annotations.Service;
38 -import org.onlab.util.KryoNamespace;
39 -import org.onosproject.cluster.ClusterService;
40 -import org.onosproject.cluster.ControllerNode;
41 -import org.onosproject.cluster.NodeId;
42 -import org.onosproject.mastership.MastershipService;
43 -import org.onosproject.net.AnnotationsUtil;
44 -import org.onosproject.net.ConnectPoint;
45 -import org.onosproject.net.DefaultAnnotations;
46 -import org.onosproject.net.DefaultLink;
47 -import org.onosproject.net.DeviceId;
48 -import org.onosproject.net.Link;
49 -import org.onosproject.net.Link.Type;
50 -import org.onosproject.net.LinkKey;
51 -import org.onosproject.net.SparseAnnotations;
52 -import org.onosproject.net.device.DeviceClockService;
53 -import org.onosproject.net.link.DefaultLinkDescription;
54 -import org.onosproject.net.link.LinkDescription;
55 -import org.onosproject.net.link.LinkEvent;
56 -import org.onosproject.net.link.LinkStore;
57 -import org.onosproject.net.link.LinkStoreDelegate;
58 -import org.onosproject.net.provider.ProviderId;
59 -import org.onosproject.store.AbstractStore;
60 -import org.onosproject.store.Timestamp;
61 -import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
62 -import org.onosproject.store.cluster.messaging.ClusterMessage;
63 -import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
64 -import org.onosproject.store.cluster.messaging.MessageSubject;
65 -import org.onosproject.store.impl.Timestamped;
66 -import org.onosproject.store.serializers.StoreSerializer;
67 -import org.onosproject.store.serializers.custom.DistributedStoreSerializers;
68 -import org.slf4j.Logger;
69 -
70 -import com.google.common.base.Function;
71 -import com.google.common.collect.FluentIterable;
72 -import com.google.common.collect.ImmutableList;
73 -import com.google.common.collect.Multimaps;
74 -import com.google.common.collect.SetMultimap;
75 -import com.google.common.collect.Sets;
76 -
77 -import static com.google.common.base.Preconditions.checkArgument;
78 -import static com.google.common.base.Preconditions.checkNotNull;
79 -import static com.google.common.base.Predicates.notNull;
80 -import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
81 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
82 -import static org.onlab.util.Tools.groupedThreads;
83 -import static org.onlab.util.Tools.minPriority;
84 -import static org.onosproject.cluster.ControllerNodeToNodeId.toNodeId;
85 -import static org.onosproject.net.DefaultAnnotations.merge;
86 -import static org.onosproject.net.DefaultAnnotations.union;
87 -import static org.onosproject.net.Link.State.ACTIVE;
88 -import static org.onosproject.net.Link.State.INACTIVE;
89 -import static org.onosproject.net.Link.Type.DIRECT;
90 -import static org.onosproject.net.Link.Type.INDIRECT;
91 -import static org.onosproject.net.LinkKey.linkKey;
92 -import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
93 -import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
94 -import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
95 -import static org.onosproject.store.link.impl.GossipLinkStoreMessageSubjects.LINK_ANTI_ENTROPY_ADVERTISEMENT;
96 -import static org.slf4j.LoggerFactory.getLogger;
97 -
98 -/**
99 - * Manages inventory of infrastructure links in distributed data store
100 - * that uses optimistic replication and gossip based techniques.
101 - */
102 -//@Component(immediate = true, enabled = false)
103 -@Service
104 -public class GossipLinkStore
105 - extends AbstractStore<LinkEvent, LinkStoreDelegate>
106 - implements LinkStore {
107 -
108 - // Timeout in milliseconds to process links on remote master node
109 - private static final int REMOTE_MASTER_TIMEOUT = 1000;
110 -
111 - // Default delay for ScheduledExecutorService of anti-entropy(BackgroundExecutor)
112 - private static final long DEFAULT_INITIAL_DELAY = 5;
113 -
114 - // Default period for ScheduledExecutorService of anti-entropy(BackgroundExecutor)
115 - private static final long DEFAULT_PERIOD = 5;
116 -
117 - private static long initialDelaySec = DEFAULT_INITIAL_DELAY;
118 - private static long periodSec = DEFAULT_PERIOD;
119 -
120 - private final Logger log = getLogger(getClass());
121 -
122 - // Link inventory
123 - private final ConcurrentMap<LinkKey, Map<ProviderId, Timestamped<LinkDescription>>> linkDescs =
124 - new ConcurrentHashMap<>();
125 -
126 - // Link instance cache
127 - private final ConcurrentMap<LinkKey, Link> links = new ConcurrentHashMap<>();
128 -
129 - // Egress and ingress link sets
130 - private final SetMultimap<DeviceId, LinkKey> srcLinks = createSynchronizedHashMultiMap();
131 - private final SetMultimap<DeviceId, LinkKey> dstLinks = createSynchronizedHashMultiMap();
132 -
133 - // Remove links
134 - private final Map<LinkKey, Timestamp> removedLinks = new ConcurrentHashMap<>();
135 -
136 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 - protected DeviceClockService deviceClockService;
138 -
139 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 - protected ClusterCommunicationService clusterCommunicator;
141 -
142 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 - protected ClusterService clusterService;
144 -
145 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
146 - protected MastershipService mastershipService;
147 -
148 - protected static final StoreSerializer SERIALIZER = StoreSerializer.using(
149 - KryoNamespace.newBuilder()
150 - .register(DistributedStoreSerializers.STORE_COMMON)
151 - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
152 - .register(InternalLinkEvent.class)
153 - .register(InternalLinkRemovedEvent.class)
154 - .register(LinkAntiEntropyAdvertisement.class)
155 - .register(LinkFragmentId.class)
156 - .register(LinkInjectedEvent.class)
157 - .build("GossipLink"));
158 -
159 - private ExecutorService executor;
160 -
161 - private ScheduledExecutorService backgroundExecutors;
162 -
163 - @Activate
164 - public void activate() {
165 -
166 - executor = Executors.newCachedThreadPool(groupedThreads("onos/link", "fg-%d"));
167 -
168 - backgroundExecutors =
169 - newSingleThreadScheduledExecutor(minPriority(groupedThreads("onos/link", "bg-%d")));
170 -
171 - clusterCommunicator.addSubscriber(
172 - GossipLinkStoreMessageSubjects.LINK_UPDATE,
173 - new InternalLinkEventListener(), executor);
174 - clusterCommunicator.addSubscriber(
175 - GossipLinkStoreMessageSubjects.LINK_REMOVED,
176 - new InternalLinkRemovedEventListener(), executor);
177 - clusterCommunicator.addSubscriber(
178 - GossipLinkStoreMessageSubjects.LINK_ANTI_ENTROPY_ADVERTISEMENT,
179 - new InternalLinkAntiEntropyAdvertisementListener(), backgroundExecutors);
180 - clusterCommunicator.addSubscriber(
181 - GossipLinkStoreMessageSubjects.LINK_INJECTED,
182 - new LinkInjectedEventListener(), executor);
183 -
184 - // start anti-entropy thread
185 - backgroundExecutors.scheduleAtFixedRate(new SendAdvertisementTask(),
186 - initialDelaySec, periodSec, TimeUnit.SECONDS);
187 -
188 - log.info("Started");
189 - }
190 -
191 - @Deactivate
192 - public void deactivate() {
193 -
194 - executor.shutdownNow();
195 -
196 - backgroundExecutors.shutdownNow();
197 - try {
198 - if (!backgroundExecutors.awaitTermination(5, TimeUnit.SECONDS)) {
199 - log.error("Timeout during executor shutdown");
200 - }
201 - } catch (InterruptedException e) {
202 - log.error("Error during executor shutdown", e);
203 - }
204 -
205 - linkDescs.clear();
206 - links.clear();
207 - srcLinks.clear();
208 - dstLinks.clear();
209 - log.info("Stopped");
210 - }
211 -
212 - @Override
213 - public int getLinkCount() {
214 - return links.size();
215 - }
216 -
217 - @Override
218 - public Iterable<Link> getLinks() {
219 - return Collections.unmodifiableCollection(links.values());
220 - }
221 -
222 - @Override
223 - public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
224 - // lock for iteration
225 - synchronized (srcLinks) {
226 - return FluentIterable.from(srcLinks.get(deviceId))
227 - .transform(lookupLink())
228 - .filter(notNull())
229 - .toSet();
230 - }
231 - }
232 -
233 - @Override
234 - public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
235 - // lock for iteration
236 - synchronized (dstLinks) {
237 - return FluentIterable.from(dstLinks.get(deviceId))
238 - .transform(lookupLink())
239 - .filter(notNull())
240 - .toSet();
241 - }
242 - }
243 -
244 - @Override
245 - public Link getLink(ConnectPoint src, ConnectPoint dst) {
246 - return links.get(linkKey(src, dst));
247 - }
248 -
249 - @Override
250 - public Set<Link> getEgressLinks(ConnectPoint src) {
251 - Set<Link> egress = new HashSet<>();
252 - //
253 - // Change `srcLinks` to ConcurrentMap<DeviceId, (Concurrent)Set>
254 - // to remove this synchronized block, if we hit performance issue.
255 - // SetMultiMap#get returns wrapped collection to provide modifiable-view.
256 - // And the wrapped collection is not concurrent access safe.
257 - //
258 - // Our use case here does not require returned collection to be modifiable,
259 - // so the wrapped collection forces us to lock the whole multiset,
260 - // for benefit we don't need.
261 - //
262 - // Same applies to `dstLinks`
263 - synchronized (srcLinks) {
264 - for (LinkKey linkKey : srcLinks.get(src.deviceId())) {
265 - if (linkKey.src().equals(src)) {
266 - Link link = links.get(linkKey);
267 - if (link != null) {
268 - egress.add(link);
269 - } else {
270 - log.debug("Egress link for {} was null, skipped", linkKey);
271 - }
272 - }
273 - }
274 - }
275 - return egress;
276 - }
277 -
278 - @Override
279 - public Set<Link> getIngressLinks(ConnectPoint dst) {
280 - Set<Link> ingress = new HashSet<>();
281 - synchronized (dstLinks) {
282 - for (LinkKey linkKey : dstLinks.get(dst.deviceId())) {
283 - if (linkKey.dst().equals(dst)) {
284 - Link link = links.get(linkKey);
285 - if (link != null) {
286 - ingress.add(link);
287 - } else {
288 - log.debug("Ingress link for {} was null, skipped", linkKey);
289 - }
290 - }
291 - }
292 - }
293 - return ingress;
294 - }
295 -
296 - @Override
297 - public LinkEvent createOrUpdateLink(ProviderId providerId,
298 - LinkDescription linkDescription) {
299 -
300 - final DeviceId dstDeviceId = linkDescription.dst().deviceId();
301 - final NodeId localNode = clusterService.getLocalNode().id();
302 - final NodeId dstNode = mastershipService.getMasterFor(dstDeviceId);
303 -
304 - // Process link update only if we're the master of the destination node,
305 - // otherwise signal the actual master.
306 - LinkEvent linkEvent = null;
307 - if (localNode.equals(dstNode)) {
308 -
309 - Timestamp newTimestamp = deviceClockService.getTimestamp(dstDeviceId);
310 -
311 - final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp);
312 -
313 - LinkKey key = linkKey(linkDescription.src(), linkDescription.dst());
314 - final Timestamped<LinkDescription> mergedDesc;
315 - Map<ProviderId, Timestamped<LinkDescription>> map = getOrCreateLinkDescriptions(key);
316 -
317 - synchronized (map) {
318 - linkEvent = createOrUpdateLinkInternal(providerId, deltaDesc);
319 - mergedDesc = map.get(providerId);
320 - }
321 -
322 - if (linkEvent != null) {
323 - log.debug("Notifying peers of a link update topology event from providerId: "
324 - + "{} between src: {} and dst: {}",
325 - providerId, linkDescription.src(), linkDescription.dst());
326 - notifyPeers(new InternalLinkEvent(providerId, mergedDesc));
327 - }
328 -
329 - } else {
330 - // Only forward for ConfigProvider
331 - // Forwarding was added as a workaround for ONOS-490
332 - if (!providerId.scheme().equals("cfg")) {
333 - return null;
334 - }
335 - // FIXME Temporary hack for NPE (ONOS-1171).
336 - // Proper fix is to implement forwarding to master on ConfigProvider
337 - // redo ONOS-490
338 - if (dstNode == null) {
339 - // silently ignore
340 - return null;
341 - }
342 -
343 -
344 - LinkInjectedEvent linkInjectedEvent = new LinkInjectedEvent(providerId, linkDescription);
345 -
346 - // TODO check unicast return value
347 - clusterCommunicator.unicast(linkInjectedEvent,
348 - GossipLinkStoreMessageSubjects.LINK_INJECTED,
349 - SERIALIZER::encode,
350 - dstNode);
351 - }
352 -
353 - return linkEvent;
354 - }
355 -
356 - @Override
357 - public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) {
358 - Link link = getLink(src, dst);
359 - if (link == null) {
360 - return null;
361 - }
362 -
363 - if (link.isDurable()) {
364 - // FIXME: this is not the right thing to call for the gossip store; will not sync link state!!!
365 - return link.state() == INACTIVE ? null :
366 - updateLink(linkKey(link.src(), link.dst()), link,
367 - DefaultLink.builder()
368 - .providerId(link.providerId())
369 - .src(link.src())
370 - .dst(link.dst())
371 - .type(link.type())
372 - .state(INACTIVE)
373 - .isExpected(link.isExpected())
374 - .annotations(link.annotations())
375 - .build());
376 - }
377 - return removeLink(src, dst);
378 - }
379 -
380 - private LinkEvent createOrUpdateLinkInternal(
381 - ProviderId providerId,
382 - Timestamped<LinkDescription> linkDescription) {
383 -
384 - final LinkKey key = linkKey(linkDescription.value().src(),
385 - linkDescription.value().dst());
386 - Map<ProviderId, Timestamped<LinkDescription>> descs = getOrCreateLinkDescriptions(key);
387 -
388 - synchronized (descs) {
389 - // if the link was previously removed, we should proceed if and
390 - // only if this request is more recent.
391 - Timestamp linkRemovedTimestamp = removedLinks.get(key);
392 - if (linkRemovedTimestamp != null) {
393 - if (linkDescription.isNewerThan(linkRemovedTimestamp)) {
394 - removedLinks.remove(key);
395 - } else {
396 - log.trace("Link {} was already removed ignoring.", key);
397 - return null;
398 - }
399 - }
400 -
401 - final Link oldLink = links.get(key);
402 - // update description
403 - createOrUpdateLinkDescription(descs, providerId, linkDescription);
404 - final Link newLink = composeLink(descs);
405 - if (oldLink == null) {
406 - return createLink(key, newLink);
407 - }
408 - return updateLink(key, oldLink, newLink);
409 - }
410 - }
411 -
412 - // Guarded by linkDescs value (=locking each Link)
413 - private Timestamped<LinkDescription> createOrUpdateLinkDescription(
414 - Map<ProviderId, Timestamped<LinkDescription>> descs,
415 - ProviderId providerId,
416 - Timestamped<LinkDescription> linkDescription) {
417 -
418 - // merge existing annotations
419 - Timestamped<LinkDescription> existingLinkDescription = descs.get(providerId);
420 - if (existingLinkDescription != null && existingLinkDescription.isNewer(linkDescription)) {
421 - log.trace("local info is more up-to-date, ignoring {}.", linkDescription);
422 - return null;
423 - }
424 - Timestamped<LinkDescription> newLinkDescription = linkDescription;
425 - if (existingLinkDescription != null) {
426 - // we only allow transition from INDIRECT -> DIRECT
427 - final Type newType;
428 - if (existingLinkDescription.value().type() == DIRECT) {
429 - newType = DIRECT;
430 - } else {
431 - newType = linkDescription.value().type();
432 - }
433 - SparseAnnotations merged = union(existingLinkDescription.value().annotations(),
434 - linkDescription.value().annotations());
435 - newLinkDescription = new Timestamped<>(
436 - new DefaultLinkDescription(
437 - linkDescription.value().src(),
438 - linkDescription.value().dst(),
439 - newType,
440 - existingLinkDescription.value().isExpected(),
441 - merged),
442 - linkDescription.timestamp());
443 - }
444 - return descs.put(providerId, newLinkDescription);
445 - }
446 -
447 - // Creates and stores the link and returns the appropriate event.
448 - // Guarded by linkDescs value (=locking each Link)
449 - private LinkEvent createLink(LinkKey key, Link newLink) {
450 - links.put(key, newLink);
451 - srcLinks.put(newLink.src().deviceId(), key);
452 - dstLinks.put(newLink.dst().deviceId(), key);
453 - return new LinkEvent(LINK_ADDED, newLink);
454 - }
455 -
456 - // Updates, if necessary the specified link and returns the appropriate event.
457 - // Guarded by linkDescs value (=locking each Link)
458 - private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
459 - // Note: INDIRECT -> DIRECT transition only
460 - // so that BDDP discovered Link will not overwrite LDDP Link
461 - if (oldLink.state() != newLink.state() ||
462 - (oldLink.type() == INDIRECT && newLink.type() == DIRECT) ||
463 - !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) {
464 -
465 - links.put(key, newLink);
466 - // strictly speaking following can be omitted
467 - srcLinks.put(oldLink.src().deviceId(), key);
468 - dstLinks.put(oldLink.dst().deviceId(), key);
469 - return new LinkEvent(LINK_UPDATED, newLink);
470 - }
471 - return null;
472 - }
473 -
474 - @Override
475 - public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
476 - final LinkKey key = linkKey(src, dst);
477 -
478 - DeviceId dstDeviceId = dst.deviceId();
479 - Timestamp timestamp = null;
480 - try {
481 - timestamp = deviceClockService.getTimestamp(dstDeviceId);
482 - } catch (IllegalStateException e) {
483 - log.debug("Failed to remove link {}, was not the master", key);
484 - // there are times when this is called before mastership
485 - // handoff correctly completes.
486 - return null;
487 - }
488 -
489 - LinkEvent event = removeLinkInternal(key, timestamp);
490 -
491 - if (event != null) {
492 - log.debug("Notifying peers of a link removed topology event for a link "
493 - + "between src: {} and dst: {}", src, dst);
494 - notifyPeers(new InternalLinkRemovedEvent(key, timestamp));
495 - }
496 - return event;
497 - }
498 -
499 - private static Timestamped<LinkDescription> getPrimaryDescription(
500 - Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions) {
501 -
502 - synchronized (linkDescriptions) {
503 - for (Entry<ProviderId, Timestamped<LinkDescription>>
504 - e : linkDescriptions.entrySet()) {
505 -
506 - if (!e.getKey().isAncillary()) {
507 - return e.getValue();
508 - }
509 - }
510 - }
511 - return null;
512 - }
513 -
514 -
515 - // TODO: consider slicing out as Timestamp utils
516 - /**
517 - * Checks is timestamp is more recent than timestamped object.
518 - *
519 - * @param timestamp to check if this is more recent then other
520 - * @param timestamped object to be tested against
521 - * @return true if {@code timestamp} is more recent than {@code timestamped}
522 - * or {@code timestamped is null}
523 - */
524 - private static boolean isMoreRecent(Timestamp timestamp, Timestamped<?> timestamped) {
525 - checkNotNull(timestamp);
526 - if (timestamped == null) {
527 - return true;
528 - }
529 - return timestamp.compareTo(timestamped.timestamp()) > 0;
530 - }
531 -
532 - private LinkEvent removeLinkInternal(LinkKey key, Timestamp timestamp) {
533 - Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions
534 - = getOrCreateLinkDescriptions(key);
535 -
536 - synchronized (linkDescriptions) {
537 - if (linkDescriptions.isEmpty()) {
538 - // never seen such link before. keeping timestamp for record
539 - removedLinks.put(key, timestamp);
540 - return null;
541 - }
542 - // accept removal request if given timestamp is newer than
543 - // the latest Timestamp from Primary provider
544 - Timestamped<LinkDescription> prim = getPrimaryDescription(linkDescriptions);
545 - if (!isMoreRecent(timestamp, prim)) {
546 - // outdated remove request, ignore
547 - return null;
548 - }
549 - removedLinks.put(key, timestamp);
550 - Link link = links.remove(key);
551 - linkDescriptions.clear();
552 - if (link != null) {
553 - srcLinks.remove(link.src().deviceId(), key);
554 - dstLinks.remove(link.dst().deviceId(), key);
555 - return new LinkEvent(LINK_REMOVED, link);
556 - }
557 - return null;
558 - }
559 - }
560 -
561 - /**
562 - * Creates concurrent readable, synchronized HashMultimap.
563 - *
564 - * @return SetMultimap
565 - */
566 - private static <K, V> SetMultimap<K, V> createSynchronizedHashMultiMap() {
567 - return synchronizedSetMultimap(
568 - Multimaps.newSetMultimap(new ConcurrentHashMap<>(),
569 - () -> Sets.newConcurrentHashSet()));
570 - }
571 -
572 - /**
573 - * @return primary ProviderID, or randomly chosen one if none exists
574 - */
575 - private static ProviderId pickBaseProviderId(
576 - Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions) {
577 -
578 - ProviderId fallBackPrimary = null;
579 - for (Entry<ProviderId, Timestamped<LinkDescription>> e : linkDescriptions.entrySet()) {
580 - if (!e.getKey().isAncillary()) {
581 - // found primary
582 - return e.getKey();
583 - } else if (fallBackPrimary == null) {
584 - // pick randomly as a fallback in case there is no primary
585 - fallBackPrimary = e.getKey();
586 - }
587 - }
588 - return fallBackPrimary;
589 - }
590 -
591 - // Guarded by linkDescs value (=locking each Link)
592 - private Link composeLink(Map<ProviderId, Timestamped<LinkDescription>> descs) {
593 - ProviderId baseProviderId = pickBaseProviderId(descs);
594 - Timestamped<LinkDescription> base = descs.get(baseProviderId);
595 -
596 - ConnectPoint src = base.value().src();
597 - ConnectPoint dst = base.value().dst();
598 - Type type = base.value().type();
599 - DefaultAnnotations annotations = DefaultAnnotations.builder().build();
600 - annotations = merge(annotations, base.value().annotations());
601 -
602 - for (Entry<ProviderId, Timestamped<LinkDescription>> e : descs.entrySet()) {
603 - if (baseProviderId.equals(e.getKey())) {
604 - continue;
605 - }
606 -
607 - // Note: In the long run we should keep track of Description timestamp
608 - // and only merge conflicting keys when timestamp is newer
609 - // Currently assuming there will never be a key conflict between
610 - // providers
611 -
612 - // annotation merging. not so efficient, should revisit later
613 - annotations = merge(annotations, e.getValue().value().annotations());
614 - }
615 -
616 - //boolean isDurable = Objects.equals(annotations.value(AnnotationKeys.DURABLE), "true");
617 -
618 - // TEMP
619 - Link.State initialLinkState = base.value().isExpected() ? ACTIVE : INACTIVE;
620 - return DefaultLink.builder()
621 - .providerId(baseProviderId)
622 - .src(src)
623 - .dst(dst)
624 - .type(type)
625 - .state(initialLinkState)
626 - .isExpected(base.value().isExpected())
627 - .annotations(annotations)
628 - .build();
629 - }
630 -
631 - private Map<ProviderId, Timestamped<LinkDescription>> getOrCreateLinkDescriptions(LinkKey key) {
632 - Map<ProviderId, Timestamped<LinkDescription>> r;
633 - r = linkDescs.get(key);
634 - if (r != null) {
635 - return r;
636 - }
637 - r = new HashMap<>();
638 - final Map<ProviderId, Timestamped<LinkDescription>> concurrentlyAdded;
639 - concurrentlyAdded = linkDescs.putIfAbsent(key, r);
640 - if (concurrentlyAdded != null) {
641 - return concurrentlyAdded;
642 - } else {
643 - return r;
644 - }
645 - }
646 -
647 - private final Function<LinkKey, Link> lookupLink = new LookupLink();
648 -
649 - /**
650 - * Returns a Function to lookup Link instance using LinkKey from cache.
651 - *
652 - * @return lookup link function
653 - */
654 - private Function<LinkKey, Link> lookupLink() {
655 - return lookupLink;
656 - }
657 -
658 - private final class LookupLink implements Function<LinkKey, Link> {
659 - @Override
660 - public Link apply(LinkKey input) {
661 - if (input == null) {
662 - return null;
663 - } else {
664 - return links.get(input);
665 - }
666 - }
667 - }
668 -
669 - private void notifyDelegateIfNotNull(LinkEvent event) {
670 - if (event != null) {
671 - notifyDelegate(event);
672 - }
673 - }
674 -
675 - private void broadcastMessage(MessageSubject subject, Object event) {
676 - clusterCommunicator.broadcast(event, subject, SERIALIZER::encode);
677 - }
678 -
679 - private void unicastMessage(NodeId recipient, MessageSubject subject, Object event) throws IOException {
680 - clusterCommunicator.unicast(event, subject, SERIALIZER::encode, recipient);
681 - }
682 -
683 - private void notifyPeers(InternalLinkEvent event) {
684 - broadcastMessage(GossipLinkStoreMessageSubjects.LINK_UPDATE, event);
685 - }
686 -
687 - private void notifyPeers(InternalLinkRemovedEvent event) {
688 - broadcastMessage(GossipLinkStoreMessageSubjects.LINK_REMOVED, event);
689 - }
690 -
691 - // notify peer, silently ignoring error
692 - private void notifyPeer(NodeId peer, InternalLinkEvent event) {
693 - try {
694 - unicastMessage(peer, GossipLinkStoreMessageSubjects.LINK_UPDATE, event);
695 - } catch (IOException e) {
696 - log.debug("Failed to notify peer {} with message {}", peer, event);
697 - }
698 - }
699 -
700 - // notify peer, silently ignoring error
701 - private void notifyPeer(NodeId peer, InternalLinkRemovedEvent event) {
702 - try {
703 - unicastMessage(peer, GossipLinkStoreMessageSubjects.LINK_REMOVED, event);
704 - } catch (IOException e) {
705 - log.debug("Failed to notify peer {} with message {}", peer, event);
706 - }
707 - }
708 -
709 - /**
710 - * sets the time to delay first execution for anti-entropy.
711 - * (scheduleAtFixedRate of ScheduledExecutorService)
712 - *
713 - * @param delay the time to delay first execution for anti-entropy
714 - */
715 - private void setInitialDelaySec(long delay) {
716 - checkArgument(delay >= 0, "Initial delay of scheduleAtFixedRate() must be 0 or more");
717 - initialDelaySec = delay;
718 - }
719 -
720 - /**
721 - * sets the period between successive execution for anti-entropy.
722 - * (scheduleAtFixedRate of ScheduledExecutorService)
723 - *
724 - * @param period the period between successive execution for anti-entropy
725 - */
726 - private void setPeriodSec(long period) {
727 - checkArgument(period > 0, "Period of scheduleAtFixedRate() must be greater than 0");
728 - periodSec = period;
729 - }
730 -
731 - private final class SendAdvertisementTask implements Runnable {
732 -
733 - @Override
734 - public void run() {
735 - if (Thread.currentThread().isInterrupted()) {
736 - log.debug("Interrupted, quitting");
737 - return;
738 - }
739 -
740 - try {
741 - final NodeId self = clusterService.getLocalNode().id();
742 - Set<ControllerNode> nodes = clusterService.getNodes();
743 -
744 - ImmutableList<NodeId> nodeIds = FluentIterable.from(nodes)
745 - .transform(toNodeId())
746 - .toList();
747 -
748 - if (nodeIds.size() == 1 && nodeIds.get(0).equals(self)) {
749 - log.trace("No other peers in the cluster.");
750 - return;
751 - }
752 -
753 - NodeId peer;
754 - do {
755 - int idx = RandomUtils.nextInt(0, nodeIds.size());
756 - peer = nodeIds.get(idx);
757 - } while (peer.equals(self));
758 -
759 - LinkAntiEntropyAdvertisement ad = createAdvertisement();
760 -
761 - if (Thread.currentThread().isInterrupted()) {
762 - log.debug("Interrupted, quitting");
763 - return;
764 - }
765 -
766 - try {
767 - unicastMessage(peer, LINK_ANTI_ENTROPY_ADVERTISEMENT, ad);
768 - } catch (IOException e) {
769 - log.debug("Failed to send anti-entropy advertisement to {}", peer);
770 - return;
771 - }
772 - } catch (Exception e) {
773 - // catch all Exception to avoid Scheduled task being suppressed.
774 - log.error("Exception thrown while sending advertisement", e);
775 - }
776 - }
777 - }
778 -
779 - private LinkAntiEntropyAdvertisement createAdvertisement() {
780 - final NodeId self = clusterService.getLocalNode().id();
781 -
782 - Map<LinkFragmentId, Timestamp> linkTimestamps = new HashMap<>(linkDescs.size());
783 - Map<LinkKey, Timestamp> linkTombstones = new HashMap<>(removedLinks.size());
784 -
785 - linkDescs.forEach((linkKey, linkDesc) -> {
786 - synchronized (linkDesc) {
787 - for (Map.Entry<ProviderId, Timestamped<LinkDescription>> e : linkDesc.entrySet()) {
788 - linkTimestamps.put(new LinkFragmentId(linkKey, e.getKey()), e.getValue().timestamp());
789 - }
790 - }
791 - });
792 -
793 - linkTombstones.putAll(removedLinks);
794 -
795 - return new LinkAntiEntropyAdvertisement(self, linkTimestamps, linkTombstones);
796 - }
797 -
798 - private void handleAntiEntropyAdvertisement(LinkAntiEntropyAdvertisement ad) {
799 -
800 - final NodeId sender = ad.sender();
801 - boolean localOutdated = false;
802 -
803 - for (Entry<LinkKey, Map<ProviderId, Timestamped<LinkDescription>>>
804 - l : linkDescs.entrySet()) {
805 -
806 - final LinkKey key = l.getKey();
807 - final Map<ProviderId, Timestamped<LinkDescription>> link = l.getValue();
808 - synchronized (link) {
809 - Timestamp localLatest = removedLinks.get(key);
810 -
811 - for (Entry<ProviderId, Timestamped<LinkDescription>> p : link.entrySet()) {
812 - final ProviderId providerId = p.getKey();
813 - final Timestamped<LinkDescription> pDesc = p.getValue();
814 -
815 - final LinkFragmentId fragId = new LinkFragmentId(key, providerId);
816 - // remote
817 - Timestamp remoteTimestamp = ad.linkTimestamps().get(fragId);
818 - if (remoteTimestamp == null) {
819 - remoteTimestamp = ad.linkTombstones().get(key);
820 - }
821 - if (remoteTimestamp == null ||
822 - pDesc.isNewerThan(remoteTimestamp)) {
823 - // I have more recent link description. update peer.
824 - notifyPeer(sender, new InternalLinkEvent(providerId, pDesc));
825 - } else {
826 - final Timestamp remoteLive = ad.linkTimestamps().get(fragId);
827 - if (remoteLive != null &&
828 - remoteLive.compareTo(pDesc.timestamp()) > 0) {
829 - // I have something outdated
830 - localOutdated = true;
831 - }
832 - }
833 -
834 - // search local latest along the way
835 - if (localLatest == null ||
836 - pDesc.isNewerThan(localLatest)) {
837 - localLatest = pDesc.timestamp();
838 - }
839 - }
840 - // Tests if remote remove is more recent then local latest.
841 - final Timestamp remoteRemove = ad.linkTombstones().get(key);
842 - if (remoteRemove != null) {
843 - if (localLatest != null &&
844 - localLatest.compareTo(remoteRemove) < 0) {
845 - // remote remove is more recent
846 - notifyDelegateIfNotNull(removeLinkInternal(key, remoteRemove));
847 - }
848 - }
849 - }
850 - }
851 -
852 - // populate remove info if not known locally
853 - for (Entry<LinkKey, Timestamp> remoteRm : ad.linkTombstones().entrySet()) {
854 - final LinkKey key = remoteRm.getKey();
855 - final Timestamp remoteRemove = remoteRm.getValue();
856 - // relying on removeLinkInternal to ignore stale info
857 - notifyDelegateIfNotNull(removeLinkInternal(key, remoteRemove));
858 - }
859 -
860 - if (localOutdated) {
861 - // send back advertisement to speed up convergence
862 - try {
863 - unicastMessage(sender, LINK_ANTI_ENTROPY_ADVERTISEMENT,
864 - createAdvertisement());
865 - } catch (IOException e) {
866 - log.debug("Failed to send back active advertisement");
867 - }
868 - }
869 - }
870 -
871 - private final class InternalLinkEventListener
872 - implements ClusterMessageHandler {
873 - @Override
874 - public void handle(ClusterMessage message) {
875 -
876 - log.trace("Received link event from peer: {}", message.sender());
877 - InternalLinkEvent event = SERIALIZER.decode(message.payload());
878 -
879 - ProviderId providerId = event.providerId();
880 - Timestamped<LinkDescription> linkDescription = event.linkDescription();
881 -
882 - try {
883 - notifyDelegateIfNotNull(createOrUpdateLinkInternal(providerId, linkDescription));
884 - } catch (Exception e) {
885 - log.warn("Exception thrown handling link event", e);
886 - }
887 - }
888 - }
889 -
890 - private final class InternalLinkRemovedEventListener
891 - implements ClusterMessageHandler {
892 - @Override
893 - public void handle(ClusterMessage message) {
894 -
895 - log.trace("Received link removed event from peer: {}", message.sender());
896 - InternalLinkRemovedEvent event = SERIALIZER.decode(message.payload());
897 -
898 - LinkKey linkKey = event.linkKey();
899 - Timestamp timestamp = event.timestamp();
900 -
901 - try {
902 - notifyDelegateIfNotNull(removeLinkInternal(linkKey, timestamp));
903 - } catch (Exception e) {
904 - log.warn("Exception thrown handling link removed", e);
905 - }
906 - }
907 - }
908 -
909 - private final class InternalLinkAntiEntropyAdvertisementListener
910 - implements ClusterMessageHandler {
911 -
912 - @Override
913 - public void handle(ClusterMessage message) {
914 - log.trace("Received Link Anti-Entropy advertisement from peer: {}", message.sender());
915 - LinkAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload());
916 - try {
917 - handleAntiEntropyAdvertisement(advertisement);
918 - } catch (Exception e) {
919 - log.warn("Exception thrown while handling Link advertisements", e);
920 - throw e;
921 - }
922 - }
923 - }
924 -
925 - private final class LinkInjectedEventListener
926 - implements ClusterMessageHandler {
927 - @Override
928 - public void handle(ClusterMessage message) {
929 -
930 - log.trace("Received injected link event from peer: {}", message.sender());
931 - LinkInjectedEvent linkInjectedEvent = SERIALIZER.decode(message.payload());
932 -
933 - ProviderId providerId = linkInjectedEvent.providerId();
934 - LinkDescription linkDescription = linkInjectedEvent.linkDescription();
935 -
936 - final DeviceId deviceId = linkDescription.dst().deviceId();
937 - if (!deviceClockService.isTimestampAvailable(deviceId)) {
938 - // workaround for ONOS-1208
939 - log.warn("Not ready to accept update. Dropping {}", linkDescription);
940 - return;
941 - }
942 -
943 - try {
944 - createOrUpdateLink(providerId, linkDescription);
945 - } catch (Exception e) {
946 - log.warn("Exception thrown while handling link injected event", e);
947 - }
948 - }
949 - }
950 -}
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 - import org.onosproject.store.cluster.messaging.MessageSubject;
19 -
20 -/**
21 - * MessageSubjects used by GossipLinkStore peer-peer communication.
22 - */
23 -public final class GossipLinkStoreMessageSubjects {
24 -
25 - private GossipLinkStoreMessageSubjects() {}
26 -
27 - public static final MessageSubject LINK_UPDATE =
28 - new MessageSubject("peer-link-update");
29 - public static final MessageSubject LINK_REMOVED =
30 - new MessageSubject("peer-link-removed");
31 - public static final MessageSubject LINK_ANTI_ENTROPY_ADVERTISEMENT =
32 - new MessageSubject("link-enti-entropy-advertisement");
33 - public static final MessageSubject LINK_INJECTED =
34 - new MessageSubject("peer-link-injected");
35 -}
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 -import com.google.common.base.MoreObjects;
19 -
20 -import org.onosproject.net.link.LinkDescription;
21 -import org.onosproject.net.provider.ProviderId;
22 -import org.onosproject.store.impl.Timestamped;
23 -
24 -/**
25 - * Information published by GossipDeviceStore to notify peers of a device
26 - * change event.
27 - */
28 -public class InternalLinkEvent {
29 -
30 - private final ProviderId providerId;
31 - private final Timestamped<LinkDescription> linkDescription;
32 -
33 - protected InternalLinkEvent(
34 - ProviderId providerId,
35 - Timestamped<LinkDescription> linkDescription) {
36 - this.providerId = providerId;
37 - this.linkDescription = linkDescription;
38 - }
39 -
40 - public ProviderId providerId() {
41 - return providerId;
42 - }
43 -
44 - public Timestamped<LinkDescription> linkDescription() {
45 - return linkDescription;
46 - }
47 -
48 - @Override
49 - public String toString() {
50 - return MoreObjects.toStringHelper(getClass())
51 - .add("providerId", providerId)
52 - .add("linkDescription", linkDescription)
53 - .toString();
54 - }
55 -
56 - // for serializer
57 - protected InternalLinkEvent() {
58 - this.providerId = null;
59 - this.linkDescription = null;
60 - }
61 -}
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 -import org.onosproject.net.LinkKey;
19 -import org.onosproject.store.Timestamp;
20 -
21 -import com.google.common.base.MoreObjects;
22 -
23 -/**
24 - * Information published by GossipLinkStore to notify peers of a link
25 - * being removed.
26 - */
27 -public class InternalLinkRemovedEvent {
28 -
29 - private final LinkKey linkKey;
30 - private final Timestamp timestamp;
31 -
32 - /**
33 - * Creates a InternalLinkRemovedEvent.
34 - * @param linkKey identifier of the removed link.
35 - * @param timestamp timestamp of when the link was removed.
36 - */
37 - public InternalLinkRemovedEvent(LinkKey linkKey, Timestamp timestamp) {
38 - this.linkKey = linkKey;
39 - this.timestamp = timestamp;
40 - }
41 -
42 - public LinkKey linkKey() {
43 - return linkKey;
44 - }
45 -
46 - public Timestamp timestamp() {
47 - return timestamp;
48 - }
49 -
50 - @Override
51 - public String toString() {
52 - return MoreObjects.toStringHelper(getClass())
53 - .add("linkKey", linkKey)
54 - .add("timestamp", timestamp)
55 - .toString();
56 - }
57 -
58 - // for serializer
59 - @SuppressWarnings("unused")
60 - private InternalLinkRemovedEvent() {
61 - linkKey = null;
62 - timestamp = null;
63 - }
64 -}
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 -import static com.google.common.base.Preconditions.checkNotNull;
19 -
20 -import java.util.Map;
21 -
22 -import org.onosproject.cluster.NodeId;
23 -import org.onosproject.net.LinkKey;
24 -import org.onosproject.store.Timestamp;
25 -
26 -/**
27 - * Link AE Advertisement message.
28 - */
29 -public class LinkAntiEntropyAdvertisement {
30 -
31 - private final NodeId sender;
32 - private final Map<LinkFragmentId, Timestamp> linkTimestamps;
33 - private final Map<LinkKey, Timestamp> linkTombstones;
34 -
35 -
36 - public LinkAntiEntropyAdvertisement(NodeId sender,
37 - Map<LinkFragmentId, Timestamp> linkTimestamps,
38 - Map<LinkKey, Timestamp> linkTombstones) {
39 - this.sender = checkNotNull(sender);
40 - this.linkTimestamps = checkNotNull(linkTimestamps);
41 - this.linkTombstones = checkNotNull(linkTombstones);
42 - }
43 -
44 - public NodeId sender() {
45 - return sender;
46 - }
47 -
48 - public Map<LinkFragmentId, Timestamp> linkTimestamps() {
49 - return linkTimestamps;
50 - }
51 -
52 - public Map<LinkKey, Timestamp> linkTombstones() {
53 - return linkTombstones;
54 - }
55 -
56 - // For serializer
57 - @SuppressWarnings("unused")
58 - private LinkAntiEntropyAdvertisement() {
59 - this.sender = null;
60 - this.linkTimestamps = null;
61 - this.linkTombstones = null;
62 - }
63 -}
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 -import java.util.Objects;
19 -
20 -import org.onosproject.net.LinkKey;
21 -import org.onosproject.net.provider.ProviderId;
22 -
23 -import com.google.common.base.MoreObjects;
24 -
25 -/**
26 - * Identifier for LinkDescription from a Provider.
27 - */
28 -public final class LinkFragmentId {
29 - public final ProviderId providerId;
30 - public final LinkKey linkKey;
31 -
32 - public LinkFragmentId(LinkKey linkKey, ProviderId providerId) {
33 - this.providerId = providerId;
34 - this.linkKey = linkKey;
35 - }
36 -
37 - public LinkKey linkKey() {
38 - return linkKey;
39 - }
40 -
41 - public ProviderId providerId() {
42 - return providerId;
43 - }
44 -
45 - @Override
46 - public int hashCode() {
47 - return Objects.hash(providerId, linkKey);
48 - }
49 -
50 - @Override
51 - public boolean equals(Object obj) {
52 - if (this == obj) {
53 - return true;
54 - }
55 - if (!(obj instanceof LinkFragmentId)) {
56 - return false;
57 - }
58 - LinkFragmentId that = (LinkFragmentId) obj;
59 - return Objects.equals(this.linkKey, that.linkKey) &&
60 - Objects.equals(this.providerId, that.providerId);
61 - }
62 -
63 - @Override
64 - public String toString() {
65 - return MoreObjects.toStringHelper(getClass())
66 - .add("providerId", providerId)
67 - .add("linkKey", linkKey)
68 - .toString();
69 - }
70 -
71 - // for serializer
72 - @SuppressWarnings("unused")
73 - private LinkFragmentId() {
74 - this.providerId = null;
75 - this.linkKey = null;
76 - }
77 -}
1 -/*
2 - * Copyright 2015-present 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.link.impl;
17 -
18 -import com.google.common.base.MoreObjects;
19 -import org.onosproject.net.link.LinkDescription;
20 -import org.onosproject.net.provider.ProviderId;
21 -
22 -public class LinkInjectedEvent {
23 -
24 - ProviderId providerId;
25 - LinkDescription linkDescription;
26 -
27 - public LinkInjectedEvent(ProviderId providerId, LinkDescription linkDescription) {
28 - this.providerId = providerId;
29 - this.linkDescription = linkDescription;
30 - }
31 -
32 - public ProviderId providerId() {
33 - return providerId;
34 - }
35 -
36 - public LinkDescription linkDescription() {
37 - return linkDescription;
38 - }
39 -
40 - @Override
41 - public String toString() {
42 - return MoreObjects.toStringHelper(getClass())
43 - .add("providerId", providerId)
44 - .add("linkDescription", linkDescription)
45 - .toString();
46 - }
47 -
48 - // for serializer
49 - protected LinkInjectedEvent() {
50 - this.providerId = null;
51 - this.linkDescription = null;
52 - }
53 -}
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Implementation of distributed link store using p2p synchronization protocol. 18 + * Implementation of distributed link store using eventually consistent map primitive.
19 */ 19 */
20 package org.onosproject.store.link.impl; 20 package org.onosproject.store.link.impl;
......
1 -/*
2 - * Copyright 2014-present 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.mastership.impl;
17 -
18 -import static org.onosproject.net.MastershipRole.MASTER;
19 -import static org.onosproject.net.MastershipRole.NONE;
20 -import static org.onosproject.net.MastershipRole.STANDBY;
21 -
22 -import java.util.Collections;
23 -import java.util.EnumMap;
24 -import java.util.LinkedList;
25 -import java.util.List;
26 -import java.util.Map;
27 -
28 -import org.onosproject.cluster.NodeId;
29 -import org.onosproject.cluster.RoleInfo;
30 -import org.onosproject.net.MastershipRole;
31 -
32 -import com.google.common.base.MoreObjects;
33 -import com.google.common.base.MoreObjects.ToStringHelper;
34 -import com.google.common.collect.Lists;
35 -
36 -/**
37 - * A structure that holds node mastership roles associated with a
38 - * {@link org.onosproject.net.DeviceId}. This structure needs to be locked through IMap.
39 - */
40 -final class RoleValue {
41 -
42 - protected final Map<MastershipRole, List<NodeId>> value = new EnumMap<>(MastershipRole.class);
43 -
44 - /**
45 - * Constructs empty RoleValue.
46 - */
47 - public RoleValue() {
48 - value.put(MastershipRole.MASTER, new LinkedList<>());
49 - value.put(MastershipRole.STANDBY, new LinkedList<>());
50 - value.put(MastershipRole.NONE, new LinkedList<>());
51 - }
52 -
53 - /**
54 - * Constructs copy of specified RoleValue.
55 - *
56 - * @param original original to create copy from
57 - */
58 - public RoleValue(final RoleValue original) {
59 - value.put(MASTER, Lists.newLinkedList(original.value.get(MASTER)));
60 - value.put(STANDBY, Lists.newLinkedList(original.value.get(STANDBY)));
61 - value.put(NONE, Lists.newLinkedList(original.value.get(NONE)));
62 - }
63 -
64 - // exposing internals for serialization purpose only
65 - Map<MastershipRole, List<NodeId>> value() {
66 - return Collections.unmodifiableMap(value);
67 - }
68 -
69 - public List<NodeId> nodesOfRole(MastershipRole type) {
70 - return value.get(type);
71 - }
72 -
73 - /**
74 - * Returns the first node to match the MastershipRole, or if there
75 - * are none, null.
76 - *
77 - * @param type the role
78 - * @return a node ID or null
79 - */
80 - public NodeId get(MastershipRole type) {
81 - return value.get(type).isEmpty() ? null : value.get(type).get(0);
82 - }
83 -
84 - public boolean contains(MastershipRole type, NodeId nodeId) {
85 - return value.get(type).contains(nodeId);
86 - }
87 -
88 - public MastershipRole getRole(NodeId nodeId) {
89 - if (contains(MASTER, nodeId)) {
90 - return MASTER;
91 - }
92 - if (contains(STANDBY, nodeId)) {
93 - return STANDBY;
94 - }
95 - return NONE;
96 - }
97 -
98 - /**
99 - * Associates a node to a certain role.
100 - *
101 - * @param type the role
102 - * @param nodeId the node ID of the node to associate
103 - * @return true if modified
104 - */
105 - public boolean add(MastershipRole type, NodeId nodeId) {
106 - List<NodeId> nodes = value.get(type);
107 -
108 - if (!nodes.contains(nodeId)) {
109 - return nodes.add(nodeId);
110 - }
111 - return false;
112 - }
113 -
114 - /**
115 - * Removes a node from a certain role.
116 - *
117 - * @param type the role
118 - * @param nodeId the ID of the node to remove
119 - * @return true if modified
120 - */
121 - public boolean remove(MastershipRole type, NodeId nodeId) {
122 - List<NodeId> nodes = value.get(type);
123 - if (!nodes.isEmpty()) {
124 - return nodes.remove(nodeId);
125 - } else {
126 - return false;
127 - }
128 - }
129 -
130 - /**
131 - * Reassigns a node from one role to another. If the node was not of the
132 - * old role, it will still be assigned the new role.
133 - *
134 - * @param nodeId the Node ID of node changing roles
135 - * @param from the old role
136 - * @param to the new role
137 - * @return true if modified
138 - */
139 - public boolean reassign(NodeId nodeId, MastershipRole from, MastershipRole to) {
140 - boolean modified = remove(from, nodeId);
141 - modified |= add(to, nodeId);
142 - return modified;
143 - }
144 -
145 - /**
146 - * Replaces a node in one role with another node. Even if there is no node to
147 - * replace, the new node is associated to the role.
148 - *
149 - * @param from the old NodeId to replace
150 - * @param to the new NodeId
151 - * @param type the role associated with the old NodeId
152 - * @return true if modified
153 - */
154 - public boolean replace(NodeId from, NodeId to, MastershipRole type) {
155 - boolean modified = remove(type, from);
156 - modified |= add(type, to);
157 - return modified;
158 - }
159 -
160 - /**
161 - * Summarizes this RoleValue as a RoleInfo. Note that master and/or backups
162 - * may be empty, so the values should be checked for safety.
163 - *
164 - * @return the RoleInfo.
165 - */
166 - public RoleInfo roleInfo() {
167 - return new RoleInfo(
168 - get(MastershipRole.MASTER), nodesOfRole(MastershipRole.STANDBY));
169 - }
170 -
171 - @Override
172 - public String toString() {
173 - ToStringHelper helper = MoreObjects.toStringHelper(this.getClass());
174 - for (Map.Entry<MastershipRole, List<NodeId>> el : value.entrySet()) {
175 - helper.add(el.getKey().toString(), el.getValue());
176 - }
177 - return helper.toString();
178 - }
179 -}
1 -/*
2 - * Copyright 2014-present 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.mastership.impl;
17 -
18 -import java.util.List;
19 -import java.util.Map;
20 -
21 -import org.onosproject.cluster.NodeId;
22 -import org.onosproject.net.MastershipRole;
23 -
24 -import com.esotericsoftware.kryo.Kryo;
25 -import com.esotericsoftware.kryo.Serializer;
26 -import com.esotericsoftware.kryo.io.Input;
27 -import com.esotericsoftware.kryo.io.Output;
28 -
29 -/**
30 - * Serializer for RoleValues used by {@link org.onosproject.mastership.MastershipStore}.
31 - */
32 -public class RoleValueSerializer extends Serializer<RoleValue> {
33 -
34 - //RoleValues are assumed to hold a Map of MastershipRoles (an enum)
35 - //to a List of NodeIds.
36 -
37 - @Override
38 - public RoleValue read(Kryo kryo, Input input, Class<RoleValue> type) {
39 - RoleValue rv = new RoleValue();
40 - int size = input.readInt();
41 - for (int i = 0; i < size; i++) {
42 - MastershipRole role = MastershipRole.values()[input.readInt()];
43 - int s = input.readInt();
44 - for (int j = 0; j < s; j++) {
45 - rv.add(role, new NodeId(input.readString()));
46 - }
47 - }
48 - return rv;
49 - }
50 -
51 - @Override
52 - public void write(Kryo kryo, Output output, RoleValue type) {
53 - final Map<MastershipRole, List<NodeId>> map = type.value();
54 - output.writeInt(map.size());
55 -
56 - for (Map.Entry<MastershipRole, List<NodeId>> el : map.entrySet()) {
57 - output.writeInt(el.getKey().ordinal());
58 -
59 - List<NodeId> nodes = el.getValue();
60 - output.writeInt(nodes.size());
61 - for (NodeId n : nodes) {
62 - output.writeString(n.toString());
63 - }
64 - }
65 - }
66 -
67 -}
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Implementation of a distributed mastership store using Hazelcast. 18 + * Implementation of a distributed mastership store.
19 */ 19 */
20 package org.onosproject.store.mastership.impl; 20 package org.onosproject.store.mastership.impl;
......
1 -/*
2 - * Copyright 2015-present 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.serializers.custom;
17 -
18 -import org.onosproject.cluster.NodeId;
19 -import org.onosproject.store.cluster.messaging.ClusterMessage;
20 -import org.onosproject.store.cluster.messaging.MessageSubject;
21 -import com.esotericsoftware.kryo.Kryo;
22 -import com.esotericsoftware.kryo.Serializer;
23 -import com.esotericsoftware.kryo.io.Input;
24 -import com.esotericsoftware.kryo.io.Output;
25 -
26 -public final class ClusterMessageSerializer extends Serializer<ClusterMessage> {
27 -
28 - /**
29 - * Creates a serializer for {@link ClusterMessage}.
30 - */
31 - public ClusterMessageSerializer() {
32 - // does not accept null
33 - super(false);
34 - }
35 -
36 - @Override
37 - public void write(Kryo kryo, Output output, ClusterMessage message) {
38 - kryo.writeClassAndObject(output, message.sender());
39 - kryo.writeClassAndObject(output, message.subject());
40 - output.writeInt(message.payload().length);
41 - output.writeBytes(message.payload());
42 - }
43 -
44 - @Override
45 - public ClusterMessage read(Kryo kryo, Input input,
46 - Class<ClusterMessage> type) {
47 - NodeId sender = (NodeId) kryo.readClassAndObject(input);
48 - MessageSubject subject = (MessageSubject) kryo.readClassAndObject(input);
49 - int payloadSize = input.readInt();
50 - byte[] payload = input.readBytes(payloadSize);
51 - return new ClusterMessage(sender, subject, payload);
52 - }
53 -}
1 -/*
2 - * Copyright 2015-present 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.serializers.custom;
17 -
18 -import org.onosproject.store.cluster.messaging.MessageSubject;
19 -
20 -import com.esotericsoftware.kryo.Kryo;
21 -import com.esotericsoftware.kryo.Serializer;
22 -import com.esotericsoftware.kryo.io.Input;
23 -import com.esotericsoftware.kryo.io.Output;
24 -
25 -public final class MessageSubjectSerializer extends Serializer<MessageSubject> {
26 -
27 - /**
28 - * Creates a serializer for {@link MessageSubject}.
29 - */
30 - public MessageSubjectSerializer() {
31 - // non-null, immutable
32 - super(false, true);
33 - }
34 -
35 -
36 - @Override
37 - public void write(Kryo kryo, Output output, MessageSubject object) {
38 - output.writeString(object.value());
39 - }
40 -
41 - @Override
42 - public MessageSubject read(Kryo kryo, Input input,
43 - Class<MessageSubject> type) {
44 - return new MessageSubject(input.readString());
45 - }
46 -}
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Cluster messaging and distributed store serializers. 18 + * Distributed store serializers.
19 */ 19 */
20 -//FIXME what is the right name for this package?
21 -//FIXME can this be moved to onos-core-serializers?
22 package org.onosproject.store.serializers.custom; 20 package org.onosproject.store.serializers.custom;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
17 package org.onosproject.store.statistic.impl; 17 package org.onosproject.store.statistic.impl;
18 18
19 import com.google.common.base.Objects; 19 import com.google.common.base.Objects;
20 +
20 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
22 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -38,6 +39,7 @@ import org.onosproject.net.flow.instructions.Instruction; ...@@ -38,6 +39,7 @@ import org.onosproject.net.flow.instructions.Instruction;
38 import org.onosproject.net.flow.instructions.Instructions; 39 import org.onosproject.net.flow.instructions.Instructions;
39 import org.onosproject.net.statistic.FlowStatisticStore; 40 import org.onosproject.net.statistic.FlowStatisticStore;
40 import org.onosproject.store.cluster.messaging.ClusterCommunicationService; 41 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
42 +import org.onosproject.store.cluster.messaging.MessageSubject;
41 import org.onosproject.store.serializers.KryoNamespaces; 43 import org.onosproject.store.serializers.KryoNamespaces;
42 import org.onosproject.store.serializers.StoreSerializer; 44 import org.onosproject.store.serializers.StoreSerializer;
43 import org.osgi.service.component.ComponentContext; 45 import org.osgi.service.component.ComponentContext;
...@@ -59,8 +61,6 @@ import static com.google.common.base.Preconditions.checkArgument; ...@@ -59,8 +61,6 @@ import static com.google.common.base.Preconditions.checkArgument;
59 import static com.google.common.base.Strings.isNullOrEmpty; 61 import static com.google.common.base.Strings.isNullOrEmpty;
60 import static org.onlab.util.Tools.get; 62 import static org.onlab.util.Tools.get;
61 import static org.onlab.util.Tools.groupedThreads; 63 import static org.onlab.util.Tools.groupedThreads;
62 -import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_CURRENT;
63 -import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_PREVIOUS;
64 import static org.slf4j.LoggerFactory.getLogger; 64 import static org.slf4j.LoggerFactory.getLogger;
65 65
66 /** 66 /**
...@@ -89,6 +89,9 @@ public class DistributedFlowStatisticStore implements FlowStatisticStore { ...@@ -89,6 +89,9 @@ public class DistributedFlowStatisticStore implements FlowStatisticStore {
89 private Map<ConnectPoint, Set<FlowEntry>> current = 89 private Map<ConnectPoint, Set<FlowEntry>> current =
90 new ConcurrentHashMap<>(); 90 new ConcurrentHashMap<>();
91 91
92 + public static final MessageSubject GET_CURRENT = new MessageSubject("peer-return-current");
93 + public static final MessageSubject GET_PREVIOUS = new MessageSubject("peer-return-previous");
94 +
92 protected static final StoreSerializer SERIALIZER = StoreSerializer.using(KryoNamespaces.API); 95 protected static final StoreSerializer SERIALIZER = StoreSerializer.using(KryoNamespaces.API);
93 96
94 private NodeId local; 97 private NodeId local;
......
...@@ -38,6 +38,7 @@ import org.onosproject.net.flow.instructions.Instruction; ...@@ -38,6 +38,7 @@ import org.onosproject.net.flow.instructions.Instruction;
38 import org.onosproject.net.flow.instructions.Instructions; 38 import org.onosproject.net.flow.instructions.Instructions;
39 import org.onosproject.net.statistic.StatisticStore; 39 import org.onosproject.net.statistic.StatisticStore;
40 import org.onosproject.store.cluster.messaging.ClusterCommunicationService; 40 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
41 +import org.onosproject.store.cluster.messaging.MessageSubject;
41 import org.onosproject.store.serializers.KryoNamespaces; 42 import org.onosproject.store.serializers.KryoNamespaces;
42 import org.onosproject.store.serializers.StoreSerializer; 43 import org.onosproject.store.serializers.StoreSerializer;
43 import org.osgi.service.component.ComponentContext; 44 import org.osgi.service.component.ComponentContext;
...@@ -59,8 +60,6 @@ import static com.google.common.base.Preconditions.checkArgument; ...@@ -59,8 +60,6 @@ import static com.google.common.base.Preconditions.checkArgument;
59 import static com.google.common.base.Strings.isNullOrEmpty; 60 import static com.google.common.base.Strings.isNullOrEmpty;
60 import static org.onlab.util.Tools.get; 61 import static org.onlab.util.Tools.get;
61 import static org.onlab.util.Tools.groupedThreads; 62 import static org.onlab.util.Tools.groupedThreads;
62 -import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_CURRENT;
63 -import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_PREVIOUS;
64 import static org.slf4j.LoggerFactory.getLogger; 63 import static org.slf4j.LoggerFactory.getLogger;
65 64
66 65
...@@ -85,6 +84,9 @@ public class DistributedStatisticStore implements StatisticStore { ...@@ -85,6 +84,9 @@ public class DistributedStatisticStore implements StatisticStore {
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected ClusterService clusterService; 85 protected ClusterService clusterService;
87 86
87 + public static final MessageSubject GET_CURRENT = new MessageSubject("peer-return-current");
88 + public static final MessageSubject GET_PREVIOUS = new MessageSubject("peer-return-previous");
89 +
88 private Map<ConnectPoint, InternalStatisticRepresentation> representations = 90 private Map<ConnectPoint, InternalStatisticRepresentation> representations =
89 new ConcurrentHashMap<>(); 91 new ConcurrentHashMap<>();
90 92
......
1 -/*
2 - * Copyright 2014-present 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.statistic.impl;
17 -
18 -import org.onosproject.store.cluster.messaging.MessageSubject;
19 -
20 -/**
21 - * MessageSubjects used by DistributedStatisticStore peer-peer communication.
22 - */
23 -public final class StatisticStoreMessageSubjects {
24 - private StatisticStoreMessageSubjects() {}
25 - public static final MessageSubject GET_CURRENT =
26 - new MessageSubject("peer-return-current");
27 - public static final MessageSubject GET_PREVIOUS =
28 - new MessageSubject("peer-return-previous");
29 -
30 -}
1 -/*
2 - * Copyright 2014-present 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.cluster.messaging.impl;
17 -
18 -import org.junit.After;
19 -import org.junit.Before;
20 -import org.junit.Ignore;
21 -import org.junit.Test;
22 -import org.onosproject.cluster.DefaultControllerNode;
23 -import org.onosproject.cluster.NodeId;
24 -import org.onosproject.store.cluster.impl.ClusterNodesDelegate;
25 -import org.onlab.packet.IpAddress;
26 -
27 -import java.util.concurrent.CountDownLatch;
28 -import java.util.concurrent.TimeUnit;
29 -
30 -import static org.junit.Assert.assertEquals;
31 -import static org.junit.Assert.assertTrue;
32 -
33 -/**
34 - * Tests of the cluster communication manager.
35 - */
36 -public class ClusterCommunicationManagerTest {
37 -
38 - private static final NodeId N1 = new NodeId("n1");
39 - private static final NodeId N2 = new NodeId("n2");
40 -
41 - private static final int P1 = 9881;
42 - private static final int P2 = 9882;
43 -
44 - private static final IpAddress IP = IpAddress.valueOf("127.0.0.1");
45 -
46 - private ClusterCommunicationManager ccm1;
47 - private ClusterCommunicationManager ccm2;
48 -
49 - private TestDelegate cnd1 = new TestDelegate();
50 - private TestDelegate cnd2 = new TestDelegate();
51 -
52 - private DefaultControllerNode node1 = new DefaultControllerNode(N1, IP, P1);
53 - private DefaultControllerNode node2 = new DefaultControllerNode(N2, IP, P2);
54 -
55 - @Before
56 - public void setUp() throws Exception {
57 -
58 - NettyMessagingManager messagingService = new NettyMessagingManager();
59 - messagingService.activate();
60 -
61 - ccm1 = new ClusterCommunicationManager();
62 - ccm1.activate();
63 -
64 - ccm2 = new ClusterCommunicationManager();
65 - ccm2.activate();
66 -
67 -// ccm1.initialize(node1, cnd1);
68 -// ccm2.initialize(node2, cnd2);
69 - }
70 -
71 - @After
72 - public void tearDown() {
73 - ccm1.deactivate();
74 - ccm2.deactivate();
75 - }
76 -
77 - @Ignore("FIXME: failing randomly?")
78 - @Test
79 - public void connect() throws Exception {
80 - cnd1.latch = new CountDownLatch(1);
81 - cnd2.latch = new CountDownLatch(1);
82 -
83 -// ccm1.addNode(node2);
84 - validateDelegateEvent(cnd1, Op.DETECTED, node2.id());
85 - validateDelegateEvent(cnd2, Op.DETECTED, node1.id());
86 - }
87 -
88 - @Test
89 - @Ignore
90 - public void disconnect() throws Exception {
91 - cnd1.latch = new CountDownLatch(1);
92 - cnd2.latch = new CountDownLatch(1);
93 -
94 -// ccm1.addNode(node2);
95 - validateDelegateEvent(cnd1, Op.DETECTED, node2.id());
96 - validateDelegateEvent(cnd2, Op.DETECTED, node1.id());
97 -
98 - cnd1.latch = new CountDownLatch(1);
99 - cnd2.latch = new CountDownLatch(1);
100 - ccm1.deactivate();
101 -//
102 -// validateDelegateEvent(cnd2, Op.VANISHED, node1.id());
103 - }
104 -
105 - private void validateDelegateEvent(TestDelegate delegate, Op op, NodeId nodeId)
106 - throws InterruptedException {
107 - assertTrue("did not connect in time", delegate.latch.await(2500, TimeUnit.MILLISECONDS));
108 - assertEquals("incorrect event", op, delegate.op);
109 - assertEquals("incorrect event node", nodeId, delegate.nodeId);
110 - }
111 -
112 - enum Op { DETECTED, VANISHED, REMOVED }
113 -
114 - private class TestDelegate implements ClusterNodesDelegate {
115 -
116 - Op op;
117 - CountDownLatch latch;
118 - NodeId nodeId;
119 -
120 - @Override
121 - public DefaultControllerNode nodeDetected(NodeId nodeId, IpAddress ip, int tcpPort) {
122 - latch(nodeId, Op.DETECTED);
123 - return new DefaultControllerNode(nodeId, ip, tcpPort);
124 - }
125 -
126 - @Override
127 - public void nodeVanished(NodeId nodeId) {
128 - latch(nodeId, Op.VANISHED);
129 - }
130 -
131 - @Override
132 - public void nodeRemoved(NodeId nodeId) {
133 - latch(nodeId, Op.REMOVED);
134 - }
135 -
136 - private void latch(NodeId nodeId, Op op) {
137 - this.op = op;
138 - this.nodeId = nodeId;
139 - latch.countDown();
140 - }
141 - }
142 -}
...@@ -17,7 +17,6 @@ package org.onosproject.store.link.impl; ...@@ -17,7 +17,6 @@ package org.onosproject.store.link.impl;
17 17
18 import com.google.common.collect.Iterables; 18 import com.google.common.collect.Iterables;
19 19
20 -import org.easymock.Capture;
21 import org.junit.After; 20 import org.junit.After;
22 import org.junit.AfterClass; 21 import org.junit.AfterClass;
23 import org.junit.Before; 22 import org.junit.Before;
...@@ -59,8 +58,6 @@ import java.util.concurrent.CountDownLatch; ...@@ -59,8 +58,6 @@ import java.util.concurrent.CountDownLatch;
59 import java.util.concurrent.ExecutorService; 58 import java.util.concurrent.ExecutorService;
60 import java.util.concurrent.TimeUnit; 59 import java.util.concurrent.TimeUnit;
61 import java.util.concurrent.atomic.AtomicLong; 60 import java.util.concurrent.atomic.AtomicLong;
62 -import java.util.function.Function;
63 -
64 import static org.easymock.EasyMock.*; 61 import static org.easymock.EasyMock.*;
65 import static org.junit.Assert.*; 62 import static org.junit.Assert.*;
66 import static org.onosproject.cluster.ControllerNode.State.ACTIVE; 63 import static org.onosproject.cluster.ControllerNode.State.ACTIVE;
...@@ -76,7 +73,8 @@ import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED; ...@@ -76,7 +73,8 @@ import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
76 /** 73 /**
77 * Test of the GossipLinkStoreTest implementation. 74 * Test of the GossipLinkStoreTest implementation.
78 */ 75 */
79 -public class GossipLinkStoreTest { 76 +@Ignore
77 +public class ECLinkStoreTest {
80 78
81 private static final ProviderId PID = new ProviderId("of", "foo"); 79 private static final ProviderId PID = new ProviderId("of", "foo");
82 private static final ProviderId PIDA = new ProviderId("of", "bar", true); 80 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
...@@ -114,10 +112,9 @@ public class GossipLinkStoreTest { ...@@ -114,10 +112,9 @@ public class GossipLinkStoreTest {
114 private static final ControllerNode ONOS2 = 112 private static final ControllerNode ONOS2 =
115 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2")); 113 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2"));
116 114
117 - private GossipLinkStore linkStoreImpl; 115 + private ECLinkStore linkStoreImpl;
118 private LinkStore linkStore; 116 private LinkStore linkStore;
119 117
120 - private final AtomicLong ticker = new AtomicLong();
121 private DeviceClockService deviceClockService; 118 private DeviceClockService deviceClockService;
122 private ClusterCommunicationService clusterCommunicator; 119 private ClusterCommunicationService clusterCommunicator;
123 120
...@@ -139,7 +136,7 @@ public class GossipLinkStoreTest { ...@@ -139,7 +136,7 @@ public class GossipLinkStoreTest {
139 expectLastCall().anyTimes(); 136 expectLastCall().anyTimes();
140 replay(clusterCommunicator); 137 replay(clusterCommunicator);
141 138
142 - linkStoreImpl = new GossipLinkStore(); 139 + linkStoreImpl = new ECLinkStore();
143 linkStoreImpl.deviceClockService = deviceClockService; 140 linkStoreImpl.deviceClockService = deviceClockService;
144 linkStoreImpl.clusterCommunicator = clusterCommunicator; 141 linkStoreImpl.clusterCommunicator = clusterCommunicator;
145 linkStoreImpl.clusterService = new TestClusterService(); 142 linkStoreImpl.clusterService = new TestClusterService();
...@@ -163,28 +160,10 @@ public class GossipLinkStoreTest { ...@@ -163,28 +160,10 @@ public class GossipLinkStoreTest {
163 SparseAnnotations... annotations) { 160 SparseAnnotations... annotations) {
164 ConnectPoint src = new ConnectPoint(srcId, srcNum); 161 ConnectPoint src = new ConnectPoint(srcId, srcNum);
165 ConnectPoint dst = new ConnectPoint(dstId, dstNum); 162 ConnectPoint dst = new ConnectPoint(dstId, dstNum);
166 - reset(clusterCommunicator);
167 - clusterCommunicator.<InternalLinkEvent>broadcast(
168 - anyObject(InternalLinkEvent.class), anyObject(MessageSubject.class), anyObject(Function.class));
169 - expectLastCall().anyTimes();
170 - replay(clusterCommunicator);
171 linkStore.createOrUpdateLink(PID, new DefaultLinkDescription(src, dst, type, annotations)); 163 linkStore.createOrUpdateLink(PID, new DefaultLinkDescription(src, dst, type, annotations));
172 verify(clusterCommunicator); 164 verify(clusterCommunicator);
173 } 165 }
174 166
175 - private <T> void resetCommunicatorExpectingSingleBroadcast(
176 - Capture<T> message,
177 - Capture<MessageSubject> subject,
178 - Capture<Function<T, byte[]>> encoder) {
179 - message.reset();
180 - subject.reset();
181 - encoder.reset();
182 - reset(clusterCommunicator);
183 - clusterCommunicator.broadcast(capture(message), capture(subject), capture(encoder));
184 - expectLastCall().once();
185 - replay(clusterCommunicator);
186 - }
187 -
188 private void putLink(LinkKey key, Type type, SparseAnnotations... annotations) { 167 private void putLink(LinkKey key, Type type, SparseAnnotations... annotations) {
189 putLink(key.src().deviceId(), key.src().port(), 168 putLink(key.src().deviceId(), key.src().port(),
190 key.dst().deviceId(), key.dst().port(), 169 key.dst().deviceId(), key.dst().port(),
...@@ -358,57 +337,26 @@ public class GossipLinkStoreTest { ...@@ -358,57 +337,26 @@ public class GossipLinkStoreTest {
358 ConnectPoint src = new ConnectPoint(DID1, P1); 337 ConnectPoint src = new ConnectPoint(DID1, P1);
359 ConnectPoint dst = new ConnectPoint(DID2, P2); 338 ConnectPoint dst = new ConnectPoint(DID2, P2);
360 339
361 - Capture<InternalLinkEvent> message = new Capture<>();
362 - Capture<MessageSubject> subject = new Capture<>();
363 - Capture<Function<InternalLinkEvent, byte[]>> encoder = new Capture<>();
364 -
365 - // add link
366 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
367 final DefaultLinkDescription linkDescription = new DefaultLinkDescription(src, dst, INDIRECT); 340 final DefaultLinkDescription linkDescription = new DefaultLinkDescription(src, dst, INDIRECT);
368 LinkEvent event = linkStore.createOrUpdateLink(PID, 341 LinkEvent event = linkStore.createOrUpdateLink(PID,
369 linkDescription); 342 linkDescription);
370 - verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, message, subject, encoder);
371 343
372 assertLink(DID1, P1, DID2, P2, INDIRECT, event.subject()); 344 assertLink(DID1, P1, DID2, P2, INDIRECT, event.subject());
373 assertEquals(LINK_ADDED, event.type()); 345 assertEquals(LINK_ADDED, event.type());
374 346
375 - // update link type
376 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
377 LinkEvent event2 = linkStore.createOrUpdateLink(PID, 347 LinkEvent event2 = linkStore.createOrUpdateLink(PID,
378 new DefaultLinkDescription(src, dst, DIRECT)); 348 new DefaultLinkDescription(src, dst, DIRECT));
379 - verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder);
380 349
381 assertLink(DID1, P1, DID2, P2, DIRECT, event2.subject()); 350 assertLink(DID1, P1, DID2, P2, DIRECT, event2.subject());
382 assertEquals(LINK_UPDATED, event2.type()); 351 assertEquals(LINK_UPDATED, event2.type());
383 352
384 // no change 353 // no change
385 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
386 LinkEvent event3 = linkStore.createOrUpdateLink(PID, 354 LinkEvent event3 = linkStore.createOrUpdateLink(PID,
387 new DefaultLinkDescription(src, dst, DIRECT)); 355 new DefaultLinkDescription(src, dst, DIRECT));
388 - verifyNoBroadcastMessage(message);
389 356
390 assertNull("No change event expected", event3); 357 assertNull("No change event expected", event3);
391 } 358 }
392 359
393 - private <T> void verifyNoBroadcastMessage(Capture<T> message) {
394 - assertFalse("No broadcast expected", message.hasCaptured());
395 - }
396 -
397 - private void verifyLinkBroadcastMessage(ProviderId providerId,
398 - NodeId sender,
399 - ConnectPoint src,
400 - ConnectPoint dst,
401 - Type type,
402 - Capture<InternalLinkEvent> actualLinkEvent,
403 - Capture<MessageSubject> actualSubject,
404 - Capture<Function<InternalLinkEvent, byte[]>> actualEncoder) {
405 - verify(clusterCommunicator);
406 - assertTrue(actualLinkEvent.hasCaptured());
407 - assertEquals(GossipLinkStoreMessageSubjects.LINK_UPDATE, actualSubject.getValue());
408 - assertEquals(providerId, actualLinkEvent.getValue().providerId());
409 - assertLinkDescriptionEquals(src, dst, type, actualLinkEvent.getValue().linkDescription().value());
410 - }
411 -
412 private static void assertLinkDescriptionEquals(ConnectPoint src, 360 private static void assertLinkDescriptionEquals(ConnectPoint src,
413 ConnectPoint dst, 361 ConnectPoint dst,
414 Type type, 362 Type type,
...@@ -424,33 +372,23 @@ public class GossipLinkStoreTest { ...@@ -424,33 +372,23 @@ public class GossipLinkStoreTest {
424 ConnectPoint src = new ConnectPoint(DID1, P1); 372 ConnectPoint src = new ConnectPoint(DID1, P1);
425 ConnectPoint dst = new ConnectPoint(DID2, P2); 373 ConnectPoint dst = new ConnectPoint(DID2, P2);
426 374
427 - Capture<InternalLinkEvent> message = new Capture<>();
428 - Capture<MessageSubject> subject = new Capture<>();
429 - Capture<Function<InternalLinkEvent, byte[]>> encoder = new Capture<>();
430 -
431 // add Ancillary link 375 // add Ancillary link
432 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
433 LinkEvent event = linkStore.createOrUpdateLink(PIDA, 376 LinkEvent event = linkStore.createOrUpdateLink(PIDA,
434 new DefaultLinkDescription(src, dst, INDIRECT, A1)); 377 new DefaultLinkDescription(src, dst, INDIRECT, A1));
435 - verifyLinkBroadcastMessage(PIDA, NID1, src, dst, INDIRECT, message, subject, encoder);
436 378
437 assertNotNull("Ancillary only link is ignored", event); 379 assertNotNull("Ancillary only link is ignored", event);
438 380
439 // add Primary link 381 // add Primary link
440 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
441 LinkEvent event2 = linkStore.createOrUpdateLink(PID, 382 LinkEvent event2 = linkStore.createOrUpdateLink(PID,
442 new DefaultLinkDescription(src, dst, INDIRECT, A2)); 383 new DefaultLinkDescription(src, dst, INDIRECT, A2));
443 - verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, message, subject, encoder);
444 384
445 assertLink(DID1, P1, DID2, P2, INDIRECT, event2.subject()); 385 assertLink(DID1, P1, DID2, P2, INDIRECT, event2.subject());
446 assertAnnotationsEquals(event2.subject().annotations(), A2, A1); 386 assertAnnotationsEquals(event2.subject().annotations(), A2, A1);
447 assertEquals(LINK_UPDATED, event2.type()); 387 assertEquals(LINK_UPDATED, event2.type());
448 388
449 // update link type 389 // update link type
450 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
451 LinkEvent event3 = linkStore.createOrUpdateLink(PID, 390 LinkEvent event3 = linkStore.createOrUpdateLink(PID,
452 new DefaultLinkDescription(src, dst, DIRECT, A2)); 391 new DefaultLinkDescription(src, dst, DIRECT, A2));
453 - verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder);
454 392
455 assertLink(DID1, P1, DID2, P2, DIRECT, event3.subject()); 393 assertLink(DID1, P1, DID2, P2, DIRECT, event3.subject());
456 assertAnnotationsEquals(event3.subject().annotations(), A2, A1); 394 assertAnnotationsEquals(event3.subject().annotations(), A2, A1);
...@@ -458,38 +396,30 @@ public class GossipLinkStoreTest { ...@@ -458,38 +396,30 @@ public class GossipLinkStoreTest {
458 396
459 397
460 // no change 398 // no change
461 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
462 LinkEvent event4 = linkStore.createOrUpdateLink(PID, 399 LinkEvent event4 = linkStore.createOrUpdateLink(PID,
463 new DefaultLinkDescription(src, dst, DIRECT)); 400 new DefaultLinkDescription(src, dst, DIRECT));
464 - verifyNoBroadcastMessage(message);
465 401
466 assertNull("No change event expected", event4); 402 assertNull("No change event expected", event4);
467 403
468 // update link annotation (Primary) 404 // update link annotation (Primary)
469 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
470 LinkEvent event5 = linkStore.createOrUpdateLink(PID, 405 LinkEvent event5 = linkStore.createOrUpdateLink(PID,
471 new DefaultLinkDescription(src, dst, DIRECT, A2_2)); 406 new DefaultLinkDescription(src, dst, DIRECT, A2_2));
472 - verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder);
473 407
474 assertLink(DID1, P1, DID2, P2, DIRECT, event5.subject()); 408 assertLink(DID1, P1, DID2, P2, DIRECT, event5.subject());
475 assertAnnotationsEquals(event5.subject().annotations(), A2, A2_2, A1); 409 assertAnnotationsEquals(event5.subject().annotations(), A2, A2_2, A1);
476 assertEquals(LINK_UPDATED, event5.type()); 410 assertEquals(LINK_UPDATED, event5.type());
477 411
478 // update link annotation (Ancillary) 412 // update link annotation (Ancillary)
479 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
480 LinkEvent event6 = linkStore.createOrUpdateLink(PIDA, 413 LinkEvent event6 = linkStore.createOrUpdateLink(PIDA,
481 new DefaultLinkDescription(src, dst, DIRECT, A1_2)); 414 new DefaultLinkDescription(src, dst, DIRECT, A1_2));
482 - verifyLinkBroadcastMessage(PIDA, NID1, src, dst, DIRECT, message, subject, encoder);
483 415
484 assertLink(DID1, P1, DID2, P2, DIRECT, event6.subject()); 416 assertLink(DID1, P1, DID2, P2, DIRECT, event6.subject());
485 assertAnnotationsEquals(event6.subject().annotations(), A2, A2_2, A1, A1_2); 417 assertAnnotationsEquals(event6.subject().annotations(), A2, A2_2, A1, A1_2);
486 assertEquals(LINK_UPDATED, event6.type()); 418 assertEquals(LINK_UPDATED, event6.type());
487 419
488 // update link type (Ancillary) : ignored 420 // update link type (Ancillary) : ignored
489 - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
490 LinkEvent event7 = linkStore.createOrUpdateLink(PIDA, 421 LinkEvent event7 = linkStore.createOrUpdateLink(PIDA,
491 new DefaultLinkDescription(src, dst, EDGE)); 422 new DefaultLinkDescription(src, dst, EDGE));
492 - verifyNoBroadcastMessage(message);
493 assertNull("Ancillary change other than annotation is ignored", event7); 423 assertNull("Ancillary change other than annotation is ignored", event7);
494 } 424 }
495 425
......
1 -/*
2 - * Copyright 2014-present 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.link.impl;
17 -
18 -import static org.onosproject.net.DeviceId.deviceId;
19 -
20 -import org.junit.Test;
21 -import org.onosproject.net.ConnectPoint;
22 -import org.onosproject.net.DeviceId;
23 -import org.onosproject.net.LinkKey;
24 -import org.onosproject.net.PortNumber;
25 -import org.onosproject.net.provider.ProviderId;
26 -import com.google.common.testing.EqualsTester;
27 -
28 -public class LinkFragmentIdTest {
29 -
30 - private static final ProviderId PID = new ProviderId("of", "foo");
31 - private static final ProviderId PIDA = new ProviderId("of", "bar", true);
32 -
33 - private static final DeviceId DID1 = deviceId("of:foo");
34 - private static final DeviceId DID2 = deviceId("of:bar");
35 -
36 - private static final PortNumber P1 = PortNumber.portNumber(1);
37 - private static final PortNumber P2 = PortNumber.portNumber(2);
38 - private static final PortNumber P3 = PortNumber.portNumber(3);
39 -
40 - private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
41 - private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2);
42 -
43 - private static final ConnectPoint CP3 = new ConnectPoint(DID1, P2);
44 - private static final ConnectPoint CP4 = new ConnectPoint(DID2, P3);
45 -
46 - private static final LinkKey L1 = LinkKey.linkKey(CP1, CP2);
47 - private static final LinkKey L2 = LinkKey.linkKey(CP3, CP4);
48 -
49 - @Test
50 - public void testEquals() {
51 - new EqualsTester()
52 - .addEqualityGroup(new LinkFragmentId(L1, PID),
53 - new LinkFragmentId(L1, PID))
54 - .addEqualityGroup(new LinkFragmentId(L2, PID),
55 - new LinkFragmentId(L2, PID))
56 - .addEqualityGroup(new LinkFragmentId(L1, PIDA),
57 - new LinkFragmentId(L1, PIDA))
58 - .addEqualityGroup(new LinkFragmentId(L2, PIDA),
59 - new LinkFragmentId(L2, PIDA))
60 - .testEquals();
61 - }
62 -
63 -}
1 -/*
2 - * Copyright 2014-present 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.mastership.impl;
17 -
18 -import static org.junit.Assert.assertEquals;
19 -import static org.junit.Assert.assertTrue;
20 -import static org.onosproject.net.MastershipRole.*;
21 -
22 -import org.junit.Test;
23 -import org.onosproject.cluster.NodeId;
24 -
25 -import com.google.common.collect.Sets;
26 -
27 -public class RoleValueTest {
28 -
29 - private static final RoleValue RV = new RoleValue();
30 -
31 - private static final NodeId NID1 = new NodeId("node1");
32 - private static final NodeId NID2 = new NodeId("node2");
33 - private static final NodeId NID3 = new NodeId("node3");
34 -
35 - @Test
36 - public void add() {
37 - assertEquals("faulty initialization: ", 3, RV.value.size());
38 - RV.add(MASTER, NID1);
39 - RV.add(STANDBY, NID2);
40 - RV.add(STANDBY, NID3);
41 -
42 - assertEquals("wrong nodeID: ", NID1, RV.get(MASTER));
43 - assertTrue("wrong nodeIDs: ",
44 - Sets.newHashSet(NID3, NID2).containsAll(RV.nodesOfRole(STANDBY)));
45 - }
46 -}