PutStream stores data from r under key without buffering the whole body in memory. It writes to a temp file and atomically renames it into place, so a truncated or failed copy never becomes a servable entry. Returns the number of bytes stored. This is the streaming counterpart to Put and is what kee
(key string, r io.Reader)
| 227 | } |
| 228 | |
| 229 | type openCacheDirectory func(string) (cacheDirectory, error) |
| 230 | |
| 231 | func openDirectory(path string) (cacheDirectory, error) { |
| 232 | return os.Open(path) |
| 233 | } |
| 234 | |
| 235 | type cacheEntry struct { |
| 236 | key string |
| 237 | size int64 |
| 238 | lastAccess time.Time |
| 239 | lastPersistedRecency time.Time |
| 240 | evictionInFlight bool |
| 241 | } |
| 242 | |
| 243 | // NewDiskCache creates a cache backed by the given directory. |
| 244 | // maxPercent is the percentage of filesystem capacity to use (e.g. 80). |
| 245 | func NewDiskCache(dir string, maxPercent int, options ...DiskCacheOptions) (*DiskCache, error) { |
| 246 | if err := os.MkdirAll(dir, 0750); err != nil { |
| 247 | return nil, fmt.Errorf("create cache dir: %w", err) |
| 248 | } |
| 249 | |
| 250 | dc := &DiskCache{ |
| 251 | dir: dir, |
| 252 | // Startup must account for committed files before applying a byte |
| 253 | // ceiling, so scans initially load without byte pruning. |
| 254 | maxBytes: math.MaxInt64, |
| 255 | maxEntries: defaultCacheMaxEntries, |
| 256 | hardMaxEntries: int(cacheMetadataEntryLimit), |
| 257 | maxPercent: maxPercent, |
| 258 | blockSize: defaultCacheBlockSizeBytes, |
| 259 | space: statfsDiskSpace, |
| 260 | order: list.New(), |
| 261 | index: make(map[string]*list.Element), |
| 262 | renameFile: os.Rename, |
| 263 | removeFile: os.Remove, |
| 264 | openScanDirectory: openDirectory, |
| 265 | recencyNow: time.Now, |
| 266 | recencyInterval: defaultRecencyGranularity, |
| 267 | } |
| 268 | var option DiskCacheOptions |
| 269 | if len(options) > 0 { |
| 270 | option = options[0] |
| 271 | if option.MaxEntries > 0 { |
| 272 | dc.maxEntries = option.MaxEntries |
| 273 | } |
| 274 | if option.BlockSizeBytes > 0 { |
| 275 | dc.blockSize = option.BlockSizeBytes |
| 276 | } |
| 277 | if option.CapacityProvider != nil { |
| 278 | dc.space = option.CapacityProvider |
| 279 | } |
| 280 | if option.openScanDirectory != nil { |
| 281 | dc.openScanDirectory = option.openScanDirectory |
| 282 | } |
| 283 | if option.removeFile != nil { |
| 284 | dc.removeFile = option.removeFile |
| 285 | } |