VOL-1334 : Fixed concurrency issues
- Semaphores were added at the different layers of the model
- Made the proxy interfaces more robust
- Eliminated problems while retrieving latest data in concurrent mode
Change-Id: I7854105d7effa10e5cb704f5d9917569ab184f84
diff --git a/db/model/merge.go b/db/model/merge.go
index 0546bd3..e40f98b 100644
--- a/db/model/merge.go
+++ b/db/model/merge.go
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package model
import (
"github.com/opencord/voltha-go/common/log"
- "reflect"
)
func revisionsAreEqual(a, b []Revision) bool {
@@ -65,17 +65,17 @@
_, v := GetAttributeValue(rev.GetData(), keyName, 0)
changes.KeyMap2[v.String()] = i
}
- for v, _ := range changes.KeyMap2 {
+ for v := range changes.KeyMap2 {
if _, ok := changes.KeyMap1[v]; !ok {
changes.AddedKeys[v] = struct{}{}
}
}
- for v, _ := range changes.KeyMap1 {
+ for v := range changes.KeyMap1 {
if _, ok := changes.KeyMap2[v]; !ok {
changes.RemovedKeys[v] = struct{}{}
}
}
- for v, _ := range changes.KeyMap1 {
+ for v := range changes.KeyMap1 {
if _, ok := changes.KeyMap2[v]; ok && lst1[changes.KeyMap1[v]].GetHash() != lst2[changes.KeyMap2[v]].GetHash() {
changes.ChangedKeys[v] = struct{}{}
}
@@ -84,6 +84,7 @@
return changes
}
+// Merge3Way takes care of combining the revision contents of the same data set
func Merge3Way(
forkRev, srcRev, dstRev Revision,
mergeChildFunc func(Revision) Revision,
@@ -101,7 +102,14 @@
configChanged = true
}
- newChildren := reflect.ValueOf(dstRev.GetChildren()).Interface().(map[string][]Revision)
+ //newChildren := reflect.ValueOf(dstRev.GetChildren()).Interface().(map[string][]Revision)
+ newChildren := make(map[string][]Revision)
+ for entryName, childrenEntry := range dstRev.GetChildren() {
+ //newRev.Children[entryName] = append(newRev.Children[entryName], childrenEntry...)
+ newChildren[entryName] = make([]Revision, len(childrenEntry))
+ copy(newChildren[entryName], childrenEntry)
+ }
+
childrenFields := ChildrenFields(forkRev.GetData())
for fieldName, field := range childrenFields {
@@ -140,9 +148,10 @@
if revisionsAreEqual(dstList, forkList) {
src := newChangeAnalysis(forkList, srcList, field.Key)
- newList := reflect.ValueOf(srcList).Interface().([]Revision)
+ newList := make([]Revision, len(srcList))
+ copy(newList, srcList)
- for key, _ := range src.AddedKeys {
+ for key := range src.AddedKeys {
idx := src.KeyMap2[key]
newRev := mergeChildFunc(newList[idx])
@@ -152,12 +161,12 @@
changes = append(changes, ChangeTuple{POST_ADD, newList[idx].GetData(), newRev.GetData()})
}
}
- for key, _ := range src.RemovedKeys {
+ for key := range src.RemovedKeys {
oldRev := forkList[src.KeyMap1[key]]
revsToDiscard = append(revsToDiscard, oldRev)
changes = append(changes, ChangeTuple{POST_REMOVE, oldRev.GetData(), nil})
}
- for key, _ := range src.ChangedKeys {
+ for key := range src.ChangedKeys {
idx := src.KeyMap2[key]
newRev := mergeChildFunc(newList[idx])
@@ -174,9 +183,10 @@
src := newChangeAnalysis(forkList, srcList, field.Key)
dst := newChangeAnalysis(forkList, dstList, field.Key)
- newList := reflect.ValueOf(dstList).Interface().([]Revision)
+ newList := make([]Revision, len(dstList))
+ copy(newList, dstList)
- for key, _ := range src.AddedKeys {
+ for key := range src.AddedKeys {
if _, exists := dst.AddedKeys[key]; exists {
childDstRev := dstList[dst.KeyMap2[key]]
childSrcRev := srcList[src.KeyMap2[key]]
@@ -191,7 +201,7 @@
changes = append(changes, ChangeTuple{POST_ADD, srcList[src.KeyMap2[key]], newRev.GetData()})
}
}
- for key, _ := range src.ChangedKeys {
+ for key := range src.ChangedKeys {
if _, removed := dst.RemovedKeys[key]; removed {
log.Error("conflict error - revision has been removed")
} else if _, changed := dst.ChangedKeys[key]; changed {
@@ -212,7 +222,7 @@
}
// TODO: how do i sort this map in reverse order?
- for key, _ := range src.RemovedKeys {
+ for key := range src.RemovedKeys {
if _, changed := dst.ChangedKeys[key]; changed {
log.Error("conflict error - revision has changed")
}
@@ -236,7 +246,7 @@
}
}
- if !dryRun {
+ if !dryRun && len(newChildren) > 0{
if configChanged {
rev = srcRev
} else {
@@ -247,15 +257,15 @@
discarded.Drop("", true)
}
- dstRev.GetBranch().Latest.Drop("", configChanged)
+ dstRev.GetBranch().GetLatest().Drop("", configChanged)
rev = rev.UpdateAllChildren(newChildren, dstRev.GetBranch())
if configChanged {
- changes = append(changes, ChangeTuple{POST_UPDATE, dstRev.GetBranch().Latest.GetData(), rev.GetData()})
+ // FIXME: what type of previous/latest data do we want to show? Specific node or Root
+ changes = append(changes, ChangeTuple{POST_UPDATE, dstRev.GetBranch().GetLatest().GetData(), rev.GetData()})
}
return rev, changes
- } else {
- return nil, nil
-
}
+
+ return nil, nil
}