| /* |
| * 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.store.primitives; |
| |
| import com.google.common.base.Throwables; |
| |
| import org.onosproject.store.service.ConsistentMapException; |
| import org.onosproject.store.service.AsyncConsistentTreeMap; |
| import org.onosproject.store.service.MapEventListener; |
| import org.onosproject.store.service.Synchronous; |
| import org.onosproject.store.service.ConsistentTreeMap; |
| import org.onosproject.store.service.Versioned; |
| |
| import java.util.Collection; |
| import java.util.Map; |
| import java.util.NavigableMap; |
| import java.util.NavigableSet; |
| import java.util.Set; |
| import java.util.concurrent.CompletableFuture; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| import java.util.function.BiFunction; |
| import java.util.function.Function; |
| import java.util.function.Predicate; |
| |
| /** |
| * Implementation of the {@link ConsistentTreeMap} interface. |
| */ |
| public class DefaultConsistentTreeMap<V> |
| extends Synchronous<AsyncConsistentTreeMap<V>> |
| implements ConsistentTreeMap<V> { |
| private static final int MAX_DELAY_BETWEEN_RETRY_MILLIS = 50; |
| private final AsyncConsistentTreeMap<V> treeMap; |
| private final long operationTimeoutMillis; |
| private Map<String, V> javaMap; |
| |
| public DefaultConsistentTreeMap(AsyncConsistentTreeMap<V> treeMap, |
| long operationTimeoutMillis) { |
| super(treeMap); |
| this.treeMap = treeMap; |
| this.operationTimeoutMillis = operationTimeoutMillis; |
| } |
| |
| private <T> T complete(CompletableFuture<T> future) { |
| try { |
| return future.get(operationTimeoutMillis, TimeUnit.MILLISECONDS); |
| } catch (InterruptedException e) { |
| Thread.currentThread().interrupt(); |
| throw new ConsistentMapException.Interrupted(); |
| } catch (ExecutionException e) { |
| Throwables.propagateIfPossible(e.getCause()); |
| throw new ConsistentMapException(e.getCause()); |
| } catch (TimeoutException e) { |
| throw new ConsistentMapException.Timeout(); |
| } |
| } |
| |
| @Override |
| public String firstKey() { |
| return complete(treeMap.firstKey()); |
| } |
| |
| @Override |
| public String lastKey() { |
| return complete(treeMap.lastKey()); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> ceilingEntry(String key) { |
| return complete(treeMap.ceilingEntry(key)); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> floorEntry(String key) { |
| return complete(treeMap.floorEntry(key)); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> higherEntry(String key) { |
| return complete(treeMap.higherEntry(key)); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> lowerEntry(String key) { |
| return complete(treeMap.lowerEntry(key)); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> firstEntry() { |
| return complete(treeMap.firstEntry()); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> lastEntry() { |
| return complete(treeMap.lastEntry()); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> pollFirstEntry() { |
| return complete(treeMap.pollFirstEntry()); |
| } |
| |
| @Override |
| public Map.Entry<String, Versioned<V>> pollLastEntry() { |
| return complete(treeMap.pollLastEntry()); |
| } |
| |
| @Override |
| public String lowerKey(String key) { |
| return complete(treeMap.lowerKey(key)); |
| } |
| |
| @Override |
| public String floorKey(String key) { |
| return complete(treeMap.floorKey(key)); |
| } |
| |
| @Override |
| public String ceilingKey(String key) { |
| return complete(treeMap.ceilingKey(key)); |
| } |
| |
| @Override |
| public String higherKey(String key) { |
| return complete(treeMap.higherKey(key)); |
| } |
| |
| |
| @Override |
| /** |
| * {@inheritDoc} |
| * <p>This may be a long operation with greater risk of timeout.</p> |
| */ |
| public NavigableSet<String> navigableKeySet() { |
| return complete(treeMap.navigableKeySet()); |
| } |
| |
| @Override |
| public int size() { |
| return complete(treeMap.size()); |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return complete(treeMap.isEmpty()); |
| } |
| |
| @Override |
| public boolean containsKey(String key) { |
| return complete(treeMap.containsKey(key)); |
| } |
| |
| @Override |
| public boolean containsValue(V value) { |
| return complete(treeMap.containsValue(value)); |
| } |
| |
| @Override |
| public Versioned<V> get(String key) { |
| return complete(treeMap.get(key)); |
| } |
| |
| @Override |
| public Versioned<V> computeIfAbsent(String key, |
| Function<? super String, |
| ? extends V> mappingFunction) { |
| return complete(treeMap.computeIfAbsent(key, mappingFunction)); |
| } |
| |
| @Override |
| public Versioned<V> compute(String key, |
| BiFunction<? super String, |
| ? super V, |
| ? extends V> remappingFunction) { |
| return complete(treeMap.compute(key, remappingFunction)); |
| } |
| |
| @Override |
| public Versioned<V> computeIfPresent( |
| String key, |
| BiFunction<? super String, |
| ? super V, |
| ? extends V> remappingFunction) { |
| return complete(treeMap.computeIfPresent(key, remappingFunction)); |
| } |
| |
| @Override |
| public Versioned<V> computeIf(String key, Predicate<? super V> condition, |
| BiFunction<? super String, |
| ? super V, |
| ? extends V> remappingFunction) { |
| return complete(treeMap.computeIf(key, condition, remappingFunction)); |
| } |
| |
| @Override |
| public Versioned<V> put(String key, V value) { |
| return complete(treeMap.put(key, value)); |
| } |
| |
| @Override |
| public Versioned<V> putAndGet(String key, V value) { |
| return complete(treeMap.putAndGet(key, value)); |
| } |
| |
| @Override |
| public Versioned<V> remove(String key) { |
| return complete(treeMap.remove(key)); |
| } |
| |
| @Override |
| public void clear() { |
| complete(treeMap.clear()); |
| } |
| |
| @Override |
| public Set<String> keySet() { |
| return complete(treeMap.keySet()); |
| } |
| |
| @Override |
| public Collection<Versioned<V>> values() { |
| return complete(treeMap.values()); |
| } |
| |
| @Override |
| public Set<Map.Entry<String, Versioned<V>>> entrySet() { |
| return complete(treeMap.entrySet()); |
| } |
| |
| @Override |
| public Versioned<V> putIfAbsent(String key, V value) { |
| return complete(treeMap.putIfAbsent(key, value)); |
| } |
| |
| @Override |
| public boolean remove(String key, V value) { |
| return complete(treeMap.remove(key, value)); |
| } |
| |
| @Override |
| public boolean remove(String key, long version) { |
| return complete(treeMap.remove(key, version)); |
| } |
| |
| @Override |
| public Versioned<V> replace(String key, V value) { |
| return complete(treeMap.replace(key, value)); |
| } |
| |
| @Override |
| public boolean replace(String key, V oldValue, V newValue) { |
| return complete(treeMap.replace(key, oldValue, newValue)); |
| } |
| |
| @Override |
| public boolean replace(String key, long oldVersion, V newValue) { |
| return complete(treeMap.replace(key, oldVersion, newValue)); |
| } |
| |
| @Override |
| public void addListener(MapEventListener<String, V> listener, |
| Executor executor) { |
| complete(treeMap.addListener(listener, executor)); |
| } |
| |
| @Override |
| public void removeListener(MapEventListener<String, V> listener) { |
| complete(treeMap.removeListener(listener)); |
| } |
| |
| @Override |
| public Map<String, V> asJavaMap() { |
| synchronized (this) { |
| if (javaMap == null) { |
| javaMap = new ConsistentMapBackedJavaMap<>(this); |
| } |
| } |
| return javaMap; |
| } |
| |
| @Override |
| public NavigableMap<String, V> subMap(String upperKey, |
| String lowerKey, |
| boolean inclusiveUpper, |
| boolean inclusiveLower) { |
| return complete(treeMap.subMap(upperKey, lowerKey, |
| inclusiveUpper, inclusiveLower)); |
| } |
| } |