mirror of
https://github.com/kopia/kopia.git
synced 2026-03-19 14:46:30 -04:00
87 lines
1.5 KiB
Go
87 lines
1.5 KiB
Go
package repo
|
|
|
|
import (
|
|
"log"
|
|
"sync"
|
|
|
|
"github.com/kopia/kopia/blob"
|
|
)
|
|
|
|
type blockSizeCache struct {
|
|
storage blob.Storage
|
|
|
|
mu sync.Mutex
|
|
cache map[string]int64
|
|
completed map[string]bool
|
|
populated map[string]bool
|
|
cancel blob.CancelFunc
|
|
}
|
|
|
|
func (c *blockSizeCache) close() error {
|
|
return nil
|
|
}
|
|
|
|
func (c *blockSizeCache) getSize(blockID string) (int64, error) {
|
|
c.mu.Lock()
|
|
size, ok := c.cache[blockID]
|
|
prefix := blockID[0:1]
|
|
complete := c.completed[prefix]
|
|
|
|
if !c.populated[prefix] {
|
|
c.populated[prefix] = true
|
|
go c.populate(prefix)
|
|
|
|
}
|
|
c.mu.Unlock()
|
|
if ok {
|
|
// found in cache, return
|
|
return size, nil
|
|
}
|
|
|
|
if complete {
|
|
// not found in cache and we loaded everything.
|
|
return 0, blob.ErrBlockNotFound
|
|
}
|
|
|
|
s, err := c.storage.BlockSize(blockID)
|
|
if err == nil {
|
|
c.mu.Lock()
|
|
c.cache[blockID] = size
|
|
c.mu.Unlock()
|
|
}
|
|
|
|
return s, err
|
|
}
|
|
|
|
func (c *blockSizeCache) populate(prefix string) {
|
|
ch, cancel := c.storage.ListBlocks(prefix)
|
|
defer cancel()
|
|
|
|
m := map[string]int64{}
|
|
for b := range ch {
|
|
if b.Error != nil {
|
|
log.Printf("warning: got error populating block size cache with prefix %q: %v", prefix, b.Error)
|
|
return
|
|
}
|
|
|
|
m[b.BlockID] = b.Length
|
|
}
|
|
|
|
c.mu.Lock()
|
|
for k, v := range m {
|
|
c.cache[k] = v
|
|
}
|
|
c.completed[prefix] = true
|
|
c.mu.Unlock()
|
|
}
|
|
|
|
func newBlockSizeCache(s blob.Storage) *blockSizeCache {
|
|
c := &blockSizeCache{
|
|
storage: s,
|
|
cache: map[string]int64{},
|
|
completed: map[string]bool{},
|
|
populated: map[string]bool{},
|
|
}
|
|
return c
|
|
}
|