package vaultik // restoreSweeper frees cached blobs once no file still to be restored in // this run needs them. It works as follows: // // 1. After each chunk is restored, chunkRestored accumulates a running // byte count. // 2. When the accumulator crosses a threshold (one hundredth of the // configured blob size — so a sweep runs about a hundred times per // blob's worth of restored bytes), the sweeper iterates every key in // the cache and deletes each blob that the restore plan no longer // needs. // // The plan drops a file once it is restored or has failed, and holds // only the files this run restores, so files outside the requested paths // never keep a blob. type restoreSweeper struct { plan *restorePlan cache *blobDiskCache threshold int64 bytesAccum int64 } // newRestoreSweeper returns a sweeper that triggers eviction every // `threshold` bytes restored. Callers should pass blob_size_limit/100. func newRestoreSweeper( plan *restorePlan, cache *blobDiskCache, threshold int64, ) *restoreSweeper { if threshold <= 0 { threshold = 1 } return &restoreSweeper{ plan: plan, cache: cache, threshold: threshold, } } // chunkRestored accounts n bytes against the sweep threshold and runs a // sweep if the threshold has been crossed since the last sweep. func (s *restoreSweeper) chunkRestored(n int64) { s.bytesAccum += n if s.bytesAccum < s.threshold { return } s.bytesAccum = 0 s.sweep() } // sweep deletes every cached blob that no pending file references. func (s *restoreSweeper) sweep() { for _, blobHash := range s.cache.Keys() { if !s.plan.pendingFileUsesBlob(blobHash) { s.cache.Delete(blobHash) } } }