mirror of
https://github.com/datarhei/core.git
synced 2025-10-08 17:30:52 +08:00
Replace memfs storage backend with a faster one
This commit is contained in:
184
io/fs/mem_storage.go
Normal file
184
io/fs/mem_storage.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sync"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
)
|
||||
|
||||
type memStorage interface {
|
||||
Delete(key string) (*memFile, bool)
|
||||
Store(key string, value *memFile) (*memFile, bool)
|
||||
Load(key string) (value *memFile, ok bool)
|
||||
LoadAndCopy(key string) (value *memFile, ok bool)
|
||||
Has(key string) bool
|
||||
Range(f func(key string, value *memFile) bool)
|
||||
}
|
||||
|
||||
type mapOfStorage struct {
|
||||
lock *xsync.RBMutex
|
||||
files *xsync.MapOf[string, *memFile]
|
||||
}
|
||||
|
||||
func newMapOfStorage() memStorage {
|
||||
m := &mapOfStorage{
|
||||
lock: xsync.NewRBMutex(),
|
||||
files: xsync.NewMapOf[string, *memFile](),
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mapOfStorage) Delete(key string) (*memFile, bool) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
return m.files.LoadAndDelete(key)
|
||||
}
|
||||
|
||||
func (m *mapOfStorage) Store(key string, value *memFile) (*memFile, bool) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
return m.files.LoadAndStore(key, value)
|
||||
}
|
||||
|
||||
func (m *mapOfStorage) Load(key string) (*memFile, bool) {
|
||||
token := m.lock.RLock()
|
||||
defer m.lock.RUnlock(token)
|
||||
|
||||
return m.files.Load(key)
|
||||
}
|
||||
|
||||
func (m *mapOfStorage) LoadAndCopy(key string) (*memFile, bool) {
|
||||
token := m.lock.RLock()
|
||||
defer m.lock.RUnlock(token)
|
||||
|
||||
v, ok := m.files.Load(key)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
f := &memFile{
|
||||
memFileInfo: memFileInfo{
|
||||
name: v.name,
|
||||
size: v.size,
|
||||
dir: v.dir,
|
||||
lastMod: v.lastMod,
|
||||
linkTo: v.linkTo,
|
||||
},
|
||||
r: nil,
|
||||
}
|
||||
|
||||
if v.data != nil {
|
||||
f.data = bytes.NewBuffer(v.data.Bytes())
|
||||
}
|
||||
|
||||
return f, true
|
||||
}
|
||||
|
||||
func (m *mapOfStorage) Has(key string) bool {
|
||||
token := m.lock.RLock()
|
||||
defer m.lock.RUnlock(token)
|
||||
|
||||
_, ok := m.files.Load(key)
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m *mapOfStorage) Range(f func(key string, value *memFile) bool) {
|
||||
token := m.lock.RLock()
|
||||
defer m.lock.RUnlock(token)
|
||||
|
||||
m.files.Range(f)
|
||||
}
|
||||
|
||||
type mapStorage struct {
|
||||
lock sync.RWMutex
|
||||
files map[string]*memFile
|
||||
}
|
||||
|
||||
func newMapStorage() memStorage {
|
||||
m := &mapStorage{
|
||||
files: map[string]*memFile{},
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mapStorage) Delete(key string) (*memFile, bool) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
v, ok := m.files[key]
|
||||
delete(m.files, key)
|
||||
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func (m *mapStorage) Store(key string, value *memFile) (*memFile, bool) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
v, ok := m.files[key]
|
||||
m.files[key] = value
|
||||
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func (m *mapStorage) Load(key string) (*memFile, bool) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
v, ok := m.files[key]
|
||||
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func (m *mapStorage) LoadAndCopy(key string) (*memFile, bool) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
v, ok := m.files[key]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
f := &memFile{
|
||||
memFileInfo: memFileInfo{
|
||||
name: v.name,
|
||||
size: v.size,
|
||||
dir: v.dir,
|
||||
lastMod: v.lastMod,
|
||||
linkTo: v.linkTo,
|
||||
},
|
||||
r: nil,
|
||||
}
|
||||
|
||||
if v.data != nil {
|
||||
f.data = bytes.NewBuffer(v.data.Bytes())
|
||||
}
|
||||
|
||||
return f, true
|
||||
}
|
||||
|
||||
func (m *mapStorage) Has(key string) bool {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
_, ok := m.files[key]
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m *mapStorage) Range(f func(key string, value *memFile) bool) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
for k, v := range m.files {
|
||||
if !f(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user