80b6994fe2
Update to abstract actor for markets state diffing. Also move the diff adt functions inside the abstract actors
115 lines
3.7 KiB
Go
115 lines
3.7 KiB
Go
package adt
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
typegen "github.com/whyrusleeping/cbor-gen"
|
|
)
|
|
|
|
// AdtArrayDiff generalizes adt.Array diffing by accepting a Deferred type that can unmarshalled to its corresponding struct
|
|
// in an interface implantation.
|
|
// Add should be called when a new k,v is added to the array
|
|
// Modify should be called when a value is modified in the array
|
|
// Remove should be called when a value is removed from the array
|
|
type AdtArrayDiff interface {
|
|
Add(key uint64, val *typegen.Deferred) error
|
|
Modify(key uint64, from, to *typegen.Deferred) error
|
|
Remove(key uint64, val *typegen.Deferred) error
|
|
}
|
|
|
|
// TODO Performance can be improved by diffing the underlying IPLD graph, e.g. https://github.com/ipfs/go-merkledag/blob/749fd8717d46b4f34c9ce08253070079c89bc56d/dagutils/diff.go#L104
|
|
// CBOR Marshaling will likely be the largest performance bottleneck here.
|
|
|
|
// DiffAdtArray accepts two *adt.Array's and an AdtArrayDiff implementation. It does the following:
|
|
// - All values that exist in preArr and not in curArr are passed to AdtArrayDiff.Remove()
|
|
// - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add()
|
|
// - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify()
|
|
// - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified.
|
|
func DiffAdtArray(preArr, curArr Array, out AdtArrayDiff) error {
|
|
prevVal := new(typegen.Deferred)
|
|
if err := preArr.ForEach(prevVal, func(i int64) error {
|
|
curVal := new(typegen.Deferred)
|
|
found, err := curArr.Get(uint64(i), curVal)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !found {
|
|
if err := out.Remove(uint64(i), prevVal); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// no modification
|
|
if !bytes.Equal(prevVal.Raw, curVal.Raw) {
|
|
if err := out.Modify(uint64(i), prevVal, curVal); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return curArr.Delete(uint64(i))
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
curVal := new(typegen.Deferred)
|
|
return curArr.ForEach(curVal, func(i int64) error {
|
|
return out.Add(uint64(i), curVal)
|
|
})
|
|
}
|
|
|
|
// TODO Performance can be improved by diffing the underlying IPLD graph, e.g. https://github.com/ipfs/go-merkledag/blob/749fd8717d46b4f34c9ce08253070079c89bc56d/dagutils/diff.go#L104
|
|
// CBOR Marshaling will likely be the largest performance bottleneck here.
|
|
|
|
// AdtMapDiff generalizes adt.Map diffing by accepting a Deferred type that can unmarshalled to its corresponding struct
|
|
// in an interface implantation.
|
|
// AsKey should return the Keyer implementation specific to the map
|
|
// Add should be called when a new k,v is added to the map
|
|
// Modify should be called when a value is modified in the map
|
|
// Remove should be called when a value is removed from the map
|
|
type AdtMapDiff interface {
|
|
AsKey(key string) (abi.Keyer, error)
|
|
Add(key string, val *typegen.Deferred) error
|
|
Modify(key string, from, to *typegen.Deferred) error
|
|
Remove(key string, val *typegen.Deferred) error
|
|
}
|
|
|
|
func DiffAdtMap(preMap, curMap Map, out AdtMapDiff) error {
|
|
prevVal := new(typegen.Deferred)
|
|
if err := preMap.ForEach(prevVal, func(key string) error {
|
|
curVal := new(typegen.Deferred)
|
|
k, err := out.AsKey(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
found, err := curMap.Get(k, curVal)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !found {
|
|
if err := out.Remove(key, prevVal); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// no modification
|
|
if !bytes.Equal(prevVal.Raw, curVal.Raw) {
|
|
if err := out.Modify(key, prevVal, curVal); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return curMap.Delete(k)
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
curVal := new(typegen.Deferred)
|
|
return curMap.ForEach(curVal, func(key string) error {
|
|
return out.Add(key, curVal)
|
|
})
|
|
}
|