DistributedFlowRuleStore: remote batch support
Change-Id: I373a942697624440e025a8022a13394396058a71
Showing
8 changed files
with
113 additions
and
81 deletions
| ... | @@ -30,7 +30,7 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T | ... | @@ -30,7 +30,7 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T |
| 30 | * @param request batch operation request. | 30 | * @param request batch operation request. |
| 31 | * @return event. | 31 | * @return event. |
| 32 | */ | 32 | */ |
| 33 | - public static FlowRuleBatchEvent create(FlowRuleBatchRequest request) { | 33 | + public static FlowRuleBatchEvent requested(FlowRuleBatchRequest request) { |
| 34 | FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_REQUESTED, request, null); | 34 | FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_REQUESTED, request, null); |
| 35 | return event; | 35 | return event; |
| 36 | } | 36 | } |
| ... | @@ -41,7 +41,7 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T | ... | @@ -41,7 +41,7 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T |
| 41 | * @param result completed batch operation result. | 41 | * @param result completed batch operation result. |
| 42 | * @return event. | 42 | * @return event. |
| 43 | */ | 43 | */ |
| 44 | - public static FlowRuleBatchEvent create(FlowRuleBatchRequest request, CompletedBatchOperation result) { | 44 | + public static FlowRuleBatchEvent completed(FlowRuleBatchRequest request, CompletedBatchOperation result) { |
| 45 | FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_COMPLETED, request, result); | 45 | FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_COMPLETED, request, result); |
| 46 | return event; | 46 | return event; |
| 47 | } | 47 | } | ... | ... |
| ... | @@ -9,10 +9,12 @@ import com.google.common.collect.Lists; | ... | @@ -9,10 +9,12 @@ import com.google.common.collect.Lists; |
| 9 | 9 | ||
| 10 | public class FlowRuleBatchRequest { | 10 | public class FlowRuleBatchRequest { |
| 11 | 11 | ||
| 12 | + private final int batchId; | ||
| 12 | private final List<FlowEntry> toAdd; | 13 | private final List<FlowEntry> toAdd; |
| 13 | private final List<FlowEntry> toRemove; | 14 | private final List<FlowEntry> toRemove; |
| 14 | 15 | ||
| 15 | - public FlowRuleBatchRequest(List<FlowEntry> toAdd, List<FlowEntry> toRemove) { | 16 | + public FlowRuleBatchRequest(int batchId, List<FlowEntry> toAdd, List<FlowEntry> toRemove) { |
| 17 | + this.batchId = batchId; | ||
| 16 | this.toAdd = Collections.unmodifiableList(toAdd); | 18 | this.toAdd = Collections.unmodifiableList(toAdd); |
| 17 | this.toRemove = Collections.unmodifiableList(toRemove); | 19 | this.toRemove = Collections.unmodifiableList(toRemove); |
| 18 | } | 20 | } |
| ... | @@ -35,4 +37,8 @@ public class FlowRuleBatchRequest { | ... | @@ -35,4 +37,8 @@ public class FlowRuleBatchRequest { |
| 35 | } | 37 | } |
| 36 | return new FlowRuleBatchOperation(entries); | 38 | return new FlowRuleBatchOperation(entries); |
| 37 | } | 39 | } |
| 40 | + | ||
| 41 | + public int batchId() { | ||
| 42 | + return batchId; | ||
| 43 | + } | ||
| 38 | } | 44 | } | ... | ... |
| ... | @@ -2,12 +2,14 @@ package org.onlab.onos.net.flow.impl; | ... | @@ -2,12 +2,14 @@ package org.onlab.onos.net.flow.impl; |
| 2 | 2 | ||
| 3 | import static com.google.common.base.Preconditions.checkNotNull; | 3 | import static com.google.common.base.Preconditions.checkNotNull; |
| 4 | import static org.slf4j.LoggerFactory.getLogger; | 4 | import static org.slf4j.LoggerFactory.getLogger; |
| 5 | +import static org.onlab.util.Tools.namedThreads; | ||
| 5 | 6 | ||
| 6 | import java.util.List; | 7 | import java.util.List; |
| 7 | import java.util.Map; | 8 | import java.util.Map; |
| 8 | import java.util.Set; | 9 | import java.util.Set; |
| 9 | import java.util.concurrent.CancellationException; | 10 | import java.util.concurrent.CancellationException; |
| 10 | import java.util.concurrent.ExecutionException; | 11 | import java.util.concurrent.ExecutionException; |
| 12 | +import java.util.concurrent.ExecutorService; | ||
| 11 | import java.util.concurrent.Executors; | 13 | import java.util.concurrent.Executors; |
| 12 | import java.util.concurrent.Future; | 14 | import java.util.concurrent.Future; |
| 13 | import java.util.concurrent.TimeUnit; | 15 | import java.util.concurrent.TimeUnit; |
| ... | @@ -74,6 +76,8 @@ public class FlowRuleManager | ... | @@ -74,6 +76,8 @@ public class FlowRuleManager |
| 74 | 76 | ||
| 75 | private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); | 77 | private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); |
| 76 | 78 | ||
| 79 | + private final ExecutorService futureListeners = Executors.newCachedThreadPool(namedThreads("provider-future-listeners")); | ||
| 80 | + | ||
| 77 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 81 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 78 | protected FlowRuleStore store; | 82 | protected FlowRuleStore store; |
| 79 | 83 | ||
| ... | @@ -92,6 +96,8 @@ public class FlowRuleManager | ... | @@ -92,6 +96,8 @@ public class FlowRuleManager |
| 92 | 96 | ||
| 93 | @Deactivate | 97 | @Deactivate |
| 94 | public void deactivate() { | 98 | public void deactivate() { |
| 99 | + futureListeners.shutdownNow(); | ||
| 100 | + | ||
| 95 | store.unsetDelegate(delegate); | 101 | store.unsetDelegate(delegate); |
| 96 | eventDispatcher.removeSink(FlowRuleEvent.class); | 102 | eventDispatcher.removeSink(FlowRuleEvent.class); |
| 97 | log.info("Stopped"); | 103 | log.info("Stopped"); |
| ... | @@ -398,9 +404,9 @@ public class FlowRuleManager | ... | @@ -398,9 +404,9 @@ public class FlowRuleManager |
| 398 | result.addListener(new Runnable() { | 404 | result.addListener(new Runnable() { |
| 399 | @Override | 405 | @Override |
| 400 | public void run() { | 406 | public void run() { |
| 401 | - store.batchOperationComplete(FlowRuleBatchEvent.create(request, Futures.getUnchecked(result))); | 407 | + store.batchOperationComplete(FlowRuleBatchEvent.completed(request, Futures.getUnchecked(result))); |
| 402 | } | 408 | } |
| 403 | - }, Executors.newCachedThreadPool()); | 409 | + }, futureListeners); |
| 404 | 410 | ||
| 405 | break; | 411 | break; |
| 406 | case BATCH_OPERATION_COMPLETED: | 412 | case BATCH_OPERATION_COMPLETED: | ... | ... |
| ... | @@ -3,15 +3,20 @@ package org.onlab.onos.store.flow.impl; | ... | @@ -3,15 +3,20 @@ package org.onlab.onos.store.flow.impl; |
| 3 | import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; | 3 | import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; |
| 4 | import static org.slf4j.LoggerFactory.getLogger; | 4 | import static org.slf4j.LoggerFactory.getLogger; |
| 5 | import static org.onlab.onos.store.flow.impl.FlowStoreMessageSubjects.*; | 5 | import static org.onlab.onos.store.flow.impl.FlowStoreMessageSubjects.*; |
| 6 | +import static org.onlab.util.Tools.namedThreads; | ||
| 6 | 7 | ||
| 7 | import java.io.IOException; | 8 | import java.io.IOException; |
| 8 | import java.util.ArrayList; | 9 | import java.util.ArrayList; |
| 9 | import java.util.Arrays; | 10 | import java.util.Arrays; |
| 10 | import java.util.Collection; | 11 | import java.util.Collection; |
| 11 | import java.util.Collections; | 12 | import java.util.Collections; |
| 13 | +import java.util.Map; | ||
| 14 | +import java.util.concurrent.ExecutorService; | ||
| 15 | +import java.util.concurrent.Executors; | ||
| 12 | import java.util.concurrent.Future; | 16 | import java.util.concurrent.Future; |
| 13 | import java.util.concurrent.TimeUnit; | 17 | import java.util.concurrent.TimeUnit; |
| 14 | import java.util.concurrent.TimeoutException; | 18 | import java.util.concurrent.TimeoutException; |
| 19 | +import java.util.concurrent.atomic.AtomicInteger; | ||
| 15 | import java.util.List; | 20 | import java.util.List; |
| 16 | 21 | ||
| 17 | import org.apache.felix.scr.annotations.Activate; | 22 | import org.apache.felix.scr.annotations.Activate; |
| ... | @@ -22,7 +27,9 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -22,7 +27,9 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 22 | import org.apache.felix.scr.annotations.Service; | 27 | import org.apache.felix.scr.annotations.Service; |
| 23 | import org.onlab.onos.ApplicationId; | 28 | import org.onlab.onos.ApplicationId; |
| 24 | import org.onlab.onos.cluster.ClusterService; | 29 | import org.onlab.onos.cluster.ClusterService; |
| 30 | +import org.onlab.onos.net.Device; | ||
| 25 | import org.onlab.onos.net.DeviceId; | 31 | import org.onlab.onos.net.DeviceId; |
| 32 | +import org.onlab.onos.net.device.DeviceService; | ||
| 26 | import org.onlab.onos.net.flow.CompletedBatchOperation; | 33 | import org.onlab.onos.net.flow.CompletedBatchOperation; |
| 27 | import org.onlab.onos.net.flow.DefaultFlowEntry; | 34 | import org.onlab.onos.net.flow.DefaultFlowEntry; |
| 28 | import org.onlab.onos.net.flow.FlowEntry; | 35 | import org.onlab.onos.net.flow.FlowEntry; |
| ... | @@ -52,8 +59,12 @@ import org.slf4j.Logger; | ... | @@ -52,8 +59,12 @@ import org.slf4j.Logger; |
| 52 | 59 | ||
| 53 | import com.google.common.collect.ArrayListMultimap; | 60 | import com.google.common.collect.ArrayListMultimap; |
| 54 | import com.google.common.collect.ImmutableSet; | 61 | import com.google.common.collect.ImmutableSet; |
| 62 | +import com.google.common.collect.Iterables; | ||
| 63 | +import com.google.common.collect.Maps; | ||
| 55 | import com.google.common.collect.Multimap; | 64 | import com.google.common.collect.Multimap; |
| 56 | import com.google.common.util.concurrent.Futures; | 65 | import com.google.common.util.concurrent.Futures; |
| 66 | +import com.google.common.util.concurrent.ListenableFuture; | ||
| 67 | +import com.google.common.util.concurrent.SettableFuture; | ||
| 57 | 68 | ||
| 58 | /** | 69 | /** |
| 59 | * Manages inventory of flow rules using a distributed state management protocol. | 70 | * Manages inventory of flow rules using a distributed state management protocol. |
| ... | @@ -74,13 +85,26 @@ public class DistributedFlowRuleStore | ... | @@ -74,13 +85,26 @@ public class DistributedFlowRuleStore |
| 74 | ArrayListMultimap.<Short, FlowRule>create(); | 85 | ArrayListMultimap.<Short, FlowRule>create(); |
| 75 | 86 | ||
| 76 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 87 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 77 | - private ReplicaInfoService replicaInfoManager; | 88 | + protected ReplicaInfoService replicaInfoManager; |
| 78 | 89 | ||
| 79 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 90 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 80 | - private ClusterCommunicationService clusterCommunicator; | 91 | + protected ClusterCommunicationService clusterCommunicator; |
| 81 | 92 | ||
| 82 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 93 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 83 | - private ClusterService clusterService; | 94 | + protected ClusterService clusterService; |
| 95 | + | ||
| 96 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 97 | + protected DeviceService deviceService; | ||
| 98 | + | ||
| 99 | + private final AtomicInteger localBatchIdGen = new AtomicInteger(); | ||
| 100 | + | ||
| 101 | + | ||
| 102 | + // FIXME switch to expiraing map/Cache? | ||
| 103 | + private Map<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = Maps.newConcurrentMap(); | ||
| 104 | + | ||
| 105 | + private final ExecutorService futureListeners = | ||
| 106 | + Executors.newCachedThreadPool(namedThreads("flowstore-peer-responders")); | ||
| 107 | + | ||
| 84 | 108 | ||
| 85 | protected static final KryoSerializer SERIALIZER = new KryoSerializer() { | 109 | protected static final KryoSerializer SERIALIZER = new KryoSerializer() { |
| 86 | @Override | 110 | @Override |
| ... | @@ -97,36 +121,26 @@ public class DistributedFlowRuleStore | ... | @@ -97,36 +121,26 @@ public class DistributedFlowRuleStore |
| 97 | 121 | ||
| 98 | @Activate | 122 | @Activate |
| 99 | public void activate() { | 123 | public void activate() { |
| 100 | - clusterCommunicator.addSubscriber(STORE_FLOW_RULE, new ClusterMessageHandler() { | 124 | + clusterCommunicator.addSubscriber(APPLY_BATCH_FLOWS, new ClusterMessageHandler() { |
| 101 | 125 | ||
| 102 | @Override | 126 | @Override |
| 103 | - public void handle(ClusterMessage message) { | 127 | + public void handle(final ClusterMessage message) { |
| 104 | - FlowRule rule = SERIALIZER.decode(message.payload()); | 128 | + FlowRuleBatchOperation operation = SERIALIZER.decode(message.payload()); |
| 105 | - log.info("received add request for {}", rule); | 129 | + log.info("received batch request {}", operation); |
| 106 | - storeFlowRule(rule); | 130 | + final ListenableFuture<CompletedBatchOperation> f = storeBatchInternal(operation); |
| 107 | - // FIXME what to respond. | 131 | + |
| 108 | - try { | 132 | + f.addListener(new Runnable() { |
| 109 | - message.respond(SERIALIZER.encode("ACK")); | 133 | + |
| 110 | - } catch (IOException e) { | 134 | + @Override |
| 111 | - log.error("Failed to respond back", e); | 135 | + public void run() { |
| 112 | - } | 136 | + CompletedBatchOperation result = Futures.getUnchecked(f); |
| 113 | - } | 137 | + try { |
| 114 | - }); | 138 | + message.respond(SERIALIZER.encode(result)); |
| 115 | - | 139 | + } catch (IOException e) { |
| 116 | - clusterCommunicator.addSubscriber(DELETE_FLOW_RULE, new ClusterMessageHandler() { | 140 | + log.error("Failed to respond back", e); |
| 117 | - | 141 | + } |
| 118 | - @Override | 142 | + } |
| 119 | - public void handle(ClusterMessage message) { | 143 | + }, futureListeners); |
| 120 | - FlowRule rule = SERIALIZER.decode(message.payload()); | ||
| 121 | - log.info("received delete request for {}", rule); | ||
| 122 | - deleteFlowRule(rule); | ||
| 123 | - // FIXME what to respond. | ||
| 124 | - try { | ||
| 125 | - message.respond(SERIALIZER.encode("ACK")); | ||
| 126 | - } catch (IOException e) { | ||
| 127 | - log.error("Failed to respond back", e); | ||
| 128 | - } | ||
| 129 | - | ||
| 130 | } | 144 | } |
| 131 | }); | 145 | }); |
| 132 | 146 | ||
| ... | @@ -159,7 +173,13 @@ public class DistributedFlowRuleStore | ... | @@ -159,7 +173,13 @@ public class DistributedFlowRuleStore |
| 159 | // make it device specific. | 173 | // make it device specific. |
| 160 | @Override | 174 | @Override |
| 161 | public int getFlowRuleCount() { | 175 | public int getFlowRuleCount() { |
| 162 | - return flowEntries.size(); | 176 | + // implementing in-efficient operation for debugging purpose. |
| 177 | + int sum = 0; | ||
| 178 | + for (Device device : deviceService.getDevices()) { | ||
| 179 | + final DeviceId did = device.id(); | ||
| 180 | + sum += Iterables.size(getFlowEntries(did)); | ||
| 181 | + } | ||
| 182 | + return sum; | ||
| 163 | } | 183 | } |
| 164 | 184 | ||
| 165 | @Override | 185 | @Override |
| ... | @@ -218,6 +238,7 @@ public class DistributedFlowRuleStore | ... | @@ -218,6 +238,7 @@ public class DistributedFlowRuleStore |
| 218 | storeBatch(new FlowRuleBatchOperation(Arrays.asList(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)))); | 238 | storeBatch(new FlowRuleBatchOperation(Arrays.asList(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)))); |
| 219 | } | 239 | } |
| 220 | 240 | ||
| 241 | + @Override | ||
| 221 | public Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation operation) { | 242 | public Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation operation) { |
| 222 | if (operation.getOperations().isEmpty()) { | 243 | if (operation.getOperations().isEmpty()) { |
| 223 | return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet())); | 244 | return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet())); |
| ... | @@ -236,7 +257,7 @@ public class DistributedFlowRuleStore | ... | @@ -236,7 +257,7 @@ public class DistributedFlowRuleStore |
| 236 | 257 | ||
| 237 | ClusterMessage message = new ClusterMessage( | 258 | ClusterMessage message = new ClusterMessage( |
| 238 | clusterService.getLocalNode().id(), | 259 | clusterService.getLocalNode().id(), |
| 239 | - FlowStoreMessageSubjects.STORE_FLOW_RULE, | 260 | + APPLY_BATCH_FLOWS, |
| 240 | SERIALIZER.encode(operation)); | 261 | SERIALIZER.encode(operation)); |
| 241 | 262 | ||
| 242 | try { | 263 | try { |
| ... | @@ -250,7 +271,7 @@ public class DistributedFlowRuleStore | ... | @@ -250,7 +271,7 @@ public class DistributedFlowRuleStore |
| 250 | return null; | 271 | return null; |
| 251 | } | 272 | } |
| 252 | 273 | ||
| 253 | - private Future<CompletedBatchOperation> storeBatchInternal(FlowRuleBatchOperation operation) { | 274 | + private ListenableFuture<CompletedBatchOperation> storeBatchInternal(FlowRuleBatchOperation operation) { |
| 254 | List<FlowEntry> toRemove = new ArrayList<>(); | 275 | List<FlowEntry> toRemove = new ArrayList<>(); |
| 255 | List<FlowEntry> toAdd = new ArrayList<>(); | 276 | List<FlowEntry> toAdd = new ArrayList<>(); |
| 256 | // TODO: backup changes to hazelcast map | 277 | // TODO: backup changes to hazelcast map |
| ... | @@ -261,8 +282,8 @@ public class DistributedFlowRuleStore | ... | @@ -261,8 +282,8 @@ public class DistributedFlowRuleStore |
| 261 | StoredFlowEntry entry = getFlowEntryInternal(flowRule); | 282 | StoredFlowEntry entry = getFlowEntryInternal(flowRule); |
| 262 | if (entry != null) { | 283 | if (entry != null) { |
| 263 | entry.setState(FlowEntryState.PENDING_REMOVE); | 284 | entry.setState(FlowEntryState.PENDING_REMOVE); |
| 285 | + toRemove.add(entry); | ||
| 264 | } | 286 | } |
| 265 | - toRemove.add(entry); | ||
| 266 | } else if (op.equals(FlowRuleOperation.ADD)) { | 287 | } else if (op.equals(FlowRuleOperation.ADD)) { |
| 267 | StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule); | 288 | StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule); |
| 268 | DeviceId deviceId = flowRule.deviceId(); | 289 | DeviceId deviceId = flowRule.deviceId(); |
| ... | @@ -276,9 +297,13 @@ public class DistributedFlowRuleStore | ... | @@ -276,9 +297,13 @@ public class DistributedFlowRuleStore |
| 276 | if (toAdd.isEmpty() && toRemove.isEmpty()) { | 297 | if (toAdd.isEmpty() && toRemove.isEmpty()) { |
| 277 | return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet())); | 298 | return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet())); |
| 278 | } | 299 | } |
| 279 | - notifyDelegate(FlowRuleBatchEvent.create(new FlowRuleBatchRequest(toAdd, toRemove))); | 300 | + |
| 280 | - // TODO: imlpement this. | 301 | + SettableFuture<CompletedBatchOperation> r = SettableFuture.create(); |
| 281 | - return Futures.immediateFailedFuture(new RuntimeException("Implement this.")); | 302 | + final int batchId = localBatchIdGen.incrementAndGet(); |
| 303 | + | ||
| 304 | + pendingFutures.put(batchId, r); | ||
| 305 | + notifyDelegate(FlowRuleBatchEvent.requested(new FlowRuleBatchRequest(batchId, toAdd, toRemove))); | ||
| 306 | + return r; | ||
| 282 | } | 307 | } |
| 283 | 308 | ||
| 284 | @Override | 309 | @Override |
| ... | @@ -293,18 +318,9 @@ public class DistributedFlowRuleStore | ... | @@ -293,18 +318,9 @@ public class DistributedFlowRuleStore |
| 293 | return addOrUpdateFlowRuleInternal(rule); | 318 | return addOrUpdateFlowRuleInternal(rule); |
| 294 | } | 319 | } |
| 295 | 320 | ||
| 296 | - ClusterMessage message = new ClusterMessage( | 321 | + log.error("Tried to update FlowRule {} state," |
| 297 | - clusterService.getLocalNode().id(), | 322 | + + " while the Node was not the master.", rule); |
| 298 | - FlowStoreMessageSubjects.ADD_OR_UPDATE_FLOW_RULE, | 323 | + return null; |
| 299 | - SERIALIZER.encode(rule)); | ||
| 300 | - | ||
| 301 | - try { | ||
| 302 | - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | ||
| 303 | - return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); | ||
| 304 | - } catch (IOException | TimeoutException e) { | ||
| 305 | - // FIXME: throw a FlowStoreException | ||
| 306 | - throw new RuntimeException(e); | ||
| 307 | - } | ||
| 308 | } | 324 | } |
| 309 | 325 | ||
| 310 | private synchronized FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) { | 326 | private synchronized FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) { |
| ... | @@ -338,18 +354,9 @@ public class DistributedFlowRuleStore | ... | @@ -338,18 +354,9 @@ public class DistributedFlowRuleStore |
| 338 | return removeFlowRuleInternal(rule); | 354 | return removeFlowRuleInternal(rule); |
| 339 | } | 355 | } |
| 340 | 356 | ||
| 341 | - ClusterMessage message = new ClusterMessage( | 357 | + log.error("Tried to remove FlowRule {}," |
| 342 | - clusterService.getLocalNode().id(), | 358 | + + " while the Node was not the master.", rule); |
| 343 | - FlowStoreMessageSubjects.REMOVE_FLOW_RULE, | 359 | + return null; |
| 344 | - SERIALIZER.encode(rule)); | ||
| 345 | - | ||
| 346 | - try { | ||
| 347 | - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | ||
| 348 | - return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); | ||
| 349 | - } catch (IOException | TimeoutException e) { | ||
| 350 | - // FIXME: throw a FlowStoreException | ||
| 351 | - throw new RuntimeException(e); | ||
| 352 | - } | ||
| 353 | } | 360 | } |
| 354 | 361 | ||
| 355 | private synchronized FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) { | 362 | private synchronized FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) { |
| ... | @@ -364,6 +371,11 @@ public class DistributedFlowRuleStore | ... | @@ -364,6 +371,11 @@ public class DistributedFlowRuleStore |
| 364 | 371 | ||
| 365 | @Override | 372 | @Override |
| 366 | public void batchOperationComplete(FlowRuleBatchEvent event) { | 373 | public void batchOperationComplete(FlowRuleBatchEvent event) { |
| 374 | + SettableFuture<CompletedBatchOperation> future | ||
| 375 | + = pendingFutures.get(event.subject().batchId()); | ||
| 376 | + if (future != null) { | ||
| 377 | + future.set(event.result()); | ||
| 378 | + } | ||
| 367 | notifyDelegate(event); | 379 | notifyDelegate(event); |
| 368 | } | 380 | } |
| 369 | } | 381 | } | ... | ... |
| ... | @@ -7,10 +7,10 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject; | ... | @@ -7,10 +7,10 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject; |
| 7 | */ | 7 | */ |
| 8 | public final class FlowStoreMessageSubjects { | 8 | public final class FlowStoreMessageSubjects { |
| 9 | private FlowStoreMessageSubjects() {} | 9 | private FlowStoreMessageSubjects() {} |
| 10 | - public static final MessageSubject STORE_FLOW_RULE = new MessageSubject("peer-forward-store-flow-rule"); | 10 | + |
| 11 | - public static final MessageSubject DELETE_FLOW_RULE = new MessageSubject("peer-forward-delete-flow-rule"); | 11 | + public static final MessageSubject APPLY_BATCH_FLOWS |
| 12 | - public static final MessageSubject ADD_OR_UPDATE_FLOW_RULE = | 12 | + = new MessageSubject("peer-forward-apply-batch"); |
| 13 | - new MessageSubject("peer-forward-add-or-update-flow-rule"); | 13 | + |
| 14 | - public static final MessageSubject REMOVE_FLOW_RULE = new MessageSubject("peer-forward-remove-flow-rule"); | 14 | + public static final MessageSubject GET_FLOW_ENTRY |
| 15 | - public static final MessageSubject GET_FLOW_ENTRY = new MessageSubject("peer-forward-get-flow-entry"); | 15 | + = new MessageSubject("peer-forward-get-flow-entry"); |
| 16 | } | 16 | } | ... | ... |
| ... | @@ -58,7 +58,6 @@ implements MastershipStore { | ... | @@ -58,7 +58,6 @@ implements MastershipStore { |
| 58 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 58 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 59 | protected ClusterService clusterService; | 59 | protected ClusterService clusterService; |
| 60 | 60 | ||
| 61 | - @SuppressWarnings({ "unchecked", "rawtypes" }) | ||
| 62 | @Override | 61 | @Override |
| 63 | @Activate | 62 | @Activate |
| 64 | public void activate() { | 63 | public void activate() { |
| ... | @@ -76,9 +75,9 @@ implements MastershipStore { | ... | @@ -76,9 +75,9 @@ implements MastershipStore { |
| 76 | } | 75 | } |
| 77 | }; | 76 | }; |
| 78 | 77 | ||
| 79 | - roleMap = new SMap(theInstance.getMap("nodeRoles"), this.serializer); | 78 | + roleMap = new SMap<>(theInstance.<byte[], byte[]>getMap("nodeRoles"), this.serializer); |
| 80 | roleMap.addEntryListener((new RemoteMasterShipEventHandler()), true); | 79 | roleMap.addEntryListener((new RemoteMasterShipEventHandler()), true); |
| 81 | - terms = new SMap(theInstance.getMap("terms"), this.serializer); | 80 | + terms = new SMap<>(theInstance.<byte[], byte[]>getMap("terms"), this.serializer); |
| 82 | clusterSize = theInstance.getAtomicLong("clustersize"); | 81 | clusterSize = theInstance.getAtomicLong("clustersize"); |
| 83 | 82 | ||
| 84 | log.info("Started"); | 83 | log.info("Started"); | ... | ... |
| ... | @@ -5,6 +5,7 @@ import java.util.ArrayList; | ... | @@ -5,6 +5,7 @@ import java.util.ArrayList; |
| 5 | import java.util.Arrays; | 5 | import java.util.Arrays; |
| 6 | import java.util.HashMap; | 6 | import java.util.HashMap; |
| 7 | import java.util.HashSet; | 7 | import java.util.HashSet; |
| 8 | +import java.util.LinkedList; | ||
| 8 | 9 | ||
| 9 | import org.onlab.onos.cluster.ControllerNode; | 10 | import org.onlab.onos.cluster.ControllerNode; |
| 10 | import org.onlab.onos.cluster.DefaultControllerNode; | 11 | import org.onlab.onos.cluster.DefaultControllerNode; |
| ... | @@ -27,12 +28,15 @@ import org.onlab.onos.net.Port; | ... | @@ -27,12 +28,15 @@ import org.onlab.onos.net.Port; |
| 27 | import org.onlab.onos.net.PortNumber; | 28 | import org.onlab.onos.net.PortNumber; |
| 28 | import org.onlab.onos.net.device.DefaultDeviceDescription; | 29 | import org.onlab.onos.net.device.DefaultDeviceDescription; |
| 29 | import org.onlab.onos.net.device.DefaultPortDescription; | 30 | import org.onlab.onos.net.device.DefaultPortDescription; |
| 31 | +import org.onlab.onos.net.flow.CompletedBatchOperation; | ||
| 30 | import org.onlab.onos.net.flow.DefaultFlowEntry; | 32 | import org.onlab.onos.net.flow.DefaultFlowEntry; |
| 31 | import org.onlab.onos.net.flow.DefaultFlowRule; | 33 | import org.onlab.onos.net.flow.DefaultFlowRule; |
| 32 | import org.onlab.onos.net.flow.DefaultTrafficSelector; | 34 | import org.onlab.onos.net.flow.DefaultTrafficSelector; |
| 33 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; | 35 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; |
| 34 | import org.onlab.onos.net.flow.FlowEntry; | 36 | import org.onlab.onos.net.flow.FlowEntry; |
| 35 | import org.onlab.onos.net.flow.FlowId; | 37 | import org.onlab.onos.net.flow.FlowId; |
| 38 | +import org.onlab.onos.net.flow.FlowRuleBatchEntry; | ||
| 39 | +import org.onlab.onos.net.flow.FlowRuleBatchOperation; | ||
| 36 | import org.onlab.onos.net.flow.StoredFlowEntry; | 40 | import org.onlab.onos.net.flow.StoredFlowEntry; |
| 37 | import org.onlab.onos.net.flow.criteria.Criteria; | 41 | import org.onlab.onos.net.flow.criteria.Criteria; |
| 38 | import org.onlab.onos.net.flow.criteria.Criterion; | 42 | import org.onlab.onos.net.flow.criteria.Criterion; |
| ... | @@ -80,6 +84,7 @@ public final class KryoNamespaces { | ... | @@ -80,6 +84,7 @@ public final class KryoNamespaces { |
| 80 | Arrays.asList().getClass(), | 84 | Arrays.asList().getClass(), |
| 81 | HashMap.class, | 85 | HashMap.class, |
| 82 | HashSet.class, | 86 | HashSet.class, |
| 87 | + LinkedList.class, | ||
| 83 | // | 88 | // |
| 84 | // | 89 | // |
| 85 | ControllerNode.State.class, | 90 | ControllerNode.State.class, |
| ... | @@ -118,7 +123,11 @@ public final class KryoNamespaces { | ... | @@ -118,7 +123,11 @@ public final class KryoNamespaces { |
| 118 | DefaultTrafficTreatment.class, | 123 | DefaultTrafficTreatment.class, |
| 119 | Instructions.DropInstruction.class, | 124 | Instructions.DropInstruction.class, |
| 120 | Instructions.OutputInstruction.class, | 125 | Instructions.OutputInstruction.class, |
| 121 | - RoleInfo.class | 126 | + RoleInfo.class, |
| 127 | + FlowRuleBatchOperation.class, | ||
| 128 | + CompletedBatchOperation.class, | ||
| 129 | + FlowRuleBatchEntry.class, | ||
| 130 | + FlowRuleBatchEntry.FlowRuleOperation.class | ||
| 122 | ) | 131 | ) |
| 123 | .register(URI.class, new URISerializer()) | 132 | .register(URI.class, new URISerializer()) |
| 124 | .register(NodeId.class, new NodeIdSerializer()) | 133 | .register(NodeId.class, new NodeIdSerializer()) | ... | ... |
| ... | @@ -176,8 +176,8 @@ public class SimpleFlowRuleStore | ... | @@ -176,8 +176,8 @@ public class SimpleFlowRuleStore |
| 176 | } | 176 | } |
| 177 | // new flow rule added | 177 | // new flow rule added |
| 178 | existing.add(f); | 178 | existing.add(f); |
| 179 | - notifyDelegate(FlowRuleBatchEvent.create( | 179 | + notifyDelegate(FlowRuleBatchEvent.requested( |
| 180 | - new FlowRuleBatchRequest( | 180 | + new FlowRuleBatchRequest( 1, /* FIXME generate something */ |
| 181 | Arrays.<FlowEntry>asList(f), | 181 | Arrays.<FlowEntry>asList(f), |
| 182 | Collections.<FlowEntry>emptyList()))); | 182 | Collections.<FlowEntry>emptyList()))); |
| 183 | } | 183 | } |
| ... | @@ -194,8 +194,8 @@ public class SimpleFlowRuleStore | ... | @@ -194,8 +194,8 @@ public class SimpleFlowRuleStore |
| 194 | synchronized (entry) { | 194 | synchronized (entry) { |
| 195 | entry.setState(FlowEntryState.PENDING_REMOVE); | 195 | entry.setState(FlowEntryState.PENDING_REMOVE); |
| 196 | // TODO: Should we notify only if it's "remote" event? | 196 | // TODO: Should we notify only if it's "remote" event? |
| 197 | - notifyDelegate(FlowRuleBatchEvent.create( | 197 | + notifyDelegate(FlowRuleBatchEvent.requested( |
| 198 | - new FlowRuleBatchRequest( | 198 | + new FlowRuleBatchRequest(1, /* FIXME generate something */ |
| 199 | Collections.<FlowEntry>emptyList(), | 199 | Collections.<FlowEntry>emptyList(), |
| 200 | Arrays.<FlowEntry>asList(entry)))); | 200 | Arrays.<FlowEntry>asList(entry)))); |
| 201 | } | 201 | } | ... | ... |
-
Please register or login to post a comment