VOL-1687 : Fix wrong in-memory node assignments
- Fixed nil pointer with createProxy
- Changed watch loop to avoid re-starting when rev changes
Change-Id: Ie821788f2422d7a2083398c65b9632c65fae001d
diff --git a/db/model/node.go b/db/model/node.go
index 15ea04e..207df09 100644
--- a/db/model/node.go
+++ b/db/model/node.go
@@ -61,9 +61,10 @@
}
type node struct {
- mutex sync.RWMutex
- Root *root
- Type interface{}
+ mutex sync.RWMutex
+ Root *root
+ Type interface{}
+
Branches map[string]*Branch
Tags map[string]Revision
Proxy *Proxy
@@ -325,7 +326,11 @@
if entry, exists := GetRevCache().Cache.Load(path); exists && entry.(Revision) != nil {
entryAge := time.Now().Sub(entry.(Revision).GetLastUpdate()).Nanoseconds() / int64(time.Millisecond)
if entryAge < DATA_REFRESH_PERIOD {
- log.Debugw("using-cache-entry", log.Fields{"path": path, "hash": hash, "age": entryAge})
+ log.Debugw("using-cache-entry", log.Fields{
+ "path": path,
+ "hash": hash,
+ "age": entryAge,
+ })
return proto.Clone(entry.(Revision).GetData().(proto.Message))
} else {
log.Debugw("cache-entry-expired", log.Fields{"path": path, "hash": hash, "age": entryAge})
@@ -950,6 +955,13 @@
}
func (n *node) createProxy(path string, fullPath string, parentNode *node, exclusive bool) *Proxy {
+ log.Debugw("node-create-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "fullPath": fullPath,
+ })
+
for strings.HasPrefix(path, "/") {
path = path[1:]
}
@@ -960,48 +972,130 @@
rev := n.GetBranch(NONE).GetLatest()
partition := strings.SplitN(path, "/", 2)
name := partition[0]
+ var nodeType interface{}
+ // Node type is chosen depending on if we have reached the end of path or not
if len(partition) < 2 {
path = ""
+ nodeType = n.Type
} else {
path = partition[1]
+ nodeType = parentNode.Type
}
- field := ChildrenFields(n.Type)[name]
- if field.IsContainer {
- if path == "" {
- //log.Error("cannot proxy a container field")
- newNode := n.MakeNode(reflect.New(field.ClassType.Elem()).Interface(), "")
- return newNode.makeProxy(path, fullPath, parentNode, exclusive)
- } else if field.Key != "" {
- partition := strings.SplitN(path, "/", 2)
- key := partition[0]
- if len(partition) < 2 {
- path = ""
+ field := ChildrenFields(nodeType)[name]
+
+ if field != nil {
+ if field.IsContainer {
+ log.Debugw("container-field", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "name": name,
+ })
+ if path == "" {
+ log.Debugw("folder-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "fullPath": fullPath,
+ "name": name,
+ })
+ newNode := n.MakeNode(reflect.New(field.ClassType.Elem()).Interface(), "")
+ return newNode.makeProxy(path, fullPath, parentNode, exclusive)
+ } else if field.Key != "" {
+ log.Debugw("key-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "fullPath": fullPath,
+ "name": name,
+ })
+ partition := strings.SplitN(path, "/", 2)
+ key := partition[0]
+ if len(partition) < 2 {
+ path = ""
+ } else {
+ path = partition[1]
+ }
+ keyValue := field.KeyFromStr(key)
+ var children []Revision
+ children = make([]Revision, len(rev.GetChildren(name)))
+ copy(children, rev.GetChildren(name))
+
+ // Try to find a matching revision in memory
+ // If not found try the db
+ var childRev Revision
+ if _, childRev = n.findRevByKey(children, field.Key, keyValue); childRev != nil {
+ log.Debugw("found-revision-matching-key-in-memory", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "fullPath": fullPath,
+ "name": name,
+ })
+ } else if revs := n.GetBranch(NONE).GetLatest().LoadFromPersistence(fullPath, "", nil); revs != nil && len(revs) > 0 {
+ log.Debugw("found-revision-matching-key-in-db", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "fullPath": fullPath,
+ "name": name,
+ })
+ childRev = revs[0]
+ } else {
+ log.Debugw("no-revision-matching-key", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "fullPath": fullPath,
+ "name": name,
+ })
+ }
+ if childRev != nil {
+ childNode := childRev.GetNode()
+ return childNode.createProxy(path, fullPath, n, exclusive)
+ }
} else {
- path = partition[1]
- }
- keyValue := field.KeyFromStr(key)
- var children []Revision
- 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)
+ log.Errorw("cannot-access-index-of-empty-container", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "name": name,
+ })
}
} else {
- log.Error("cannot index into container with no keys")
+ log.Debugw("non-container-field", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "name": name,
+ })
+ childRev := rev.GetChildren(name)[0]
+ childNode := childRev.GetNode()
+ return childNode.createProxy(path, fullPath, n, exclusive)
}
} else {
- childRev := rev.GetChildren(name)[0]
- childNode := childRev.GetNode()
- return childNode.createProxy(path, fullPath, n, exclusive)
+ log.Debugw("field-object-is-nil", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "fullPath": fullPath,
+ "name": name,
+ })
}
- log.Warnf("Cannot create proxy - latest rev:%s, all revs:%+v", rev.GetHash(), n.GetBranch(NONE).Revisions)
+ log.Warnw("cannot-create-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "fullPath": fullPath,
+ "latest-rev": rev.GetHash(),
+ })
return nil
}
func (n *node) makeProxy(path string, fullPath string, parentNode *node, exclusive bool) *Proxy {
+ log.Debugw("node-make-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "fullPath": fullPath,
+ })
+
r := &root{
node: n,
Callbacks: n.Root.GetCallbacks(),
@@ -1013,8 +1107,20 @@
}
if n.Proxy == nil {
+ log.Debugw("constructing-new-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Type).Type(),
+ "parent-node-type": reflect.ValueOf(parentNode.Type).Type(),
+ "path": path,
+ "fullPath": fullPath,
+ })
n.Proxy = NewProxy(r, n, parentNode, path, fullPath, exclusive)
} else {
+ log.Debugw("node-has-existing-proxy", log.Fields{
+ "node-type": reflect.ValueOf(n.Proxy.Node.Type).Type(),
+ "parent-node-type": reflect.ValueOf(n.Proxy.ParentNode.Type).Type(),
+ "path": n.Proxy.Path,
+ "fullPath": n.Proxy.FullPath,
+ })
if n.Proxy.Exclusive {
log.Error("node is already owned exclusively")
}
diff --git a/db/model/non_persisted_revision.go b/db/model/non_persisted_revision.go
index 6075b3f..297a740 100644
--- a/db/model/non_persisted_revision.go
+++ b/db/model/non_persisted_revision.go
@@ -55,7 +55,6 @@
Branch *Branch
WeakRef string
Name string
- discarded bool
lastUpdate time.Time
}
@@ -66,14 +65,9 @@
r.Config = NewDataRevision(root, data)
r.Children = children
r.Hash = r.hashContent()
- r.discarded = false
return r
}
-func (npr *NonPersistedRevision) IsDiscarded() bool {
- return npr.discarded
-}
-
func (npr *NonPersistedRevision) SetConfig(config *DataRevision) {
npr.mutex.Lock()
defer npr.mutex.Unlock()
@@ -356,14 +350,33 @@
if nameExists {
// Check if the data has changed or not
if existingChildren[nameIndex].GetData().(proto.Message).String() != newChild.GetData().(proto.Message).String() {
+ log.Debugw("replacing-existing-child", log.Fields{
+ "old-hash": existingChildren[nameIndex].GetHash(),
+ "old-data": existingChildren[nameIndex].GetData(),
+ "new-hash": newChild.GetHash(),
+ "new-data": newChild.GetData(),
+ })
+
// replace entry
newChild.GetNode().Root = existingChildren[nameIndex].GetNode().Root
updatedChildren = append(updatedChildren, newChild)
} else {
+ log.Debugw("keeping-existing-child", log.Fields{
+ "old-hash": existingChildren[nameIndex].GetHash(),
+ "old-data": existingChildren[nameIndex].GetData(),
+ "new-hash": newChild.GetHash(),
+ "new-data": newChild.GetData(),
+ })
+
// keep existing entry
updatedChildren = append(updatedChildren, existingChildren[nameIndex])
}
} else {
+ log.Debugw("adding-unknown-child", log.Fields{
+ "hash": newChild.GetHash(),
+ "data": newChild.GetData(),
+ })
+
// new entry ... just add it
updatedChildren = append(updatedChildren, newChild)
}
@@ -413,7 +426,6 @@
// Drop is used to indicate when a revision is no longer required
func (npr *NonPersistedRevision) Drop(txid string, includeConfig bool) {
log.Debugw("dropping-revision", log.Fields{"hash": npr.GetHash(), "name": npr.GetName()})
- npr.discarded = true
}
// ChildDrop will remove a child entry matching the provided parameters from the current revision
@@ -458,6 +470,6 @@
// stub ... required by interface
}
-func (pr *NonPersistedRevision) StorageDrop(txid string, includeConfig bool) {
+func (npr *NonPersistedRevision) StorageDrop(txid string, includeConfig bool) {
// stub ... required by interface
}
diff --git a/db/model/persisted_revision.go b/db/model/persisted_revision.go
index 226fc3c..2ab91b7 100644
--- a/db/model/persisted_revision.go
+++ b/db/model/persisted_revision.go
@@ -127,34 +127,31 @@
StopWatchLoop:
for {
- if pr.IsDiscarded() {
- break StopWatchLoop
- }
+ latestRev := pr.GetBranch().GetLatest()
select {
case event, ok := <-pr.events:
if !ok {
- log.Errorw("event-channel-failure: stopping watch loop", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
+ log.Errorw("event-channel-failure: stopping watch loop", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName()})
break StopWatchLoop
}
-
- log.Debugw("received-event", log.Fields{"type": event.EventType, "watch": pr.GetName()})
+ log.Debugw("received-event", log.Fields{"type": event.EventType, "watch": latestRev.GetName()})
switch event.EventType {
case kvstore.DELETE:
- log.Debugw("delete-from-memory", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
+ log.Debugw("delete-from-memory", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName()})
pr.Revision.Drop("", true)
break StopWatchLoop
case kvstore.PUT:
- log.Debugw("update-in-memory", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
+ log.Debugw("update-in-memory", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName()})
- data := reflect.New(reflect.TypeOf(pr.GetData()).Elem())
+ data := reflect.New(reflect.TypeOf(latestRev.GetData()).Elem())
if err := proto.Unmarshal(event.Value.([]byte), data.Interface().(proto.Message)); err != nil {
- log.Errorw("failed-to-unmarshal-watch-data", log.Fields{"key": pr.GetHash(), "watch": pr.GetName(), "error": err})
+ log.Errorw("failed-to-unmarshal-watch-data", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName(), "error": err})
} else {
- log.Debugw("un-marshaled-watch-data", log.Fields{"key": pr.GetHash(), "watch": pr.GetName(), "data": data.Interface()})
+ log.Debugw("un-marshaled-watch-data", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName(), "data": data.Interface()})
var pathLock string
var pac *proxyAccessControl
@@ -171,24 +168,26 @@
Lease: 0,
}
- if pr.GetNode().GetProxy() != nil {
+ if latestRev.GetNode().GetProxy() != nil {
//
// If a proxy exists for this revision, use it to lock access to the path
// and prevent simultaneous updates to the object in memory
//
- pathLock, _ = pr.GetNode().GetProxy().parseForControlledPath(pr.GetNode().GetProxy().getFullPath())
+ pathLock, _ = latestRev.GetNode().GetProxy().parseForControlledPath(latestRev.GetNode().GetProxy().getFullPath())
//If the proxy already has a request in progress, then there is no need to process the watch
- log.Debugw("checking-if-path-is-locked", log.Fields{"key": pr.GetHash(), "pathLock": pathLock})
+ log.Debugw("checking-if-path-is-locked", log.Fields{"key": latestRev.GetHash(), "pathLock": pathLock})
if PAC().IsReserved(pathLock) {
log.Debugw("operation-in-progress", log.Fields{
- "key": pr.GetHash(),
- "path": pr.GetNode().GetProxy().getFullPath(),
- "operation": pr.GetNode().GetProxy().Operation.String(),
+ "key": latestRev.GetHash(),
+ "path": latestRev.GetNode().GetProxy().getFullPath(),
+ "operation": latestRev.GetNode().GetProxy().Operation.String(),
})
+ //continue
+
// Identify the operation type and determine if the watch event should be applied or not.
- switch pr.GetNode().GetProxy().Operation {
+ switch latestRev.GetNode().GetProxy().Operation {
case PROXY_REMOVE:
fallthrough
@@ -200,9 +199,9 @@
// Therefore, the data of the current event is most likely out-dated
// and should be ignored
log.Debugw("ignore-watch-event", log.Fields{
- "key": pr.GetHash(),
- "path": pr.GetNode().GetProxy().getFullPath(),
- "operation": pr.GetNode().GetProxy().Operation.String(),
+ "key": latestRev.GetHash(),
+ "path": latestRev.GetNode().GetProxy().getFullPath(),
+ "operation": latestRev.GetNode().GetProxy().Operation.String(),
})
continue
@@ -216,41 +215,45 @@
case PROXY_GET:
fallthrough
+ case PROXY_WATCH:
+ fallthrough
+
default:
log.Debugw("process-watch-event", log.Fields{
- "key": pr.GetHash(),
- "path": pr.GetNode().GetProxy().getFullPath(),
- "operation": pr.GetNode().GetProxy().Operation.String(),
+ "key": latestRev.GetHash(),
+ "path": latestRev.GetNode().GetProxy().getFullPath(),
+ "operation": latestRev.GetNode().GetProxy().Operation.String(),
})
}
}
// Reserve the path to prevent others to modify while we reload from persistence
- log.Debugw("reserve-and-lock-path", log.Fields{"key": pr.GetHash(), "path": pathLock})
- pac = PAC().ReservePath(pr.GetNode().GetProxy().getFullPath(), pr.GetNode().GetProxy(), pathLock)
+ log.Debugw("reserve-and-lock-path", log.Fields{"key": latestRev.GetHash(), "path": pathLock})
+ pac = PAC().ReservePath(latestRev.GetNode().GetProxy().getFullPath(),
+ latestRev.GetNode().GetProxy(), pathLock)
pac.lock()
- pr.GetNode().GetProxy().Operation = PROXY_UPDATE
- pac.SetProxy(pr.GetNode().GetProxy())
+ latestRev.GetNode().GetProxy().Operation = PROXY_WATCH
+ pac.SetProxy(latestRev.GetNode().GetProxy())
// Load changes and apply to memory
- pr.LoadFromPersistence(pr.GetName(), "", blobs)
+ latestRev.LoadFromPersistence(latestRev.GetName(), "", blobs)
- log.Debugw("release-and-unlock-path", log.Fields{"key": pr.GetHash(), "path": pathLock})
+ log.Debugw("release-and-unlock-path", log.Fields{"key": latestRev.GetHash(), "path": pathLock})
pac.getProxy().Operation = PROXY_GET
pac.unlock()
PAC().ReleasePath(pathLock)
} else {
// This block should be reached only if coming from a non-proxied request
- log.Debugw("revision-with-no-proxy", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
+ log.Debugw("revision-with-no-proxy", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName()})
// Load changes and apply to memory
- pr.LoadFromPersistence(pr.GetName(), "", blobs)
+ latestRev.LoadFromPersistence(latestRev.GetName(), "", blobs)
}
}
default:
- log.Debugw("unhandled-event", log.Fields{"key": pr.GetHash(), "watch": pr.GetName(), "type": event.EventType})
+ log.Debugw("unhandled-event", log.Fields{"key": latestRev.GetHash(), "watch": latestRev.GetName(), "type": event.EventType})
}
}
}
@@ -267,19 +270,18 @@
newNPR := pr.Revision.UpdateData(data, branch)
newPR := &PersistedRevision{
- Revision: newNPR,
- Compress: pr.Compress,
- kvStore: pr.kvStore,
- events: pr.events,
+ Revision: newNPR,
+ Compress: pr.Compress,
+ kvStore: pr.kvStore,
+ events: pr.events,
+ isWatched: pr.isWatched,
}
if newPR.GetHash() != pr.GetHash() {
- newPR.isWatched = false
newPR.isStored = false
pr.Drop(branch.Txid, false)
pr.Drop(branch.Txid, false)
} else {
- newPR.isWatched = true
newPR.isStored = true
}
@@ -294,18 +296,17 @@
newNPR := pr.Revision.UpdateChildren(name, children, branch)
newPR := &PersistedRevision{
- Revision: newNPR,
- Compress: pr.Compress,
- kvStore: pr.kvStore,
- events: pr.events,
+ Revision: newNPR,
+ Compress: pr.Compress,
+ kvStore: pr.kvStore,
+ events: pr.events,
+ isWatched: pr.isWatched,
}
if newPR.GetHash() != pr.GetHash() {
- newPR.isWatched = false
newPR.isStored = false
pr.Drop(branch.Txid, false)
} else {
- newPR.isWatched = true
newPR.isStored = true
}
@@ -319,18 +320,17 @@
newNPR := pr.Revision.UpdateAllChildren(children, branch)
newPR := &PersistedRevision{
- Revision: newNPR,
- Compress: pr.Compress,
- kvStore: pr.kvStore,
- events: pr.events,
+ Revision: newNPR,
+ Compress: pr.Compress,
+ kvStore: pr.kvStore,
+ events: pr.events,
+ isWatched: pr.isWatched,
}
if newPR.GetHash() != pr.GetHash() {
- newPR.isWatched = false
newPR.isStored = false
pr.Drop(branch.Txid, false)
} else {
- newPR.isWatched = true
newPR.isStored = true
}
@@ -388,6 +388,7 @@
if childIdx, childRev := pr.GetNode().findRevByKey(children, keyName, keyValue); childRev != nil {
// A child matching the provided key exists in memory
// Verify if the data differs from what was retrieved from persistence
+ // Also check if we are treating a newer revision of the data or not
if childRev.GetData().(proto.Message).String() != data.(proto.Message).String() {
log.Debugw("revision-data-is-different", log.Fields{
"key": childRev.GetHash(),
@@ -407,11 +408,11 @@
updatedChildRev.GetNode().SetProxy(childRev.GetNode().GetProxy())
updatedChildRev.SetupWatch(updatedChildRev.GetName())
- childRev.Drop(txid, false)
updatedChildRev.SetLastUpdate()
// Update cache
GetRevCache().Cache.Store(updatedChildRev.GetName(), updatedChildRev)
+ childRev.Drop(txid, false)
childRev.GetBranch().LatestLock.Unlock()
// END lock child
@@ -459,6 +460,7 @@
response = childRev
}
}
+
} else {
// There is no available child with that key value.
// Create a new child and update the parent revision.
@@ -478,7 +480,6 @@
childRev.SetName(typeName + "/" + keyValue)
childRev.SetupWatch(childRev.GetName())
- pr.GetBranch().Node.makeLatest(pr.GetBranch(), childRev, nil)
pr.GetBranch().LatestLock.Unlock()
// END child lock
@@ -491,7 +492,6 @@
children = append(children, childRev)
updatedRev := parent.GetBranch(NONE).Latest.UpdateChildren(typeName, children, parent.GetBranch(NONE))
updatedRev.GetNode().SetProxy(parent.GetBranch(NONE).Node.GetProxy())
-
parent.GetBranch(NONE).Node.makeLatest(parent.GetBranch(NONE), updatedRev, nil)
parent.GetBranch(NONE).LatestLock.Unlock()
// END parent lock
@@ -512,8 +512,7 @@
// LoadFromPersistence retrieves data from kv store at the specified location and refreshes the memory
// by adding missing entries, updating changed entries and ignoring unchanged ones
-func (pr *PersistedRevision) LoadFromPersistence(
- path string, txid string, blobs map[string]*kvstore.KVPair) []Revision {
+func (pr *PersistedRevision) LoadFromPersistence(path string, txid string, blobs map[string]*kvstore.KVPair) []Revision {
pr.mutex.Lock()
defer pr.mutex.Unlock()
@@ -575,8 +574,7 @@
// based on the field's key attribute
_, key := GetAttributeValue(data.Interface(), field.Key, 0)
- if entry := pr.verifyPersistedEntry(data.Interface(), name, field.Key, key.String(),
- txid); entry != nil {
+ if entry := pr.verifyPersistedEntry(data.Interface(), name, field.Key, key.String(), txid); entry != nil {
response = append(response, entry)
}
} else {
@@ -603,8 +601,7 @@
}
keyValue := field.KeyFromStr(key)
- if entry := pr.verifyPersistedEntry(data.Interface(), name, field.Key, keyValue.(string),
- txid); entry != nil {
+ if entry := pr.verifyPersistedEntry(data.Interface(), name, field.Key, keyValue.(string), txid); entry != nil {
response = append(response, entry)
}
}
diff --git a/db/model/proxy.go b/db/model/proxy.go
index d4a86f4..182dcdd 100644
--- a/db/model/proxy.go
+++ b/db/model/proxy.go
@@ -100,8 +100,12 @@
// getCallbacks returns the full list of callbacks associated to the proxy
func (p *Proxy) getCallbacks(callbackType CallbackType) map[string]*CallbackTuple {
- if cb, exists := p.Callbacks[callbackType]; exists {
- return cb
+ if p != nil {
+ if cb, exists := p.Callbacks[callbackType]; exists {
+ return cb
+ }
+ } else {
+ log.Debugw("proxy-is-nil", log.Fields{"callback-type": callbackType.String()})
}
return nil
}
@@ -148,6 +152,7 @@
PROXY_UPDATE
PROXY_REMOVE
PROXY_CREATE
+ PROXY_WATCH
)
var proxyOperationTypes = []string{
@@ -157,6 +162,7 @@
"PROXY_UPDATE",
"PROXY_REMOVE",
"PROXY_CREATE",
+ "PROXY_WATCH",
}
func (t ProxyOperation) String() string {
diff --git a/db/model/proxy_access_control.go b/db/model/proxy_access_control.go
index 2a5d034..a1ea6be 100644
--- a/db/model/proxy_access_control.go
+++ b/db/model/proxy_access_control.go
@@ -255,7 +255,7 @@
defer log.Debugw("unlocked-access--create-proxy", log.Fields{"path": path, "fullPath": pac.Proxy.getFullPath()})
}
- result := pac.getProxy().GetRoot().CreateProxy(path, exclusive)
+ result := pac.getProxy().ParentNode.CreateProxy(path, exclusive)
if result != nil {
return result
diff --git a/db/model/revision.go b/db/model/revision.go
index 4e606f1..cd4c5df 100644
--- a/db/model/revision.go
+++ b/db/model/revision.go
@@ -22,7 +22,6 @@
type Revision interface {
Finalize(bool)
- IsDiscarded() bool
SetConfig(revision *DataRevision)
GetConfig() *DataRevision
Drop(txid string, includeConfig bool)
diff --git a/db/model/root.go b/db/model/root.go
index 338ef67..5036ce1 100644
--- a/db/model/root.go
+++ b/db/model/root.go
@@ -91,7 +91,7 @@
dirtyNode.DeleteBranch(txid)
}
delete(r.DirtyNodes, txid)
- delete(r.node.Branches, txid)
+ r.node.DeleteBranch(txid)
}
// FoldTxBranch will merge the contents of a transaction branch with the root object
@@ -111,9 +111,8 @@
// ExecuteCallbacks will invoke all the callbacks linked to root object
func (r *root) ExecuteCallbacks() {
r.mutex.Lock()
- log.Debugf("ExecuteCallbacks has the ROOT lock : %+v", r)
defer r.mutex.Unlock()
- defer log.Debugf("ExecuteCallbacks released the ROOT lock : %+v", r)
+
for len(r.Callbacks) > 0 {
callback := r.Callbacks[0]
r.Callbacks = r.Callbacks[1:]
@@ -133,36 +132,32 @@
// getCallbacks returns the available callbacks
func (r *root) GetCallbacks() []CallbackTuple {
r.mutex.Lock()
- log.Debugf("getCallbacks has the ROOT lock : %+v", r)
defer r.mutex.Unlock()
- defer log.Debugf("getCallbacks released the ROOT lock : %+v", r)
+
return r.Callbacks
}
// getCallbacks returns the available notification callbacks
func (r *root) GetNotificationCallbacks() []CallbackTuple {
r.mutex.Lock()
- log.Debugf("GetNotificationCallbacks has the ROOT lock : %+v", r)
defer r.mutex.Unlock()
- defer log.Debugf("GetNotificationCallbacks released the ROOT lock : %+v", r)
+
return r.NotificationCallbacks
}
// AddCallback inserts a new callback with its arguments
func (r *root) AddCallback(callback CallbackFunction, args ...interface{}) {
r.mutex.Lock()
- log.Debugf("AddCallback has the ROOT lock : %+v", r)
defer r.mutex.Unlock()
- defer log.Debugf("AddCallback released the ROOT lock : %+v", r)
+
r.Callbacks = append(r.Callbacks, CallbackTuple{callback, args})
}
// AddNotificationCallback inserts a new notification callback with its arguments
func (r *root) AddNotificationCallback(callback CallbackFunction, args ...interface{}) {
r.mutex.Lock()
- log.Debugf("AddNotificationCallback has the ROOT lock : %+v", r)
defer r.mutex.Unlock()
- defer log.Debugf("AddNotificationCallback released the ROOT lock : %+v", r)
+
r.NotificationCallbacks = append(r.NotificationCallbacks, CallbackTuple{callback, args})
}