X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/eae1286badb67ee63888633ff59bda9cb736131e..1a61611cbb8ed4471eb2e04e60bad548bff94678:/sdk/go/keepclient/block_cache.go diff --git a/sdk/go/keepclient/block_cache.go b/sdk/go/keepclient/block_cache.go index e841a00fa1..89eecc6e27 100644 --- a/sdk/go/keepclient/block_cache.go +++ b/sdk/go/keepclient/block_cache.go @@ -5,8 +5,11 @@ package keepclient import ( + "fmt" "io" "sort" + "strconv" + "strings" "sync" "time" ) @@ -49,10 +52,30 @@ func (c *BlockCache) Sweep() { } } +// ReadAt returns data from the cache, first retrieving it from Keep if +// necessary. +func (c *BlockCache) ReadAt(kc *KeepClient, locator string, p []byte, off int) (int, error) { + buf, err := c.Get(kc, locator) + if err != nil { + return 0, err + } + if off > len(buf) { + return 0, io.ErrUnexpectedEOF + } + return copy(p, buf[off:]), nil +} + // Get returns data from the cache, first retrieving it from Keep if // necessary. func (c *BlockCache) Get(kc *KeepClient, locator string) ([]byte, error) { cacheKey := locator[:32] + bufsize := BLOCKSIZE + if parts := strings.SplitN(locator, "+", 3); len(parts) >= 2 { + datasize, err := strconv.ParseInt(parts[1], 10, 32) + if err == nil && datasize >= 0 { + bufsize = int(datasize) + } + } c.mtx.Lock() if c.cache == nil { c.cache = make(map[string]*cacheBlock) @@ -68,11 +91,14 @@ func (c *BlockCache) Get(kc *KeepClient, locator string) ([]byte, error) { rdr, size, _, err := kc.Get(locator) var data []byte if err == nil { - data = make([]byte, size, BLOCKSIZE) + data = make([]byte, size, bufsize) _, err = io.ReadFull(rdr, data) err2 := rdr.Close() - if err == nil { - err = err2 + if err == nil && err2 != nil { + err = fmt.Errorf("close(): %w", err2) + } + if err != nil { + err = fmt.Errorf("Get %s: %w", locator, err) } } c.mtx.Lock()