VOL-1904 openolt adapter reconcile. along with the local caches data is stored in kv store as well.
child device cache is not removed as it is used to get child devices,
it will anyway be rebuilt even after adapter restart.
One more cache (flowsUsedByGemPort) got reintroduced recently which will be fixed later.
Updated test files as well.

Change-Id: I43378ff682f29477b22d61a76b0a721e83422853
diff --git a/adaptercore/device_handler.go b/adaptercore/device_handler.go
index a97a37d..26b62b3 100644
--- a/adaptercore/device_handler.go
+++ b/adaptercore/device_handler.go
@@ -76,7 +76,6 @@
 	resourceMgr   *rsrcMgr.OpenOltResourceMgr
 	discOnus      map[string]bool
 	onus          map[string]*OnuDevice
-	nniIntfID     int
 	portStats     *OpenOltStatisticsMgr
 	metrics       *pmmetrics.PmMetrics
 	stopCollector chan bool
@@ -133,10 +132,6 @@
 	dh.discOnus = make(map[string]bool)
 	dh.lockDevice = sync.RWMutex{}
 	dh.onus = make(map[string]*OnuDevice)
-	// The nniIntfID is initialized to -1 (invalid) and set to right value
-	// when the first IntfOperInd with status as "up" is received for
-	// any one of the available NNI port on the OLT device.
-	dh.nniIntfID = -1
 	dh.stopCollector = make(chan bool, 2)
 	dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
 	//TODO initialize the support classes.
@@ -255,12 +250,6 @@
 	if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
 		log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
 	}
-
-	// Once we have successfully added the NNI port to the core, if the
-	// locally cached nniIntfID is set to invalid (-1), set it to the right value.
-	if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
-		dh.nniIntfID = int(intfID)
-	}
 }
 
 // readIndications to read the indications from the OLT device
@@ -293,7 +282,13 @@
 	for {
 		indication, err := indications.Recv()
 		if err == io.EOF {
-			break
+			log.Infow("EOF for  indications", log.Fields{"err": err})
+			indications, err = dh.Client.EnableIndication(context.Background(), new(oop.Empty))
+			if err != nil {
+				log.Errorw("Failed to read indications", log.Fields{"err": err})
+				return
+			}
+			continue
 		}
 		if err != nil {
 			log.Infow("Failed to read from indications", log.Fields{"err": err})
@@ -343,6 +338,7 @@
 		intfOperInd := indication.GetIntfOperInd()
 		if intfOperInd.GetType() == "nni" {
 			go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
+			dh.resourceMgr.AddNNIToKVStore(intfOperInd.GetIntfId())
 		} else if intfOperInd.GetType() == "pon" {
 			// TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
 			// Handle pon port update
@@ -1165,37 +1161,39 @@
 	return nil
 }
 
-func (dh *DeviceHandler) clearUNIData(onu *OnuDevice) error {
+func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
 	var uniID uint32
 	var err error
-	for port := range onu.uniPorts {
-		delete(onu.uniPorts, port)
-		uniID = UniIDFromPortNum(port)
+	for _, port := range onu.UniPorts {
+		uniID = UniIDFromPortNum(uint32(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.DeleteTechProfileInstances(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})
+		if err = dh.flowMgr.DeleteTechProfileInstances(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)
+		log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
+		flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
 		for _, flowID := range flowIDs {
-			dh.resourceMgr.FreeFlowID(onu.intfID, int32(onu.onuID), int32(uniID), flowID)
+			dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
 		}
-		dh.resourceMgr.FreePONResourcesForONU(onu.intfID, onu.onuID, uniID)
-		if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(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})
-		tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.intfID, onu.onuID, uniID)
+		tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
 		for _, tpID := range tpIDList {
-			if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.intfID, onu.onuID, uniID, tpID); err != nil {
-				log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
+			if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); 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, tpID); 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-upstream", log.Fields{"onu-id": onu.OnuID})
+			if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); 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})
+			log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
+		}
+		dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
+		if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(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.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
+			log.Debugw("Failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
 		}
 	}
 	return nil
@@ -1204,26 +1202,29 @@
 func (dh *DeviceHandler) clearNNIData() error {
 	nniUniID := -1
 	nniOnuID := -1
+
 	if dh.resourceMgr == nil {
 		return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
 	}
-	flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(dh.nniIntfID), uint32(nniOnuID), uint32(nniUniID))
-	log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
-	for _, flowID := range flowIDs {
-		dh.resourceMgr.FreeFlowID(uint32(dh.nniIntfID), -1, -1, uint32(flowID))
-	}
 	//Free the flow-ids for the NNI port
-	dh.resourceMgr.FreePONResourcesForONU(uint32(dh.nniIntfID), uint32(nniOnuID), uint32(nniUniID))
-	/* Free ONU IDs for each pon port
-	   intfIDToONUIds is a map of intf-id: [onu-ids]*/
-	intfIDToONUIds := make(map[uint32][]uint32)
-	for _, onu := range dh.onus {
-		intfIDToONUIds[onu.intfID] = append(intfIDToONUIds[onu.intfID], onu.onuID)
+	nni, err := dh.resourceMgr.GetNNIFromKVStore()
+	if err != nil {
+		log.Error("Failed to fetch nni from kv store")
+		return err
 	}
-	for intfID, onuIds := range intfIDToONUIds {
-		dh.resourceMgr.FreeonuID(intfID, onuIds)
+	log.Debugw("NNI are ", log.Fields{"nni": nni})
+	for _, nniIntfID := range nni {
+		flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
+		log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
+		for _, flowID := range flowIDs {
+			dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
+		}
 	}
-	return nil
+	if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
+		log.Error("Failed to clear nni from kv store")
+		return err
+	}
+	return err
 }
 
 // DeleteDevice deletes the device instance from openolt handler array.  Also clears allocated resource manager resources.  Also reboots the OLT hardware!
@@ -1241,16 +1242,32 @@
 	   other pon resources like alloc_id and gemport_id
 	*/
 	if dh.resourceMgr != nil {
-		for _, onu := range dh.onus {
-			if err := dh.clearUNIData(onu); err != nil {
-				log.Debugw("Failed to clear data for onu", log.Fields{"onu-device": onu})
+		noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
+		var ponPort uint32
+		for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
+			var onuGemData []rsrcMgr.OnuGemInfo
+			err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
+			if err != nil {
+				log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
+				return err
+			}
+			for _, onu := range onuGemData {
+				log.Debugw("onu data ", log.Fields{"onu": onu})
+				if err = dh.clearUNIData(&onu); err != nil {
+					log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
+				}
+			}
+			onuGemData = nil
+			err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
+			if err != nil {
+				log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
 			}
 		}
 		/* Clear the flows from KV store associated with NNI port.
 		   There are mostly trap rules from NNI port (like LLDP)
 		*/
 		if err := dh.clearNNIData(); err != nil {
-			log.Debugw("Failed to clear data for NNI port", log.Fields{"deviceID": dh.deviceID})
+			log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
 		}
 
 		/* Clear the resource pool for each PON port in the background */