Skip to content

Commit 62b79d2

Browse files
committed
Shared memory API.
1 parent 07241d0 commit 62b79d2

File tree

6 files changed

+50
-35
lines changed

6 files changed

+50
-35
lines changed

internal/util/unwrap.go

Lines changed: 0 additions & 8 deletions
This file was deleted.

vfs/adiantum/hbsh.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,19 @@ func (h *hbshVFS) OpenParams(name string, flags vfs.OpenFlag, params url.Values)
2727
// Encrypt everything except super journals.
2828
if flags&vfs.OPEN_SUPER_JOURNAL == 0 {
2929
var key []byte
30-
if t, ok := params["key"]; ok {
30+
if name == "" {
31+
key = h.hbsh.KDF("") // Temporary files get a random key.
32+
} else if t, ok := params["key"]; ok {
3133
key = []byte(t[0])
3234
} else if t, ok := params["hexkey"]; ok {
3335
key, _ = hex.DecodeString(t[0])
3436
} else if t, ok := params["textkey"]; ok {
3537
key = h.hbsh.KDF(t[0])
36-
} else if name == "" {
37-
key = h.hbsh.KDF("")
3838
}
3939

4040
if hbsh = h.hbsh.HBSH(key); hbsh == nil {
41-
return nil, flags, sqlite3.NOTADB
41+
// Can't open without a valid key.
42+
return nil, flags, sqlite3.CANTOPEN
4243
}
4344
}
4445

@@ -51,6 +52,7 @@ func (h *hbshVFS) OpenParams(name string, flags vfs.OpenFlag, params url.Values)
5152
file, flags, err = h.Open(name, flags)
5253
}
5354
if err != nil || hbsh == nil || flags&vfs.OPEN_MEMORY != 0 {
55+
// Error, or no encryption (super journals, memory files).
5456
return file, flags, err
5557
}
5658
return &hbshFile{File: file, hbsh: hbsh}, flags, err
@@ -72,8 +74,8 @@ func (h *hbshFile) ReadAt(p []byte, off int64) (n int, err error) {
7274
min := (off) &^ (blockSize - 1) // round down
7375
max := (off + int64(len(p)) + blockSize - 1) &^ (blockSize - 1) // round up
7476

77+
// Read one block at a time.
7578
for ; min < max; min += blockSize {
76-
// Read full block.
7779
m, err := h.File.ReadAt(h.block[:], min)
7880
if m != blockSize {
7981
return n, err
@@ -98,20 +100,24 @@ func (h *hbshFile) WriteAt(p []byte, off int64) (n int, err error) {
98100
min := (off) &^ (blockSize - 1) // round down
99101
max := (off + int64(len(p)) + blockSize - 1) &^ (blockSize - 1) // round up
100102

103+
// Write one block at a time.
101104
for ; min < max; min += blockSize {
102105
binary.LittleEndian.PutUint64(h.tweak[:], uint64(min))
103106
data := h.block[:]
104107

105108
if off > min || len(p[n:]) < blockSize {
106-
// Read full block.
109+
// Partial block write: read-update-write.
107110
m, err := h.File.ReadAt(h.block[:], min)
108111
if m != blockSize {
109112
if err != io.EOF {
110113
return n, err
111114
}
112-
// Writing past the EOF.
113-
// A partially written block is corrupt,
114-
// and also considered to be past the EOF.
115+
// Writing past the EOF:
116+
// We're either appending an entirely new block,
117+
// or the final block was only partially written.
118+
// A partially written block can't be decripted,
119+
// and is as good as corrupt.
120+
// Either way, zero pad the file to the next block size.
115121
clear(data)
116122
}
117123

@@ -124,7 +130,6 @@ func (h *hbshFile) WriteAt(p []byte, off int64) (n int, err error) {
124130
t := copy(data, p[n:])
125131
h.hbsh.Encrypt(h.block[:], h.tweak[:])
126132

127-
// Write full block.
128133
m, err := h.File.WriteAt(h.block[:], min)
129134
if m != blockSize {
130135
return n, err
@@ -155,9 +160,11 @@ func (h *hbshFile) DeviceCharacteristics() vfs.DeviceCharacteristic {
155160
vfs.IOCAP_BATCH_ATOMIC)
156161
}
157162

158-
// This is needed for shared memory.
159-
func (h *hbshFile) Unwrap() vfs.File {
160-
return h.File
163+
func (h *hbshFile) SharedMemory() vfs.SharedMemory {
164+
if shm, ok := h.File.(vfs.FileSharedMemory); ok {
165+
return shm.SharedMemory()
166+
}
167+
return nil
161168
}
162169

163170
// Wrap optional methods.

vfs/api.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
// Package vfs wraps the C SQLite VFS API.
22
package vfs
33

4-
import "net/url"
4+
import (
5+
"context"
6+
"net/url"
7+
8+
"github.com/tetratelabs/wazero/api"
9+
)
510

611
// A VFS defines the interface between the SQLite core and the underlying operating system.
712
//
@@ -129,3 +134,18 @@ type FileBatchAtomicWrite interface {
129134
CommitAtomicWrite() error
130135
RollbackAtomicWrite() error
131136
}
137+
138+
// FileSharedMemory extends File to possibly implement shared memory.
139+
// It's OK for SharedMemory to return nil.
140+
type FileSharedMemory interface {
141+
File
142+
SharedMemory() SharedMemory
143+
}
144+
145+
// SharedMemory is a shared memory implementation.
146+
// This cannot be externally implemented.
147+
type SharedMemory interface {
148+
shmMap(context.Context, api.Module, int32, int32, bool) (uint32, error)
149+
shmLock(int32, int32, _ShmFlag) error
150+
shmUnmap(bool)
151+
}

vfs/file.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package vfs
22

33
import (
4-
"context"
54
"errors"
65
"io"
76
"io/fs"
@@ -12,7 +11,6 @@ import (
1211
"syscall"
1312

1413
"github.com/ncruces/go-sqlite3/util/osutil"
15-
"github.com/tetratelabs/wazero/api"
1614
)
1715

1816
type vfsOS struct{}
@@ -215,9 +213,3 @@ func (f *vfsFile) PowersafeOverwrite() bool { return f.psow }
215213
func (f *vfsFile) PersistentWAL() bool { return f.keepWAL }
216214
func (f *vfsFile) SetPowersafeOverwrite(psow bool) { f.psow = psow }
217215
func (f *vfsFile) SetPersistentWAL(keepWAL bool) { f.keepWAL = keepWAL }
218-
219-
type fileShm interface {
220-
shmMap(context.Context, api.Module, int32, int32, bool) (uint32, error)
221-
shmLock(int32, int32, _ShmFlag) error
222-
shmUnmap(bool)
223-
}

vfs/shm.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const (
3333
_SHM_DMS = _SHM_BASE + _SHM_NLOCK
3434
)
3535

36+
func (f *vfsFile) SharedMemory() SharedMemory { return f }
37+
3638
func (f *vfsFile) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, error) {
3739
// Ensure size is a multiple of the OS page size.
3840
if int(size)&(unix.Getpagesize()-1) != 0 {

vfs/vfs.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, fla
171171
util.WriteUint32(mod, pOutFlags, uint32(flags))
172172
}
173173
if pOutVFS != 0 && util.CanMapFiles(ctx) {
174-
if _, ok := util.Unwrap(file).(fileShm); ok {
175-
util.WriteUint32(mod, pOutVFS, 1)
174+
if f, ok := file.(FileSharedMemory); ok {
175+
if f.SharedMemory() != nil {
176+
util.WriteUint32(mod, pOutVFS, 1)
177+
}
176178
}
177179
}
178180
vfsFileRegister(ctx, mod, pFile, file)
@@ -366,7 +368,7 @@ func vfsShmBarrier(ctx context.Context, mod api.Module, pFile uint32) {
366368
}
367369

368370
func vfsShmMap(ctx context.Context, mod api.Module, pFile uint32, iRegion, szRegion int32, bExtend, pp uint32) _ErrorCode {
369-
file := util.Unwrap(vfsFileGet(ctx, mod, pFile)).(fileShm)
371+
file := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
370372
p, err := file.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
371373
if err != nil {
372374
return vfsErrorCode(err, _IOERR_SHMMAP)
@@ -376,13 +378,13 @@ func vfsShmMap(ctx context.Context, mod api.Module, pFile uint32, iRegion, szReg
376378
}
377379

378380
func vfsShmLock(ctx context.Context, mod api.Module, pFile uint32, offset, n int32, flags _ShmFlag) _ErrorCode {
379-
file := util.Unwrap(vfsFileGet(ctx, mod, pFile)).(fileShm)
381+
file := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
380382
err := file.shmLock(offset, n, flags)
381383
return vfsErrorCode(err, _IOERR_SHMLOCK)
382384
}
383385

384386
func vfsShmUnmap(ctx context.Context, mod api.Module, pFile, bDelete uint32) _ErrorCode {
385-
file := util.Unwrap(vfsFileGet(ctx, mod, pFile)).(fileShm)
387+
file := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
386388
file.shmUnmap(bDelete != 0)
387389
return _OK
388390
}

0 commit comments

Comments
 (0)