VOL-1387 : Fixed issue introduced with watch mechanism submission

- Added flag to determine when a revision is watched
- Added flag to determine when a revision is stored
- Refactored confusing method names for Set/GetChildren
- Fixed issue with deletion of devices due to previous submission

Change-Id: I68c46951f9d40d47e4e74854bba449c9fec4a427
diff --git a/db/model/merge.go b/db/model/merge.go
index e40f98b..b230076 100644
--- a/db/model/merge.go
+++ b/db/model/merge.go
@@ -102,9 +102,9 @@
 		configChanged = true
 	}
 
-	//newChildren := reflect.ValueOf(dstRev.GetChildren()).Interface().(map[string][]Revision)
+	//newChildren := reflect.ValueOf(dstRev.GetAllChildren()).Interface().(map[string][]Revision)
 	newChildren := make(map[string][]Revision)
-	for entryName, childrenEntry := range dstRev.GetChildren() {
+	for entryName, childrenEntry := range dstRev.GetAllChildren() {
 		//newRev.Children[entryName] = append(newRev.Children[entryName], childrenEntry...)
 		newChildren[entryName] = make([]Revision, len(childrenEntry))
 		copy(newChildren[entryName], childrenEntry)
@@ -113,9 +113,9 @@
 	childrenFields := ChildrenFields(forkRev.GetData())
 
 	for fieldName, field := range childrenFields {
-		forkList := forkRev.GetChildren()[fieldName]
-		srcList := srcRev.GetChildren()[fieldName]
-		dstList := dstRev.GetChildren()[fieldName]
+		forkList := forkRev.GetChildren(fieldName)
+		srcList := srcRev.GetChildren(fieldName)
+		dstList := dstRev.GetChildren(fieldName)
 
 		if revisionsAreEqual(dstList, srcList) {
 			for _, rev := range srcList {
diff --git a/db/model/node.go b/db/model/node.go
index b8daadd..55b0eb7 100644
--- a/db/model/node.go
+++ b/db/model/node.go
@@ -302,8 +302,8 @@
 	field := names[name]
 
 	if field != nil && field.IsContainer {
-		children := make([]Revision, len(rev.GetChildren()[name]))
-		copy(children, rev.GetChildren()[name])
+		children := make([]Revision, len(rev.GetChildren(name)))
+		copy(children, rev.GetChildren(name))
 
 		if field.Key != "" {
 			if path != "" {
@@ -341,7 +341,7 @@
 		}
 	}
 
-	childRev := rev.GetChildren()[name][0]
+	childRev := rev.GetChildren(name)[0]
 	childNode := childRev.GetNode()
 	return childNode.getPath(childRev, path, depth)
 }
@@ -409,8 +409,8 @@
 			}
 			keyValue := field.KeyFromStr(key)
 
-			children = make([]Revision, len(rev.GetChildren()[name]))
-			copy(children, rev.GetChildren()[name])
+			children = make([]Revision, len(rev.GetChildren(name)))
+			copy(children, rev.GetChildren(name))
 
 			idx, childRev := n.findRevByKey(children, field.Key, keyValue)
 			childNode := childRev.GetNode()
@@ -448,7 +448,7 @@
 			log.Errorf("cannot index into container with no keys")
 		}
 	} else {
-		childRev := rev.GetChildren()[name][0]
+		childRev := rev.GetChildren(name)[0]
 		childNode := childRev.GetNode()
 		newChildRev := childNode.Update(path, data, strict, txid, makeBranch)
 		updatedRev := rev.UpdateChildren(name, []Revision{newChildRev}, branch)
@@ -543,8 +543,8 @@
 					n.GetProxy().InvokeCallbacks(PRE_ADD, false, data)
 				}
 
-				children = make([]Revision, len(rev.GetChildren()[name]))
-				copy(children, rev.GetChildren()[name])
+				children = make([]Revision, len(rev.GetChildren(name)))
+				copy(children, rev.GetChildren(name))
 
 				_, key := GetAttributeValue(data, field.Key, 0)
 
@@ -582,8 +582,8 @@
 			}
 			keyValue := field.KeyFromStr(key)
 
-			children = make([]Revision, len(rev.GetChildren()[name]))
-			copy(children, rev.GetChildren()[name])
+			children = make([]Revision, len(rev.GetChildren(name)))
+			copy(children, rev.GetChildren(name))
 
 			idx, childRev := n.findRevByKey(children, field.Key, keyValue)
 
@@ -592,7 +592,7 @@
 
 			children[idx] = newChildRev
 
-			rev = rev.UpdateChildren(name, branch.GetLatest().GetChildren()[name], branch)
+			rev = rev.UpdateChildren(name, branch.GetLatest().GetChildren(name), branch)
 			rev.Drop(txid, false)
 			n.makeLatest(branch, rev.GetBranch().GetLatest(), nil)
 
@@ -649,14 +649,14 @@
 				path = partition[1]
 			}
 			keyValue := field.KeyFromStr(key)
