blob: 5360e502d37758e83eda84dd3137c734bd05326e [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;
25import java.util.concurrent.TimeUnit;
26import java.util.concurrent.TimeoutException;
Madan Jampani346d4f52015-05-04 11:09:39 -070027import java.util.function.BiFunction;
Madan Jampani1d3b6172016-04-28 13:22:57 -070028import java.util.function.Consumer;
Madan Jampani346d4f52015-05-04 11:09:39 -070029import java.util.function.Function;
30import java.util.function.Predicate;
Madan Jampani7c521002015-03-23 12:23:01 -070031
Madan Jampanif6c973a2016-01-30 22:20:48 -080032import org.onlab.util.Tools;
Madan Jampania090a112016-01-18 16:38:17 -080033import org.onosproject.store.service.AsyncConsistentMap;
Madan Jampani7c521002015-03-23 12:23:01 -070034import org.onosproject.store.service.ConsistentMap;
35import org.onosproject.store.service.ConsistentMapException;
Madan Jampanif6c973a2016-01-30 22:20:48 -080036import org.onosproject.store.service.ConsistentMapException.ConcurrentModification;
Madan Jampani50589ac2015-06-08 11:38:46 -070037import org.onosproject.store.service.MapEventListener;
Madan Jampania090a112016-01-18 16:38:17 -080038import org.onosproject.store.service.Synchronous;
Madan Jampani7c521002015-03-23 12:23:01 -070039import org.onosproject.store.service.Versioned;
40
Madan Jampanif6c973a2016-01-30 22:20:48 -080041import com.google.common.base.Throwables;
42
Madan Jampani7c521002015-03-23 12:23:01 -070043/**
Madan Jampanifa242182016-01-22 13:42:54 -080044 * Default implementation of {@code ConsistentMap}.
Madan Jampani7c521002015-03-23 12:23:01 -070045 *
46 * @param <K> type of key.
47 * @param <V> type of value.
48 */
Madan Jampania090a112016-01-18 16:38:17 -080049public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K, V>> implements ConsistentMap<K, V> {
Madan Jampani7c521002015-03-23 12:23:01 -070050
Madan Jampanif6c973a2016-01-30 22:20:48 -080051 private static final int MAX_DELAY_BETWEEN_RETY_MILLS = 50;
Madan Jampanifa242182016-01-22 13:42:54 -080052 private final AsyncConsistentMap<K, V> asyncMap;
Madan Jampani28b2cd62016-02-02 10:49:52 -080053 private final long operationTimeoutMillis;
Madan Jampanie1065222015-08-17 16:21:51 -070054 private Map<K, V> javaMap;
Madan Jampani7c521002015-03-23 12:23:01 -070055
Madan Jampani28b2cd62016-02-02 10:49:52 -080056 public DefaultConsistentMap(AsyncConsistentMap<K, V> asyncMap, long operationTimeoutMillis) {
Madan Jampania090a112016-01-18 16:38:17 -080057 super(asyncMap);
Madan Jampani50589ac2015-06-08 11:38:46 -070058 this.asyncMap = asyncMap;
Madan Jampani28b2cd62016-02-02 10:49:52 -080059 this.operationTimeoutMillis = operationTimeoutMillis;
Madan Jampani7c521002015-03-23 12:23:01 -070060 }
61
62 @Override
63 public int size() {
64 return complete(asyncMap.size());
65 }
66
67 @Override
68 public boolean isEmpty() {
69 return complete(asyncMap.isEmpty());
70 }
71
72 @Override
73 public boolean containsKey(K key) {
74 return complete(asyncMap.containsKey(key));
75 }
76
77 @Override
78 public boolean containsValue(V value) {
79 return complete(asyncMap.containsValue(value));
80 }
81
82 @Override
83 public Versioned<V> get(K key) {
84 return complete(asyncMap.get(key));
85 }
86
87 @Override
Madan Jampani346d4f52015-05-04 11:09:39 -070088 public Versioned<V> computeIfAbsent(K key,
89 Function<? super K, ? extends V> mappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -080090 return computeIf(key, Objects::isNull, (k, v) -> mappingFunction.apply(k));
Madan Jampani346d4f52015-05-04 11:09:39 -070091 }
92
93 @Override
94 public Versioned<V> computeIfPresent(K key,
95 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -080096 return computeIf(key, Objects::nonNull, remappingFunction);
Madan Jampani346d4f52015-05-04 11:09:39 -070097 }
98
99 @Override
100 public Versioned<V> compute(K key,
101 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800102 return computeIf(key, v -> true, remappingFunction);
Madan Jampani346d4f52015-05-04 11:09:39 -0700103 }
104
105 @Override
106 public Versioned<V> computeIf(K key,
107 Predicate<? super V> condition,
108 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800109 return Tools.retryable(() -> complete(asyncMap.computeIf(key, condition, remappingFunction)),
110 ConcurrentModification.class,
111 Integer.MAX_VALUE,
112 MAX_DELAY_BETWEEN_RETY_MILLS).get();
Madan Jampani346d4f52015-05-04 11:09:39 -0700113 }
114
115 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700116 public Versioned<V> put(K key, V value) {
117 return complete(asyncMap.put(key, value));
118 }
119
120 @Override
Madan Jampani346d4f52015-05-04 11:09:39 -0700121 public Versioned<V> putAndGet(K key, V value) {
122 return complete(asyncMap.putAndGet(key, value));
123 }
124
125 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700126 public Versioned<V> remove(K key) {
127 return complete(asyncMap.remove(key));
128 }
129
130 @Override
131 public void clear() {
132 complete(asyncMap.clear());
133 }
134
135 @Override
136 public Set<K> keySet() {
137 return complete(asyncMap.keySet());
138 }
139
140 @Override
141 public Collection<Versioned<V>> values() {
142 return complete(asyncMap.values());
143 }
144
145 @Override
146 public Set<Entry<K, Versioned<V>>> entrySet() {
147 return complete(asyncMap.entrySet());
148 }
149
150 @Override
151 public Versioned<V> putIfAbsent(K key, V value) {
152 return complete(asyncMap.putIfAbsent(key, value));
153 }
154
155 @Override
156 public boolean remove(K key, V value) {
157 return complete(asyncMap.remove(key, value));
158 }
159
160 @Override
161 public boolean remove(K key, long version) {
162 return complete(asyncMap.remove(key, version));
163 }
164
165 @Override
Jihwan Kim9887ad92015-12-12 00:23:57 +0900166 public Versioned<V> replace(K key, V value) {
167 return complete(asyncMap.replace(key, value));
168 }
169
170 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700171 public boolean replace(K key, V oldValue, V newValue) {
172 return complete(asyncMap.replace(key, oldValue, newValue));
173 }
174
175 @Override
176 public boolean replace(K key, long oldVersion, V newValue) {
177 return complete(asyncMap.replace(key, oldVersion, newValue));
178 }
179
Madan Jampanifa242182016-01-22 13:42:54 -0800180 @Override
181 public void addListener(MapEventListener<K, V> listener) {
182 complete(asyncMap.addListener(listener));
183 }
184
185 @Override
186 public void removeListener(MapEventListener<K, V> listener) {
187 complete(asyncMap.addListener(listener));
188 }
189
190 @Override
Madan Jampani1d3b6172016-04-28 13:22:57 -0700191 public void addStatusChangeListener(Consumer<Status> listener) {
192 asyncMap.addStatusChangeListener(listener);
193 }
194
195 @Override
196 public void removeStatusChangeListener(Consumer<Status> listener) {
197 asyncMap.removeStatusChangeListener(listener);
198 }
199
200 @Override
201 public Collection<Consumer<Status>> statusChangeListeners() {
202 return asyncMap.statusChangeListeners();
203 }
204
205 @Override
Madan Jampanifa242182016-01-22 13:42:54 -0800206 public Map<K, V> asJavaMap() {
207 synchronized (this) {
208 if (javaMap == null) {
209 javaMap = new ConsistentMapBackedJavaMap<>(this);
210 }
211 }
212 return javaMap;
213 }
214
HIGUCHI Yutadc4394c2016-01-29 15:35:10 -0800215 @Override
216 public String toString() {
217 return asJavaMap().toString();
218 }
219
Madan Jampani28b2cd62016-02-02 10:49:52 -0800220 private <T> T complete(CompletableFuture<T> future) {
Madan Jampani7c521002015-03-23 12:23:01 -0700221 try {
Madan Jampani28b2cd62016-02-02 10:49:52 -0800222 return future.get(operationTimeoutMillis, TimeUnit.MILLISECONDS);
Madan Jampani7c521002015-03-23 12:23:01 -0700223 } catch (InterruptedException e) {
224 Thread.currentThread().interrupt();
225 throw new ConsistentMapException.Interrupted();
226 } catch (TimeoutException e) {
227 throw new ConsistentMapException.Timeout();
228 } catch (ExecutionException e) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800229 Throwables.propagateIfPossible(e.getCause());
230 throw new ConsistentMapException(e.getCause());
Madan Jampani7c521002015-03-23 12:23:01 -0700231 }
232 }
Madan Jampani7c521002015-03-23 12:23:01 -0700233}