commit fa0c7a0043bdbf05a175b94d463d705b6e1f6647
parent 41dc0ccbaaf9366b8d92c4770dc7ee8754b2d862
Author: lash <dev@holbrook.no>
Date: Mon, 2 Sep 2024 01:30:58 +0100
Finish persister setup for engine
Diffstat:
3 files changed, 136 insertions(+), 4 deletions(-)
diff --git a/engine/db.go b/engine/db.go
@@ -2,6 +2,7 @@ package engine
import (
"context"
+ "errors"
"fmt"
"io"
"os"
@@ -139,6 +140,59 @@ func(en *DbEngine) ensureMemory() {
}
}
+func(en *DbEngine) preparePersist() error {
+ if en.pe == nil {
+ return nil
+ }
+ st := en.pe.GetState()
+ if st != nil {
+ if en.st != nil {
+ return errors.New("state cannot be explicitly set in both persister and engine.")
+ }
+ en.st = st
+ } else {
+ if en.st == nil {
+ logg.Debugf("defer persist state set until state set in engine")
+ } else {
+ en.st = st
+ }
+ }
+ ca := en.pe.GetMemory().(*cache.Cache)
+ if ca != nil {
+ if en.ca == nil {
+ return errors.New("cache cannot be explicitly set in both persister and engine.")
+ }
+ en.ca = ca
+ } else {
+ if en.ca == nil {
+ logg.Debugf("defer persist memory set until state set in engine")
+ } else {
+ en.ca = ca
+ }
+ }
+ return nil
+}
+
+func(en *DbEngine) ensurePersist() error {
+ if en.pe == nil {
+ return nil
+ }
+ st := en.pe.GetState()
+ if st == nil {
+ st = en.st
+ }
+ ca := en.pe.GetMemory()
+ if ca == nil {
+ ca = en.ca
+ }
+ cac, ok := ca.(*cache.Cache)
+ if !ok {
+ return errors.New("Memory is not a *cache.Cache. For the time being it has to be, because of the way persister serialization is implemented. This hopefully changes in the future.")
+ }
+ en.pe = en.pe.WithContent(st, cac)
+ return nil
+}
+
func(en *DbEngine) setupVm() {
var szr *render.Sizer
if en.cfg.OutputSize > 0 {
@@ -147,10 +201,19 @@ func(en *DbEngine) setupVm() {
en.vm = vm.NewVm(en.st, en.rs, en.ca, szr)
}
-func(en *DbEngine) prepare() {
+func(en *DbEngine) prepare() error {
+ err := en.preparePersist()
+ if err != nil {
+ return err
+ }
en.ensureState()
en.ensureMemory()
+ err = en.ensurePersist()
+ if err != nil {
+ return err
+ }
en.setupVm()
+ return nil
}
// execute the first function, if set
@@ -228,7 +291,10 @@ func(en *DbEngine) restore() {
//
// It loads and executes code for the start node.
func(en *DbEngine) Init(ctx context.Context) (bool, error) {
- en.prepare()
+ err := en.prepare()
+ if err != nil {
+ return false, err
+ }
en.restore()
if en.initd {
logg.DebugCtxf(ctx, "already initialized")
@@ -241,7 +307,7 @@ func(en *DbEngine) Init(ctx context.Context) (bool, error) {
}
inSave, _ := en.st.GetInput()
- err := en.st.SetInput([]byte{})
+ err = en.st.SetInput([]byte{})
if err != nil {
return false, err
}
diff --git a/engine/db_test.go b/engine/db_test.go
@@ -3,12 +3,23 @@ package engine
import (
"context"
"fmt"
+ "io"
+ "os"
"testing"
"git.defalsify.org/vise.git/resource"
+ "git.defalsify.org/vise.git/state"
"git.defalsify.org/vise.git/vm"
)
+func getNull() io.WriteCloser {
+ nul, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0700)
+ if err != nil {
+ panic(err)
+ }
+ return nul
+}
+
func codeGet(ctx context.Context, s string) ([]byte, error) {
var b []byte
var err error
@@ -22,6 +33,13 @@ func codeGet(ctx context.Context, s string) ([]byte, error) {
return b, err
}
+func flagSet(ctx context.Context, nodeSym string, input []byte) (resource.Result, error) {
+ return resource.Result{
+ Content: "xyzzy",
+ FlagSet: []uint32{state.FLAG_USERSTART},
+ }, nil
+}
+
func TestDbEngineMinimal(t *testing.T) {
ctx := context.Background()
cfg := Config{}
@@ -37,6 +55,8 @@ func TestDbEngineMinimal(t *testing.T) {
}
func TestDbEngineRoot(t *testing.T) {
+ nul := getNull()
+ defer nul.Close()
ctx := context.Background()
cfg := Config{}
rs := resource.NewMenuResource()
@@ -49,4 +69,51 @@ func TestDbEngineRoot(t *testing.T) {
if !cont {
t.Fatalf("expected continue")
}
+
+ cont, err = en.Exec(ctx, []byte{0x30})
+ if err == nil {
+ t.Fatalf("expected loadfail")
+ }
+
+ _, err = en.WriteResult(ctx, nul)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cont, err = en.Exec(ctx, []byte{0x30})
+ if err == nil {
+ t.Fatalf("expected nocode")
+ }
+}
+
+func TestDbEnginePersist(t *testing.T) {
+ nul := getNull()
+ defer nul.Close()
+ ctx := context.Background()
+ cfg := Config{
+ FlagCount: 1,
+ SessionId: "bar",
+ }
+ rs := resource.NewMenuResource()
+ rs.WithCodeGetter(codeGet)
+ rs.AddLocalFunc("foo", flagSet)
+ en := NewDbEngine(cfg, rs)
+ cont, err := en.Init(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !cont {
+ t.Fatalf("expected continue")
+ }
+
+ cont, err = en.Exec(ctx, []byte{0x30})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = en.WriteResult(ctx, nul)
+ if err != nil {
+ t.Fatal(err)
+ }
+
}
diff --git a/vm/runner.go b/vm/runner.go
@@ -482,7 +482,6 @@ func(vm *Vm) refresh(key string, rs resource.Resource, ctx context.Context) (str
_ = vm.st.SetFlag(state.FLAG_LOADFAIL)
return "", NewExternalCodeError(key, err).WithCode(r.Status)
}
- logg.TraceCtxf(ctx, "foo", "flags", r.FlagSet)
for _, flag := range r.FlagReset {
if !state.IsWriteableFlag(flag) {
continue