// selectBlobs splits the list of all blobs randomly into two lists. A blob // will be contained in the firstone ith probability p. func selectBlobs(t *testing.T, repo restic.Repository, p float32) (list1, list2 restic.BlobSet) { done := make(chan struct{}) defer close(done) list1 = restic.NewBlobSet() list2 = restic.NewBlobSet() blobs := restic.NewBlobSet() for id := range repo.List(restic.DataFile, done) { entries, _, err := repo.ListPack(id) if err != nil { t.Fatalf("error listing pack %v: %v", id, err) } for _, entry := range entries { h := restic.BlobHandle{ID: entry.ID, Type: entry.Type} if blobs.Has(h) { t.Errorf("ignoring duplicate blob %v", h) continue } blobs.Insert(h) if rand.Float32() <= p { list1.Insert(restic.BlobHandle{ID: entry.ID, Type: entry.Type}) } else { list2.Insert(restic.BlobHandle{ID: entry.ID, Type: entry.Type}) } } } return list1, list2 }
func validateIndex(t testing.TB, repo restic.Repository, idx *Index) { for id := range repo.List(restic.DataFile, nil) { if _, ok := idx.Packs[id]; !ok { t.Errorf("pack %v missing from index", id.Str()) } } }
func listPacks(t *testing.T, repo restic.Repository) restic.IDSet { done := make(chan struct{}) defer close(done) list := restic.NewIDSet() for id := range repo.List(restic.DataFile, done) { list.Insert(id) } return list }
// RebuildIndex lists all packs in the repo, writes a new index and removes all // old indexes. This operation should only be done with an exclusive lock in // place. func RebuildIndex(repo restic.Repository) error { debug.Log("start rebuilding index") done := make(chan struct{}) defer close(done) ch := make(chan worker.Job) go list.AllPacks(repo, ch, done) idx := NewIndex() for job := range ch { id := job.Data.(restic.ID) if job.Error != nil { fmt.Fprintf(os.Stderr, "error for pack %v: %v\n", id, job.Error) continue } res := job.Result.(list.Result) for _, entry := range res.Entries() { pb := restic.PackedBlob{ Blob: entry, PackID: res.PackID(), } idx.Store(pb) } } oldIndexes := restic.NewIDSet() for id := range repo.List(restic.IndexFile, done) { idx.AddToSupersedes(id) oldIndexes.Insert(id) } id, err := SaveIndex(repo, idx) if err != nil { debug.Log("error saving index: %v", err) return err } debug.Log("new index saved as %v", id.Str()) for indexID := range oldIndexes { err := repo.Backend().Remove(restic.IndexFile, indexID.String()) if err != nil { fmt.Fprintf(os.Stderr, "unable to remove index %v: %v\n", indexID.Str(), err) } } return nil }
func dumpIndexes(repo restic.Repository) error { done := make(chan struct{}) defer close(done) for id := range repo.List(restic.IndexFile, done) { fmt.Printf("index_id: %v\n", id) idx, err := repository.LoadIndex(repo, id) if err != nil { return err } err = idx.Dump(os.Stdout) if err != nil { return err } } return nil }
// Load creates an index by loading all index files from the repo. func Load(repo restic.Repository, p *restic.Progress) (*Index, error) { debug.Log("loading indexes") p.Start() defer p.Done() done := make(chan struct{}) defer close(done) supersedes := make(map[restic.ID]restic.IDSet) results := make(map[restic.ID]map[restic.ID]Pack) index := newIndex() for id := range repo.List(restic.IndexFile, done) { p.Report(restic.Stat{Blobs: 1}) debug.Log("Load index %v", id.Str()) idx, err := loadIndexJSON(repo, id) if err != nil { return nil, err } res := make(map[restic.ID]Pack) supersedes[id] = restic.NewIDSet() for _, sid := range idx.Supersedes { debug.Log(" index %v supersedes %v", id.Str(), sid) supersedes[id].Insert(sid) } for _, jpack := range idx.Packs { entries := make([]restic.Blob, 0, len(jpack.Blobs)) for _, blob := range jpack.Blobs { entry := restic.Blob{ ID: blob.ID, Type: blob.Type, Offset: blob.Offset, Length: blob.Length, } entries = append(entries, entry) } if err = index.AddPack(jpack.ID, 0, entries); err != nil { return nil, err } } results[id] = res index.IndexIDs.Insert(id) } for superID, list := range supersedes { for indexID := range list { if _, ok := results[indexID]; !ok { continue } debug.Log(" removing index %v, superseded by %v", indexID.Str(), superID.Str()) fmt.Fprintf(os.Stderr, "index %v can be removed, superseded by index %v\n", indexID.Str(), superID.Str()) delete(results, indexID) } } return index, nil }