Refactor.

This commit is contained in:
Nuno Cruces
2023-01-22 15:44:39 +00:00
parent 6527435c0f
commit 48105a529c
3 changed files with 52 additions and 68 deletions

View File

@@ -11,7 +11,7 @@ Roadmap:
- branch [`wasi`](https://github.com/ncruces/go-sqlite3/tree/wasi) uses `test_demovfs.c` directly
- [x] come up with a simple, nice API, enough for simple queries
- [ ] file locking, compatible with SQLite on Windows/Unix
- [ ] shared-memory, compatible with SQLite on Windows/Unix
- [ ] ~shared-memory, compatible with SQLite on Windows/Unix~
Benchmarks:

26
conn.go
View File

@@ -3,14 +3,11 @@ package sqlite3
import (
"bytes"
"context"
"io/fs"
"os"
"path/filepath"
"strconv"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/experimental/writefs"
)
type Conn struct {
@@ -22,29 +19,16 @@ type Conn struct {
files []*os.File
}
func Open(name string) (conn *Conn, err error) {
return OpenFlags(name, OPEN_READWRITE|OPEN_CREATE)
func Open(filename string) (conn *Conn, err error) {
return OpenFlags(filename, OPEN_READWRITE|OPEN_CREATE)
}
func OpenFlags(name string, flags OpenFlag) (conn *Conn, err error) {
func OpenFlags(filename string, flags OpenFlag) (conn *Conn, err error) {
once.Do(compile)
var fs fs.FS
if name != ":memory:" {
dir := filepath.Dir(name)
name = filepath.Base(name)
fs, err = writefs.NewDirFS(dir)
if err != nil {
return nil, err
}
}
ctx := context.Background()
cfg := wazero.NewModuleConfig().
WithName("sqlite3-" + strconv.FormatUint(counter.Add(1), 10))
if fs != nil {
cfg = cfg.WithFS(fs)
}
module, err := wasm.InstantiateModule(ctx, module, cfg)
if err != nil {
return nil, err
@@ -57,7 +41,7 @@ func OpenFlags(name string, flags OpenFlag) (conn *Conn, err error) {
c := newConn(module)
c.ctx = context.WithValue(ctx, connContext{}, c)
namePtr := c.newString(name)
namePtr := c.newString(filename)
connPtr := c.new(ptrSize)
defer c.free(namePtr)
defer c.free(connPtr)
@@ -227,7 +211,7 @@ func (c *Conn) getString(ptr, maxlen uint32) string {
}
func getString(memory api.Memory, ptr, maxlen uint32) string {
mem, ok := memory.Read(ptr, maxlen)
mem, ok := memory.Read(ptr, maxlen+1)
if !ok {
mem, ok = memory.Read(ptr, memory.Size()-ptr)
if !ok {

92
vfs.go
View File

@@ -51,8 +51,8 @@ func vfsExit(ctx context.Context, mod api.Module, exitCode uint32) {
panic(sys.NewExitError(mod.Name(), exitCode))
}
func vfsRandomness(ctx context.Context, mod api.Module, vfs, nByte, zOut uint32) uint32 {
mem, ok := mod.Memory().Read(zOut, nByte)
func vfsRandomness(ctx context.Context, mod api.Module, pVfs, nByte, zByte uint32) uint32 {
mem, ok := mod.Memory().Read(zByte, nByte)
if !ok {
panic(rangeErr)
}
@@ -60,52 +60,52 @@ func vfsRandomness(ctx context.Context, mod api.Module, vfs, nByte, zOut uint32)
return uint32(n)
}
func vfsSleep(ctx context.Context, vfs, microseconds uint32) uint32 {
time.Sleep(time.Duration(microseconds) * time.Microsecond)
func vfsSleep(ctx context.Context, pVfs, nMicro uint32) uint32 {
time.Sleep(time.Duration(nMicro) * time.Microsecond)
return _OK
}
func vfsCurrentTime(ctx context.Context, mod api.Module, vfs, out uint32) uint32 {
func vfsCurrentTime(ctx context.Context, mod api.Module, pVfs, prNow uint32) uint32 {
day := julianday.Float(time.Now())
if ok := mod.Memory().WriteFloat64Le(out, day); !ok {
if ok := mod.Memory().WriteFloat64Le(prNow, day); !ok {
panic(rangeErr)
}
return _OK
}
func vfsCurrentTime64(ctx context.Context, mod api.Module, vfs, out uint32) uint32 {
func vfsCurrentTime64(ctx context.Context, mod api.Module, pVfs, piNow uint32) uint32 {
day, nsec := julianday.Date(time.Now())
msec := day*86_400_000 + nsec/1_000_000
if ok := mod.Memory().WriteUint64Le(out, uint64(msec)); !ok {
if ok := mod.Memory().WriteUint64Le(piNow, uint64(msec)); !ok {
panic(rangeErr)
}
return _OK
}
func vfsFullPathname(ctx context.Context, mod api.Module, vfs, zName, nOut, zOut uint32) uint32 {
name := getString(mod.Memory(), zName, _MAX_PATHNAME)
s, err := filepath.Abs(name)
func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative, nFull, zFull uint32) uint32 {
rel := getString(mod.Memory(), zRelative, _MAX_PATHNAME)
abs, err := filepath.Abs(rel)
if err != nil {
return uint32(IOERR)
}
siz := uint32(len(s) + 1)
if siz > nOut {
siz := uint32(len(abs) + 1)
if siz > nFull {
return uint32(IOERR)
}
mem, ok := mod.Memory().Read(zOut, siz)
mem, ok := mod.Memory().Read(zFull, siz)
if !ok {
panic(rangeErr)
}
mem[len(s)] = 0
copy(mem, s)
mem[len(abs)] = 0
copy(mem, abs)
return _OK
}
func vfsDelete(ctx context.Context, mod api.Module, vfs, zName, syncDir uint32) uint32 {
name := getString(mod.Memory(), zName, _MAX_PATHNAME)
err := os.Remove(name)
func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32) uint32 {
path := getString(mod.Memory(), zPath, _MAX_PATHNAME)
err := os.Remove(path)
if errors.Is(err, fs.ErrNotExist) {
return _OK
}
@@ -113,7 +113,7 @@ func vfsDelete(ctx context.Context, mod api.Module, vfs, zName, syncDir uint32)
return uint32(IOERR_DELETE)
}
if syncDir != 0 {
f, err := os.Open(filepath.Dir(name))
f, err := os.Open(filepath.Dir(path))
if err == nil {
err = f.Sync()
f.Close()
@@ -125,9 +125,9 @@ func vfsDelete(ctx context.Context, mod api.Module, vfs, zName, syncDir uint32)
return _OK
}
func vfsAccess(ctx context.Context, mod api.Module, vfs, zName, flags, pResOut uint32) uint32 {
name := getString(mod.Memory(), zName, _MAX_PATHNAME)
fi, err := os.Stat(name)
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath, flags, pResOut uint32) uint32 {
path := getString(mod.Memory(), zPath, _MAX_PATHNAME)
fi, err := os.Stat(path)
var res uint32
if flags == uint32(ACCESS_EXISTS) {
@@ -164,7 +164,7 @@ func vfsAccess(ctx context.Context, mod api.Module, vfs, zName, flags, pResOut u
return _OK
}
func vfsOpen(ctx context.Context, mod api.Module, vfs, zName, file, flags, pOutFlags uint32) uint32 {
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zName, pFile, flags, pOutFlags uint32) uint32 {
name := getString(mod.Memory(), zName, _MAX_PATHNAME)
c := ctx.Value(connContext{}).(*Conn)
@@ -186,7 +186,7 @@ func vfsOpen(ctx context.Context, mod api.Module, vfs, zName, file, flags, pOutF
return uint32(CANTOPEN)
}
if ok := mod.Memory().WriteUint32Le(file+ptrSize, c.getFile(f)); !ok {
if ok := mod.Memory().WriteUint32Le(pFile+ptrSize, c.getFile(f)); !ok {
panic(rangeErr)
}
if pOutFlags == 0 {
@@ -198,8 +198,8 @@ func vfsOpen(ctx context.Context, mod api.Module, vfs, zName, file, flags, pOutF
return _OK
}
func vfsClose(ctx context.Context, mod api.Module, file uint32) uint32 {
id, ok := mod.Memory().ReadUint32Le(file + ptrSize)
func vfsClose(ctx context.Context, mod api.Module, pFile uint32) uint32 {
id, ok := mod.Memory().ReadUint32Le(pFile + ptrSize)
if !ok {
panic(rangeErr)
}
@@ -213,8 +213,8 @@ func vfsClose(ctx context.Context, mod api.Module, file uint32) uint32 {
return _OK
}
func vfsFile(ctx context.Context, mod api.Module, file uint32) *os.File {
id, ok := mod.Memory().ReadUint32Le(file + ptrSize)
func vfsFile(ctx context.Context, mod api.Module, pFile uint32) *os.File {
id, ok := mod.Memory().ReadUint32Le(pFile + ptrSize)
if !ok {
panic(rangeErr)
}
@@ -223,14 +223,14 @@ func vfsFile(ctx context.Context, mod api.Module, file uint32) *os.File {
return c.files[id]
}
func vfsRead(ctx context.Context, mod api.Module, file, buf, iAmt uint32, iOfst uint64) uint32 {
mem, ok := mod.Memory().Read(buf, iAmt)
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst uint64) uint32 {
mem, ok := mod.Memory().Read(zBuf, iAmt)
if !ok {
panic(rangeErr)
}
f := vfsFile(ctx, mod, file)
n, err := f.ReadAt(mem, int64(iOfst))
file := vfsFile(ctx, mod, pFile)
n, err := file.ReadAt(mem, int64(iOfst))
if n == int(iAmt) {
return _OK
}
@@ -243,41 +243,41 @@ func vfsRead(ctx context.Context, mod api.Module, file, buf, iAmt uint32, iOfst
return uint32(IOERR_SHORT_READ)
}
func vfsWrite(ctx context.Context, mod api.Module, file, buf, iAmt uint32, iOfst uint64) uint32 {
mem, ok := mod.Memory().Read(buf, iAmt)
func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst uint64) uint32 {
mem, ok := mod.Memory().Read(zBuf, iAmt)
if !ok {
panic(rangeErr)
}
f := vfsFile(ctx, mod, file)
_, err := f.WriteAt(mem, int64(iOfst))
file := vfsFile(ctx, mod, pFile)
_, err := file.WriteAt(mem, int64(iOfst))
if err != nil {
return uint32(IOERR_WRITE)
}
return _OK
}
func vfsTruncate(ctx context.Context, mod api.Module, file uint32, size uint64) uint32 {
f := vfsFile(ctx, mod, file)
err := f.Truncate(int64(size))
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte uint64) uint32 {
file := vfsFile(ctx, mod, pFile)
err := file.Truncate(int64(nByte))
if err != nil {
return uint32(IOERR_TRUNCATE)
}
return _OK
}
func vfsSync(ctx context.Context, mod api.Module, file, flags uint32) uint32 {
f := vfsFile(ctx, mod, file)
err := f.Sync()
func vfsSync(ctx context.Context, mod api.Module, pFile, flags uint32) uint32 {
file := vfsFile(ctx, mod, pFile)
err := file.Sync()
if err != nil {
return uint32(IOERR_FSYNC)
}
return _OK
}
func vfsFileSize(ctx context.Context, mod api.Module, file, pSize uint32) uint32 {
f := vfsFile(ctx, mod, file)
off, err := f.Seek(0, io.SeekEnd)
func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize uint32) uint32 {
file := vfsFile(ctx, mod, pFile)
off, err := file.Seek(0, io.SeekEnd)
if err != nil {
return uint32(IOERR_SEEK)
}