mirror of https://github.com/restic/restic.git
Implement Repack()
This commit is contained in:
parent
d5f42201c5
commit
0e6c72ad1d
|
@ -1,9 +1,12 @@
|
||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"restic/backend"
|
"restic/backend"
|
||||||
|
"restic/crypto"
|
||||||
"restic/debug"
|
"restic/debug"
|
||||||
"restic/pack"
|
"restic/pack"
|
||||||
"restic/worker"
|
"restic/worker"
|
||||||
|
@ -11,38 +14,54 @@ import (
|
||||||
|
|
||||||
// Repack takes a list of packs together with a list of blobs contained in
|
// Repack takes a list of packs together with a list of blobs contained in
|
||||||
// these packs. Each pack is loaded and the blobs listed in keepBlobs is saved
|
// these packs. Each pack is loaded and the blobs listed in keepBlobs is saved
|
||||||
// into a new pack. Afterwards, the packs are removed.
|
// into a new pack. Afterwards, the packs are removed. This operation requires
|
||||||
func Repack(repo *Repository, packs, keepBlobs backend.IDSet) error {
|
// an exclusive lock on the repo.
|
||||||
|
func Repack(repo *Repository, packs, keepBlobs backend.IDSet) (err error) {
|
||||||
debug.Log("Repack", "repacking %d packs while keeping %d blobs", len(packs), len(keepBlobs))
|
debug.Log("Repack", "repacking %d packs while keeping %d blobs", len(packs), len(keepBlobs))
|
||||||
|
|
||||||
var buf []byte
|
buf := make([]byte, 0, maxPackSize)
|
||||||
for packID := range packs {
|
for packID := range packs {
|
||||||
list, err := repo.ListPack(packID)
|
// load the complete blob
|
||||||
|
h := backend.Handle{Type: backend.Data, Name: packID.String()}
|
||||||
|
|
||||||
|
l, err := repo.Backend().Load(h, buf[:cap(buf)], 0)
|
||||||
|
if err == io.ErrUnexpectedEOF {
|
||||||
|
err = nil
|
||||||
|
buf = buf[:l]
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("Repack", "processing pack %v, blobs: %v", packID.Str(), list)
|
debug.Log("Repack", "pack %v loaded (%d bytes)", packID.Str(), len(buf))
|
||||||
|
|
||||||
for _, blob := range list {
|
unpck, err := pack.NewUnpacker(repo.Key(), bytes.NewReader(buf))
|
||||||
if !keepBlobs.Has(blob.ID) {
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.Log("Repack", "processing pack %v, blobs: %v", packID.Str(), len(unpck.Entries))
|
||||||
|
var plaintext []byte
|
||||||
|
for _, entry := range unpck.Entries {
|
||||||
|
if !keepBlobs.Has(entry.ID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err = repo.LoadBlob(blob.Type, blob.ID, buf)
|
ciphertext := buf[entry.Offset : entry.Offset+entry.Length]
|
||||||
if err != nil {
|
plaintext, err = crypto.Decrypt(repo.Key(), plaintext, ciphertext)
|
||||||
return err
|
|
||||||
}
|
|
||||||
debug.Log("Repack", " loaded blob %v", blob.ID.Str())
|
|
||||||
|
|
||||||
_, err = repo.SaveAndEncrypt(blob.Type, buf, &blob.ID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("Repack", " saved blob %v", blob.ID.Str())
|
_, err = repo.SaveAndEncrypt(entry.Type, plaintext, &entry.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
keepBlobs.Delete(blob.ID)
|
debug.Log("Repack", " saved blob %v", entry.ID.Str())
|
||||||
|
|
||||||
|
keepBlobs.Delete(entry.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue