Implement minimum heartbeat interval in failure detectors

Change-Id: I6c0cab43f69c25d085ec6168655e60cc73b41b21
diff --git a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
index ceaec03..af1cffe 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
@@ -293,6 +293,7 @@
                 if (phi >= phiFailureThreshold) {
                     if (currentState.isActive()) {
                         updateNode(node.id(), State.INACTIVE, null);
+                        failureDetector.reset(node.id());
                     }
                 } else {
                     if (currentState == State.INACTIVE) {
@@ -334,11 +335,12 @@
         public void accept(Endpoint sender, byte[] message) {
             HeartbeatMessage hb = SERIALIZER.decode(message);
             if (clusterMetadataService.getClusterMetadata().getNodes().contains(hb.source())) {
-                State state = nodeStates.get(hb.source().id());
-                if (state != null && !state.isActive() && hb.state.isActive()) {
-                    failureDetector.reset(hb.source().id());
+                // Avoid reporting heartbeats that have been enqueued by setting a minimum interval.
+                long heartbeatTime = System.currentTimeMillis();
+                long lastHeartbeatTime = failureDetector.getLastHeartbeatTime(hb.source().id());
+                if (heartbeatTime - lastHeartbeatTime > heartbeatInterval / 2) {
+                    failureDetector.report(hb.source().id(), heartbeatTime);
                 }
-                failureDetector.report(hb.source().id());
                 updateNode(hb.source().id(), hb.state, hb.version);
             }
         }
diff --git a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java
index 922057f..b80142b 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java
@@ -49,6 +49,17 @@
     private double bootstrapPhiValue = DEFAULT_BOOTSTRAP_PHI_VALUE;
 
     /**
+     * Returns the last heartbeat time for the given node.
+     *
+     * @param nodeId the node identifier
+     * @return the last heartbeat time for the given node
+     */
+    public long getLastHeartbeatTime(NodeId nodeId) {
+        History nodeState = states.computeIfAbsent(nodeId, key -> new History());
+        return nodeState.latestHeartbeatTime();
+    }
+
+    /**
      * Report a new heart beat for the specified node id.
      * @param nodeId node id
      */
@@ -81,7 +92,7 @@
      * @param nodeId node identifier for the node for which to reset the failure detector
      */
     public void reset(NodeId nodeId) {
-        states.put(nodeId, new History());
+        states.remove(nodeId);
     }
 
     /**