/* * Copyright 2016-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.pcelabelstore.util; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import org.onlab.util.KryoNamespace; import org.onosproject.cluster.NodeId; import org.onosproject.store.Timestamp; import org.onosproject.store.service.EventuallyConsistentMap; import org.onosproject.store.service.EventuallyConsistentMapBuilder; import org.onosproject.store.service.EventuallyConsistentMapEvent; import org.onosproject.store.service.EventuallyConsistentMapListener; import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; /** * Testing version of an Eventually Consistent Map. */ public final class TestEventuallyConsistentMap<K, V> extends EventuallyConsistentMapAdapter<K, V> { private final HashMap<K, V> map; private final String mapName; private final List<EventuallyConsistentMapListener<K, V>> listeners; private final BiFunction<K, V, Collection<NodeId>> peerUpdateFunction; private TestEventuallyConsistentMap(String mapName, BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) { map = new HashMap<>(); listeners = new LinkedList<>(); this.mapName = mapName; this.peerUpdateFunction = peerUpdateFunction; } /** * Notify all listeners of an event. */ private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) { listeners.forEach( listener -> listener.event(event) ); } @Override public int size() { return map.size(); } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public boolean containsKey(K key) { return map.containsKey(key); } @Override public boolean containsValue(V value) { return map.containsValue(value); } @Override public V get(K key) { return map.get(key); } @Override public void put(K key, V value) { map.put(key, value); EventuallyConsistentMapEvent<K, V> addEvent = new EventuallyConsistentMapEvent<>(mapName, PUT, key, value); notifyListeners(addEvent); if (peerUpdateFunction != null) { peerUpdateFunction.apply(key, value); } } @Override public V remove(K key) { V result = map.remove(key); if (result != null) { EventuallyConsistentMapEvent<K, V> removeEvent = new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, map.get(key)); notifyListeners(removeEvent); } return result; } @Override public void remove(K key, V value) { boolean removed = map.remove(key, value); if (removed) { EventuallyConsistentMapEvent<K, V> removeEvent = new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, value); notifyListeners(removeEvent); } } @Override public V compute(K key, BiFunction<K, V, V> recomputeFunction) { return map.compute(key, recomputeFunction); } @Override public void putAll(Map<? extends K, ? extends V> m) { map.putAll(m); } @Override public void clear() { map.clear(); } @Override public Set<K> keySet() { return map.keySet(); } @Override public Collection<V> values() { return map.values(); } @Override public Set<Map.Entry<K, V>> entrySet() { return map.entrySet(); } public static <K, V> Builder<K, V> builder() { return new Builder<>(); } @Override public void addListener(EventuallyConsistentMapListener<K, V> listener) { listeners.add(listener); } @Override public void removeListener(EventuallyConsistentMapListener<K, V> listener) { listeners.remove(listener); } public static class Builder<K, V> implements EventuallyConsistentMapBuilder<K, V> { private String name; private BiFunction<K, V, Collection<NodeId>> peerUpdateFunction; @Override public EventuallyConsistentMapBuilder<K, V> withName(String name) { this.name = name; return this; } @Override public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace.Builder serializerBuilder) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace serializer) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withEventExecutor(ExecutorService executor) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor(ExecutorService executor) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(ScheduledExecutorService executor) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withPeerUpdateFunction(BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) { this.peerUpdateFunction = peerUpdateFunction; return this; } @Override public EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled() { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(long period, TimeUnit unit) { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withFasterConvergence() { return this; } @Override public EventuallyConsistentMapBuilder<K, V> withPersistence() { return this; } @Override public EventuallyConsistentMap<K, V> build() { if (name == null) { name = "test"; } return new TestEventuallyConsistentMap<>(name, peerUpdateFunction); } } }