Introduce LoadTreeBlob and LoadDataBlob
This commit is contained in:
parent
573410afab
commit
84f95a09d7
14 changed files with 67 additions and 32 deletions
|
@ -61,7 +61,7 @@ func parseTime(str string) (time.Time, error) {
|
|||
|
||||
func (c CmdFind) findInTree(repo *repository.Repository, id restic.ID, path string) ([]findResult, error) {
|
||||
debug.Log("restic.find", "checking tree %v\n", id)
|
||||
tree, err := restic.LoadTree(repo, id)
|
||||
tree, err := repo.LoadTree(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ func (cmd CmdLs) printNode(prefix string, n *restic.Node) string {
|
|||
}
|
||||
|
||||
func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id restic.ID) error {
|
||||
tree, err := restic.LoadTree(repo, id)
|
||||
tree, err := repo.LoadTree(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func loadBlob(t *testing.T, repo *repository.Repository, id restic.ID, buf []byt
|
|||
}
|
||||
|
||||
func checkSavedFile(t *testing.T, repo *repository.Repository, treeID restic.ID, name string, rd io.Reader) {
|
||||
tree, err := restic.LoadTree(repo, treeID)
|
||||
tree, err := repo.LoadTree(treeID)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadTree() returned error %v", err)
|
||||
}
|
||||
|
|
|
@ -376,7 +376,7 @@ func loadTreeWorker(repo restic.Repository,
|
|||
}
|
||||
debug.Log("checker.loadTreeWorker", "load tree %v", treeID.Str())
|
||||
|
||||
tree, err := restic.LoadTree(repo, treeID)
|
||||
tree, err := repo.LoadTree(treeID)
|
||||
debug.Log("checker.loadTreeWorker", "load tree %v (%v) returned err: %v", tree, treeID.Str(), err)
|
||||
job = treeJob{ID: treeID, error: err, Tree: tree}
|
||||
outCh = out
|
||||
|
|
|
@ -6,7 +6,7 @@ package restic
|
|||
func FindUsedBlobs(repo Repository, treeID ID, blobs BlobSet, seen BlobSet) error {
|
||||
blobs.Insert(BlobHandle{ID: treeID, Type: TreeBlob})
|
||||
|
||||
tree, err := LoadTree(repo, treeID)
|
||||
tree, err := repo.LoadTree(treeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ type dir struct {
|
|||
|
||||
func newDir(repo *repository.Repository, node *restic.Node, ownerIsRoot bool) (*dir, error) {
|
||||
debug.Log("newDir", "new dir for %v (%v)", node.Name, node.Subtree.Str())
|
||||
tree, err := restic.LoadTree(repo, *node.Subtree)
|
||||
tree, err := repo.LoadTree(*node.Subtree)
|
||||
if err != nil {
|
||||
debug.Log("newDir", " error loading tree %v: %v", node.Subtree.Str(), err)
|
||||
return nil, err
|
||||
|
@ -59,7 +59,7 @@ func replaceSpecialNodes(repo *repository.Repository, node *restic.Node) ([]*res
|
|||
return []*restic.Node{node}, nil
|
||||
}
|
||||
|
||||
tree, err := restic.LoadTree(repo, *node.Subtree)
|
||||
tree, err := repo.LoadTree(*node.Subtree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ func replaceSpecialNodes(repo *repository.Repository, node *restic.Node) ([]*res
|
|||
|
||||
func newDirFromSnapshot(repo *repository.Repository, snapshot SnapshotWithId, ownerIsRoot bool) (*dir, error) {
|
||||
debug.Log("newDirFromSnapshot", "new dir for snapshot %v (%v)", snapshot.ID.Str(), snapshot.Tree.Str())
|
||||
tree, err := restic.LoadTree(repo, *snapshot.Tree)
|
||||
tree, err := repo.LoadTree(*snapshot.Tree)
|
||||
if err != nil {
|
||||
debug.Log("newDirFromSnapshot", " loadTree(%v) failed: %v", snapshot.ID.Str(), err)
|
||||
return nil, err
|
||||
|
|
|
@ -218,10 +218,11 @@ func (node Node) createFileAt(path string, repo Repository) error {
|
|||
buf = make([]byte, size)
|
||||
}
|
||||
|
||||
buf, err := repo.LoadBlob(id, DataBlob, buf)
|
||||
n, err := repo.LoadDataBlob(id, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf = buf[:n]
|
||||
|
||||
_, err = f.Write(buf)
|
||||
if err != nil {
|
||||
|
|
|
@ -31,10 +31,11 @@ type Repository interface {
|
|||
SaveAndEncrypt(BlobType, []byte, *ID) (ID, error)
|
||||
SaveJSONUnpacked(FileType, interface{}) (ID, error)
|
||||
|
||||
LoadJSONPack(BlobType, ID, interface{}) error
|
||||
LoadJSONUnpacked(FileType, ID, interface{}) error
|
||||
LoadBlob(ID, BlobType, []byte) ([]byte, error)
|
||||
LoadAndDecrypt(FileType, ID) ([]byte, error)
|
||||
|
||||
LoadTree(id ID) (*Tree, error)
|
||||
LoadDataBlob(id ID, buf []byte) (int, error)
|
||||
}
|
||||
|
||||
// Deleter removes all data stored in a backend/repo.
|
||||
|
|
|
@ -589,3 +589,45 @@ func (r *Repository) Delete() error {
|
|||
func (r *Repository) Close() error {
|
||||
return r.be.Close()
|
||||
}
|
||||
|
||||
// LoadTree loads a tree from the repository.
|
||||
func (r *Repository) LoadTree(id restic.ID) (*restic.Tree, error) {
|
||||
size, err := r.idx.LookupSize(id, restic.TreeBlob)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := make([]byte, size)
|
||||
|
||||
buf, err = r.LoadBlob(id, restic.TreeBlob, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t := &restic.Tree{}
|
||||
err = json.Unmarshal(buf, t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// LoadDataBlob loads a data blob from the repository to the buffer.
|
||||
func (r *Repository) LoadDataBlob(id restic.ID, buf []byte) (int, error) {
|
||||
size, err := r.idx.LookupSize(id, restic.DataBlob)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if len(buf) < int(size) {
|
||||
return 0, errors.Errorf("buffer is too small for data blob (%d < %d)", len(buf), size)
|
||||
}
|
||||
|
||||
buf, err = r.LoadBlob(id, restic.DataBlob, buf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(buf), err
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func NewRestorer(repo Repository, id ID) (*Restorer, error) {
|
|||
}
|
||||
|
||||
func (res *Restorer) restoreTo(dst string, dir string, treeID ID) error {
|
||||
tree, err := LoadTree(res.repo, treeID)
|
||||
tree, err := res.repo.LoadTree(treeID)
|
||||
if err != nil {
|
||||
return res.Error(dir, nil, err)
|
||||
}
|
||||
|
|
|
@ -25,20 +25,6 @@ func (t Tree) String() string {
|
|||
return fmt.Sprintf("Tree<%d nodes>", len(t.Nodes))
|
||||
}
|
||||
|
||||
type TreeLoader interface {
|
||||
LoadJSONPack(BlobType, ID, interface{}) error
|
||||
}
|
||||
|
||||
func LoadTree(repo TreeLoader, id ID) (*Tree, error) {
|
||||
tree := &Tree{}
|
||||
err := repo.LoadJSONPack(TreeBlob, id, tree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tree, nil
|
||||
}
|
||||
|
||||
// Equals returns true if t and other have exactly the same nodes.
|
||||
func (t Tree) Equals(other *Tree) bool {
|
||||
if len(t.Nodes) != len(other.Nodes) {
|
||||
|
@ -85,6 +71,7 @@ func (t Tree) binarySearch(name string) (int, *Node, error) {
|
|||
return pos, nil, errors.New("named node not found")
|
||||
}
|
||||
|
||||
// Find returns a node with the given name.
|
||||
func (t Tree) Find(name string) (*Node, error) {
|
||||
_, node, err := t.binarySearch(name)
|
||||
return node, err
|
||||
|
|
|
@ -104,7 +104,7 @@ func TestLoadTree(t *testing.T) {
|
|||
OK(t, repo.Flush())
|
||||
|
||||
// load tree again
|
||||
tree2, err := restic.LoadTree(repo, id)
|
||||
tree2, err := repo.LoadTree(id)
|
||||
OK(t, err)
|
||||
|
||||
Assert(t, tree.Equals(tree2),
|
||||
|
|
|
@ -156,17 +156,21 @@ func loadTreeWorker(wg *sync.WaitGroup, in <-chan loadTreeJob, load treeLoader,
|
|||
}
|
||||
}
|
||||
|
||||
// TreeLoader loads tree objects.
|
||||
type TreeLoader interface {
|
||||
LoadTree(restic.ID) (*restic.Tree, error)
|
||||
}
|
||||
|
||||
const loadTreeWorkers = 10
|
||||
|
||||
// Tree walks the tree specified by id recursively and sends a job for each
|
||||
// file and directory it finds. When the channel done is closed, processing
|
||||
// stops.
|
||||
func Tree(repo restic.TreeLoader, id restic.ID, done chan struct{}, jobCh chan<- TreeJob) {
|
||||
func Tree(repo TreeLoader, id restic.ID, done chan struct{}, jobCh chan<- TreeJob) {
|
||||
debug.Log("WalkTree", "start on %v, start workers", id.Str())
|
||||
|
||||
load := func(id restic.ID) (*restic.Tree, error) {
|
||||
tree := &restic.Tree{}
|
||||
err := repo.LoadJSONPack(restic.TreeBlob, id, tree)
|
||||
tree, err := repo.LoadTree(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -95,9 +95,9 @@ type delayRepo struct {
|
|||
delay time.Duration
|
||||
}
|
||||
|
||||
func (d delayRepo) LoadJSONPack(t restic.BlobType, id restic.ID, dst interface{}) error {
|
||||
func (d delayRepo) LoadTree(id restic.ID) (*restic.Tree, error) {
|
||||
time.Sleep(d.delay)
|
||||
return d.repo.LoadJSONPack(t, id, dst)
|
||||
return d.repo.LoadTree(id)
|
||||
}
|
||||
|
||||
var repoFixture = filepath.Join("testdata", "walktree-test-repo.tar.gz")
|
||||
|
|
Loading…
Reference in a new issue