VOL-1459 : Fix failure to load device from persistence

- fixed watch logic which was not really updating memory
- force get depth to 0 to work around corrupted data structures

Change-Id: I595981e2ee3d816d17702e7f39c099193590fa6f
diff --git a/db/model/node.go b/db/model/node.go
index 7ea4417..7b05f8e 100644
--- a/db/model/node.go
+++ b/db/model/node.go
@@ -249,7 +249,7 @@
 
 // Get retrieves the data from a node tree that resides at the specified path
 func (n *node) List(path string, hash string, depth int, deep bool, txid string) interface{} {
-	log.Debugw("node-list-request", log.Fields{"path": path, "hash": hash, "depth":depth, "deep":deep, "txid":txid})
+	log.Debugw("node-list-request", log.Fields{"path": path, "hash": hash, "depth": depth, "deep": deep, "txid": txid})
 	if deep {
 		depth = -1
 	}
@@ -285,7 +285,7 @@
 
 // Get retrieves the data from a node tree that resides at the specified path
 func (n *node) Get(path string, hash string, depth int, deep bool, txid string) interface{} {
-	log.Debugw("node-get-request", log.Fields{"path": path, "hash": hash, "depth":depth, "deep":deep, "txid":txid})
+	log.Debugw("node-get-request", log.Fields{"path": path, "hash": hash, "depth": depth, "deep": deep, "txid": txid})
 	if deep {
 		depth = -1
 	}
@@ -309,14 +309,19 @@
 
 	var result interface{}
 	if result = n.getPath(rev.GetBranch().GetLatest(), path, depth);
-		reflect.ValueOf(result).IsValid() && reflect.ValueOf(result).IsNil() && n.Root.KvStore != nil {
+		(result == nil || reflect.ValueOf(result).IsValid() && reflect.ValueOf(result).IsNil()) && n.Root.KvStore != nil {
 		// We got nothing from memory, try to pull it from persistence
 		var prList []interface{}
 		if pr := rev.LoadFromPersistence(path, txid); pr != nil {
-			for _, revEntry := range pr {
-				prList = append(prList, revEntry.GetData())
+			// Did we receive a single or multiple revisions?
+			if len(pr) > 1 {
+				for _, revEntry := range pr {
+					prList = append(prList, revEntry.GetData())
+				}
+				result = prList
+			} else {
+				result = pr[0].GetData()
 			}
-			result = prList
 		}
 	}
 
@@ -404,7 +409,7 @@
 
 // Update changes the content of a node at the specified path with the provided data
 func (n *node) Update(path string, data interface{}, strict bool, txid string, makeBranch MakeBranchFunction) Revision {
-	log.Debugw("node-update-request", log.Fields{"path": path, "strict": strict, "txid":txid, "makeBranch": makeBranch})
+	log.Debugw("node-update-request", log.Fields{"path": path, "strict": strict, "txid": txid, "makeBranch": makeBranch})
 
 	for strings.HasPrefix(path, "/") {
 		path = path[1:]
@@ -435,7 +440,6 @@
 		path = partition[1]
 	}
 
-
 	field := ChildrenFields(n.Type)[name]
 	var children []Revision
 
@@ -559,7 +563,7 @@
 
 // Add inserts a new node at the specified path with the provided data
 func (n *node) Add(path string, data interface{}, txid string, makeBranch MakeBranchFunction) Revision {
-	log.Debugw("node-add-request", log.Fields{"path": path, "txid":txid, "makeBranch": makeBranch})
+	log.Debugw("node-add-request", log.Fields{"path": path, "txid": txid, "makeBranch": makeBranch})
 
 	for strings.HasPrefix(path, "/") {
 		path = path[1:]
@@ -669,7 +673,7 @@
 
 // Remove eliminates a node at the specified path
 func (n *node) Remove(path string, txid string, makeBranch MakeBranchFunction) Revision {
-	log.Debugw("node-remove-request", log.Fields{"path": path, "txid":txid, "makeBranch": makeBranch})
+	log.Debugw("node-remove-request", log.Fields{"path": path, "txid": txid, "makeBranch": makeBranch})
 
 	for strings.HasPrefix(path, "/") {
 		path = path[1:]
diff --git a/db/model/persisted_revision.go b/db/model/persisted_revision.go
index ecef3ae..b21deeb 100644
--- a/db/model/persisted_revision.go
+++ b/db/model/persisted_revision.go
@@ -136,7 +136,9 @@
 					if err := proto.Unmarshal(dataPair.Value.([]byte), data.Interface().(proto.Message)); err != nil {
 						log.Errorw("update-in-memory--unmarshal-failed", log.Fields{"key": pr.GetHash(), "error": err})
 					} else {
-						pr.UpdateData(data.Interface(), pr.GetBranch())
+						// Traverse the node and update as necessary
+						rev := pr.GetBranch().GetLatest()
+						rev.GetBranch().Node.Update("", data.Interface(), false, "", nil)
 					}
 				}
 
@@ -190,32 +192,20 @@
 						"loading-from-persistence--failed-to-unmarshal",
 						log.Fields{"path": path, "txid": txid, "error": err},
 					)
-				} else {
+				} else if field.Key != "" {
+					var key reflect.Value
+					var keyValue interface{}
+					var keyStr string
+
 					if path == "" {
-						if field.Key != "" {
-							// e.g. /logical_devices/abcde --> path="" name=logical_devices key=abcde
-							if field.Key != "" {
-								_, key := GetAttributeValue(data.Interface(), field.Key, 0)
+						// e.g. /logical_devices --> path="" name=logical_devices key=""
+						_, key = GetAttributeValue(data.Interface(), field.Key, 0)
+						keyStr = key.String()
 
-								childRev := rev.GetBranch().Node.MakeNode(data.Interface(), txid).Latest(txid)
-								childRev.SetHash(name + "/" + key.String())
-
-								// Do not process a child that is already in memory
-								if _, childExists := existChildMap[childRev.GetHash()]; !childExists {
-									// Create watch for <component>/<key>
-									pr.SetupWatch(childRev.GetHash())
-
-									children = append(children, childRev)
-									rev = rev.UpdateChildren(name, children, rev.GetBranch())
-
-									rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
-								}
-								response = append(response, childRev)
-								continue
-							}
-						}
-					} else if field.Key != "" {
-						// e.g. /logical_devices/abcde/flows/vwxyz --> path=abcde/flows/vwxyz
+					} else {
+						// e.g.
+						// /logical_devices/abcde --> path="abcde" name=logical_devices
+						// /logical_devices/abcde/image_downloads --> path="abcde/image_downloads" name=logical_devices
 
 						partition := strings.SplitN(path, "/", 2)
 						key := partition[0]
@@ -224,24 +214,43 @@
 						} else {
 							path = partition[1]
 						}
-						keyValue := field.KeyFromStr(key)
+						keyValue = field.KeyFromStr(key)
+						keyStr = keyValue.(string)
 
-						idx, childRev := rev.GetBranch().Node.findRevByKey(children, field.Key, keyValue)
+						if idx, childRev := rev.GetBranch().Node.findRevByKey(children, field.Key, keyValue); childRev != nil {
+							// Key is memory, continue recursing path
+							newChildRev := childRev.LoadFromPersistence(path, txid)
 
-						newChildRev := childRev.LoadFromPersistence(path, txid)
+							children[idx] = newChildRev[0]
 
-						children[idx] = newChildRev[0]
+							rev := rev.UpdateChildren(name, rev.GetChildren(name), rev.GetBranch())
+							rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
 
-						rev := rev.UpdateChildren(name, rev.GetChildren(name), rev.GetBranch())
-						rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
-
-						response = append(response, newChildRev[0])
-						continue
+							response = append(response, newChildRev[0])
+							continue
+						}
 					}
+
+					childRev := rev.GetBranch().Node.MakeNode(data.Interface(), txid).Latest(txid)
+					childRev.SetHash(name + "/" + keyStr)
+
+					// Do not process a child that is already in memory
+					if _, childExists := existChildMap[childRev.GetHash()]; !childExists {
+						// Create watch for <component>/<key>
+						childRev.SetupWatch(childRev.GetHash())
+
+						children = append(children, childRev)
+						rev = rev.UpdateChildren(name, children, rev.GetBranch())
+
+						rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
+					}
+					response = append(response, childRev)
+					continue
 				}
 			}
 		}
 	}
+
 	return response
 }
 
diff --git a/db/model/proxy_access_control.go b/db/model/proxy_access_control.go
index a3a7cee..234bcd9 100644
--- a/db/model/proxy_access_control.go
+++ b/db/model/proxy_access_control.go
@@ -183,8 +183,7 @@
 
 	// FIXME: Forcing depth to 0 for now due to problems deep copying the data structure
 	// The data traversal through reflection currently corrupts the content
-
-	return pac.getProxy().GetRoot().Get(path, "", depth, deep, txid)
+	return pac.getProxy().GetRoot().Get(path, "", 0, deep, txid)
 }
 
 // Update changes the content of the data model at the specified location with the provided data