XVOL-1689 : ONU stays in DISCOVERED state
VOL-1586 : Possible race condition in openolt python adapter during onu discovery
1) gets Device in response of ChildDeviceDetected.
This avoids race and also removes the need for GetChildDevice.
2)Puts the Device Id into cache to use in future requests,
especially avoid the fail when calling GetChildDevice
in onuIndication because of race.
Change-Id: I60944a6ee0e2ffad80a31ef93f72b55b0b136284
diff --git a/vendor/github.com/opencord/voltha-go/db/model/node.go b/vendor/github.com/opencord/voltha-go/db/model/node.go
index 15ea04e..207df09 100644
--- a/vendor/github.com/opencord/voltha-go/db/model/node.go
+++ b/vendor/github.com/opencord/voltha-go/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")
}