This commit cleans up the loading of a logical device in
memory.

Change-Id: Ib7e77aacedc6841f95afdf0ece90c18c19263337
diff --git a/rw_core/core/logical_device_agent.go b/rw_core/core/logical_device_agent.go
index 9d05757..511ca13 100644
--- a/rw_core/core/logical_device_agent.go
+++ b/rw_core/core/logical_device_agent.go
@@ -36,7 +36,7 @@
 
 type LogicalDeviceAgent struct {
 	logicalDeviceId   string
-	lastData          *voltha.LogicalDevice
+	//lastData          *voltha.LogicalDevice
 	rootDeviceId      string
 	deviceMgr         *DeviceManager
 	ldeviceMgr        *LogicalDeviceManager
@@ -135,6 +135,8 @@
 			log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
 			return err
 		}
+		// Update the root device Id
+		agent.rootDeviceId = ld.RootDeviceId
 	}
 	agent.lockLogicalDevice.Lock()
 	agent.flowProxy = agent.clusterDataProxy.Root.CreateProxy(
@@ -160,6 +162,14 @@
 	log.Info("stopping-logical_device-agent")
 	agent.lockLogicalDevice.Lock()
 	defer agent.lockLogicalDevice.Unlock()
+
+	// Unregister to teh callbacks
+	if agent.flowProxy != nil {
+		agent.flowProxy.UnregisterCallback(model.POST_UPDATE, agent.flowTableUpdated)
+	}
+	if agent.groupProxy != nil {
+		agent.groupProxy.UnregisterCallback(model.POST_UPDATE, agent.groupTableUpdated)
+	}
 	//Remove the logical device from the model
 	if removed := agent.clusterDataProxy.Remove("/logical_devices/"+agent.logicalDeviceId, ""); removed == nil {
 		log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
@@ -175,7 +185,7 @@
 	log.Debug("GetLogicalDevice")
 	agent.lockLogicalDevice.Lock()
 	defer agent.lockLogicalDevice.Unlock()
-	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
+	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
 	if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
 		return lDevice, nil
 	}
@@ -186,7 +196,7 @@
 	log.Debug("!!!!!ListLogicalDevicePorts")
 	agent.lockLogicalDevice.Lock()
 	defer agent.lockLogicalDevice.Unlock()
-	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
+	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
 	if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
 		lPorts := make([]*voltha.LogicalPort, 0)
 		for _, port := range lDevice.Ports {
@@ -202,7 +212,7 @@
 	log.Debug("listFlows")
 	agent.lockLogicalDevice.Lock()
 	defer agent.lockLogicalDevice.Unlock()
-	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
+	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
 	if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
 		return lDevice.Flows.Items
 	}
@@ -214,7 +224,7 @@
 	log.Debug("listFlowGroups")
 	agent.lockLogicalDevice.Lock()
 	defer agent.lockLogicalDevice.Unlock()
-	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
+	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
 	if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
 		return lDevice.FlowGroups.Items
 	}
@@ -243,7 +253,7 @@
 // functions that have already acquired the logical device lock to the model
 func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
 	log.Debug("getLogicalDeviceWithoutLock")
-	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
+	logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
 	if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
 		return lDevice, nil
 	}
diff --git a/rw_core/core/logical_device_manager.go b/rw_core/core/logical_device_manager.go
index b4dc7ea..1b2fb1e 100644
--- a/rw_core/core/logical_device_manager.go
+++ b/rw_core/core/logical_device_manager.go
@@ -86,11 +86,23 @@
 	}
 }
 
+// getLogicalDeviceAgent returns the logical device agent.  If the device is not in memory then the device will
+// be loaded from dB and a logical device agent created to managed it.
 func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(logicalDeviceId string) *LogicalDeviceAgent {
 	ldMgr.lockLogicalDeviceAgentsMap.Lock()
-	defer ldMgr.lockLogicalDeviceAgentsMap.Unlock()
 	if agent, ok := ldMgr.logicalDeviceAgents[logicalDeviceId]; ok {
+		ldMgr.lockLogicalDeviceAgentsMap.Unlock()
 		return agent
+	} else {
+		//	Try to load into memory - loading will also create the logical device agent
+		ldMgr.lockLogicalDeviceAgentsMap.Unlock()
+		if err := ldMgr.load(logicalDeviceId); err == nil {
+			ldMgr.lockLogicalDeviceAgentsMap.Lock()
+			defer ldMgr.lockLogicalDeviceAgentsMap.Unlock()
+			if agent, ok = ldMgr.logicalDeviceAgents[logicalDeviceId]; ok {
+				return agent
+			}
+		}
 	}
 	return nil
 }
@@ -101,7 +113,8 @@
 	delete(ldMgr.logicalDeviceAgents, logicalDeviceId)
 }
 
-// GetLogicalDevice provides a cloned most up to date logical device
+// GetLogicalDevice provides a cloned most up to date logical device.  If device is not in memory
+// it will be fetched from the dB
 func (ldMgr *LogicalDeviceManager) getLogicalDevice(id string) (*voltha.LogicalDevice, error) {
 	log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
 	if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
@@ -132,6 +145,7 @@
 	return result, nil
 }
 
+// List only logical devices that are in memory
 //func (ldMgr *LogicalDeviceManager) listLogicalDevices() (*voltha.LogicalDevices, error) {
 //	log.Debug("listLogicalDevices")
 //	result := &voltha.LogicalDevices{}
@@ -183,7 +197,7 @@
 		// Logical device not in memory - create a temp logical device Agent and let it load from memory
 		agent := newLogicalDeviceAgent(lDeviceId, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy)
 		if err := agent.start(nil, true); err != nil {
-			agent.stop(nil)
+			//agent.stop(nil)
 			return err
 		}
 		ldMgr.logicalDeviceAgents[agent.logicalDeviceId] = agent