VOL-1027 : Initial commit of voltha 2.0 data model
Change-Id: Ib8006de1af2166281ccf1c9d7c2b9156991bf4e4
diff --git a/db/model/persisted_revision.go b/db/model/persisted_revision.go
new file mode 100644
index 0000000..f390e0b
--- /dev/null
+++ b/db/model/persisted_revision.go
@@ -0,0 +1,150 @@
+package model
+
+import (
+ "bytes"
+ "compress/gzip"
+ "encoding/json"
+ "fmt"
+ "github.com/golang/protobuf/proto"
+ "io/ioutil"
+ "reflect"
+)
+
+type PersistedRevision struct {
+ *Revision
+ Compress bool
+ kvStore *Backend
+}
+
+func NewPersistedRevision(branch *Branch, data interface{}, children map[string][]*Revision) *PersistedRevision {
+ pr := &PersistedRevision{}
+ pr.kvStore = branch.node.root.KvStore
+ pr.Revision = NewRevision(branch, data, children)
+ return pr
+}
+
+func (pr *PersistedRevision) finalize() {
+ pr.Revision.finalize()
+ pr.store()
+}
+
+type revData struct {
+ Children map[string][]string
+ Config string
+}
+
+func (pr *PersistedRevision) store() {
+ if ok, _ := pr.kvStore.Get(pr.Revision.Hash); ok != nil {
+ return
+ }
+
+ pr.storeConfig()
+
+ childrenHashes := make(map[string][]string)
+ for fieldName, children := range pr.Children {
+ hashes := []string{}
+ for _, rev := range children {
+ hashes = append(hashes, rev.Hash)
+ }
+ childrenHashes[fieldName] = hashes
+ }
+ data := &revData{
+ Children: childrenHashes,
+ Config: pr.Config.Hash,
+ }
+ if blob, err := json.Marshal(data); err != nil {
+ // TODO report error
+ } else {
+ if pr.Compress {
+ var b bytes.Buffer
+ w := gzip.NewWriter(&b)
+ w.Write(blob)
+ w.Close()
+ blob = b.Bytes()
+ }
+ pr.kvStore.Put(pr.Hash, blob)
+ }
+}
+
+func (pr *PersistedRevision) load(branch *Branch, kvStore *Backend, msgClass interface{}, hash string) *PersistedRevision {
+ blob, _ := kvStore.Get(hash)
+ output := blob.Value.([]byte)
+ var data revData
+ if pr.Compress {
+ b := bytes.NewBuffer(blob.Value.([]byte))
+ if r, err := gzip.NewReader(b); err != nil {
+ // TODO : report error
+ } else {
+ if output, err = ioutil.ReadAll(r); err != nil {
+ // TODO report error
+ }
+ }
+ }
+ if err := json.Unmarshal(output, &data); err != nil {
+ fmt.Errorf("problem to unmarshal data - %s", err.Error())
+ }
+
+ configHash := data.Config
+ configData := pr.loadConfig(kvStore, msgClass, configHash)
+ assembledChildren := make(map[string][]*Revision)
+
+ childrenHashes := data.Children
+ node := branch.node
+ for fieldName, child := range ChildrenFields(msgClass) {
+ var children []*Revision
+ for _, childHash := range childrenHashes[fieldName] {
+ //fmt.Printf("child class type: %+v", reflect.New(n).Elem().Interface())
+ childNode := node.makeNode(reflect.New(child.ClassType).Elem().Interface(), "")
+ childNode.LoadLatest(kvStore, childHash)
+ childRev := childNode.Latest()
+ children = append(children, childRev)
+ }
+ assembledChildren[fieldName] = children
+ }
+ rev := NewPersistedRevision(branch, configData, assembledChildren)
+ return rev
+}
+
+func (pr *PersistedRevision) storeConfig() {
+ if ok, _ := pr.kvStore.Get(pr.Config.Hash); ok != nil {
+ return
+ }
+ if blob, err := proto.Marshal(pr.Config.Data.(proto.Message)); err != nil {
+ // TODO report error
+ } else {
+ if pr.Compress {
+ var b bytes.Buffer
+ w := gzip.NewWriter(&b)
+ w.Write(blob)
+ w.Close()
+ blob = b.Bytes()
+ }
+ pr.kvStore.Put(pr.Config.Hash, blob)
+ }
+}
+
+func (pr *PersistedRevision) loadConfig(kvStore *Backend, msgClass interface{}, hash string) interface{} {
+ blob, _ := kvStore.Get(hash)
+ output := blob.Value.([]byte)
+
+ if pr.Compress {
+ b := bytes.NewBuffer(blob.Value.([]byte))
+ if r, err := gzip.NewReader(b); err != nil {
+ // TODO : report error
+ } else {
+ if output, err = ioutil.ReadAll(r); err != nil {
+ // TODO report error
+ }
+ }
+ }
+
+ var data reflect.Value
+ if msgClass != nil {
+ data = reflect.New(reflect.TypeOf(msgClass).Elem())
+ if err := proto.Unmarshal(output, data.Interface().(proto.Message)); err != nil {
+ // TODO report error
+ }
+ }
+
+ return data.Interface()
+}