[ONOS-4743] - DB sync is suspended if PCEP session is formed before BGP devices are learnt

Change-Id: I543201c54883e06182c1c83c4c64dd16a18e096c
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index a28a26e..76f6e3f 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -1058,6 +1058,18 @@
                 // Node-label allocation is being done during Label DB Sync.
                 // So, when device is detected, no need to do node-label
                 // allocation.
+                String lsrId = specificDevice.annotations().value(LSRID);
+                if (lsrId != null) {
+                    pceStore.addLsrIdDevice(lsrId, specificDevice.id());
+
+                    // Search in failed DB sync store. If found, trigger label DB sync.
+                    DeviceId pccDeviceId = DeviceId.deviceId(lsrId);
+                    if (pceStore.hasPccLsr(pccDeviceId)) {
+                        log.debug("Continue to perform label DB sync for device {}.", pccDeviceId.toString());
+                        syncLabelDb(pccDeviceId);
+                        pceStore.removePccLsr(pccDeviceId);
+                    }
+                }
                 break;
 
             case DEVICE_REMOVED:
@@ -1065,6 +1077,11 @@
                 if (mastershipService.getLocalRole(specificDevice.id()) == MastershipRole.MASTER) {
                     releaseNodeLabel(specificDevice);
                 }
+
+                if (specificDevice.annotations().value(LSRID) != null) {
+                    pceStore.removeLsrIdDevice(specificDevice.annotations().value(LSRID));
+                }
+
                 break;
 
             default:
