Explicitly disallow null values in the map
Change-Id: I3b8d287a534e85d9454ca261a8eb666c477c43c1
Showing
2 changed files
with
21 additions
and
3 deletions
| ... | @@ -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)) { | ... | ... |
-
Please register or login to post a comment