VOL-1372 : Fixed core crash due to how revisions are updated

- UpdateChildren merges new and existing entries
- proxy access control singleton now uses sync.Map since the
  entry was intermittently losing its content
- Switch to AddWithID in the device_agent to ensure thread safety

Change-Id: Ifcb2374f48b612a487a00f4a952aeec21d1c4af1
diff --git a/db/model/proxy_access_control.go b/db/model/proxy_access_control.go
index f6169b6..990a61c 100644
--- a/db/model/proxy_access_control.go
+++ b/db/model/proxy_access_control.go
@@ -25,7 +25,8 @@
 
 type singletonProxyAccessControl struct {
 	sync.RWMutex
-	cache map[string]ProxyAccessControl
+	cache sync.Map
+	reservedCount int
 }
 
 var instanceProxyAccessControl *singletonProxyAccessControl
@@ -34,35 +35,37 @@
 // PAC provides access to the proxy access control singleton instance
 func PAC() *singletonProxyAccessControl {
 	onceProxyAccessControl.Do(func() {
-		instanceProxyAccessControl = &singletonProxyAccessControl{cache: make(map[string]ProxyAccessControl)}
+		instanceProxyAccessControl = &singletonProxyAccessControl{}
 	})
 	return instanceProxyAccessControl
 }
 
 // ReservePath will apply access control for a specific path within the model
-func (singleton *singletonProxyAccessControl) ReservePath(path string, proxy *Proxy, pathLock string) ProxyAccessControl {
+func (singleton *singletonProxyAccessControl) ReservePath(path string, proxy *Proxy, pathLock string) *proxyAccessControl {
 	singleton.Lock()
 	defer singleton.Unlock()
-	var pac ProxyAccessControl
-	var exists bool
-	if pac, exists = singleton.cache[path]; !exists {
-		pac = NewProxyAccessControl(proxy, pathLock)
-		singleton.cache[path] = pac
-	}
-
-	if exists {
-		log.Debugf("PAC exists for path: %s... re-using", path)
+	singleton.reservedCount++
+	if pac, exists := singleton.cache.Load(pathLock); !exists {
+		log.Debugf("Creating new PAC entry for path:%s pathLock:%s", path, pathLock)
+		newPac := NewProxyAccessControl(proxy, pathLock)
+		singleton.cache.Store(pathLock,newPac)
+		return newPac
 	} else {
-		log.Debugf("PAC does not exists for path: %s... creating", path)
+		log.Debugf("Re-using existing PAC entry for path:%s pathLock:%s", path, pathLock)
+		return pac.(*proxyAccessControl)
 	}
-	return pac
 }
 
 // ReleasePath will remove access control for a specific path within the model
 func (singleton *singletonProxyAccessControl) ReleasePath(pathLock string) {
 	singleton.Lock()
 	defer singleton.Unlock()
-	delete(singleton.cache, pathLock)
+
+	singleton.reservedCount--
+
+	if singleton.reservedCount == 0 {
+		singleton.cache.Delete(pathLock)
+	}
 }
 
 // ProxyAccessControl is the abstraction interface to the base proxyAccessControl structure
@@ -86,7 +89,7 @@
 }
 
 // NewProxyAccessControl creates a new instance of an access control structure
-func NewProxyAccessControl(proxy *Proxy, path string) ProxyAccessControl {
+func NewProxyAccessControl(proxy *Proxy, path string) *proxyAccessControl {
 	return &proxyAccessControl{
 		Proxy:    proxy,
 		Path:     path,
@@ -190,7 +193,7 @@
 	if control {
 		pac.lock()
 		defer pac.unlock()
-		log.Debugf("controlling add, stack = %s", string(debug.Stack()))
+		log.Debugf("controlling add %s, stack = %s", pac.Path, string(debug.Stack()))
 	}
 	result := pac.getProxy().GetRoot().Add(path, data, txid, nil)