[SDFAB-199] Add the support for last-change

- Add parsing in OpenConfigGnmiDeviceDescriptionDiscovery and
  defaults to 0 for the devices not providing last-change
- Remove hack in OpenConfigGnmiPortStatisticsDiscovery and set
  the duration to 0 for the devices that do not support last-change
- Subscribe to the state changes of a given port and add parsing of
  last-change timestamp in GnmiDeviceStateSubscribe

Note that if the device does not aggregate updates into a single notification
two PORT_UPDATED events will be generated. The first as consequence of the
operational status change and the second caused by the reconciliation which
updates correctly last-change

Change-Id: I6b2cb3652b306358bd9e701780946864a1ed324b
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java
index 6e361ff..bae396b 100644
--- a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java
@@ -22,11 +22,9 @@
 import gnmi.Gnmi.GetRequest;
 import gnmi.Gnmi.GetResponse;
 import gnmi.Gnmi.Path;
-import org.apache.commons.lang3.tuple.Pair;
 import org.onosproject.gnmi.api.GnmiClient;
 import org.onosproject.gnmi.api.GnmiController;
 import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DefaultPortStatistics;
@@ -48,9 +46,7 @@
         extends AbstractGrpcHandlerBehaviour<GnmiClient, GnmiController>
         implements PortStatisticsDiscovery {
 
-    private static final Map<Pair<DeviceId, PortNumber>, Long> PORT_START_TIMES =
-            Maps.newConcurrentMap();
-    private static final String LAST_CHANGE = "last-changed";
+    private static final String LAST_CHANGE = "last-change";
 
     public OpenConfigGnmiPortStatisticsDiscovery() {
         super(GnmiController.class);
@@ -185,21 +181,16 @@
             //FIXME log
             return Duration.ZERO;
         }
+
+        // Set duration 0 for devices that do not support reporting last-change
         String lastChangedStr = port.annotations().value(LAST_CHANGE);
         if (lastChangedStr == null) {
-            //FIXME log
-            // Falling back to the hack...
-            // FIXME: This is a workaround since we cannot determine the port
-            // duration from gNMI now
-            final long now = System.currentTimeMillis() / 1000;
-            final Long startTime = PORT_START_TIMES.putIfAbsent(
-                    Pair.of(deviceId, portNumber), now);
-            return Duration.ofSeconds(startTime == null ? now : now - startTime);
+            return Duration.ZERO;
         }
 
         try {
             long lastChanged = Long.parseLong(lastChangedStr);
-            return timestamp.minus(lastChanged, ChronoUnit.NANOS);
+            return lastChanged == 0 ? Duration.ZERO : timestamp.minus(lastChanged, ChronoUnit.NANOS);
         } catch (NullPointerException | NumberFormatException ex) {
             //FIXME log
             return Duration.ZERO;