Revert "VOL-4559: Delete the TP Instance and TP ID first once all the GEM"

This reverts commit 5467db8fa4fd1113cbdf93c11e7cf90284dd49f5.

Change-Id: I30b571a6ead40b86029a241132ec833df5ba7364
diff --git a/VERSION b/VERSION
index 6aba2b2..fae6e3d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.2.0
+4.2.1
diff --git a/internal/pkg/core/openolt_flowmgr.go b/internal/pkg/core/openolt_flowmgr.go
index c3036a5..50c1707 100644
--- a/internal/pkg/core/openolt_flowmgr.go
+++ b/internal/pkg/core/openolt_flowmgr.go
@@ -388,10 +388,9 @@
 }
 
 // CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
-// nolint: gocyclo
 func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
 
-	logger.Infow(ctx, "CreateSchedulerQueues",
+	logger.Debugw(ctx, "CreateSchedulerQueues",
 		log.Fields{"dir": sq.direction,
 			"intf-id":      sq.intfID,
 			"onu-id":       sq.onuID,
@@ -407,34 +406,12 @@
 		return err
 	}
 
-	var TrafficShaping *tp_pb.TrafficShapingInfo
-	if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
-		return olterrors.NewErrInvalidValue(log.Fields{
-			"reason":    "invalid-meter-config",
-			"meter-id":  sq.meterID,
-			"device-id": f.deviceHandler.device.Id}, nil)
-	}
-
-	if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
-		return olterrors.NewErrInvalidValue(log.Fields{
-			"reason":    "invalid-meter-config",
-			"meter-id":  sq.meterID,
-			"device-id": f.deviceHandler.device.Id}, nil)
-	}
-
-	var SchedCfg *tp_pb.SchedulerConfig
-	if sq.direction == tp_pb.Direction_UPSTREAM {
-		SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
-	} else if sq.direction == tp_pb.Direction_DOWNSTREAM {
-		SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
-	}
-	TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
-	TrafficSched[0].TechProfileId = sq.tpID
-
 	/* Lets make a simple assumption that if the meter-id is present on the KV store,
 	 * then the scheduler and queues configuration is applied on the OLT device
 	 * in the given direction.
 	 */
+
+	var SchedCfg *tp_pb.SchedulerConfig
 	meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
 	if err != nil {
 		return olterrors.NewErrNotFound("meter",
@@ -444,42 +421,11 @@
 				"device-id": f.deviceHandler.device.Id}, err)
 	}
 
-	// update reference count and return if the meter was already installed before
+	// update referernce count and return if the meter was already installed before
 	if meterInfo != nil && meterInfo.MeterID == sq.meterID {
-		logger.Infow(ctx, "scheduler-already-created-for-direction",
+		logger.Debugw(ctx, "scheduler-already-created-for-direction",
 			log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
-		if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
-			return err
-		}
-
-		if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
-			// Alloc object was already created as part of flow setup on another uni of the onu for the same service.
-			// Just create gem ports and traffic queues on the current uni for the given service
-			logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
-				log.Fields{"intf-id": sq.intfID,
-					"onu-id":    sq.onuID,
-					"uni-id":    sq.uniID,
-					"tp-id":     sq.tpID,
-					"device-id": f.deviceHandler.device.Id})
-			// The upstream scheduler is already created. We only need to create the queues
-			// If there are multiple upstream flows on a given uni, then it is possible that
-			// we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
-			// TODO: Find better mechanism to not duplicate request.
-			if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
-				return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
-					log.Fields{"intf-id": sq.intfID,
-						"direction": sq.direction,
-						"device-id": f.deviceHandler.device.Id}, err)
-			}
-		} else {
-			logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
-				log.Fields{"intf-id": sq.intfID,
-					"onu-id":    sq.onuID,
-					"uni-id":    sq.uniID,
-					"tp-id":     sq.tpID,
-					"device-id": f.deviceHandler.device.Id})
-		}
-		return err
+		return f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true)
 	}
 
 	logger.Debugw(ctx, "meter-does-not-exist-creating-new",
@@ -488,6 +434,12 @@
 			"direction": direction,
 			"device-id": f.deviceHandler.device.Id})
 
