10 var DefaultBlockCache = &BlockCache{}
12 type BlockCache struct {
13 // Maximum number of blocks to keep in the cache. If 0, a
14 // default size (currently 4) is used instead.
17 cache map[string]*cacheBlock
22 const defaultMaxBlocks = 4
24 // Sweep deletes the least recently used blocks from the cache until
25 // there are no more than MaxBlocks left.
26 func (c *BlockCache) Sweep() {
28 if max < defaultMaxBlocks {
29 max = defaultMaxBlocks
33 if len(c.cache) <= max {
36 lru := make([]time.Time, 0, len(c.cache))
37 for _, b := range c.cache {
38 lru = append(lru, b.lastUse)
40 sort.Sort(sort.Reverse(timeSlice(lru)))
42 for loc, b := range c.cache {
43 if !b.lastUse.After(threshold) {
49 // Get returns data from the cache, first retrieving it from Keep if
51 func (c *BlockCache) Get(kc *KeepClient, locator string) ([]byte, error) {
52 c.setupOnce.Do(c.setup)
53 cacheKey := locator[:32]
55 b, ok := c.cache[cacheKey]
56 if !ok || b.err != nil {
58 fetched: make(chan struct{}),
63 rdr, _, _, err := kc.Get(locator)
66 data, err = ioutil.ReadAll(rdr)
69 b.data, b.err = data, err
77 // Wait (with mtx unlocked) for the fetch goroutine to finish,
78 // in case it hasn't already.
82 b.lastUse = time.Now()
87 func (c *BlockCache) setup() {
88 c.cache = make(map[string]*cacheBlock)
91 type timeSlice []time.Time
93 func (ts timeSlice) Len() int { return len(ts) }
95 func (ts timeSlice) Less(i, j int) bool { return ts[i].Before(ts[j]) }
97 func (ts timeSlice) Swap(i, j int) { ts[i], ts[j] = ts[j], ts[i] }
99 type cacheBlock struct {
102 fetched chan struct{}