From 05280d7d9a808a46df68a8560dedfd1b98153228 Mon Sep 17 00:00:00 2001 From: Nicholas Novak <34256932+NickyBoy89@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:36:02 -0800 Subject: [PATCH] feat: Added a file cache --- storage/file_cache.go | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 storage/file_cache.go diff --git a/storage/file_cache.go b/storage/file_cache.go new file mode 100644 index 0000000..1171d0a --- /dev/null +++ b/storage/file_cache.go @@ -0,0 +1,62 @@ +package storage + +import ( + "math/rand" + "os" +) + +// A `FileCache` stores open file descriptors for all files that have been +// requested, and returns them when requested +type FileCache struct { + cacheSize int + fileNames map[string]int + indexesOfFiles map[int]string + files []*os.File +} + +func NewFileCache(cacheSize int) FileCache { + var c FileCache + + c.cacheSize = cacheSize + c.fileNames = make(map[string]int) + c.indexesOfFiles = make(map[int]string) + c.files = make([]*os.File, cacheSize) + + return c +} + +// `FetchFile` takes in a file's name and returns its file descriptor +// +// If the file is not found in the cache, the file is added to the cache +func (fc *FileCache) FetchFile(fileName string) (*os.File, error) { + // The file is already in the cache + if index, contains := fc.fileNames[fileName]; contains { + return fc.files[index], nil + } + + // The file was not in the cache, try and insert it + + // Random cache eviction + indexToRemove := rand.Intn(fc.cacheSize) + + // Remove the old value + oldName, present := fc.indexesOfFiles[indexToRemove] + + // If there is already a value, delete its mapping + if present { + delete(fc.fileNames, oldName) + delete(fc.indexesOfFiles, indexToRemove) + } + + f, err := os.Open(fileName) + if err != nil { + return nil, err + } + + // Insert the new value + fc.files[indexToRemove] = f + fc.fileNames[fileName] = indexToRemove + fc.indexesOfFiles[indexToRemove] = fileName + + return f, nil +}