blob: db6f548c1f6d3f99a83756f684ad1e600f5f7903 [file] [log] [blame]
Madan Jampani7c521002015-03-23 12:23:01 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Madan Jampani7c521002015-03-23 12:23:01 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connor7cbbbb72016-04-09 02:13:23 -070016package org.onosproject.store.primitives;
17
Madan Jampani7c521002015-03-23 12:23:01 -070018import java.util.Collection;
Madan Jampanie1065222015-08-17 16:21:51 -070019import java.util.Map;
Madan Jampani7c521002015-03-23 12:23:01 -070020import java.util.Map.Entry;
Madan Jampanif6c973a2016-01-30 22:20:48 -080021import java.util.Objects;
Madan Jampanifa242182016-01-22 13:42:54 -080022import java.util.Set;
Madan Jampani7c521002015-03-23 12:23:01 -070023import java.util.concurrent.CompletableFuture;
24import java.util.concurrent.ExecutionException;
Madan Jampani0463cf92016-05-04 14:46:08 -070025import java.util.concurrent.Executor;
Madan Jampani7c521002015-03-23 12:23:01 -070026import java.util.concurrent.TimeUnit;
27import java.util.concurrent.TimeoutException;
Madan Jampani346d4f52015-05-04 11:09:39 -070028import java.util.function.BiFunction;
Madan Jampani1d3b6172016-04-28 13:22:57 -070029import java.util.function.Consumer;
Madan Jampani346d4f52015-05-04 11:09:39 -070030import java.util.function.Function;
31import java.util.function.Predicate;
Madan Jampani7c521002015-03-23 12:23:01 -070032
Madan Jampanif6c973a2016-01-30 22:20:48 -080033import org.onlab.util.Tools;
Madan Jampania090a112016-01-18 16:38:17 -080034import org.onosproject.store.service.AsyncConsistentMap;
Madan Jampani7c521002015-03-23 12:23:01 -070035import org.onosproject.store.service.ConsistentMap;
36import org.onosproject.store.service.ConsistentMapException;
Madan Jampanif6c973a2016-01-30 22:20:48 -080037import org.onosproject.store.service.ConsistentMapException.ConcurrentModification;
Madan Jampani50589ac2015-06-08 11:38:46 -070038import org.onosproject.store.service.MapEventListener;
Madan Jampania090a112016-01-18 16:38:17 -080039import org.onosproject.store.service.Synchronous;
Madan Jampani7c521002015-03-23 12:23:01 -070040import org.onosproject.store.service.Versioned;
41
Madan Jampanif6c973a2016-01-30 22:20:48 -080042import com.google.common.base.Throwables;
43
Madan Jampani7c521002015-03-23 12:23:01 -070044/**
Madan Jampanifa242182016-01-22 13:42:54 -080045 * Default implementation of {@code ConsistentMap}.
Madan Jampani7c521002015-03-23 12:23:01 -070046 *
47 * @param <K> type of key.
48 * @param <V> type of value.
49 */
Madan Jampania090a112016-01-18 16:38:17 -080050public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K, V>> implements ConsistentMap<K, V> {
Madan Jampani7c521002015-03-23 12:23:01 -070051
Aaron Kruglikov2f2e81e2016-12-01 15:39:06 -080052 private static final int MAX_DELAY_BETWEEN_RETRY_MILLS = 50;
Madan Jampanifa242182016-01-22 13:42:54 -080053 private final AsyncConsistentMap<K, V> asyncMap;
Madan Jampani28b2cd62016-02-02 10:49:52 -080054 private final long operationTimeoutMillis;
Madan Jampanie1065222015-08-17 16:21:51 -070055 private Map<K, V> javaMap;
Madan Jampani7c521002015-03-23 12:23:01 -070056
Madan Jampani28b2cd62016-02-02 10:49:52 -080057 public DefaultConsistentMap(AsyncConsistentMap<K, V> asyncMap, long operationTimeoutMillis) {
Madan Jampania090a112016-01-18 16:38:17 -080058 super(asyncMap);
Madan Jampani50589ac2015-06-08 11:38:46 -070059 this.asyncMap = asyncMap;
Madan Jampani28b2cd62016-02-02 10:49:52 -080060 this.operationTimeoutMillis = operationTimeoutMillis;
Madan Jampani7c521002015-03-23 12:23:01 -070061 }
62
63 @Override
64 public int size() {
65 return complete(asyncMap.size());
66 }
67
68 @Override
69 public boolean isEmpty() {
70 return complete(asyncMap.isEmpty());
71 }
72
73 @Override
74 public boolean containsKey(K key) {
75 return complete(asyncMap.containsKey(key));
76 }
77
78 @Override
79 public boolean containsValue(V value) {
80 return complete(asyncMap.containsValue(value));
81 }
82
83 @Override
84 public Versioned<V> get(K key) {
85 return complete(asyncMap.get(key));
86 }
87
88 @Override
Jordan Haltermanf6272442017-04-20 02:18:08 -070089 public Versioned<V> getOrDefault(K key, V defaultValue) {
90 return complete(asyncMap.getOrDefault(key, defaultValue));
91 }
92
93 @Override
Madan Jampani346d4f52015-05-04 11:09:39 -070094 public Versioned<V> computeIfAbsent(K key,
95 Function<? super K, ? extends V> mappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -080096 return computeIf(key, Objects::isNull, (k, v) -> mappingFunction.apply(k));
Madan Jampani346d4f52015-05-04 11:09:39 -070097 }
98
99 @Override
100 public Versioned<V> computeIfPresent(K key,
101 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800102 return computeIf(key, Objects::nonNull, remappingFunction);
Madan Jampani346d4f52015-05-04 11:09:39 -0700103 }
104
105 @Override
106 public Versioned<V> compute(K key,
107 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800108 return computeIf(key, v -> true, remappingFunction);
Madan Jampani346d4f52015-05-04 11:09:39 -0700109 }
110
111 @Override
112 public Versioned<V> computeIf(K key,
113 Predicate<? super V> condition,
114 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800115 return Tools.retryable(() -> complete(asyncMap.computeIf(key, condition, remappingFunction)),
116 ConcurrentModification.class,
117 Integer.MAX_VALUE,
Aaron Kruglikov2f2e81e2016-12-01 15:39:06 -0800118 MAX_DELAY_BETWEEN_RETRY_MILLS).get();
Madan Jampani346d4f52015-05-04 11:09:39 -0700119 }
120
121 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700122 public Versioned<V> put(K key, V value) {
123 return complete(asyncMap.put(key, value));
124 }
125
126 @Override
Madan Jampani346d4f52015-05-04 11:09:39 -0700127 public Versioned<V> putAndGet(K key, V value) {
128 return complete(asyncMap.putAndGet(key, value));
129 }
130
131 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700132 public Versioned<V> remove(K key) {
133 return complete(asyncMap.remove(key));
134 }
135
136 @Override
137 public void clear() {
138 complete(asyncMap.clear());
139 }
140
141 @Override
142 public Set<K> keySet() {
143 return complete(asyncMap.keySet());
144 }
145
146 @Override
147 public Collection<Versioned<V>> values() {
148 return complete(asyncMap.values());
149 }
150
151 @Override
152 public Set<Entry<K, Versioned<V>>> entrySet() {
153 return complete(asyncMap.entrySet());
154 }
155
156 @Override
157 public Versioned<V> putIfAbsent(K key, V value) {
158 return complete(asyncMap.putIfAbsent(key, value));
159 }
160
161 @Override
162 public boolean remove(K key, V value) {
163 return complete(asyncMap.remove(key, value));
164 }
165
166 @Override
167 public boolean remove(K key, long version) {
168 return complete(asyncMap.remove(key, version));
169 }
170
171 @Override
Jihwan Kim9887ad92015-12-12 00:23:57 +0900172 public Versioned<V> replace(K key, V value) {
173 return complete(asyncMap.replace(key, value));
174 }
175
176 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700177 public boolean replace(K key, V oldValue, V newValue) {
178 return complete(asyncMap.replace(key, oldValue, newValue));
179 }
180
181 @Override
182 public boolean replace(K key, long oldVersion, V newValue) {
183 return complete(asyncMap.replace(key, oldVersion, newValue));
184 }
185
Madan Jampanifa242182016-01-22 13:42:54 -0800186 @Override
Madan Jampani0463cf92016-05-04 14:46:08 -0700187 public void addListener(MapEventListener<K, V> listener, Executor executor) {
188 complete(asyncMap.addListener(listener, executor));
Madan Jampanifa242182016-01-22 13:42:54 -0800189 }
190
191 @Override
192 public void removeListener(MapEventListener<K, V> listener) {
Hyunsun Moon65b38cb2016-05-06 18:27:37 -0700193 complete(asyncMap.removeListener(listener));
Madan Jampanifa242182016-01-22 13:42:54 -0800194 }
195
196 @Override
Madan Jampani1d3b6172016-04-28 13:22:57 -0700197 public void addStatusChangeListener(Consumer<Status> listener) {
198 asyncMap.addStatusChangeListener(listener);
199 }
200
201 @Override
202 public void removeStatusChangeListener(Consumer<Status> listener) {
203 asyncMap.removeStatusChangeListener(listener);
204 }
205
206 @Override
207 public Collection<Consumer<Status>> statusChangeListeners() {
208 return asyncMap.statusChangeListeners();
209 }
210
211 @Override
Madan Jampanifa242182016-01-22 13:42:54 -0800212 public Map<K, V> asJavaMap() {
213 synchronized (this) {
214 if (javaMap == null) {
215 javaMap = new ConsistentMapBackedJavaMap<>(this);
216 }
217 }
218 return javaMap;
219 }
220
HIGUCHI Yutadc4394c2016-01-29 15:35:10 -0800221 @Override
222 public String toString() {
223 return asJavaMap().toString();
224 }
225
Madan Jampani28b2cd62016-02-02 10:49:52 -0800226 private <T> T complete(CompletableFuture<T> future) {
Madan Jampani7c521002015-03-23 12:23:01 -0700227 try {
Madan Jampani28b2cd62016-02-02 10:49:52 -0800228 return future.get(operationTimeoutMillis, TimeUnit.MILLISECONDS);
Madan Jampani7c521002015-03-23 12:23:01 -0700229 } catch (InterruptedException e) {
230 Thread.currentThread().interrupt();
231 throw new ConsistentMapException.Interrupted();
232 } catch (TimeoutException e) {
Madan Jampani42755872016-09-06 19:31:06 -0700233 throw new ConsistentMapException.Timeout(name());
Madan Jampani7c521002015-03-23 12:23:01 -0700234 } catch (ExecutionException e) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800235 Throwables.propagateIfPossible(e.getCause());
236 throw new ConsistentMapException(e.getCause());
Madan Jampani7c521002015-03-23 12:23:01 -0700237 }
238 }
Madan Jampani7c521002015-03-23 12:23:01 -0700239}