// vfs/gc/gc.go package gc import ( "io" "s1d3sw1ped/SteamCache2/vfs" "s1d3sw1ped/SteamCache2/vfs/disk" "s1d3sw1ped/SteamCache2/vfs/memory" ) // GCAlgorithm represents different garbage collection strategies type GCAlgorithm string const ( LRU GCAlgorithm = "lru" LFU GCAlgorithm = "lfu" FIFO GCAlgorithm = "fifo" Largest GCAlgorithm = "largest" Smallest GCAlgorithm = "smallest" Hybrid GCAlgorithm = "hybrid" ) // GCFS wraps a VFS with garbage collection capabilities type GCFS struct { vfs vfs.VFS algorithm GCAlgorithm gcFunc func(vfs.VFS, uint) uint } // New creates a new GCFS with the specified algorithm func New(wrappedVFS vfs.VFS, algorithm GCAlgorithm) *GCFS { gcfs := &GCFS{ vfs: wrappedVFS, algorithm: algorithm, } switch algorithm { case LRU: gcfs.gcFunc = gcLRU case LFU: gcfs.gcFunc = gcLFU case FIFO: gcfs.gcFunc = gcFIFO case Largest: gcfs.gcFunc = gcLargest case Smallest: gcfs.gcFunc = gcSmallest case Hybrid: gcfs.gcFunc = gcHybrid default: // Default to LRU gcfs.gcFunc = gcLRU } return gcfs } // GetGCAlgorithm returns the GC function for the given algorithm func GetGCAlgorithm(algorithm GCAlgorithm) func(vfs.VFS, uint) uint { switch algorithm { case LRU: return gcLRU case LFU: return gcLFU case FIFO: return gcFIFO case Largest: return gcLargest case Smallest: return gcSmallest case Hybrid: return gcHybrid default: return gcLRU } } // Create wraps the underlying Create method func (gc *GCFS) Create(key string, size int64) (io.WriteCloser, error) { // Check if we need to GC before creating if gc.vfs.Size()+size > gc.vfs.Capacity() { needed := uint((gc.vfs.Size() + size) - gc.vfs.Capacity()) gc.gcFunc(gc.vfs, needed) } return gc.vfs.Create(key, size) } // Open wraps the underlying Open method func (gc *GCFS) Open(key string) (io.ReadCloser, error) { return gc.vfs.Open(key) } // Delete wraps the underlying Delete method func (gc *GCFS) Delete(key string) error { return gc.vfs.Delete(key) } // Stat wraps the underlying Stat method func (gc *GCFS) Stat(key string) (*vfs.FileInfo, error) { return gc.vfs.Stat(key) } // Name wraps the underlying Name method func (gc *GCFS) Name() string { return gc.vfs.Name() + "(GC:" + string(gc.algorithm) + ")" } // Size wraps the underlying Size method func (gc *GCFS) Size() int64 { return gc.vfs.Size() } // Capacity wraps the underlying Capacity method func (gc *GCFS) Capacity() int64 { return gc.vfs.Capacity() } // EvictionStrategy defines an interface for cache eviction type EvictionStrategy interface { Evict(vfs vfs.VFS, bytesNeeded uint) uint } // GC functions // gcLRU implements Least Recently Used eviction func gcLRU(v vfs.VFS, bytesNeeded uint) uint { return evictLRU(v, bytesNeeded) } // gcLFU implements Least Frequently Used eviction func gcLFU(v vfs.VFS, bytesNeeded uint) uint { return evictLFU(v, bytesNeeded) } // gcFIFO implements First In First Out eviction func gcFIFO(v vfs.VFS, bytesNeeded uint) uint { return evictFIFO(v, bytesNeeded) } // gcLargest implements largest file first eviction func gcLargest(v vfs.VFS, bytesNeeded uint) uint { return evictLargest(v, bytesNeeded) } // gcSmallest implements smallest file first eviction func gcSmallest(v vfs.VFS, bytesNeeded uint) uint { return evictSmallest(v, bytesNeeded) } // gcHybrid implements a hybrid eviction strategy func gcHybrid(v vfs.VFS, bytesNeeded uint) uint { return evictHybrid(v, bytesNeeded) } // evictLRU performs LRU eviction by removing least recently used files func evictLRU(v vfs.VFS, bytesNeeded uint) uint { // Try to use specific eviction methods if available switch fs := v.(type) { case *memory.MemoryFS: return fs.EvictLRU(bytesNeeded) case *disk.DiskFS: return fs.EvictLRU(bytesNeeded) default: // No fallback - return 0 (no eviction performed) return 0 } } // evictLFU performs LFU (Least Frequently Used) eviction func evictLFU(v vfs.VFS, bytesNeeded uint) uint { // For now, fall back to size-based eviction // TODO: Implement proper LFU tracking return evictBySize(v, bytesNeeded) } // evictFIFO performs FIFO (First In First Out) eviction func evictFIFO(v vfs.VFS, bytesNeeded uint) uint { switch fs := v.(type) { case *memory.MemoryFS: return fs.EvictFIFO(bytesNeeded) case *disk.DiskFS: return fs.EvictFIFO(bytesNeeded) default: // No fallback - return 0 (no eviction performed) return 0 } } // evictLargest evicts largest files first func evictLargest(v vfs.VFS, bytesNeeded uint) uint { return evictBySizeDesc(v, bytesNeeded) } // evictSmallest evicts smallest files first func evictSmallest(v vfs.VFS, bytesNeeded uint) uint { return evictBySizeAsc(v, bytesNeeded) } // evictBySize evicts files based on size (smallest first) func evictBySize(v vfs.VFS, bytesNeeded uint) uint { return evictBySizeAsc(v, bytesNeeded) } // evictBySizeAsc evicts smallest files first func evictBySizeAsc(v vfs.VFS, bytesNeeded uint) uint { switch fs := v.(type) { case *memory.MemoryFS: return fs.EvictBySize(bytesNeeded, true) // true = ascending (smallest first) case *disk.DiskFS: return fs.EvictBySize(bytesNeeded, true) // true = ascending (smallest first) default: // No fallback - return 0 (no eviction performed) return 0 } } // evictBySizeDesc evicts largest files first func evictBySizeDesc(v vfs.VFS, bytesNeeded uint) uint { switch fs := v.(type) { case *memory.MemoryFS: return fs.EvictBySize(bytesNeeded, false) // false = descending (largest first) case *disk.DiskFS: return fs.EvictBySize(bytesNeeded, false) // false = descending (largest first) default: // No fallback - return 0 (no eviction performed) return 0 } } // evictHybrid implements a hybrid eviction strategy func evictHybrid(v vfs.VFS, bytesNeeded uint) uint { // Use LRU as primary strategy, but consider size as tiebreaker return evictLRU(v, bytesNeeded) } // AdaptivePromotionDeciderFunc is a placeholder for the adaptive promotion logic var AdaptivePromotionDeciderFunc = func() interface{} { return nil }