@@ -1252,13 +1269,20 @@
     private boolean syncLabelDb(DeviceId deviceId) {
         checkNotNull(deviceId);
 
-        Device specificDevice = deviceService.getDevice(deviceId);
-        if (specificDevice == null) {
-            log.error("Unable to find device for specific device id {}.", deviceId.toString());
+        DeviceId actualDevcieId = pceStore.getLsrIdDevice(deviceId.toString());
+        if (actualDevcieId == null) {
+            log.error("Device not available {}.", deviceId.toString());
+            pceStore.addPccLsr(deviceId);
             return false;
         }
 
-        if (pceStore.getGlobalNodeLabel(deviceId) != null) {
+        Device specificDevice = deviceService.getDevice(actualDevcieId);
+        if (specificDevice == null) {
+            log.error("Unable to find device for specific device id {}.", actualDevcieId.toString());
+            return false;
+        }
+
+        if (pceStore.getGlobalNodeLabel(actualDevcieId) != null) {
             Map<DeviceId, LabelResourceId> globalNodeLabelMap = pceStore.getGlobalNodeLabels();
 
             for (Entry<DeviceId, LabelResourceId> entry : globalNodeLabelMap.entrySet()) {
@@ -1279,7 +1303,7 @@
                     continue;
                 }
 
-                srTeHandler.advertiseNodeLabelRule(deviceId,
+                srTeHandler.advertiseNodeLabelRule(actualDevcieId,
                                                    entry.getValue(),
                                                    IpPrefix.valueOf(IpAddress.valueOf(srcLsrId), PREFIX_LENGTH),
                                                    Objective.Operation.ADD, false);
@@ -1287,8 +1311,8 @@
 
             Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
             for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
-                if (entry.getKey().src().deviceId().equals(deviceId)) {
-                    srTeHandler.installAdjLabelRule(deviceId,
+                if (entry.getKey().src().deviceId().equals(actualDevcieId)) {
+                    srTeHandler.installAdjLabelRule(actualDevcieId,
                                                     entry.getValue(),
                                                     entry.getKey().src().port(),
                                                     entry.getKey().dst().port(),
@@ -1297,12 +1321,12 @@
             }
         }
 
-        srTeHandler.advertiseNodeLabelRule(deviceId,
+        srTeHandler.advertiseNodeLabelRule(actualDevcieId,
                                            LabelResourceId.labelResourceId(0),
                                            IpPrefix.valueOf(END_OF_SYNC_IP_PREFIX),
                                            Objective.Operation.ADD, true);
 
-        log.debug("End of label DB sync for device {}", deviceId);
+        log.debug("End of label DB sync for device {}", actualDevcieId);
 
         if (mastershipService.getLocalRole(specificDevice.id()) == MastershipRole.MASTER) {
             // Allocate node-label to this specific device.
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
index 6afdb30..0cda281 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
@@ -19,6 +19,8 @@
 
 import com.google.common.collect.ImmutableSet;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -89,6 +91,13 @@
     // List of Failed path info
     private DistributedSet<PcePathInfo> failedPathSet;
 
+    // Locally maintain LSRID to device id mapping for better performance.
+    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
+
+    // List of PCC LSR ids whose BGP device information was not available to perform
+    // label db sync.
+    private HashSet<DeviceId> pendinglabelDbSyncPccMap = new HashSet();
+
     @Activate
     protected void activate() {
         globalNodeLabelMap = storageService.<DeviceId, LabelResourceId>consistentMapBuilder()
@@ -341,4 +350,50 @@
         }
         return true;
     }
+
+    @Override
+    public boolean addLsrIdDevice(String lsrId, DeviceId deviceId) {
+        checkNotNull(lsrId);
+        checkNotNull(deviceId);
+
+        lsrIdDeviceIdMap.put(lsrId, deviceId);
+        return true;
+    }
+
+    @Override
+    public boolean removeLsrIdDevice(String lsrId) {
+        checkNotNull(lsrId);
+
+        lsrIdDeviceIdMap.remove(lsrId);
+        return true;
+    }
+
+    @Override
+    public DeviceId getLsrIdDevice(String lsrId) {
+        checkNotNull(lsrId);
+
+        return lsrIdDeviceIdMap.get(lsrId);
+
+    }
+
+    @Override
+    public boolean addPccLsr(DeviceId lsrId) {
+        checkNotNull(lsrId);
+        pendinglabelDbSyncPccMap.add(lsrId);
+        return true;
+    }
+
+    @Override
+    public boolean removePccLsr(DeviceId lsrId) {
+        checkNotNull(lsrId);
+        pendinglabelDbSyncPccMap.remove(lsrId);
+        return true;
+    }
+
+    @Override
+    public boolean hasPccLsr(DeviceId lsrId) {
+        checkNotNull(lsrId);
+        return pendinglabelDbSyncPccMap.contains(lsrId);
+
+    }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java
index 02ffcf6..3c9ceb7 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java
@@ -224,4 +224,54 @@
      * @return success or failure
      */
     boolean removeFailedPathInfo(PcePathInfo failedPathInfo);
+
+    /**
+     * Adds lsrid to device id mapping.
+     *
+     * @param lsrId lsrId of the device
+     * @param deviceId device id
+     * @return success or failure
+     */
+    boolean addLsrIdDevice(String lsrId, DeviceId deviceId);
+
+    /**
+     * Removes lsrid to device id mapping.
+     *
+     * @param lsrId lsrId of the device
+     * @return success or failure
+     */
+    boolean removeLsrIdDevice(String lsrId);
+
+    /**
+     * Gets lsrid to device id mapping.
+     *
+     * @param lsrId lsrId of the device
+     * @return device id of the lsrId
+     */
+    DeviceId getLsrIdDevice(String lsrId);
+
+    /**
+     * Adds lsrId of the PCC in form of device id for the PCC for which sync is pending due to non-availability of BGP.
+     * device.
+     *
+     * @param lsrId LSR id of the PCC in form of device id
+     * @return success or failure
+     */
+    public boolean addPccLsr(DeviceId lsrId);
+
+    /**
+     * Removes lsrId of the PCC in form of device id for the PCC for which pending sync is done.
+     *
+     * @param lsrId LSR id of the PCC in form of device id
+     * @return success or failure
+     */
+    public boolean removePccLsr(DeviceId lsrId);
+
+    /**
+     * Gets lsrId of the PCC in form of device id.
+     *
+     * @param lsrId LSR id of the PCC in form of device id
+     * @return success or failure
+     */
+    public boolean hasPccLsr(DeviceId lsrId);
 }
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
index 602c328..852a7c1 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
@@ -690,6 +690,7 @@
         LabelResourceId node1Label = LabelResourceId.labelResourceId(5200);
         LabelResourceId node2Label = LabelResourceId.labelResourceId(5201);
 
+        pceManager.pceStore.addLsrIdDevice(deviceD1.annotations().value(LSRID), deviceD1.id());
         pceManager.pceStore.addGlobalNodeLabel(D1.deviceId(), node1Label);
         pceManager.pceStore.addGlobalNodeLabel(D2.deviceId(), node2Label);
 
@@ -713,7 +714,7 @@
         eth.setEtherType(Ethernet.TYPE_IPV4);
         eth.setPayload(ipv4);
 
-        InboundPacket inPkt = new DefaultInboundPacket(new ConnectPoint(D1.deviceId(),
+        InboundPacket inPkt = new DefaultInboundPacket(new ConnectPoint(DeviceId.deviceId("1.1.1.1"),
                                                                         PortNumber.portNumber(PCEP_PORT)),
                                                        eth, null);
 
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java b/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
index beaf8ae..48120ad 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
@@ -19,6 +19,8 @@
 
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -52,6 +54,9 @@
     // Set of Path info
     private Set<PcePathInfo> failedPathInfoSet = new HashSet<>();
 
+    // Locally maintain LSRID to device id mapping for better performance.
+    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
+
     @Override
     public boolean existsGlobalNodeLabel(DeviceId id) {
         return globalNodeLabelMap.containsKey(id);
@@ -208,4 +213,39 @@
         }
         return true;
     }
+
+    @Override
+    public boolean addLsrIdDevice(String lsrId, DeviceId deviceId) {
+        lsrIdDeviceIdMap.put(lsrId, deviceId);
+        return true;
+    }
+
+    @Override
+    public boolean removeLsrIdDevice(String lsrId) {
+        lsrIdDeviceIdMap.remove(lsrId);
+        return true;
+    }
+
+    @Override
+    public DeviceId getLsrIdDevice(String lsrId) {
+        return lsrIdDeviceIdMap.get(lsrId);
+    }
+
+    @Override
+    public boolean addPccLsr(DeviceId lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean removePccLsr(DeviceId lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean hasPccLsr(DeviceId lsrId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
 }
diff --git a/providers/pcep/packet/src/main/java/org/onosproject/provider/pcep/packet/impl/PcepPacketProvider.java b/providers/pcep/packet/src/main/java/org/onosproject/provider/pcep/packet/impl/PcepPacketProvider.java
index 41cf375..5d4a042 100644
--- a/providers/pcep/packet/src/main/java/org/onosproject/provider/pcep/packet/impl/PcepPacketProvider.java
+++ b/providers/pcep/packet/src/main/java/org/onosproject/provider/pcep/packet/impl/PcepPacketProvider.java
@@ -12,9 +12,7 @@
 import org.onlab.packet.IPv4;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.TCP;
-import org.onosproject.net.AnnotationKeys;
 import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DeviceService;
@@ -96,22 +94,7 @@
 
             // Get lsrId of the PCEP client from the PCC ID. Session info is based on lsrID.
             String lsrId = String.valueOf(pccId.ipAddress());
-            DeviceId pccDeviceId = null;
-
-            // Find PCC deviceID from lsrId stored as annotations
-            Iterable<Device> devices = deviceService.getAvailableDevices();
-            for (Device dev : devices) {
-                if ("L3".equals(dev.annotations().value(AnnotationKeys.TYPE))
-                        && lsrId.equals(dev.annotations().value(LSRID))) {
-                    pccDeviceId = dev.id();
-                    break;
-                }
-            }
-
-            if (pccDeviceId == null) {
-                log.error("Device not found to perform label DB sync.");
-                return;
-            }
+            DeviceId pccDeviceId = DeviceId.deviceId(lsrId);
 
             InboundPacket inPkt = new DefaultInboundPacket(new ConnectPoint(pccDeviceId,
                                                                             PortNumber.portNumber(PCEP_PORT)),