forked from TrueCloudLab/restic
Embed context into ReaderAt
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.
This commit is contained in:
parent
d6cfe857b7
commit
e638b46a13
4 changed files with 13 additions and 10 deletions
|
@ -87,7 +87,7 @@ func printPacks(ctx context.Context, repo *repository.Repository, wr io.Writer)
|
||||||
return repo.List(ctx, restic.PackFile, func(id restic.ID, size int64) error {
|
return repo.List(ctx, restic.PackFile, func(id restic.ID, size int64) error {
|
||||||
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
||||||
|
|
||||||
blobs, err := pack.List(repo.Key(), restic.ReaderAt(repo.Backend(), h), size)
|
blobs, err := pack.List(repo.Key(), restic.ReaderAt(ctx, repo.Backend(), h), size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("error for pack %v: %v\n", id.Str(), err)
|
Warnf("error for pack %v: %v\n", id.Str(), err)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -128,7 +128,7 @@ func TestUnpackReadSeeker(t *testing.T) {
|
||||||
|
|
||||||
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
||||||
rtest.OK(t, b.Save(context.TODO(), handle, restic.NewByteReader(packData)))
|
rtest.OK(t, b.Save(context.TODO(), handle, restic.NewByteReader(packData)))
|
||||||
verifyBlobs(t, bufs, k, restic.ReaderAt(b, handle), packSize)
|
verifyBlobs(t, bufs, k, restic.ReaderAt(context.TODO(), b, handle), packSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShortPack(t *testing.T) {
|
func TestShortPack(t *testing.T) {
|
||||||
|
@ -141,5 +141,5 @@ func TestShortPack(t *testing.T) {
|
||||||
|
|
||||||
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
||||||
rtest.OK(t, b.Save(context.TODO(), handle, restic.NewByteReader(packData)))
|
rtest.OK(t, b.Save(context.TODO(), handle, restic.NewByteReader(packData)))
|
||||||
verifyBlobs(t, bufs, k, restic.ReaderAt(b, handle), packSize)
|
verifyBlobs(t, bufs, k, restic.ReaderAt(context.TODO(), b, handle), packSize)
|
||||||
}
|
}
|
||||||
|
|
|
@ -679,7 +679,7 @@ func (r *Repository) List(ctx context.Context, t restic.FileType, fn func(restic
|
||||||
func (r *Repository) ListPack(ctx context.Context, id restic.ID, size int64) ([]restic.Blob, int64, error) {
|
func (r *Repository) ListPack(ctx context.Context, id restic.ID, size int64) ([]restic.Blob, int64, error) {
|
||||||
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
||||||
|
|
||||||
blobs, err := pack.List(r.Key(), restic.ReaderAt(r.Backend(), h), size)
|
blobs, err := pack.List(r.Key(), restic.ReaderAt(ctx, r.Backend(), h), size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type backendReaderAt struct {
|
type backendReaderAt struct {
|
||||||
be Backend
|
ctx context.Context
|
||||||
h Handle
|
be Backend
|
||||||
|
h Handle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (brd backendReaderAt) ReadAt(p []byte, offset int64) (n int, err error) {
|
func (brd backendReaderAt) ReadAt(p []byte, offset int64) (n int, err error) {
|
||||||
return ReadAt(context.TODO(), brd.be, brd.h, offset, p)
|
return ReadAt(brd.ctx, brd.be, brd.h, offset, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReaderAt returns an io.ReaderAt for a file in the backend.
|
// ReaderAt returns an io.ReaderAt for a file in the backend. The returned reader
|
||||||
func ReaderAt(be Backend, h Handle) io.ReaderAt {
|
// should not escape the caller function to avoid unexpected interactions with the
|
||||||
return backendReaderAt{be: be, h: h}
|
// 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.
|
// ReadAt reads from the backend handle h at the given position.
|
||||||
|
|
Loading…
Reference in a new issue