feat: add upstream and verbose flags to command line interface
All checks were successful
Release Tag / release (push) Successful in 13s
All checks were successful
Release Tag / release (push) Successful in 13s
feat: add upstream support allowing to chain cache servers if needed fix: tweaked garbage collection to be better
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"s1d3sw1ped/SteamCache2/steamcache/logger"
|
||||
"s1d3sw1ped/SteamCache2/vfs"
|
||||
"s1d3sw1ped/SteamCache2/vfs/vfserror"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -82,6 +84,8 @@ func (d *DiskFS) init() {
|
||||
Str("name", d.Name()).
|
||||
Str("root", d.root).
|
||||
Str("capacity", units.HumanSize(float64(d.capacity))).
|
||||
Str("size", units.HumanSize(float64(d.Size()))).
|
||||
Str("files", fmt.Sprint(len(d.info))).
|
||||
Str("duration", time.Since(tstart).String()).
|
||||
Msg("init")
|
||||
}
|
||||
@@ -105,7 +109,8 @@ func (d *DiskFS) walk(path string) {
|
||||
}
|
||||
|
||||
d.mu.Lock()
|
||||
k := npath[len(d.root)+1:]
|
||||
k := strings.ReplaceAll(npath[len(d.root)+1:], "\\", "/")
|
||||
logger.Logger.Debug().Str("name", k).Str("root", d.root).Msg("walk")
|
||||
d.info[k] = vfs.NewFileInfoFromOS(info, k)
|
||||
d.mu.Unlock()
|
||||
|
||||
@@ -124,9 +129,10 @@ func (d *DiskFS) Name() string {
|
||||
}
|
||||
|
||||
func (d *DiskFS) Size() int64 {
|
||||
var size int64
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
var size int64
|
||||
for _, v := range d.info {
|
||||
size += v.Size()
|
||||
}
|
||||
@@ -134,24 +140,34 @@ func (d *DiskFS) Size() int64 {
|
||||
}
|
||||
|
||||
func (d *DiskFS) Set(key string, src []byte) error {
|
||||
if key == "" {
|
||||
return vfserror.ErrInvalidKey
|
||||
}
|
||||
if key[0] == '/' {
|
||||
return vfserror.ErrInvalidKey
|
||||
}
|
||||
|
||||
if d.capacity > 0 {
|
||||
if size := d.Size() + int64(len(src)); size > d.capacity {
|
||||
return vfserror.ErrDiskFull
|
||||
}
|
||||
}
|
||||
|
||||
logger.Logger.Debug().Str("name", key).Str("root", d.root).Msg("set")
|
||||
|
||||
if _, err := d.Stat(key); err == nil {
|
||||
logger.Logger.Debug().Str("name", key).Str("root", d.root).Msg("delete")
|
||||
d.Delete(key)
|
||||
}
|
||||
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
os.MkdirAll(filepath.Join(d.root, filepath.Dir(key)), 0755)
|
||||
if err := os.WriteFile(filepath.Join(d.root, key), src, 0644); err != nil {
|
||||
os.MkdirAll(d.root+"/"+filepath.Dir(key), 0755)
|
||||
if err := os.WriteFile(d.root+"/"+key, src, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fi, err := os.Stat(filepath.Join(d.root, key))
|
||||
fi, err := os.Stat(d.root + "/" + key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -163,6 +179,13 @@ func (d *DiskFS) Set(key string, src []byte) error {
|
||||
|
||||
// Delete deletes the value of key.
|
||||
func (d *DiskFS) Delete(key string) error {
|
||||
if key == "" {
|
||||
return vfserror.ErrInvalidKey
|
||||
}
|
||||
if key[0] == '/' {
|
||||
return vfserror.ErrInvalidKey
|
||||
}
|
||||
|
||||
_, err := d.Stat(key)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -170,6 +193,7 @@ func (d *DiskFS) Delete(key string) error {
|
||||
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
delete(d.info, key)
|
||||
if err := os.Remove(filepath.Join(d.root, key)); err != nil {
|
||||
return err
|
||||
@@ -180,6 +204,13 @@ func (d *DiskFS) Delete(key string) error {
|
||||
|
||||
// Get gets the value of key and returns it.
|
||||
func (d *DiskFS) Get(key string) ([]byte, error) {
|
||||
if key == "" {
|
||||
return nil, vfserror.ErrInvalidKey
|
||||
}
|
||||
if key[0] == '/' {
|
||||
return nil, vfserror.ErrInvalidKey
|
||||
}
|
||||
|
||||
_, err := d.Stat(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -198,25 +229,23 @@ func (d *DiskFS) Get(key string) ([]byte, error) {
|
||||
|
||||
// Stat returns the FileInfo of key. If key is not found in the cache, it will stat the file on disk. If the file is not found on disk, it will return vfs.ErrNotFound.
|
||||
func (d *DiskFS) Stat(key string) (*vfs.FileInfo, error) {
|
||||
d.mu.Lock()
|
||||
fi, ok := d.info[key]
|
||||
d.mu.Unlock() // unlock before statting the file
|
||||
|
||||
if !ok {
|
||||
fii, err := os.Stat(filepath.Join(d.root, key))
|
||||
if err != nil {
|
||||
return nil, vfserror.ErrNotFound
|
||||
}
|
||||
|
||||
d.mu.Lock() // relock to update the info map
|
||||
defer d.mu.Unlock() // nothing else needs to unlock before returning
|
||||
|
||||
d.info[key] = vfs.NewFileInfoFromOS(fii, key)
|
||||
fi = d.info[key]
|
||||
// fallthrough to return fi with shiny new info
|
||||
if key == "" {
|
||||
return nil, vfserror.ErrInvalidKey
|
||||
}
|
||||
if key[0] == '/' {
|
||||
return nil, vfserror.ErrInvalidKey
|
||||
}
|
||||
|
||||
return fi, nil
|
||||
logger.Logger.Debug().Str("name", key).Str("root", d.root).Msg("stat")
|
||||
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if fi, ok := d.info[key]; !ok {
|
||||
return nil, vfserror.ErrNotFound
|
||||
} else {
|
||||
return fi, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *DiskFS) StatAll() []*vfs.FileInfo {
|
||||
|
||||
@@ -85,3 +85,62 @@ func TestInit(t *testing.T) {
|
||||
t.Errorf("Stat failed: got %s, want %s", s.Name(), "key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiskSizeDiscrepancy(t *testing.T) {
|
||||
t.Parallel()
|
||||
td := t.TempDir()
|
||||
|
||||
assumedSize := int64(6 + 5 + 6) // 6 + 5 + 6 bytes for key, key1, key2
|
||||
os.WriteFile(filepath.Join(td, "key2"), []byte("value2"), 0644)
|
||||
|
||||
m := New(td, 1024)
|
||||
if 6 != m.Size() {
|
||||
t.Errorf("Size failed: got %d, want %d", m.Size(), 6)
|
||||
}
|
||||
|
||||
if err := m.Set("key", []byte("value")); err != nil {
|
||||
t.Errorf("Set failed: %v", err)
|
||||
}
|
||||
|
||||
if err := m.Set("key1", []byte("value1")); err != nil {
|
||||
t.Errorf("Set failed: %v", err)
|
||||
}
|
||||
|
||||
if assumedSize != m.Size() {
|
||||
t.Errorf("Size failed: got %d, want %d", m.Size(), assumedSize)
|
||||
}
|
||||
|
||||
if d, err := m.Get("key"); err != nil {
|
||||
t.Errorf("Get failed: %v", err)
|
||||
} else if string(d) != "value" {
|
||||
t.Errorf("Get failed: got %s, want %s", d, "value")
|
||||
}
|
||||
|
||||
if d, err := m.Get("key1"); err != nil {
|
||||
t.Errorf("Get failed: %v", err)
|
||||
} else if string(d) != "value1" {
|
||||
t.Errorf("Get failed: got %s, want %s", d, "value1")
|
||||
}
|
||||
|
||||
m = New(td, 1024)
|
||||
|
||||
if assumedSize != m.Size() {
|
||||
t.Errorf("Size failed: got %d, want %d", m.Size(), assumedSize)
|
||||
}
|
||||
|
||||
if d, err := m.Get("key"); err != nil {
|
||||
t.Errorf("Get failed: %v", err)
|
||||
} else if string(d) != "value" {
|
||||
t.Errorf("Get failed: got %s, want %s", d, "value")
|
||||
}
|
||||
|
||||
if d, err := m.Get("key1"); err != nil {
|
||||
t.Errorf("Get failed: %v", err)
|
||||
} else if string(d) != "value1" {
|
||||
t.Errorf("Get failed: got %s, want %s", d, "value1")
|
||||
}
|
||||
|
||||
if assumedSize != m.Size() {
|
||||
t.Errorf("Size failed: got %d, want %d", m.Size(), assumedSize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ type FileInfo struct {
|
||||
ATime time.Time
|
||||
}
|
||||
|
||||
func NewFileInfo(name string, size int64, modTime time.Time) *FileInfo {
|
||||
func NewFileInfo(key string, size int64, modTime time.Time) *FileInfo {
|
||||
return &FileInfo{
|
||||
name: name,
|
||||
name: key,
|
||||
size: size,
|
||||
MTime: modTime,
|
||||
ATime: time.Now(),
|
||||
|
||||
@@ -73,9 +73,8 @@ func (m *MemoryFS) Set(key string, src []byte) error {
|
||||
int64(len(src)),
|
||||
time.Now(),
|
||||
),
|
||||
data: make([]byte, len(src)),
|
||||
data: src,
|
||||
}
|
||||
copy(m.files[key].data, src)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ package vfserror
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrInvalidKey is returned when a key is invalid.
|
||||
ErrInvalidKey = errors.New("vfs: invalid key")
|
||||
|
||||
// ErrUnreachable is returned when a code path is unreachable.
|
||||
ErrUnreachable = errors.New("unreachable")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user