github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/storage/snapshot/snapshot_tree.go (about) 1 package snapshot 2 3 import ( 4 "github.com/onflow/flow-go/model/flow" 5 ) 6 7 const ( 8 compactThreshold = 10 9 ) 10 11 type UpdateLog []map[flow.RegisterID]flow.RegisterValue 12 13 // SnapshotTree is a simple LSM tree representation of the key/value storage 14 // at a given point in time. 15 type SnapshotTree struct { 16 base StorageSnapshot 17 18 compactedLog UpdateLog 19 } 20 21 // NewSnapshotTree returns a tree with keys/values initialized to the base 22 // storage snapshot. 23 func NewSnapshotTree(base StorageSnapshot) SnapshotTree { 24 return SnapshotTree{ 25 base: base, 26 compactedLog: nil, 27 } 28 } 29 30 // Append returns a new tree with updates from the execution snapshot "applied" 31 // to the original original tree. 32 func (tree SnapshotTree) Append( 33 update *ExecutionSnapshot, 34 ) SnapshotTree { 35 compactedLog := tree.compactedLog 36 if len(update.WriteSet) > 0 { 37 compactedLog = append(tree.compactedLog, update.WriteSet) 38 if len(compactedLog) > compactThreshold { 39 size := 0 40 for _, set := range compactedLog { 41 size += len(set) 42 } 43 44 mergedSet := make(map[flow.RegisterID]flow.RegisterValue, size) 45 for _, set := range compactedLog { 46 for id, value := range set { 47 mergedSet[id] = value 48 } 49 } 50 51 compactedLog = UpdateLog{mergedSet} 52 } 53 } 54 55 return SnapshotTree{ 56 base: tree.base, 57 compactedLog: compactedLog, 58 } 59 } 60 61 // Get returns the register id's value. 62 func (tree SnapshotTree) Get(id flow.RegisterID) (flow.RegisterValue, error) { 63 for idx := len(tree.compactedLog) - 1; idx >= 0; idx-- { 64 value, ok := tree.compactedLog[idx][id] 65 if ok { 66 return value, nil 67 } 68 } 69 70 if tree.base != nil { 71 return tree.base.Get(id) 72 } 73 74 return nil, nil 75 }