16745: Prune enough sessions to reach size limit, not all.
authorTom Clegg <tom@curii.com>
Tue, 23 Feb 2021 02:46:27 +0000 (21:46 -0500)
committerTom Clegg <tom@curii.com>
Tue, 23 Feb 2021 02:46:27 +0000 (21:46 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

services/keep-web/cache.go

index 71e99533042c693badbb1c00a5dc9e60af02b875..af143c77edc7be31298abeb6cd774c0fbfd970c4 100644 (file)
@@ -83,7 +83,7 @@ func (m *cacheMetrics) setup(reg *prometheus.Registry) {
                Namespace: "arvados",
                Subsystem: "keepweb_collectioncache",
                Name:      "cached_manifest_bytes",
-               Help:      "Total size of all manifests in cache.",
+               Help:      "Total size of all cached manifests and sessions.",
        })
        reg.MustRegister(m.collectionBytes)
        m.collectionEntries = prometheus.NewGauge(prometheus.GaugeOpts{
@@ -251,10 +251,13 @@ func (c *cache) GetSession(token string) (arvados.CustomFileSystem, error) {
        return fs, nil
 }
 
+// Remove all expired session cache entries, then remove more entries
+// until approximate remaining size <= maxsize/2
 func (c *cache) pruneSessions() {
        now := time.Now()
        var size int64
-       for _, token := range c.sessions.Keys() {
+       keys := c.sessions.Keys()
+       for _, token := range keys {
                ent, ok := c.sessions.Peek(token)
                if !ok {
                        continue
@@ -264,16 +267,28 @@ func (c *cache) pruneSessions() {
                        c.sessions.Remove(token)
                        continue
                }
+               if fs, ok := s.fs.Load().(arvados.CustomFileSystem); ok {
+                       size += fs.MemorySize()
+               }
+       }
+       // Remove tokens until reaching size limit, starting with the
+       // least frequently used entries (which Keys() returns last).
+       for i := len(keys) - 1; i >= 0; i-- {
+               token := keys[i]
+               if size <= c.cluster.Collections.WebDAVCache.MaxCollectionBytes/2 {
+                       break
+               }
+               ent, ok := c.sessions.Peek(token)
+               if !ok {
+                       continue
+               }
+               s := ent.(*cachedSession)
                fs, _ := s.fs.Load().(arvados.CustomFileSystem)
                if fs == nil {
                        continue
                }
-               size += fs.MemorySize()
-       }
-       if size > c.cluster.Collections.WebDAVCache.MaxCollectionBytes/2 {
-               for _, token := range c.sessions.Keys() {
-                       c.sessions.Remove(token)
-               }
+               c.sessions.Remove(token)
+               size -= fs.MemorySize()
        }
 }