blob: 580931861798fe229a6eadb62bd2235e5a87a912 [file] [log] [blame]
Madan Jampani28b2cd62016-02-02 10:49:52 -08001package org.onosproject.store.primitives;
2
Madan Jampani7c521002015-03-23 12:23:01 -07003/*
Madan Jampani28b2cd62016-02-02 10:49:52 -08004 * Copyright 2016 Open Networking Laboratory
Madan Jampani7c521002015-03-23 12:23:01 -07005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
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;
28import java.util.function.Function;
29import java.util.function.Predicate;
Madan Jampani7c521002015-03-23 12:23:01 -070030
Madan Jampanif6c973a2016-01-30 22:20:48 -080031import org.onlab.util.Tools;
Madan Jampania090a112016-01-18 16:38:17 -080032import org.onosproject.store.service.AsyncConsistentMap;
Madan Jampani7c521002015-03-23 12:23:01 -070033import org.onosproject.store.service.ConsistentMap;
34import org.onosproject.store.service.ConsistentMapException;
Madan Jampanif6c973a2016-01-30 22:20:48 -080035import org.onosproject.store.service.ConsistentMapException.ConcurrentModification;
Madan Jampani50589ac2015-06-08 11:38:46 -070036import org.onosproject.store.service.MapEventListener;
Madan Jampania090a112016-01-18 16:38:17 -080037import org.onosproject.store.service.Synchronous;
Madan Jampani7c521002015-03-23 12:23:01 -070038import org.onosproject.store.service.Versioned;
39
Madan Jampanif6c973a2016-01-30 22:20:48 -080040import com.google.common.base.Throwables;
41
Madan Jampani7c521002015-03-23 12:23:01 -070042/**
Madan Jampanifa242182016-01-22 13:42:54 -080043 * Default implementation of {@code ConsistentMap}.
Madan Jampani7c521002015-03-23 12:23:01 -070044 *
45 * @param <K> type of key.
46 * @param <V> type of value.
47 */
Madan Jampania090a112016-01-18 16:38:17 -080048public class DefaultConsistentMap<K, V> extends Synchronous<AsyncConsistentMap<K, V>> implements ConsistentMap<K, V> {
Madan Jampani7c521002015-03-23 12:23:01 -070049
Madan Jampanif6c973a2016-01-30 22:20:48 -080050 private static final int MAX_DELAY_BETWEEN_RETY_MILLS = 50;
Madan Jampanifa242182016-01-22 13:42:54 -080051 private final AsyncConsistentMap<K, V> asyncMap;
Madan Jampani28b2cd62016-02-02 10:49:52 -080052 private final long operationTimeoutMillis;
Madan Jampanie1065222015-08-17 16:21:51 -070053 private Map<K, V> javaMap;
Madan Jampani7c521002015-03-23 12:23:01 -070054
Madan Jampani28b2cd62016-02-02 10:49:52 -080055 public DefaultConsistentMap(AsyncConsistentMap<K, V> asyncMap, long operationTimeoutMillis) {
Madan Jampania090a112016-01-18 16:38:17 -080056 super(asyncMap);
Madan Jampani50589ac2015-06-08 11:38:46 -070057 this.asyncMap = asyncMap;
Madan Jampani28b2cd62016-02-02 10:49:52 -080058 this.operationTimeoutMillis = operationTimeoutMillis;
Madan Jampani7c521002015-03-23 12:23:01 -070059 }
60
61 @Override
62 public int size() {
63 return complete(asyncMap.size());
64 }
65
66 @Override
67 public boolean isEmpty() {
68 return complete(asyncMap.isEmpty());
69 }
70
71 @Override
72 public boolean containsKey(K key) {
73 return complete(asyncMap.containsKey(key));
74 }
75
76 @Override
77 public boolean containsValue(V value) {
78 return complete(asyncMap.containsValue(value));
79 }
80
81 @Override
82 public Versioned<V> get(K key) {
83 return complete(asyncMap.get(key));
84 }
85
86 @Override
Madan Jampani346d4f52015-05-04 11:09:39 -070087 public Versioned<V> computeIfAbsent(K key,
88 Function<? super K, ? extends V> mappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -080089 return computeIf(key, Objects::isNull, (k, v) -> mappingFunction.apply(k));
Madan Jampani346d4f52015-05-04 11:09:39 -070090 }
91
92 @Override
93 public Versioned<V> computeIfPresent(K key,
94 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -080095 return computeIf(key, Objects::nonNull, remappingFunction);
Madan Jampani346d4f52015-05-04 11:09:39 -070096 }
97
98 @Override
99 public Versioned<V> compute(K key,
100 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800101 return computeIf(key, v -> true, remappingFunction);
Madan Jampani346d4f52015-05-04 11:09:39 -0700102 }
103
104 @Override
105 public Versioned<V> computeIf(K key,
106 Predicate<? super V> condition,
107 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800108 return Tools.retryable(() -> complete(asyncMap.computeIf(key, condition, remappingFunction)),
109 ConcurrentModification.class,
110 Integer.MAX_VALUE,
111 MAX_DELAY_BETWEEN_RETY_MILLS).get();
Madan Jampani346d4f52015-05-04 11:09:39 -0700112 }
113
114 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700115 public Versioned<V> put(K key, V value) {
116 return complete(asyncMap.put(key, value));
117 }
118
119 @Override
Madan Jampani346d4f52015-05-04 11:09:39 -0700120 public Versioned<V> putAndGet(K key, V value) {
121 return complete(asyncMap.putAndGet(key, value));
122 }
123
124 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700125 public Versioned<V> remove(K key) {
126 return complete(asyncMap.remove(key));
127 }
128
129 @Override
130 public void clear() {
131 complete(asyncMap.clear());
132 }
133
134 @Override
135 public Set<K> keySet() {
136 return complete(asyncMap.keySet());
137 }
138
139 @Override
140 public Collection<Versioned<V>> values() {
141 return complete(asyncMap.values());
142 }
143
144 @Override
145 public Set<Entry<K, Versioned<V>>> entrySet() {
146 return complete(asyncMap.entrySet());
147 }
148
149 @Override
150 public Versioned<V> putIfAbsent(K key, V value) {
151 return complete(asyncMap.putIfAbsent(key, value));
152 }
153
154 @Override
155 public boolean remove(K key, V value) {
156 return complete(asyncMap.remove(key, value));
157 }
158
159 @Override
160 public boolean remove(K key, long version) {
161 return complete(asyncMap.remove(key, version));
162 }
163
164 @Override
Jihwan Kim9887ad92015-12-12 00:23:57 +0900165 public Versioned<V> replace(K key, V value) {
166 return complete(asyncMap.replace(key, value));
167 }
168
169 @Override
Madan Jampani7c521002015-03-23 12:23:01 -0700170 public boolean replace(K key, V oldValue, V newValue) {
171 return complete(asyncMap.replace(key, oldValue, newValue));
172 }
173
174 @Override
175 public boolean replace(K key, long oldVersion, V newValue) {
176 return complete(asyncMap.replace(key, oldVersion, newValue));
177 }
178
Madan Jampanifa242182016-01-22 13:42:54 -0800179 @Override
180 public void addListener(MapEventListener<K, V> listener) {
181 complete(asyncMap.addListener(listener));
182 }
183
184 @Override
185 public void removeListener(MapEventListener<K, V> listener) {
186 complete(asyncMap.addListener(listener));
187 }
188
189 @Override
190 public Map<K, V> asJavaMap() {
191 synchronized (this) {
192 if (javaMap == null) {
193 javaMap = new ConsistentMapBackedJavaMap<>(this);
194 }
195 }
196 return javaMap;
197 }
198
HIGUCHI Yutadc4394c2016-01-29 15:35:10 -0800199 @Override
200 public String toString() {
201 return asJavaMap().toString();
202 }
203
Madan Jampani28b2cd62016-02-02 10:49:52 -0800204 private <T> T complete(CompletableFuture<T> future) {
Madan Jampani7c521002015-03-23 12:23:01 -0700205 try {
Madan Jampani28b2cd62016-02-02 10:49:52 -0800206 return future.get(operationTimeoutMillis, TimeUnit.MILLISECONDS);
Madan Jampani7c521002015-03-23 12:23:01 -0700207 } catch (InterruptedException e) {
208 Thread.currentThread().interrupt();
209 throw new ConsistentMapException.Interrupted();
210 } catch (TimeoutException e) {
211 throw new ConsistentMapException.Timeout();
212 } catch (ExecutionException e) {
Madan Jampanif6c973a2016-01-30 22:20:48 -0800213 Throwables.propagateIfPossible(e.getCause());
214 throw new ConsistentMapException(e.getCause());
Madan Jampani7c521002015-03-23 12:23:01 -0700215 }
216 }
Madan Jampani7c521002015-03-23 12:23:01 -0700217}