VOL-1497 : Further improved data synchronization between cores

- Introduced locking when modifying branches
- Introduced locking when modifying rev children
- Rewrote persistence loading logic to avoid unecessary changes
- Access controlled CreateProxy to ensure a proxy is not created
  against an incomplete device entry
- Removed locking logic from etcd client
- Replaced revision merging logic with persistence loading

VOL-1544 : Cleanup revisions to improve overall performance

- Ensure that old revisions are discarded
- Ensure that children do not contain discarded revisions
- Disabled cache logic for now

Change-Id: I1b952c82aba379fce64a47a71b5309a6f28fb5ff
diff --git a/db/model/proxy.go b/db/model/proxy.go
index 86d426a..eb3cb71 100644
--- a/db/model/proxy.go
+++ b/db/model/proxy.go
@@ -147,6 +147,7 @@
 	PROXY_ADD
 	PROXY_UPDATE
 	PROXY_REMOVE
+	PROXY_CREATE
 )
 
 // parseForControlledPath verifies if a proxy path matches a pattern
@@ -243,6 +244,9 @@
 
 	p.Operation = PROXY_UPDATE
 	pac.SetProxy(p)
+	defer func(op ProxyOperation) {
+		pac.getProxy().Operation = op
+	}(PROXY_GET)
 
 	log.Debugw("proxy-operation--update", log.Fields{"operation":p.Operation})
 
@@ -275,6 +279,10 @@
 	defer PAC().ReleasePath(pathLock)
 
 	p.Operation = PROXY_ADD
+	defer func() {
+		p.Operation = PROXY_GET
+	}()
+
 	pac.SetProxy(p)
 
 	log.Debugw("proxy-operation--add", log.Fields{"operation":p.Operation})
@@ -307,6 +315,9 @@
 
 	p.Operation = PROXY_ADD
 	pac.SetProxy(p)
+	defer func() {
+		p.Operation = PROXY_GET
+	}()
 
 	log.Debugw("proxy-operation--add", log.Fields{"operation":p.Operation})
 
@@ -338,12 +349,50 @@
 
 	p.Operation = PROXY_REMOVE
 	pac.SetProxy(p)
+	defer func() {
+		p.Operation = PROXY_GET
+	}()
 
 	log.Debugw("proxy-operation--remove", log.Fields{"operation":p.Operation})
 
 	return pac.Remove(fullPath, txid, controlled)
 }
 
+// CreateProxy to interact with specific path directly
+func (p *Proxy) CreateProxy(path string, exclusive bool) *Proxy {
+	if !strings.HasPrefix(path, "/") {
+		log.Errorf("invalid path: %s", path)
+		return nil
+	}
+
+	var fullPath string
+	var effectivePath string
+	if path == "/" {
+		fullPath = p.getPath()
+		effectivePath = p.getFullPath()
+	} else {
+		fullPath = p.getPath() + path
+		effectivePath = p.getFullPath() + path
+	}
+
+	pathLock, controlled := p.parseForControlledPath(effectivePath)
+
+	log.Debugf("Path: %s, Effective: %s, Full: %s, PathLock: %s", path, effectivePath, fullPath, pathLock)
+
+	pac := PAC().ReservePath(path, p, pathLock)
+	defer PAC().ReleasePath(pathLock)
+
+	p.Operation = PROXY_CREATE
+	pac.SetProxy(p)
+	defer func() {
+		p.Operation = PROXY_GET
+	}()
+
+	log.Debugw("proxy-operation--create-proxy", log.Fields{"operation":p.Operation})
+
+	return pac.CreateProxy(fullPath, exclusive, controlled)
+}
+
 // OpenTransaction creates a new transaction branch to isolate operations made to the data model
 func (p *Proxy) OpenTransaction() *Transaction {
 	txid := p.GetRoot().MakeTxBranch()