Jonathan Hart

Explicitly disallow null values in the map

Change-Id: I3b8d287a534e85d9454ca261a8eb666c477c43c1
...@@ -21,19 +21,22 @@ import java.util.Set; ...@@ -21,19 +21,22 @@ import java.util.Set;
21 21
22 /** 22 /**
23 * A distributed, eventually consistent map. 23 * A distributed, eventually consistent map.
24 - * 24 + * <p>
25 * This map does not offer read after writes consistency. Operations are 25 * This map does not offer read after writes consistency. Operations are
26 * serialized via the timestamps issued by the clock service. If two updates 26 * serialized via the timestamps issued by the clock service. If two updates
27 * are in conflict, the update with the more recent timestamp will endure. 27 * are in conflict, the update with the more recent timestamp will endure.
28 - * 28 + * </p><p>
29 * The interface is mostly similar to {@link java.util.Map} with some minor 29 * The interface is mostly similar to {@link java.util.Map} with some minor
30 * semantic changes and the addition of a listener framework (because the map 30 * semantic changes and the addition of a listener framework (because the map
31 * can be mutated by clients on other instances, not only through the local Java 31 * can be mutated by clients on other instances, not only through the local Java
32 * API). 32 * API).
33 - * 33 + * </p><p>
34 * Clients are expected to register an 34 * Clients are expected to register an
35 * {@link org.onosproject.store.impl.EventuallyConsistentMapListener} if they 35 * {@link org.onosproject.store.impl.EventuallyConsistentMapListener} if they
36 * are interested in receiving notifications of update to the map. 36 * are interested in receiving notifications of update to the map.
37 + * </p><p>
38 + * Null values are not allowed in this map.
39 + * </p>
37 */ 40 */
38 public interface EventuallyConsistentMap<K, V> { 41 public interface EventuallyConsistentMap<K, V> {
39 42
...@@ -84,6 +87,8 @@ public interface EventuallyConsistentMap<K, V> { ...@@ -84,6 +87,8 @@ public interface EventuallyConsistentMap<K, V> {
84 * Clients are expected to register an 87 * Clients are expected to register an
85 * {@link org.onosproject.store.impl.EventuallyConsistentMapListener} if 88 * {@link org.onosproject.store.impl.EventuallyConsistentMapListener} if
86 * they are interested in receiving notification of updates to the map. 89 * they are interested in receiving notification of updates to the map.
90 + * </p><p>
91 + * Null values are not allowed in the map.
87 * </p> 92 * </p>
88 * 93 *
89 * @param key the key to add a mapping for in this map 94 * @param key the key to add a mapping for in this map
......
...@@ -85,6 +85,9 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -85,6 +85,9 @@ public class EventuallyConsistentMapImpl<K, V>
85 private volatile boolean destroyed = false; 85 private volatile boolean destroyed = false;
86 private static final String ERROR_DESTROYED = " map is already destroyed"; 86 private static final String ERROR_DESTROYED = " map is already destroyed";
87 87
88 + private static final String ERROR_NULL_KEY = "Key cannot be null";
89 + private static final String ERROR_NULL_VALUE = "Null values are not allowed";
90 +
88 // TODO: Make these anti-entropy params configurable 91 // TODO: Make these anti-entropy params configurable
89 private long initialDelaySec = 5; 92 private long initialDelaySec = 5;
90 private long periodSec = 5; 93 private long periodSec = 5;
...@@ -193,12 +196,14 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -193,12 +196,14 @@ public class EventuallyConsistentMapImpl<K, V>
193 @Override 196 @Override
194 public boolean containsKey(K key) { 197 public boolean containsKey(K key) {
195 checkState(!destroyed, mapName + ERROR_DESTROYED); 198 checkState(!destroyed, mapName + ERROR_DESTROYED);
199 + checkNotNull(key, ERROR_NULL_KEY);
196 return items.containsKey(key); 200 return items.containsKey(key);
197 } 201 }
198 202
199 @Override 203 @Override
200 public boolean containsValue(V value) { 204 public boolean containsValue(V value) {
201 checkState(!destroyed, mapName + ERROR_DESTROYED); 205 checkState(!destroyed, mapName + ERROR_DESTROYED);
206 + checkNotNull(value, ERROR_NULL_VALUE);
202 207
203 return items.values().stream() 208 return items.values().stream()
204 .anyMatch(timestamped -> timestamped.value().equals(value)); 209 .anyMatch(timestamped -> timestamped.value().equals(value));
...@@ -207,6 +212,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -207,6 +212,7 @@ public class EventuallyConsistentMapImpl<K, V>
207 @Override 212 @Override
208 public V get(K key) { 213 public V get(K key) {
209 checkState(!destroyed, mapName + ERROR_DESTROYED); 214 checkState(!destroyed, mapName + ERROR_DESTROYED);
215 + checkNotNull(key, ERROR_NULL_KEY);
210 216
211 Timestamped<V> value = items.get(key); 217 Timestamped<V> value = items.get(key);
212 if (value != null) { 218 if (value != null) {
...@@ -218,6 +224,8 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -218,6 +224,8 @@ public class EventuallyConsistentMapImpl<K, V>
218 @Override 224 @Override
219 public void put(K key, V value) { 225 public void put(K key, V value) {
220 checkState(!destroyed, mapName + ERROR_DESTROYED); 226 checkState(!destroyed, mapName + ERROR_DESTROYED);
227 + checkNotNull(key, ERROR_NULL_KEY);
228 + checkNotNull(value, ERROR_NULL_VALUE);
221 229
222 Timestamp timestamp = clockService.getTimestamp(key); 230 Timestamp timestamp = clockService.getTimestamp(key);
223 if (putInternal(key, value, timestamp)) { 231 if (putInternal(key, value, timestamp)) {
...@@ -250,6 +258,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -250,6 +258,7 @@ public class EventuallyConsistentMapImpl<K, V>
250 @Override 258 @Override
251 public void remove(K key) { 259 public void remove(K key) {
252 checkState(!destroyed, mapName + ERROR_DESTROYED); 260 checkState(!destroyed, mapName + ERROR_DESTROYED);
261 + checkNotNull(key, ERROR_NULL_KEY);
253 262
254 Timestamp timestamp = clockService.getTimestamp(key); 263 Timestamp timestamp = clockService.getTimestamp(key);
255 if (removeInternal(key, timestamp)) { 264 if (removeInternal(key, timestamp)) {
...@@ -282,6 +291,10 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -282,6 +291,10 @@ public class EventuallyConsistentMapImpl<K, V>
282 for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) { 291 for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
283 K key = entry.getKey(); 292 K key = entry.getKey();
284 V value = entry.getValue(); 293 V value = entry.getValue();
294 +
295 + checkNotNull(key, ERROR_NULL_KEY);
296 + checkNotNull(value, ERROR_NULL_VALUE);
297 +
285 Timestamp timestamp = clockService.getTimestamp(entry.getKey()); 298 Timestamp timestamp = clockService.getTimestamp(entry.getKey());
286 299
287 if (putInternal(key, value, timestamp)) { 300 if (putInternal(key, value, timestamp)) {
......