Brian O'Connor
Committed by Ray Milkey

Updates to ECM interface

Change-Id: Ie0cae42ac2b361cf3b94e5047c157cb0945f4209

Adding origin to IntentData and use it to pick GossipIntentStore peer

Change-Id: I50e9621a69a35ec02b8c8dd79cc926591e5a73e9
...@@ -84,14 +84,13 @@ public class IntentRemoveCommand extends AbstractShellCommand { ...@@ -84,14 +84,13 @@ public class IntentRemoveCommand extends AbstractShellCommand {
84 Key key = Key.of(new BigInteger(id, 16).longValue(), appId); 84 Key key = Key.of(new BigInteger(id, 16).longValue(), appId);
85 Intent intent = intentService.getIntent(key); 85 Intent intent = intentService.getIntent(key);
86 86
87 -
88 if (intent != null) { 87 if (intent != null) {
89 // set up latch and listener to track uninstall progress 88 // set up latch and listener to track uninstall progress
90 CountDownLatch latch = new CountDownLatch(1); 89 CountDownLatch latch = new CountDownLatch(1);
91 IntentListener listener = (IntentEvent event) -> { 90 IntentListener listener = (IntentEvent event) -> {
92 if (Objects.equals(event.subject().key(), key) && 91 if (Objects.equals(event.subject().key(), key) &&
93 - (event.type() == IntentEvent.Type.WITHDRAWN 92 + (event.type() == IntentEvent.Type.WITHDRAWN ||
94 - || event.type() == IntentEvent.Type.WITHDRAWN)) { 93 + event.type() == IntentEvent.Type.FAILED)) {
95 latch.countDown(); 94 latch.countDown();
96 } 95 }
97 }; 96 };
......
...@@ -17,6 +17,7 @@ package org.onosproject.net.intent; ...@@ -17,6 +17,7 @@ package org.onosproject.net.intent;
17 17
18 import com.google.common.base.MoreObjects; 18 import com.google.common.base.MoreObjects;
19 import com.google.common.collect.ImmutableList; 19 import com.google.common.collect.ImmutableList;
20 +import org.onosproject.cluster.NodeId;
20 import org.onosproject.store.Timestamp; 21 import org.onosproject.store.Timestamp;
21 22
22 import java.util.List; 23 import java.util.List;
...@@ -32,6 +33,7 @@ public class IntentData { //FIXME need to make this "immutable" ...@@ -32,6 +33,7 @@ public class IntentData { //FIXME need to make this "immutable"
32 33
33 private IntentState state; 34 private IntentState state;
34 private Timestamp version; 35 private Timestamp version;
36 + private NodeId origin;
35 37
36 private List<Intent> installables; 38 private List<Intent> installables;
37 39
...@@ -61,6 +63,19 @@ public class IntentData { //FIXME need to make this "immutable" ...@@ -61,6 +63,19 @@ public class IntentData { //FIXME need to make this "immutable"
61 return version; 63 return version;
62 } 64 }
63 65
66 + /**
67 + * Sets the origin, which is the node that created the instance.
68 + *
69 + * @param origin origin instance
70 + */
71 + public void setOrigin(NodeId origin) {
72 + this.origin = origin;
73 + }
74 +
75 + public NodeId origin() {
76 + return origin;
77 + }
78 +
64 public void setState(IntentState newState) { 79 public void setState(IntentState newState) {
65 this.state = newState; 80 this.state = newState;
66 } 81 }
......
...@@ -16,11 +16,9 @@ ...@@ -16,11 +16,9 @@
16 package org.onosproject.store.cluster.messaging; 16 package org.onosproject.store.cluster.messaging;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 -
20 import org.onosproject.cluster.NodeId; 19 import org.onosproject.cluster.NodeId;
21 20
22 import java.io.IOException; 21 import java.io.IOException;
23 -import java.util.Set;
24 import java.util.concurrent.ExecutorService; 22 import java.util.concurrent.ExecutorService;
25 23
26 // TODO: remove IOExceptions? 24 // TODO: remove IOExceptions?
...@@ -51,9 +49,8 @@ public interface ClusterCommunicationService { ...@@ -51,9 +49,8 @@ public interface ClusterCommunicationService {
51 * @param message message to send 49 * @param message message to send
52 * @param toNodeId node identifier 50 * @param toNodeId node identifier
53 * @return true if the message was sent successfully; false otherwise. 51 * @return true if the message was sent successfully; false otherwise.
54 - * @throws IOException when I/O exception of some sort has occurred
55 */ 52 */
56 - boolean unicast(ClusterMessage message, NodeId toNodeId) throws IOException; 53 + boolean unicast(ClusterMessage message, NodeId toNodeId);
57 54
58 /** 55 /**
59 * Multicast a message to a set of controller nodes. 56 * Multicast a message to a set of controller nodes.
...@@ -62,7 +59,7 @@ public interface ClusterCommunicationService { ...@@ -62,7 +59,7 @@ public interface ClusterCommunicationService {
62 * @param nodeIds recipient node identifiers 59 * @param nodeIds recipient node identifiers
63 * @return true if the message was sent successfully to all nodes in the group; false otherwise. 60 * @return true if the message was sent successfully to all nodes in the group; false otherwise.
64 */ 61 */
65 - boolean multicast(ClusterMessage message, Set<NodeId> nodeIds); 62 + boolean multicast(ClusterMessage message, Iterable<NodeId> nodeIds);
66 63
67 /** 64 /**
68 * Sends a message synchronously. 65 * Sends a message synchronously.
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
16 package org.onosproject.store.cluster.messaging.impl; 16 package org.onosproject.store.cluster.messaging.impl;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 -
20 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
22 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -39,7 +38,6 @@ import org.slf4j.Logger; ...@@ -39,7 +38,6 @@ import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory; 38 import org.slf4j.LoggerFactory;
40 39
41 import java.io.IOException; 40 import java.io.IOException;
42 -import java.util.Set;
43 import java.util.concurrent.ExecutorService; 41 import java.util.concurrent.ExecutorService;
44 42
45 import static com.google.common.base.Preconditions.checkArgument; 43 import static com.google.common.base.Preconditions.checkArgument;
...@@ -107,7 +105,7 @@ public class ClusterCommunicationManager ...@@ -107,7 +105,7 @@ public class ClusterCommunicationManager
107 } 105 }
108 106
109 @Override 107 @Override
110 - public boolean multicast(ClusterMessage message, Set<NodeId> nodes) { 108 + public boolean multicast(ClusterMessage message, Iterable<NodeId> nodes) {
111 boolean ok = true; 109 boolean ok = true;
112 final ControllerNode localNode = clusterService.getLocalNode(); 110 final ControllerNode localNode = clusterService.getLocalNode();
113 byte[] payload = message.getBytes(); 111 byte[] payload = message.getBytes();
...@@ -120,8 +118,8 @@ public class ClusterCommunicationManager ...@@ -120,8 +118,8 @@ public class ClusterCommunicationManager
120 } 118 }
121 119
122 @Override 120 @Override
123 - public boolean unicast(ClusterMessage message, NodeId toNodeId) throws IOException { 121 + public boolean unicast(ClusterMessage message, NodeId toNodeId) {
124 - return unicast(message.subject(), message.getBytes(), toNodeId); 122 + return unicastUnchecked(message.subject(), message.getBytes(), toNodeId);
125 } 123 }
126 124
127 private boolean unicast(MessageSubject subject, byte[] payload, NodeId toNodeId) throws IOException { 125 private boolean unicast(MessageSubject subject, byte[] payload, NodeId toNodeId) throws IOException {
...@@ -137,7 +135,6 @@ public class ClusterCommunicationManager ...@@ -137,7 +135,6 @@ public class ClusterCommunicationManager
137 } 135 }
138 } 136 }
139 137
140 -
141 private boolean unicastUnchecked(MessageSubject subject, byte[] payload, NodeId toNodeId) { 138 private boolean unicastUnchecked(MessageSubject subject, byte[] payload, NodeId toNodeId) {
142 try { 139 try {
143 return unicast(subject, payload, toNodeId); 140 return unicast(subject, payload, toNodeId);
......
...@@ -21,7 +21,6 @@ import com.google.common.collect.FluentIterable; ...@@ -21,7 +21,6 @@ import com.google.common.collect.FluentIterable;
21 import com.google.common.collect.ImmutableList; 21 import com.google.common.collect.ImmutableList;
22 import com.google.common.collect.Maps; 22 import com.google.common.collect.Maps;
23 import com.google.common.collect.Sets; 23 import com.google.common.collect.Sets;
24 -
25 import org.apache.commons.lang3.RandomUtils; 24 import org.apache.commons.lang3.RandomUtils;
26 import org.apache.felix.scr.annotations.Activate; 25 import org.apache.felix.scr.annotations.Activate;
27 import org.apache.felix.scr.annotations.Component; 26 import org.apache.felix.scr.annotations.Component;
...@@ -305,14 +304,13 @@ public class GossipDeviceStore ...@@ -305,14 +304,13 @@ public class GossipDeviceStore
305 ClusterMessage clusterMessage = new ClusterMessage(localNode, DEVICE_INJECTED, 304 ClusterMessage clusterMessage = new ClusterMessage(localNode, DEVICE_INJECTED,
306 SERIALIZER.encode(deviceInjectedEvent)); 305 SERIALIZER.encode(deviceInjectedEvent));
307 306
308 - try { 307 + // TODO check unicast return value
309 clusterCommunicator.unicast(clusterMessage, deviceNode); 308 clusterCommunicator.unicast(clusterMessage, deviceNode);
310 - } catch (IOException e) { 309 + /* error log:
311 log.warn("Failed to process injected device id: {} desc: {} " + 310 log.warn("Failed to process injected device id: {} desc: {} " +
312 "(cluster messaging failed: {})", 311 "(cluster messaging failed: {})",
313 deviceId, deviceDescription, e); 312 deviceId, deviceDescription, e);
314 - } 313 + */
315 -
316 } 314 }
317 315
318 return deviceEvent; 316 return deviceEvent;
...@@ -556,13 +554,14 @@ public class GossipDeviceStore ...@@ -556,13 +554,14 @@ public class GossipDeviceStore
556 PortInjectedEvent portInjectedEvent = new PortInjectedEvent(providerId, deviceId, portDescriptions); 554 PortInjectedEvent portInjectedEvent = new PortInjectedEvent(providerId, deviceId, portDescriptions);
557 ClusterMessage clusterMessage = new ClusterMessage( 555 ClusterMessage clusterMessage = new ClusterMessage(
558 localNode, PORT_INJECTED, SERIALIZER.encode(portInjectedEvent)); 556 localNode, PORT_INJECTED, SERIALIZER.encode(portInjectedEvent));
559 - try { 557 +
558 + //TODO check unicast return value
560 clusterCommunicator.unicast(clusterMessage, deviceNode); 559 clusterCommunicator.unicast(clusterMessage, deviceNode);
561 - } catch (IOException e) { 560 + /* error log:
562 log.warn("Failed to process injected ports of device id: {} " + 561 log.warn("Failed to process injected ports of device id: {} " +
563 "(cluster messaging failed: {})", 562 "(cluster messaging failed: {})",
564 deviceId, e); 563 deviceId, e);
565 - } 564 + */
566 } 565 }
567 566
568 return deviceEvents == null ? Collections.emptyList() : deviceEvents; 567 return deviceEvents == null ? Collections.emptyList() : deviceEvents;
...@@ -842,11 +841,11 @@ public class GossipDeviceStore ...@@ -842,11 +841,11 @@ public class GossipDeviceStore
842 DEVICE_REMOVE_REQ, 841 DEVICE_REMOVE_REQ,
843 SERIALIZER.encode(deviceId)); 842 SERIALIZER.encode(deviceId));
844 843
845 - try { 844 + // TODO check unicast return value
846 clusterCommunicator.unicast(message, master); 845 clusterCommunicator.unicast(message, master);
847 - } catch (IOException e) { 846 + /* error log:
848 log.error("Failed to forward {} remove request to {}", deviceId, master, e); 847 log.error("Failed to forward {} remove request to {}", deviceId, master, e);
849 - } 848 + */
850 849
851 // event will be triggered after master processes it. 850 // event will be triggered after master processes it.
852 return null; 851 return null;
......
...@@ -29,6 +29,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -29,6 +29,7 @@ import org.apache.felix.scr.annotations.Deactivate;
29 import org.apache.felix.scr.annotations.Reference; 29 import org.apache.felix.scr.annotations.Reference;
30 import org.apache.felix.scr.annotations.ReferenceCardinality; 30 import org.apache.felix.scr.annotations.ReferenceCardinality;
31 import org.apache.felix.scr.annotations.Service; 31 import org.apache.felix.scr.annotations.Service;
32 +import org.onlab.util.BoundedThreadPool;
32 import org.onlab.util.KryoNamespace; 33 import org.onlab.util.KryoNamespace;
33 import org.onlab.util.NewConcurrentHashMap; 34 import org.onlab.util.NewConcurrentHashMap;
34 import org.onosproject.cluster.ClusterService; 35 import org.onosproject.cluster.ClusterService;
...@@ -138,7 +139,8 @@ public class DistributedFlowRuleStore ...@@ -138,7 +139,8 @@ public class DistributedFlowRuleStore
138 private ExecutorService messageHandlingExecutor; 139 private ExecutorService messageHandlingExecutor;
139 140
140 private final ExecutorService backupExecutors = 141 private final ExecutorService backupExecutors =
141 - Executors.newSingleThreadExecutor(groupedThreads("onos/flow", "async-backups")); 142 + BoundedThreadPool.newSingleThreadExecutor(groupedThreads("onos/flow", "async-backups"));
143 + //Executors.newSingleThreadExecutor(groupedThreads("onos/flow", "async-backups"));
142 144
143 private boolean syncBackup = false; 145 private boolean syncBackup = false;
144 146
...@@ -385,12 +387,8 @@ public class DistributedFlowRuleStore ...@@ -385,12 +387,8 @@ public class DistributedFlowRuleStore
385 SERIALIZER.encode(operation)); 387 SERIALIZER.encode(operation));
386 388
387 389
388 - try { 390 + if (!clusterCommunicator.unicast(message, replicaInfo.master().get())) {
389 - 391 + log.warn("Failed to storeBatch: {} to {}", message, replicaInfo.master());
390 - clusterCommunicator.unicast(message, replicaInfo.master().get());
391 -
392 - } catch (IOException e) {
393 - log.warn("Failed to storeBatch: {}", e.getMessage());
394 392
395 Set<FlowRule> allFailures = operation.getOperations().stream() 393 Set<FlowRule> allFailures = operation.getOperations().stream()
396 .map(op -> op.target()) 394 .map(op -> op.target())
...@@ -401,7 +399,6 @@ public class DistributedFlowRuleStore ...@@ -401,7 +399,6 @@ public class DistributedFlowRuleStore
401 new CompletedBatchOperation(false, allFailures, deviceId))); 399 new CompletedBatchOperation(false, allFailures, deviceId)));
402 return; 400 return;
403 } 401 }
404 -
405 } 402 }
406 403
407 private void storeBatchInternal(FlowRuleBatchOperation operation) { 404 private void storeBatchInternal(FlowRuleBatchOperation operation) {
...@@ -576,15 +573,13 @@ public class DistributedFlowRuleStore ...@@ -576,15 +573,13 @@ public class DistributedFlowRuleStore
576 if (nodeId == null) { 573 if (nodeId == null) {
577 notifyDelegate(event); 574 notifyDelegate(event);
578 } else { 575 } else {
579 - try {
580 ClusterMessage message = new ClusterMessage( 576 ClusterMessage message = new ClusterMessage(
581 clusterService.getLocalNode().id(), 577 clusterService.getLocalNode().id(),
582 REMOTE_APPLY_COMPLETED, 578 REMOTE_APPLY_COMPLETED,
583 SERIALIZER.encode(event)); 579 SERIALIZER.encode(event));
580 + // TODO check unicast return value
584 clusterCommunicator.unicast(message, nodeId); 581 clusterCommunicator.unicast(message, nodeId);
585 - } catch (IOException e) { 582 + //error log: log.warn("Failed to respond to peer for batch operation result");
586 - log.warn("Failed to respond to peer for batch operation result");
587 - }
588 } 583 }
589 } 584 }
590 585
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.store.intent.impl; 16 package org.onosproject.store.intent.impl;
17 17
18 +import com.google.common.collect.ImmutableList;
18 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
19 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -23,6 +24,8 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -23,6 +24,8 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.apache.felix.scr.annotations.Service; 24 import org.apache.felix.scr.annotations.Service;
24 import org.onlab.util.KryoNamespace; 25 import org.onlab.util.KryoNamespace;
25 import org.onosproject.cluster.ClusterService; 26 import org.onosproject.cluster.ClusterService;
27 +import org.onosproject.cluster.ControllerNode;
28 +import org.onosproject.cluster.NodeId;
26 import org.onosproject.net.intent.Intent; 29 import org.onosproject.net.intent.Intent;
27 import org.onosproject.net.intent.IntentData; 30 import org.onosproject.net.intent.IntentData;
28 import org.onosproject.net.intent.IntentEvent; 31 import org.onosproject.net.intent.IntentEvent;
...@@ -41,7 +44,10 @@ import org.onosproject.store.impl.WallClockTimestamp; ...@@ -41,7 +44,10 @@ import org.onosproject.store.impl.WallClockTimestamp;
41 import org.onosproject.store.serializers.KryoNamespaces; 44 import org.onosproject.store.serializers.KryoNamespaces;
42 import org.slf4j.Logger; 45 import org.slf4j.Logger;
43 46
47 +import java.util.ArrayList;
48 +import java.util.Collections;
44 import java.util.List; 49 import java.util.List;
50 +import java.util.Objects;
45 import java.util.stream.Collectors; 51 import java.util.stream.Collectors;
46 52
47 import static org.onosproject.net.intent.IntentState.*; 53 import static org.onosproject.net.intent.IntentState.*;
...@@ -51,6 +57,8 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -51,6 +57,8 @@ import static org.slf4j.LoggerFactory.getLogger;
51 * Manages inventory of Intents in a distributed data store that uses optimistic 57 * Manages inventory of Intents in a distributed data store that uses optimistic
52 * replication and gossip based techniques. 58 * replication and gossip based techniques.
53 */ 59 */
60 +//FIXME we should listen for leadership changes. if the local instance has just
61 +// ... become a leader, scan the pending map and process those
54 @Component(immediate = false, enabled = true) 62 @Component(immediate = false, enabled = true)
55 @Service 63 @Service
56 public class GossipIntentStore 64 public class GossipIntentStore
...@@ -86,15 +94,17 @@ public class GossipIntentStore ...@@ -86,15 +94,17 @@ public class GossipIntentStore
86 clusterService, 94 clusterService,
87 clusterCommunicator, 95 clusterCommunicator,
88 intentSerializer, 96 intentSerializer,
89 - new IntentDataLogicalClockManager<>()); 97 + new IntentDataLogicalClockManager<>(),
98 + (key, intentData) -> getPeerNodes(key, intentData));
90 99
91 pendingMap = new EventuallyConsistentMapImpl<>("intent-pending", 100 pendingMap = new EventuallyConsistentMapImpl<>("intent-pending",
92 clusterService, 101 clusterService,
93 clusterCommunicator, 102 clusterCommunicator,
94 intentSerializer, // TODO 103 intentSerializer, // TODO
95 - new IntentDataClockManager<>()); 104 + new IntentDataClockManager<>(),
105 + (key, intentData) -> getPeerNodes(key, intentData));
96 106
97 - currentMap.addListener(new InternalIntentStatesListener()); 107 + currentMap.addListener(new InternalCurrentListener());
98 pendingMap.addListener(new InternalPendingListener()); 108 pendingMap.addListener(new InternalPendingListener());
99 109
100 log.info("Started"); 110 log.info("Started");
...@@ -226,7 +236,6 @@ public class GossipIntentStore ...@@ -226,7 +236,6 @@ public class GossipIntentStore
226 @Override 236 @Override
227 public void write(IntentData newData) { 237 public void write(IntentData newData) {
228 IntentData currentData = currentMap.get(newData.key()); 238 IntentData currentData = currentMap.get(newData.key());
229 -
230 if (isUpdateAcceptable(currentData, newData)) { 239 if (isUpdateAcceptable(currentData, newData)) {
231 // Only the master is modifying the current state. Therefore assume 240 // Only the master is modifying the current state. Therefore assume
232 // this always succeeds 241 // this always succeeds
...@@ -239,6 +248,34 @@ public class GossipIntentStore ...@@ -239,6 +248,34 @@ public class GossipIntentStore
239 } 248 }
240 } 249 }
241 250
251 + private Iterable<NodeId> getPeerNodes(Key key, IntentData data) {
252 + NodeId master = partitionService.getLeader(key);
253 + NodeId origin = (data != null) ? data.origin() : null;
254 + NodeId me = clusterService.getLocalNode().id();
255 + boolean isMaster = Objects.equals(master, me);
256 + boolean isOrigin = Objects.equals(origin, me);
257 + if (isMaster && isOrigin) {
258 + return ImmutableList.of(getRandomNode());
259 + } else if (isMaster) {
260 + return ImmutableList.of(origin);
261 + } else if (isOrigin) {
262 + return ImmutableList.of(master);
263 + } else {
264 + // FIXME: why are we here? log error?
265 + return ImmutableList.of(master);
266 + }
267 + }
268 +
269 + private NodeId getRandomNode() {
270 + List<NodeId> nodes = clusterService.getNodes().stream()
271 + .map(ControllerNode::id)
272 + .collect(Collectors.toCollection(ArrayList::new));
273 + Collections.shuffle(nodes);
274 + // FIXME check if self
275 + // FIXME verify nodes.size() > 0
276 + return nodes.get(0);
277 + }
278 +
242 @Override 279 @Override
243 public void batchWrite(Iterable<IntentData> updates) { 280 public void batchWrite(Iterable<IntentData> updates) {
244 updates.forEach(this::write); 281 updates.forEach(this::write);
...@@ -263,6 +300,7 @@ public class GossipIntentStore ...@@ -263,6 +300,7 @@ public class GossipIntentStore
263 if (data.version() == null) { 300 if (data.version() == null) {
264 data.setVersion(new WallClockTimestamp()); 301 data.setVersion(new WallClockTimestamp());
265 } 302 }
303 + data.setOrigin(clusterService.getLocalNode().id());
266 pendingMap.put(data.key(), copyData(data)); 304 pendingMap.put(data.key(), copyData(data));
267 } 305 }
268 306
...@@ -292,7 +330,7 @@ public class GossipIntentStore ...@@ -292,7 +330,7 @@ public class GossipIntentStore
292 } 330 }
293 } 331 }
294 332
295 - private final class InternalIntentStatesListener implements 333 + private final class InternalCurrentListener implements
296 EventuallyConsistentMapListener<Key, IntentData> { 334 EventuallyConsistentMapListener<Key, IntentData> {
297 @Override 335 @Override
298 public void event( 336 public void event(
......
...@@ -29,13 +29,13 @@ import org.onosproject.cluster.Leadership; ...@@ -29,13 +29,13 @@ import org.onosproject.cluster.Leadership;
29 import org.onosproject.cluster.LeadershipEvent; 29 import org.onosproject.cluster.LeadershipEvent;
30 import org.onosproject.cluster.LeadershipEventListener; 30 import org.onosproject.cluster.LeadershipEventListener;
31 import org.onosproject.cluster.LeadershipService; 31 import org.onosproject.cluster.LeadershipService;
32 +import org.onosproject.cluster.NodeId;
32 import org.onosproject.net.intent.Key; 33 import org.onosproject.net.intent.Key;
33 import org.slf4j.Logger; 34 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory; 35 import org.slf4j.LoggerFactory;
35 36
36 -import com.google.common.base.Objects;
37 -
38 import java.util.List; 37 import java.util.List;
38 +import java.util.Objects;
39 import java.util.concurrent.Executors; 39 import java.util.concurrent.Executors;
40 import java.util.concurrent.ScheduledExecutorService; 40 import java.util.concurrent.ScheduledExecutorService;
41 import java.util.concurrent.TimeUnit; 41 import java.util.concurrent.TimeUnit;
...@@ -109,10 +109,15 @@ public class PartitionManager implements PartitionService { ...@@ -109,10 +109,15 @@ public class PartitionManager implements PartitionService {
109 109
110 @Override 110 @Override
111 public boolean isMine(Key intentKey) { 111 public boolean isMine(Key intentKey) {
112 - return Objects.equal(leadershipService.getLeader(getPartitionPath(getPartitionForKey(intentKey))), 112 + return Objects.equals(leadershipService.getLeader(getPartitionPath(getPartitionForKey(intentKey))),
113 clusterService.getLocalNode().id()); 113 clusterService.getLocalNode().id());
114 } 114 }
115 115
116 + @Override
117 + public NodeId getLeader(Key intentKey) {
118 + return leadershipService.getLeader(getPartitionPath(getPartitionForKey(intentKey)));
119 + }
120 +
116 private void doRelinquish() { 121 private void doRelinquish() {
117 try { 122 try {
118 relinquish(); 123 relinquish();
...@@ -171,7 +176,7 @@ public class PartitionManager implements PartitionService { ...@@ -171,7 +176,7 @@ public class PartitionManager implements PartitionService {
171 public void event(LeadershipEvent event) { 176 public void event(LeadershipEvent event) {
172 Leadership leadership = event.subject(); 177 Leadership leadership = event.subject();
173 178
174 - if (Objects.equal(leadership.leader(), clusterService.getLocalNode().id()) && 179 + if (Objects.equals(leadership.leader(), clusterService.getLocalNode().id()) &&
175 leadership.topic().startsWith(ELECTION_PREFIX)) { 180 leadership.topic().startsWith(ELECTION_PREFIX)) {
176 181
177 // See if we need to let some partitions go 182 // See if we need to let some partitions go
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.store.intent.impl; 16 package org.onosproject.store.intent.impl;
17 17
18 +import org.onosproject.cluster.NodeId;
18 import org.onosproject.net.intent.Key; 19 import org.onosproject.net.intent.Key;
19 20
20 /** 21 /**
...@@ -31,5 +32,13 @@ public interface PartitionService { ...@@ -31,5 +32,13 @@ public interface PartitionService {
31 */ 32 */
32 boolean isMine(Key intentKey); 33 boolean isMine(Key intentKey);
33 34
35 + /**
36 + * Returns the leader for a particular key.
37 + *
38 + * @param intentKey intent key to query
39 + * @return the leader node
40 + */
41 + NodeId getLeader(Key intentKey);
42 +
34 // TODO add API for rebalancing partitions 43 // TODO add API for rebalancing partitions
35 } 44 }
......
...@@ -337,13 +337,13 @@ public class GossipLinkStore ...@@ -337,13 +337,13 @@ public class GossipLinkStore
337 ClusterMessage linkInjectedMessage = new ClusterMessage(localNode, 337 ClusterMessage linkInjectedMessage = new ClusterMessage(localNode,
338 GossipLinkStoreMessageSubjects.LINK_INJECTED, SERIALIZER.encode(linkInjectedEvent)); 338 GossipLinkStoreMessageSubjects.LINK_INJECTED, SERIALIZER.encode(linkInjectedEvent));
339 339
340 - try { 340 + // TODO check unicast return value
341 clusterCommunicator.unicast(linkInjectedMessage, dstNode); 341 clusterCommunicator.unicast(linkInjectedMessage, dstNode);
342 - } catch (IOException e) { 342 + /* error log:
343 log.warn("Failed to process link update between src: {} and dst: {} " + 343 log.warn("Failed to process link update between src: {} and dst: {} " +
344 "(cluster messaging failed: {})", 344 "(cluster messaging failed: {})",
345 linkDescription.src(), linkDescription.dst(), e); 345 linkDescription.src(), linkDescription.dst(), e);
346 - } 346 + */
347 347
348 } 348 }
349 349
......
...@@ -15,19 +15,13 @@ ...@@ -15,19 +15,13 @@
15 */ 15 */
16 package org.onosproject.store.packet.impl; 16 package org.onosproject.store.packet.impl;
17 17
18 -import static org.onlab.util.Tools.groupedThreads;
19 -import static org.slf4j.LoggerFactory.getLogger;
20 -
21 -import java.io.IOException;
22 -import java.util.concurrent.ExecutorService;
23 -import java.util.concurrent.Executors;
24 -
25 import org.apache.felix.scr.annotations.Activate; 18 import org.apache.felix.scr.annotations.Activate;
26 import org.apache.felix.scr.annotations.Component; 19 import org.apache.felix.scr.annotations.Component;
27 import org.apache.felix.scr.annotations.Deactivate; 20 import org.apache.felix.scr.annotations.Deactivate;
28 import org.apache.felix.scr.annotations.Reference; 21 import org.apache.felix.scr.annotations.Reference;
29 import org.apache.felix.scr.annotations.ReferenceCardinality; 22 import org.apache.felix.scr.annotations.ReferenceCardinality;
30 import org.apache.felix.scr.annotations.Service; 23 import org.apache.felix.scr.annotations.Service;
24 +import org.onlab.util.KryoNamespace;
31 import org.onosproject.cluster.ClusterService; 25 import org.onosproject.cluster.ClusterService;
32 import org.onosproject.cluster.NodeId; 26 import org.onosproject.cluster.NodeId;
33 import org.onosproject.mastership.MastershipService; 27 import org.onosproject.mastership.MastershipService;
...@@ -43,9 +37,14 @@ import org.onosproject.store.cluster.messaging.ClusterMessageHandler; ...@@ -43,9 +37,14 @@ import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
43 import org.onosproject.store.cluster.messaging.MessageSubject; 37 import org.onosproject.store.cluster.messaging.MessageSubject;
44 import org.onosproject.store.serializers.KryoNamespaces; 38 import org.onosproject.store.serializers.KryoNamespaces;
45 import org.onosproject.store.serializers.KryoSerializer; 39 import org.onosproject.store.serializers.KryoSerializer;
46 -import org.onlab.util.KryoNamespace;
47 import org.slf4j.Logger; 40 import org.slf4j.Logger;
48 41
42 +import java.util.concurrent.ExecutorService;
43 +import java.util.concurrent.Executors;
44 +
45 +import static org.onlab.util.Tools.groupedThreads;
46 +import static org.slf4j.LoggerFactory.getLogger;
47 +
49 /** 48 /**
50 * Distributed packet store implementation allowing packets to be sent to 49 * Distributed packet store implementation allowing packets to be sent to
51 * remote instances. 50 * remote instances.
...@@ -118,12 +117,10 @@ public class DistributedPacketStore ...@@ -118,12 +117,10 @@ public class DistributedPacketStore
118 return; 117 return;
119 } 118 }
120 119
121 - try { 120 + // TODO check unicast return value
122 communicationService.unicast(new ClusterMessage( 121 communicationService.unicast(new ClusterMessage(
123 myId, PACKET_OUT_SUBJECT, SERIALIZER.encode(packet)), master); 122 myId, PACKET_OUT_SUBJECT, SERIALIZER.encode(packet)), master);
124 - } catch (IOException e) { 123 + // error log: log.warn("Failed to send packet-out to {}", master);
125 - log.warn("Failed to send packet-out to {}", master);
126 - }
127 } 124 }
128 125
129 /** 126 /**
......
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
16 package org.onosproject.store.ecmap; 16 package org.onosproject.store.ecmap;
17 17
18 import com.google.common.collect.ComparisonChain; 18 import com.google.common.collect.ComparisonChain;
19 +import com.google.common.collect.ImmutableSet;
19 import com.google.common.util.concurrent.ListenableFuture; 20 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors; 21 import com.google.common.util.concurrent.MoreExecutors;
21 -
22 import org.junit.After; 22 import org.junit.After;
23 import org.junit.Before; 23 import org.junit.Before;
24 import org.junit.Test; 24 import org.junit.Test;
...@@ -53,10 +53,7 @@ import java.util.concurrent.atomic.AtomicLong; ...@@ -53,10 +53,7 @@ import java.util.concurrent.atomic.AtomicLong;
53 import static com.google.common.base.Preconditions.checkArgument; 53 import static com.google.common.base.Preconditions.checkArgument;
54 import static junit.framework.TestCase.assertFalse; 54 import static junit.framework.TestCase.assertFalse;
55 import static org.easymock.EasyMock.*; 55 import static org.easymock.EasyMock.*;
56 -import static org.junit.Assert.assertEquals; 56 +import static org.junit.Assert.*;
57 -import static org.junit.Assert.assertNull;
58 -import static org.junit.Assert.assertTrue;
59 -import static org.junit.Assert.fail;
60 57
61 /** 58 /**
62 * Unit tests for EventuallyConsistentMapImpl. 59 * Unit tests for EventuallyConsistentMapImpl.
...@@ -119,8 +116,8 @@ public class EventuallyConsistentMapImplTest { ...@@ -119,8 +116,8 @@ public class EventuallyConsistentMapImplTest {
119 @Before 116 @Before
120 public void setUp() throws Exception { 117 public void setUp() throws Exception {
121 clusterService = createMock(ClusterService.class); 118 clusterService = createMock(ClusterService.class);
122 - expect(clusterService.getLocalNode()).andReturn(self) 119 + expect(clusterService.getLocalNode()).andReturn(self).anyTimes();
123 - .anyTimes(); 120 + expect(clusterService.getNodes()).andReturn(ImmutableSet.of(self)).anyTimes();
124 replay(clusterService); 121 replay(clusterService);
125 122
126 clusterCommunicator = createMock(ClusterCommunicationService.class); 123 clusterCommunicator = createMock(ClusterCommunicationService.class);
...@@ -163,7 +160,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -163,7 +160,7 @@ public class EventuallyConsistentMapImplTest {
163 160
164 @Test 161 @Test
165 public void testSize() throws Exception { 162 public void testSize() throws Exception {
166 - expectAnyMessage(clusterCommunicator); 163 + expectPeerMessage(clusterCommunicator);
167 164
168 assertEquals(0, ecMap.size()); 165 assertEquals(0, ecMap.size());
169 ecMap.put(KEY1, VALUE1); 166 ecMap.put(KEY1, VALUE1);
...@@ -184,7 +181,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -184,7 +181,7 @@ public class EventuallyConsistentMapImplTest {
184 181
185 @Test 182 @Test
186 public void testIsEmpty() throws Exception { 183 public void testIsEmpty() throws Exception {
187 - expectAnyMessage(clusterCommunicator); 184 + expectPeerMessage(clusterCommunicator);
188 185
189 assertTrue(ecMap.isEmpty()); 186 assertTrue(ecMap.isEmpty());
190 ecMap.put(KEY1, VALUE1); 187 ecMap.put(KEY1, VALUE1);
...@@ -195,7 +192,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -195,7 +192,7 @@ public class EventuallyConsistentMapImplTest {
195 192
196 @Test 193 @Test
197 public void testContainsKey() throws Exception { 194 public void testContainsKey() throws Exception {
198 - expectAnyMessage(clusterCommunicator); 195 + expectPeerMessage(clusterCommunicator);
199 196
200 assertFalse(ecMap.containsKey(KEY1)); 197 assertFalse(ecMap.containsKey(KEY1));
201 ecMap.put(KEY1, VALUE1); 198 ecMap.put(KEY1, VALUE1);
...@@ -207,7 +204,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -207,7 +204,7 @@ public class EventuallyConsistentMapImplTest {
207 204
208 @Test 205 @Test
209 public void testContainsValue() throws Exception { 206 public void testContainsValue() throws Exception {
210 - expectAnyMessage(clusterCommunicator); 207 + expectPeerMessage(clusterCommunicator);
211 208
212 assertFalse(ecMap.containsValue(VALUE1)); 209 assertFalse(ecMap.containsValue(VALUE1));
213 ecMap.put(KEY1, VALUE1); 210 ecMap.put(KEY1, VALUE1);
...@@ -222,7 +219,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -222,7 +219,7 @@ public class EventuallyConsistentMapImplTest {
222 219
223 @Test 220 @Test
224 public void testGet() throws Exception { 221 public void testGet() throws Exception {
225 - expectAnyMessage(clusterCommunicator); 222 + expectPeerMessage(clusterCommunicator);
226 223
227 CountDownLatch latch; 224 CountDownLatch latch;
228 225
...@@ -278,7 +275,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -278,7 +275,7 @@ public class EventuallyConsistentMapImplTest {
278 ecMap.addListener(listener); 275 ecMap.addListener(listener);
279 276
280 // Set up expected internal message to be broadcast to peers on first put 277 // Set up expected internal message to be broadcast to peers on first put
281 - expectSpecificMessage(generatePutMessage(KEY1, VALUE1, clockService 278 + expectSpecificMulticastMessage(generatePutMessage(KEY1, VALUE1, clockService
282 .peekAtNextTimestamp()), clusterCommunicator); 279 .peekAtNextTimestamp()), clusterCommunicator);
283 280
284 // Put first value 281 // Put first value
...@@ -289,7 +286,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -289,7 +286,7 @@ public class EventuallyConsistentMapImplTest {
289 verify(clusterCommunicator); 286 verify(clusterCommunicator);
290 287
291 // Set up expected internal message to be broadcast to peers on second put 288 // Set up expected internal message to be broadcast to peers on second put
292 - expectSpecificMessage(generatePutMessage( 289 + expectSpecificMulticastMessage(generatePutMessage(
293 KEY1, VALUE2, clockService.peekAtNextTimestamp()), clusterCommunicator); 290 KEY1, VALUE2, clockService.peekAtNextTimestamp()), clusterCommunicator);
294 291
295 // Update same key to a new value 292 // Update same key to a new value
...@@ -332,13 +329,13 @@ public class EventuallyConsistentMapImplTest { ...@@ -332,13 +329,13 @@ public class EventuallyConsistentMapImplTest {
332 ecMap.addListener(listener); 329 ecMap.addListener(listener);
333 330
334 // Put in an initial value 331 // Put in an initial value
335 - expectAnyMessage(clusterCommunicator); 332 + expectPeerMessage(clusterCommunicator);
336 ecMap.put(KEY1, VALUE1); 333 ecMap.put(KEY1, VALUE1);
337 assertEquals(VALUE1, ecMap.get(KEY1)); 334 assertEquals(VALUE1, ecMap.get(KEY1));
338 335
339 // Remove the value and check the correct internal cluster messages 336 // Remove the value and check the correct internal cluster messages
340 // are sent 337 // are sent
341 - expectSpecificMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()), 338 + expectSpecificMulticastMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()),
342 clusterCommunicator); 339 clusterCommunicator);
343 340
344 ecMap.remove(KEY1); 341 ecMap.remove(KEY1);
...@@ -349,7 +346,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -349,7 +346,7 @@ public class EventuallyConsistentMapImplTest {
349 // Remove the same value again. Even though the value is no longer in 346 // Remove the same value again. Even though the value is no longer in
350 // the map, we expect that the tombstone is updated and another remove 347 // the map, we expect that the tombstone is updated and another remove
351 // event is sent to the cluster and external listeners. 348 // event is sent to the cluster and external listeners.
352 - expectSpecificMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()), 349 + expectSpecificMulticastMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()),
353 clusterCommunicator); 350 clusterCommunicator);
354 351
355 ecMap.remove(KEY1); 352 ecMap.remove(KEY1);
...@@ -359,7 +356,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -359,7 +356,7 @@ public class EventuallyConsistentMapImplTest {
359 356
360 357
361 // Put in a new value for us to try and remove 358 // Put in a new value for us to try and remove
362 - expectAnyMessage(clusterCommunicator); 359 + expectPeerMessage(clusterCommunicator);
363 360
364 ecMap.put(KEY2, VALUE2); 361 ecMap.put(KEY2, VALUE2);
365 362
...@@ -400,7 +397,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -400,7 +397,7 @@ public class EventuallyConsistentMapImplTest {
400 ecMap.addListener(listener); 397 ecMap.addListener(listener);
401 398
402 // Expect a multi-update inter-instance message 399 // Expect a multi-update inter-instance message
403 - expectSpecificMessage(generatePutMessage(KEY1, VALUE1, KEY2, VALUE2), 400 + expectSpecificBroadcastMessage(generatePutMessage(KEY1, VALUE1, KEY2, VALUE2),
404 clusterCommunicator); 401 clusterCommunicator);
405 402
406 Map<String, String> putAllValues = new HashMap<>(); 403 Map<String, String> putAllValues = new HashMap<>();
...@@ -434,12 +431,12 @@ public class EventuallyConsistentMapImplTest { ...@@ -434,12 +431,12 @@ public class EventuallyConsistentMapImplTest {
434 verify(clusterCommunicator); 431 verify(clusterCommunicator);
435 432
436 // Put some items in the map 433 // Put some items in the map
437 - expectAnyMessage(clusterCommunicator); 434 + expectPeerMessage(clusterCommunicator);
438 ecMap.put(KEY1, VALUE1); 435 ecMap.put(KEY1, VALUE1);
439 ecMap.put(KEY2, VALUE2); 436 ecMap.put(KEY2, VALUE2);
440 437
441 ecMap.addListener(listener); 438 ecMap.addListener(listener);
442 - expectSpecificMessage(generateRemoveMessage(KEY1, KEY2), clusterCommunicator); 439 + expectSpecificBroadcastMessage(generateRemoveMessage(KEY1, KEY2), clusterCommunicator);
443 440
444 ecMap.clear(); 441 ecMap.clear();
445 442
...@@ -449,7 +446,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -449,7 +446,7 @@ public class EventuallyConsistentMapImplTest {
449 446
450 @Test 447 @Test
451 public void testKeySet() throws Exception { 448 public void testKeySet() throws Exception {
452 - expectAnyMessage(clusterCommunicator); 449 + expectPeerMessage(clusterCommunicator);
453 450
454 assertTrue(ecMap.keySet().isEmpty()); 451 assertTrue(ecMap.keySet().isEmpty());
455 452
...@@ -482,7 +479,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -482,7 +479,7 @@ public class EventuallyConsistentMapImplTest {
482 479
483 @Test 480 @Test
484 public void testValues() throws Exception { 481 public void testValues() throws Exception {
485 - expectAnyMessage(clusterCommunicator); 482 + expectPeerMessage(clusterCommunicator);
486 483
487 assertTrue(ecMap.values().isEmpty()); 484 assertTrue(ecMap.values().isEmpty());
488 485
...@@ -520,7 +517,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -520,7 +517,7 @@ public class EventuallyConsistentMapImplTest {
520 517
521 @Test 518 @Test
522 public void testEntrySet() throws Exception { 519 public void testEntrySet() throws Exception {
523 - expectAnyMessage(clusterCommunicator); 520 + expectPeerMessage(clusterCommunicator);
524 521
525 assertTrue(ecMap.entrySet().isEmpty()); 522 assertTrue(ecMap.entrySet().isEmpty());
526 523
...@@ -658,7 +655,7 @@ public class EventuallyConsistentMapImplTest { ...@@ -658,7 +655,7 @@ public class EventuallyConsistentMapImplTest {
658 * @param m message we expect to be sent 655 * @param m message we expect to be sent
659 * @param clusterCommunicator a mock ClusterCommunicationService to set up 656 * @param clusterCommunicator a mock ClusterCommunicationService to set up
660 */ 657 */
661 - private static void expectSpecificMessage(ClusterMessage m, 658 + private static void expectSpecificBroadcastMessage(ClusterMessage m,
662 ClusterCommunicationService clusterCommunicator) { 659 ClusterCommunicationService clusterCommunicator) {
663 reset(clusterCommunicator); 660 reset(clusterCommunicator);
664 expect(clusterCommunicator.broadcast(m)).andReturn(true); 661 expect(clusterCommunicator.broadcast(m)).andReturn(true);
...@@ -666,13 +663,44 @@ public class EventuallyConsistentMapImplTest { ...@@ -666,13 +663,44 @@ public class EventuallyConsistentMapImplTest {
666 } 663 }
667 664
668 /** 665 /**
669 - * Sets up a mock ClusterCommunicationService to expect any cluster message 666 + * Sets up a mock ClusterCommunicationService to expect a specific cluster
667 + * message to be multicast to the cluster.
668 + *
669 + * @param m message we expect to be sent
670 + * @param clusterCommunicator a mock ClusterCommunicationService to set up
671 + */
672 + private static void expectSpecificMulticastMessage(ClusterMessage m,
673 + ClusterCommunicationService clusterCommunicator) {
674 + reset(clusterCommunicator);
675 + expect(clusterCommunicator.multicast(eq(m), anyObject(Set.class))).andReturn(true);
676 + replay(clusterCommunicator);
677 + }
678 +
679 +
680 + /**
681 + * Sets up a mock ClusterCommunicationService to expect a multicast cluster message
670 * that is sent to it. This is useful for unit tests where we aren't 682 * that is sent to it. This is useful for unit tests where we aren't
671 * interested in testing the messaging component. 683 * interested in testing the messaging component.
672 * 684 *
673 * @param clusterCommunicator a mock ClusterCommunicationService to set up 685 * @param clusterCommunicator a mock ClusterCommunicationService to set up
674 */ 686 */
675 - private void expectAnyMessage(ClusterCommunicationService clusterCommunicator) { 687 + private void expectPeerMessage(ClusterCommunicationService clusterCommunicator) {
688 + reset(clusterCommunicator);
689 + expect(clusterCommunicator.multicast(anyObject(ClusterMessage.class),
690 + anyObject(Iterable.class)))
691 + .andReturn(true)
692 + .anyTimes();
693 + replay(clusterCommunicator);
694 + }
695 +
696 + /**
697 + * Sets up a mock ClusterCommunicationService to expect a broadcast cluster message
698 + * that is sent to it. This is useful for unit tests where we aren't
699 + * interested in testing the messaging component.
700 + *
701 + * @param clusterCommunicator a mock ClusterCommunicationService to set up
702 + */
703 + private void expectBroadcastMessage(ClusterCommunicationService clusterCommunicator) {
676 reset(clusterCommunicator); 704 reset(clusterCommunicator);
677 expect(clusterCommunicator.broadcast(anyObject(ClusterMessage.class))) 705 expect(clusterCommunicator.broadcast(anyObject(ClusterMessage.class)))
678 .andReturn(true) 706 .andReturn(true)
...@@ -700,13 +728,12 @@ public class EventuallyConsistentMapImplTest { ...@@ -700,13 +728,12 @@ public class EventuallyConsistentMapImplTest {
700 } 728 }
701 729
702 @Override 730 @Override
703 - public boolean unicast(ClusterMessage message, NodeId toNodeId) 731 + public boolean unicast(ClusterMessage message, NodeId toNodeId) {
704 - throws IOException {
705 return false; 732 return false;
706 } 733 }
707 734
708 @Override 735 @Override
709 - public boolean multicast(ClusterMessage message, Set<NodeId> nodeIds) { 736 + public boolean multicast(ClusterMessage message, Iterable<NodeId> nodeIds) {
710 return false; 737 return false;
711 } 738 }
712 739
......
...@@ -31,6 +31,8 @@ import static org.junit.Assert.*; ...@@ -31,6 +31,8 @@ import static org.junit.Assert.*;
31 */ 31 */
32 public class BlockingBooleanTest { 32 public class BlockingBooleanTest {
33 33
34 + private static final int TIMEOUT = 100; //ms
35 +
34 @Test 36 @Test
35 public void basics() { 37 public void basics() {
36 BlockingBoolean b = new BlockingBoolean(false); 38 BlockingBoolean b = new BlockingBoolean(false);
...@@ -60,7 +62,7 @@ public class BlockingBooleanTest { ...@@ -60,7 +62,7 @@ public class BlockingBooleanTest {
60 } 62 }
61 b.set(value); 63 b.set(value);
62 try { 64 try {
63 - assertTrue(latch.await(10, TimeUnit.MILLISECONDS)); 65 + assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS));
64 } catch (InterruptedException e) { 66 } catch (InterruptedException e) {
65 fail(); 67 fail();
66 } 68 }
...@@ -92,7 +94,7 @@ public class BlockingBooleanTest { ...@@ -92,7 +94,7 @@ public class BlockingBooleanTest {
92 } 94 }
93 }); 95 });
94 try { 96 try {
95 - assertTrue(latch.await(10, TimeUnit.MILLISECONDS)); 97 + assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS));
96 } catch (InterruptedException e) { 98 } catch (InterruptedException e) {
97 fail(); 99 fail();
98 } 100 }
...@@ -124,14 +126,14 @@ public class BlockingBooleanTest { ...@@ -124,14 +126,14 @@ public class BlockingBooleanTest {
124 }); 126 });
125 } 127 }
126 try { 128 try {
127 - assertTrue(sameLatch.await(10, TimeUnit.MILLISECONDS)); 129 + assertTrue(sameLatch.await(TIMEOUT, TimeUnit.MILLISECONDS));
128 assertEquals(waitLatch.getCount(), numThreads / 2); 130 assertEquals(waitLatch.getCount(), numThreads / 2);
129 } catch (InterruptedException e) { 131 } catch (InterruptedException e) {
130 fail(); 132 fail();
131 } 133 }
132 b.set(true); 134 b.set(true);
133 try { 135 try {
134 - assertTrue(waitLatch.await(10, TimeUnit.MILLISECONDS)); 136 + assertTrue(waitLatch.await(TIMEOUT, TimeUnit.MILLISECONDS));
135 } catch (InterruptedException e) { 137 } catch (InterruptedException e) {
136 fail(); 138 fail();
137 } 139 }
...@@ -156,7 +158,7 @@ public class BlockingBooleanTest { ...@@ -156,7 +158,7 @@ public class BlockingBooleanTest {
156 } 158 }
157 }); 159 });
158 try { 160 try {
159 - assertTrue(latch.await(10, TimeUnit.MILLISECONDS)); 161 + assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS));
160 } catch (InterruptedException e) { 162 } catch (InterruptedException e) {
161 fail(); 163 fail();
162 } 164 }
......