Refactor VFS.

This commit is contained in:
Nuno Cruces
2023-05-19 03:04:07 +01:00
parent 66effb4249
commit 4e2ce6c635
35 changed files with 243 additions and 335 deletions

View File

@@ -19,7 +19,7 @@ embeds a build of SQLite into your application.
### Caveats
This module replaces the SQLite [OS Interface](https://www.sqlite.org/vfs.html) (aka VFS)
with a [pure Go](internal/vfs/) implementation.
with a [pure Go](sqlite3vfs/) implementation.
This has numerous benefits, but also comes with some drawbacks.
#### Write-Ahead Logging

View File

@@ -1,170 +0,0 @@
package vfs
import (
"github.com/ncruces/go-sqlite3/internal/util"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
)
const (
_MAX_STRING = 512 // Used for short strings: names, error messages…
_MAX_PATHNAME = 512
_DEFAULT_SECTOR_SIZE = 4096
)
// https://www.sqlite.org/rescode.html
type _ErrorCode uint32
func (e _ErrorCode) Error() string {
return util.ErrorCodeString(uint32(e))
}
const (
_OK _ErrorCode = util.OK
_PERM _ErrorCode = util.PERM
_BUSY _ErrorCode = util.BUSY
_IOERR _ErrorCode = util.IOERR
_NOTFOUND _ErrorCode = util.NOTFOUND
_CANTOPEN _ErrorCode = util.CANTOPEN
_IOERR_READ _ErrorCode = util.IOERR_READ
_IOERR_SHORT_READ _ErrorCode = util.IOERR_SHORT_READ
_IOERR_WRITE _ErrorCode = util.IOERR_WRITE
_IOERR_FSYNC _ErrorCode = util.IOERR_FSYNC
_IOERR_DIR_FSYNC _ErrorCode = util.IOERR_DIR_FSYNC
_IOERR_TRUNCATE _ErrorCode = util.IOERR_TRUNCATE
_IOERR_FSTAT _ErrorCode = util.IOERR_FSTAT
_IOERR_UNLOCK _ErrorCode = util.IOERR_UNLOCK
_IOERR_RDLOCK _ErrorCode = util.IOERR_RDLOCK
_IOERR_DELETE _ErrorCode = util.IOERR_DELETE
_IOERR_ACCESS _ErrorCode = util.IOERR_ACCESS
_IOERR_CHECKRESERVEDLOCK _ErrorCode = util.IOERR_CHECKRESERVEDLOCK
_IOERR_LOCK _ErrorCode = util.IOERR_LOCK
_IOERR_CLOSE _ErrorCode = util.IOERR_CLOSE
_IOERR_SEEK _ErrorCode = util.IOERR_SEEK
_IOERR_DELETE_NOENT _ErrorCode = util.IOERR_DELETE_NOENT
_CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH
_OK_SYMLINK _ErrorCode = util.OK_SYMLINK
)
// https://www.sqlite.org/c3ref/c_open_autoproxy.html
type _OpenFlag = sqlite3vfs.OpenFlag
const (
_OPEN_READONLY = sqlite3vfs.OPEN_READONLY
_OPEN_READWRITE = sqlite3vfs.OPEN_READWRITE
_OPEN_CREATE = sqlite3vfs.OPEN_CREATE
_OPEN_DELETEONCLOSE = sqlite3vfs.OPEN_DELETEONCLOSE
_OPEN_EXCLUSIVE = sqlite3vfs.OPEN_EXCLUSIVE
_OPEN_AUTOPROXY = sqlite3vfs.OPEN_AUTOPROXY
_OPEN_URI = sqlite3vfs.OPEN_URI
_OPEN_MEMORY = sqlite3vfs.OPEN_MEMORY
_OPEN_MAIN_DB = sqlite3vfs.OPEN_MAIN_DB
_OPEN_TEMP_DB = sqlite3vfs.OPEN_TEMP_DB
_OPEN_TRANSIENT_DB = sqlite3vfs.OPEN_TRANSIENT_DB
_OPEN_MAIN_JOURNAL = sqlite3vfs.OPEN_MAIN_JOURNAL
_OPEN_TEMP_JOURNAL = sqlite3vfs.OPEN_TEMP_JOURNAL
_OPEN_SUBJOURNAL = sqlite3vfs.OPEN_SUBJOURNAL
_OPEN_SUPER_JOURNAL = sqlite3vfs.OPEN_SUPER_JOURNAL
_OPEN_NOMUTEX = sqlite3vfs.OPEN_NOMUTEX
_OPEN_FULLMUTEX = sqlite3vfs.OPEN_FULLMUTEX
_OPEN_SHAREDCACHE = sqlite3vfs.OPEN_SHAREDCACHE
_OPEN_PRIVATECACHE = sqlite3vfs.OPEN_PRIVATECACHE
_OPEN_WAL = sqlite3vfs.OPEN_WAL
_OPEN_NOFOLLOW = sqlite3vfs.OPEN_NOFOLLOW
)
// https://www.sqlite.org/c3ref/c_access_exists.html
type _AccessFlag = sqlite3vfs.AccessFlag
const (
_ACCESS_EXISTS = sqlite3vfs.ACCESS_EXISTS
_ACCESS_READWRITE = sqlite3vfs.ACCESS_READWRITE
_ACCESS_READ = sqlite3vfs.ACCESS_READ
)
// https://www.sqlite.org/c3ref/c_sync_dataonly.html
type _SyncFlag = sqlite3vfs.SyncFlag
const (
_SYNC_NORMAL = sqlite3vfs.SYNC_NORMAL
_SYNC_FULL = sqlite3vfs.SYNC_FULL
_SYNC_DATAONLY = sqlite3vfs.SYNC_DATAONLY
)
// https://www.sqlite.org/c3ref/c_lock_exclusive.html
type _LockLevel = sqlite3vfs.LockLevel
const (
_LOCK_NONE = sqlite3vfs.LOCK_NONE
_LOCK_SHARED = sqlite3vfs.LOCK_SHARED
_LOCK_RESERVED = sqlite3vfs.LOCK_RESERVED
_LOCK_PENDING = sqlite3vfs.LOCK_PENDING
_LOCK_EXCLUSIVE = sqlite3vfs.LOCK_EXCLUSIVE
)
// https://www.sqlite.org/c3ref/c_iocap_atomic.html
type _DeviceCharacteristic = sqlite3vfs.DeviceCharacteristic
const (
_IOCAP_ATOMIC = sqlite3vfs.IOCAP_ATOMIC
_IOCAP_ATOMIC512 = sqlite3vfs.IOCAP_ATOMIC512
_IOCAP_ATOMIC1K = sqlite3vfs.IOCAP_ATOMIC1K
_IOCAP_ATOMIC2K = sqlite3vfs.IOCAP_ATOMIC2K
_IOCAP_ATOMIC4K = sqlite3vfs.IOCAP_ATOMIC4K
_IOCAP_ATOMIC8K = sqlite3vfs.IOCAP_ATOMIC8K
_IOCAP_ATOMIC16K = sqlite3vfs.IOCAP_ATOMIC16K
_IOCAP_ATOMIC32K = sqlite3vfs.IOCAP_ATOMIC32K
_IOCAP_ATOMIC64K = sqlite3vfs.IOCAP_ATOMIC64K
_IOCAP_SAFE_APPEND = sqlite3vfs.IOCAP_SAFE_APPEND
_IOCAP_SEQUENTIAL = sqlite3vfs.IOCAP_SEQUENTIAL
_IOCAP_UNDELETABLE_WHEN_OPEN = sqlite3vfs.IOCAP_UNDELETABLE_WHEN_OPEN
_IOCAP_POWERSAFE_OVERWRITE = sqlite3vfs.IOCAP_POWERSAFE_OVERWRITE
_IOCAP_IMMUTABLE = sqlite3vfs.IOCAP_IMMUTABLE
_IOCAP_BATCH_ATOMIC = sqlite3vfs.IOCAP_BATCH_ATOMIC
)
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
type _FcntlOpcode uint32
const (
_FCNTL_LOCKSTATE _FcntlOpcode = 1
_FCNTL_GET_LOCKPROXYFILE _FcntlOpcode = 2
_FCNTL_SET_LOCKPROXYFILE _FcntlOpcode = 3
_FCNTL_LAST_ERRNO _FcntlOpcode = 4
_FCNTL_SIZE_HINT _FcntlOpcode = 5
_FCNTL_CHUNK_SIZE _FcntlOpcode = 6
_FCNTL_FILE_POINTER _FcntlOpcode = 7
_FCNTL_SYNC_OMITTED _FcntlOpcode = 8
_FCNTL_WIN32_AV_RETRY _FcntlOpcode = 9
_FCNTL_PERSIST_WAL _FcntlOpcode = 10
_FCNTL_OVERWRITE _FcntlOpcode = 11
_FCNTL_VFSNAME _FcntlOpcode = 12
_FCNTL_POWERSAFE_OVERWRITE _FcntlOpcode = 13
_FCNTL_PRAGMA _FcntlOpcode = 14
_FCNTL_BUSYHANDLER _FcntlOpcode = 15
_FCNTL_TEMPFILENAME _FcntlOpcode = 16
_FCNTL_MMAP_SIZE _FcntlOpcode = 18
_FCNTL_TRACE _FcntlOpcode = 19
_FCNTL_HAS_MOVED _FcntlOpcode = 20
_FCNTL_SYNC _FcntlOpcode = 21
_FCNTL_COMMIT_PHASETWO _FcntlOpcode = 22
_FCNTL_WIN32_SET_HANDLE _FcntlOpcode = 23
_FCNTL_WAL_BLOCK _FcntlOpcode = 24
_FCNTL_ZIPVFS _FcntlOpcode = 25
_FCNTL_RBU _FcntlOpcode = 26
_FCNTL_VFS_POINTER _FcntlOpcode = 27
_FCNTL_JOURNAL_POINTER _FcntlOpcode = 28
_FCNTL_WIN32_GET_HANDLE _FcntlOpcode = 29
_FCNTL_PDB _FcntlOpcode = 30
_FCNTL_BEGIN_ATOMIC_WRITE _FcntlOpcode = 31
_FCNTL_COMMIT_ATOMIC_WRITE _FcntlOpcode = 32
_FCNTL_ROLLBACK_ATOMIC_WRITE _FcntlOpcode = 33
_FCNTL_LOCK_TIMEOUT _FcntlOpcode = 34
_FCNTL_DATA_VERSION _FcntlOpcode = 35
_FCNTL_SIZE_LIMIT _FcntlOpcode = 36
_FCNTL_CKPT_DONE _FcntlOpcode = 37
_FCNTL_RESERVE_BYTES _FcntlOpcode = 38
_FCNTL_CKPT_START _FcntlOpcode = 39
_FCNTL_EXTERNAL_READER _FcntlOpcode = 40
_FCNTL_CKSM_FILE _FcntlOpcode = 41
_FCNTL_RESET_CACHE _FcntlOpcode = 42
)

View File

@@ -1,30 +0,0 @@
package vfs
import (
"reflect"
"github.com/ncruces/go-sqlite3/internal/util"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
"github.com/tetratelabs/wazero/api"
)
func vfsAPIGet(mod api.Module, pVfs uint32) sqlite3vfs.VFS {
if pVfs != 0 {
name := util.ReadString(mod, util.ReadUint32(mod, pVfs+16), _MAX_STRING)
if vfs := sqlite3vfs.Find(name); vfs != nil {
return vfs
}
}
return vfsOS{}
}
func vfsAPIErrorCode(err error, def _ErrorCode) _ErrorCode {
if err == nil {
return _OK
}
switch v := reflect.ValueOf(err); v.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
return _ErrorCode(v.Uint())
}
return def
}

