[VOL-3590] Synchronizing read ans subsequent write to the pending Meters map to avoid duplicate meters

Change-Id: I7c08a642dd7183f5bed2da86f59f53a30865790a
diff --git a/app/src/main/java/org/opencord/olt/impl/Olt.java b/app/src/main/java/org/opencord/olt/impl/Olt.java
index d572657..3323480 100644
--- a/app/src/main/java/org/opencord/olt/impl/Olt.java
+++ b/app/src/main/java/org/opencord/olt/impl/Olt.java
@@ -797,11 +797,10 @@
         }
     }
     private void checkAndCreateDevMeter(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
-        if (oltMeterService.isMeterPending(deviceId, bwpInfo)) {
-            log.debug("Meter is already pending {} on device {}", bwpInfo, deviceId);
+        //If false the meter is already being installed, skipping installation
+        if (!oltMeterService.checkAndAddPendingMeter(deviceId, bwpInfo)) {
             return;
         }
-        oltMeterService.addToPendingMeters(deviceId, bwpInfo);
         createMeter(deviceId, bwpInfo);
     }
 
diff --git a/app/src/main/java/org/opencord/olt/impl/OltFlowService.java b/app/src/main/java/org/opencord/olt/impl/OltFlowService.java
index f934c54..6ae705a 100644
--- a/app/src/main/java/org/opencord/olt/impl/OltFlowService.java
+++ b/app/src/main/java/org/opencord/olt/impl/OltFlowService.java
@@ -473,12 +473,10 @@
                                                                null, bpInfo.id());
                 pendingEapolForMeters.add(fi);
 
-                if (oltMeterService.isMeterPending(devId, bpInfo)) {
-                    log.debug("Meter is already pending for EAPOL on {} with bp {}",
-                              devId, bpInfo);
+                //If false the meter is already being installed, skipping installation
+                if (!oltMeterService.checkAndAddPendingMeter(devId, bpInfo)) {
                     return;
                 }
-                oltMeterService.addToPendingMeters(devId, bpInfo);
                 MeterId innerMeterId = oltMeterService.createMeter(devId, bpInfo,
                                                                    meterFuture);
                 fi.setUpMeterId(innerMeterId);
diff --git a/app/src/main/java/org/opencord/olt/impl/OltMeterService.java b/app/src/main/java/org/opencord/olt/impl/OltMeterService.java
index 7616141..478e280 100644
--- a/app/src/main/java/org/opencord/olt/impl/OltMeterService.java
+++ b/app/src/main/java/org/opencord/olt/impl/OltMeterService.java
@@ -256,20 +256,6 @@
     }
 
     @Override
-    public void addToPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
-        if (deviceId == null) {
-            return;
-        }
-        pendingMeters.compute(deviceId, (id, bwps) -> {
-            if (bwps == null) {
-                bwps = new HashSet<>();
-            }
-            bwps.add(bwpInfo);
-            return bwps;
-        });
-    }
-
-    @Override
     public void removeFromPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
         if (deviceId == null) {
             return;
@@ -281,11 +267,24 @@
     }
 
     @Override
-    public boolean isMeterPending(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
-        if (!pendingMeters.containsKey(deviceId)) {
+    public synchronized boolean checkAndAddPendingMeter(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
+        if (pendingMeters.containsKey(deviceId)
+                && pendingMeters.get(deviceId).contains(bwpInfo)) {
+            log.debug("Meter is already pending for EAPOL on {} with bp {}",
+                      deviceId, bwpInfo);
             return false;
         }
-        return pendingMeters.get(deviceId).contains(bwpInfo);
+        log.debug("Adding bandwidth profile {} to pending on {}",
+                  bwpInfo, deviceId);
+        pendingMeters.compute(deviceId, (id, bwps) -> {
+            if (bwps == null) {
+                bwps = new HashSet<>();
+            }
+            bwps.add(bwpInfo);
+            return bwps;
+        });
+
+        return true;
     }
 
     @Override
diff --git a/app/src/main/java/org/opencord/olt/internalapi/AccessDeviceMeterService.java b/app/src/main/java/org/opencord/olt/internalapi/AccessDeviceMeterService.java
index 4b921fb..ca04ed4 100644
--- a/app/src/main/java/org/opencord/olt/internalapi/AccessDeviceMeterService.java
+++ b/app/src/main/java/org/opencord/olt/internalapi/AccessDeviceMeterService.java
@@ -68,14 +68,6 @@
                         CompletableFuture<Object> meterFuture);
 
     /**
-     * Adds the DeviceBandwidthProfile to the pendingMeters.
-     *
-     * @param deviceId the device
-     * @param bwpInfo the bandwidth profile info
-     */
-    void addToPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo);
-
-    /**
      * Removes the DeviceBandwidthProfile from the pendingMeters.
      *
      * @param deviceId the device
@@ -85,14 +77,18 @@
     void removeFromPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo);
 
     /**
-     * Checks if DeviceBandwidthProfile is pending.
+     * Checks if DeviceBandwidthProfile is pending installation.
+     * If so immediately returns false meaning that no further action is needed,
+     * if not it adds the bandwidth profile do the pending list and returns true,
+     * meaning that further action to install the meter is required.
      *
      * @param deviceId the device
      * @param bwpInfo the bandwidth profile info
      *
-     * @return true if pending.
+     * @return true if it was added to pending and a create meter action is needed,
+     * false if it is already pending and no further action is needed.
      */
-    boolean isMeterPending(DeviceId deviceId, BandwidthProfileInformation bwpInfo);
+    boolean checkAndAddPendingMeter(DeviceId deviceId, BandwidthProfileInformation bwpInfo);
 
     /**
      * Clears out meters for the given device.
diff --git a/app/src/test/java/org/opencord/olt/impl/OltFlowTest.java b/app/src/test/java/org/opencord/olt/impl/OltFlowTest.java
index 52ccce4..73f9b14 100644
--- a/app/src/test/java/org/opencord/olt/impl/OltFlowTest.java
+++ b/app/src/test/java/org/opencord/olt/impl/OltFlowTest.java
@@ -300,17 +300,12 @@
         }
 
         @Override
-        public void addToPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
-
-        }
-
-        @Override
         public void removeFromPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
 
         }
 
         @Override
-        public boolean isMeterPending(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
+        public boolean checkAndAddPendingMeter(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
             return false;
         }