github.com/artpar/rclone@v1.67.3/backend/cache/storage_memory.go (about) 1 //go:build !plan9 && !js 2 3 package cache 4 5 import ( 6 "fmt" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/artpar/rclone/fs" 12 cache "github.com/patrickmn/go-cache" 13 ) 14 15 // Memory is a wrapper of transient storage for a go-cache store 16 type Memory struct { 17 db *cache.Cache 18 } 19 20 // NewMemory builds this cache storage 21 // defaultExpiration will set the expiry time of chunks in this storage 22 func NewMemory(defaultExpiration time.Duration) *Memory { 23 mem := &Memory{} 24 err := mem.Connect(defaultExpiration) 25 if err != nil { 26 fs.Errorf("cache", "can't open ram connection: %v", err) 27 } 28 29 return mem 30 } 31 32 // Connect will create a connection for the storage 33 func (m *Memory) Connect(defaultExpiration time.Duration) error { 34 m.db = cache.New(defaultExpiration, -1) 35 return nil 36 } 37 38 // HasChunk confirms the existence of a single chunk of an object 39 func (m *Memory) HasChunk(cachedObject *Object, offset int64) bool { 40 key := cachedObject.abs() + "-" + strconv.FormatInt(offset, 10) 41 _, found := m.db.Get(key) 42 return found 43 } 44 45 // GetChunk will retrieve a single chunk which belongs to a cached object or an error if it doesn't find it 46 func (m *Memory) GetChunk(cachedObject *Object, offset int64) ([]byte, error) { 47 key := cachedObject.abs() + "-" + strconv.FormatInt(offset, 10) 48 var data []byte 49 50 if x, found := m.db.Get(key); found { 51 data = x.([]byte) 52 return data, nil 53 } 54 55 return nil, fmt.Errorf("couldn't get cached object data at offset %v", offset) 56 } 57 58 // AddChunk adds a new chunk of a cached object 59 func (m *Memory) AddChunk(fp string, data []byte, offset int64) error { 60 return m.AddChunkAhead(fp, data, offset, time.Second) 61 } 62 63 // AddChunkAhead adds a new chunk of a cached object 64 func (m *Memory) AddChunkAhead(fp string, data []byte, offset int64, t time.Duration) error { 65 key := fp + "-" + strconv.FormatInt(offset, 10) 66 m.db.Set(key, data, cache.DefaultExpiration) 67 68 return nil 69 } 70 71 // CleanChunksByAge will cleanup on a cron basis 72 func (m *Memory) CleanChunksByAge(chunkAge time.Duration) { 73 m.db.DeleteExpired() 74 } 75 76 // CleanChunksByNeed will cleanup chunks after the FS passes a specific chunk 77 func (m *Memory) CleanChunksByNeed(offset int64) { 78 for key := range m.db.Items() { 79 sepIdx := strings.LastIndex(key, "-") 80 keyOffset, err := strconv.ParseInt(key[sepIdx+1:], 10, 64) 81 if err != nil { 82 fs.Errorf("cache", "couldn't parse offset entry %v", key) 83 continue 84 } 85 86 if keyOffset < offset { 87 m.db.Delete(key) 88 } 89 } 90 } 91 92 // CleanChunksBySize will cleanup chunks after the total size passes a certain point 93 func (m *Memory) CleanChunksBySize(maxSize int64) { 94 // NOOP 95 }