diff --git a/README.md b/README.md index 33a15ed..0eabecd 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/internal/vfs/const.go b/internal/vfs/const.go deleted file mode 100644 index eb5d751..0000000 --- a/internal/vfs/const.go +++ /dev/null @@ -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 -) diff --git a/internal/vfs/vfs_api.go b/internal/vfs/vfs_api.go deleted file mode 100644 index 9248a05..0000000 --- a/internal/vfs/vfs_api.go +++ /dev/null @@ -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 -} diff --git a/module.go b/module.go index f3d96a2..0aadf67 100644 --- a/module.go +++ b/module.go @@ -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) diff --git a/sqlite3/download.sh b/sqlite3/download.sh index 20077d8..3000a6c 100755 --- a/sqlite3/download.sh +++ b/sqlite3/download.sh @@ -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 ~- \ No newline at end of file diff --git a/sqlite3vfs/const.go b/sqlite3vfs/const.go index 0ff4863..6ae98b7 100644 --- a/sqlite3vfs/const.go +++ b/sqlite3vfs/const.go @@ -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 +) diff --git a/internal/vfs/tests/mptest/mptest_test.go b/sqlite3vfs/tests/mptest/mptest_test.go similarity index 89% rename from internal/vfs/tests/mptest/mptest_test.go rename to sqlite3vfs/tests/mptest/mptest_test.go index ab652cf..1dd088d 100644 --- a/internal/vfs/tests/mptest/mptest_test.go +++ b/sqlite3vfs/tests/mptest/mptest_test.go @@ -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 { diff --git a/internal/vfs/tests/mptest/testdata/.gitattributes b/sqlite3vfs/tests/mptest/testdata/.gitattributes similarity index 100% rename from internal/vfs/tests/mptest/testdata/.gitattributes rename to sqlite3vfs/tests/mptest/testdata/.gitattributes diff --git a/internal/vfs/tests/mptest/testdata/.gitignore b/sqlite3vfs/tests/mptest/testdata/.gitignore similarity index 100% rename from internal/vfs/tests/mptest/testdata/.gitignore rename to sqlite3vfs/tests/mptest/testdata/.gitignore diff --git a/internal/vfs/tests/mptest/testdata/build.sh b/sqlite3vfs/tests/mptest/testdata/build.sh similarity index 94% rename from internal/vfs/tests/mptest/testdata/build.sh rename to sqlite3vfs/tests/mptest/testdata/build.sh index 509770f..2865127 100755 --- a/internal/vfs/tests/mptest/testdata/build.sh +++ b/sqlite3vfs/tests/mptest/testdata/build.sh @@ -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" diff --git a/internal/vfs/tests/mptest/testdata/config01.test b/sqlite3vfs/tests/mptest/testdata/config01.test similarity index 100% rename from internal/vfs/tests/mptest/testdata/config01.test rename to sqlite3vfs/tests/mptest/testdata/config01.test diff --git a/internal/vfs/tests/mptest/testdata/config02.test b/sqlite3vfs/tests/mptest/testdata/config02.test similarity index 100% rename from internal/vfs/tests/mptest/testdata/config02.test rename to sqlite3vfs/tests/mptest/testdata/config02.test diff --git a/internal/vfs/tests/mptest/testdata/crash01.test b/sqlite3vfs/tests/mptest/testdata/crash01.test similarity index 100% rename from internal/vfs/tests/mptest/testdata/crash01.test rename to sqlite3vfs/tests/mptest/testdata/crash01.test diff --git a/internal/vfs/tests/mptest/testdata/crash02.subtest b/sqlite3vfs/tests/mptest/testdata/crash02.subtest similarity index 100% rename from internal/vfs/tests/mptest/testdata/crash02.subtest rename to sqlite3vfs/tests/mptest/testdata/crash02.subtest diff --git a/internal/vfs/tests/mptest/testdata/main.c b/sqlite3vfs/tests/mptest/testdata/main.c similarity index 100% rename from internal/vfs/tests/mptest/testdata/main.c rename to sqlite3vfs/tests/mptest/testdata/main.c diff --git a/internal/vfs/tests/mptest/testdata/mptest.wasm b/sqlite3vfs/tests/mptest/testdata/mptest.wasm similarity index 100% rename from internal/vfs/tests/mptest/testdata/mptest.wasm rename to sqlite3vfs/tests/mptest/testdata/mptest.wasm diff --git a/internal/vfs/tests/mptest/testdata/multiwrite01.test b/sqlite3vfs/tests/mptest/testdata/multiwrite01.test similarity index 100% rename from internal/vfs/tests/mptest/testdata/multiwrite01.test rename to sqlite3vfs/tests/mptest/testdata/multiwrite01.test diff --git a/internal/vfs/tests/speedtest1/speedtest1_test.go b/sqlite3vfs/tests/speedtest1/speedtest1_test.go similarity index 89% rename from internal/vfs/tests/speedtest1/speedtest1_test.go rename to sqlite3vfs/tests/speedtest1/speedtest1_test.go index 2e9c2b7..e5467ba 100644 --- a/internal/vfs/tests/speedtest1/speedtest1_test.go +++ b/sqlite3vfs/tests/speedtest1/speedtest1_test.go @@ -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() } diff --git a/internal/vfs/tests/speedtest1/testdata/.gitattributes b/sqlite3vfs/tests/speedtest1/testdata/.gitattributes similarity index 100% rename from internal/vfs/tests/speedtest1/testdata/.gitattributes rename to sqlite3vfs/tests/speedtest1/testdata/.gitattributes diff --git a/internal/vfs/tests/speedtest1/testdata/.gitignore b/sqlite3vfs/tests/speedtest1/testdata/.gitignore similarity index 100% rename from internal/vfs/tests/speedtest1/testdata/.gitignore rename to sqlite3vfs/tests/speedtest1/testdata/.gitignore diff --git a/internal/vfs/tests/speedtest1/testdata/build.sh b/sqlite3vfs/tests/speedtest1/testdata/build.sh similarity index 91% rename from internal/vfs/tests/speedtest1/testdata/build.sh rename to sqlite3vfs/tests/speedtest1/testdata/build.sh index 681bf21..114977d 100755 --- a/internal/vfs/tests/speedtest1/testdata/build.sh +++ b/sqlite3vfs/tests/speedtest1/testdata/build.sh @@ -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" diff --git a/internal/vfs/tests/speedtest1/testdata/main.c b/sqlite3vfs/tests/speedtest1/testdata/main.c similarity index 100% rename from internal/vfs/tests/speedtest1/testdata/main.c rename to sqlite3vfs/tests/speedtest1/testdata/main.c diff --git a/internal/vfs/tests/speedtest1/testdata/speedtest1.wasm b/sqlite3vfs/tests/speedtest1/testdata/speedtest1.wasm similarity index 100% rename from internal/vfs/tests/speedtest1/testdata/speedtest1.wasm rename to sqlite3vfs/tests/speedtest1/testdata/speedtest1.wasm diff --git a/internal/vfs/vfs.go b/sqlite3vfs/vfs.go similarity index 88% rename from internal/vfs/vfs.go rename to sqlite3vfs/vfs.go index e05e765..a4d51be 100644 --- a/internal/vfs/vfs.go +++ b/sqlite3vfs/vfs.go @@ -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 +} diff --git a/internal/vfs/vfs_file.go b/sqlite3vfs/vfs_file.go similarity index 74% rename from internal/vfs/vfs_file.go rename to sqlite3vfs/vfs_file.go index b18c7af..f20ab0e 100644 --- a/internal/vfs/vfs_file.go +++ b/sqlite3vfs/vfs_file.go @@ -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 } diff --git a/internal/vfs/vfs_lock.go b/sqlite3vfs/vfs_lock.go similarity index 69% rename from internal/vfs/vfs_lock.go rename to sqlite3vfs/vfs_lock.go index f5140cc..496622c 100644 --- a/internal/vfs/vfs_lock.go +++ b/sqlite3vfs/vfs_lock.go @@ -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) diff --git a/internal/vfs/vfs_lock_test.go b/sqlite3vfs/vfs_lock_test.go similarity index 89% rename from internal/vfs/vfs_lock_test.go rename to sqlite3vfs/vfs_lock_test.go index b78ff78..cbd0a6e 100644 --- a/internal/vfs/vfs_lock_test.go +++ b/sqlite3vfs/vfs_lock_test.go @@ -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) } diff --git a/internal/vfs/vfs_os_bsd.go b/sqlite3vfs/vfs_os_bsd.go similarity index 98% rename from internal/vfs/vfs_os_bsd.go rename to sqlite3vfs/vfs_os_bsd.go index 2f04d3b..88372c5 100644 --- a/internal/vfs/vfs_os_bsd.go +++ b/sqlite3vfs/vfs_os_bsd.go @@ -1,6 +1,6 @@ //go:build freebsd || openbsd || netbsd || dragonfly || (darwin && sqlite3_bsd) -package vfs +package sqlite3vfs import ( "os" diff --git a/internal/vfs/vfs_os_darwin.go b/sqlite3vfs/vfs_os_darwin.go similarity index 99% rename from internal/vfs/vfs_os_darwin.go rename to sqlite3vfs/vfs_os_darwin.go index 4062cd1..39e0b58 100644 --- a/internal/vfs/vfs_os_darwin.go +++ b/sqlite3vfs/vfs_os_darwin.go @@ -1,6 +1,6 @@ //go:build !sqlite3_bsd -package vfs +package sqlite3vfs import ( "io" diff --git a/internal/vfs/vfs_os_linux.go b/sqlite3vfs/vfs_os_linux.go similarity index 95% rename from internal/vfs/vfs_os_linux.go rename to sqlite3vfs/vfs_os_linux.go index 2161380..d8c3307 100644 --- a/internal/vfs/vfs_os_linux.go +++ b/sqlite3vfs/vfs_os_linux.go @@ -1,4 +1,4 @@ -package vfs +package sqlite3vfs import ( "os" diff --git a/internal/vfs/vfs_os_ofd.go b/sqlite3vfs/vfs_os_ofd.go similarity index 98% rename from internal/vfs/vfs_os_ofd.go rename to sqlite3vfs/vfs_os_ofd.go index 27179d4..d8a3194 100644 --- a/internal/vfs/vfs_os_ofd.go +++ b/sqlite3vfs/vfs_os_ofd.go @@ -1,6 +1,6 @@ //go:build linux || illumos -package vfs +package sqlite3vfs import ( "os" diff --git a/internal/vfs/vfs_os_other.go b/sqlite3vfs/vfs_os_other.go similarity index 94% rename from internal/vfs/vfs_os_other.go rename to sqlite3vfs/vfs_os_other.go index 23fe3b4..2b7d728 100644 --- a/internal/vfs/vfs_os_other.go +++ b/sqlite3vfs/vfs_os_other.go @@ -1,6 +1,6 @@ //go:build !linux && (!darwin || sqlite3_bsd) -package vfs +package sqlite3vfs import ( "io" diff --git a/internal/vfs/vfs_os_unix.go b/sqlite3vfs/vfs_os_unix.go similarity index 87% rename from internal/vfs/vfs_os_unix.go rename to sqlite3vfs/vfs_os_unix.go index 032042e..8ed788a 100644 --- a/internal/vfs/vfs_os_unix.go +++ b/sqlite3vfs/vfs_os_unix.go @@ -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) } diff --git a/internal/vfs/vfs_os_windows.go b/sqlite3vfs/vfs_os_windows.go similarity index 93% rename from internal/vfs/vfs_os_windows.go rename to sqlite3vfs/vfs_os_windows.go index 55e3f8d..424a892 100644 --- a/internal/vfs/vfs_os_windows.go +++ b/sqlite3vfs/vfs_os_windows.go @@ -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 diff --git a/internal/vfs/vfs_test.go b/sqlite3vfs/vfs_test.go similarity index 94% rename from internal/vfs/vfs_test.go rename to sqlite3vfs/vfs_test.go index 1c064fe..061526a 100644 --- a/internal/vfs/vfs_test.go +++ b/sqlite3vfs/vfs_test.go @@ -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) }