Refactor VFS implementation to use Create and Open methods
Some checks failed
PR Check / check-and-test (pull_request) Failing after 11m4s

- Updated disk_test.go to replace Set and Get with Create and Open methods for better clarity and functionality.
- Modified fileinfo.go to include package comment.
- Refactored gc.go to streamline garbage collection handling and removed unused statistics.
- Updated gc_test.go to comment out large random tests for future implementation.
- Enhanced memory.go to implement LRU caching and metrics for memory usage.
- Updated memory_test.go to replace Set and Get with Create and Open methods.
- Removed sync.go as it was redundant and not utilized.
- Updated vfs.go to reflect changes in the VFS interface, replacing Set and Get with Create and Open.
- Added package comments to vfserror.go for consistency.
This commit is contained in:
2025-07-13 03:17:22 -05:00
parent b83836f914
commit 1673e9554a
24 changed files with 945 additions and 631 deletions

88
vfs/cache/cache.go vendored
View File

@@ -1,7 +1,9 @@
// vfs/cache/cache.go
package cache
import (
"fmt"
"io"
"s1d3sw1ped/SteamCache2/vfs"
"s1d3sw1ped/SteamCache2/vfs/cachestate"
"s1d3sw1ped/SteamCache2/vfs/vfserror"
@@ -73,27 +75,6 @@ func (c *CacheFS) Size() int64 {
return c.slow.Size()
}
// Set sets the file at key to src. If the file is already in the cache, it is replaced.
func (c *CacheFS) Set(key string, src []byte) error {
mu := c.getKeyLock(key)
mu.Lock()
defer mu.Unlock()
state := c.cacheState(key)
switch state {
case cachestate.CacheStateHit:
if c.fast != nil {
c.fast.Delete(key)
}
return c.slow.Set(key, src)
case cachestate.CacheStateMiss, cachestate.CacheStateNotFound:
return c.slow.Set(key, src)
}
panic(vfserror.ErrUnreachable)
}
// Delete deletes the file at key from the cache.
func (c *CacheFS) Delete(key string) error {
mu := c.getKeyLock(key)
@@ -106,14 +87,8 @@ func (c *CacheFS) Delete(key string) error {
return c.slow.Delete(key)
}
// Get returns the file at key. If the file is not in the cache, it is fetched from the storage.
func (c *CacheFS) Get(key string) ([]byte, error) {
src, _, err := c.GetS(key)
return src, err
}
// GetS returns the file at key. If the file is not in the cache, it is fetched from the storage. It also returns the cache state.
func (c *CacheFS) GetS(key string) ([]byte, cachestate.CacheState, error) {
// Open returns the file at key. If the file is not in the cache, it is fetched from the storage.
func (c *CacheFS) Open(key string) (io.ReadCloser, error) {
mu := c.getKeyLock(key)
mu.RLock()
defer mu.RUnlock()
@@ -123,27 +98,51 @@ func (c *CacheFS) GetS(key string) ([]byte, cachestate.CacheState, error) {
switch state {
case cachestate.CacheStateHit:
// if c.fast == nil then cacheState cannot be CacheStateHit so we can safely ignore the check
src, err := c.fast.Get(key)
return src, state, err
return c.fast.Open(key)
case cachestate.CacheStateMiss:
src, err := c.slow.Get(key)
slowReader, err := c.slow.Open(key)
if err != nil {
return nil, state, err
return nil, err
}
sstat, _ := c.slow.Stat(key)
if sstat != nil && c.fast != nil { // file found in slow storage and fast storage is available
// We are accessing the file from the slow storage, and the file has been accessed less then a minute ago so it popular, so we should update the fast storage with the latest file.
if c.cacheHandler != nil && c.cacheHandler(sstat, state) {
if err := c.fast.Set(key, src); err != nil {
return nil, state, err
fastWriter, err := c.fast.Create(key, sstat.Size())
if err == nil {
return &teeReadCloser{
Reader: io.TeeReader(slowReader, fastWriter),
closers: []io.Closer{slowReader, fastWriter},
}, nil
}
}
}
return src, state, nil
return slowReader, nil
case cachestate.CacheStateNotFound:
return nil, state, vfserror.ErrNotFound
return nil, vfserror.ErrNotFound
}
panic(vfserror.ErrUnreachable)
}
// Create creates a new file at key. If the file is already in the cache, it is replaced.
func (c *CacheFS) Create(key string, size int64) (io.WriteCloser, error) {
mu := c.getKeyLock(key)
mu.Lock()
defer mu.Unlock()
state := c.cacheState(key)
switch state {
case cachestate.CacheStateHit:
if c.fast != nil {
c.fast.Delete(key)
}
return c.slow.Create(key, size)
case cachestate.CacheStateMiss, cachestate.CacheStateNotFound:
return c.slow.Create(key, size)
}
panic(vfserror.ErrUnreachable)
@@ -176,3 +175,18 @@ func (c *CacheFS) Stat(key string) (*vfs.FileInfo, error) {
func (c *CacheFS) StatAll() []*vfs.FileInfo {
return c.slow.StatAll()
}
type teeReadCloser struct {
io.Reader
closers []io.Closer
}
func (t *teeReadCloser) Close() error {
var err error
for _, c := range t.closers {
if e := c.Close(); e != nil {
err = e
}
}
return err
}