blob: 57b36abe28a24143d7c603ed882dee0d444c7f88 [file] [log] [blame]
Ray Milkey6f440332015-07-31 10:40:53 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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 */
16package org.onosproject.store.service;
17
18import java.util.Collection;
19import java.util.HashMap;
20import java.util.LinkedList;
21import java.util.List;
22import java.util.Map;
23import java.util.Set;
alshabibe1248b62015-08-20 17:21:55 -070024import java.util.concurrent.atomic.AtomicLong;
Ray Milkey6f440332015-07-31 10:40:53 -070025import java.util.function.BiFunction;
26import java.util.function.Function;
27import java.util.function.Predicate;
28import java.util.stream.Collectors;
29
30import org.onosproject.core.ApplicationId;
31import static org.onosproject.store.service.MapEvent.Type;
32import static org.onosproject.store.service.MapEvent.Type.*;
33
34/**
35 * Test implementation of the consistent map.
36 */
37public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
38
39 private final List<MapEventListener<K, V>> listeners;
40 private final HashMap<K, V> map;
41 private final String mapName;
alshabibe1248b62015-08-20 17:21:55 -070042 private final AtomicLong counter = new AtomicLong(0);
Ray Milkey6f440332015-07-31 10:40:53 -070043
44 private TestConsistentMap(String mapName) {
45 map = new HashMap<>();
46 listeners = new LinkedList<>();
47 this.mapName = mapName;
48 }
49
50 private Versioned<V> version(V v) {
alshabibe1248b62015-08-20 17:21:55 -070051 return new Versioned<>(v, counter.incrementAndGet(), System.currentTimeMillis());
Ray Milkey6f440332015-07-31 10:40:53 -070052 }
53
54 /**
55 * Notify all listeners of an event.
56 */
57 private void notifyListeners(String mapName, Type type,
58 K key, Versioned<V> value) {
59 MapEvent<K, V> event = new MapEvent<>(mapName, type, key, value);
60 listeners.forEach(
61 listener -> listener.event(event)
62 );
63 }
64
65 @Override
66 public int size() {
67 return map.size();
68 }
69
70 @Override
71 public boolean isEmpty() {
72 return map.isEmpty();
73 }
74
75 @Override
76 public boolean containsKey(K key) {
77 return map.containsKey(key);
78 }
79
80 @Override
81 public boolean containsValue(V value) {
82 return map.containsValue(value);
83 }
84
85 @Override
86 public Versioned<V> get(K key) {
Ray Milkey24e60b32015-08-12 11:39:54 -070087 V value = map.get(key);
88 if (value != null) {
89 return version(value);
90 } else {
91 return null;
92 }
Ray Milkey6f440332015-07-31 10:40:53 -070093 }
94
95 @Override
96 public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
97 Versioned<V> result = version(map.computeIfAbsent(key, mappingFunction));
98 notifyListeners(mapName, INSERT, key, result);
99 return result;
100 }
101
102 @Override
103 public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
104 return version(map.compute(key, remappingFunction));
105 }
106
107 @Override
108 public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
109 return version(map.computeIfPresent(key, remappingFunction));
110 }
111
112 @Override
113 public Versioned<V> computeIf(K key, Predicate<? super V> condition,
114 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Brian O'Connorb2a383f2015-12-07 20:05:14 -0800115 return version(map.compute(key, (k, existingValue) -> {
116 if (condition.test(existingValue)) {
117 return remappingFunction.apply(k, existingValue);
118 } else {
119 return existingValue;
120 }
121 }));
Ray Milkey6f440332015-07-31 10:40:53 -0700122 }
123
124 @Override
125 public Versioned<V> put(K key, V value) {
alshabibe1248b62015-08-20 17:21:55 -0700126 Versioned<V> result = version(value);
127 if (map.put(key, value) == null) {
128 notifyListeners(mapName, INSERT, key, result);
129 } else {
130 notifyListeners(mapName, UPDATE, key, result);
131 }
Ray Milkey6f440332015-07-31 10:40:53 -0700132 return result;
133 }
134
135 @Override
136 public Versioned<V> putAndGet(K key, V value) {
137 Versioned<V> result = version(map.put(key, value));
138 notifyListeners(mapName, UPDATE, key, result);
139 return result;
140 }
141
142 @Override
143 public Versioned<V> remove(K key) {
144 Versioned<V> result = version(map.remove(key));
145 notifyListeners(mapName, REMOVE, key, result);
146 return result;
147 }
148
149 @Override
150 public void clear() {
151 map.clear();
152 }
153
154 @Override
155 public Set<K> keySet() {
156 return map.keySet();
157 }
158
159 @Override
160 public Collection<Versioned<V>> values() {
161 return map
162 .values()
163 .stream()
164 .map(this::version)
165 .collect(Collectors.toList());
166 }
167
168 @Override
169 public Set<Map.Entry<K, Versioned<V>>> entrySet() {
170 return super.entrySet();
171 }
172
173 @Override
174 public Versioned<V> putIfAbsent(K key, V value) {
175 Versioned<V> result = version(map.putIfAbsent(key, value));
176 if (map.get(key).equals(value)) {
177 notifyListeners(mapName, INSERT, key, result);
178 }
179 return result;
180 }
181
182 @Override
183 public boolean remove(K key, V value) {
184 boolean removed = map.remove(key, value);
185 if (removed) {
186 notifyListeners(mapName, REMOVE, key, null);
187 }
188 return removed;
189 }
190
191 @Override
192 public boolean remove(K key, long version) {
193 boolean removed = map.remove(key, version);
194 if (removed) {
195 notifyListeners(mapName, REMOVE, key, null);
196 }
197 return removed;
198 }
199
200 @Override
Jihwan Kim9887ad92015-12-12 00:23:57 +0900201 public Versioned<V> replace(K key, V value) {
202 Versioned<V> result = version(map.replace(key, value));
203 if (map.get(key).equals(value)) {
204 notifyListeners(mapName, UPDATE, key, result);
205 }
206 return result;
207 }
208
209 @Override
Ray Milkey6f440332015-07-31 10:40:53 -0700210 public boolean replace(K key, V oldValue, V newValue) {
211 boolean replaced = map.replace(key, oldValue, newValue);
212 if (replaced) {
213 notifyListeners(mapName, REMOVE, key, null);
214 }
215 return replaced;
216 }
217
218 @Override
219 public boolean replace(K key, long oldVersion, V newValue) {
220 boolean replaced = map.replace(key, map.get(key), newValue);
221 if (replaced) {
222 notifyListeners(mapName, REMOVE, key, null);
223 }
224 return replaced;
225 }
226
227 @Override
228 public void addListener(MapEventListener<K, V> listener) {
229 listeners.add(listener);
230 }
231
232 @Override
233 public void removeListener(MapEventListener<K, V> listener) {
234 listeners.remove(listener);
235 }
236
alshabibe1248b62015-08-20 17:21:55 -0700237 @Override
238 public Map<K, V> asJavaMap() {
239 return map;
240 }
241
Ray Milkey6f440332015-07-31 10:40:53 -0700242 public static Builder builder() {
243 return new Builder();
244 }
245
246 public static class Builder<K, V> implements ConsistentMapBuilder<K, V> {
247 String mapName = "map";
248
249 @Override
250 public ConsistentMapBuilder<K, V> withName(String mapName) {
251 this.mapName = mapName;
252 return this;
253 }
254
255 @Override
256 public ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id) {
257 return this;
258 }
259
260 @Override
261 public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) {
262 return this;
263 }
264
265 @Override
266 public ConsistentMapBuilder<K, V> withPartitionsDisabled() {
267 return this;
268 }
269
270 @Override
271 public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
272 return this;
273 }
274
275 @Override
276 public ConsistentMapBuilder<K, V> withPurgeOnUninstall() {
277 return this;
278 }
279
280 @Override
Madan Jampani3d6a2f62015-08-12 07:19:07 -0700281 public ConsistentMapBuilder<K, V> withRelaxedReadConsistency() {
282 return this;
283 }
284
285 @Override
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700286 public ConsistentMapBuilder<K, V> withMeteringDisabled() {
287 return this;
288 }
289
290 @Override
Ray Milkey6f440332015-07-31 10:40:53 -0700291 public ConsistentMap<K, V> build() {
292 return new TestConsistentMap<>(mapName);
293 }
294
295 @Override
296 public AsyncConsistentMap<K, V> buildAsyncMap() {
297 return null;
298 }
299
300 }
301
302}