+	if sq.direction == tp_pb.Direction_UPSTREAM {
+		SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
+	} else if sq.direction == tp_pb.Direction_DOWNSTREAM {
+		SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
+	}
+
 	found := false
 	meterInfo = &rsrcMgr.MeterInfo{}
 	if sq.flowMetadata != nil {
@@ -513,6 +465,17 @@
 			"device-id":     f.deviceHandler.device.Id}, nil)
 	}
 
+	var TrafficShaping *tp_pb.TrafficShapingInfo
+	if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
+		return olterrors.NewErrInvalidValue(log.Fields{
+			"reason":    "invalid-meter-config",
+			"meter-id":  sq.meterID,
+			"device-id": f.deviceHandler.device.Id}, nil)
+	}
+
+	TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
+	TrafficSched[0].TechProfileId = sq.tpID
+
 	if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
 		return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
 			log.Fields{"intf-id": sq.intfID,
@@ -536,32 +499,6 @@
 	return nil
 }
 
-func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
-	trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
-	if err != nil {
-		return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
-			log.Fields{"intf-id": sq.intfID,
-				"direction": sq.direction,
-				"device-id": f.deviceHandler.device.Id}, err)
-	}
-	logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
-		log.Fields{"direction": sq.direction,
-			"traffic-queues": trafficQueues,
-			"device-id":      f.deviceHandler.device.Id})
-	queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
-		UniId: sq.uniID, PortNo: sq.uniPort,
-		TrafficQueues: trafficQueues,
-		TechProfileId: TrafficSched[0].TechProfileId}
-	if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
-		if len(queues.TrafficQueues) > 1 {
-			logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
-			_, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
-		}
-		return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
-	}
-	return err
-}
-
 func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
 	trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
 
@@ -642,49 +579,13 @@
 	return nil
 }
 
-// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
-func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
-	var err error
-	logger.Infow(ctx, "removing-queue-in-olt",
-		log.Fields{
-			"direction": sq.direction,
-			"intf-id":   sq.intfID,
-			"onu-id":    sq.onuID,
-			"uni-id":    sq.uniID,
-			"uni-port":  sq.uniPort,
-			"device-id": f.deviceHandler.device.Id})
+// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
+func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
 
-	TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
-	if err != nil {
-		return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
-			log.Fields{
-				"intf-id":   sq.intfID,
-				"direction": sq.direction,
-				"device-id": f.deviceHandler.device.Id}, err)
-	}
-
-	if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
-		&tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
-			UniId: sq.uniID, PortNo: sq.uniPort,
-			TrafficQueues: TrafficQueues,
-			TechProfileId: sq.tpID}); err != nil {
-		return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
-			log.Fields{
-				"intf-id":        sq.intfID,
-				"traffic-queues": TrafficQueues,
-				"device-id":      f.deviceHandler.device.Id}, err)
-	}
-	logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
-
-	return err
-}
-
-// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
-func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
 	var Direction string
 	var SchedCfg *tp_pb.SchedulerConfig
 	var err error
-	logger.Infow(ctx, "removing-scheduler-in-olt",
+	logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
 		log.Fields{
 			"direction": sq.direction,
 			"intf-id":   sq.intfID,
@@ -705,46 +606,88 @@
 	TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
 	TrafficSched[0].TechProfileId = sq.tpID
 
-	if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
-		IntfId: sq.intfID, OnuId: sq.onuID,
-		UniId: sq.uniID, PortNo: sq.uniPort,
-		TrafficScheds: TrafficSched}); err != nil {
-		return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
+	TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
+	if err != nil {
+		return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
 			log.Fields{
-				"intf-id":            sq.intfID,
-				"traffic-schedulers": TrafficSched,
-				"onu-id":             sq.onuID,
-				"uni-id":             sq.uniID,
-				"uni-port":           sq.uniPort}, err)
+				"intf-id":   sq.intfID,
+				"direction": sq.direction,
+				"device-id": f.deviceHandler.device.Id}, err)
 	}
 
