Madan Jampani
Committed by Gerrit Code Review

DefaultConsistentMap to automatically retry compute* calls failing due to ConcurrentModification

Change-Id: If59e432e423d323282eb8fe7b1b438899154aae9
...@@ -19,6 +19,7 @@ package org.onosproject.store.primitives.impl; ...@@ -19,6 +19,7 @@ package org.onosproject.store.primitives.impl;
19 import java.util.Collection; 19 import java.util.Collection;
20 import java.util.Map; 20 import java.util.Map;
21 import java.util.Map.Entry; 21 import java.util.Map.Entry;
22 +import java.util.Objects;
22 import java.util.Set; 23 import java.util.Set;
23 import java.util.concurrent.CompletableFuture; 24 import java.util.concurrent.CompletableFuture;
24 import java.util.concurrent.ExecutionException; 25 import java.util.concurrent.ExecutionException;
...@@ -28,14 +29,18 @@ import java.util.function.BiFunction; ...@@ -28,14 +29,18 @@ import java.util.function.BiFunction;
28 import java.util.function.Function; 29 import java.util.function.Function;
29 import java.util.function.Predicate; 30 import java.util.function.Predicate;
30 31
32 +import org.onlab.util.Tools;
31 import org.onosproject.store.primitives.ConsistentMapBackedJavaMap; 33 import org.onosproject.store.primitives.ConsistentMapBackedJavaMap;
32 import org.onosproject.store.service.AsyncConsistentMap; 34 import org.onosproject.store.service.AsyncConsistentMap;
33 import org.onosproject.store.service.ConsistentMap; 35 import org.onosproject.store.service.ConsistentMap;
34 import org.onosproject.store.service.ConsistentMapException; 36 import org.onosproject.store.service.ConsistentMapException;
37 +import org.onosproject.store.service.ConsistentMapException.ConcurrentModification;
35 import org.onosproject.store.service.MapEventListener; 38 import org.onosproject.store.service.MapEventListener;
36 import org.onosproject.store.service.Synchronous; 39 import org.onosproject.store.service.Synchronous;
37 import org.onosproject.store.service.Versioned; 40 import org.onosproject.store.service.Versioned;
38 41
42 +import com.google.common.base.Throwables;
43 +
39 /** 44 /**
40 * Default implementation of {@code ConsistentMap}. 45 * Default implementation of {@code ConsistentMap}.
41 * 46 *
...@@ -45,6 +50,7 @@ import org.onosproject.store.service.Versioned; ...@@ -45,6 +50,7 @@ import org.onosproject.store.service.Versioned;
45 public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K, V>> implements ConsistentMap<K, V> { 50 public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K, V>> implements ConsistentMap<K, V> {
46 51
47 private static final int OPERATION_TIMEOUT_MILLIS = 5000; 52 private static final int OPERATION_TIMEOUT_MILLIS = 5000;
53 + private static final int MAX_DELAY_BETWEEN_RETY_MILLS = 50;
48 54
49 private final AsyncConsistentMap<K, V> asyncMap; 55 private final AsyncConsistentMap<K, V> asyncMap;
50 private Map<K, V> javaMap; 56 private Map<K, V> javaMap;
...@@ -82,26 +88,29 @@ public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K ...@@ -82,26 +88,29 @@ public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K
82 @Override 88 @Override
83 public Versioned<V> computeIfAbsent(K key, 89 public Versioned<V> computeIfAbsent(K key,
84 Function<? super K, ? extends V> mappingFunction) { 90 Function<? super K, ? extends V> mappingFunction) {
85 - return complete(asyncMap.computeIfAbsent(key, mappingFunction)); 91 + return computeIf(key, Objects::isNull, (k, v) -> mappingFunction.apply(k));
86 } 92 }
87 93
88 @Override 94 @Override
89 public Versioned<V> computeIfPresent(K key, 95 public Versioned<V> computeIfPresent(K key,
90 BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 96 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
91 - return complete(asyncMap.computeIfPresent(key, remappingFunction)); 97 + return computeIf(key, Objects::nonNull, remappingFunction);
92 } 98 }
93 99
94 @Override 100 @Override
95 public Versioned<V> compute(K key, 101 public Versioned<V> compute(K key,
96 BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 102 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
97 - return complete(asyncMap.compute(key, remappingFunction)); 103 + return computeIf(key, v -> true, remappingFunction);
98 } 104 }
99 105
100 @Override 106 @Override
101 public Versioned<V> computeIf(K key, 107 public Versioned<V> computeIf(K key,
102 Predicate<? super V> condition, 108 Predicate<? super V> condition,
103 BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 109 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
104 - return complete(asyncMap.computeIf(key, condition, remappingFunction)); 110 + return Tools.retryable(() -> complete(asyncMap.computeIf(key, condition, remappingFunction)),
111 + ConcurrentModification.class,
112 + Integer.MAX_VALUE,
113 + MAX_DELAY_BETWEEN_RETY_MILLS).get();
105 } 114 }
106 115
107 @Override 116 @Override
...@@ -203,11 +212,8 @@ public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K ...@@ -203,11 +212,8 @@ public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K
203 } catch (TimeoutException e) { 212 } catch (TimeoutException e) {
204 throw new ConsistentMapException.Timeout(); 213 throw new ConsistentMapException.Timeout();
205 } catch (ExecutionException e) { 214 } catch (ExecutionException e) {
206 - if (e.getCause() instanceof ConsistentMapException) { 215 + Throwables.propagateIfPossible(e.getCause());
207 - throw (ConsistentMapException) e.getCause(); 216 + throw new ConsistentMapException(e.getCause());
208 - } else {
209 - throw new ConsistentMapException(e.getCause());
210 - }
211 } 217 }
212 } 218 }
213 } 219 }
...\ No newline at end of file ...\ No newline at end of file
......