Yuta HIGUCHI

FlowRule : handle Future failure and timeouts.

Change-Id: Ie945b7ee936ae48ec3205592c309baebe8538ce0
...@@ -21,6 +21,7 @@ import com.google.common.collect.Lists; ...@@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
21 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
22 import com.google.common.collect.Multimap; 22 import com.google.common.collect.Multimap;
23 import com.google.common.collect.Sets; 23 import com.google.common.collect.Sets;
24 +
24 import org.apache.felix.scr.annotations.Activate; 25 import org.apache.felix.scr.annotations.Activate;
25 import org.apache.felix.scr.annotations.Component; 26 import org.apache.felix.scr.annotations.Component;
26 import org.apache.felix.scr.annotations.Deactivate; 27 import org.apache.felix.scr.annotations.Deactivate;
...@@ -54,6 +55,7 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; ...@@ -54,6 +55,7 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
54 import org.onlab.onos.net.provider.AbstractProviderService; 55 import org.onlab.onos.net.provider.AbstractProviderService;
55 import org.slf4j.Logger; 56 import org.slf4j.Logger;
56 57
58 +import java.util.HashSet;
57 import java.util.List; 59 import java.util.List;
58 import java.util.Map; 60 import java.util.Map;
59 import java.util.Set; 61 import java.util.Set;
...@@ -389,15 +391,22 @@ public class FlowRuleManager ...@@ -389,15 +391,22 @@ public class FlowRuleManager
389 futureService.submit(new Runnable() { 391 futureService.submit(new Runnable() {
390 @Override 392 @Override
391 public void run() { 393 public void run() {
392 - CompletedBatchOperation res = null; 394 + CompletedBatchOperation res;
393 try { 395 try {
394 res = result.get(TIMEOUT, TimeUnit.MILLISECONDS); 396 res = result.get(TIMEOUT, TimeUnit.MILLISECONDS);
397 + store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res));
395 } catch (TimeoutException | InterruptedException | ExecutionException e) { 398 } catch (TimeoutException | InterruptedException | ExecutionException e) {
396 log.warn("Something went wrong with the batch operation {}", 399 log.warn("Something went wrong with the batch operation {}",
397 - request.batchId()); 400 + request.batchId(), e);
401 +
402 + Set<FlowRule> failures = new HashSet<>(batchOperation.size());
403 + for (FlowRuleBatchEntry op : batchOperation.getOperations()) {
404 + failures.add(op.getTarget());
398 } 405 }
406 + res = new CompletedBatchOperation(false, failures);
399 store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res)); 407 store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res));
400 } 408 }
409 + }
401 }); 410 });
402 break; 411 break;
403 412
......
...@@ -85,6 +85,8 @@ import com.google.common.cache.Cache; ...@@ -85,6 +85,8 @@ import com.google.common.cache.Cache;
85 import com.google.common.cache.CacheBuilder; 85 import com.google.common.cache.CacheBuilder;
86 import com.google.common.cache.CacheLoader; 86 import com.google.common.cache.CacheLoader;
87 import com.google.common.cache.LoadingCache; 87 import com.google.common.cache.LoadingCache;
88 +import com.google.common.cache.RemovalListener;
89 +import com.google.common.cache.RemovalNotification;
88 import com.google.common.collect.ArrayListMultimap; 90 import com.google.common.collect.ArrayListMultimap;
89 import com.google.common.collect.ImmutableList; 91 import com.google.common.collect.ImmutableList;
90 import com.google.common.collect.ImmutableSet; 92 import com.google.common.collect.ImmutableSet;
...@@ -132,8 +134,7 @@ public class DistributedFlowRuleStore ...@@ -132,8 +134,7 @@ public class DistributedFlowRuleStore
132 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = 134 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures =
133 CacheBuilder.newBuilder() 135 CacheBuilder.newBuilder()
134 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) 136 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES)
135 - // TODO Explicitly fail the future if expired? 137 + .removalListener(new TimeoutFuture())
136 - //.removalListener(listener)
137 .build(); 138 .build();
138 139
139 // Cache of SMaps used for backup data. each SMap contain device flow table 140 // Cache of SMaps used for backup data. each SMap contain device flow table
...@@ -541,6 +542,17 @@ public class DistributedFlowRuleStore ...@@ -541,6 +542,17 @@ public class DistributedFlowRuleStore
541 log.debug("removedFromPrimary {}", removed); 542 log.debug("removedFromPrimary {}", removed);
542 } 543 }
543 544
545 + private static final class TimeoutFuture
546 + implements RemovalListener<Integer, SettableFuture<CompletedBatchOperation>> {
547 + @Override
548 + public void onRemoval(RemovalNotification<Integer, SettableFuture<CompletedBatchOperation>> notification) {
549 + // wrapping in ExecutionException to support Future.get
550 + notification.getValue()
551 + .setException(new ExecutionException("Timed out",
552 + new TimeoutException()));
553 + }
554 + }
555 +
544 private final class OnStoreBatch implements ClusterMessageHandler { 556 private final class OnStoreBatch implements ClusterMessageHandler {
545 private final NodeId local; 557 private final NodeId local;
546 558
...@@ -580,7 +592,18 @@ public class DistributedFlowRuleStore ...@@ -580,7 +592,18 @@ public class DistributedFlowRuleStore
580 592
581 @Override 593 @Override
582 public void run() { 594 public void run() {
583 - CompletedBatchOperation result = Futures.getUnchecked(f); 595 + CompletedBatchOperation result;
596 + try {
597 + result = f.get();
598 + } catch (InterruptedException | ExecutionException e) {
599 + log.error("Batch operation failed", e);
600 + // create everything failed response
601 + Set<FlowRule> failures = new HashSet<>(operation.size());
602 + for (FlowRuleBatchEntry op : operation.getOperations()) {
603 + failures.add(op.getTarget());
604 + }
605 + result = new CompletedBatchOperation(false, failures);
606 + }
584 try { 607 try {
585 message.respond(SERIALIZER.encode(result)); 608 message.respond(SERIALIZER.encode(result));
586 } catch (IOException e) { 609 } catch (IOException e) {
......
...@@ -18,6 +18,8 @@ package org.onlab.onos.store.trivial.impl; ...@@ -18,6 +18,8 @@ package org.onlab.onos.store.trivial.impl;
18 import com.google.common.base.Function; 18 import com.google.common.base.Function;
19 import com.google.common.cache.Cache; 19 import com.google.common.cache.Cache;
20 import com.google.common.cache.CacheBuilder; 20 import com.google.common.cache.CacheBuilder;
21 +import com.google.common.cache.RemovalListener;
22 +import com.google.common.cache.RemovalNotification;
21 import com.google.common.collect.FluentIterable; 23 import com.google.common.collect.FluentIterable;
22 import com.google.common.util.concurrent.Futures; 24 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.SettableFuture; 25 import com.google.common.util.concurrent.SettableFuture;
...@@ -53,8 +55,10 @@ import java.util.List; ...@@ -53,8 +55,10 @@ import java.util.List;
53 import java.util.concurrent.ConcurrentHashMap; 55 import java.util.concurrent.ConcurrentHashMap;
54 import java.util.concurrent.ConcurrentMap; 56 import java.util.concurrent.ConcurrentMap;
55 import java.util.concurrent.CopyOnWriteArrayList; 57 import java.util.concurrent.CopyOnWriteArrayList;
58 +import java.util.concurrent.ExecutionException;
56 import java.util.concurrent.Future; 59 import java.util.concurrent.Future;
57 import java.util.concurrent.TimeUnit; 60 import java.util.concurrent.TimeUnit;
61 +import java.util.concurrent.TimeoutException;
58 import java.util.concurrent.atomic.AtomicInteger; 62 import java.util.concurrent.atomic.AtomicInteger;
59 63
60 import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; 64 import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
...@@ -86,8 +90,7 @@ public class SimpleFlowRuleStore ...@@ -86,8 +90,7 @@ public class SimpleFlowRuleStore
86 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = 90 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures =
87 CacheBuilder.newBuilder() 91 CacheBuilder.newBuilder()
88 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) 92 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES)
89 - // TODO Explicitly fail the future if expired? 93 + .removalListener(new TimeoutFuture())
90 - //.removalListener(listener)
91 .build(); 94 .build();
92 95
93 @Activate 96 @Activate
...@@ -303,4 +306,15 @@ public class SimpleFlowRuleStore ...@@ -303,4 +306,15 @@ public class SimpleFlowRuleStore
303 } 306 }
304 notifyDelegate(event); 307 notifyDelegate(event);
305 } 308 }
309 +
310 + private static final class TimeoutFuture
311 + implements RemovalListener<Integer, SettableFuture<CompletedBatchOperation>> {
312 + @Override
313 + public void onRemoval(RemovalNotification<Integer, SettableFuture<CompletedBatchOperation>> notification) {
314 + // wrapping in ExecutionException to support Future.get
315 + notification.getValue()
316 + .setException(new ExecutionException("Timed out",
317 + new TimeoutException()));
318 + }
319 + }
306 } 320 }
......