Showing
11 changed files
with
59 additions
and
221 deletions
... | @@ -4,6 +4,7 @@ import static java.lang.Thread.sleep; | ... | @@ -4,6 +4,7 @@ import static java.lang.Thread.sleep; |
4 | 4 | ||
5 | import java.io.IOException; | 5 | import java.io.IOException; |
6 | import java.util.concurrent.ExecutionException; | 6 | import java.util.concurrent.ExecutionException; |
7 | +import java.util.concurrent.Future; | ||
7 | import java.util.concurrent.TimeUnit; | 8 | import java.util.concurrent.TimeUnit; |
8 | import java.util.concurrent.TimeoutException; | 9 | import java.util.concurrent.TimeoutException; |
9 | 10 | ||
... | @@ -12,7 +13,6 @@ import org.onlab.metrics.MetricsFeature; | ... | @@ -12,7 +13,6 @@ import org.onlab.metrics.MetricsFeature; |
12 | import org.onlab.metrics.MetricsManager; | 13 | import org.onlab.metrics.MetricsManager; |
13 | import org.onlab.netty.Endpoint; | 14 | import org.onlab.netty.Endpoint; |
14 | import org.onlab.netty.NettyMessagingService; | 15 | import org.onlab.netty.NettyMessagingService; |
15 | -import org.onlab.netty.Response; | ||
16 | import org.slf4j.Logger; | 16 | import org.slf4j.Logger; |
17 | import org.slf4j.LoggerFactory; | 17 | import org.slf4j.LoggerFactory; |
18 | 18 | ||
... | @@ -74,10 +74,10 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); | ... | @@ -74,10 +74,10 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); |
74 | 74 | ||
75 | for (int i = 0; i < warmup; i++) { | 75 | for (int i = 0; i < warmup; i++) { |
76 | messaging.sendAsync(endpoint, "simple", "Hello World".getBytes()); | 76 | messaging.sendAsync(endpoint, "simple", "Hello World".getBytes()); |
77 | - Response response = messaging | 77 | + Future<byte[]> responseFuture = messaging |
78 | .sendAndReceive(endpoint, "echo", | 78 | .sendAndReceive(endpoint, "echo", |
79 | "Hello World".getBytes()); | 79 | "Hello World".getBytes()); |
80 | - response.get(100000, TimeUnit.MILLISECONDS); | 80 | + responseFuture.get(100000, TimeUnit.MILLISECONDS); |
81 | } | 81 | } |
82 | 82 | ||
83 | log.info("measuring round-trip send & receive"); | 83 | log.info("measuring round-trip send & receive"); |
... | @@ -85,13 +85,13 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); | ... | @@ -85,13 +85,13 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); |
85 | int timeouts = 0; | 85 | int timeouts = 0; |
86 | 86 | ||
87 | for (int i = 0; i < iterations; i++) { | 87 | for (int i = 0; i < iterations; i++) { |
88 | - Response response; | 88 | + Future<byte[]> responseFuture; |
89 | Timer.Context context = sendAndReceiveTimer.time(); | 89 | Timer.Context context = sendAndReceiveTimer.time(); |
90 | try { | 90 | try { |
91 | - response = messaging | 91 | + responseFuture = messaging |
92 | .sendAndReceive(endpoint, "echo", | 92 | .sendAndReceive(endpoint, "echo", |
93 | "Hello World".getBytes()); | 93 | "Hello World".getBytes()); |
94 | - response.get(10000, TimeUnit.MILLISECONDS); | 94 | + responseFuture.get(10000, TimeUnit.MILLISECONDS); |
95 | } catch (TimeoutException e) { | 95 | } catch (TimeoutException e) { |
96 | timeouts++; | 96 | timeouts++; |
97 | log.info("timeout:" + timeouts + " at iteration:" + i); | 97 | log.info("timeout:" + timeouts + " at iteration:" + i); | ... | ... |
... | @@ -5,6 +5,8 @@ import java.util.Set; | ... | @@ -5,6 +5,8 @@ import java.util.Set; |
5 | 5 | ||
6 | import org.onlab.onos.cluster.NodeId; | 6 | import org.onlab.onos.cluster.NodeId; |
7 | 7 | ||
8 | +import com.google.common.util.concurrent.ListenableFuture; | ||
9 | + | ||
8 | // TODO: remove IOExceptions? | 10 | // TODO: remove IOExceptions? |
9 | /** | 11 | /** |
10 | * Service for assisting communications between controller cluster nodes. | 12 | * Service for assisting communications between controller cluster nodes. |
... | @@ -40,10 +42,10 @@ public interface ClusterCommunicationService { | ... | @@ -40,10 +42,10 @@ public interface ClusterCommunicationService { |
40 | * Sends a message synchronously. | 42 | * Sends a message synchronously. |
41 | * @param message message to send | 43 | * @param message message to send |
42 | * @param toNodeId recipient node identifier | 44 | * @param toNodeId recipient node identifier |
43 | - * @return ClusterMessageResponse which is reply future. | 45 | + * @return reply future. |
44 | * @throws IOException | 46 | * @throws IOException |
45 | */ | 47 | */ |
46 | - ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException; | 48 | + ListenableFuture<byte[]> sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException; |
47 | 49 | ||
48 | /** | 50 | /** |
49 | * Adds a new subscriber for the specified message subject. | 51 | * Adds a new subscriber for the specified message subject. | ... | ... |
core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessageResponse.java
deleted
100644 → 0
1 | -package org.onlab.onos.store.cluster.messaging; | ||
2 | - | ||
3 | -import java.util.concurrent.Future; | ||
4 | -import java.util.concurrent.TimeUnit; | ||
5 | -import java.util.concurrent.TimeoutException; | ||
6 | - | ||
7 | -import org.onlab.onos.cluster.NodeId; | ||
8 | - | ||
9 | -public interface ClusterMessageResponse extends Future<byte[]> { | ||
10 | - | ||
11 | - public NodeId sender(); | ||
12 | - | ||
13 | - // TODO InterruptedException, ExecutionException removed from original | ||
14 | - // Future declaration. Revisit if we ever need those. | ||
15 | - @Override | ||
16 | - public byte[] get(long timeout, TimeUnit unit) throws TimeoutException; | ||
17 | - | ||
18 | -} |
... | @@ -4,9 +4,7 @@ import static com.google.common.base.Preconditions.checkArgument; | ... | @@ -4,9 +4,7 @@ import static com.google.common.base.Preconditions.checkArgument; |
4 | 4 | ||
5 | import java.io.IOException; | 5 | import java.io.IOException; |
6 | import java.util.Set; | 6 | import java.util.Set; |
7 | -import java.util.concurrent.ExecutionException; | 7 | + |
8 | -import java.util.concurrent.TimeUnit; | ||
9 | -import java.util.concurrent.TimeoutException; | ||
10 | import org.apache.felix.scr.annotations.Activate; | 8 | import org.apache.felix.scr.annotations.Activate; |
11 | import org.apache.felix.scr.annotations.Component; | 9 | import org.apache.felix.scr.annotations.Component; |
12 | import org.apache.felix.scr.annotations.Deactivate; | 10 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -20,7 +18,6 @@ import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent; | ... | @@ -20,7 +18,6 @@ import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent; |
20 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | 18 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; |
21 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 19 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
22 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; | 20 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; |
23 | -import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse; | ||
24 | import org.onlab.onos.store.cluster.messaging.MessageSubject; | 21 | import org.onlab.onos.store.cluster.messaging.MessageSubject; |
25 | import org.onlab.onos.store.serializers.ClusterMessageSerializer; | 22 | import org.onlab.onos.store.serializers.ClusterMessageSerializer; |
26 | import org.onlab.onos.store.serializers.KryoNamespaces; | 23 | import org.onlab.onos.store.serializers.KryoNamespaces; |
... | @@ -32,10 +29,11 @@ import org.onlab.netty.Message; | ... | @@ -32,10 +29,11 @@ import org.onlab.netty.Message; |
32 | import org.onlab.netty.MessageHandler; | 29 | import org.onlab.netty.MessageHandler; |
33 | import org.onlab.netty.MessagingService; | 30 | import org.onlab.netty.MessagingService; |
34 | import org.onlab.netty.NettyMessagingService; | 31 | import org.onlab.netty.NettyMessagingService; |
35 | -import org.onlab.netty.Response; | ||
36 | import org.slf4j.Logger; | 32 | import org.slf4j.Logger; |
37 | import org.slf4j.LoggerFactory; | 33 | import org.slf4j.LoggerFactory; |
38 | 34 | ||
35 | +import com.google.common.util.concurrent.ListenableFuture; | ||
36 | + | ||
39 | @Component(immediate = true) | 37 | @Component(immediate = true) |
40 | @Service | 38 | @Service |
41 | public class ClusterCommunicationManager | 39 | public class ClusterCommunicationManager |
... | @@ -133,14 +131,12 @@ public class ClusterCommunicationManager | ... | @@ -133,14 +131,12 @@ public class ClusterCommunicationManager |
133 | } | 131 | } |
134 | 132 | ||
135 | @Override | 133 | @Override |
136 | - public ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException { | 134 | + public ListenableFuture<byte[]> sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException { |
137 | ControllerNode node = clusterService.getNode(toNodeId); | 135 | ControllerNode node = clusterService.getNode(toNodeId); |
138 | checkArgument(node != null, "Unknown nodeId: %s", toNodeId); | 136 | checkArgument(node != null, "Unknown nodeId: %s", toNodeId); |
139 | Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); | 137 | Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); |
140 | try { | 138 | try { |
141 | - Response responseFuture = | 139 | + return messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message)); |
142 | - messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message)); | ||
143 | - return new InternalClusterMessageResponse(toNodeId, responseFuture); | ||
144 | 140 | ||
145 | } catch (IOException e) { | 141 | } catch (IOException e) { |
146 | log.error("Failed interaction with remote nodeId: " + toNodeId, e); | 142 | log.error("Failed interaction with remote nodeId: " + toNodeId, e); |
... | @@ -188,60 +184,4 @@ public class ClusterCommunicationManager | ... | @@ -188,60 +184,4 @@ public class ClusterCommunicationManager |
188 | rawMessage.respond(response); | 184 | rawMessage.respond(response); |
189 | } | 185 | } |
190 | } | 186 | } |
191 | - | ||
192 | - private static final class InternalClusterMessageResponse | ||
193 | - implements ClusterMessageResponse { | ||
194 | - | ||
195 | - private final NodeId sender; | ||
196 | - private final Response responseFuture; | ||
197 | - private volatile boolean isCancelled = false; | ||
198 | - private volatile boolean isDone = false; | ||
199 | - | ||
200 | - public InternalClusterMessageResponse(NodeId sender, Response responseFuture) { | ||
201 | - this.sender = sender; | ||
202 | - this.responseFuture = responseFuture; | ||
203 | - } | ||
204 | - @Override | ||
205 | - public NodeId sender() { | ||
206 | - return sender; | ||
207 | - } | ||
208 | - | ||
209 | - @Override | ||
210 | - public byte[] get(long timeout, TimeUnit timeunit) | ||
211 | - throws TimeoutException { | ||
212 | - final byte[] result = responseFuture.get(timeout, timeunit); | ||
213 | - isDone = true; | ||
214 | - return result; | ||
215 | - } | ||
216 | - | ||
217 | - @Override | ||
218 | - public boolean cancel(boolean mayInterruptIfRunning) { | ||
219 | - if (isDone()) { | ||
220 | - return false; | ||
221 | - } | ||
222 | - // doing nothing for now | ||
223 | - // when onlab.netty Response support cancel, call them. | ||
224 | - isCancelled = true; | ||
225 | - return true; | ||
226 | - } | ||
227 | - | ||
228 | - @Override | ||
229 | - public boolean isCancelled() { | ||
230 | - return isCancelled; | ||
231 | - } | ||
232 | - | ||
233 | - @Override | ||
234 | - public boolean isDone() { | ||
235 | - return this.isDone || isCancelled(); | ||
236 | - } | ||
237 | - | ||
238 | - @Override | ||
239 | - public byte[] get() throws InterruptedException, ExecutionException { | ||
240 | - // TODO: consider forbidding this call and force the use of timed get | ||
241 | - // to enforce handling of remote peer failure scenario | ||
242 | - final byte[] result = responseFuture.get(); | ||
243 | - isDone = true; | ||
244 | - return result; | ||
245 | - } | ||
246 | - } | ||
247 | } | 187 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -12,6 +12,7 @@ import java.util.Collection; | ... | @@ -12,6 +12,7 @@ import java.util.Collection; |
12 | import java.util.Collections; | 12 | import java.util.Collections; |
13 | import java.util.Map; | 13 | import java.util.Map; |
14 | import java.util.Set; | 14 | import java.util.Set; |
15 | +import java.util.concurrent.ExecutionException; | ||
15 | import java.util.concurrent.ExecutorService; | 16 | import java.util.concurrent.ExecutorService; |
16 | import java.util.concurrent.Executors; | 17 | import java.util.concurrent.Executors; |
17 | import java.util.concurrent.Future; | 18 | import java.util.concurrent.Future; |
... | @@ -49,7 +50,6 @@ import org.onlab.onos.store.AbstractStore; | ... | @@ -49,7 +50,6 @@ import org.onlab.onos.store.AbstractStore; |
49 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | 50 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; |
50 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 51 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
51 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; | 52 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; |
52 | -import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse; | ||
53 | import org.onlab.onos.store.flow.ReplicaInfo; | 53 | import org.onlab.onos.store.flow.ReplicaInfo; |
54 | import org.onlab.onos.store.flow.ReplicaInfoService; | 54 | import org.onlab.onos.store.flow.ReplicaInfoService; |
55 | import org.onlab.onos.store.serializers.DistributedStoreSerializers; | 55 | import org.onlab.onos.store.serializers.DistributedStoreSerializers; |
... | @@ -57,6 +57,7 @@ import org.onlab.onos.store.serializers.KryoSerializer; | ... | @@ -57,6 +57,7 @@ import org.onlab.onos.store.serializers.KryoSerializer; |
57 | import org.onlab.util.KryoNamespace; | 57 | import org.onlab.util.KryoNamespace; |
58 | import org.slf4j.Logger; | 58 | import org.slf4j.Logger; |
59 | 59 | ||
60 | +import com.google.common.base.Function; | ||
60 | import com.google.common.collect.ArrayListMultimap; | 61 | import com.google.common.collect.ArrayListMultimap; |
61 | import com.google.common.collect.ImmutableSet; | 62 | import com.google.common.collect.ImmutableSet; |
62 | import com.google.common.collect.Iterables; | 63 | import com.google.common.collect.Iterables; |
... | @@ -213,9 +214,9 @@ public class DistributedFlowRuleStore | ... | @@ -213,9 +214,9 @@ public class DistributedFlowRuleStore |
213 | SERIALIZER.encode(rule)); | 214 | SERIALIZER.encode(rule)); |
214 | 215 | ||
215 | try { | 216 | try { |
216 | - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | 217 | + Future<byte[]> responseFuture = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); |
217 | - return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); | 218 | + return SERIALIZER.decode(responseFuture.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
218 | - } catch (IOException | TimeoutException e) { | 219 | + } catch (IOException | TimeoutException | ExecutionException | InterruptedException e) { |
219 | // FIXME: throw a FlowStoreException | 220 | // FIXME: throw a FlowStoreException |
220 | throw new RuntimeException(e); | 221 | throw new RuntimeException(e); |
221 | } | 222 | } |
... | @@ -247,9 +248,9 @@ public class DistributedFlowRuleStore | ... | @@ -247,9 +248,9 @@ public class DistributedFlowRuleStore |
247 | SERIALIZER.encode(deviceId)); | 248 | SERIALIZER.encode(deviceId)); |
248 | 249 | ||
249 | try { | 250 | try { |
250 | - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | 251 | + Future<byte[]> responseFuture = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); |
251 | - return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); | 252 | + return SERIALIZER.decode(responseFuture.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
252 | - } catch (IOException | TimeoutException e) { | 253 | + } catch (IOException | TimeoutException | ExecutionException | InterruptedException e) { |
253 | // FIXME: throw a FlowStoreException | 254 | // FIXME: throw a FlowStoreException |
254 | throw new RuntimeException(e); | 255 | throw new RuntimeException(e); |
255 | } | 256 | } |
... | @@ -291,14 +292,17 @@ public class DistributedFlowRuleStore | ... | @@ -291,14 +292,17 @@ public class DistributedFlowRuleStore |
291 | SERIALIZER.encode(operation)); | 292 | SERIALIZER.encode(operation)); |
292 | 293 | ||
293 | try { | 294 | try { |
294 | - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | 295 | + ListenableFuture<byte[]> responseFuture = |
295 | - response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); | 296 | + clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); |
296 | - } catch (IOException | TimeoutException e) { | 297 | + return Futures.transform(responseFuture, new Function<byte[], CompletedBatchOperation>() { |
297 | - // FIXME: throw a FlowStoreException | 298 | + @Override |
298 | - throw new RuntimeException(e); | 299 | + public CompletedBatchOperation apply(byte[] input) { |
300 | + return SERIALIZER.decode(input); | ||
301 | + } | ||
302 | + }); | ||
303 | + } catch (IOException e) { | ||
304 | + return Futures.immediateFailedFuture(e); | ||
299 | } | 305 | } |
300 | - | ||
301 | - return null; | ||
302 | } | 306 | } |
303 | 307 | ||
304 | private ListenableFuture<CompletedBatchOperation> storeBatchInternal(FlowRuleBatchOperation operation) { | 308 | private ListenableFuture<CompletedBatchOperation> storeBatchInternal(FlowRuleBatchOperation operation) { | ... | ... |
... | @@ -4,6 +4,7 @@ import static org.onlab.onos.store.statistic.impl.StatisticStoreMessageSubjects. | ... | @@ -4,6 +4,7 @@ import static org.onlab.onos.store.statistic.impl.StatisticStoreMessageSubjects. |
4 | import static org.slf4j.LoggerFactory.getLogger; | 4 | import static org.slf4j.LoggerFactory.getLogger; |
5 | 5 | ||
6 | import com.google.common.collect.Sets; | 6 | import com.google.common.collect.Sets; |
7 | + | ||
7 | import org.apache.felix.scr.annotations.Activate; | 8 | import org.apache.felix.scr.annotations.Activate; |
8 | import org.apache.felix.scr.annotations.Component; | 9 | import org.apache.felix.scr.annotations.Component; |
9 | import org.apache.felix.scr.annotations.Deactivate; | 10 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -21,7 +22,6 @@ import org.onlab.onos.net.statistic.StatisticStore; | ... | @@ -21,7 +22,6 @@ import org.onlab.onos.net.statistic.StatisticStore; |
21 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | 22 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; |
22 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 23 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
23 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; | 24 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; |
24 | -import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse; | ||
25 | import org.onlab.onos.store.flow.ReplicaInfo; | 25 | import org.onlab.onos.store.flow.ReplicaInfo; |
26 | import org.onlab.onos.store.flow.ReplicaInfoService; | 26 | import org.onlab.onos.store.flow.ReplicaInfoService; |
27 | import org.onlab.onos.store.serializers.KryoNamespaces; | 27 | import org.onlab.onos.store.serializers.KryoNamespaces; |
... | @@ -34,6 +34,8 @@ import java.util.HashSet; | ... | @@ -34,6 +34,8 @@ import java.util.HashSet; |
34 | import java.util.Map; | 34 | import java.util.Map; |
35 | import java.util.Set; | 35 | import java.util.Set; |
36 | import java.util.concurrent.ConcurrentHashMap; | 36 | import java.util.concurrent.ConcurrentHashMap; |
37 | +import java.util.concurrent.ExecutionException; | ||
38 | +import java.util.concurrent.Future; | ||
37 | import java.util.concurrent.TimeUnit; | 39 | import java.util.concurrent.TimeUnit; |
38 | import java.util.concurrent.TimeoutException; | 40 | import java.util.concurrent.TimeoutException; |
39 | import java.util.concurrent.atomic.AtomicInteger; | 41 | import java.util.concurrent.atomic.AtomicInteger; |
... | @@ -184,11 +186,11 @@ public class DistributedStatisticStore implements StatisticStore { | ... | @@ -184,11 +186,11 @@ public class DistributedStatisticStore implements StatisticStore { |
184 | SERIALIZER.encode(connectPoint)); | 186 | SERIALIZER.encode(connectPoint)); |
185 | 187 | ||
186 | try { | 188 | try { |
187 | - ClusterMessageResponse response = | 189 | + Future<byte[]> response = |
188 | clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | 190 | clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); |
189 | return SERIALIZER.decode(response.get(STATISTIC_STORE_TIMEOUT_MILLIS, | 191 | return SERIALIZER.decode(response.get(STATISTIC_STORE_TIMEOUT_MILLIS, |
190 | TimeUnit.MILLISECONDS)); | 192 | TimeUnit.MILLISECONDS)); |
191 | - } catch (IOException | TimeoutException e) { | 193 | + } catch (IOException | TimeoutException | ExecutionException | InterruptedException e) { |
192 | // FIXME: throw a StatsStoreException | 194 | // FIXME: throw a StatsStoreException |
193 | throw new RuntimeException(e); | 195 | throw new RuntimeException(e); |
194 | } | 196 | } |
... | @@ -212,11 +214,11 @@ public class DistributedStatisticStore implements StatisticStore { | ... | @@ -212,11 +214,11 @@ public class DistributedStatisticStore implements StatisticStore { |
212 | SERIALIZER.encode(connectPoint)); | 214 | SERIALIZER.encode(connectPoint)); |
213 | 215 | ||
214 | try { | 216 | try { |
215 | - ClusterMessageResponse response = | 217 | + Future<byte[]> response = |
216 | clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | 218 | clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); |
217 | return SERIALIZER.decode(response.get(STATISTIC_STORE_TIMEOUT_MILLIS, | 219 | return SERIALIZER.decode(response.get(STATISTIC_STORE_TIMEOUT_MILLIS, |
218 | TimeUnit.MILLISECONDS)); | 220 | TimeUnit.MILLISECONDS)); |
219 | - } catch (IOException | TimeoutException e) { | 221 | + } catch (IOException | TimeoutException | ExecutionException | InterruptedException e) { |
220 | // FIXME: throw a StatsStoreException | 222 | // FIXME: throw a StatsStoreException |
221 | throw new RuntimeException(e); | 223 | throw new RuntimeException(e); |
222 | } | 224 | } | ... | ... |
1 | -package org.onlab.netty; | ||
2 | - | ||
3 | -import java.util.concurrent.TimeUnit; | ||
4 | -import java.util.concurrent.TimeoutException; | ||
5 | - | ||
6 | -/** | ||
7 | - * An asynchronous response. | ||
8 | - * This class provides a base implementation of Response, with methods to retrieve the | ||
9 | - * result and query to see if the result is ready. The result can only be retrieved when | ||
10 | - * it is ready and the get methods will block if the result is not ready yet. | ||
11 | - */ | ||
12 | -public class AsyncResponse implements Response { | ||
13 | - | ||
14 | - private byte[] value; | ||
15 | - private boolean done = false; | ||
16 | - private final long start = System.nanoTime(); | ||
17 | - | ||
18 | - @Override | ||
19 | - public byte[] get(long timeout, TimeUnit timeUnit) throws TimeoutException { | ||
20 | - timeout = timeUnit.toNanos(timeout); | ||
21 | - boolean interrupted = false; | ||
22 | - try { | ||
23 | - synchronized (this) { | ||
24 | - while (!done) { | ||
25 | - try { | ||
26 | - long timeRemaining = timeout - (System.nanoTime() - start); | ||
27 | - if (timeRemaining <= 0) { | ||
28 | - throw new TimeoutException("Operation timed out."); | ||
29 | - } | ||
30 | - TimeUnit.NANOSECONDS.timedWait(this, timeRemaining); | ||
31 | - } catch (InterruptedException e) { | ||
32 | - interrupted = true; | ||
33 | - } | ||
34 | - } | ||
35 | - } | ||
36 | - } finally { | ||
37 | - if (interrupted) { | ||
38 | - Thread.currentThread().interrupt(); | ||
39 | - } | ||
40 | - } | ||
41 | - return value; | ||
42 | - } | ||
43 | - | ||
44 | - @Override | ||
45 | - public byte[] get() throws InterruptedException { | ||
46 | - throw new UnsupportedOperationException(); | ||
47 | - } | ||
48 | - | ||
49 | - @Override | ||
50 | - public boolean isReady() { | ||
51 | - return done; | ||
52 | - } | ||
53 | - | ||
54 | - /** | ||
55 | - * Sets response value and unblocks any thread blocking on the response to become | ||
56 | - * available. | ||
57 | - * @param data response data. | ||
58 | - */ | ||
59 | - public synchronized void setResponse(byte[] data) { | ||
60 | - if (!done) { | ||
61 | - done = true; | ||
62 | - value = data; | ||
63 | - this.notifyAll(); | ||
64 | - } | ||
65 | - } | ||
66 | -} |
... | @@ -2,6 +2,8 @@ package org.onlab.netty; | ... | @@ -2,6 +2,8 @@ package org.onlab.netty; |
2 | 2 | ||
3 | import java.io.IOException; | 3 | import java.io.IOException; |
4 | 4 | ||
5 | +import com.google.common.util.concurrent.ListenableFuture; | ||
6 | + | ||
5 | /** | 7 | /** |
6 | * Interface for low level messaging primitives. | 8 | * Interface for low level messaging primitives. |
7 | */ | 9 | */ |
... | @@ -24,7 +26,7 @@ public interface MessagingService { | ... | @@ -24,7 +26,7 @@ public interface MessagingService { |
24 | * @return a response future | 26 | * @return a response future |
25 | * @throws IOException | 27 | * @throws IOException |
26 | */ | 28 | */ |
27 | - public Response sendAndReceive(Endpoint ep, String type, byte[] payload) throws IOException; | 29 | + public ListenableFuture<byte[]> sendAndReceive(Endpoint ep, String type, byte[] payload) throws IOException; |
28 | 30 | ||
29 | /** | 31 | /** |
30 | * Registers a new message handler for message type. | 32 | * Registers a new message handler for message type. | ... | ... |
... | @@ -5,6 +5,7 @@ import java.net.UnknownHostException; | ... | @@ -5,6 +5,7 @@ import java.net.UnknownHostException; |
5 | import java.util.concurrent.ConcurrentHashMap; | 5 | import java.util.concurrent.ConcurrentHashMap; |
6 | import java.util.concurrent.ConcurrentMap; | 6 | import java.util.concurrent.ConcurrentMap; |
7 | import java.util.concurrent.TimeUnit; | 7 | import java.util.concurrent.TimeUnit; |
8 | +import java.util.concurrent.atomic.AtomicLong; | ||
8 | 9 | ||
9 | import io.netty.bootstrap.Bootstrap; | 10 | import io.netty.bootstrap.Bootstrap; |
10 | import io.netty.bootstrap.ServerBootstrap; | 11 | import io.netty.bootstrap.ServerBootstrap; |
... | @@ -26,7 +27,6 @@ import io.netty.channel.socket.SocketChannel; | ... | @@ -26,7 +27,6 @@ import io.netty.channel.socket.SocketChannel; |
26 | import io.netty.channel.socket.nio.NioServerSocketChannel; | 27 | import io.netty.channel.socket.nio.NioServerSocketChannel; |
27 | import io.netty.channel.socket.nio.NioSocketChannel; | 28 | import io.netty.channel.socket.nio.NioSocketChannel; |
28 | 29 | ||
29 | -import org.apache.commons.lang.math.RandomUtils; | ||
30 | import org.apache.commons.pool.KeyedPoolableObjectFactory; | 30 | import org.apache.commons.pool.KeyedPoolableObjectFactory; |
31 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; | 31 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; |
32 | import org.slf4j.Logger; | 32 | import org.slf4j.Logger; |
... | @@ -34,6 +34,8 @@ import org.slf4j.LoggerFactory; | ... | @@ -34,6 +34,8 @@ import org.slf4j.LoggerFactory; |
34 | 34 | ||
35 | import com.google.common.cache.Cache; | 35 | import com.google.common.cache.Cache; |
36 | import com.google.common.cache.CacheBuilder; | 36 | import com.google.common.cache.CacheBuilder; |
37 | +import com.google.common.util.concurrent.ListenableFuture; | ||
38 | +import com.google.common.util.concurrent.SettableFuture; | ||
37 | 39 | ||
38 | /** | 40 | /** |
39 | * A Netty based implementation of MessagingService. | 41 | * A Netty based implementation of MessagingService. |
... | @@ -44,7 +46,8 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -44,7 +46,8 @@ public class NettyMessagingService implements MessagingService { |
44 | 46 | ||
45 | private final Endpoint localEp; | 47 | private final Endpoint localEp; |
46 | private final ConcurrentMap<String, MessageHandler> handlers = new ConcurrentHashMap<>(); | 48 | private final ConcurrentMap<String, MessageHandler> handlers = new ConcurrentHashMap<>(); |
47 | - private final Cache<Long, AsyncResponse> responseFutures = CacheBuilder.newBuilder() | 49 | + private final AtomicLong messageIdGenerator = new AtomicLong(0); |
50 | + private final Cache<Long, SettableFuture<byte[]>> responseFutures = CacheBuilder.newBuilder() | ||
48 | .maximumSize(100000) | 51 | .maximumSize(100000) |
49 | .weakValues() | 52 | .weakValues() |
50 | // TODO: Once the entry expires, notify blocking threads (if any). | 53 | // TODO: Once the entry expires, notify blocking threads (if any). |
... | @@ -119,7 +122,7 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -119,7 +122,7 @@ public class NettyMessagingService implements MessagingService { |
119 | @Override | 122 | @Override |
120 | public void sendAsync(Endpoint ep, String type, byte[] payload) throws IOException { | 123 | public void sendAsync(Endpoint ep, String type, byte[] payload) throws IOException { |
121 | InternalMessage message = new InternalMessage.Builder(this) | 124 | InternalMessage message = new InternalMessage.Builder(this) |
122 | - .withId(RandomUtils.nextLong()) | 125 | + .withId(messageIdGenerator.incrementAndGet()) |
123 | .withSender(localEp) | 126 | .withSender(localEp) |
124 | .withType(type) | 127 | .withType(type) |
125 | .withPayload(payload) | 128 | .withPayload(payload) |
... | @@ -142,10 +145,10 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -142,10 +145,10 @@ public class NettyMessagingService implements MessagingService { |
142 | } | 145 | } |
143 | 146 | ||
144 | @Override | 147 | @Override |
145 | - public Response sendAndReceive(Endpoint ep, String type, byte[] payload) | 148 | + public ListenableFuture<byte[]> sendAndReceive(Endpoint ep, String type, byte[] payload) |
146 | throws IOException { | 149 | throws IOException { |
147 | - AsyncResponse futureResponse = new AsyncResponse(); | 150 | + SettableFuture<byte[]> futureResponse = SettableFuture.create(); |
148 | - Long messageId = RandomUtils.nextLong(); | 151 | + Long messageId = messageIdGenerator.incrementAndGet(); |
149 | responseFutures.put(messageId, futureResponse); | 152 | responseFutures.put(messageId, futureResponse); |
150 | InternalMessage message = new InternalMessage.Builder(this) | 153 | InternalMessage message = new InternalMessage.Builder(this) |
151 | .withId(messageId) | 154 | .withId(messageId) |
... | @@ -267,10 +270,10 @@ public class NettyMessagingService implements MessagingService { | ... | @@ -267,10 +270,10 @@ public class NettyMessagingService implements MessagingService { |
267 | String type = message.type(); | 270 | String type = message.type(); |
268 | if (type.equals(InternalMessage.REPLY_MESSAGE_TYPE)) { | 271 | if (type.equals(InternalMessage.REPLY_MESSAGE_TYPE)) { |
269 | try { | 272 | try { |
270 | - AsyncResponse futureResponse = | 273 | + SettableFuture<byte[]> futureResponse = |
271 | NettyMessagingService.this.responseFutures.getIfPresent(message.id()); | 274 | NettyMessagingService.this.responseFutures.getIfPresent(message.id()); |
272 | if (futureResponse != null) { | 275 | if (futureResponse != null) { |
273 | - futureResponse.setResponse(message.payload()); | 276 | + futureResponse.set(message.payload()); |
274 | } else { | 277 | } else { |
275 | log.warn("Received a reply. But was unable to locate the request handle"); | 278 | log.warn("Received a reply. But was unable to locate the request handle"); |
276 | } | 279 | } | ... | ... |
1 | -package org.onlab.netty; | ||
2 | - | ||
3 | -import java.util.concurrent.TimeUnit; | ||
4 | -import java.util.concurrent.TimeoutException; | ||
5 | - | ||
6 | -/** | ||
7 | - * Response object returned when making synchronous requests. | ||
8 | - * Can you used to check is a response is ready and/or wait for a response | ||
9 | - * to become available. | ||
10 | - */ | ||
11 | -public interface Response { | ||
12 | - | ||
13 | - /** | ||
14 | - * Gets the response waiting for a designated timeout period. | ||
15 | - * @param timeout timeout period (since request was sent out) | ||
16 | - * @param tu unit of time. | ||
17 | - * @return response payload | ||
18 | - * @throws TimeoutException if the timeout expires before the response arrives. | ||
19 | - */ | ||
20 | - public byte[] get(long timeout, TimeUnit tu) throws TimeoutException; | ||
21 | - | ||
22 | - /** | ||
23 | - * Gets the response waiting for indefinite timeout period. | ||
24 | - * @return response payload | ||
25 | - * @throws InterruptedException if the thread is interrupted before the response arrives. | ||
26 | - */ | ||
27 | - public byte[] get() throws InterruptedException; | ||
28 | - | ||
29 | - /** | ||
30 | - * Checks if the response is ready without blocking. | ||
31 | - * @return true if response is ready, false otherwise. | ||
32 | - */ | ||
33 | - public boolean isReady(); | ||
34 | -} |
1 | package org.onlab.netty; | 1 | package org.onlab.netty; |
2 | 2 | ||
3 | +import java.util.concurrent.Future; | ||
3 | import java.util.concurrent.TimeUnit; | 4 | import java.util.concurrent.TimeUnit; |
4 | 5 | ||
5 | import org.apache.commons.lang3.RandomUtils; | 6 | import org.apache.commons.lang3.RandomUtils; |
7 | + | ||
6 | import static org.junit.Assert.*; | 8 | import static org.junit.Assert.*; |
9 | + | ||
7 | import org.junit.Test; | 10 | import org.junit.Test; |
8 | 11 | ||
9 | /** | 12 | /** |
... | @@ -20,8 +23,8 @@ public class PingPongTest { | ... | @@ -20,8 +23,8 @@ public class PingPongTest { |
20 | ponger.activate(); | 23 | ponger.activate(); |
21 | ponger.registerHandler("echo", new EchoHandler()); | 24 | ponger.registerHandler("echo", new EchoHandler()); |
22 | byte[] payload = RandomUtils.nextBytes(100); | 25 | byte[] payload = RandomUtils.nextBytes(100); |
23 | - Response response = pinger.sendAndReceive(new Endpoint("localhost", 9086), "echo", payload); | 26 | + Future<byte[]> responseFuture = pinger.sendAndReceive(new Endpoint("localhost", 9086), "echo", payload); |
24 | - assertArrayEquals(payload, response.get(10000, TimeUnit.MILLISECONDS)); | 27 | + assertArrayEquals(payload, responseFuture.get(10000, TimeUnit.MILLISECONDS)); |
25 | } finally { | 28 | } finally { |
26 | pinger.deactivate(); | 29 | pinger.deactivate(); |
27 | ponger.deactivate(); | 30 | ponger.deactivate(); | ... | ... |
-
Please register or login to post a comment