92 lines
1.7 KiB
Go
92 lines
1.7 KiB
Go
// Copyright (C) 2022 Marius Schellenberger
|
|
|
|
package fs
|
|
|
|
import (
|
|
"os"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
func now() int64 {
|
|
return time.Now().UTC().Unix()
|
|
}
|
|
|
|
type MetadataMap map[string]*Metadata
|
|
|
|
type Metadata struct {
|
|
mu sync.RWMutex `json:"-"`
|
|
fs *FS `json:"-"`
|
|
f *os.File `json:"-"`
|
|
name string `json:"-"`
|
|
Size int64 `json:"s"`
|
|
Atime int64 `json:"a"`
|
|
Chunks Chunks `json:"c"`
|
|
}
|
|
|
|
func (md *Metadata) Delete() error {
|
|
md.mu.Lock()
|
|
defer md.mu.Unlock()
|
|
md.Chunks = Chunks{}
|
|
md.f.Close()
|
|
md.f = nil
|
|
atomic.StoreInt64(&md.Atime, now())
|
|
return md.fs.RemoveDst(md.name)
|
|
}
|
|
|
|
func (md *Metadata) HasChunk(off int64, n int) bool {
|
|
md.mu.RLock()
|
|
defer md.mu.RUnlock()
|
|
return md.Chunks.Exists(off, n, md.Size)
|
|
}
|
|
|
|
func (md *Metadata) AddChunk(off int64, n int) {
|
|
md.mu.Lock()
|
|
defer md.mu.Unlock()
|
|
md.Chunks.Add(off, n)
|
|
}
|
|
|
|
func (md *Metadata) ReadAt(p []byte, pos int64) (int, error) {
|
|
if md.f == nil {
|
|
err := md.openCacheFile()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
atomic.StoreInt64(&md.Atime, now())
|
|
return md.f.ReadAt(p, pos)
|
|
}
|
|
|
|
func (md *Metadata) WriteAt(data []byte, pos int64) (int, error) {
|
|
if md.f == nil {
|
|
err := md.openCacheFile()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
atomic.StoreInt64(&md.Atime, now())
|
|
md.fs.q.Add(len(data))
|
|
return md.f.WriteAt(data, pos)
|
|
}
|
|
|
|
func (md *Metadata) openCacheFile() error {
|
|
md.mu.Lock()
|
|
defer md.mu.Unlock()
|
|
if md.f != nil {
|
|
return nil
|
|
}
|
|
f, err := md.fs.openCacheFile(md.name, md.Size)
|
|
md.f = f
|
|
return err
|
|
}
|
|
|
|
func (md *Metadata) Stat() (os.FileInfo, error) {
|
|
if md.f == nil {
|
|
err := md.openCacheFile()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return md.f.Stat()
|
|
}
|