Showing
11 changed files
with
60 additions
and
222 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 | - | 187 | +} |
| 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 | -} | ||
| ... | \ 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