blob: 85d1a68a2ef280476e5af6305bd8636bb6f1f97f [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
201 public boolean replace(K key, V oldValue, V newValue) {
202 boolean replaced = map.replace(key, oldValue, newValue);
203 if (replaced) {
204 notifyListeners(mapName, REMOVE, key, null);
205 }
206 return replaced;
207 }
208
209 @Override
210 public boolean replace(K key, long oldVersion, V newValue) {
211 boolean replaced = map.replace(key, map.get(key), newValue);
212 if (replaced) {
213 notifyListeners(mapName, REMOVE, key, null);
214 }
215 return replaced;
216 }
217
218 @Override
219 public void addListener(MapEventListener<K, V> listener) {
220 listeners.add(listener);
221 }
222
223 @Override
224 public void removeListener(MapEventListener<K, V> listener) {
225 listeners.remove(listener);
226 }
227
alshabibe1248b62015-08-20 17:21:55 -0700228 @Override
229 public Map<K, V> asJavaMap() {
230 return map;
231 }
232
Ray Milkey6f440332015-07-31 10:40:53 -0700233 public static Builder builder() {
234 return new Builder();
235 }
236
237 public static class Builder<K, V> implements ConsistentMapBuilder<K, V> {
238 String mapName = "map";
239
240 @Override
241 public ConsistentMapBuilder<K, V> withName(String mapName) {
242 this.mapName = mapName;
243 return this;
244 }
245
246 @Override
247 public ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id) {
248 return this;
249 }
250
251 @Override
252 public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) {
253 return this;
254 }
255
256 @Override
257 public ConsistentMapBuilder<K, V> withPartitionsDisabled() {
258 return this;
259 }
260
261 @Override
262 public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
263 return this;
264 }
265
266 @Override
267 public ConsistentMapBuilder<K, V> withPurgeOnUninstall() {
268 return this;
269 }
270
271 @Override
Madan Jampani3d6a2f62015-08-12 07:19:07 -0700272 public ConsistentMapBuilder<K, V> withRelaxedReadConsistency() {
273 return this;
274 }
275
276 @Override
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700277 public ConsistentMapBuilder<K, V> withMeteringDisabled() {
278 return this;
279 }
280
281 @Override
Ray Milkey6f440332015-07-31 10:40:53 -0700282 public ConsistentMap<K, V> build() {
283 return new TestConsistentMap<>(mapName);
284 }
285
286 @Override
287 public AsyncConsistentMap<K, V> buildAsyncMap() {
288 return null;
289 }
290
291 }
292
293}