-	logger.Infow(ctx, "removed-traffic-schedulers-successfully",
-		log.Fields{"device-id": f.deviceHandler.device.Id,
-			"intf-id":  sq.intfID,
-			"onu-id":   sq.onuID,
-			"uni-id":   sq.uniID,
-			"uni-port": sq.uniPort})
+	if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
+		&tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
+			UniId: sq.uniID, PortNo: sq.uniPort,
+			TrafficQueues: TrafficQueues,
+			TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
+		return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
+			log.Fields{
+				"intf-id":        sq.intfID,
+				"traffic-queues": TrafficQueues,
+				"device-id":      f.deviceHandler.device.Id}, err)
+	}
+	logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
 
-	if sq.direction == tp_pb.Direction_UPSTREAM {
-		allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
-		// Delete the TCONT on the ONU.
-		uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
-		tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
-		if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
-			logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
+	if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
+		if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
+			IntfId: sq.intfID, OnuId: sq.onuID,
+			UniId: sq.uniID, PortNo: sq.uniPort,
+			TrafficScheds: TrafficSched}); err != nil {
+			return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
 				log.Fields{
-					"intf":      sq.intfID,
-					"onu-id":    sq.onuID,
-					"uni-id":    sq.uniID,
-					"device-id": f.deviceHandler.device.Id,
-					"alloc-id":  allocID})
+					"intf-id":            sq.intfID,
+					"traffic-schedulers": TrafficSched,
+					"onu-id":             sq.onuID,
+					"uni-id":             sq.uniID,
+					"uni-port":           sq.uniPort}, err)
+		}
+
+		logger.Infow(ctx, "removed-traffic-schedulers-successfully",
+			log.Fields{"device-id": f.deviceHandler.device.Id,
+				"intf-id":  sq.intfID,
+				"onu-id":   sq.onuID,
+				"uni-id":   sq.uniID,
+				"uni-port": sq.uniPort})
+
+		if sq.direction == tp_pb.Direction_UPSTREAM {
+			allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
+			// Delete the TCONT on the ONU.
+			uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
+			tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
+			if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
+				logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
+					log.Fields{
+						"intf":      sq.intfID,
+						"onu-id":    sq.onuID,
+						"uni-id":    sq.uniID,
+						"device-id": f.deviceHandler.device.Id,
+						"alloc-id":  allocID})
+			}
 		}
 	}
 
 	/* After we successfully remove the scheduler configuration on the OLT device,
 	 * delete the meter id on the KV store.
 	 */
-	err = f.removeMeterReference(ctx, Direction, sq)
+	err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
+	if err != nil {
+		return olterrors.NewErrAdapter("unable-to-remove-meter",
+			log.Fields{
+				"onu":       sq.onuID,
+				"device-id": f.deviceHandler.device.Id,
+				"intf-id":   sq.intfID,
+				"onu-id":    sq.onuID,
+				"uni-id":    sq.uniID,
+				"uni-port":  sq.uniPort}, err)
+	}
+	logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
+		log.Fields{
+			"dir":       Direction,
+			"device-id": f.deviceHandler.device.Id,
+			"intf-id":   sq.intfID,
+			"onu-id":    sq.onuID,
+			"uni-id":    sq.uniID,
+			"uni-port":  sq.uniPort})
 	return err
 }
 
@@ -2023,97 +1966,70 @@
 	}
 
 	logger.Debugw(ctx, "all-gem-ports-are-free-to-be-deleted", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
-
-	// Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
 	switch techprofileInst := techprofileInst.(type) {
 	case *tp_pb.TechProfileInstance:
-		if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
-			logger.Warn(ctx, err)
-		}
-		if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
-			logger.Warn(ctx, err)
-		}
-
-		for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
-			gemPortID := gemPort.GemportId
-			f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), gemPortID)
-			_ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
-
-			if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err == nil {
-				//everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
-				// by calling DeleteFlowIDsForGem
-				f.gemToFlowIDsKey.Lock()
-				delete(f.gemToFlowIDs, gemPortID)
-				f.gemToFlowIDsKey.Unlock()
-			} else {
-				logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
-					log.Fields{
-						"err":        err,
-						"intf":       intfID,
-						"onu-id":     onuID,
-						"uni-id":     uniID,
-						"device-id":  f.deviceHandler.device.Id,
-						"gemport-id": gemPortID})
+		schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
+		allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
+		if !allocExists {
+			if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
+				logger.Warn(ctx, err)
+			}
+			if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
+				logger.Warn(ctx, err)
 			}
 
