blob: 0136a94c9abca46ef6e7f3a21f7386e4f06e7e3e [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) {
115 return null;
116 }
117
118 @Override
119 public Versioned<V> put(K key, V value) {
alshabibe1248b62015-08-20 17:21:55 -0700120 Versioned<V> result = version(value);
121 if (map.put(key, value) == null) {
122 notifyListeners(mapName, INSERT, key, result);
123 } else {
124 notifyListeners(mapName, UPDATE, key, result);
125 }
Ray Milkey6f440332015-07-31 10:40:53 -0700126 return result;
127 }
128
129 @Override
130 public Versioned<V> putAndGet(K key, V value) {
131 Versioned<V> result = version(map.put(key, value));
132 notifyListeners(mapName, UPDATE, key, result);
133 return result;
134 }
135
136 @Override
137 public Versioned<V> remove(K key) {
138 Versioned<V> result = version(map.remove(key));
139 notifyListeners(mapName, REMOVE, key, result);
140 return result;
141 }
142
143 @Override
144 public void clear() {
145 map.clear();
146 }
147
148 @Override
149 public Set<K> keySet() {
150 return map.keySet();
151 }
152
153 @Override
154 public Collection<Versioned<V>> values() {
155 return map
156 .values()
157 .stream()
158 .map(this::version)
159 .collect(Collectors.toList());
160 }
161
162 @Override
163 public Set<Map.Entry<K, Versioned<V>>> entrySet() {
164 return super.entrySet();
165 }
166
167 @Override
168 public Versioned<V> putIfAbsent(K key, V value) {
169 Versioned<V> result = version(map.putIfAbsent(key, value));
170 if (map.get(key).equals(value)) {
171 notifyListeners(mapName, INSERT, key, result);
172 }
173 return result;
174 }
175
176 @Override
177 public boolean remove(K key, V value) {
178 boolean removed = map.remove(key, value);
179 if (removed) {
180 notifyListeners(mapName, REMOVE, key, null);
181 }
182 return removed;
183 }
184
185 @Override
186 public boolean remove(K key, long version) {
187 boolean removed = map.remove(key, version);
188 if (removed) {
189 notifyListeners(mapName, REMOVE, key, null);
190 }
191 return removed;
192 }
193
194 @Override
195 public boolean replace(K key, V oldValue, V newValue) {
196 boolean replaced = map.replace(key, oldValue, newValue);
197 if (replaced) {
198 notifyListeners(mapName, REMOVE, key, null);
199 }
200 return replaced;
201 }
202
203 @Override
204 public boolean replace(K key, long oldVersion, V newValue) {
205 boolean replaced = map.replace(key, map.get(key), newValue);
206 if (replaced) {
207 notifyListeners(mapName, REMOVE, key, null);
208 }
209 return replaced;
210 }
211
212 @Override
213 public void addListener(MapEventListener<K, V> listener) {
214 listeners.add(listener);
215 }
216
217 @Override
218 public void removeListener(MapEventListener<K, V> listener) {
219 listeners.remove(listener);
220 }
221
alshabibe1248b62015-08-20 17:21:55 -0700222 @Override
223 public Map<K, V> asJavaMap() {
224 return map;
225 }
226
Ray Milkey6f440332015-07-31 10:40:53 -0700227 public static Builder builder() {
228 return new Builder();
229 }
230
231 public static class Builder<K, V> implements ConsistentMapBuilder<K, V> {
232 String mapName = "map";
233
234 @Override
235 public ConsistentMapBuilder<K, V> withName(String mapName) {
236 this.mapName = mapName;
237 return this;
238 }
239
240 @Override
241 public ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id) {
242 return this;
243 }
244
245 @Override
246 public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) {
247 return this;
248 }
249
250 @Override
251 public ConsistentMapBuilder<K, V> withPartitionsDisabled() {
252 return this;
253 }
254
255 @Override
256 public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
257 return this;
258 }
259
260 @Override
261 public ConsistentMapBuilder<K, V> withPurgeOnUninstall() {
262 return this;
263 }
264
265 @Override
Madan Jampani3d6a2f62015-08-12 07:19:07 -0700266 public ConsistentMapBuilder<K, V> withRelaxedReadConsistency() {
267 return this;
268 }
269
270 @Override
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700271 public ConsistentMapBuilder<K, V> withMeteringDisabled() {
272 return this;
273 }
274
275 @Override
Ray Milkey6f440332015-07-31 10:40:53 -0700276 public ConsistentMap<K, V> build() {
277 return new TestConsistentMap<>(mapName);
278 }
279
280 @Override
281 public AsyncConsistentMap<K, V> buildAsyncMap() {
282 return null;
283 }
284
285 }
286
287}