1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
14 var DefaultBlockCache = &BlockCache{}
16 type BlockCache struct {
17 // Maximum number of blocks to keep in the cache. If 0, a
18 // default size (currently 4) is used instead.
21 cache map[string]*cacheBlock
25 const defaultMaxBlocks = 4
27 // Sweep deletes the least recently used blocks from the cache until
28 // there are no more than MaxBlocks left.
29 func (c *BlockCache) Sweep() {
32 max = defaultMaxBlocks
36 if len(c.cache) <= max {
39 lru := make([]time.Time, 0, len(c.cache))
40 for _, b := range c.cache {
41 lru = append(lru, b.lastUse)
43 sort.Sort(sort.Reverse(timeSlice(lru)))
45 for loc, b := range c.cache {
46 if !b.lastUse.After(threshold) {
52 // Get returns data from the cache, first retrieving it from Keep if
54 func (c *BlockCache) Get(kc *KeepClient, locator string) ([]byte, error) {
55 cacheKey := locator[:32]
58 c.cache = make(map[string]*cacheBlock)
60 b, ok := c.cache[cacheKey]
61 if !ok || b.err != nil {
63 fetched: make(chan struct{}),
68 rdr, size, _, err := kc.Get(locator)
71 data = make([]byte, size, BLOCKSIZE)
72 _, err = io.ReadFull(rdr, data)
79 b.data, b.err = data, err
87 // Wait (with mtx unlocked) for the fetch goroutine to finish,
88 // in case it hasn't already.
92 b.lastUse = time.Now()
97 func (c *BlockCache) Clear() {
103 type timeSlice []time.Time
105 func (ts timeSlice) Len() int { return len(ts) }
107 func (ts timeSlice) Less(i, j int) bool { return ts[i].Before(ts[j]) }
109 func (ts timeSlice) Swap(i, j int) { ts[i], ts[j] = ts[j], ts[i] }
111 type cacheBlock struct {
114 fetched chan struct{}