Add API in DeviceClock*Service to check if Timestamp can be issued.

- check local DeviceClockProviderService before trying to
  store Port update information.

Change-Id: I22c94cb712d7001a227497b723780b6db3fbdf04
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
index 72dc03c..011f2a8 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
@@ -25,6 +25,14 @@
 public interface DeviceClockProviderService {
 
     /**
+     * Checks if this service can issue Timestamp for specified device.
+     *
+     * @param deviceId device identifier.
+     * @return true if timestamp can be issued for specified device
+     */
+    public boolean isTimestampAvailable(DeviceId deviceId);
+
+    /**
      * Updates the mastership term for the specified deviceId.
      *
      * @param deviceId device identifier.
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
index 2104d2e..2214cfd 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
@@ -24,7 +24,16 @@
 public interface DeviceClockService {
 
     /**
+     * Checks if this service can issue Timestamp for specified device.
+     *
+     * @param deviceId device identifier.
+     * @return true if timestamp can be issued for specified device
+     */
+    public boolean isTimestampAvailable(DeviceId deviceId);
+
+    /**
      * Returns a new timestamp for the specified deviceId.
+     *
      * @param deviceId device identifier.
      * @return timestamp.
      */
diff --git a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
index 740a110..33200b9 100644
--- a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
@@ -343,6 +343,13 @@
                          "Port descriptions list cannot be null");
             checkValidity();
 
+            if (!deviceClockProviderService.isTimestampAvailable(deviceId)) {
+                // Never been a master for this device
+                // any update will be ignored.
+                log.trace("Ignoring {} port updates on standby node. {}", deviceId, portDescriptions);
+                return;
+            }
+
             List<DeviceEvent> events = store.updatePorts(this.provider().id(),
                                                          deviceId, portDescriptions);
             for (DeviceEvent event : events) {
@@ -357,6 +364,13 @@
             checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
             checkValidity();
 
+            if (!deviceClockProviderService.isTimestampAvailable(deviceId)) {
+                // Never been a master for this device
+                // any update will be ignored.
+                log.trace("Ignoring {} port update on standby node. {}", deviceId, portDescription);
+                return;
+            }
+
             final DeviceEvent event = store.updatePortStatus(this.provider().id(),
                                                              deviceId, portDescription);
             if (event != null) {
diff --git a/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
index 25fa922..79e2f10 100644
--- a/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
@@ -19,7 +19,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.onlab.onos.cluster.ClusterEventListener;
 import org.onlab.onos.cluster.ClusterService;
@@ -181,16 +180,6 @@
         assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1));
     }
 
-    @Ignore("disabled until we settle the device-mastership wiring")
-    @Test
-    public void setRole() throws InterruptedException {
-        connectDevice(DID1, SW1);
-        validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED);
-        assertEquals("incorrect role", MastershipRole.STANDBY, service.getRole(DID1));
-        assertEquals("incorrect device", DID1, provider.deviceReceived.id());
-        assertEquals("incorrect role", MastershipRole.STANDBY, provider.roleReceived);
-    }
-
     @Test
     public void updatePorts() {
         connectDevice(DID1, SW1);
@@ -360,9 +349,16 @@
     private final class TestClockProviderService implements
             DeviceClockProviderService {
 
+        private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet();
+
         @Override
         public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
-            // TODO Auto-generated method stub
+            registerdBefore.add(deviceId);
+        }
+
+        @Override
+        public boolean isTimestampAvailable(DeviceId deviceId) {
+            return registerdBefore.contains(deviceId);
         }
     }
 }
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
index f7f24e9..486d41e 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
@@ -72,4 +72,9 @@
         log.info("adding term info {} {}", deviceId, term.master());
         deviceMastershipTerms.put(deviceId, term);
     }
+
+    @Override
+    public boolean isTimestampAvailable(DeviceId deviceId) {
+        return deviceMastershipTerms.containsKey(deviceId);
+    }
 }
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
index 64e5e16..d32ac53 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
@@ -15,13 +15,16 @@
  */
 package org.onlab.onos.store.trivial.impl;
 
+import java.util.Set;
+
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.onos.mastership.MastershipTerm;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.device.DeviceClockProviderService;
 
-//FIXME: Code clone in onos-core-trivial, onos-core-hz-net
+import com.google.common.collect.Sets;
+
 /**
  * Dummy implementation of {@link DeviceClockProviderService}.
  */
@@ -29,7 +32,15 @@
 @Service
 public class NoOpClockProviderService implements DeviceClockProviderService {
 
+    private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet();
+
     @Override
     public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
+        registerdBefore.add(deviceId);
+    }
+
+    @Override
+    public boolean isTimestampAvailable(DeviceId deviceId) {
+        return registerdBefore.contains(deviceId);
     }
 }