-			children = make([]Revision, len(rev.GetChildren()[name]))
-			copy(children, rev.GetChildren()[name])
+			children = make([]Revision, len(rev.GetChildren(name)))
+			copy(children, rev.GetChildren(name))
 			if path != "" {
 				idx, childRev := n.findRevByKey(children, field.Key, keyValue)
 				childNode := childRev.GetNode()
 				newChildRev := childNode.Remove(path, txid, makeBranch)
 				children[idx] = newChildRev
-				rev := rev.UpdateChildren(name, children, branch)
+				rev.SetChildren(name, children)
 				branch.GetLatest().Drop(txid, false)
 				n.makeLatest(branch, rev, nil)
 				return rev
@@ -671,7 +671,7 @@
 			}
 			childRev.Drop(txid, true)
 			children = append(children[:idx], children[idx+1:]...)
-			rev := rev.UpdateChildren(name, children, branch)
+			rev.SetChildren(name, children)
 			branch.GetLatest().Drop(txid, false)
 			n.makeLatest(branch, rev, postAnnouncement)
 			return rev
@@ -812,8 +812,8 @@
 			}
 			keyValue := field.KeyFromStr(key)
 			var children []Revision
-			children = make([]Revision, len(rev.GetChildren()[name]))
-			copy(children, rev.GetChildren()[name])
+			children = make([]Revision, len(rev.GetChildren(name)))
+			copy(children, rev.GetChildren(name))
 			if _, childRev := n.findRevByKey(children, field.Key, keyValue); childRev != nil {
 				childNode := childRev.GetNode()
 				return childNode.createProxy(path, fullPath, n, exclusive)
@@ -822,7 +822,7 @@
 			log.Error("cannot index into container with no keys")
 		}
 	} else {
-		childRev := rev.GetChildren()[name][0]
+		childRev := rev.GetChildren(name)[0]
 		childNode := childRev.GetNode()
 		return childNode.createProxy(path, fullPath, n, exclusive)
 	}
diff --git a/db/model/non_persisted_revision.go b/db/model/non_persisted_revision.go
index 66e6f74..765bbaf 100644
--- a/db/model/non_persisted_revision.go
+++ b/db/model/non_persisted_revision.go
@@ -72,18 +72,35 @@
 	return npr.Config
 }
 
