cachefs/pkg/fs/metadata.go
2022-03-17 00:47:45 +01:00

109 lines
1.9 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"`
preload bool `json:"-"`
}
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) Preload() bool {
md.mu.Lock()
defer md.mu.Unlock()
if md.preload {
return true
}
md.preload = true
return false
}
func (md *Metadata) UnlockPreload() {
md.mu.Lock()
defer md.mu.Unlock()
md.preload = false
}
func (md *Metadata) Stat() (os.FileInfo, error) {
if md.f == nil {
err := md.openCacheFile()
if err != nil {
return nil, err
}
}
return md.f.Stat()
}