Skip to content

Commit 992676d

Browse files
committed
Improved WAL API.
1 parent 82d8a2d commit 992676d

File tree

4 files changed

+69
-41
lines changed

4 files changed

+69
-41
lines changed

vfs/api.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package vfs
33

44
import (
55
"context"
6+
"io"
67

78
"github.com/tetratelabs/wazero/api"
89
)
@@ -154,17 +155,19 @@ type FileCheckpoint interface {
154155
CheckpointStart() error
155156
}
156157

157-
// FileSharedMemory extends File to possibly implement shared memory.
158+
// FileSharedMemory extends File to possibly implement
159+
// shared-memory for the WAL-index.
158160
// It's OK for SharedMemory to return nil.
159161
type FileSharedMemory interface {
160162
File
161163
SharedMemory() SharedMemory
162164
}
163165

164-
// SharedMemory is a shared memory implementation.
166+
// SharedMemory is a shared-memory WAL-index implementation.
165167
// This cannot be externally implemented.
166168
type SharedMemory interface {
167169
shmMap(context.Context, api.Module, int32, int32, bool) (uint32, error)
168170
shmLock(int32, int32, _ShmFlag) error
169171
shmUnmap(bool)
172+
io.Closer
170173
}

vfs/file.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,14 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
118118
syncDir: runtime.GOOS != "windows" &&
119119
flags&(OPEN_CREATE) != 0 &&
120120
flags&(OPEN_MAIN_JOURNAL|OPEN_SUPER_JOURNAL|OPEN_WAL) != 0,
121+
shm: NewSharedMemory(name.String()+"-shm", flags),
121122
}
122123
return &file, flags, nil
123124
}
124125

