[ONOS-6423] Implement missing getOrDefault methods in primitive wrappers

Change-Id: I560ee03e20511f5ffc93cc4ceb874cb3142c11ab
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CachingAsyncConsistentMap.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CachingAsyncConsistentMap.java
index 5c0eaef..cedd810 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CachingAsyncConsistentMap.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CachingAsyncConsistentMap.java
@@ -50,7 +50,7 @@
     private final Logger log = getLogger(getClass());
 
     private final LoadingCache<K, CompletableFuture<Versioned<V>>> cache;
-
+    private final AsyncConsistentMap<K, V> backingMap;
     private final MapEventListener<K, V> cacheUpdater;
     private final Consumer<Status> statusListener;
 
@@ -71,6 +71,7 @@
      */
     public CachingAsyncConsistentMap(AsyncConsistentMap<K, V> backingMap, int cacheSize) {
         super(backingMap);
+        this.backingMap = backingMap;
         cache = CacheBuilder.newBuilder()
                             .maximumSize(cacheSize)
                             .build(CacheLoader.from(CachingAsyncConsistentMap.super::get));
@@ -111,6 +112,23 @@
     }
 
     @Override
+    public CompletableFuture<Versioned<V>> getOrDefault(K key, V defaultValue) {
+        return cache.getUnchecked(key).thenCompose(r -> {
+            if (r == null) {
+                CompletableFuture<Versioned<V>> versioned = backingMap.getOrDefault(key, defaultValue);
+                cache.put(key, versioned);
+                return versioned;
+            } else {
+                return CompletableFuture.completedFuture(r);
+            }
+        }).whenComplete((r, e) -> {
+            if (e != null) {
+                cache.invalidate(key);
+            }
+        });
+    }
+
+    @Override
     public CompletableFuture<Versioned<V>> computeIf(K key,
             Predicate<? super V> condition,
             BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/MeteredAsyncConsistentMap.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/MeteredAsyncConsistentMap.java
index ccffead..4b9ff98 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/MeteredAsyncConsistentMap.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/MeteredAsyncConsistentMap.java
@@ -54,6 +54,7 @@
     private static final String CONTAINS_KEY = "containsKey";
     private static final String CONTAINS_VALUE = "containsValue";
     private static final String GET = "get";
+    private static final String GET_OR_DEFAULT = "getOrDefault";
     private static final String COMPUTE_IF = "computeIf";
     private static final String PUT = "put";
     private static final String PUT_AND_GET = "putAndGet";
@@ -119,6 +120,13 @@
     }
 
     @Override
+    public CompletableFuture<Versioned<V>> getOrDefault(K key, V defaultValue) {
+        final MeteringAgent.Context timer = monitor.startTimer(GET_OR_DEFAULT);
+        return super.getOrDefault(key, defaultValue)
+                .whenComplete((r, e) -> timer.stop(e));
+    }
+
+    @Override
     public CompletableFuture<Versioned<V>> computeIfAbsent(K key,
                                                            Function<? super K, ? extends V> mappingFunction) {
         final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF_ABSENT);