VOL-2029: Fix for OLT delete device.
Don't call core to get child device as onu might not exist during delete of parent device.
This would cause delays in delete and leaks with not releasing uniport resources.
Add the uni port to device handler for OLT when the uniport resources are allocated while adding flows.
Clear the uni port resources allocated during delete of olt device.
Also ensure the resources for the PON port are deleted in the background since the olt device delete
needs to finish within transaction timeout (8 seconds by default) and this can be time consuming.

Make the call to add uniPort to the ONU device after trap-nni flows.
make sca fixes to comment exported function.
And also change the uniPorts from array to a map for the onu device.

Change-Id: I4889032eab9c72acd64b5f553d5507c4d3bb00da
diff --git a/adaptercore/device_handler.go b/adaptercore/device_handler.go
index 3ba0967..fb0d6d7 100644
--- a/adaptercore/device_handler.go
+++ b/adaptercore/device_handler.go
@@ -86,6 +86,7 @@
 	onuID         uint32
 	intfID        uint32
 	proxyDeviceID string
+	uniPorts      map[uint32]struct{}
 }
 
 //NewOnuDevice creates a new Onu Device
@@ -97,6 +98,7 @@
 	device.onuID = onuID
 	device.intfID = intfID
 	device.proxyDeviceID = proxyDevID
+	device.uniPorts = make(map[uint32]struct{})
 	return &device
 }
 
@@ -974,6 +976,20 @@
 	log.Debug("Sent packet-in to core successfully")
 }
 
+// AddUniPortToOnu adds the uni port to the onu device
+func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
+	onuKey := dh.formOnuKey(intfID, onuID)
+	dh.lockDevice.Lock()
+	defer dh.lockDevice.Unlock()
+	if onuDevice, ok := dh.onus[onuKey]; ok {
+		// add it to the uniPort map for the onu device
+		if _, ok = onuDevice.uniPorts[uniPort]; !ok {
+			onuDevice.uniPorts[uniPort] = struct{}{}
+			log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
+		}
+	}
+}
+
 //UpdateFlowsIncrementally updates the device flow
 func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
 	log.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
@@ -1069,35 +1085,35 @@
 	return nil
 }
 
-func (dh *DeviceHandler) clearUNIData(onu *OnuDevice, uniPorts []*voltha.Port) error {
+func (dh *DeviceHandler) clearUNIData(onu *OnuDevice) error {
 	var uniID uint32
 	var err error
-	for _, port := range uniPorts {
-		if port.Type == voltha.Port_ETHERNET_UNI {
-			uniID = UniIDFromPortNum(port.PortNo)
-			/* Delete tech-profile instance from the KV store */
-			if err = dh.flowMgr.DeleteTechProfileInstance(onu.intfID, onu.onuID, uniID, onu.serialNumber); err != nil {
-				log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
-			}
-			log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
-			flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.intfID, onu.onuID, uniID)
-			for _, flowID := range flowIDs {
-				dh.resourceMgr.FreeFlowID(onu.intfID, int32(onu.onuID), int32(uniID), flowID)
-			}
-			dh.resourceMgr.FreePONResourcesForONU(onu.intfID, onu.onuID, uniID)
-			if err = dh.resourceMgr.RemoveTechProfileIDForOnu(onu.intfID, onu.onuID, uniID); err != nil {
-				log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
-			}
-			log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
-			if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.intfID, onu.onuID, uniID); err != nil {
-				log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
-			}
-			log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
-			if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.intfID, onu.onuID, uniID); err != nil {
-				log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
-			}
-			log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
+	for port := range onu.uniPorts {
+		delete(onu.uniPorts, port)
+		uniID = UniIDFromPortNum(port)
+		log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
+		/* Delete tech-profile instance from the KV store */
+		if err = dh.flowMgr.DeleteTechProfileInstance(onu.intfID, onu.onuID, uniID, onu.serialNumber); err != nil {
+			log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
 		}
+		log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
+		flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.intfID, onu.onuID, uniID)
+		for _, flowID := range flowIDs {
+			dh.resourceMgr.FreeFlowID(onu.intfID, int32(onu.onuID), int32(uniID), flowID)
+		}
+		dh.resourceMgr.FreePONResourcesForONU(onu.intfID, onu.onuID, uniID)
+		if err = dh.resourceMgr.RemoveTechProfileIDForOnu(onu.intfID, onu.onuID, uniID); err != nil {
+			log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
+		}
+		log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
+		if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.intfID, onu.onuID, uniID); err != nil {
+			log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
+		}
+		log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
+		if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.intfID, onu.onuID, uniID); err != nil {
+			log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
+		}
+		log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
 	}
 	return nil
 }
@@ -1128,6 +1144,10 @@
 func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
 	log.Debug("Function entry delete device")
 	dh.lockDevice.Lock()
+	if dh.adminState == "deleted" {
+		dh.lockDevice.Unlock()
+		return nil
+	}
 	dh.adminState = "deleted"
 	dh.lockDevice.Unlock()
 	/* Clear the KV store data associated with the all the UNI ports
@@ -1135,14 +1155,7 @@
 	   other pon resources like alloc_id and gemport_id
 	*/
 	for _, onu := range dh.onus {
-		childDevice, err := dh.coreProxy.GetDevice(nil, dh.deviceID, onu.deviceID)
-		if err != nil {
-			log.Debug("Failed to get onu device")
-			continue
-		}
-		uniPorts := childDevice.Ports
-		log.Debugw("onu-uni-ports", log.Fields{"onu-ports": uniPorts})
-		if err := dh.clearUNIData(onu, uniPorts); err != nil {
+		if err := dh.clearUNIData(onu); err != nil {
 			log.Debugw("Failed to clear data for onu", log.Fields{"onu-device": onu})
 		}
 	}
@@ -1152,10 +1165,10 @@
 	if err := dh.clearNNIData(); err != nil {
 		log.Debugw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
 	}
-	/* Clear the resource pool for each PON port*/
-	if err := dh.resourceMgr.Delete(); err != nil {
-		log.Debug("Failed-to-remove-device-from-Resource-mananger-KV-store")
-	}
+
+	/* Clear the resource pool for each PON port in the background */
+	go dh.resourceMgr.Delete()
+
 	/*Delete ONU map for the device*/
 	for onu := range dh.onus {
 		delete(dh.onus, onu)
diff --git a/adaptercore/openolt_flowmgr.go b/adaptercore/openolt_flowmgr.go
index 7fb968f..50fae3c 100644
--- a/adaptercore/openolt_flowmgr.go
+++ b/adaptercore/openolt_flowmgr.go
@@ -1302,6 +1302,7 @@
 
 	log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
 	portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
+
 	if ethType, ok := classifierInfo[EthType]; ok {
 		if ethType.(uint32) == LldpEthType {
 			log.Info("Adding LLDP flow")
@@ -1320,6 +1321,9 @@
 			}
 		}
 	}
+
+	f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
+
 	/* Metadata 8 bytes:
 	    Most Significant 2 Bytes = Inner VLAN
 	    Next 2 Bytes = Tech Profile ID(TPID)