[ONOS-4931] fix doc of FlowEntry.life(), add life(TimeUnit)

Fix the doc: life() returns the time in seconds, not milliseconds.

Add new method life(TimeUnit) that allows specifying the timeunit to
receive the life value as as seconds might not be enough for
all applications and OpenFlow can provide this value to nanoseconds resolution
(in its spec).

Change-Id: Ia6a7573797249e0edc04e03c7204a550a2823742
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java
index dbd5e08..a770e97 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java
@@ -16,16 +16,22 @@
 package org.onosproject.net.flow;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.slf4j.LoggerFactory.getLogger;
 
 import org.slf4j.Logger;
 
+import java.util.concurrent.TimeUnit;
+
 public class DefaultFlowEntry extends DefaultFlowRule
     implements StoredFlowEntry {
 
     private static final Logger log = getLogger(DefaultFlowEntry.class);
 
+    /* Stored in nanoseconds (allows for 292 years) */
     private long life;
+
     private long packets;
     private long bytes;
     private FlowEntryState state;
@@ -37,10 +43,10 @@
     private final int errCode;
 
     public DefaultFlowEntry(FlowRule rule, FlowEntryState state,
-            long life, long packets, long bytes) {
+                            long life, TimeUnit lifeTimeUnit, long packets, long bytes) {
         super(rule);
         this.state = state;
-        this.life = life;
+        this.life = lifeTimeUnit.toNanos(life);
         this.packets = packets;
         this.bytes = bytes;
         this.errCode = -1;
@@ -48,15 +54,13 @@
         this.lastSeen = System.currentTimeMillis();
     }
 
+    public DefaultFlowEntry(FlowRule rule, FlowEntryState state,
+                            long lifeSecs, long packets, long bytes) {
+        this(rule, state, lifeSecs, SECONDS, packets, bytes);
+    }
+
     public DefaultFlowEntry(FlowRule rule) {
-        super(rule);
-        this.state = FlowEntryState.PENDING_ADD;
-        this.life = 0;
-        this.packets = 0;
-        this.bytes = 0;
-        this.errCode = -1;
-        this.errType = -1;
-        this.lastSeen = System.currentTimeMillis();
+        this(rule, FlowEntryState.PENDING_ADD, 0, 0, 0);
     }
 
     public DefaultFlowEntry(FlowRule rule, int errType, int errCode) {
@@ -69,7 +73,12 @@
 
     @Override
     public long life() {
-        return life;
+        return life(SECONDS);
+    }
+
+    @Override
+    public long life(TimeUnit timeUnit) {
+        return timeUnit.convert(life, NANOSECONDS);
     }
 
     @Override
@@ -104,7 +113,12 @@
 
     @Override
     public void setLife(long life) {
-        this.life = life;
+        setLife(life, SECONDS);
+    }
+
+    @Override
+    public void setLife(long life, TimeUnit timeUnit) {
+        this.life = timeUnit.toNanos(life);
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTypedFlowEntry.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTypedFlowEntry.java
index 03ea3d7..31d394a 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTypedFlowEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTypedFlowEntry.java
@@ -16,7 +16,10 @@
 
 package org.onosproject.net.flow;
 
+import java.util.concurrent.TimeUnit;
+
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
 /**
  * Default flow entry class with FlowLiveType value, IMMEDIATE_FLOW, SHORT_FLOW, MID_FLOW, LONG_FLOW.
@@ -25,6 +28,23 @@
     implements TypedStoredFlowEntry {
     private FlowLiveType liveType;
 
+
+    /**
+     * Creates a typed flow entry from flow rule and its statistics, with default flow live type(IMMEDIATE_FLOW).
+     *
+     * @param rule the flow rule
+     * @param state the flow state
+     * @param life the flow duration since creation
+     * @param lifeTimeUnit the time unit of life
+     * @param packets the flow packets count
+     * @param bytes the flow bytes count
+     */
+    public DefaultTypedFlowEntry(FlowRule rule, FlowEntryState state,
+                                 long life, TimeUnit lifeTimeUnit, long packets, long bytes) {
+        super(rule, state, life, lifeTimeUnit, packets, bytes);
+        this.liveType = FlowLiveType.IMMEDIATE_FLOW;
+    }
+
     /**
      * Creates a typed flow entry from flow rule and its statistics, with default flow live type(IMMEDIATE_FLOW).
      *
@@ -59,7 +79,7 @@
      *
      */
     public DefaultTypedFlowEntry(FlowEntry fe) {
-        super(fe, fe.state(), fe.life(), fe.packets(), fe.bytes());
+        super(fe, fe.state(), fe.life(NANOSECONDS), NANOSECONDS, fe.packets(), fe.bytes());
         this.liveType = FlowLiveType.IMMEDIATE_FLOW;
     }
 
@@ -83,7 +103,7 @@
      *
      */
     public DefaultTypedFlowEntry(FlowEntry fe,  FlowLiveType liveType) {
-        super(fe, fe.state(), fe.life(), fe.packets(), fe.bytes());
+        super(fe, fe.state(), fe.life(NANOSECONDS), NANOSECONDS, fe.packets(), fe.bytes());
         this.liveType = liveType;
     }
 
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java b/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java
index 019d3be..1511d21 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java
@@ -16,6 +16,8 @@
 package org.onosproject.net.flow;
 
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Represents a generalized match & action pair to be applied to
  * an infrastucture device.
@@ -60,13 +62,20 @@
     FlowEntryState state();
 
     /**
-     * Returns the number of milliseconds this flow rule has been applied.
+     * Returns the number of seconds this flow rule has been applied.
      *
-     * @return number of millis
+     * @return number of seconds
      */
     long life();
 
     /**
+     * Returns the time this flow rule has been applied.
+     *
+     * @return time in the requested {@link TimeUnit}
+     */
+    long life(TimeUnit unit);
+
+    /**
      * Returns the number of packets this flow rule has matched.
      *
      * @return number of packets
diff --git a/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java b/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java
index ff0700d..b3a6564 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java
@@ -16,6 +16,8 @@
 package org.onosproject.net.flow;
 
 
+import java.util.concurrent.TimeUnit;
+
 public interface StoredFlowEntry extends FlowEntry {
 
     /**
@@ -31,9 +33,16 @@
 
     /**
      * Sets how long this entry has been entered in the system.
-     * @param life epoch time
+     * @param lifeSecs seconds
      */
-    void setLife(long life);
+    void setLife(long lifeSecs);
+
+    /**
+     * Sets how long this entry has been entered in the system.
+     * @param life time
+     * @param timeUnit unit of time
+     */
+    void setLife(long life, TimeUnit timeUnit);
 
     /**
      * Number of packets seen by this entry.
diff --git a/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowEntryTest.java b/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowEntryTest.java
index 21b7a80..e0cd135 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowEntryTest.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowEntryTest.java
@@ -75,6 +75,9 @@
         assertThat(defaultFlowEntry1.treatment(), is(TREATMENT));
         assertThat(defaultFlowEntry1.timeout(), is(1));
         assertThat(defaultFlowEntry1.life(), is(1L));
+        assertThat(defaultFlowEntry1.life(TimeUnit.SECONDS), is(1L));
+        assertThat(defaultFlowEntry1.life(TimeUnit.MILLISECONDS), is(1000L));
+        assertThat(defaultFlowEntry1.life(TimeUnit.MINUTES), is(0L));
         assertThat(defaultFlowEntry1.packets(), is(1L));
         assertThat(defaultFlowEntry1.bytes(), is(1L));
         assertThat(defaultFlowEntry1.state(), is(FlowEntry.FlowEntryState.ADDED));
@@ -94,13 +97,14 @@
         entry.setState(FlowEntry.FlowEntryState.PENDING_REMOVE);
         entry.setPackets(11);
         entry.setBytes(22);
-        entry.setLife(33);
+        entry.setLife(33333, TimeUnit.MILLISECONDS);
 
         assertThat(entry.deviceId(), is(did("id1")));
         assertThat(entry.selector(), is(SELECTOR));
         assertThat(entry.treatment(), is(TREATMENT));
         assertThat(entry.timeout(), is(1));
         assertThat(entry.life(), is(33L));
+        assertThat(entry.life(TimeUnit.MILLISECONDS), is(33333L));
         assertThat(entry.packets(), is(11L));
         assertThat(entry.bytes(), is(22L));
         assertThat(entry.state(), is(FlowEntry.FlowEntryState.PENDING_REMOVE));
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java
index 5926832..1f2d359 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java
@@ -51,7 +51,7 @@
                 .put("isPermanent", flowEntry.isPermanent())
                 .put("deviceId", flowEntry.deviceId().toString())
                 .put("state", flowEntry.state().toString())
-                .put("life", flowEntry.life())
+                .put("life", flowEntry.life()) //FIXME life is destroying precision (seconds granularity is default)
                 .put("packets", flowEntry.packets())
                 .put("bytes", flowEntry.bytes())
                 .put("lastSeen", flowEntry.lastSeen());
diff --git a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
index ed68887..b2860b1 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
@@ -569,7 +569,7 @@
         if (stored != null) {
             //FIXME modification of "stored" flow entry outside of flow table
             stored.setBytes(rule.bytes());
-            stored.setLife(rule.life());
+            stored.setLife(rule.life(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
             stored.setPackets(rule.packets());
             stored.setLastSeen();
             if (stored.state() == FlowEntryState.PENDING_ADD) {
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java
index 2d55531..52d6099 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java
@@ -449,7 +449,7 @@
 
                 // update now
                 //FIXME modification of "stored" flow entry outside of store
-                stored.setLife(fe.life());
+                stored.setLife(fe.life(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
                 stored.setPackets(fe.packets());
                 stored.setBytes(fe.bytes());
                 stored.setLastSeen();
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
index 8c3cb92..7a2edc2 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
@@ -94,6 +94,8 @@
 
 import java.util.List;
 
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.onosproject.net.flow.criteria.Criteria.*;
 import static org.onosproject.net.flow.instructions.Instructions.modL0Lambda;
 import static org.onosproject.net.flow.instructions.Instructions.modL1OduSignalId;
@@ -170,7 +172,8 @@
                     }
 
                     return new DefaultFlowEntry(builder.build(), FlowEntryState.ADDED,
-                                                stat.getDurationSec(),
+                                                SECONDS.toNanos(stat.getDurationSec())
+                                                        + stat.getDurationNsec(), NANOSECONDS,
                                                 stat.getPacketCount().getValue(),
                                                 stat.getByteCount().getValue());
                 case REMOVED:
@@ -185,7 +188,8 @@
                     }
 
                     return new DefaultFlowEntry(builder.build(), FlowEntryState.REMOVED,
-                                                removed.getDurationSec(),
+                                                SECONDS.toNanos(removed.getDurationSec())
+                                                        + removed.getDurationNsec(), NANOSECONDS,
                                                 removed.getPacketCount().getValue(),
                                                 removed.getByteCount().getValue());
                 case MOD:
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java
index 4687e44..68dc393 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java
@@ -64,7 +64,9 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.anyShort;
 import static org.easymock.EasyMock.anyString;
@@ -141,7 +143,12 @@
 
         @Override
         public long life() {
-            return baseValue + 11;
+            return life(SECONDS);
+        }
+
+        @Override
+        public long life(TimeUnit timeUnit) {
+            return SECONDS.convert(baseValue + 11, timeUnit);
         }
 
         @Override