-func (npr *NonPersistedRevision) SetChildren(children map[string][]Revision) {
+func (npr *NonPersistedRevision) SetAllChildren(children map[string][]Revision) {
 	npr.mutex.Lock()
 	defer npr.mutex.Unlock()
 	npr.Children = children
 }
 
-func (npr *NonPersistedRevision) GetChildren() map[string][]Revision {
+func (npr *NonPersistedRevision) SetChildren(name string, children []Revision) {
+	npr.mutex.Lock()
+	defer npr.mutex.Unlock()
+	if _, exists := npr.Children[name]; exists {
+		npr.Children[name] = children
+	}
+}
+
+func (npr *NonPersistedRevision) GetAllChildren() map[string][]Revision {
 	npr.mutex.Lock()
 	defer npr.mutex.Unlock()
 	return npr.Children
 }
 
+func (npr *NonPersistedRevision) GetChildren(name string) []Revision {
+	npr.mutex.Lock()
+	defer npr.mutex.Unlock()
+	if _, exists := npr.Children[name]; exists {
+		return npr.Children[name]
+	}
+	return nil
+}
+
 func (npr *NonPersistedRevision) SetHash(hash string) {
 	npr.mutex.Lock()
 	defer npr.mutex.Unlock()
@@ -188,7 +205,7 @@
 		for fieldName, field := range ChildrenFields(latestRev.GetData()) {
 			childDataName, childDataHolder := GetAttributeValue(data, fieldName, 0)
 			if field.IsContainer {
-				for _, rev := range latestRev.GetChildren()[fieldName] {
+				for _, rev := range latestRev.GetChildren(fieldName) {
 					childData := rev.Get(depth - 1)
 					foundEntry := false
 					for i := 0; i < childDataHolder.Len(); i++ {
@@ -204,8 +221,8 @@
 					}
 				}
 			} else {
-				if revs := latestRev.GetChildren()[fieldName]; revs != nil && len(revs) > 0 {
-					rev := latestRev.GetChildren()[fieldName][0]
+				if revs := latestRev.GetChildren(fieldName); revs != nil && len(revs) > 0 {
+					rev := latestRev.GetChildren(fieldName)[0]
 					if rev != nil {
 						childData := rev.Get(depth - 1)
 						if reflect.TypeOf(childData) == reflect.TypeOf(childDataHolder.Interface()) {
diff --git a/db/model/persisted_revision.go b/db/model/persisted_revision.go
index dd24e7e..84b9569 100644
--- a/db/model/persisted_revision.go
+++ b/db/model/persisted_revision.go
@@ -33,9 +33,11 @@
 	Revision
 	Compress bool
 
-	events  chan *kvstore.Event `json:"-"`
-	kvStore *Backend            `json:"-"`
-	mutex   sync.RWMutex        `json:"-"`
+	events    chan *kvstore.Event `json:"-"`
+	kvStore   *Backend            `json:"-"`
+	mutex     sync.RWMutex        `json:"-"`
+	isStored  bool
+	isWatched bool
 }
 
 // NewPersistedRevision creates a new instance of a PersistentRevision structure
@@ -83,6 +85,7 @@
 		} else {
 			log.Debugw("storing-revision-config",
 				log.Fields{"hash": pr.GetHash(), "data": pr.GetConfig().Data})
+			pr.isStored = true
 		}
 	}
 }
@@ -95,6 +98,8 @@
 
 		pr.events = pr.kvStore.CreateWatch(key)
 
+		pr.isWatched = true
+
 		// Start watching
 		go pr.startWatching()
 	}
@@ -176,8 +181,8 @@
 						if field.Key != "" {
 							// e.g. /logical_devices/abcde --> path="" name=logical_devices key=abcde
 							if field.Key != "" {
-								children = make([]Revision, len(rev.GetChildren()[name]))
-								copy(children, rev.GetChildren()[name])
+								children = make([]Revision, len(rev.GetChildren(name)))
+								copy(children, rev.GetChildren(name))
 
 								_, key := GetAttributeValue(data.Interface(), field.Key, 0)
 
@@ -208,8 +213,8 @@
 						}
 						keyValue := field.KeyFromStr(key)
 
-						children = make([]Revision, len(rev.GetChildren()[name]))
-						copy(children, rev.GetChildren()[name])
+						children = make([]Revision, len(rev.GetChildren(name)))
+						copy(children, rev.GetChildren(name))
 
 						idx, childRev := rev.GetBranch().Node.findRevByKey(children, field.Key, keyValue)
 
@@ -217,7 +222,7 @@
 
 						children[idx] = newChildRev[0]
 
-						rev := rev.UpdateChildren(name, rev.GetChildren()[name], rev.GetBranch())
+						rev := rev.UpdateChildren(name, rev.GetChildren(name), rev.GetBranch())
 						rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
 
 						response = append(response, newChildRev[0])
@@ -284,18 +289,25 @@
 	pr.mutex.Lock()
 	defer pr.mutex.Unlock()
 	if pr.kvStore != nil && txid == "" {
-		if includeConfig {
-			if err := pr.kvStore.Delete(pr.GetConfig().Hash); err != nil {
-				log.Errorw("failed-to-remove-revision-config", log.Fields{"hash": pr.GetConfig().Hash, "error": err.Error()})
+		if pr.isStored {
+			if includeConfig {
+				if err := pr.kvStore.Delete(pr.GetConfig().Hash); err != nil {
+					log.Errorw("failed-to-remove-revision-config", log.Fields{"hash": pr.GetConfig().Hash, "error": err.Error()})
+				}
+			}
+
+			if err := pr.kvStore.Delete(pr.GetHash()); err != nil {
+				log.Errorw("failed-to-remove-revision", log.Fields{"hash": pr.GetHash(), "error": err.Error()})
+			} else {
+				pr.isStored = false
+			}
+
+			if pr.isWatched {
+				pr.kvStore.DeleteWatch(pr.GetHash(), pr.events)
+				pr.isWatched = false
 			}
 		}
 
-		if err := pr.kvStore.Delete(pr.GetHash()); err != nil {
-			log.Errorw("failed-to-remove-revision", log.Fields{"hash": pr.GetHash(), "error": err.Error()})
-		}
-
-		pr.kvStore.DeleteWatch(pr.GetConfig().Hash, pr.events)
-
 	} else {
 		if includeConfig {
 			log.Debugw("attempted-to-remove-transacted-revision-config", log.Fields{"hash": pr.GetConfig().Hash, "txid": txid})
diff --git a/db/model/proxy_load_test.go b/db/model/proxy_load_test.go
index b388d97..49443cd 100644
--- a/db/model/proxy_load_test.go
+++ b/db/model/proxy_load_test.go
@@ -227,7 +227,7 @@
 	//	tlog.Debugf("%sbranchIndex: %s", prefix, brIdx)
 	//	traverseBranches(brRev, depth+1)
 	//}
-	for childrenI, children := range revision.GetChildren() {
+	for childrenI, children := range revision.GetAllChildren() {
 		tlog.Debugf("%schildrenIndex: %s, length: %d", prefix, childrenI, len(children))
 
 		for _, subrev := range children {
diff --git a/db/model/revision.go b/db/model/revision.go
index 0a58ccd..51f7a1a 100644
--- a/db/model/revision.go
+++ b/db/model/revision.go
@@ -20,8 +20,10 @@
 	SetConfig(revision *DataRevision)
 	GetConfig() *DataRevision
 	Drop(txid string, includeConfig bool)
-	SetChildren(children map[string][]Revision)
-	GetChildren() map[string][]Revision
+	SetChildren(name string, children []Revision)
+	GetChildren(name string) []Revision
+	SetAllChildren(children map[string][]Revision)
+	GetAllChildren() map[string][]Revision
 	SetHash(hash string)
 	GetHash() string
 	ClearHash()