vm: use single function instead of committer/discarder

This commit is contained in:
Anna Shaleva 2022-05-23 12:02:37 +03:00
parent 08b68e9b82
commit f79f62dab4
2 changed files with 22 additions and 35 deletions

View file

@ -324,29 +324,27 @@ func (ic *Context) SpawnVM() *vm.VM {
} }
ic.DAO = ic.DAO.GetPrivate() ic.DAO = ic.DAO.GetPrivate()
} }
committer := func() error { 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 { if ic.DAO == nil {
return nil return nil
} }
_, err := ic.DAO.Persist() if commit {
if err != nil { _, err := ic.DAO.Persist()
return fmt.Errorf("failed to persist changes %w", err) if err != nil {
return fmt.Errorf("failed to persist changes %w", err)
}
} }
ic.DAO = ic.DAO.GetUnwrapped() ic.DAO = ic.DAO.GetUnwrapped()
return nil return nil
} }
reverter := func(ntfToRemove int) { v.SetIsolationCallbacks(wrapper, unwrapper)
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
}
ic.DAO = ic.DAO.GetUnwrapped() // Discard all changes made in this layer.
}
v.SetIsolationCallbacks(wrapper, committer, reverter)
ic.VM = v ic.VM = v
return v return v
} }

View file

@ -69,10 +69,8 @@ type VM struct {
// wraps DAO with private MemCachedStore // wraps DAO with private MemCachedStore
wrapDao func() wrapDao func()
// commits DAO changes and unwraps DAO. // either commits or discards changes made in the current context; performs DAO unwrapping.
commitChanges func() error unwrapDAO func(commit bool, notificationsCount int) error
// unwraps DAO and removes last notificationsCount notifications from the context
revertChanges func(notificationsCount int)
istack Stack // invocation stack. istack Stack // invocation stack.
estack *Stack // execution stack. estack *Stack // execution stack.
@ -136,10 +134,9 @@ func (v *VM) EmitNotification() {
// wrapper performs DAO cloning; // wrapper performs DAO cloning;
// committer persists changes made in the upper snapshot to the underlying DAO; // 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. // 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.wrapDao = wrapper
v.commitChanges = committer v.unwrapDAO = unwrapper
v.revertChanges = reverter
} }
// SetPriceGetter registers the given PriceGetterFunc in v. // 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) { if ctx.static != nil && (currCtx == nil || ctx.static != currCtx.static) {
ctx.static.ClearRefs(&v.refs) 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 ctx.isWrapped && v.unwrapDAO != nil { // In case of CALL, CALLA, CALLL we don't need to commit/discard changes, unwrap DAO and change notificationsCount.
if v.uncaughtException == nil { err := v.unwrapDAO(v.uncaughtException == nil, *ctx.notificationsCount)
if v.commitChanges != nil { if err != nil {
if err := v.commitChanges(); err != nil { panic(fmt.Errorf("failed to unwrap DAO: %w", err))
// TODO: return an error instead?
panic(fmt.Errorf("failed to commit changes: %w", err))
}
}
} else {
if v.revertChanges != nil {
v.revertChanges(*ctx.notificationsCount)
}
} }
} }
if currCtx != nil && ctx.persistNotificationsCountOnUnloading && !(ctx.isWrapped && v.uncaughtException != nil) { if currCtx != nil && ctx.persistNotificationsCountOnUnloading && !(ctx.isWrapped && v.uncaughtException != nil) {