-			f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID)
+			if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
+				if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
+					logger.Warn(ctx, err)
+				}
+			}
+			f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId)
 
-			// Delete the gem port on the ONU.
-			if sendDeleteGemRequest {
-				if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID, tpPath); err != nil {
-					logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
+			schedQueue.direction = tp_pb.Direction_DOWNSTREAM
+			if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
+				if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
+					logger.Warn(ctx, err)
+				}
+			}
+
+			for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
+				gemPortID := gemPort.GemportId
+				f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), gemPortID)
+				_ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
+
+				if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err == nil {
+					//everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
+					// by calling DeleteFlowIDsForGem
+					f.gemToFlowIDsKey.Lock()
+					delete(f.gemToFlowIDs, gemPortID)
+					f.gemToFlowIDsKey.Unlock()
+				} else {
+					logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
 						log.Fields{
 							"err":        err,
-							"intfID":     intfID,
+							"intf":       intfID,
 							"onu-id":     onuID,
 							"uni-id":     uniID,
 							"device-id":  f.deviceHandler.device.Id,
 							"gemport-id": gemPortID})
 				}
-			}
-		}
-		// Remove queues at OLT in upstream and downstream direction
-		schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
-		if err := f.RemoveQueues(ctx, schedQueue); err != nil {
-			logger.Warn(ctx, err)
-		}
-		schedQueue.direction = tp_pb.Direction_DOWNSTREAM
-		if err := f.RemoveQueues(ctx, schedQueue); err != nil {
-			logger.Warn(ctx, err)
-		}
-	}
 
-	switch techprofileInst := techprofileInst.(type) {
-	case *tp_pb.TechProfileInstance:
-		// Proceed to free allocid and cleanup schedulers (US/DS) if no other references are found for this TP across all the UNIs on the ONU
-		schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
-		allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
-		if !allocExists {
-			// all alloc object references removed, remove upstream scheduler
-			if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
-				if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
-					logger.Warn(ctx, err)
+				f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID)
+
+				// Delete the gem port on the ONU.
+				if sendDeleteGemRequest {
+					if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID, tpPath); err != nil {
+						logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
+							log.Fields{
+								"err":        err,
+								"intfID":     intfID,
+								"onu-id":     onuID,
+								"uni-id":     uniID,
+								"device-id":  f.deviceHandler.device.Id,
+								"gemport-id": gemPortID})
+					}
 				}
 			}
-			// remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
-			f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
-		} else {
-			// just remove meter reference for the upstream direction for the current pon/onu/uni
-			// The upstream scheduler, alloc id and meter-reference for the last remaining pon/onu/uni will be removed when no other alloc references that TP
-			if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
-				return err
-			}
-			// setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
-			// but still preserve it on the resource pool.
-			f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
-		}
-
-		// Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
-		schedQueue.direction = tp_pb.Direction_DOWNSTREAM
-		if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
-			if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
-				logger.Warn(ctx, err)
-			}
 		}
 	case *tp_pb.EponTechProfileInstance:
 		if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
@@ -2122,7 +2038,7 @@
 		if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
 			logger.Warn(ctx, err)
 		}
-		f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
+		f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
 		// Delete the TCONT on the ONU.
 		if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
 			logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
@@ -3139,11 +3055,12 @@
 	tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
 	if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
 		tpInstances := f.techprofile.FindAllTpInstances(ctx, f.deviceHandler.device.Id, sq.tpID, sq.intfID, sq.onuID).([]tp_pb.TechProfileInstance)
+		logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
 		for i := 0; i < len(tpInstances); i++ {
 			tpI := tpInstances[i]
 			if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
 				tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
-				logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
+				logger.Debugw(ctx, "alloc-is-in-use",
 					log.Fields{
 						"device-id": f.deviceHandler.device.Id,
 						"intfID":    sq.intfID,
@@ -3583,7 +3500,7 @@
 		for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
 			f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
 		}
-		f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
+		f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId)
 	}
 }
 
@@ -3629,29 +3546,3 @@
 	}
 	return nil
 }
