Improvements to ECMapImpl to increase consistency

- When a new map is created, initiate advertisements with peers
- Increase High Load threshold to an average of 1 op per slot
- Attempts to mitigate [ONOS-4569]

Change-Id: I0412d17b55804e4bc095347256e94a49a344c0cc
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/EventuallyConsistentMapImpl.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/EventuallyConsistentMapImpl.java
index 2e1e29a..11b446a 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/EventuallyConsistentMapImpl.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/EventuallyConsistentMapImpl.java
@@ -120,7 +120,7 @@
     private final boolean tombstonesDisabled;
 
     private static final int WINDOW_SIZE = 5;
-    private static final int HIGH_LOAD_THRESHOLD = 0;
+    private static final int HIGH_LOAD_THRESHOLD = 2;
     private static final int LOAD_WINDOW = 2;
     private SlidingWindowCounter counter = new SlidingWindowCounter(WINDOW_SIZE);
 
@@ -262,6 +262,9 @@
 
         this.tombstonesDisabled = tombstonesDisabled;
         this.lightweightAntiEntropy = !convergeFaster;
+
+        // Initiate first round of Gossip
+        this.bootstrap();
     }
 
     private StoreSerializer createSerializer(KryoNamespace ns) {
@@ -721,6 +724,35 @@
         });
     }
 
+    private void bootstrap() {
+        /*
+         * Attempt to get in sync with the cluster when a map is created. This is to help avoid a new node
+         * writing to an ECM until it has a view of the map. Depending on how lightweight the map instance
+         * is, this will attempt to advertise to all or some of the peers.
+         */
+        int n = 0;
+        List<NodeId> activePeers = clusterService.getNodes()
+                .stream()
+                .map(ControllerNode::id)
+                .filter(id -> !localNodeId.equals(id))
+                .filter(id -> clusterService.getState(id).isActive())
+                .collect(Collectors.toList());
+
+        if (activePeers.isEmpty()) {
+            return;
+        }
+
+        if (lightweightAntiEntropy) {
+            n = activePeers.size() / 2;
+        } else {
+            n = activePeers.size();
+        }
+
+        for (int i = 0; i < n; i++) {
+            sendAdvertisementToPeer(activePeers.get(i));
+        }
+    }
+
     // TODO pull this into the class if this gets pulled out...
     private static final int DEFAULT_MAX_EVENTS = 1000;
     private static final int DEFAULT_MAX_IDLE_MS = 10;