View File

@@ -9,7 +9,7 @@ import (
"sync"
"github.com/ncruces/go-sqlite3/internal/util"
"github.com/ncruces/go-sqlite3/internal/vfs"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
)
@@ -53,7 +53,7 @@ func compileModule() {
ctx := context.Background()
sqlite3.runtime = wazero.NewRuntime(ctx)
env := vfs.Export(sqlite3.runtime.NewHostModuleBuilder("env"))
env := sqlite3vfs.ExportHostFunctions(sqlite3.runtime.NewHostModuleBuilder("env"))
_, sqlite3.err = env.Instantiate(ctx)
if sqlite3.err != nil {
return
@@ -85,7 +85,7 @@ type module struct {
func newModule(mod api.Module) (m *module, err error) {
m = &module{}
m.mod = mod
m.ctx, m.vfs = vfs.Context(context.Background())
m.ctx, m.vfs = sqlite3vfs.NewContext(context.Background())
getFun := func(name string) api.Function {
f := mod.ExportedFunction(name)

View File

@@ -17,7 +17,7 @@ curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/regexp.c
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/series.c"
cd ~-
cd ../internal/vfs/tests/mptest/testdata/
cd ../sqlite3vfs/tests/mptest/testdata/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/mptest/mptest.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/mptest/config01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/mptest/config02.test"
@@ -26,6 +26,6 @@ curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/mptest/crash02.su
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/mptest/multiwrite01.test"
cd ~-
cd ../internal/vfs/tests/speedtest1/testdata/
cd ../sqlite3vfs/tests/speedtest1/testdata/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/test/speedtest1.c"
cd ~-

View File

@@ -1,5 +1,47 @@
package sqlite3vfs
import "github.com/ncruces/go-sqlite3/internal/util"
const (
_MAX_STRING = 512 // Used for short strings: names, error messages…
_MAX_PATHNAME = 512
_DEFAULT_SECTOR_SIZE = 4096
)
// https://www.sqlite.org/rescode.html
type _ErrorCode uint32
func (e _ErrorCode) Error() string {
return util.ErrorCodeString(uint32(e))
}
const (
_OK _ErrorCode = util.OK
_PERM _ErrorCode = util.PERM
_BUSY _ErrorCode = util.BUSY
_IOERR _ErrorCode = util.IOERR
_NOTFOUND _ErrorCode = util.NOTFOUND
_CANTOPEN _ErrorCode = util.CANTOPEN
_IOERR_READ _ErrorCode = util.IOERR_READ
_IOERR_SHORT_READ _ErrorCode = util.IOERR_SHORT_READ
_IOERR_WRITE _ErrorCode = util.IOERR_WRITE
_IOERR_FSYNC _ErrorCode = util.IOERR_FSYNC
_IOERR_DIR_FSYNC _ErrorCode = util.IOERR_DIR_FSYNC
_IOERR_TRUNCATE _ErrorCode = util.IOERR_TRUNCATE
_IOERR_FSTAT _ErrorCode = util.IOERR_FSTAT
_IOERR_UNLOCK _ErrorCode = util.IOERR_UNLOCK
_IOERR_RDLOCK _ErrorCode = util.IOERR_RDLOCK
_IOERR_DELETE _ErrorCode = util.IOERR_DELETE
_IOERR_ACCESS _ErrorCode = util.IOERR_ACCESS
_IOERR_CHECKRESERVEDLOCK _ErrorCode = util.IOERR_CHECKRESERVEDLOCK
_IOERR_LOCK _ErrorCode = util.IOERR_LOCK
_IOERR_CLOSE _ErrorCode = util.IOERR_CLOSE
_IOERR_SEEK _ErrorCode = util.IOERR_SEEK
_IOERR_DELETE_NOENT _ErrorCode = util.IOERR_DELETE_NOENT
_CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH
_OK_SYMLINK _ErrorCode = util.OK_SYMLINK
)
// OpenFlag is a flag for the [VFS.Open] method.
//
// https://www.sqlite.org/c3ref/c_open_autoproxy.html
@@ -119,3 +161,50 @@ const (
IOCAP_IMMUTABLE DeviceCharacteristic = 0x00002000
IOCAP_BATCH_ATOMIC DeviceCharacteristic = 0x00004000
)
// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
type _FcntlOpcode uint32
const (
_FCNTL_LOCKSTATE _FcntlOpcode = 1
_FCNTL_GET_LOCKPROXYFILE _FcntlOpcode = 2
_FCNTL_SET_LOCKPROXYFILE _FcntlOpcode = 3
_FCNTL_LAST_ERRNO _FcntlOpcode = 4
_FCNTL_SIZE_HINT _FcntlOpcode = 5
_FCNTL_CHUNK_SIZE _FcntlOpcode = 6
_FCNTL_FILE_POINTER _FcntlOpcode = 7
_FCNTL_SYNC_OMITTED _FcntlOpcode = 8
_FCNTL_WIN32_AV_RETRY _FcntlOpcode = 9
_FCNTL_PERSIST_WAL _FcntlOpcode = 10
_FCNTL_OVERWRITE _FcntlOpcode = 11
_FCNTL_VFSNAME _FcntlOpcode = 12
_FCNTL_POWERSAFE_OVERWRITE _FcntlOpcode = 13
_FCNTL_PRAGMA _FcntlOpcode = 14
_FCNTL_BUSYHANDLER _FcntlOpcode = 15
_FCNTL_TEMPFILENAME _FcntlOpcode = 16
_FCNTL_MMAP_SIZE _FcntlOpcode = 18
_FCNTL_TRACE _FcntlOpcode = 19
_FCNTL_HAS_MOVED _FcntlOpcode = 20
_FCNTL_SYNC _FcntlOpcode = 21
_FCNTL_COMMIT_PHASETWO _FcntlOpcode = 22
_FCNTL_WIN32_SET_HANDLE _FcntlOpcode = 23
_FCNTL_WAL_BLOCK _FcntlOpcode = 24
_FCNTL_ZIPVFS _FcntlOpcode = 25
_FCNTL_RBU _FcntlOpcode = 26
_FCNTL_VFS_POINTER _FcntlOpcode = 27
_FCNTL_JOURNAL_POINTER _FcntlOpcode = 28
_FCNTL_WIN32_GET_HANDLE _FcntlOpcode = 29
_FCNTL_PDB _FcntlOpcode = 30
_FCNTL_BEGIN_ATOMIC_WRITE _FcntlOpcode = 31
_FCNTL_COMMIT_ATOMIC_WRITE _FcntlOpcode = 32
_FCNTL_ROLLBACK_ATOMIC_WRITE _FcntlOpcode = 33
_FCNTL_LOCK_TIMEOUT _FcntlOpcode = 34
_FCNTL_DATA_VERSION _FcntlOpcode = 35
_FCNTL_SIZE_LIMIT _FcntlOpcode = 36
_FCNTL_CKPT_DONE _FcntlOpcode = 37
_FCNTL_RESERVE_BYTES _FcntlOpcode = 38
_FCNTL_CKPT_START _FcntlOpcode = 39
_FCNTL_EXTERNAL_READER _FcntlOpcode = 40
_FCNTL_CKSM_FILE _FcntlOpcode = 41
_FCNTL_RESET_CACHE _FcntlOpcode = 42
)

View File

@@ -16,11 +16,10 @@ import (
"sync/atomic"
"testing"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/ncruces/go-sqlite3/internal/vfs"
)
//go:embed testdata/mptest.wasm
@@ -41,7 +40,7 @@ func init() {
rt = wazero.NewRuntime(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, rt)
env := vfs.Export(rt.NewHostModuleBuilder("env"))
env := sqlite3vfs.ExportHostFunctions(rt.NewHostModuleBuilder("env"))
env.NewFunctionBuilder().WithFunc(system).Export("system")
_, err := env.Instantiate(ctx)
if err != nil {
@@ -81,23 +80,24 @@ func system(ctx context.Context, mod api.Module, ptr uint32) uint32 {
cfg := config(ctx).WithArgs(args...)
go func() {
ctx, vfs := vfs.Context(ctx)
rt.InstantiateModule(ctx, module, cfg)
ctx, vfs := sqlite3vfs.NewContext(ctx)
mod, _ := rt.InstantiateModule(ctx, module, cfg)
mod.Close(ctx)
vfs.Close()
}()
return 0
}
func Test_config01(t *testing.T) {
ctx, vfs := vfs.Context(newContext(t))
ctx, vfs := sqlite3vfs.NewContext(newContext(t))
name := filepath.Join(t.TempDir(), "test.db")
cfg := config(ctx).WithArgs("mptest", name, "config01.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
}
vfs.Close()
mod.Close(ctx)
vfs.Close()
}
func Test_config02(t *testing.T) {
@@ -108,15 +108,15 @@ func Test_config02(t *testing.T) {
t.Skip("skipping in CI")
}
ctx, vfs := vfs.Context(newContext(t))
ctx, vfs := sqlite3vfs.NewContext(newContext(t))
name := filepath.Join(t.TempDir(), "test.db")
cfg := config(ctx).WithArgs("mptest", name, "config02.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
}
vfs.Close()
mod.Close(ctx)
vfs.Close()
}
func Test_crash01(t *testing.T) {
@@ -124,15 +124,15 @@ func Test_crash01(t *testing.T) {
t.Skip("skipping in short mode")
}
ctx, vfs := vfs.Context(newContext(t))
ctx, vfs := sqlite3vfs.NewContext(newContext(t))
name := filepath.Join(t.TempDir(), "test.db")
cfg := config(ctx).WithArgs("mptest", name, "crash01.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
}
vfs.Close()
mod.Close(ctx)
vfs.Close()
}
func Test_multiwrite01(t *testing.T) {
@@ -140,15 +140,15 @@ func Test_multiwrite01(t *testing.T) {
t.Skip("skipping in short mode")
}
ctx, vfs := vfs.Context(newContext(t))
ctx, vfs := sqlite3vfs.NewContext(newContext(t))
name := filepath.Join(t.TempDir(), "test.db")
cfg := config(ctx).WithArgs("mptest", name, "multiwrite01.test")
mod, err := rt.InstantiateModule(ctx, module, cfg)
if err != nil {
t.Error(err)
}
vfs.Close()
mod.Close(ctx)
vfs.Close()
}
func newContext(t *testing.T) context.Context {

View File

@@ -3,7 +3,7 @@ set -euo pipefail
cd -P -- "$(dirname -- "$0")"
ROOT=../../../../../
ROOT=../../../../
BINARYEN="$ROOT/tools/binaryen-version_112/bin"
WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin"

View File

@@ -17,7 +17,7 @@ import (
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/ncruces/go-sqlite3/internal/vfs"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
)
//go:embed testdata/speedtest1.wasm
@@ -35,7 +35,7 @@ func init() {
rt = wazero.NewRuntime(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, rt)
env := vfs.Export(rt.NewHostModuleBuilder("env"))
env := sqlite3vfs.ExportHostFunctions(rt.NewHostModuleBuilder("env"))
_, err := env.Instantiate(ctx)
if err != nil {
panic(err)
@@ -67,7 +67,7 @@ func TestMain(m *testing.M) {
func Benchmark_speedtest1(b *testing.B) {
output.Reset()
ctx, vfs := vfs.Context(context.Background())
ctx, vfs := sqlite3vfs.NewContext(context.Background())
name := filepath.Join(b.TempDir(), "test.db")
args := append(options, "--size", strconv.Itoa(b.N), name)
cfg := wazero.NewModuleConfig().
@@ -80,6 +80,6 @@ func Benchmark_speedtest1(b *testing.B) {
if err != nil {
b.Error(err)
}
vfs.Close()
mod.Close(ctx)
vfs.Close()
}

View File

@@ -3,7 +3,7 @@ set -euo pipefail
cd -P -- "$(dirname -- "$0")"
ROOT=../../../../../
ROOT=../../../../
BINARYEN="$ROOT/tools/binaryen-version_112/bin"
WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin"

View File

@@ -1,19 +1,19 @@
package vfs
package sqlite3vfs
import (
"context"
"crypto/rand"
"io"
"reflect"
"time"
"github.com/ncruces/go-sqlite3/internal/util"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
"github.com/ncruces/julianday"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
)
func Export(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
func ExportHostFunctions(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
util.RegisterFuncII(env, "go_vfs_find", vfsFind)
util.RegisterFuncIIJ(env, "go_localtime", vfsLocaltime)
util.RegisterFuncIIII(env, "go_randomness", vfsRandomness)
@@ -41,10 +41,10 @@ func Export(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
type vfsKey struct{}
type vfsState struct {
files []sqlite3vfs.File
files []File
}
func Context(ctx context.Context) (context.Context, io.Closer) {
func NewContext(ctx context.Context) (context.Context, io.Closer) {
vfs := &vfsState{}
return context.WithValue(ctx, vfsKey{}, vfs), vfs
}
@@ -61,7 +61,7 @@ func (vfs *vfsState) Close() error {
func vfsFind(ctx context.Context, mod api.Module, zVfsName uint32) uint32 {
name := util.ReadString(mod, zVfsName, _MAX_STRING)
if sqlite3vfs.Find(name) != nil {
if Find(name) != nil {
return 1
}
return 0
@@ -137,7 +137,7 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32)
return vfsAPIErrorCode(err, _IOERR_DELETE)
}
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags _AccessFlag, pResOut uint32) _ErrorCode {
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags AccessFlag, pResOut uint32) _ErrorCode {
vfs := vfsAPIGet(mod, pVfs)
path := util.ReadString(mod, zPath, _MAX_PATHNAME)
@@ -151,7 +151,7 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags _A
return vfsAPIErrorCode(err, _IOERR_ACCESS)
}
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, flags _OpenFlag, pOutFlags uint32) _ErrorCode {
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, flags OpenFlag, pOutFlags uint32) _ErrorCode {
vfs := vfsAPIGet(mod, pVfs)
var path string
@@ -213,7 +213,7 @@ func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte int64)
return vfsAPIErrorCode(err, _IOERR_TRUNCATE)
}
func vfsSync(ctx context.Context, mod api.Module, pFile uint32, flags _SyncFlag) _ErrorCode {
func vfsSync(ctx context.Context, mod api.Module, pFile uint32, flags SyncFlag) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile)
err := file.Sync(flags)
return vfsAPIErrorCode(err, _IOERR_FSYNC)
@@ -226,13 +226,13 @@ func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize uint32) _Erro
return vfsAPIErrorCode(err, _IOERR_SEEK)
}
func vfsLock(ctx context.Context, mod api.Module, pFile uint32, eLock _LockLevel) _ErrorCode {
func vfsLock(ctx context.Context, mod api.Module, pFile uint32, eLock LockLevel) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile)
err := file.Lock(eLock)
return vfsAPIErrorCode(err, _IOERR_LOCK)
}
func vfsUnlock(ctx context.Context, mod api.Module, pFile uint32, eLock _LockLevel) _ErrorCode {
func vfsUnlock(ctx context.Context, mod api.Module, pFile uint32, eLock LockLevel) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile)
err := file.Unlock(eLock)
return vfsAPIErrorCode(err, _IOERR_UNLOCK)
@@ -256,7 +256,7 @@ func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _Fcntl
switch op {
case _FCNTL_LOCKSTATE:
if file, ok := file.(sqlite3vfs.FileLockState); ok {
if file, ok := file.(FileLockState); ok {
util.WriteUint32(mod, pArg, uint32(file.LockState()))
return _OK
}
@@ -270,7 +270,7 @@ func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _Fcntl
}
case _FCNTL_POWERSAFE_OVERWRITE:
if file, ok := file.(sqlite3vfs.FilePowersafeOverwrite); ok {
if file, ok := file.(FilePowersafeOverwrite); ok {
switch util.ReadUint32(mod, pArg) {
case 0:
file.SetPowersafeOverwrite(false)
@@ -287,14 +287,14 @@ func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _Fcntl
}
case _FCNTL_SIZE_HINT:
if file, ok := file.(sqlite3vfs.FileSizeHint); ok {
if file, ok := file.(FileSizeHint); ok {
size := util.ReadUint64(mod, pArg)
err := file.SizeHint(int64(size))
return vfsAPIErrorCode(err, _IOERR_TRUNCATE)
}
case _FCNTL_HAS_MOVED:
if file, ok := file.(sqlite3vfs.FileHasMoved); ok {
if file, ok := file.(FileHasMoved); ok {
moved, err := file.HasMoved()
var res uint32
@@ -321,7 +321,28 @@ func vfsSectorSize(ctx context.Context, mod api.Module, pFile uint32) uint32 {
return uint32(file.SectorSize())
}
func vfsDeviceCharacteristics(ctx context.Context, mod api.Module, pFile uint32) _DeviceCharacteristic {
func vfsDeviceCharacteristics(ctx context.Context, mod api.Module, pFile uint32) DeviceCharacteristic {
file := vfsFileGet(ctx, mod, pFile)
return file.DeviceCharacteristics()
}
func vfsAPIGet(mod api.Module, pVfs uint32) VFS {
if pVfs != 0 {
name := util.ReadString(mod, util.ReadUint32(mod, pVfs+16), _MAX_STRING)
if vfs := Find(name); vfs != nil {
return vfs
}
}
return vfsOS{}
}
func vfsAPIErrorCode(err error, def _ErrorCode) _ErrorCode {
if err == nil {
return _OK
}
switch v := reflect.ValueOf(err); v.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
return _ErrorCode(v.Uint())
}
return def
}

View File

@@ -1,4 +1,4 @@
package vfs
package sqlite3vfs
import (
"context"
@@ -11,7 +11,6 @@ import (
"time"
"github.com/ncruces/go-sqlite3/internal/util"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
"github.com/tetratelabs/wazero/api"
)
@@ -57,9 +56,9 @@ func (vfsOS) Delete(path string, syncDir bool) error {
return nil
}
func (vfsOS) Access(name string, flags sqlite3vfs.AccessFlag) (bool, error) {
func (vfsOS) Access(name string, flags AccessFlag) (bool, error) {
err := osAccess(name, flags)
if flags == _ACCESS_EXISTS {
if flags == ACCESS_EXISTS {
if errors.Is(err, fs.ErrNotExist) {
return false, nil
}
@@ -71,18 +70,18 @@ func (vfsOS) Access(name string, flags sqlite3vfs.AccessFlag) (bool, error) {
return err == nil, err
}
func (vfsOS) Open(name string, flags sqlite3vfs.OpenFlag) (sqlite3vfs.File, sqlite3vfs.OpenFlag, error) {
func (vfsOS) Open(name string, flags OpenFlag) (File, OpenFlag, error) {
var oflags int
if flags&_OPEN_EXCLUSIVE != 0 {
if flags&OPEN_EXCLUSIVE != 0 {
oflags |= os.O_EXCL
}
if flags&_OPEN_CREATE != 0 {
if flags&OPEN_CREATE != 0 {
oflags |= os.O_CREATE
}
if flags&_OPEN_READONLY != 0 {
if flags&OPEN_READONLY != 0 {
oflags |= os.O_RDONLY
}
if flags&_OPEN_READWRITE != 0 {
if flags&OPEN_READWRITE != 0 {
oflags |= os.O_RDWR
}
@@ -97,17 +96,17 @@ func (vfsOS) Open(name string, flags sqlite3vfs.OpenFlag) (sqlite3vfs.File, sqli
return nil, flags, err
}
if flags&_OPEN_DELETEONCLOSE != 0 {
if flags&OPEN_DELETEONCLOSE != 0 {
os.Remove(f.Name())
}
file := vfsFile{
File: f,
psow: true,
readOnly: flags&_OPEN_READONLY != 0,
readOnly: flags&OPEN_READONLY != 0,
syncDir: runtime.GOOS != "windows" &&
flags&(_OPEN_CREATE) != 0 &&
flags&(_OPEN_MAIN_JOURNAL|_OPEN_SUPER_JOURNAL|_OPEN_WAL) != 0,
flags&(OPEN_CREATE) != 0 &&
flags&(OPEN_MAIN_JOURNAL|OPEN_SUPER_JOURNAL|OPEN_WAL) != 0,
}
return &file, flags, nil
}
@@ -115,7 +114,7 @@ func (vfsOS) Open(name string, flags sqlite3vfs.OpenFlag) (sqlite3vfs.File, sqli
type vfsFile struct {
*os.File
lockTimeout time.Duration
lock _LockLevel
lock LockLevel
psow bool
syncDir bool
readOnly bool
@@ -123,13 +122,13 @@ type vfsFile struct {
var (
// Ensure these interfaces are implemented:
_ sqlite3vfs.FileLockState = &vfsFile{}
_ sqlite3vfs.FileHasMoved = &vfsFile{}
_ sqlite3vfs.FileSizeHint = &vfsFile{}
_ sqlite3vfs.FilePowersafeOverwrite = &vfsFile{}
_ FileLockState = &vfsFile{}
_ FileHasMoved = &vfsFile{}
_ FileSizeHint = &vfsFile{}
_ FilePowersafeOverwrite = &vfsFile{}
)
func vfsFileNew(vfs *vfsState, file sqlite3vfs.File) uint32 {
func vfsFileNew(vfs *vfsState, file File) uint32 {
// Find an empty slot.
for id, f := range vfs.files {
if f == nil {
@@ -143,12 +142,12 @@ func vfsFileNew(vfs *vfsState, file sqlite3vfs.File) uint32 {
return uint32(len(vfs.files) - 1)
}
func vfsFileRegister(ctx context.Context, mod api.Module, pFile uint32, file sqlite3vfs.File) {
func vfsFileRegister(ctx context.Context, mod api.Module, pFile uint32, file File) {
id := vfsFileNew(ctx.Value(vfsKey{}).(*vfsState), file)
util.WriteUint32(mod, pFile+4, id)
}
func vfsFileGet(ctx context.Context, mod api.Module, pFile uint32) sqlite3vfs.File {
func vfsFileGet(ctx context.Context, mod api.Module, pFile uint32) File {
vfs := ctx.Value(vfsKey{}).(*vfsState)
id := util.ReadUint32(mod, pFile+4)
return vfs.files[id]
@@ -162,9 +161,9 @@ func vfsFileClose(ctx context.Context, mod api.Module, pFile uint32) error {
return file.Close()
}
func (f *vfsFile) Sync(flags sqlite3vfs.SyncFlag) error {
dataonly := (flags & _SYNC_DATAONLY) != 0
fullsync := (flags & 0x0f) == _SYNC_FULL
func (f *vfsFile) Sync(flags SyncFlag) error {
dataonly := (flags & SYNC_DATAONLY) != 0
fullsync := (flags & 0x0f) == SYNC_FULL
err := osSync(f.File, fullsync, dataonly)
if err != nil {
@@ -193,9 +192,9 @@ func (*vfsFile) SectorSize() int {
return _DEFAULT_SECTOR_SIZE
}
func (f *vfsFile) DeviceCharacteristics() sqlite3vfs.DeviceCharacteristic {
func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic {
if f.psow {
return _IOCAP_POWERSAFE_OVERWRITE
return IOCAP_POWERSAFE_OVERWRITE
}
return 0
}
@@ -216,6 +215,6 @@ func (f *vfsFile) HasMoved() (bool, error) {
return !os.SameFile(fi, pi), nil
}
func (f *vfsFile) LockState() sqlite3vfs.LockLevel { return f.lock }
func (f *vfsFile) LockState() LockLevel { return f.lock }
func (f *vfsFile) PowersafeOverwrite() bool { return f.psow }
func (f *vfsFile) SetPowersafeOverwrite(psow bool) { f.psow = psow }

View File

@@ -1,11 +1,10 @@
package vfs
package sqlite3vfs
import (
"os"
"time"
"github.com/ncruces/go-sqlite3/internal/util"
"github.com/ncruces/go-sqlite3/sqlite3vfs"
)
const (
@@ -15,20 +14,20 @@ const (
_SHARED_SIZE = 510
)
func (file *vfsFile) Lock(eLock sqlite3vfs.LockLevel) error {
func (file *vfsFile) Lock(eLock LockLevel) error {
// Argument check. SQLite never explicitly requests a pending lock.
if eLock != _LOCK_SHARED && eLock != _LOCK_RESERVED && eLock != _LOCK_EXCLUSIVE {
if eLock != LOCK_SHARED && eLock != LOCK_RESERVED && eLock != LOCK_EXCLUSIVE {
panic(util.AssertErr())
}
switch {
case file.lock < _LOCK_NONE || file.lock > _LOCK_EXCLUSIVE:
case file.lock < LOCK_NONE || file.lock > LOCK_EXCLUSIVE:
// Connection state check.
panic(util.AssertErr())
case file.lock == _LOCK_NONE && eLock > _LOCK_SHARED:
case file.lock == LOCK_NONE && eLock > LOCK_SHARED:
// We never move from unlocked to anything higher than a shared lock.
panic(util.AssertErr())
case file.lock != _LOCK_SHARED && eLock == _LOCK_RESERVED:
case file.lock != LOCK_SHARED && eLock == LOCK_RESERVED:
// A shared lock is always held when a reserved lock is requested.
panic(util.AssertErr())
}
@@ -39,49 +38,49 @@ func (file *vfsFile) Lock(eLock sqlite3vfs.LockLevel) error {
}
// Do not allow any kind of write-lock on a read-only database.
if file.readOnly && eLock >= _LOCK_RESERVED {
if file.readOnly && eLock >= LOCK_RESERVED {
return _IOERR_LOCK
}
switch eLock {
case _LOCK_SHARED:
case LOCK_SHARED:
// Must be unlocked to get SHARED.
if file.lock != _LOCK_NONE {
if file.lock != LOCK_NONE {
panic(util.AssertErr())
}
if rc := osGetSharedLock(file.File, file.lockTimeout); rc != _OK {
return rc
}
file.lock = _LOCK_SHARED
file.lock = LOCK_SHARED
return nil
case _LOCK_RESERVED:
case LOCK_RESERVED:
// Must be SHARED to get RESERVED.
if file.lock != _LOCK_SHARED {
if file.lock != LOCK_SHARED {
panic(util.AssertErr())
}
if rc := osGetReservedLock(file.File, file.lockTimeout); rc != _OK {
return rc
}
file.lock = _LOCK_RESERVED
file.lock = LOCK_RESERVED
return nil
case _LOCK_EXCLUSIVE:
case LOCK_EXCLUSIVE:
// Must be SHARED, RESERVED or PENDING to get EXCLUSIVE.
if file.lock <= _LOCK_NONE || file.lock >= _LOCK_EXCLUSIVE {
if file.lock <= LOCK_NONE || file.lock >= LOCK_EXCLUSIVE {
panic(util.AssertErr())
}
// A PENDING lock is needed before acquiring an EXCLUSIVE lock.
if file.lock < _LOCK_PENDING {
if file.lock < LOCK_PENDING {
if rc := osGetPendingLock(file.File); rc != _OK {
return rc
}
file.lock = _LOCK_PENDING
file.lock = LOCK_PENDING
}
if rc := osGetExclusiveLock(file.File, file.lockTimeout); rc != _OK {
return rc
}
file.lock = _LOCK_EXCLUSIVE
file.lock = LOCK_EXCLUSIVE
return nil
default:
@@ -89,14 +88,14 @@ func (file *vfsFile) Lock(eLock sqlite3vfs.LockLevel) error {
}
}
func (file *vfsFile) Unlock(eLock sqlite3vfs.LockLevel) error {
func (file *vfsFile) Unlock(eLock LockLevel) error {
// Argument check.
if eLock != _LOCK_NONE && eLock != _LOCK_SHARED {
if eLock != LOCK_NONE && eLock != LOCK_SHARED {
panic(util.AssertErr())
}
// Connection state check.
if file.lock < _LOCK_NONE || file.lock > _LOCK_EXCLUSIVE {
if file.lock < LOCK_NONE || file.lock > LOCK_EXCLUSIVE {
panic(util.AssertErr())
}
@@ -106,16 +105,16 @@ func (file *vfsFile) Unlock(eLock sqlite3vfs.LockLevel) error {
}
switch eLock {
case _LOCK_SHARED:
case LOCK_SHARED:
if rc := osDowngradeLock(file.File, file.lock); rc != _OK {
return rc
}
file.lock = _LOCK_SHARED
file.lock = LOCK_SHARED
return nil
case _LOCK_NONE:
case LOCK_NONE:
rc := osReleaseLock(file.File, file.lock)
file.lock = _LOCK_NONE
file.lock = LOCK_NONE
return rc
default:
@@ -125,11 +124,11 @@ func (file *vfsFile) Unlock(eLock sqlite3vfs.LockLevel) error {
func (file *vfsFile) CheckReservedLock() (bool, error) {
// Connection state check.
if file.lock < _LOCK_NONE || file.lock > _LOCK_EXCLUSIVE {
if file.lock < LOCK_NONE || file.lock > LOCK_EXCLUSIVE {
panic(util.AssertErr())
}
if file.lock >= _LOCK_RESERVED {
if file.lock >= LOCK_RESERVED {
return true, nil
}
return osCheckReservedLock(file.File)

View File

@@ -1,4 +1,4 @@
package vfs
package sqlite3vfs
import (
"context"
@@ -40,7 +40,7 @@ func Test_vfsLock(t *testing.T) {
pOutput = 32
)
mod := util.NewMockModule(128)
ctx, vfs := Context(context.TODO())
ctx, vfs := NewContext(context.TODO())
defer vfs.Close()
vfsFileRegister(ctx, mod, pFile1, &vfsFile{File: file1})
@@ -61,7 +61,7 @@ func Test_vfsLock(t *testing.T) {
t.Error("file was locked")
}
rc = vfsLock(ctx, mod, pFile2, _LOCK_SHARED)
rc = vfsLock(ctx, mod, pFile2, LOCK_SHARED)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -81,11 +81,11 @@ func Test_vfsLock(t *testing.T) {
t.Error("file was locked")
}
rc = vfsLock(ctx, mod, pFile2, _LOCK_RESERVED)
rc = vfsLock(ctx, mod, pFile2, LOCK_RESERVED)
if rc != _OK {
t.Fatal("returned", rc)
}
rc = vfsLock(ctx, mod, pFile2, _LOCK_SHARED)
rc = vfsLock(ctx, mod, pFile2, LOCK_SHARED)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -105,7 +105,7 @@ func Test_vfsLock(t *testing.T) {
t.Error("file wasn't locked")
}
rc = vfsLock(ctx, mod, pFile2, _LOCK_EXCLUSIVE)
rc = vfsLock(ctx, mod, pFile2, LOCK_EXCLUSIVE)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -125,7 +125,7 @@ func Test_vfsLock(t *testing.T) {
t.Error("file wasn't locked")
}
rc = vfsLock(ctx, mod, pFile1, _LOCK_SHARED)
rc = vfsLock(ctx, mod, pFile1, LOCK_SHARED)
if rc == _OK {
t.Fatal("returned", rc)
}
@@ -145,7 +145,7 @@ func Test_vfsLock(t *testing.T) {
t.Error("file wasn't locked")
}
rc = vfsUnlock(ctx, mod, pFile2, _LOCK_SHARED)
rc = vfsUnlock(ctx, mod, pFile2, LOCK_SHARED)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -165,7 +165,7 @@ func Test_vfsLock(t *testing.T) {
t.Error("file was locked")
}
rc = vfsLock(ctx, mod, pFile1, _LOCK_SHARED)
rc = vfsLock(ctx, mod, pFile1, LOCK_SHARED)
if rc != _OK {
t.Fatal("returned", rc)
}

View File

@@ -1,6 +1,6 @@
//go:build freebsd || openbsd || netbsd || dragonfly || (darwin && sqlite3_bsd)
package vfs
package sqlite3vfs
import (
"os"

View File

@@ -1,6 +1,6 @@
//go:build !sqlite3_bsd
package vfs
package sqlite3vfs
import (
"io"

View File

@@ -1,4 +1,4 @@
package vfs
package sqlite3vfs
import (
"os"

View File

@@ -1,6 +1,6 @@
//go:build linux || illumos
package vfs
package sqlite3vfs
import (
"os"

View File

@@ -1,6 +1,6 @@
//go:build !linux && (!darwin || sqlite3_bsd)
package vfs
package sqlite3vfs
import (
"io"

View File

@@ -1,6 +1,6 @@
//go:build unix
package vfs
package sqlite3vfs
import (
"io/fs"
@@ -14,12 +14,12 @@ func osOpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
return os.OpenFile(name, flag, perm)
}
func osAccess(path string, flags _AccessFlag) error {
func osAccess(path string, flags AccessFlag) error {
var access uint32 // unix.F_OK
switch flags {
case _ACCESS_READWRITE:
case ACCESS_READWRITE:
access = unix.R_OK | unix.W_OK
case _ACCESS_READ:
case ACCESS_READ:
access = unix.R_OK
}
return unix.Access(path, access)
@@ -43,8 +43,8 @@ func osGetExclusiveLock(file *os.File, timeout time.Duration) _ErrorCode {
return osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, timeout)
}
func osDowngradeLock(file *os.File, state _LockLevel) _ErrorCode {
if state >= _LOCK_EXCLUSIVE {
func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
if state >= LOCK_EXCLUSIVE {
// Downgrade to a SHARED lock.
if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK {
// In theory, the downgrade to a SHARED cannot fail because another
@@ -59,7 +59,7 @@ func osDowngradeLock(file *os.File, state _LockLevel) _ErrorCode {
return osUnlock(file, _PENDING_BYTE, 2)
}
func osReleaseLock(file *os.File, _ _LockLevel) _ErrorCode {
func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode {
// Release all locks.
return osUnlock(file, 0, 0)
}

View File

@@ -1,4 +1,4 @@
package vfs
package sqlite3vfs
import (
"io/fs"
@@ -25,17 +25,17 @@ func osOpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
return os.NewFile(uintptr(r), name), nil
}
func osAccess(path string, flags _AccessFlag) error {
func osAccess(path string, flags AccessFlag) error {
fi, err := os.Stat(path)
if err != nil {
return err
}
if flags == _ACCESS_EXISTS {
if flags == ACCESS_EXISTS {
return nil
}
var want fs.FileMode = windows.S_IRUSR
if flags == _ACCESS_READWRITE {
if flags == ACCESS_READWRITE {
want |= windows.S_IWUSR
}
if fi.IsDir() {
@@ -79,8 +79,8 @@ func osGetExclusiveLock(file *os.File, timeout time.Duration) _ErrorCode {
return rc
}
func osDowngradeLock(file *os.File, state _LockLevel) _ErrorCode {
if state >= _LOCK_EXCLUSIVE {
func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
if state >= LOCK_EXCLUSIVE {
// Release the SHARED lock.
osUnlock(file, _SHARED_FIRST, _SHARED_SIZE)
@@ -93,24 +93,24 @@ func osDowngradeLock(file *os.File, state _LockLevel) _ErrorCode {
}
// Release the PENDING and RESERVED locks.
if state >= _LOCK_RESERVED {
if state >= LOCK_RESERVED {
osUnlock(file, _RESERVED_BYTE, 1)
}
if state >= _LOCK_PENDING {
if state >= LOCK_PENDING {
osUnlock(file, _PENDING_BYTE, 1)
}
return _OK
}
func osReleaseLock(file *os.File, state _LockLevel) _ErrorCode {
func osReleaseLock(file *os.File, state LockLevel) _ErrorCode {
// Release all locks.
if state >= _LOCK_RESERVED {
if state >= LOCK_RESERVED {
osUnlock(file, _RESERVED_BYTE, 1)
}
if state >= _LOCK_SHARED {
if state >= LOCK_SHARED {
osUnlock(file, _SHARED_FIRST, _SHARED_SIZE)
}
if state >= _LOCK_PENDING {
if state >= LOCK_PENDING {
osUnlock(file, _PENDING_BYTE, 1)
}
return _OK

View File

@@ -1,4 +1,4 @@
package vfs
package sqlite3vfs
import (
"bytes"
@@ -181,7 +181,7 @@ func Test_vfsAccess(t *testing.T) {
util.WriteString(mod, 8, dir)
ctx := context.TODO()
rc := vfsAccess(ctx, mod, 0, 8, _ACCESS_EXISTS, 4)
rc := vfsAccess(ctx, mod, 0, 8, ACCESS_EXISTS, 4)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -189,7 +189,7 @@ func Test_vfsAccess(t *testing.T) {
t.Error("directory did not exist")
}
rc = vfsAccess(ctx, mod, 0, 8, _ACCESS_READWRITE, 4)
rc = vfsAccess(ctx, mod, 0, 8, ACCESS_READWRITE, 4)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -198,7 +198,7 @@ func Test_vfsAccess(t *testing.T) {
}
util.WriteString(mod, 8, file)
rc = vfsAccess(ctx, mod, 0, 8, _ACCESS_READWRITE, 4)
rc = vfsAccess(ctx, mod, 0, 8, ACCESS_READWRITE, 4)
if rc != _OK {
t.Fatal("returned", rc)
}
@@ -209,11 +209,11 @@ func Test_vfsAccess(t *testing.T) {
func Test_vfsFile(t *testing.T) {
mod := util.NewMockModule(128)
ctx, vfs := Context(context.TODO())
ctx, vfs := NewContext(context.TODO())
defer vfs.Close()
// Open a temporary file.
rc := vfsOpen(ctx, mod, 0, 0, 4, _OPEN_CREATE|_OPEN_EXCLUSIVE|_OPEN_READWRITE|_OPEN_DELETEONCLOSE, 0)
rc := vfsOpen(ctx, mod, 0, 0, 4, OPEN_CREATE|OPEN_EXCLUSIVE|OPEN_READWRITE|OPEN_DELETEONCLOSE, 0)
if rc != _OK {
t.Fatal("returned", rc)
}