VOL-1775 VOL-1779 VOL-1780 : Fix several issues with overall stability

- Apply changes as reported by golang race utility
- Added version attribute in KV object
- Added context object to db/model api
- Carrying timestamp info through context to help in the
  decision making when applying a revision change
- Replaced proxy access control mechanism with etcd reservation mechanism

Change-Id: If3d142a73b1da0d64fa6a819530f297dbfada2d3
diff --git a/db/model/non_persisted_revision.go b/db/model/non_persisted_revision.go
index 297a740..6900c5d 100644
--- a/db/model/non_persisted_revision.go
+++ b/db/model/non_persisted_revision.go
@@ -17,6 +17,7 @@
 
 import (
 	"bytes"
+	"context"
 	"crypto/md5"
 	"fmt"
 	"github.com/golang/protobuf/proto"
@@ -35,6 +36,16 @@
 	Cache sync.Map
 }
 
+func (s *revCacheSingleton) Get(path string) (interface{}, bool) {
+	return s.Cache.Load(path)
+}
+func (s *revCacheSingleton) Set(path string, value interface{}) {
+	s.Cache.Store(path, value)
+}
+func (s *revCacheSingleton) Delete(path string) {
+	s.Cache.Delete(path)
+}
+
 var revCacheInstance *revCacheSingleton
 var revCacheOnce sync.Once
 
@@ -269,10 +280,17 @@
 }
 
 // UpdateData will refresh the data content of the revision
-func (npr *NonPersistedRevision) UpdateData(data interface{}, branch *Branch) Revision {
+func (npr *NonPersistedRevision) UpdateData(ctx context.Context, data interface{}, branch *Branch) Revision {
 	npr.mutex.Lock()
 	defer npr.mutex.Unlock()
 
+	if ctx != nil {
+		if ctxTS, ok := ctx.Value(RequestTimestamp).(int64); ok && npr.lastUpdate.UnixNano() > ctxTS {
+			log.Warnw("data-is-older-than-current", log.Fields{"ctx-ts": ctxTS, "rev-ts": npr.lastUpdate.UnixNano()})
+			return npr
+		}
+	}
+
 	// Do not update the revision if data is the same
 	if npr.Config.Data != nil && npr.Config.hashData(npr.Root, data) == npr.Config.Hash {
 		log.Debugw("stored-data-matches-latest", log.Fields{"stored": npr.Config.Data, "provided": data})
@@ -300,7 +318,7 @@
 
 // UpdateChildren will refresh the list of children with the provided ones
 // It will carefully go through the list and ensure that no child is lost
-func (npr *NonPersistedRevision) UpdateChildren(name string, children []Revision, branch *Branch) Revision {
+func (npr *NonPersistedRevision) UpdateChildren(ctx context.Context, name string, children []Revision, branch *Branch) Revision {
 	npr.mutex.Lock()
 	defer npr.mutex.Unlock()
 
@@ -358,7 +376,7 @@
 					})
 
 					// replace entry
-					newChild.GetNode().Root = existingChildren[nameIndex].GetNode().Root
+					newChild.GetNode().SetRoot(existingChildren[nameIndex].GetNode().GetRoot())
 					updatedChildren = append(updatedChildren, newChild)
 				} else {
 					log.Debugw("keeping-existing-child", log.Fields{
@@ -461,7 +479,7 @@
 	return npr.lastUpdate
 }
 
-func (npr *NonPersistedRevision) LoadFromPersistence(path string, txid string, blobs map[string]*kvstore.KVPair) []Revision {
+func (npr *NonPersistedRevision) LoadFromPersistence(ctx context.Context, path string, txid string, blobs map[string]*kvstore.KVPair) []Revision {
 	// stub... required by interface
 	return nil
 }
@@ -473,3 +491,7 @@
 func (npr *NonPersistedRevision) StorageDrop(txid string, includeConfig bool) {
 	// stub ... required by interface
 }
+
+func (npr *NonPersistedRevision) getVersion() int64 {
+	return -1
+}