mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Sync journal directories.
This commit is contained in:
@@ -20,12 +20,14 @@ struct os_file {
|
||||
int id;
|
||||
char lock;
|
||||
char psow;
|
||||
char syncDir;
|
||||
int lockTimeout;
|
||||
};
|
||||
|
||||
static_assert(offsetof(struct os_file, id) == 4, "Unexpected offset");
|
||||
static_assert(offsetof(struct os_file, lock) == 8, "Unexpected offset");
|
||||
static_assert(offsetof(struct os_file, psow) == 9, "Unexpected offset");
|
||||
static_assert(offsetof(struct os_file, syncDir) == 10, "Unexpected offset");
|
||||
static_assert(offsetof(struct os_file, lockTimeout) == 12, "Unexpected offset");
|
||||
|
||||
int os_close(sqlite3_file *);
|
||||
|
||||
45
vfs.go
45
vfs.go
@@ -79,8 +79,8 @@ func (vfs *vfsState) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func vfsLocaltime(ctx context.Context, mod api.Module, pTm uint32, t uint64) uint32 {
|
||||
tm := time.Unix(int64(t), 0)
|
||||
func vfsLocaltime(ctx context.Context, mod api.Module, pTm uint32, t int64) uint32 {
|
||||
tm := time.Unix(t, 0)
|
||||
var isdst int
|
||||
if tm.IsDST() {
|
||||
isdst = 1
|
||||
@@ -224,7 +224,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zName, pFile uint32, fla
|
||||
file, err = os.CreateTemp("", "*.db")
|
||||
} else {
|
||||
name := memory{mod}.readString(zName, _MAX_PATHNAME)
|
||||
file, err = vfsOS.OpenFile(name, oflags, 0600)
|
||||
file, err = vfsOS.OpenFile(name, oflags, 0666)
|
||||
}
|
||||
if err != nil {
|
||||
return uint32(CANTOPEN)
|
||||
@@ -236,6 +236,12 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zName, pFile uint32, fla
|
||||
|
||||
vfsFile.Open(ctx, mod, pFile, file)
|
||||
|
||||
if runtime.GOOS != "windows" &&
|
||||
flags&(OPEN_CREATE) != 0 &&
|
||||
flags&(OPEN_MAIN_JOURNAL|OPEN_SUPER_JOURNAL|OPEN_WAL) != 0 {
|
||||
vfsFile.SetSyncDir(ctx, mod, pFile, true)
|
||||
}
|
||||
|
||||
if pOutFlags != 0 {
|
||||
memory{mod}.writeUint32(pOutFlags, uint32(flags))
|
||||
}
|
||||
@@ -250,11 +256,11 @@ func vfsClose(ctx context.Context, mod api.Module, pFile uint32) uint32 {
|
||||
return _OK
|
||||
}
|
||||
|
||||
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst uint64) uint32 {
|
||||
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst int64) uint32 {
|
||||
buf := memory{mod}.view(zBuf, uint64(iAmt))
|
||||
|
||||
file := vfsFile.GetOS(ctx, mod, pFile)
|
||||
n, err := file.ReadAt(buf, int64(iOfst))
|
||||
n, err := file.ReadAt(buf, iOfst)
|
||||
if n == int(iAmt) {
|
||||
return _OK
|
||||
}
|
||||
@@ -267,20 +273,20 @@ func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfs
|
||||
return uint32(IOERR_SHORT_READ)
|
||||
}
|
||||
|
||||
func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst uint64) uint32 {
|
||||
func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst int64) uint32 {
|
||||
buf := memory{mod}.view(zBuf, uint64(iAmt))
|
||||
|
||||
file := vfsFile.GetOS(ctx, mod, pFile)
|
||||
_, err := file.WriteAt(buf, int64(iOfst))
|
||||
_, err := file.WriteAt(buf, iOfst)
|
||||
if err != nil {
|
||||
return uint32(IOERR_WRITE)
|
||||
}
|
||||
return _OK
|
||||
}
|
||||
|
||||
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte uint64) uint32 {
|
||||
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte int64) uint32 {
|
||||
file := vfsFile.GetOS(ctx, mod, pFile)
|
||||
err := file.Truncate(int64(nByte))
|
||||
err := file.Truncate(nByte)
|
||||
if err != nil {
|
||||
return uint32(IOERR_TRUNCATE)
|
||||
}
|
||||
@@ -290,11 +296,24 @@ func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte uint64
|
||||
func vfsSync(ctx context.Context, mod api.Module, pFile uint32, flags _SyncFlag) uint32 {
|
||||
dataonly := (flags & _SYNC_DATAONLY) != 0
|
||||
fullsync := (flags & 0x0f) == _SYNC_FULL
|
||||
|
||||
file := vfsFile.GetOS(ctx, mod, pFile)
|
||||
err := vfsOS.Sync(file, fullsync, dataonly)
|
||||
if err != nil {
|
||||
return uint32(IOERR_FSYNC)
|
||||
}
|
||||
if runtime.GOOS != "windows" && vfsFile.GetSyncDir(ctx, mod, pFile) {
|
||||
vfsFile.SetSyncDir(ctx, mod, pFile, false)
|
||||
f, err := os.Open(filepath.Dir(file.Name()))
|
||||
if err != nil {
|
||||
return _OK
|
||||
}
|
||||
defer f.Close()
|
||||
err = vfsOS.Sync(f, false, false)
|
||||
if err != nil {
|
||||
return uint32(IOERR_DIR_FSYNC)
|
||||
}
|
||||
}
|
||||
return _OK
|
||||
}
|
||||
|
||||
@@ -397,21 +416,21 @@ func vfsRegisterFunc5[T0, T1, T2, T3, T4 ~uint32](mod wazero.HostModuleBuilder,
|
||||
Export(name)
|
||||
}
|
||||
|
||||
func vfsRegisterFuncRW(mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _, _, _ uint32, _ uint64) uint32) {
|
||||
func vfsRegisterFuncRW(mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _, _, _ uint32, _ int64) uint32) {
|
||||
mod.NewFunctionBuilder().
|
||||
WithGoModuleFunction(api.GoModuleFunc(
|
||||
func(ctx context.Context, mod api.Module, stack []uint64) {
|
||||
stack[0] = uint64(fn(ctx, mod, uint32(stack[0]), uint32(stack[1]), uint32(stack[2]), stack[3]))
|
||||
stack[0] = uint64(fn(ctx, mod, uint32(stack[0]), uint32(stack[1]), uint32(stack[2]), int64(stack[3])))
|
||||
}),
|
||||
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}).
|
||||
Export(name)
|
||||
}
|
||||
|
||||
func vfsRegisterFuncT(mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ uint32, _ uint64) uint32) {
|
||||
func vfsRegisterFuncT(mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ uint32, _ int64) uint32) {
|
||||
mod.NewFunctionBuilder().
|
||||
WithGoModuleFunction(api.GoModuleFunc(
|
||||
func(ctx context.Context, mod api.Module, stack []uint64) {
|
||||
stack[0] = uint64(fn(ctx, mod, uint32(stack[0]), stack[1]))
|
||||
stack[0] = uint64(fn(ctx, mod, uint32(stack[0]), int64(stack[1])))
|
||||
}),
|
||||
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}).
|
||||
Export(name)
|
||||
|
||||
18
vfs_file.go
18
vfs_file.go
@@ -12,6 +12,7 @@ const (
|
||||
// These need to match the offsets asserted in os.c
|
||||
vfsFileIDOffset = 4
|
||||
vfsFileLockOffset = 8
|
||||
vfsFileSyncDirOffset = 10
|
||||
vfsFileLockTimeoutOffset = 12
|
||||
)
|
||||
|
||||
@@ -67,3 +68,20 @@ func (vfsFileMethods) GetLockTimeout(ctx context.Context, mod api.Module, pFile
|
||||
mem := memory{mod}
|
||||
return time.Duration(mem.readUint32(pFile+vfsFileLockTimeoutOffset)) * time.Millisecond
|
||||
}
|
||||
|
||||
func (vfsFileMethods) GetSyncDir(ctx context.Context, mod api.Module, pFile uint32) bool {
|
||||
mem := memory{mod}
|
||||
if b := mem.readUint8(pFile + vfsFileSyncDirOffset); b != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (vfsFileMethods) SetSyncDir(ctx context.Context, mod api.Module, pFile uint32, state bool) {
|
||||
mem := memory{mod}
|
||||
var b uint8
|
||||
if state {
|
||||
b = 1
|
||||
}
|
||||
mem.writeUint8(pFile+vfsFileSyncDirOffset, b)
|
||||
}
|
||||
|
||||
20
vfs_test.go
20
vfs_test.go
@@ -18,34 +18,34 @@ func Test_vfsLocaltime(t *testing.T) {
|
||||
mem := newMemory(128)
|
||||
ctx := context.TODO()
|
||||
|
||||
rc := vfsLocaltime(ctx, mem.mod, 4, 0)
|
||||
tm := time.Now()
|
||||
rc := vfsLocaltime(ctx, mem.mod, 4, tm.Unix())
|
||||
if rc != 0 {
|
||||
t.Fatal("returned", rc)
|
||||
}
|
||||
|
||||
epoch := time.Unix(0, 0)
|
||||
if s := mem.readUint32(4 + 0*4); int(s) != epoch.Second() {
|
||||
if s := mem.readUint32(4 + 0*4); int(s) != tm.Second() {
|
||||
t.Error("wrong second")
|
||||
}
|
||||
if m := mem.readUint32(4 + 1*4); int(m) != epoch.Minute() {
|
||||
if m := mem.readUint32(4 + 1*4); int(m) != tm.Minute() {
|
||||
t.Error("wrong minute")
|
||||
}
|
||||
if h := mem.readUint32(4 + 2*4); int(h) != epoch.Hour() {
|
||||
if h := mem.readUint32(4 + 2*4); int(h) != tm.Hour() {
|
||||
t.Error("wrong hour")
|
||||
}
|
||||
if d := mem.readUint32(4 + 3*4); int(d) != epoch.Day() {
|
||||
if d := mem.readUint32(4 + 3*4); int(d) != tm.Day() {
|
||||
t.Error("wrong day")
|
||||
}
|
||||
if m := mem.readUint32(4 + 4*4); time.Month(1+m) != epoch.Month() {
|
||||
if m := mem.readUint32(4 + 4*4); time.Month(1+m) != tm.Month() {
|
||||
t.Error("wrong month")
|
||||
}
|
||||
if y := mem.readUint32(4 + 5*4); 1900+int(y) != epoch.Year() {
|
||||
if y := mem.readUint32(4 + 5*4); 1900+int(y) != tm.Year() {
|
||||
t.Error("wrong year")
|
||||
}
|
||||
if w := mem.readUint32(4 + 6*4); time.Weekday(w) != epoch.Weekday() {
|
||||
if w := mem.readUint32(4 + 6*4); time.Weekday(w) != tm.Weekday() {
|
||||
t.Error("wrong weekday")
|
||||
}
|
||||
if d := mem.readUint32(4 + 7*4); int(d) != epoch.YearDay()-1 {
|
||||
if d := mem.readUint32(4 + 7*4); int(d) != tm.YearDay()-1 {
|
||||
t.Error("wrong yearday")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user