diff --git a/util/fsutil/mode.go b/util/fsutil/mode.go index 88b15722..4e0834ab 100644 --- a/util/fsutil/mode.go +++ b/util/fsutil/mode.go @@ -1,4 +1,4 @@ -// Package fsutil implements filesystem utility functions. +// Package fsutil implements filesystem utilities. package fsutil import ( diff --git a/util/ioutil/ioutil.go b/util/ioutil/ioutil.go index 479a5cf5..bbfecdd9 100644 --- a/util/ioutil/ioutil.go +++ b/util/ioutil/ioutil.go @@ -1,2 +1,2 @@ -// Package ioutil implements I/O utility functions. +// Package ioutil implements I/O utilities. package ioutil diff --git a/util/osutil/osutil.go b/util/osutil/osutil.go index 7fbd0478..83444e90 100644 --- a/util/osutil/osutil.go +++ b/util/osutil/osutil.go @@ -1,2 +1,2 @@ -// Package osutil implements operating system utility functions. +// Package osutil implements operating system utilities. package osutil diff --git a/util/vfsutil/wrap.go b/util/vfsutil/wrap.go new file mode 100644 index 00000000..40279792 --- /dev/null +++ b/util/vfsutil/wrap.go @@ -0,0 +1,132 @@ +// Package vtabutil implements virtual filesystem utilities. +package vfsutil + +import ( + "github.com/ncruces/go-sqlite3" + "github.com/ncruces/go-sqlite3/vfs" +) + +// WrapSharedMemory helps wrap [vfs.FileSharedMemory]. +func WrapSharedMemory(f vfs.File) vfs.SharedMemory { + if f, ok := f.(vfs.FileSharedMemory); ok { + return f.SharedMemory() + } + return nil +} + +// WrapChunkSize helps wrap [vfs.FileChunkSize]. +func WrapChunkSize(f vfs.File, size int) { + if f, ok := f.(vfs.FileChunkSize); ok { + f.ChunkSize(size) + } +} + +// WrapSizeHint helps wrap [vfs.FileSizeHint]. +func WrapSizeHint(f vfs.File, size int64) error { + if f, ok := f.(vfs.FileSizeHint); ok { + return f.SizeHint(size) + } + return sqlite3.NOTFOUND +} + +// WrapHasMoved helps wrap [vfs.FileHasMoved]. +func WrapHasMoved(f vfs.File) (bool, error) { + if f, ok := f.(vfs.FileHasMoved); ok { + return f.HasMoved() + } + return false, sqlite3.NOTFOUND +} + +// WrapOverwrite helps wrap [vfs.FileOverwrite]. +func WrapOverwrite(f vfs.File) error { + if f, ok := f.(vfs.FileOverwrite); ok { + return f.Overwrite() + } + return sqlite3.NOTFOUND +} + +// WrapPersistentWAL helps wrap [vfs.FilePersistentWAL]. +func WrapPersistentWAL(f vfs.File) bool { + if f, ok := f.(vfs.FilePersistentWAL); ok { + return f.PersistentWAL() + } + return false +} + +// WrapSetPersistentWAL helps wrap [vfs.FilePersistentWAL]. +func WrapSetPersistentWAL(f vfs.File, keepWAL bool) { + if f, ok := f.(vfs.FilePersistentWAL); ok { + f.SetPersistentWAL(keepWAL) + } +} + +// WrapPowersafeOverwrite helps wrap [vfs.FilePowersafeOverwrite]. +func WrapPowersafeOverwrite(f vfs.File) bool { + if f, ok := f.(vfs.FilePowersafeOverwrite); ok { + return f.PowersafeOverwrite() + } + return false +} + +// WrapSetPowersafeOverwrite helps wrap [vfs.FilePowersafeOverwrite]. +func WrapSetPowersafeOverwrite(f vfs.File, psow bool) { + if f, ok := f.(vfs.FilePowersafeOverwrite); ok { + f.SetPowersafeOverwrite(psow) + } +} + +// WrapCommitPhaseTwo helps wrap [vfs.FileCommitPhaseTwo]. +func WrapCommitPhaseTwo(f vfs.File) error { + if f, ok := f.(vfs.FileCommitPhaseTwo); ok { + return f.CommitPhaseTwo() + } + return sqlite3.NOTFOUND +} + +// WrapBeginAtomicWrite helps wrap [vfs.FileBatchAtomicWrite]. +func WrapBeginAtomicWrite(f vfs.File) error { + if f, ok := f.(vfs.FileBatchAtomicWrite); ok { + return f.BeginAtomicWrite() + } + return sqlite3.NOTFOUND +} + +// WrapCommitAtomicWrite helps wrap [vfs.FileBatchAtomicWrite]. +func WrapCommitAtomicWrite(f vfs.File) error { + if f, ok := f.(vfs.FileBatchAtomicWrite); ok { + return f.CommitAtomicWrite() + } + return sqlite3.NOTFOUND +} + +// WrapRollbackAtomicWrite helps wrap [vfs.FileBatchAtomicWrite]. +func WrapRollbackAtomicWrite(f vfs.File) error { + if f, ok := f.(vfs.FileBatchAtomicWrite); ok { + return f.RollbackAtomicWrite() + } + return sqlite3.NOTFOUND +} + +// WrapCheckpointDone helps wrap [vfs.FileCheckpoint]. +func WrapCheckpointDone(f vfs.File) error { + if f, ok := f.(vfs.FileCheckpoint); ok { + return f.CheckpointDone() + } + return sqlite3.NOTFOUND +} + +// WrapCheckpointStart helps wrap [vfs.FileCheckpoint]. +func WrapCheckpointStart(f vfs.File) error { + if f, ok := f.(vfs.FileCheckpoint); ok { + return f.CheckpointStart() + } + return sqlite3.NOTFOUND +} + +// WrapPragma helps wrap [vfs.FilePragma]. +func WrapPragma(f vfs.File, name, value string) (string, error) { + if f, ok := f.(vfs.FilePragma); ok { + return f.Pragma(name, value) + } + return "", sqlite3.NOTFOUND +} diff --git a/util/vtabutil/vtabutil.go b/util/vtabutil/vtabutil.go index eb797788..ce71e466 100644 --- a/util/vtabutil/vtabutil.go +++ b/util/vtabutil/vtabutil.go @@ -1,2 +1,2 @@ -// Package vtabutil implements virtual table utility functions. +// Package vtabutil implements virtual table utilities. package vtabutil diff --git a/vfs/adiantum/hbsh.go b/vfs/adiantum/hbsh.go index 1d20fea9..a4555b48 100644 --- a/vfs/adiantum/hbsh.go +++ b/vfs/adiantum/hbsh.go @@ -9,6 +9,7 @@ import ( "github.com/ncruces/go-sqlite3" "github.com/ncruces/go-sqlite3/internal/util" + "github.com/ncruces/go-sqlite3/util/vfsutil" "github.com/ncruces/go-sqlite3/vfs" ) @@ -90,10 +91,7 @@ func (h *hbshFile) Pragma(name string, value string) (string, error) { key = h.init.KDF(value) } default: - if f, ok := h.File.(vfs.FilePragma); ok { - return f.Pragma(name, value) - } - return "", sqlite3.NOTFOUND + return vfsutil.WrapPragma(h.File, name, value) } if h.hbsh = h.init.HBSH(key); h.hbsh != nil { @@ -209,92 +207,55 @@ func (h *hbshFile) DeviceCharacteristics() vfs.DeviceCharacteristic { // Wrap optional methods. func (h *hbshFile) SharedMemory() vfs.SharedMemory { - if f, ok := h.File.(vfs.FileSharedMemory); ok { - return f.SharedMemory() - } - return nil + return vfsutil.WrapSharedMemory(h.File) } func (h *hbshFile) ChunkSize(size int) { - if f, ok := h.File.(vfs.FileChunkSize); ok { - size = (size + (blockSize - 1)) &^ (blockSize - 1) // round up - f.ChunkSize(size) - } + size = (size + (blockSize - 1)) &^ (blockSize - 1) // round up + vfsutil.WrapChunkSize(h.File, size) } func (h *hbshFile) SizeHint(size int64) error { - if f, ok := h.File.(vfs.FileSizeHint); ok { - size = (size + (blockSize - 1)) &^ (blockSize - 1) // round up - return f.SizeHint(size) - } - return sqlite3.NOTFOUND + size = (size + (blockSize - 1)) &^ (blockSize - 1) // round up + return vfsutil.WrapSizeHint(h.File, size) } func (h *hbshFile) HasMoved() (bool, error) { - if f, ok := h.File.(vfs.FileHasMoved); ok { - return f.HasMoved() - } - return false, sqlite3.NOTFOUND + return vfsutil.WrapHasMoved(h.File) // notest } func (h *hbshFile) Overwrite() error { - if f, ok := h.File.(vfs.FileOverwrite); ok { - return f.Overwrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapOverwrite(h.File) // notest } func (h *hbshFile) PersistentWAL() bool { - if f, ok := h.File.(vfs.FilePersistentWAL); ok { - return f.PersistentWAL() - } - return false + return vfsutil.WrapPersistentWAL(h.File) // notest } func (h *hbshFile) SetPersistentWAL(keepWAL bool) { - if f, ok := h.File.(vfs.FilePersistentWAL); ok { - f.SetPersistentWAL(keepWAL) - } + vfsutil.WrapSetPersistentWAL(h.File, keepWAL) // notest } func (h *hbshFile) CommitPhaseTwo() error { - if f, ok := h.File.(vfs.FileCommitPhaseTwo); ok { - return f.CommitPhaseTwo() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCommitPhaseTwo(h.File) // notest } func (h *hbshFile) BeginAtomicWrite() error { - if f, ok := h.File.(vfs.FileBatchAtomicWrite); ok { - return f.BeginAtomicWrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapBeginAtomicWrite(h.File) // notest } func (h *hbshFile) CommitAtomicWrite() error { - if f, ok := h.File.(vfs.FileBatchAtomicWrite); ok { - return f.CommitAtomicWrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCommitAtomicWrite(h.File) // notest } func (h *hbshFile) RollbackAtomicWrite() error { - if f, ok := h.File.(vfs.FileBatchAtomicWrite); ok { - return f.RollbackAtomicWrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapRollbackAtomicWrite(h.File) // notest } func (h *hbshFile) CheckpointDone() error { - if f, ok := h.File.(vfs.FileCheckpoint); ok { - return f.CheckpointDone() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCheckpointDone(h.File) // notest } func (h *hbshFile) CheckpointStart() error { - if f, ok := h.File.(vfs.FileCheckpoint); ok { - return f.CheckpointStart() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCheckpointStart(h.File) // notest } diff --git a/vfs/xts/xts.go b/vfs/xts/xts.go index b86eee8b..5805882f 100644 --- a/vfs/xts/xts.go +++ b/vfs/xts/xts.go @@ -8,6 +8,7 @@ import ( "github.com/ncruces/go-sqlite3" "github.com/ncruces/go-sqlite3/internal/util" + "github.com/ncruces/go-sqlite3/util/vfsutil" "github.com/ncruces/go-sqlite3/vfs" ) @@ -85,10 +86,7 @@ func (x *xtsFile) Pragma(name string, value string) (string, error) { key = x.init.KDF(value) } default: - if f, ok := x.File.(vfs.FilePragma); ok { - return f.Pragma(name, value) - } - return "", sqlite3.NOTFOUND + return vfsutil.WrapPragma(x.File, name, value) } if x.cipher = x.init.XTS(key); x.cipher != nil { @@ -205,92 +203,55 @@ func (x *xtsFile) DeviceCharacteristics() vfs.DeviceCharacteristic { // Wrap optional methods. func (x *xtsFile) SharedMemory() vfs.SharedMemory { - if f, ok := x.File.(vfs.FileSharedMemory); ok { - return f.SharedMemory() - } - return nil + return vfsutil.WrapSharedMemory(x.File) } func (x *xtsFile) ChunkSize(size int) { - if f, ok := x.File.(vfs.FileChunkSize); ok { - size = (size + (sectorSize - 1)) &^ (sectorSize - 1) // round up - f.ChunkSize(size) - } + size = (size + (sectorSize - 1)) &^ (sectorSize - 1) // round up + vfsutil.WrapChunkSize(x.File, size) } func (x *xtsFile) SizeHint(size int64) error { - if f, ok := x.File.(vfs.FileSizeHint); ok { - size = (size + (sectorSize - 1)) &^ (sectorSize - 1) // round up - return f.SizeHint(size) - } - return sqlite3.NOTFOUND + size = (size + (sectorSize - 1)) &^ (sectorSize - 1) // round up + return vfsutil.WrapSizeHint(x.File, size) } func (x *xtsFile) HasMoved() (bool, error) { - if f, ok := x.File.(vfs.FileHasMoved); ok { - return f.HasMoved() - } - return false, sqlite3.NOTFOUND + return vfsutil.WrapHasMoved(x.File) // notest } func (x *xtsFile) Overwrite() error { - if f, ok := x.File.(vfs.FileOverwrite); ok { - return f.Overwrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapOverwrite(x.File) // notest } func (x *xtsFile) PersistentWAL() bool { - if f, ok := x.File.(vfs.FilePersistentWAL); ok { - return f.PersistentWAL() - } - return false + return vfsutil.WrapPersistentWAL(x.File) // notest } func (x *xtsFile) SetPersistentWAL(keepWAL bool) { - if f, ok := x.File.(vfs.FilePersistentWAL); ok { - f.SetPersistentWAL(keepWAL) - } + vfsutil.WrapSetPersistentWAL(x.File, keepWAL) // notest } func (x *xtsFile) CommitPhaseTwo() error { - if f, ok := x.File.(vfs.FileCommitPhaseTwo); ok { - return f.CommitPhaseTwo() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCommitPhaseTwo(x.File) // notest } func (x *xtsFile) BeginAtomicWrite() error { - if f, ok := x.File.(vfs.FileBatchAtomicWrite); ok { - return f.BeginAtomicWrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapBeginAtomicWrite(x.File) // notest } func (x *xtsFile) CommitAtomicWrite() error { - if f, ok := x.File.(vfs.FileBatchAtomicWrite); ok { - return f.CommitAtomicWrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCommitAtomicWrite(x.File) // notest } func (x *xtsFile) RollbackAtomicWrite() error { - if f, ok := x.File.(vfs.FileBatchAtomicWrite); ok { - return f.RollbackAtomicWrite() - } - return sqlite3.NOTFOUND + return vfsutil.WrapRollbackAtomicWrite(x.File) // notest } func (x *xtsFile) CheckpointDone() error { - if f, ok := x.File.(vfs.FileCheckpoint); ok { - return f.CheckpointDone() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCheckpointDone(x.File) // notest } func (x *xtsFile) CheckpointStart() error { - if f, ok := x.File.(vfs.FileCheckpoint); ok { - return f.CheckpointStart() - } - return sqlite3.NOTFOUND + return vfsutil.WrapCheckpointStart(x.File) // notest }