151 lines
3.0 KiB
Go
151 lines
3.0 KiB
Go
package cachedvfs
|
|
|
|
import (
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/vfs"
|
|
)
|
|
|
|
type FS struct {
|
|
fs vfs.FS
|
|
enabled atomic.Bool
|
|
|
|
directoryExistsCache collections.SyncMap[string, bool]
|
|
fileExistsCache collections.SyncMap[string, bool]
|
|
getAccessibleEntriesCache collections.SyncMap[string, vfs.Entries]
|
|
realpathCache collections.SyncMap[string, string]
|
|
statCache collections.SyncMap[string, vfs.FileInfo]
|
|
}
|
|
|
|
var _ vfs.FS = (*FS)(nil)
|
|
|
|
func From(fs vfs.FS) *FS {
|
|
fsys := &FS{fs: fs}
|
|
fsys.enabled.Store(true)
|
|
return fsys
|
|
}
|
|
|
|
func (fsys *FS) DisableAndClearCache() {
|
|
if fsys.enabled.CompareAndSwap(true, false) {
|
|
fsys.ClearCache()
|
|
}
|
|
}
|
|
|
|
func (fsys *FS) Enable() {
|
|
fsys.enabled.Store(true)
|
|
}
|
|
|
|
func (fsys *FS) ClearCache() {
|
|
fsys.directoryExistsCache.Clear()
|
|
fsys.fileExistsCache.Clear()
|
|
fsys.getAccessibleEntriesCache.Clear()
|
|
fsys.realpathCache.Clear()
|
|
fsys.statCache.Clear()
|
|
}
|
|
|
|
func (fsys *FS) DirectoryExists(path string) bool {
|
|
if fsys.enabled.Load() {
|
|
if ret, ok := fsys.directoryExistsCache.Load(path); ok {
|
|
return ret
|
|
}
|
|
}
|
|
|
|
ret := fsys.fs.DirectoryExists(path)
|
|
|
|
if fsys.enabled.Load() {
|
|
fsys.directoryExistsCache.Store(path, ret)
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (fsys *FS) FileExists(path string) bool {
|
|
if fsys.enabled.Load() {
|
|
if ret, ok := fsys.fileExistsCache.Load(path); ok {
|
|
return ret
|
|
}
|
|
}
|
|
|
|
ret := fsys.fs.FileExists(path)
|
|
|
|
if fsys.enabled.Load() {
|
|
fsys.fileExistsCache.Store(path, ret)
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (fsys *FS) GetAccessibleEntries(path string) vfs.Entries {
|
|
if fsys.enabled.Load() {
|
|
if ret, ok := fsys.getAccessibleEntriesCache.Load(path); ok {
|
|
return ret
|
|
}
|
|
}
|
|
|
|
ret := fsys.fs.GetAccessibleEntries(path)
|
|
|
|
if fsys.enabled.Load() {
|
|
fsys.getAccessibleEntriesCache.Store(path, ret)
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (fsys *FS) ReadFile(path string) (contents string, ok bool) {
|
|
return fsys.fs.ReadFile(path)
|
|
}
|
|
|
|
func (fsys *FS) Realpath(path string) string {
|
|
if fsys.enabled.Load() {
|
|
if ret, ok := fsys.realpathCache.Load(path); ok {
|
|
return ret
|
|
}
|
|
}
|
|
|
|
ret := fsys.fs.Realpath(path)
|
|
|
|
if fsys.enabled.Load() {
|
|
fsys.realpathCache.Store(path, ret)
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (fsys *FS) Remove(path string) error {
|
|
return fsys.fs.Remove(path)
|
|
}
|
|
|
|
func (fsys *FS) Chtimes(path string, aTime time.Time, mTime time.Time) error {
|
|
return fsys.fs.Chtimes(path, aTime, mTime)
|
|
}
|
|
|
|
func (fsys *FS) Stat(path string) vfs.FileInfo {
|
|
if fsys.enabled.Load() {
|
|
if ret, ok := fsys.statCache.Load(path); ok {
|
|
return ret
|
|
}
|
|
}
|
|
|
|
ret := fsys.fs.Stat(path)
|
|
|
|
if fsys.enabled.Load() {
|
|
fsys.statCache.Store(path, ret)
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (fsys *FS) UseCaseSensitiveFileNames() bool {
|
|
return fsys.fs.UseCaseSensitiveFileNames()
|
|
}
|
|
|
|
func (fsys *FS) WalkDir(root string, walkFn vfs.WalkDirFunc) error {
|
|
return fsys.fs.WalkDir(root, walkFn)
|
|
}
|
|
|
|
func (fsys *FS) WriteFile(path string, data string, writeByteOrderMark bool) error {
|
|
return fsys.fs.WriteFile(path, data, writeByteOrderMark)
|
|
}
|