Sync journal directories.

This commit is contained in:
Nuno Cruces
2023-03-25 11:16:51 +00:00
parent 37a3ff37e8
commit 89f4327b2b
4 changed files with 62 additions and 23 deletions

View File

@@ -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
View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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")
}
}