-
-func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
-	/* After we successfully remove the scheduler configuration on the OLT device,
-	 * delete the meter id on the KV store.
-	 */
-	err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
-	if err != nil {
-		return olterrors.NewErrAdapter("unable-to-remove-meter",
-			log.Fields{
-				"onu":       sq.onuID,
-				"device-id": f.deviceHandler.device.Id,
-				"intf-id":   sq.intfID,
-				"onu-id":    sq.onuID,
-				"uni-id":    sq.uniID,
-				"uni-port":  sq.uniPort}, err)
-	}
-	logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
-		log.Fields{
-			"dir":       direction,
-			"device-id": f.deviceHandler.device.Id,
-			"intf-id":   sq.intfID,
-			"onu-id":    sq.onuID,
-			"uni-id":    sq.uniID,
-			"uni-port":  sq.uniPort})
-	return err
-}
diff --git a/internal/pkg/core/openolt_flowmgr_test.go b/internal/pkg/core/openolt_flowmgr_test.go
index 5f64a71..af7b147 100644
--- a/internal/pkg/core/openolt_flowmgr_test.go
+++ b/internal/pkg/core/openolt_flowmgr_test.go
@@ -98,16 +98,17 @@
 		{"CreateSchedulerQueues-19", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 1, createFlowMetadata(tprofile, 5, Upstream)}, false},
 		{"CreateSchedulerQueues-20", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 1, createFlowMetadata(tprofile2, 5, Downstream)}, false},
 
-		//Negative testcases
-		{"CreateSchedulerQueues-1", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 1, createFlowMetadata(tprofile, 0, Upstream)}, true},
-		{"CreateSchedulerQueues-2", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 1, createFlowMetadata(tprofile2, 0, Downstream)}, true},
+		{"CreateSchedulerQueues-1", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 1, createFlowMetadata(tprofile, 0, Upstream)}, false},
+		{"CreateSchedulerQueues-2", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 1, createFlowMetadata(tprofile2, 0, Downstream)}, false},
 		{"CreateSchedulerQueues-3", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 2, createFlowMetadata(tprofile, 2, Upstream)}, true},
 		{"CreateSchedulerQueues-4", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 2, createFlowMetadata(tprofile2, 2, Downstream)}, true},
 		{"CreateSchedulerQueues-5", schedQueue{tp_pb.Direction_UPSTREAM, 1, 2, 2, 64, 2, tprofile, 2, createFlowMetadata(tprofile, 3, Upstream)}, true},
 		{"CreateSchedulerQueues-6", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 2, 2, 65, 2, tprofile2, 2, createFlowMetadata(tprofile2, 3, Downstream)}, true},
-		{"CreateSchedulerQueues-7", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 1, &ofp.FlowMetadata{}}, true},
+
+		//Negative testcases
+		{"CreateSchedulerQueues-7", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 1, &ofp.FlowMetadata{}}, false},
 		{"CreateSchedulerQueues-8", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 0, &ofp.FlowMetadata{}}, true},
-		{"CreateSchedulerQueues-9", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 1, &ofp.FlowMetadata{}}, true},
+		{"CreateSchedulerQueues-9", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 1, &ofp.FlowMetadata{}}, false},
 		{"CreateSchedulerQueues-10", schedQueue{tp_pb.Direction_UPSTREAM, 0, 1, 1, 64, 1, tprofile, 2, &ofp.FlowMetadata{}}, true},
 		{"CreateSchedulerQueues-11", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 2, &ofp.FlowMetadata{}}, true},
 		{"CreateSchedulerQueues-12", schedQueue{tp_pb.Direction_DOWNSTREAM, 0, 1, 1, 65, 1, tprofile2, 2, nil}, true},
@@ -167,7 +168,7 @@
 		Meters: []*ofp.OfpMeterConfig{ofpMeterConfig}}
 }
 
