k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/greenhouse/eviction.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "sort" 21 "time" 22 23 "github.com/sirupsen/logrus" 24 "k8s.io/test-infra/greenhouse/diskcache" 25 "k8s.io/test-infra/greenhouse/diskutil" 26 ) 27 28 // monitorDiskAndEvict loops monitoring the disk, evicting cache entries 29 // when the disk passes either minPercentBlocksFree until the disk is above 30 // evictUntilPercentBlocksFree 31 func monitorDiskAndEvict( 32 c *diskcache.Cache, 33 interval time.Duration, 34 minPercentBlocksFree, evictUntilPercentBlocksFree float64, 35 ) { 36 diskRoot := c.DiskRoot() 37 // forever check if usage is past thresholds and evict 38 ticker := time.NewTicker(interval) 39 for ; true; <-ticker.C { 40 blocksFree, _, _, _, _, _, err := diskutil.GetDiskUsage(diskRoot) 41 if err != nil { 42 logrus.WithError(err).Error("Failed to get disk usage!") 43 continue 44 } 45 logger := logrus.WithFields(logrus.Fields{ 46 "sync-loop": "MonitorDiskAndEvict", 47 "blocks-free": blocksFree, 48 }) 49 logger.Info("tick") 50 // if we are past the threshold, start evicting 51 if blocksFree < minPercentBlocksFree { 52 logger.Warn("Eviction triggered") 53 // get all cache entries and sort by lastaccess 54 // so we can pop entries until we have evicted enough 55 files := c.GetEntries() 56 sort.Slice(files, func(i, j int) bool { 57 return files[i].LastAccess.Before(files[j].LastAccess) 58 }) 59 // evict until we pass the safe threshold so we don't thrash at the eviction trigger 60 for blocksFree < evictUntilPercentBlocksFree { 61 if len(files) < 1 { 62 logger.Fatal("Failed to find entries to evict!") 63 } 64 // pop entry and delete 65 var entry diskcache.EntryInfo 66 entry, files = files[0], files[1:] 67 err = c.Delete(c.PathToKey(entry.Path)) 68 if err != nil { 69 logger.WithError(err).Errorf("Error deleting entry at path: %v", entry.Path) 70 } else { 71 promMetrics.FilesEvicted.Inc() 72 promMetrics.LastEvictedAccessAge.Set(time.Since(entry.LastAccess).Hours()) 73 } 74 // get new disk usage 75 blocksFree, _, _, _, _, _, err = diskutil.GetDiskUsage(diskRoot) 76 logger = logrus.WithFields(logrus.Fields{ 77 "sync-loop": "MonitorDiskAndEvict", 78 "blocks-free": blocksFree, 79 }) 80 if err != nil { 81 logrus.WithError(err).Error("Failed to get disk usage!") 82 continue 83 } 84 } 85 logger.Info("Done evicting") 86 } 87 } 88 }