blob: 1adaa39ee9f15b4f4ca9a7b42fd7851761af8143 [file] [log] [blame]
Avantika-Huawei9e848e82016-09-01 12:12:42 +05301/*
Brian O'Connor0a4e6742016-09-15 23:03:10 -07002 * Copyright 2016-present Open Networking Laboratory
Avantika-Huawei9e848e82016-09-01 12:12:42 +05303 *
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.pcelabelstore.util;
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;
24import java.util.concurrent.atomic.AtomicBoolean;
25import java.util.concurrent.atomic.AtomicLong;
26import java.util.concurrent.atomic.AtomicReference;
27import java.util.function.BiFunction;
28import java.util.function.Function;
29import java.util.function.Predicate;
30import java.util.stream.Collectors;
31
32import org.onosproject.store.primitives.ConsistentMapBackedJavaMap;
33import org.onosproject.store.service.AsyncConsistentMap;
34import org.onosproject.store.service.ConsistentMap;
35import org.onosproject.store.service.ConsistentMapBuilder;
36import org.onosproject.store.service.MapEvent;
37import org.onosproject.store.service.MapEventListener;
38import org.onosproject.store.service.Versioned;
39
40import com.google.common.base.Objects;
41
42/**
43 * Test implementation of the consistent map.
44 */
45public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
46
47 private final List<MapEventListener<K, V>> listeners;
48 private final Map<K, Versioned<V>> map;
49 private final String mapName;
50 private final AtomicLong counter = new AtomicLong(0);
51
52 private TestConsistentMap(String mapName) {
53 map = new HashMap<>();
54 listeners = new LinkedList<>();
55 this.mapName = mapName;
56 }
57
58 private Versioned<V> version(V v) {
59 return new Versioned<>(v, counter.incrementAndGet(), System.currentTimeMillis());
60 }
61
62 /**
63 * Notify all listeners of an event.
64 */
65 private void notifyListeners(String mapName,
66 K key, Versioned<V> newvalue, Versioned<V> oldValue) {
67 MapEvent<K, V> event = new MapEvent<>(mapName, key, newvalue, oldValue);
68 listeners.forEach(
69 listener -> listener.event(event)
70 );
71 }
72
73 @Override
74 public int size() {
75 return map.size();
76 }
77
78 @Override
79 public boolean isEmpty() {
80 return map.isEmpty();
81 }
82
83 @Override
84 public boolean containsKey(K key) {
85 return map.containsKey(key);
86 }
87
88 @Override
89 public boolean containsValue(V value) {
90 return map.containsValue(value);
91 }
92
93 @Override
94 public Versioned<V> get(K key) {
95 return map.get(key);
96 }
97
98 @Override
99 public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
100 AtomicBoolean updated = new AtomicBoolean(false);
101 Versioned<V> result = map.compute(key, (k, v) -> {
102 if (v == null) {
103 updated.set(true);
104 return version(mappingFunction.apply(key));
105 }
106 return v;
107 });
108 if (updated.get()) {
109 notifyListeners(mapName, key, result, null);
110 }
111 return result;
112 }
113
114 @Override
115 public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
116 AtomicBoolean updated = new AtomicBoolean(false);
117 AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
118 Versioned<V> result = map.compute(key, (k, v) -> {
119 updated.set(true);
120 previousValue.set(v);
121 return version(remappingFunction.apply(k, Versioned.valueOrNull(v)));
122 });
123 if (updated.get()) {
124 notifyListeners(mapName, key, result, previousValue.get());
125 }
126 return result;
127 }
128
129 @Override
130 public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
131 AtomicBoolean updated = new AtomicBoolean(false);
132 AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
133 Versioned<V> result = map.compute(key, (k, v) -> {
134 if (v != null) {
135 updated.set(true);
136 previousValue.set(v);
137 return version(remappingFunction.apply(k, v.value()));
138 }
139 return v;
140 });
141 if (updated.get()) {
142 notifyListeners(mapName, key, result, previousValue.get());
143 }
144 return result;
145 }
146
147 @Override
148 public Versioned<V> computeIf(K key, Predicate<? super V> condition,
149 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
150 AtomicBoolean updated = new AtomicBoolean(false);
151 AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
152 Versioned<V> result = map.compute(key, (k, v) -> {
153 if (condition.test(Versioned.valueOrNull(v))) {
154 previousValue.set(v);
155 updated.set(true);
156 return version(remappingFunction.apply(k, Versioned.valueOrNull(v)));
157 }
158 return v;
159 });
160 if (updated.get()) {
161 notifyListeners(mapName, key, result, previousValue.get());
162 }
163 return result;
164 }
165
166 @Override
167 public Versioned<V> put(K key, V value) {
168 Versioned<V> newValue = version(value);
169 Versioned<V> previousValue = map.put(key, newValue);
170 notifyListeners(mapName, key, newValue, previousValue);
171 return previousValue;
172 }
173
174 @Override
175 public Versioned<V> putAndGet(K key, V value) {
176 Versioned<V> newValue = version(value);
177 Versioned<V> previousValue = map.put(key, newValue);
178 notifyListeners(mapName, key, newValue, previousValue);
179 return newValue;
180 }
181
182 @Override
183 public Versioned<V> remove(K key) {
184 Versioned<V> result = map.remove(key);
185 notifyListeners(mapName, key, null, result);
186 return result;
187 }
188
189 @Override
190 public void clear() {
191 map.keySet().forEach(this::remove);
192 }
193
194 @Override
195 public Set<K> keySet() {
196 return map.keySet();
197 }
198
199 @Override
200 public Collection<Versioned<V>> values() {
201 return map.values()
202 .stream()
203 .collect(Collectors.toList());
204 }
205
206 @Override
207 public Set<Map.Entry<K, Versioned<V>>> entrySet() {
208 return map.entrySet();
209 }
210
211 @Override
212 public Versioned<V> putIfAbsent(K key, V value) {
213 Versioned<V> newValue = version(value);
214 Versioned<V> result = map.putIfAbsent(key, newValue);
215 if (result == null) {
216 notifyListeners(mapName, key, newValue, result);
217 }
218 return result;
219 }
220
221 @Override
222 public boolean remove(K key, V value) {
223 Versioned<V> existingValue = map.get(key);
224 if (Objects.equal(Versioned.valueOrNull(existingValue), value)) {
225 map.remove(key);
226 notifyListeners(mapName, key, null, existingValue);
227 return true;
228 }
229 return false;
230 }
231
232 @Override
233 public boolean remove(K key, long version) {
234 Versioned<V> existingValue = map.get(key);
235 if (existingValue == null) {
236 return false;
237 }
238 if (existingValue.version() == version) {
239 map.remove(key);
240 notifyListeners(mapName, key, null, existingValue);
241 return true;
242 }
243 return false;
244 }
245
246 @Override
247 public Versioned<V> replace(K key, V value) {
248 Versioned<V> existingValue = map.get(key);
249 if (existingValue == null) {
250 return null;
251 }
252 Versioned<V> newValue = version(value);
253 Versioned<V> result = map.put(key, newValue);
254 notifyListeners(mapName, key, newValue, result);
255 return result;
256 }
257
258 @Override
259 public boolean replace(K key, V oldValue, V newValue) {
260 Versioned<V> existingValue = map.get(key);
261 if (existingValue == null || !existingValue.value().equals(oldValue)) {
262 return false;
263 }
264 Versioned<V> value = version(newValue);
265 Versioned<V> result = map.put(key, value);
266 notifyListeners(mapName, key, value, result);
267 return true;
268 }
269
270 @Override
271 public boolean replace(K key, long oldVersion, V newValue) {
272 Versioned<V> existingValue = map.get(key);
273 if (existingValue == null || existingValue.version() != oldVersion) {
274 return false;
275 }
276 Versioned<V> value = version(newValue);
277 Versioned<V> result = map.put(key, value);
278 notifyListeners(mapName, key, value, result);
279 return true;
280 }
281
282 @Override
283 public void addListener(MapEventListener<K, V> listener) {
284 listeners.add(listener);
285 }
286
287 @Override
288 public void removeListener(MapEventListener<K, V> listener) {
289 listeners.remove(listener);
290 }
291
292 @Override
293 public Map<K, V> asJavaMap() {
294 return new ConsistentMapBackedJavaMap<>(this);
295 }
296
297 public static Builder builder() {
298 return new Builder();
299 }
300
301 public static class Builder<K, V> extends ConsistentMapBuilder<K, V> {
302
303 @Override
304 public ConsistentMap<K, V> build() {
305 return new TestConsistentMap<>(name());
306 }
307
308 @Override
309 public AsyncConsistentMap<K, V> buildAsyncMap() {
310 return null;
311 }
312
313 }
314
315}