125126
type vfsFile struct {
126127
*os.File
127-
shm vfsShm
128+
shm SharedMemory
128129
lock LockLevel
129130
readOnly bool
130131
keepWAL bool
@@ -142,7 +143,9 @@ var (
142143
)
143144

144145
func (f *vfsFile) Close() error {
145-
f.shm.Close()
146+
if f.shm != nil {
147+
f.shm.Close()
148+
}
146149
return f.File.Close()
147150
}
148151

vfs/shm.go

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,90 +22,107 @@ import (
2222
// [EXCLUSIVE locking mode]: https://sqlite.org/pragma.html#pragma_locking_mode
2323
const SupportsSharedMemory = true
2424

25-
type vfsShm struct {
26-
*os.File
27-
regions []*util.MappedRegion
28-
}
29-
3025
const (
3126
_SHM_NLOCK = 8
3227
_SHM_BASE = 120
3328
_SHM_DMS = _SHM_BASE + _SHM_NLOCK
3429
)
3530

36-
func (f *vfsFile) SharedMemory() SharedMemory { return f }
31+
func (f *vfsFile) SharedMemory() SharedMemory { return f.shm }
32+
33+
// NewSharedMemory returns a shared-memory WAL-index
34+
// backed a file with the given path.
35+
// It may return nil if shared-memory is not supported,
36+
// or not appropriate for the given flags.
37+
// Only [OPEN_MAIN_DB] databases support WAL mode.
38+
func NewSharedMemory(path string, flags OpenFlag) SharedMemory {
39+
if flags&OPEN_MAIN_DB == 0 {
40+
return nil
41+
}
42+
return &vfsShm{
43+
path: path,
44+
readOnly: flags&OPEN_READONLY != 0,
45+
}
46+
}
47+
48+
type vfsShm struct {
49+
*os.File
50+
regions []*util.MappedRegion
51+
path string
52+
readOnly bool
53+
}
3754

38-
func (f *vfsFile) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, error) {
55+
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, error) {
3956
// Ensure size is a multiple of the OS page size.
4057
if int(size)&(unix.Getpagesize()-1) != 0 {
4158
return 0, _IOERR_SHMMAP
4259
}
4360

44-
if f.shm.File == nil {
61+
if s.File == nil {
4562
var flag int
46-
if f.readOnly {
63+
if s.readOnly {
4764
flag = unix.O_RDONLY
4865
} else {
4966
flag = unix.O_RDWR
5067
}
51-
s, err := os.OpenFile(f.Name()+"-shm",
68+
f, err := os.OpenFile(s.path,
5269
flag|unix.O_CREAT|unix.O_NOFOLLOW, 0666)
5370
if err != nil {
5471
return 0, _CANTOPEN
5572
}
56-
f.shm.File = s
73+
s.File = f
5774
}
5875

5976
// Dead man's switch.
60-
if lock, rc := osGetLock(f.shm.File, _SHM_DMS, 1); rc != _OK {
77+
if lock, rc := osGetLock(s.File, _SHM_DMS, 1); rc != _OK {
6178
return 0, _IOERR_LOCK
6279
} else if lock == unix.F_WRLCK {
6380
return 0, _BUSY
6481
} else if lock == unix.F_UNLCK {
65-
if f.readOnly {
82+
if s.readOnly {
6683
return 0, _READONLY_CANTINIT
6784
}
68-
if rc := osWriteLock(f.shm.File, _SHM_DMS, 1, 0); rc != _OK {
85+
if rc := osWriteLock(s.File, _SHM_DMS, 1, 0); rc != _OK {
6986
return 0, rc
7087
}
71-
if err := f.shm.Truncate(0); err != nil {
88+
if err := s.Truncate(0); err != nil {
7289
return 0, _IOERR_SHMOPEN
7390
}
7491
}
75-
if rc := osReadLock(f.shm.File, _SHM_DMS, 1, 0); rc != _OK {
92+
if rc := osReadLock(s.File, _SHM_DMS, 1, 0); rc != _OK {
7693
return 0, rc
7794
}
7895

7996
// Check if file is big enough.
80-
s, err := f.shm.Seek(0, io.SeekEnd)
97+
o, err := s.Seek(0, io.SeekEnd)
8198
if err != nil {
8299
return 0, _IOERR_SHMSIZE
83100
}
84-
if n := (int64(id) + 1) * int64(size); n > s {
101+
if n := (int64(id) + 1) * int64(size); n > o {
85102
if !extend {
86103
return 0, nil
87104
}
88-
err := osAllocate(f.shm.File, n)
105+
err := osAllocate(s.File, n)
89106
if err != nil {
90107
return 0, _IOERR_SHMSIZE
91108
}
92109
}
93110

94111
var prot int
95-
if f.readOnly {
112+
if s.readOnly {
96113
prot = unix.PROT_READ
97114
} else {
98115
prot = unix.PROT_READ | unix.PROT_WRITE
99116
}
100-
r, err := util.MapRegion(ctx, mod, f.shm.File, int64(id)*int64(size), size, prot)
117+
r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, prot)
101118
if err != nil {
102119
return 0, err
103120
}
104-
f.shm.regions = append(f.shm.regions, r)
121+
s.regions = append(s.regions, r)
105122
return r.Ptr, nil
106123
}
107124

108-
func (f *vfsFile) shmLock(offset, n int32, flags _ShmFlag) error {
125+
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error {
109126
// Argument check.
110127
if n <= 0 || offset < 0 || offset+n > _SHM_NLOCK {
111128
panic(util.AssertErr())
@@ -126,28 +143,28 @@ func (f *vfsFile) shmLock(offset, n int32, flags _ShmFlag) error {
126143

127144
switch {
128145
case flags&_SHM_UNLOCK != 0:
129-
return osUnlock(f.shm.File, _SHM_BASE+int64(offset), int64(n))
146+
return osUnlock(s.File, _SHM_BASE+int64(offset), int64(n))
130147
case flags&_SHM_SHARED != 0:
131-
return osReadLock(f.shm.File, _SHM_BASE+int64(offset), int64(n), 0)
148+
return osReadLock(s.File, _SHM_BASE+int64(offset), int64(n), 0)
132149
case flags&_SHM_EXCLUSIVE != 0:
133-
return osWriteLock(f.shm.File, _SHM_BASE+int64(offset), int64(n), 0)
150+
return osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n), 0)
134151
default:
135152
panic(util.AssertErr())
136153
}
137154
}
138155

139-
func (f *vfsFile) shmUnmap(delete bool) {
156+
func (s *vfsShm) shmUnmap(delete bool) {
140157
// Unmap regions.
141-
for _, r := range f.shm.regions {
158+
for _, r := range s.regions {
142159
r.Unmap()
143160
}
144-
clear(f.shm.regions)
145-
f.shm.regions = f.shm.regions[:0]
161+
clear(s.regions)
162+
s.regions = s.regions[:0]
146163

147164
// Close the file.
148-
if delete && f.shm.File != nil {
149-
os.Remove(f.shm.Name())
165+
if delete && s.File != nil {
166+
os.Remove(s.Name())
150167
}
151-
f.shm.Close()
152-
f.shm.File = nil
168+
s.Close()
169+
s.File = nil
153170
}

vfs/shm_other.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ package vfs
1212
// [EXCLUSIVE locking mode]: https://sqlite.org/pragma.html#pragma_locking_mode
1313
const SupportsSharedMemory = false
1414

15-
type vfsShm struct{}
16-
17-
func (vfsShm) Close() error { return nil }
15+
// NewSharedMemory returns a shared-memory WAL-index
16+
// backed a file with the given path.
17+
// It may return nil if shared-memory is not supported,
18+
// or not appropriate for the given flags.
19+
// Only [OPEN_MAIN_DB] databases support WAL mode.
20+
func NewSharedMemory(path string, flags OpenFlag) SharedMemory {
21+
return nil
22+
}

0 commit comments

Comments
 (0)