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()
}
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
}

View file

@ -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) {