forked from TrueCloudLab/restic
e638b46a13
The io.Reader interface does not support contexts, such that it is necessary to embed the context into the backendReaderAt struct. This has the problem that a reader might suddenly stop working when it's contained context is canceled. However, this is now problem here as the reader instances never escape the calling function.
44 lines
1.1 KiB
Go
44 lines
1.1 KiB
Go
package restic
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"github.com/restic/restic/internal/debug"
|
|
"github.com/restic/restic/internal/errors"
|
|
)
|
|
|
|
type backendReaderAt struct {
|
|
ctx context.Context
|
|
be Backend
|
|
h Handle
|
|
}
|
|
|
|
func (brd backendReaderAt) ReadAt(p []byte, offset int64) (n int, err error) {
|
|
return ReadAt(brd.ctx, brd.be, brd.h, offset, p)
|
|
}
|
|
|
|
// ReaderAt returns an io.ReaderAt for a file in the backend. The returned reader
|
|
// should not escape the caller function to avoid unexpected interactions with the
|
|
// embedded context
|
|
func ReaderAt(ctx context.Context, be Backend, h Handle) io.ReaderAt {
|
|
return backendReaderAt{ctx: ctx, be: be, h: h}
|
|
}
|
|
|
|
// ReadAt reads from the backend handle h at the given position.
|
|
func ReadAt(ctx context.Context, be Backend, h Handle, offset int64, p []byte) (n int, err error) {
|
|
debug.Log("ReadAt(%v) at %v, len %v", h, offset, len(p))
|
|
|
|
err = be.Load(ctx, h, len(p), offset, func(rd io.Reader) (ierr error) {
|
|
n, ierr = io.ReadFull(rd, p)
|
|
|
|
return ierr
|
|
})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
debug.Log("ReadAt(%v) ReadFull returned %v bytes", h, n)
|
|
|
|
return n, errors.Wrapf(err, "ReadFull(%v)", h)
|
|
}
|