-func TestOpenOltFlowMgr_RemoveScheduler(t *testing.T) {
+func TestOpenOltFlowMgr_RemoveSchedulerQueues(t *testing.T) {
 	tprofile := &tp_pb.TechProfileInstance{Name: "tp1", SubscriberIdentifier: "subscriber1",
 		ProfileType: "pt1", NumGemPorts: 1, Version: 1,
 		InstanceControl: &tp_pb.InstanceControl{Onu: "1", Uni: "1", MaxGemPayloadSize: "1"},
@@ -188,82 +189,19 @@
 		schedQueue schedQueue
 		wantErr    bool
 	}{
-		{"RemoveScheduler-1", schedQueue{tp_pb.Direction_UPSTREAM, 1, 1, 1, 64, 1, tprofile, 0, nil}, false},
-		{"RemoveScheduler-2", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
-		{"RemoveScheduler-3", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
-		{"RemoveScheduler-4", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
+		// TODO: Add test cases.
+		{"RemoveSchedulerQueues", schedQueue{tp_pb.Direction_UPSTREAM, 1, 1, 1, 64, 1, tprofile, 0, nil}, false},
+		{"RemoveSchedulerQueues", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
+		// negative test cases
+		{"RemoveSchedulerQueues", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
+		{"RemoveSchedulerQueues", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
 	}
 	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 	defer cancel()
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if err := flowMgr[tt.schedQueue.intfID].RemoveScheduler(ctx, tt.schedQueue); (err != nil) != tt.wantErr {
-				t.Errorf("OpenOltFlowMgr.RemoveScheduler() error = %v, wantErr %v", err, tt.wantErr)
-			}
-		})
-	}
-
-}
-
-func TestOpenOltFlowMgr_RemoveQueues(t *testing.T) {
-	tprofile := &tp_pb.TechProfileInstance{Name: "tp1", SubscriberIdentifier: "subscriber1",
-		ProfileType: "pt1", NumGemPorts: 1, Version: 1,
-		InstanceControl: &tp_pb.InstanceControl{Onu: "single-instance", Uni: "single-instance", MaxGemPayloadSize: "1"},
-	}
-	tprofile.UsScheduler = &tp_pb.SchedulerAttributes{}
-	tprofile.UsScheduler.Direction = tp_pb.Direction_UPSTREAM
-	tprofile.UsScheduler.AdditionalBw = tp_pb.AdditionalBW_AdditionalBW_None
-	tprofile.UsScheduler.QSchedPolicy = tp_pb.SchedulingPolicy_WRR
-	tprofile.DsScheduler = &tp_pb.SchedulerAttributes{}
-	tprofile.DsScheduler.Direction = tp_pb.Direction_DOWNSTREAM
-	tprofile.DsScheduler.AdditionalBw = tp_pb.AdditionalBW_AdditionalBW_BestEffort
-	tprofile.DsScheduler.QSchedPolicy = tp_pb.SchedulingPolicy_StrictPriority
-	tprofile.UpstreamGemPortAttributeList = make([]*tp_pb.GemPortAttributes, 0)
-	tprofile.UpstreamGemPortAttributeList = append(tprofile.UpstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 1, PbitMap: "0b00000011"})
-	tprofile.UpstreamGemPortAttributeList = append(tprofile.UpstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 2, PbitMap: "0b00001100"})
-	tprofile.UpstreamGemPortAttributeList = append(tprofile.UpstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 3, PbitMap: "0b00110000"})
-	tprofile.UpstreamGemPortAttributeList = append(tprofile.UpstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 4, PbitMap: "0b11000000"})
-
-	tprofile.DownstreamGemPortAttributeList = make([]*tp_pb.GemPortAttributes, 0)
-	tprofile.DownstreamGemPortAttributeList = append(tprofile.DownstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 1, PbitMap: "0b00000011"})
-	tprofile.DownstreamGemPortAttributeList = append(tprofile.DownstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 2, PbitMap: "0b00001100"})
-	tprofile.DownstreamGemPortAttributeList = append(tprofile.DownstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 3, PbitMap: "0b00110000"})
-	tprofile.DownstreamGemPortAttributeList = append(tprofile.DownstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 4, PbitMap: "0b11000000"})
-
-	tprofile2 := &tp_pb.TechProfileInstance{Name: "tp2", SubscriberIdentifier: "subscriber2",
-		ProfileType: "pt1", NumGemPorts: 1, Version: 1,
-		InstanceControl: &tp_pb.InstanceControl{Onu: "multi-instance", Uni: "single-instance", MaxGemPayloadSize: "1"},
-	}
-	tprofile2.UsScheduler = &tp_pb.SchedulerAttributes{}
-	tprofile2.UsScheduler.Direction = tp_pb.Direction_UPSTREAM
-	tprofile2.UsScheduler.AdditionalBw = tp_pb.AdditionalBW_AdditionalBW_None
-	tprofile2.UsScheduler.QSchedPolicy = tp_pb.SchedulingPolicy_WRR
-	tprofile2.DsScheduler = &tp_pb.SchedulerAttributes{}
-	tprofile2.DsScheduler.Direction = tp_pb.Direction_DOWNSTREAM
-	tprofile2.DsScheduler.AdditionalBw = tp_pb.AdditionalBW_AdditionalBW_BestEffort
-	tprofile2.DsScheduler.QSchedPolicy = tp_pb.SchedulingPolicy_StrictPriority
-	tprofile2.UpstreamGemPortAttributeList = make([]*tp_pb.GemPortAttributes, 0)
-	tprofile2.UpstreamGemPortAttributeList = append(tprofile.UpstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 1, PbitMap: "0b11111111"})
-	tprofile2.DownstreamGemPortAttributeList = make([]*tp_pb.GemPortAttributes, 0)
-	tprofile2.DownstreamGemPortAttributeList = append(tprofile.DownstreamGemPortAttributeList, &tp_pb.GemPortAttributes{GemportId: 1, PbitMap: "0b11111111"})
-
-	//defTprofile := &tp.DefaultTechProfile{}
-	tests := []struct {
-		name       string
-		schedQueue schedQueue
-		wantErr    bool
-	}{
-		{"RemoveQueues-1", schedQueue{tp_pb.Direction_UPSTREAM, 1, 1, 1, 64, 1, tprofile, 0, nil}, false},
-		{"RemoveQueues-2", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
-		{"RemoveQueues-3", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
-		{"RemoveQueues-4", schedQueue{tp_pb.Direction_DOWNSTREAM, 1, 1, 1, 65, 1, tprofile2, 0, nil}, false},
-	}
-	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-	defer cancel()
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if err := flowMgr[tt.schedQueue.intfID].RemoveQueues(ctx, tt.schedQueue); (err != nil) != tt.wantErr {
-				t.Errorf("OpenOltFlowMgr.RemoveQueues() error = %v, wantErr %v", err, tt.wantErr)
+			if err := flowMgr[tt.schedQueue.intfID].RemoveSchedulerQueues(ctx, tt.schedQueue); (err != nil) != tt.wantErr {
+				t.Errorf("OpenOltFlowMgr.RemoveSchedulerQueues() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
 	}
diff --git a/internal/pkg/resourcemanager/resourcemanager.go b/internal/pkg/resourcemanager/resourcemanager.go
index 05a5076..e9809f2 100755
--- a/internal/pkg/resourcemanager/resourcemanager.go
+++ b/internal/pkg/resourcemanager/resourcemanager.go
@@ -508,22 +508,18 @@
 // for the given OLT device.
 // The caller should ensure that this is a blocking call and this operation is serialized for
 // the ONU so as not cause resource corruption since there are no mutexes used here.
-// Setting freeFromResourcePool to false will not clear it from the resource pool but only
-// clear it for the given pon/onu/uni
 func (rsrcMgr *OpenOltResourceMgr) FreeAllocID(ctx context.Context, intfID uint32, onuID uint32,
-	uniID uint32, allocID uint32, freeFromResourcePool bool) {
+	uniID uint32, allocID uint32) {
 
 	rsrcMgr.RemoveAllocIDForOnu(ctx, intfID, onuID, uniID, allocID)
-	if freeFromResourcePool {
-		allocIDs := make([]uint32, 0)
-		allocIDs = append(allocIDs, allocID)
-		if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, intfID, ponrmgr.ALLOC_ID, allocIDs); err != nil {
-			logger.Errorw(ctx, "error-while-freeing-alloc-id", log.Fields{
-				"intf-id": intfID,
-				"onu-id":  onuID,
-				"err":     err.Error(),
-			})
-		}
+	allocIDs := make([]uint32, 0)
+	allocIDs = append(allocIDs, allocID)
+	if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, intfID, ponrmgr.ALLOC_ID, allocIDs); err != nil {
+		logger.Errorw(ctx, "error-while-freeing-alloc-id", log.Fields{
+			"intf-id": intfID,
+			"onu-id":  onuID,
+			"err":     err.Error(),
+		})
 	}
 }