diff options
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs')
6 files changed, 89 insertions, 124 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/api.go b/vendor/github.com/ncruces/go-sqlite3/vfs/api.go index d5bb3a7ae..a0d36b214 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/api.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/api.go @@ -36,9 +36,9 @@ type VFSFilename interface { // // https://sqlite.org/c3ref/io_methods.html type File interface { - Close() error - ReadAt(p []byte, off int64) (n int, err error) - WriteAt(p []byte, off int64) (n int, err error) + io.Closer + io.ReaderAt + io.WriterAt Truncate(size int64) error Sync(flags SyncFlag) error Size() (int64, error) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go b/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go index 0ff7b6f18..0123cc634 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go @@ -5,7 +5,6 @@ import ( "context" _ "embed" "encoding/binary" - "strconv" "github.com/tetratelabs/wazero/api" @@ -13,48 +12,30 @@ import ( "github.com/ncruces/go-sqlite3/util/sql3util" ) -func cksmWrapFile(name *Filename, flags OpenFlag, file File) File { - // Checksum only main databases and WALs. - if flags&(OPEN_MAIN_DB|OPEN_WAL) == 0 { +func cksmWrapFile(file File, flags OpenFlag) File { + // Checksum only main databases. + if flags&OPEN_MAIN_DB == 0 { return file } - - cksm := cksmFile{File: file} - - if flags&OPEN_WAL != 0 { - main, _ := name.DatabaseFile().(cksmFile) - cksm.cksmFlags = main.cksmFlags - } else { - cksm.cksmFlags = new(cksmFlags) - cksm.isDB = true - } - - return cksm + return &cksmFile{File: file} } type cksmFile struct { File - *cksmFlags - isDB bool -} - -type cksmFlags struct { - computeCksm bool verifyCksm bool - inCkpt bool - pageSize int + computeCksm bool } -func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) { +func (c *cksmFile) ReadAt(p []byte, off int64) (n int, err error) { n, err = c.File.ReadAt(p, off) p = p[:n] - if isHeader(c.isDB, p, off) { + if isHeader(p, off) { c.init((*[100]byte)(p)) } // Verify checksums. - if c.verifyCksm && !c.inCkpt && len(p) == c.pageSize { + if c.verifyCksm && sql3util.ValidPageSize(len(p)) { cksm1 := cksmCompute(p[:len(p)-8]) cksm2 := *(*[8]byte)(p[len(p)-8:]) if cksm1 != cksm2 { @@ -64,20 +45,20 @@ func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) { return n, err } -func (c cksmFile) WriteAt(p []byte, off int64) (n int, err error) { - if isHeader(c.isDB, p, off) { +func (c *cksmFile) WriteAt(p []byte, off int64) (n int, err error) { + if isHeader(p, off) { c.init((*[100]byte)(p)) } // Compute checksums. - if c.computeCksm && !c.inCkpt && len(p) == c.pageSize { + if c.computeCksm && sql3util.ValidPageSize(len(p)) { *(*[8]byte)(p[len(p)-8:]) = cksmCompute(p[:len(p)-8]) } return c.File.WriteAt(p, off) } -func (c cksmFile) Pragma(name string, value string) (string, error) { +func (c *cksmFile) Pragma(name string, value string) (string, error) { switch name { case "checksum_verification": b, ok := sql3util.ParseBool(value) @@ -90,15 +71,15 @@ func (c cksmFile) Pragma(name string, value string) (string, error) { return "1", nil case "page_size": - if c.computeCksm { + if c.computeCksm && value != "" { // Do not allow page size changes on a checksum database. - return strconv.Itoa(c.pageSize), nil + return "", nil } } return "", _NOTFOUND } -func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic { +func (c *cksmFile) DeviceCharacteristics() DeviceCharacteristic { ret := c.File.DeviceCharacteristics() if c.verifyCksm { ret &^= IOCAP_SUBPAGE_READ @@ -106,13 +87,8 @@ func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic { return ret } -func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode { - switch op { - case _FCNTL_CKPT_START: - c.inCkpt = true - case _FCNTL_CKPT_DONE: - c.inCkpt = false - case _FCNTL_PRAGMA: +func (c *cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode { + if op == _FCNTL_PRAGMA { rc := vfsFileControlImpl(ctx, mod, c, op, pArg) if rc != _NOTFOUND { return rc @@ -121,24 +97,26 @@ func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpco return vfsFileControlImpl(ctx, mod, c.File, op, pArg) } -func (f *cksmFlags) init(header *[100]byte) { - f.pageSize = 256 * int(binary.LittleEndian.Uint16(header[16:18])) - if r := header[20] == 8; r != f.computeCksm { - f.computeCksm = r - f.verifyCksm = r - } - if !sql3util.ValidPageSize(f.pageSize) { - f.computeCksm = false - f.verifyCksm = false +func (c *cksmFile) init(header *[100]byte) { + if r := header[20] == 8; r != c.computeCksm { + c.computeCksm = r + c.verifyCksm = r } } -func isHeader(isDB bool, p []byte, off int64) bool { - check := sql3util.ValidPageSize(len(p)) - if isDB { - check = off == 0 && len(p) >= 100 +func (c *cksmFile) SharedMemory() SharedMemory { + if f, ok := c.File.(FileSharedMemory); ok { + return f.SharedMemory() } - return check && bytes.HasPrefix(p, []byte("SQLite format 3\000")) + return nil +} + +func (c *cksmFile) Unwrap() File { + return c.File +} + +func isHeader(p []byte, off int64) bool { + return off == 0 && len(p) >= 100 && bytes.HasPrefix(p, []byte("SQLite format 3\000")) } func cksmCompute(a []byte) (cksm [8]byte) { @@ -155,14 +133,3 @@ func cksmCompute(a []byte) (cksm [8]byte) { binary.LittleEndian.PutUint32(cksm[4:8], s2) return } - -func (c cksmFile) SharedMemory() SharedMemory { - if f, ok := c.File.(FileSharedMemory); ok { - return f.SharedMemory() - } - return nil -} - -func (c cksmFile) Unwrap() File { - return c.File -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go index 8e65ca660..06906c961 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go @@ -75,6 +75,9 @@ func (vfsOS) Access(name string, flags AccessFlag) (bool, error) { func (vfsOS) Open(name string, flags OpenFlag) (File, OpenFlag, error) { // notest // OpenFilename is called instead + if name == "" { + return vfsOS{}.OpenFilename(nil, flags) + } return nil, 0, _CANTOPEN } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go index 965c3b1a6..be16b3dde 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go @@ -56,7 +56,7 @@ func (n *Filename) Journal() string { return n.path("sqlite3_filename_journal") } -// Journal returns the name of the corresponding WAL file. +// WAL returns the name of the corresponding WAL file. // // https://sqlite.org/c3ref/filename_database.html func (n *Filename) WAL() string { diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go index b99070496..e304f6d58 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go @@ -2,40 +2,39 @@ package memdb import ( "io" + "strings" "sync" "time" "github.com/ncruces/go-sqlite3" + "github.com/ncruces/go-sqlite3/util/vfsutil" "github.com/ncruces/go-sqlite3/vfs" ) const sectorSize = 65536 -// Ensure sectorSize is a multiple of 64K (the largest page size). -var _ [0]struct{} = [sectorSize & 65535]struct{}{} - type memVFS struct{} func (memVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) { // For simplicity, we do not support reading or writing data // across "sector" boundaries. - // - // This is not a problem for most SQLite file types: - // - databases, which only do page aligned reads/writes; - // - temp journals, as used by the sorter, which does the same: - // https://github.com/sqlite/sqlite/blob/b74eb0/src/vdbesort.c#L409-L412 - // - // We refuse to open all other file types, - // but returning OPEN_MEMORY means SQLite won't ask us to. - const types = vfs.OPEN_MAIN_DB | vfs.OPEN_TEMP_DB | - vfs.OPEN_TRANSIENT_DB | vfs.OPEN_TEMP_JOURNAL - if flags&types == 0 { + // This is not a problem for SQLite database files. + const databases = vfs.OPEN_MAIN_DB | vfs.OPEN_TEMP_DB | vfs.OPEN_TRANSIENT_DB + + // Temp journals, as used by the sorter, use SliceFile. + if flags&vfs.OPEN_TEMP_JOURNAL != 0 { + return &vfsutil.SliceFile{}, flags | vfs.OPEN_MEMORY, nil + } + + // Refuse to open all other file types. + // Returning OPEN_MEMORY means SQLite won't ask us to. + if flags&databases == 0 { // notest // OPEN_MEMORY return nil, flags, sqlite3.CANTOPEN } // A shared database has a name that begins with "/". - shared := len(name) > 1 && name[0] == '/' + shared := strings.HasPrefix(name, "/") var db *memDB if shared { @@ -76,18 +75,16 @@ func (memVFS) FullPathname(name string) (string, error) { type memDB struct { name string + // +checklocks:lockMtx + waiter *sync.Cond // +checklocks:dataMtx data []*[sectorSize]byte - // +checklocks:dataMtx - size int64 - - // +checklocks:memoryMtx - refs int32 - shared int32 // +checklocks:lockMtx - pending bool // +checklocks:lockMtx - reserved bool // +checklocks:lockMtx - waiter *sync.Cond // +checklocks:lockMtx + size int64 // +checklocks:dataMtx + refs int32 // +checklocks:memoryMtx + shared int32 // +checklocks:lockMtx + pending bool // +checklocks:lockMtx + reserved bool // +checklocks:lockMtx lockMtx sync.Mutex dataMtx sync.RWMutex @@ -129,7 +126,7 @@ func (m *memFile) ReadAt(b []byte, off int64) (n int, err error) { base := off / sectorSize rest := off % sectorSize have := int64(sectorSize) - if base == int64(len(m.data))-1 { + if m.size < off+int64(len(b)) { have = modRoundUp(m.size, sectorSize) } n = copy(b, (*m.data[base])[rest:have]) @@ -150,22 +147,37 @@ func (m *memFile) WriteAt(b []byte, off int64) (n int, err error) { m.data = append(m.data, new([sectorSize]byte)) } n = copy((*m.data[base])[rest:], b) + if size := off + int64(n); size > m.size { + m.size = size + } if n < len(b) { // notest // assume writes are page aligned return n, io.ErrShortWrite } - if size := off + int64(len(b)); size > m.size { - m.size = size - } return n, nil } +func (m *memFile) Size() (int64, error) { + m.dataMtx.RLock() + defer m.dataMtx.RUnlock() + return m.size, nil +} + func (m *memFile) Truncate(size int64) error { m.dataMtx.Lock() defer m.dataMtx.Unlock() return m.truncate(size) } +func (m *memFile) SizeHint(size int64) error { + m.dataMtx.Lock() + defer m.dataMtx.Unlock() + if size > m.size { + return m.truncate(size) + } + return nil +} + // +checklocks:m.dataMtx func (m *memFile) truncate(size int64) error { if size < m.size { @@ -185,16 +197,6 @@ func (m *memFile) truncate(size int64) error { return nil } -func (m *memFile) Sync(flag vfs.SyncFlag) error { - return nil -} - -func (m *memFile) Size() (int64, error) { - m.dataMtx.RLock() - defer m.dataMtx.RUnlock() - return m.size, nil -} - func (m *memFile) Lock(lock vfs.LockLevel) error { if m.lock >= lock { return nil @@ -278,31 +280,24 @@ func (m *memFile) CheckReservedLock() (bool, error) { return m.reserved, nil } -func (m *memFile) SectorSize() int { +func (m *memFile) LockState() vfs.LockLevel { + return m.lock +} + +func (*memFile) Sync(flag vfs.SyncFlag) error { return nil } + +func (*memFile) SectorSize() int { // notest // IOCAP_POWERSAFE_OVERWRITE return sectorSize } -func (m *memFile) DeviceCharacteristics() vfs.DeviceCharacteristic { +func (*memFile) DeviceCharacteristics() vfs.DeviceCharacteristic { return vfs.IOCAP_ATOMIC | vfs.IOCAP_SEQUENTIAL | vfs.IOCAP_SAFE_APPEND | vfs.IOCAP_POWERSAFE_OVERWRITE } -func (m *memFile) SizeHint(size int64) error { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - if size > m.size { - return m.truncate(size) - } - return nil -} - -func (m *memFile) LockState() vfs.LockLevel { - return m.lock -} - func divRoundUp(a, b int64) int64 { return (a + b - 1) / b } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go index 2656ddb49..aef81c3f2 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go @@ -148,7 +148,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag if pOutFlags != 0 { util.Write32(mod, pOutFlags, flags) } - file = cksmWrapFile(name, flags, file) + file = cksmWrapFile(file, flags) vfsFileRegister(ctx, mod, pFile, file) return _OK } |
