repository: change LoadBlob, LookupBlob and LookupBlobSize to BlobHandles (#21857)

This commit is contained in:
Michael Eischer
2026-06-14 15:30:00 +02:00
committed by GitHub
parent 71f38d266c
commit 7d36449ea8
27 changed files with 85 additions and 85 deletions
+3 -3
View File
@@ -177,11 +177,11 @@ func runCat(ctx context.Context, gopts global.Options, args []string, term ui.Te
}
for _, t := range []restic.BlobType{restic.DataBlob, restic.TreeBlob} {
if _, ok := repo.LookupBlobSize(t, id); !ok {
if _, ok := repo.LookupBlobSize(restic.BlobHandle{Type: t, ID: id}); !ok {
continue
}
buf, err := repo.LoadBlob(ctx, t, id, nil)
buf, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: t, ID: id}, nil)
if err != nil {
return err
}
@@ -208,7 +208,7 @@ func runCat(ctx context.Context, gopts global.Options, args []string, term ui.Te
return err
}
buf, err := repo.LoadBlob(ctx, restic.TreeBlob, *sn.Tree, nil)
buf, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.TreeBlob, ID: *sn.Tree}, nil)
if err != nil {
return err
}
+3 -3
View File
@@ -264,8 +264,8 @@ func copyTree(ctx context.Context, srcRepo *repository.Repository, dstRepo resti
enqueue := func(h restic.BlobHandle) {
lock.Lock()
defer lock.Unlock()
if _, ok := dstRepo.LookupBlobSize(h.Type, h.ID); !ok {
pb := srcRepo.LookupBlob(h.Type, h.ID)
if _, ok := dstRepo.LookupBlobSize(h); !ok {
pb := srcRepo.LookupBlob(h)
copyBlobs.Insert(h)
for _, p := range pb {
packList.Insert(p.PackID())
@@ -317,7 +317,7 @@ func copyStats(srcRepo restic.Repository, copyBlobs restic.AssociatedBlobSet, pa
countBlobs := 0
sizeBlobs := uint64(0)
for blob := range copyBlobs.Keys() {
for _, pb := range srcRepo.LookupBlob(blob.Type, blob.ID) {
for _, pb := range srcRepo.LookupBlob(blob) {
countBlobs++
sizeBlobs += uint64(pb.CiphertextLength())
break
+1 -1
View File
@@ -167,7 +167,7 @@ func updateBlobs(repo restic.Loader, blobs restic.AssociatedBlobSet, stats *Diff
stats.TreeBlobs++
}
size, found := repo.LookupBlobSize(h.Type, h.ID)
size, found := repo.LookupBlobSize(h)
if !found {
printError("unable to find blob size for %v", h)
continue
+1 -1
View File
@@ -571,7 +571,7 @@ func (f *Finder) findObjectPack(id string, t restic.BlobType) {
return
}
blobs := f.repo.LookupBlob(t, rid)
blobs := f.repo.LookupBlob(restic.BlobHandle{Type: t, ID: rid})
if len(blobs) == 0 {
f.printer.S("Object %s with type %s not found in the index", t.String(), rid.Str())
return
+1 -1
View File
@@ -115,7 +115,7 @@ func runRepairSnapshots(ctx context.Context, gopts global.Options, opts RepairOp
var newSize uint64
// check all contents and remove if not available
for _, id := range node.Content {
if size, found := repo.LookupBlobSize(restic.DataBlob, id); !found {
if size, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id}); !found {
ok = false
} else {
newContent = append(newContent, id)
+2 -2
View File
@@ -155,7 +155,7 @@ func runStats(ctx context.Context, opts StatsOptions, gopts global.Options, args
if opts.countMode == countModeRawData {
// the blob handles have been collected, but not yet counted
for blobHandle := range stats.blobs.Keys() {
pbs := repo.LookupBlob(blobHandle.Type, blobHandle.ID)
pbs := repo.LookupBlob(blobHandle)
if len(pbs) == 0 {
return fmt.Errorf("blob %v not found", blobHandle)
}
@@ -274,7 +274,7 @@ func statsWalkTree(repo restic.Loader, opts StatsOptions, stats *statsContainer,
}
if _, ok := stats.fileBlobs[nodePath][blobID]; !ok {
// is always a data blob since we're accessing it via a file's Content array
blobSize, found := repo.LookupBlobSize(restic.DataBlob, blobID)
blobSize, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: blobID})
if !found {
return fmt.Errorf("blob %s not found for tree %s", blobID, parentTreeID)
}
+2 -2
View File
@@ -297,7 +297,7 @@ func (arch *Archiver) loadSubtree(ctx context.Context, node *data.Node) (data.Tr
}
func (arch *Archiver) wrapLoadTreeError(id restic.ID, err error) error {
if _, ok := arch.Repo.LookupBlobSize(restic.TreeBlob, id); ok {
if _, ok := arch.Repo.LookupBlobSize(restic.BlobHandle{Type: restic.TreeBlob, ID: id}); ok {
err = errors.Errorf("tree %v could not be loaded; the repository could be damaged: %v", id, err)
} else {
err = errors.Errorf("tree %v is not known; the repository could be damaged, run `repair index` to try to repair it", id)
@@ -435,7 +435,7 @@ func (fn *futureNode) take(ctx context.Context) futureNodeResult {
func (arch *Archiver) allBlobsPresent(previous *data.Node) bool {
// check if all blobs are contained in index
for _, id := range previous.Content {
if _, ok := arch.Repo.LookupBlobSize(restic.DataBlob, id); !ok {
if _, ok := arch.Repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id}); !ok {
return false
}
}
+1 -1
View File
@@ -243,7 +243,7 @@ func TestEnsureFileContent(ctx context.Context, t testing.TB, repo restic.BlobLo
content := make([]byte, len(file.Content))
pos := 0
for _, id := range node.Content {
part, err := repo.LoadBlob(ctx, restic.DataBlob, id, content[pos:])
part, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.DataBlob, ID: id}, content[pos:])
if err != nil {
t.Fatalf("error loading blob %v: %v", id.Str(), err)
return
+2 -2
View File
@@ -217,7 +217,7 @@ func (c *Checker) checkTree(id restic.ID, tree data.TreeNodeIterator) (errs []er
// unfortunately fails in some cases that are not resolvable
// by users, so we omit this check, see #1887
_, found := c.repo.LookupBlobSize(restic.DataBlob, blobID)
_, found := c.repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: blobID})
if !found {
debug.Log("tree %v references blob %v which isn't contained in index", id, blobID)
errs = append(errs, &Error{TreeID: id, Err: errors.Errorf("file %q blob %v not found in index", node.Name, blobID)})
@@ -306,7 +306,7 @@ func (c *Checker) ReadPacks(ctx context.Context, filter func(packs map[restic.ID
// convert used blobs into their encompassing packfiles
for bh := range c.blobRefs.M.Keys() {
for _, pb := range c.repo.LookupBlob(bh.Type, bh.ID) {
for _, pb := range c.repo.LookupBlob(bh) {
filteredPacks[pb.PackID()] = allPacks[pb.PackID()]
}
}
+14 -14
View File
@@ -397,20 +397,20 @@ type loadTreesOnceRepository struct {
DuplicateTree bool
}
func (r *loadTreesOnceRepository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) {
if t != restic.TreeBlob {
return r.Repository.LoadBlob(ctx, t, id, buf)
func (r *loadTreesOnceRepository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) {
if bh.Type != restic.TreeBlob {
return r.Repository.LoadBlob(ctx, bh, buf)
}
r.mutex.Lock()
defer r.mutex.Unlock()
if r.loadedTrees.Has(id) {
if r.loadedTrees.Has(bh.ID) {
// additionally store error to ensure that it cannot be swallowed
r.DuplicateTree = true
return nil, errors.Errorf("trying to load tree with id %v twice", id)
return nil, errors.Errorf("trying to load tree with id %v twice", bh.ID)
}
r.loadedTrees.Insert(id)
return r.Repository.LoadBlob(ctx, t, id, buf)
r.loadedTrees.Insert(bh.ID)
return r.Repository.LoadBlob(ctx, bh, buf)
}
func TestCheckerNoDuplicateTreeDecodes(t *testing.T) {
@@ -442,18 +442,18 @@ type delayRepository struct {
Triggered bool
}
func (r *delayRepository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) {
if t == restic.TreeBlob && id == r.DelayTree {
func (r *delayRepository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) {
if bh.Type == restic.TreeBlob && bh.ID == r.DelayTree {
<-r.UnblockChannel
}
return r.Repository.LoadBlob(ctx, t, id, buf)
return r.Repository.LoadBlob(ctx, bh, buf)
}
func (r *delayRepository) LookupBlobSize(t restic.BlobType, id restic.ID) (uint, bool) {
if id == r.DelayTree && t == restic.DataBlob {
func (r *delayRepository) LookupBlobSize(bh restic.BlobHandle) (uint, bool) {
if bh.ID == r.DelayTree && bh.Type == restic.DataBlob {
r.Unblock()
}
return r.Repository.LookupBlobSize(t, id)
return r.Repository.LookupBlobSize(bh)
}
func (r *delayRepository) Unblock() {
@@ -484,7 +484,7 @@ func TestCheckerBlobTypeConfusion(t *testing.T) {
return nil
}))
buf, err := repo.LoadBlob(ctx, restic.TreeBlob, id, nil)
buf, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.TreeBlob, ID: id}, nil)
test.OK(t, err)
test.OK(t, repo.WithBlobUploader(ctx, func(ctx context.Context, uploader restic.BlobSaverWithAsync) error {
+2 -2
View File
@@ -163,11 +163,11 @@ func TestMultiFindUsedBlobs(t *testing.T) {
type ForbiddenRepo struct{}
func (r ForbiddenRepo) LoadBlob(context.Context, restic.BlobType, restic.ID, []byte) ([]byte, error) {
func (r ForbiddenRepo) LoadBlob(context.Context, restic.BlobHandle, []byte) ([]byte, error) {
return nil, errors.New("should not be called")
}
func (r ForbiddenRepo) LookupBlobSize(_ restic.BlobType, _ restic.ID) (uint, bool) {
func (r ForbiddenRepo) LookupBlobSize(_ restic.BlobHandle) (uint, bool) {
return 0, false
}
+3 -3
View File
@@ -202,11 +202,11 @@ func TestLoadAllSnapshots(ctx context.Context, repo restic.ListerLoaderUnpacked,
// TestTreeMap returns the trees from the map on LoadTree.
type TestTreeMap map[restic.ID][]byte
func (t TestTreeMap) LoadBlob(_ context.Context, tpe restic.BlobType, id restic.ID, _ []byte) ([]byte, error) {
if tpe != restic.TreeBlob {
func (t TestTreeMap) LoadBlob(_ context.Context, bh restic.BlobHandle, _ []byte) ([]byte, error) {
if bh.Type != restic.TreeBlob {
return nil, fmt.Errorf("can only load trees")
}
tree, ok := t[id]
tree, ok := t[bh.ID]
if !ok {
return nil, fmt.Errorf("tree not found")
}
+1 -1
View File
@@ -143,7 +143,7 @@ func (t *treeIterator) assertToken(token json.Token) error {
}
func LoadTree(ctx context.Context, loader restic.BlobLoader, content restic.ID) (TreeNodeIterator, error) {
rd, err := loader.LoadBlob(ctx, restic.TreeBlob, content, nil)
rd, err := loader.LoadBlob(ctx, restic.BlobHandle{Type: restic.TreeBlob, ID: content}, nil)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -124,7 +124,7 @@ func filterTrees(ctx context.Context, repo restic.Loader, trees restic.IDs, load
continue
}
treeSize, found := repo.LookupBlobSize(restic.TreeBlob, nextTreeID.ID)
treeSize, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.TreeBlob, ID: nextTreeID.ID})
if found && treeSize > 50*1024*1024 {
loadCh = hugeTreeLoaderChan
} else {
+1 -1
View File
@@ -142,7 +142,7 @@ loop:
wg.Go(func() error {
blob, err := d.cache.GetOrCompute(id, func() ([]byte, error) {
return d.repo.LoadBlob(ctx, restic.DataBlob, id, nil)
return d.repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil)
})
if err == nil {
+2 -2
View File
@@ -82,7 +82,7 @@ func (f *file) Open(ctx context.Context, _ *fuse.OpenRequest, _ *fuse.OpenRespon
return nil, ctx.Err()
}
size, found := f.root.repo.LookupBlobSize(restic.DataBlob, id)
size, found := f.root.repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id})
if !found {
return nil, errors.Errorf("id %v not found in repository", id)
}
@@ -107,7 +107,7 @@ func (f *file) Open(ctx context.Context, _ *fuse.OpenRequest, _ *fuse.OpenRespon
func (f *openFile) getBlobAt(ctx context.Context, i int) (blob []byte, err error) {
blob, err = f.root.blobCache.GetOrCompute(f.node.Content[i], func() ([]byte, error) {
return f.root.repo.LoadBlob(ctx, restic.DataBlob, f.node.Content[i], nil)
return f.root.repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.DataBlob, ID: f.node.Content[i]}, nil)
})
if err != nil {
debug.Log("LoadBlob(%v, %v) failed: %v", f.node.Name, f.node.Content[i], err)
+2 -2
View File
@@ -91,11 +91,11 @@ func TestFuseFile(t *testing.T) {
memfile []byte
)
for _, id := range content {
size, found := repo.LookupBlobSize(restic.DataBlob, id)
size, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id})
rtest.Assert(t, found, "Expected to find blob id %v", id)
filesize += uint64(size)
buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil)
buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil)
rtest.OK(t, err)
if len(buf) != int(size) {
+1 -1
View File
@@ -25,7 +25,7 @@ func FuzzSaveLoadBlob(f *testing.F) {
return err
}))
buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, make([]byte, buflen))
buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, make([]byte, buflen))
if err != nil {
t.Fatal(err)
}
+2 -2
View File
@@ -28,7 +28,7 @@ func testPrune(t *testing.T, opts repository.PruneOptions, errOnUnused bool) {
rtest.OK(t, repo.WithBlobUploader(context.TODO(), func(ctx context.Context, uploader restic.BlobSaverWithAsync) error {
// duplicate a few blobs to exercise those code paths
for blob := range keep {
buf, err := repo.LoadBlob(ctx, blob.Type, blob.ID, nil)
buf, err := repo.LoadBlob(ctx, blob, nil)
rtest.OK(t, err)
_, _, _, err = uploader.SaveBlob(ctx, blob.Type, buf, blob.ID, true)
rtest.OK(t, err)
@@ -180,7 +180,7 @@ func TestPruneSmall(t *testing.T) {
// load all blobs
for blob := range keep {
_, err := repo.LoadBlob(context.TODO(), blob.Type, blob.ID, nil)
_, err := repo.LoadBlob(context.TODO(), blob, nil)
rtest.OK(t, err)
}
+4 -4
View File
@@ -135,7 +135,7 @@ func findPacksForBlobs(t *testing.T, repo restic.Repository, blobs restic.BlobSe
packs := restic.NewIDSet()
for h := range blobs {
list := repo.LookupBlob(h.Type, h.ID)
list := repo.LookupBlob(h)
if len(list) == 0 {
t.Fatal("Failed to find blob", h.ID.Str(), "with type", h.Type)
}
@@ -208,7 +208,7 @@ func testRepack(t *testing.T, version uint) {
}
for h := range keepBlobs {
list := repo.LookupBlob(h.Type, h.ID)
list := repo.LookupBlob(h)
if len(list) == 0 {
t.Errorf("unable to find blob %v in repo", h.ID.Str())
continue
@@ -227,7 +227,7 @@ func testRepack(t *testing.T, version uint) {
}
for h := range removeBlobs {
if _, found := repo.LookupBlobSize(h.Type, h.ID); found {
if _, found := repo.LookupBlobSize(h); found {
t.Errorf("blob %v still contained in the repo", h)
}
}
@@ -277,7 +277,7 @@ func testRepackCopy(t *testing.T, version uint) {
rebuildAndReloadIndex(t, dstRepo)
for h := range keepBlobs {
list := dstRepo.LookupBlob(h.Type, h.ID)
list := dstRepo.LookupBlob(h)
if len(list) == 0 {
t.Errorf("unable to find blob %v in repo", h.ID.Str())
continue
+13 -13
View File
@@ -236,16 +236,16 @@ func sortCachedPacksFirst(cache haver, blobs []*pack.PackedBlob) {
copy(blobs[len(cached):], noncached)
}
// LoadBlob loads a blob of type t from the repository.
// LoadBlob loads a blob from the repository.
// It may use all of buf[:cap(buf)] as scratch space.
func (r *Repository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) {
debug.Log("load %v with id %v (buf len %v, cap %d)", t, id, len(buf), cap(buf))
func (r *Repository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) {
debug.Log("load %v (buf len %v, cap %d)", bh, len(buf), cap(buf))
// lookup packs
blobs := r.idx.Lookup(restic.BlobHandle{ID: id, Type: t})
blobs := r.idx.Lookup(bh)
if len(blobs) == 0 {
debug.Log("id %v not found in index", id)
return nil, errors.Errorf("id %v not found in repository", id)
debug.Log("id %v not found in index", bh.ID)
return nil, errors.Errorf("id %v not found in repository", bh.ID)
}
// try cached pack files first
@@ -671,8 +671,8 @@ func (r *Repository) Connections() uint {
return r.be.Properties().Connections
}
func (r *Repository) LookupBlob(tpe restic.BlobType, id restic.ID) []restic.PackBlob {
entries := r.idx.Lookup(restic.BlobHandle{Type: tpe, ID: id})
func (r *Repository) LookupBlob(bh restic.BlobHandle) []restic.PackBlob {
entries := r.idx.Lookup(bh)
out := make([]restic.PackBlob, len(entries))
for i, e := range entries {
out[i] = e
@@ -681,8 +681,8 @@ func (r *Repository) LookupBlob(tpe restic.BlobType, id restic.ID) []restic.Pack
}
// LookupBlobSize returns the size of blob id. Also returns pending blobs.
func (r *Repository) LookupBlobSize(tpe restic.BlobType, id restic.ID) (uint, bool) {
return r.idx.LookupSize(restic.BlobHandle{Type: tpe, ID: id})
func (r *Repository) LookupBlobSize(bh restic.BlobHandle) (uint, bool) {
return r.idx.LookupSize(bh)
}
// ListBlobs runs fn on all blobs known to the index. When the context is cancelled,
@@ -1059,7 +1059,7 @@ func (r *Repository) saveBlobAsync(ctx context.Context, t restic.BlobType, buf [
}
type backendLoadFn func(ctx context.Context, h backend.Handle, length int, offset int64, fn func(rd io.Reader) error) error
type loadBlobFn func(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error)
type loadBlobFn func(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error)
// Skip sections with more than 1MB unused blobs
const maxUnusedRange = 1 * 1024 * 1024
@@ -1164,7 +1164,7 @@ func streamPackPart(ctx context.Context, beLoad backendLoadFn, loadBlobFn loadBl
if loadBlobFn != nil {
// check whether we can get the remaining blobs somewhere else
for _, entry := range blobs {
buf, ierr := loadBlobFn(ctx, entry.Type, entry.ID, nil)
buf, ierr := loadBlobFn(ctx, entry.BlobHandle, nil)
err = handleBlobFn(entry.BlobHandle, buf, ierr)
if err != nil {
break
@@ -1191,7 +1191,7 @@ func streamPackPart(ctx context.Context, beLoad backendLoadFn, loadBlobFn loadBl
if val.Err != nil && loadBlobFn != nil {
var ierr error
// check whether we can get a valid copy somewhere else
buf, ierr := loadBlobFn(ctx, val.Handle.Type, val.Handle.ID, nil)
buf, ierr := loadBlobFn(ctx, val.Handle, nil)
if ierr == nil {
// success
val.Plaintext = buf
@@ -548,8 +548,8 @@ func TestStreamPackFallback(t *testing.T) {
}
}
loadBlob := func(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) {
if id == blobID {
loadBlob := func(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) {
if bh.ID == blobID {
return plaintext, nil
}
return nil, errors.New("unknown blob")
+8 -8
View File
@@ -66,7 +66,7 @@ func testSave(t *testing.T, version uint, calculateID bool) {
}))
// read back
buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil)
buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil)
rtest.OK(t, err)
rtest.Equals(t, size, len(buf))
@@ -97,7 +97,7 @@ func testSaveLoadZeroSizedBlob(t *testing.T, version uint) {
return nil
}))
buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil)
buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil)
rtest.OK(t, err)
rtest.Equals(t, 0, len(buf))
}
@@ -138,7 +138,7 @@ func testSavePackMerging(t *testing.T, targetPercentage int, expectedPacks int)
// check that all blobs are readable
for _, id := range ids {
_, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil)
_, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil)
rtest.OK(t, err)
}
@@ -201,7 +201,7 @@ func testLoadBlob(t *testing.T, version uint) {
base := crypto.CiphertextLength(length)
for _, testlength := range []int{0, base - 20, base - 1, base, base + 7, base + 15, base + 1000} {
buf = make([]byte, 0, testlength)
buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf)
buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, buf)
if err != nil {
t.Errorf("LoadBlob() returned an error for buffer size %v: %v", testlength, err)
continue
@@ -230,10 +230,10 @@ func TestLoadBlobBroken(t *testing.T) {
c := cache.TestNewCache(t)
repo.UseCache(c, t.Logf)
data, err := repo.LoadBlob(context.TODO(), restic.TreeBlob, id, nil)
data, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.TreeBlob, ID: id}, nil)
rtest.OK(t, err)
rtest.Assert(t, bytes.Equal(buf, data), "data mismatch")
pack := repo.LookupBlob(restic.TreeBlob, id)[0].PackID()
pack := repo.LookupBlob(restic.BlobHandle{Type: restic.TreeBlob, ID: id})[0].PackID()
rtest.Assert(t, c.Has(backend.Handle{Type: restic.PackFile, Name: pack.String()}), "expected tree pack to be cached")
}
@@ -260,7 +260,7 @@ func benchmarkLoadBlob(b *testing.B, version uint) {
for i := 0; i < b.N; i++ {
var err error
buf, err = repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf)
buf, err = repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, buf)
// Checking the SHA-256 with restic.Hash can make up 38% of the time
// spent in this loop, so pause the timer.
@@ -466,7 +466,7 @@ func TestListPack(t *testing.T) {
repo.UseCache(c, t.Logf)
// Forcibly cache pack file
packID := repo.LookupBlob(restic.TreeBlob, id)[0].PackID()
packID := repo.LookupBlob(restic.BlobHandle{Type: restic.TreeBlob, ID: id})[0].PackID()
rtest.OK(t, be.Load(context.TODO(), backend.Handle{Type: restic.PackFile, IsMetadata: true, Name: packID.String()}, 0, 0, func(rd io.Reader) error { return nil }))
// Get size to list pack
+6 -6
View File
@@ -21,8 +21,8 @@ type Repository interface {
LoadIndex(ctx context.Context, p TerminalCounterFactory) error
LookupBlob(t BlobType, id ID) []PackBlob
LookupBlobSize(t BlobType, id ID) (size uint, exists bool)
LookupBlob(bh BlobHandle) []PackBlob
LookupBlobSize(bh BlobHandle) (size uint, exists bool)
NewAssociatedBlobSet() AssociatedBlobSet
// ListBlobs runs fn on all blobs known to the index. When the context is cancelled,
@@ -31,7 +31,7 @@ type Repository interface {
// ListPackHandles returns the blob handles stored in the pack file header.
ListPackHandles(ctx context.Context, id ID, packSize int64) ([]BlobHandle, error)
LoadBlob(ctx context.Context, t BlobType, id ID, buf []byte) ([]byte, error)
LoadBlob(ctx context.Context, bh BlobHandle, buf []byte) ([]byte, error)
LoadBlobsFromPack(ctx context.Context, packID ID, blobs []BlobHandle, handleBlobFn func(blob BlobHandle, buf []byte, err error) error) error
// WithUploader starts the necessary workers to upload new blobs. Once the callback returns,
@@ -148,7 +148,7 @@ type ListBlobser interface {
}
type BlobLoader interface {
LoadBlob(context.Context, BlobType, ID, []byte) ([]byte, error)
LoadBlob(context.Context, BlobHandle, []byte) ([]byte, error)
}
type WithBlobUploader interface {
@@ -173,8 +173,8 @@ type BlobSaverAsync interface {
// Loader loads a blob from a repository.
type Loader interface {
LoadBlob(context.Context, BlobType, ID, []byte) ([]byte, error)
LookupBlobSize(tpe BlobType, id ID) (uint, bool)
LoadBlob(context.Context, BlobHandle, []byte) ([]byte, error)
LookupBlobSize(bh BlobHandle) (uint, bool)
Connections() uint
}
+4 -4
View File
@@ -47,7 +47,7 @@ type startWarmupFn func(context.Context, restic.IDSet) (restic.WarmupJob, error)
// fileRestorer restores set of files
type fileRestorer struct {
idx func(restic.BlobType, restic.ID) []restic.PackBlob
idx func(restic.BlobHandle) []restic.PackBlob
blobsLoader blobsLoaderFn
startWarmup startWarmupFn
@@ -68,7 +68,7 @@ type fileRestorer struct {
func newFileRestorer(dst string,
blobsLoader blobsLoaderFn,
idx func(restic.BlobType, restic.ID) []restic.PackBlob,
idx func(restic.BlobHandle) []restic.PackBlob,
connections uint,
sparse bool,
allowRecursiveDelete bool,
@@ -109,7 +109,7 @@ func (r *fileRestorer) forEachBlob(blobIDs []restic.ID, fn func(blob restic.Pack
fileOffset := int64(0)
for i, blobID := range blobIDs {
packs := r.idx(restic.DataBlob, blobID)
packs := r.idx(restic.BlobHandle{Type: restic.DataBlob, ID: blobID})
if len(packs) == 0 {
return errors.Errorf("Unknown blob %s", blobID.String())
}
@@ -290,7 +290,7 @@ func (r *fileRestorer) downloadPack(ctx context.Context, pack *packInfo) error {
}
} else if packsMap, ok := file.blobs.(map[restic.ID][]fileBlobInfo); ok {
for _, blob := range packsMap[pack.id] {
idxPacks := r.idx(restic.DataBlob, blob.id)
idxPacks := r.idx(restic.BlobHandle{Type: restic.DataBlob, ID: blob.id})
for _, idxPack := range idxPacks {
if idxPack.PackID().Equal(pack.id) {
addBlob(idxPack.Handle(), blob.offset)
+2 -2
View File
@@ -67,8 +67,8 @@ type TestRepo struct {
loader blobsLoaderFn
}
func (i *TestRepo) Lookup(_ restic.BlobType, id restic.ID) []restic.PackBlob {
packs := i.blobs[id]
func (i *TestRepo) Lookup(bh restic.BlobHandle) []restic.PackBlob {
packs := i.blobs[bh.ID]
return packs
}
+1 -1
View File
@@ -744,7 +744,7 @@ func (res *Restorer) verifyFile(ctx context.Context, target string, node *data.N
if ctx.Err() != nil {
return nil, buf, ctx.Err()
}
length, found := res.repo.LookupBlobSize(restic.DataBlob, blobID)
length, found := res.repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: blobID})
if !found {
return nil, buf, errors.Errorf("Unable to fetch blob %s", blobID)
}