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  }