| 231 | } |
| 232 | |
| 233 | func (f *fileSystemCache) clean() { |
| 234 | currentTime := time.Now() |
| 235 | |
| 236 | log.Debugf("cache %q: start cleaning dir %q", f.Name(), f.dir) |
| 237 | |
| 238 | // Remove cached files after a deadline from their expiration, |
| 239 | // so they may be served until they are substituted with fresh files. |
| 240 | expire := f.expire + f.grace |
| 241 | |
| 242 | // Calculate total cache size and remove expired files. |
| 243 | var totalSize uint64 |
| 244 | var totalItems uint64 |
| 245 | var removedSize uint64 |
| 246 | var removedItems uint64 |
| 247 | err := walkDir(f.dir, func(fi os.FileInfo) { |
| 248 | mt := fi.ModTime() |
| 249 | fs := uint64(fi.Size()) |
| 250 | if currentTime.Sub(mt) > expire { |
| 251 | fn := f.fileInfoPath(fi) |
| 252 | err := os.Remove(fn) |
| 253 | if err == nil { |
| 254 | removedSize += fs |
| 255 | removedItems++ |
| 256 | return |
| 257 | } |
| 258 | log.Errorf("cache %q: cannot remove file %q: %s", f.Name(), fn, err) |
| 259 | // Return skipped intentionally. |
| 260 | } |
| 261 | totalSize += fs |
| 262 | totalItems++ |
| 263 | }) |
| 264 | if err != nil { |
| 265 | log.Errorf("cache %q: %s", f.Name(), err) |
| 266 | return |
| 267 | } |
| 268 | |
| 269 | loopsCount := 0 |
| 270 | |
| 271 | // Use dedicated random generator instead of global one from math/rand, |
| 272 | // since the global generator is slow due to locking. |
| 273 | // |
| 274 | // Seed the generator with the current time in order to randomize |
| 275 | // set of files to be removed below. |
| 276 | // nolint:gosec // not security sensitve, only used internally. |
| 277 | rnd := rand.New(rand.NewSource(time.Now().UnixNano())) |
| 278 | |
| 279 | for totalSize > f.maxSize && loopsCount < 3 { |
| 280 | // Remove some files in order to reduce cache size. |
| 281 | excessSize := totalSize - f.maxSize |
| 282 | p := int32(float64(excessSize) / float64(totalSize) * 100) |
| 283 | // Remove +10% over totalSize. |
| 284 | p += 10 |
| 285 | err := walkDir(f.dir, func(fi os.FileInfo) { |
| 286 | if rnd.Int31n(100) > p { |
| 287 | return |
| 288 | } |
| 289 | |
| 290 | fs := uint64(fi.Size()) |