mirror of
https://github.com/datarhei/core.git
synced 2025-10-06 16:37:04 +08:00
185 lines
3.1 KiB
Go
185 lines
3.1 KiB
Go
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
|
|
}
|
|
}
|
|
}
|