vm: use single function instead of committer/discarder
This commit is contained in:
parent
08b68e9b82
commit
f79f62dab4
2 changed files with 22 additions and 35 deletions
|
@ -324,29 +324,27 @@ func (ic *Context) SpawnVM() *vm.VM {
|
|||
}
|
||||
ic.DAO = ic.DAO.GetPrivate()
|
||||
}
|
||||
committer := func() error {
|
||||
if ic.DAO == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := ic.DAO.Persist()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to persist changes %w", err)
|
||||
}
|
||||
ic.DAO = ic.DAO.GetUnwrapped()
|
||||
return nil
|
||||
}
|
||||
reverter := func(ntfToRemove int) {
|
||||
unwrapper := func(commit bool, ntfToRemove int) error {
|
||||
if !commit {
|
||||
have := len(ic.Notifications)
|
||||
if have < ntfToRemove {
|
||||
panic(fmt.Errorf("inconsistent notifications count: should remove %d, have %d", ntfToRemove, len(ic.Notifications)))
|
||||
}
|
||||
ic.Notifications = ic.Notifications[:have-ntfToRemove]
|
||||
}
|
||||
if ic.DAO == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ic.DAO = ic.DAO.GetUnwrapped() // Discard all changes made in this layer.
|
||||
if commit {
|
||||
_, err := ic.DAO.Persist()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to persist changes %w", err)
|
||||
}
|
||||
v.SetIsolationCallbacks(wrapper, committer, reverter)
|
||||
}
|
||||
ic.DAO = ic.DAO.GetUnwrapped()
|
||||
return nil
|
||||
}
|
||||
v.SetIsolationCallbacks(wrapper, unwrapper)
|
||||
ic.VM = v
|
||||
return v
|
||||
}
|
||||
|
|
27
pkg/vm/vm.go
27
pkg/vm/vm.go
|
@ -69,10 +69,8 @@ type VM struct {
|
|||
|
||||
// wraps DAO with private MemCachedStore
|
||||
wrapDao func()
|
||||
// commits DAO changes and unwraps DAO.
|
||||
commitChanges func() error
|
||||
// unwraps DAO and removes last notificationsCount notifications from the context
|
||||
revertChanges func(notificationsCount int)
|
||||
// either commits or discards changes made in the current context; performs DAO unwrapping.
|
||||
unwrapDAO func(commit bool, notificationsCount int) error
|
||||
|
||||
istack Stack // invocation stack.
|
||||
estack *Stack // execution stack.
|
||||
|
@ -136,10 +134,9 @@ func (v *VM) EmitNotification() {
|
|||
// wrapper performs DAO cloning;
|
||||
// committer persists changes made in the upper snapshot to the underlying DAO;
|
||||
// reverter rolls back the whole set of changes made in the current snapshot.
|
||||
func (v *VM) SetIsolationCallbacks(wrapper func(), committer func() error, reverter func(ntfToRemove int)) {
|
||||
func (v *VM) SetIsolationCallbacks(wrapper func(), unwrapper func(commit bool, notificationsCount int) error) {
|
||||
v.wrapDao = wrapper
|
||||
v.commitChanges = committer
|
||||
v.revertChanges = reverter
|
||||
v.unwrapDAO = unwrapper
|
||||
}
|
||||
|
||||
// SetPriceGetter registers the given PriceGetterFunc in v.
|
||||
|
@ -1635,18 +1632,10 @@ func (v *VM) unloadContext(ctx *Context) {
|
|||
if ctx.static != nil && (currCtx == nil || ctx.static != currCtx.static) {
|
||||
ctx.static.ClearRefs(&v.refs)
|
||||
}
|
||||
if ctx.isWrapped { // In case of CALL, CALLA, CALLL we don't need to commit/discard changes, unwrap DAO and change notificationsCount.
|
||||
if v.uncaughtException == nil {
|
||||
if v.commitChanges != nil {
|
||||
if err := v.commitChanges(); err != nil {
|
||||
// TODO: return an error instead?
|
||||
panic(fmt.Errorf("failed to commit changes: %w", err))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if v.revertChanges != nil {
|
||||
v.revertChanges(*ctx.notificationsCount)
|
||||
}
|
||||
if ctx.isWrapped && v.unwrapDAO != nil { // In case of CALL, CALLA, CALLL we don't need to commit/discard changes, unwrap DAO and change notificationsCount.
|
||||
err := v.unwrapDAO(v.uncaughtException == nil, *ctx.notificationsCount)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to unwrap DAO: %w", err))
|
||||
}
|
||||
}
|
||||
if currCtx != nil && ctx.persistNotificationsCountOnUnloading && !(ctx.isWrapped && v.uncaughtException != nil) {
|
||||
|
|
Loading…
Reference in a new issue