Madan Jampani
Committed by Gerrit Code Review

ONOS-1362: Support async version of ConsistentMap that lets efficient chaining of operations

Change-Id: I672a15ba2a517db3e22f6ce8d739ca48307e6e63
1 +/*
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 + */
16 +
17 +package org.onosproject.store.service;
18 +
19 +import java.util.Collection;
20 +import java.util.Set;
21 +import java.util.Map.Entry;
22 +import java.util.concurrent.CompletableFuture;
23 +
24 +/**
25 + * A distributed, strongly consistent map whose methods are all executed asynchronously.
26 + * <p>
27 + * This map offers strong read-after-update (where update == create/update/delete)
28 + * consistency. All operations to the map are serialized and applied in a consistent
29 + * manner.
30 + * <p>
31 + * The stronger consistency comes at the expense of availability in
32 + * the event of a network partition. A network partition can be either due to
33 + * a temporary disruption in network connectivity between participating nodes
34 + * or due to a node being temporarily down.
35 + * </p><p>
36 + * All values stored in this map are versioned and the API supports optimistic
37 + * concurrency by allowing conditional updates that take into consideration
38 + * the version or value that was previously read.
39 + * </p><p>
40 + * This map does not allow null values. All methods can throw a ConsistentMapException
41 + * (which extends RuntimeException) to indicate failures.
42 + *
43 + */
44 +public interface AsyncConsistentMap<K, V> {
45 +
46 + /**
47 + * Returns the number of entries in the map.
48 + *
49 + * @return a future for map size.
50 + */
51 + CompletableFuture<Integer> size();
52 +
53 + /**
54 + * Returns true if the map is empty.
55 + *
56 + * @return a future whose value will be true if map has no entries, false otherwise.
57 + */
58 + CompletableFuture<Boolean> isEmpty();
59 +
60 + /**
61 + * Returns true if this map contains a mapping for the specified key.
62 + *
63 + * @param key key
64 + * @return a future whose value will be true if map contains key, false otherwise.
65 + */
66 + CompletableFuture<Boolean> containsKey(K key);
67 +
68 + /**
69 + * Returns true if this map contains the specified value.
70 + *
71 + * @param value value
72 + * @return a future whose value will be true if map contains value, false otherwise.
73 + */
74 + CompletableFuture<Boolean> containsValue(V value);
75 +
76 + /**
77 + * Returns the value (and version) to which the specified key is mapped, or null if this
78 + * map contains no mapping for the key.
79 + *
80 + * @param key the key whose associated value (and version) is to be returned
81 + * @return a future value (and version) to which the specified key is mapped, or null if
82 + * this map contains no mapping for the key
83 + */
84 + CompletableFuture<Versioned<V>> get(K key);
85 +
86 + /**
87 + * Associates the specified value with the specified key in this map (optional operation).
88 + * If the map previously contained a mapping for the key, the old value is replaced by the
89 + * specified value.
90 + *
91 + * @param key key with which the specified value is to be associated
92 + * @param value value to be associated with the specified key
93 + * @return the previous value (and version) associated with key, or null if there was
94 + * no mapping for key.
95 + */
96 + CompletableFuture<Versioned<V>> put(K key, V value);
97 +
98 + /**
99 + * Removes the mapping for a key from this map if it is present (optional operation).
100 + *
101 + * @param key key whose value is to be removed from the map
102 + * @return the value (and version) to which this map previously associated the key,
103 + * or null if the map contained no mapping for the key.
104 + */
105 + CompletableFuture<Versioned<V>> remove(K key);
106 +
107 + /**
108 + * Removes all of the mappings from this map (optional operation).
109 + * The map will be empty after this call returns.
110 + */
111 + CompletableFuture<Void> clear();
112 +
113 + /**
114 + * Returns a Set view of the keys contained in this map.
115 + * This method differs from the behavior of java.util.Map.keySet() in that
116 + * what is returned is a unmodifiable snapshot view of the keys in the ConsistentMap.
117 + * Attempts to modify the returned set, whether direct or via its iterator,
118 + * result in an UnsupportedOperationException.
119 + *
120 + * @return a set of the keys contained in this map
121 + */
122 + CompletableFuture<Set<K>> keySet();
123 +
124 + /**
125 + * Returns the collection of values (and associated versions) contained in this map.
126 + * This method differs from the behavior of java.util.Map.values() in that
127 + * what is returned is a unmodifiable snapshot view of the values in the ConsistentMap.
128 + * Attempts to modify the returned collection, whether direct or via its iterator,
129 + * result in an UnsupportedOperationException.
130 + *
131 + * @return a collection of the values (and associated versions) contained in this map
132 + */
133 + CompletableFuture<Collection<Versioned<V>>> values();
134 +
135 + /**
136 + * Returns the set of entries contained in this map.
137 + * This method differs from the behavior of java.util.Map.entrySet() in that
138 + * what is returned is a unmodifiable snapshot view of the entries in the ConsistentMap.
139 + * Attempts to modify the returned set, whether direct or via its iterator,
140 + * result in an UnsupportedOperationException.
141 + *
142 + * @return set of entries contained in this map.
143 + */
144 + CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet();
145 +
146 + /**
147 + * If the specified key is not already associated with a value
148 + * associates it with the given value and returns null, else returns the current value.
149 + *
150 + * @param key key with which the specified value is to be associated
151 + * @param value value to be associated with the specified key
152 + * @return the previous value associated with the specified key or null
153 + * if key does not already mapped to a value.
154 + */
155 + CompletableFuture<Versioned<V>> putIfAbsent(K key, V value);
156 +
157 + /**
158 + * Removes the entry for the specified key only if it is currently
159 + * mapped to the specified value.
160 + *
161 + * @param key key with which the specified value is associated
162 + * @param value value expected to be associated with the specified key
163 + * @return true if the value was removed
164 + */
165 + CompletableFuture<Boolean> remove(K key, V value);
166 +
167 + /**
168 + * Removes the entry for the specified key only if its current
169 + * version in the map is equal to the specified version.
170 + *
171 + * @param key key with which the specified version is associated
172 + * @param version version expected to be associated with the specified key
173 + * @return true if the value was removed
174 + */
175 + CompletableFuture<Boolean> remove(K key, long version);
176 +
177 + /**
178 + * Replaces the entry for the specified key only if currently mapped
179 + * to the specified value.
180 + *
181 + * @param key key with which the specified value is associated
182 + * @param oldValue value expected to be associated with the specified key
183 + * @param newValue value to be associated with the specified key
184 + * @return true if the value was replaced
185 + */
186 + CompletableFuture<Boolean> replace(K key, V oldValue, V newValue);
187 +
188 + /**
189 + * Replaces the entry for the specified key only if it is currently mapped to the
190 + * specified version.
191 + *
192 + * @param key key key with which the specified value is associated
193 + * @param oldVersion version expected to be associated with the specified key
194 + * @param newValue value to be associated with the specified key
195 + * @return true if the value was replaced
196 + */
197 + CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue);
198 +}
...@@ -30,9 +30,8 @@ public interface StorageService { ...@@ -30,9 +30,8 @@ public interface StorageService {
30 30
31 /** 31 /**
32 * Creates a ConsistentMap. 32 * Creates a ConsistentMap.
33 - *
34 * @param name map name 33 * @param name map name
35 - * @param serializer serializer to use for serializing keys and values. 34 + * @param serializer serializer to use for serializing keys and values
36 * @return consistent map. 35 * @return consistent map.
37 * @param <K> key type 36 * @param <K> key type
38 * @param <V> value type 37 * @param <V> value type
...@@ -40,6 +39,16 @@ public interface StorageService { ...@@ -40,6 +39,16 @@ public interface StorageService {
40 <K, V> ConsistentMap<K , V> createConsistentMap(String name, Serializer serializer); 39 <K, V> ConsistentMap<K , V> createConsistentMap(String name, Serializer serializer);
41 40
42 /** 41 /**
42 + * Creates a AsyncConsistentMap.
43 + * @param name map name
44 + * @param serializer serializer to use for serializing keys and values
45 + * @return async consistent map
46 + * @param <K> key type
47 + * @param <V> value type
48 + */
49 + <K, V> AsyncConsistentMap<K , V> createAsyncConsistentMap(String name, Serializer serializer);
50 +
51 + /**
43 * Creates a new transaction context. 52 * Creates a new transaction context.
44 * @return transaction context 53 * @return transaction context
45 */ 54 */
......
...@@ -32,6 +32,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -32,6 +32,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
32 import org.apache.felix.scr.annotations.Service; 32 import org.apache.felix.scr.annotations.Service;
33 import org.onosproject.cluster.ClusterService; 33 import org.onosproject.cluster.ClusterService;
34 import org.onosproject.store.cluster.impl.NodeInfo; 34 import org.onosproject.store.cluster.impl.NodeInfo;
35 +import org.onosproject.store.service.AsyncConsistentMap;
35 import org.onosproject.store.service.ConsistentMap; 36 import org.onosproject.store.service.ConsistentMap;
36 import org.onosproject.store.service.PartitionInfo; 37 import org.onosproject.store.service.PartitionInfo;
37 import org.onosproject.store.service.Serializer; 38 import org.onosproject.store.service.Serializer;
...@@ -168,7 +169,12 @@ public class DatabaseManager implements StorageService, StorageAdminService { ...@@ -168,7 +169,12 @@ public class DatabaseManager implements StorageService, StorageAdminService {
168 169
169 @Override 170 @Override
170 public <K, V> ConsistentMap<K , V> createConsistentMap(String name, Serializer serializer) { 171 public <K, V> ConsistentMap<K , V> createConsistentMap(String name, Serializer serializer) {
171 - return new ConsistentMapImpl<K, V>(name, partitionedDatabase, serializer); 172 + return new DefaultConsistentMap<K, V>(name, partitionedDatabase, serializer);
173 + }
174 +
175 + @Override
176 + public <K, V> AsyncConsistentMap<K , V> createAsyncConsistentMap(String name, Serializer serializer) {
177 + return new DefaultAsyncConsistentMap<K, V>(name, partitionedDatabase, serializer);
172 } 178 }
173 179
174 @Override 180 @Override
......
...@@ -19,20 +19,15 @@ package org.onosproject.store.consistent.impl; ...@@ -19,20 +19,15 @@ package org.onosproject.store.consistent.impl;
19 import static com.google.common.base.Preconditions.*; 19 import static com.google.common.base.Preconditions.*;
20 20
21 import java.util.Collection; 21 import java.util.Collection;
22 -import java.util.Collections;
23 import java.util.Map; 22 import java.util.Map;
24 import java.util.Map.Entry; 23 import java.util.Map.Entry;
25 import java.util.concurrent.CompletableFuture; 24 import java.util.concurrent.CompletableFuture;
26 -import java.util.concurrent.ExecutionException;
27 -import java.util.concurrent.TimeUnit;
28 -import java.util.concurrent.TimeoutException;
29 import java.util.stream.Collectors; 25 import java.util.stream.Collectors;
30 import java.util.Set; 26 import java.util.Set;
31 27
32 import org.apache.commons.lang3.tuple.Pair; 28 import org.apache.commons.lang3.tuple.Pair;
33 import org.onlab.util.HexString; 29 import org.onlab.util.HexString;
34 -import org.onosproject.store.service.ConsistentMap; 30 +import org.onosproject.store.service.AsyncConsistentMap;
35 -import org.onosproject.store.service.ConsistentMapException;
36 import org.onosproject.store.service.Serializer; 31 import org.onosproject.store.service.Serializer;
37 import org.onosproject.store.service.Versioned; 32 import org.onosproject.store.service.Versioned;
38 33
...@@ -41,19 +36,18 @@ import com.google.common.cache.CacheLoader; ...@@ -41,19 +36,18 @@ import com.google.common.cache.CacheLoader;
41 import com.google.common.cache.LoadingCache; 36 import com.google.common.cache.LoadingCache;
42 37
43 /** 38 /**
44 - * ConsistentMap implementation that is backed by a Raft consensus 39 + * AsyncConsistentMap implementation that is backed by a Raft consensus
45 * based database. 40 * based database.
46 * 41 *
47 * @param <K> type of key. 42 * @param <K> type of key.
48 * @param <V> type of value. 43 * @param <V> type of value.
49 */ 44 */
50 -public class ConsistentMapImpl<K, V> implements ConsistentMap<K, V> { 45 +public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V> {
51 46
52 private final String name; 47 private final String name;
53 private final DatabaseProxy<String, byte[]> proxy; 48 private final DatabaseProxy<String, byte[]> proxy;
54 private final Serializer serializer; 49 private final Serializer serializer;
55 50
56 - private static final int OPERATION_TIMEOUT_MILLIS = 5000;
57 private static final String ERROR_NULL_KEY = "Key cannot be null"; 51 private static final String ERROR_NULL_KEY = "Key cannot be null";
58 private static final String ERROR_NULL_VALUE = "Null values are not allowed"; 52 private static final String ERROR_NULL_VALUE = "Null values are not allowed";
59 53
...@@ -71,7 +65,7 @@ public class ConsistentMapImpl<K, V> implements ConsistentMap<K, V> { ...@@ -71,7 +65,7 @@ public class ConsistentMapImpl<K, V> implements ConsistentMap<K, V> {
71 return serializer.decode(HexString.fromHexString(key)); 65 return serializer.decode(HexString.fromHexString(key));
72 } 66 }
73 67
74 - public ConsistentMapImpl(String name, 68 + public DefaultAsyncConsistentMap(String name,
75 DatabaseProxy<String, byte[]> proxy, 69 DatabaseProxy<String, byte[]> proxy,
76 Serializer serializer) { 70 Serializer serializer) {
77 this.name = checkNotNull(name, "map name cannot be null"); 71 this.name = checkNotNull(name, "map name cannot be null");
...@@ -80,152 +74,119 @@ public class ConsistentMapImpl<K, V> implements ConsistentMap<K, V> { ...@@ -80,152 +74,119 @@ public class ConsistentMapImpl<K, V> implements ConsistentMap<K, V> {
80 } 74 }
81 75
82 @Override 76 @Override
83 - public int size() { 77 + public CompletableFuture<Integer> size() {
84 - return complete(proxy.size(name)); 78 + return proxy.size(name);
85 } 79 }
86 80
87 @Override 81 @Override
88 - public boolean isEmpty() { 82 + public CompletableFuture<Boolean> isEmpty() {
89 - return complete(proxy.isEmpty(name)); 83 + return proxy.isEmpty(name);
90 } 84 }
91 85
92 @Override 86 @Override
93 - public boolean containsKey(K key) { 87 + public CompletableFuture<Boolean> containsKey(K key) {
94 checkNotNull(key, ERROR_NULL_KEY); 88 checkNotNull(key, ERROR_NULL_KEY);
95 - return complete(proxy.containsKey(name, keyCache.getUnchecked(key))); 89 + return proxy.containsKey(name, keyCache.getUnchecked(key));
96 } 90 }
97 91
98 @Override 92 @Override
99 - public boolean containsValue(V value) { 93 + public CompletableFuture<Boolean> containsValue(V value) {
100 checkNotNull(value, ERROR_NULL_VALUE); 94 checkNotNull(value, ERROR_NULL_VALUE);
101 - return complete(proxy.containsValue(name, serializer.encode(value))); 95 + return proxy.containsValue(name, serializer.encode(value));
102 } 96 }
103 97
104 @Override 98 @Override
105 - public Versioned<V> get(K key) { 99 + public CompletableFuture<Versioned<V>> get(K key) {
106 checkNotNull(key, ERROR_NULL_KEY); 100 checkNotNull(key, ERROR_NULL_KEY);
107 - Versioned<byte[]> value = complete(proxy.get(name, keyCache.getUnchecked(key))); 101 + return proxy.get(name, keyCache.getUnchecked(key))
108 - if (value == null) { 102 + .thenApply(v -> v != null
109 - return null; 103 + ? new Versioned<>(serializer.decode(v.value()), v.version(), v.creationTime()) : null);
110 - }
111 - return new Versioned<>(
112 - serializer.decode(value.value()),
113 - value.version(),
114 - value.creationTime());
115 } 104 }
116 105
117 @Override 106 @Override
118 - public Versioned<V> put(K key, V value) { 107 + public CompletableFuture<Versioned<V>> put(K key, V value) {
119 checkNotNull(key, ERROR_NULL_KEY); 108 checkNotNull(key, ERROR_NULL_KEY);
120 checkNotNull(value, ERROR_NULL_VALUE); 109 checkNotNull(value, ERROR_NULL_VALUE);
121 - Versioned<byte[]> previousValue = 110 + return proxy.put(name, keyCache.getUnchecked(key), serializer.encode(value))
122 - complete(proxy.put(name, keyCache.getUnchecked(key), serializer.encode(value))); 111 + .thenApply(v -> v != null
123 - if (previousValue == null) { 112 + ? new Versioned<>(serializer.decode(v.value()), v.version(), v.creationTime()) : null);
124 - return null;
125 - }
126 - return new Versioned<>(
127 - serializer.decode(previousValue.value()),
128 - previousValue.version(),
129 - previousValue.creationTime());
130 } 113 }
131 114
132 @Override 115 @Override
133 - public Versioned<V> remove(K key) { 116 + public CompletableFuture<Versioned<V>> remove(K key) {
134 checkNotNull(key, ERROR_NULL_KEY); 117 checkNotNull(key, ERROR_NULL_KEY);
135 - Versioned<byte[]> value = complete(proxy.remove(name, keyCache.getUnchecked(key))); 118 + return proxy.remove(name, keyCache.getUnchecked(key))
136 - if (value == null) { 119 + .thenApply(v -> v != null
137 - return null; 120 + ? new Versioned<>(serializer.decode(v.value()), v.version(), v.creationTime()) : null);
138 - }
139 - return new Versioned<>(
140 - serializer.decode(value.value()),
141 - value.version(),
142 - value.creationTime());
143 } 121 }
144 122
145 @Override 123 @Override
146 - public void clear() { 124 + public CompletableFuture<Void> clear() {
147 - complete(proxy.clear(name)); 125 + return proxy.clear(name);
148 } 126 }
149 127
150 @Override 128 @Override
151 - public Set<K> keySet() { 129 + public CompletableFuture<Set<K>> keySet() {
152 - return Collections.unmodifiableSet(complete(proxy.keySet(name)) 130 + return proxy.keySet(name)
131 + .thenApply(s -> s
153 .stream() 132 .stream()
154 .map(this::dK) 133 .map(this::dK)
155 .collect(Collectors.toSet())); 134 .collect(Collectors.toSet()));
156 } 135 }
157 136
158 @Override 137 @Override
159 - public Collection<Versioned<V>> values() { 138 + public CompletableFuture<Collection<Versioned<V>>> values() {
160 - return Collections.unmodifiableList(complete(proxy.values(name)) 139 + return proxy.values(name).thenApply(c -> c
161 .stream() 140 .stream()
162 .map(v -> new Versioned<V>(serializer.decode(v.value()), v.version(), v.creationTime())) 141 .map(v -> new Versioned<V>(serializer.decode(v.value()), v.version(), v.creationTime()))
163 .collect(Collectors.toList())); 142 .collect(Collectors.toList()));
164 } 143 }
165 144
166 @Override 145 @Override
167 - public Set<Entry<K, Versioned<V>>> entrySet() { 146 + public CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet() {
168 - return Collections.unmodifiableSet(complete(proxy.entrySet(name)) 147 + return proxy.entrySet(name).thenApply(s -> s
169 .stream() 148 .stream()
170 .map(this::fromRawEntry) 149 .map(this::fromRawEntry)
171 .collect(Collectors.toSet())); 150 .collect(Collectors.toSet()));
172 } 151 }
173 152
174 @Override 153 @Override
175 - public Versioned<V> putIfAbsent(K key, V value) { 154 + public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
176 checkNotNull(key, ERROR_NULL_KEY); 155 checkNotNull(key, ERROR_NULL_KEY);
177 checkNotNull(value, ERROR_NULL_VALUE); 156 checkNotNull(value, ERROR_NULL_VALUE);
178 - Versioned<byte[]> existingValue = complete(proxy.putIfAbsent( 157 + return proxy.putIfAbsent(
179 - name, keyCache.getUnchecked(key), serializer.encode(value))); 158 + name, keyCache.getUnchecked(key), serializer.encode(value)).thenApply(v ->
180 - if (existingValue == null) { 159 + v != null ?
181 - return null; 160 + new Versioned<>(serializer.decode(v.value()), v.version(), v.creationTime()) : null);
182 - }
183 - return new Versioned<>(
184 - serializer.decode(existingValue.value()),
185 - existingValue.version(),
186 - existingValue.creationTime());
187 } 161 }
188 162
189 @Override 163 @Override
190 - public boolean remove(K key, V value) { 164 + public CompletableFuture<Boolean> remove(K key, V value) {
191 checkNotNull(key, ERROR_NULL_KEY); 165 checkNotNull(key, ERROR_NULL_KEY);
192 checkNotNull(value, ERROR_NULL_VALUE); 166 checkNotNull(value, ERROR_NULL_VALUE);
193 - return complete(proxy.remove(name, keyCache.getUnchecked(key), serializer.encode(value))); 167 + return proxy.remove(name, keyCache.getUnchecked(key), serializer.encode(value));
194 } 168 }
195 169
196 @Override 170 @Override
197 - public boolean remove(K key, long version) { 171 + public CompletableFuture<Boolean> remove(K key, long version) {
198 checkNotNull(key, ERROR_NULL_KEY); 172 checkNotNull(key, ERROR_NULL_KEY);
199 - return complete(proxy.remove(name, keyCache.getUnchecked(key), version)); 173 + return proxy.remove(name, keyCache.getUnchecked(key), version);
200 174
201 } 175 }
202 176
203 @Override 177 @Override
204 - public boolean replace(K key, V oldValue, V newValue) { 178 + public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
205 checkNotNull(key, ERROR_NULL_KEY); 179 checkNotNull(key, ERROR_NULL_KEY);
206 checkNotNull(newValue, ERROR_NULL_VALUE); 180 checkNotNull(newValue, ERROR_NULL_VALUE);
207 byte[] existing = oldValue != null ? serializer.encode(oldValue) : null; 181 byte[] existing = oldValue != null ? serializer.encode(oldValue) : null;
208 - return complete(proxy.replace(name, keyCache.getUnchecked(key), existing, serializer.encode(newValue))); 182 + return proxy.replace(name, keyCache.getUnchecked(key), existing, serializer.encode(newValue));
209 } 183 }
210 184
211 @Override 185 @Override
212 - public boolean replace(K key, long oldVersion, V newValue) { 186 + public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
213 checkNotNull(key, ERROR_NULL_KEY); 187 checkNotNull(key, ERROR_NULL_KEY);
214 checkNotNull(newValue, ERROR_NULL_VALUE); 188 checkNotNull(newValue, ERROR_NULL_VALUE);
215 - return complete(proxy.replace(name, keyCache.getUnchecked(key), oldVersion, serializer.encode(newValue))); 189 + return proxy.replace(name, keyCache.getUnchecked(key), oldVersion, serializer.encode(newValue));
216 - }
217 -
218 - private static <T> T complete(CompletableFuture<T> future) {
219 - try {
220 - return future.get(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
221 - } catch (InterruptedException e) {
222 - Thread.currentThread().interrupt();
223 - throw new ConsistentMapException.Interrupted();
224 - } catch (TimeoutException e) {
225 - throw new ConsistentMapException.Timeout();
226 - } catch (ExecutionException e) {
227 - throw new ConsistentMapException(e.getCause());
228 - }
229 } 190 }
230 191
231 private Map.Entry<K, Versioned<V>> fromRawEntry(Map.Entry<String, Versioned<byte[]>> e) { 192 private Map.Entry<K, Versioned<V>> fromRawEntry(Map.Entry<String, Versioned<byte[]>> e) {
......
1 +/*
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 + */
16 +
17 +package org.onosproject.store.consistent.impl;
18 +
19 +import java.util.Collection;
20 +import java.util.Map.Entry;
21 +import java.util.concurrent.CompletableFuture;
22 +import java.util.concurrent.ExecutionException;
23 +import java.util.concurrent.TimeUnit;
24 +import java.util.concurrent.TimeoutException;
25 +import java.util.Set;
26 +
27 +import org.onosproject.store.service.AsyncConsistentMap;
28 +import org.onosproject.store.service.ConsistentMap;
29 +import org.onosproject.store.service.ConsistentMapException;
30 +import org.onosproject.store.service.Serializer;
31 +import org.onosproject.store.service.Versioned;
32 +
33 +/**
34 + * ConsistentMap implementation that is backed by a Raft consensus
35 + * based database.
36 + *
37 + * @param <K> type of key.
38 + * @param <V> type of value.
39 + */
40 +public class DefaultConsistentMap<K, V> implements ConsistentMap<K, V> {
41 +
42 + private static final int OPERATION_TIMEOUT_MILLIS = 5000;
43 +
44 + private final AsyncConsistentMap<K, V> asyncMap;
45 +
46 + public DefaultConsistentMap(String name,
47 + DatabaseProxy<String, byte[]> proxy,
48 + Serializer serializer) {
49 + asyncMap = new DefaultAsyncConsistentMap<>(name, proxy, serializer);
50 + }
51 +
52 + @Override
53 + public int size() {
54 + return complete(asyncMap.size());
55 + }
56 +
57 + @Override
58 + public boolean isEmpty() {
59 + return complete(asyncMap.isEmpty());
60 + }
61 +
62 + @Override
63 + public boolean containsKey(K key) {
64 + return complete(asyncMap.containsKey(key));
65 + }
66 +
67 + @Override
68 + public boolean containsValue(V value) {
69 + return complete(asyncMap.containsValue(value));
70 + }
71 +
72 + @Override
73 + public Versioned<V> get(K key) {
74 + return complete(asyncMap.get(key));
75 + }
76 +
77 + @Override
78 + public Versioned<V> put(K key, V value) {
79 + return complete(asyncMap.put(key, value));
80 + }
81 +
82 + @Override
83 + public Versioned<V> remove(K key) {
84 + return complete(asyncMap.remove(key));
85 + }
86 +
87 + @Override
88 + public void clear() {
89 + complete(asyncMap.clear());
90 + }
91 +
92 + @Override
93 + public Set<K> keySet() {
94 + return complete(asyncMap.keySet());
95 + }
96 +
97 + @Override
98 + public Collection<Versioned<V>> values() {
99 + return complete(asyncMap.values());
100 + }
101 +
102 + @Override
103 + public Set<Entry<K, Versioned<V>>> entrySet() {
104 + return complete(asyncMap.entrySet());
105 + }
106 +
107 + @Override
108 + public Versioned<V> putIfAbsent(K key, V value) {
109 + return complete(asyncMap.putIfAbsent(key, value));
110 + }
111 +
112 + @Override
113 + public boolean remove(K key, V value) {
114 + return complete(asyncMap.remove(key, value));
115 + }
116 +
117 + @Override
118 + public boolean remove(K key, long version) {
119 + return complete(asyncMap.remove(key, version));
120 + }
121 +
122 + @Override
123 + public boolean replace(K key, V oldValue, V newValue) {
124 + return complete(asyncMap.replace(key, oldValue, newValue));
125 + }
126 +
127 + @Override
128 + public boolean replace(K key, long oldVersion, V newValue) {
129 + return complete(asyncMap.replace(key, oldVersion, newValue));
130 + }
131 +
132 + private static <T> T complete(CompletableFuture<T> future) {
133 + try {
134 + return future.get(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
135 + } catch (InterruptedException e) {
136 + Thread.currentThread().interrupt();
137 + throw new ConsistentMapException.Interrupted();
138 + } catch (TimeoutException e) {
139 + throw new ConsistentMapException.Timeout();
140 + } catch (ExecutionException e) {
141 + throw new ConsistentMapException(e.getCause());
142 + }
143 + }
144 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -63,7 +63,7 @@ public class DefaultTransactionContext implements TransactionContext { ...@@ -63,7 +63,7 @@ public class DefaultTransactionContext implements TransactionContext {
63 checkNotNull(serializer, "serializer is null"); 63 checkNotNull(serializer, "serializer is null");
64 checkState(isOpen, TX_NOT_OPEN_ERROR); 64 checkState(isOpen, TX_NOT_OPEN_ERROR);
65 if (!txMaps.containsKey(mapName)) { 65 if (!txMaps.containsKey(mapName)) {
66 - ConsistentMap<K, V> backingMap = new ConsistentMapImpl<>(mapName, databaseProxy, serializer); 66 + ConsistentMap<K, V> backingMap = new DefaultConsistentMap<>(mapName, databaseProxy, serializer);
67 DefaultTransactionalMap<K, V> txMap = new DefaultTransactionalMap<>(mapName, backingMap, this, serializer); 67 DefaultTransactionalMap<K, V> txMap = new DefaultTransactionalMap<>(mapName, backingMap, this, serializer);
68 txMaps.put(mapName, txMap); 68 txMaps.put(mapName, txMap);
69 } 69 }
......