blob: d349ec2206f26f3adab173744d14484a19d0864b [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package model
18
19import (
20 "bytes"
21 "crypto/md5"
22 "encoding/json"
23 "fmt"
24 "github.com/golang/protobuf/proto"
25 "github.com/opencord/voltha-lib-go/pkg/common/log"
26 "reflect"
27)
28
29// DataRevision stores the data associated to a revision along with its calculated checksum hash value
30type DataRevision struct {
31 Data interface{}
32 Hash string
33}
34
35// NewDataRevision creates a new instance of a DataRevision structure
36func NewDataRevision(root *root, data interface{}) *DataRevision {
37 dr := DataRevision{}
38 dr.Data = data
39 dr.Hash = dr.hashData(root, data)
40
41 return &dr
42}
43
44func (dr *DataRevision) hashData(root *root, data interface{}) string {
45 var buffer bytes.Buffer
46
47 if IsProtoMessage(data) {
48 if pbdata, err := proto.Marshal(data.(proto.Message)); err != nil {
49 log.Debugf("problem to marshal protobuf data --> err: %s", err.Error())
50 } else {
51 buffer.Write(pbdata)
52 // To ensure uniqueness in case data is nil, also include data type
53 buffer.Write([]byte(reflect.TypeOf(data).String()))
54 }
55
56 } else if reflect.ValueOf(data).IsValid() {
57 dataObj := reflect.New(reflect.TypeOf(data).Elem())
58 if json, err := json.Marshal(dataObj.Interface()); err != nil {
59 log.Debugf("problem to marshal data --> err: %s", err.Error())
60 } else {
61 buffer.Write(json)
62 }
63 } else {
64 dataObj := reflect.New(reflect.TypeOf(data).Elem())
65 buffer.Write(dataObj.Bytes())
66 }
67
68 // Add the root pointer that owns the current data for extra uniqueness
69 rootPtr := fmt.Sprintf("%p", root)
70 buffer.Write([]byte(rootPtr))
71
72 return fmt.Sprintf("%x", md5.Sum(buffer.Bytes()))[:12]
73}