forked from TrueCloudLab/neoneo-go
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()
|
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
|
||||||
}
|
}
|
||||||
|
|
27
pkg/vm/vm.go
27
pkg/vm/vm.go
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue