mirror of
https://github.com/octoleo/restic.git
synced 2024-11-26 23:06:32 +00:00
Merge pull request #392 from restic/fix-build
Allow saving duplicate blobs in the repacker
This commit is contained in:
commit
4d7e802c44
@ -136,7 +136,7 @@ func repackBlob(src, dst *repository.Repository, id backend.ID) error {
|
|||||||
return errors.New("LoadBlob returned wrong data, len() doesn't match")
|
return errors.New("LoadBlob returned wrong data, len() doesn't match")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = dst.SaveAndEncrypt(blob.Type, buf, &id)
|
_, err = dst.SaveAndEncrypt(blob.Type, buf, &id, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,6 @@ func TestLargeEncrypt(t *testing.T) {
|
|||||||
|
|
||||||
func BenchmarkEncryptWriter(b *testing.B) {
|
func BenchmarkEncryptWriter(b *testing.B) {
|
||||||
size := 8 << 20 // 8MiB
|
size := 8 << 20 // 8MiB
|
||||||
rd := RandomReader(23, size)
|
|
||||||
|
|
||||||
k := crypto.NewRandomKey()
|
k := crypto.NewRandomKey()
|
||||||
|
|
||||||
@ -141,7 +140,7 @@ func BenchmarkEncryptWriter(b *testing.B) {
|
|||||||
b.SetBytes(int64(size))
|
b.SetBytes(int64(size))
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
rd.Seek(0, 0)
|
rd := RandomReader(23, size)
|
||||||
wr := crypto.EncryptTo(k, ioutil.Discard)
|
wr := crypto.EncryptTo(k, ioutil.Discard)
|
||||||
n, err := io.Copy(wr, rd)
|
n, err := io.Copy(wr, rd)
|
||||||
OK(b, err)
|
OK(b, err)
|
||||||
@ -195,14 +194,13 @@ func BenchmarkEncryptDecryptReader(b *testing.B) {
|
|||||||
k := crypto.NewRandomKey()
|
k := crypto.NewRandomKey()
|
||||||
|
|
||||||
size := 8 << 20 // 8MiB
|
size := 8 << 20 // 8MiB
|
||||||
rd := RandomReader(23, size)
|
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.SetBytes(int64(size))
|
b.SetBytes(int64(size))
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
rd.Seek(0, 0)
|
rd := RandomReader(23, size)
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
wr := crypto.EncryptTo(k, buf)
|
wr := crypto.EncryptTo(k, buf)
|
||||||
_, err := io.Copy(wr, rd)
|
_, err := io.Copy(wr, rd)
|
||||||
|
@ -155,25 +155,32 @@ func (mi *MasterIndex) Current() *Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddInFlight add the given ID to the list of in-flight IDs. An error is
|
// AddInFlight add the given ID to the list of in-flight IDs. An error is
|
||||||
// returned when the ID is already in the list.
|
// returned when the ID is already in the list. Setting ignoreDuplicates to
|
||||||
func (mi *MasterIndex) AddInFlight(id backend.ID) error {
|
// true only checks the in flight list, otherwise the index itself is also
|
||||||
|
// tested.
|
||||||
|
func (mi *MasterIndex) AddInFlight(id backend.ID, ignoreDuplicates bool) error {
|
||||||
// The index + inFlight store must be searched for a matching id in one
|
// The index + inFlight store must be searched for a matching id in one
|
||||||
// atomic operation. This requires locking the inFlight store and the
|
// atomic operation. This requires locking the inFlight store and the
|
||||||
// index together!
|
// index together!
|
||||||
mi.inFlight.Lock()
|
mi.inFlight.Lock()
|
||||||
defer mi.inFlight.Unlock()
|
defer mi.inFlight.Unlock()
|
||||||
|
|
||||||
|
if !ignoreDuplicates {
|
||||||
// Note: mi.Has read locks the index again.
|
// Note: mi.Has read locks the index again.
|
||||||
mi.idxMutex.RLock()
|
mi.idxMutex.RLock()
|
||||||
defer mi.idxMutex.RUnlock()
|
defer mi.idxMutex.RUnlock()
|
||||||
|
|
||||||
debug.Log("MasterIndex.AddInFlight", "adding %v", id)
|
|
||||||
if mi.inFlight.Has(id) {
|
|
||||||
return fmt.Errorf("%v is already in flight", id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug.Log("MasterIndex.AddInFlight", "adding %v", id.Str())
|
||||||
|
if mi.inFlight.Has(id) {
|
||||||
|
return fmt.Errorf("%v is already in flight", id.Str())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignoreDuplicates {
|
||||||
if mi.Has(id) {
|
if mi.Has(id) {
|
||||||
return fmt.Errorf("%v is already indexed (fully processed)", id)
|
return fmt.Errorf("%v is already indexed (fully processed)", id)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mi.inFlight.Insert(id)
|
mi.inFlight.Insert(id)
|
||||||
return nil
|
return nil
|
||||||
@ -187,7 +194,6 @@ func (mi *MasterIndex) IsInFlight(id backend.ID) bool {
|
|||||||
mi.inFlight.RLock()
|
mi.inFlight.RLock()
|
||||||
defer mi.inFlight.RUnlock()
|
defer mi.inFlight.RUnlock()
|
||||||
|
|
||||||
// Note: mi.Has read locks the index again.
|
|
||||||
mi.idxMutex.RLock()
|
mi.idxMutex.RLock()
|
||||||
defer mi.idxMutex.RUnlock()
|
defer mi.idxMutex.RUnlock()
|
||||||
|
|
||||||
|
@ -219,8 +219,9 @@ func (r *Repository) LookupBlobSize(id backend.ID) (uint, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveAndEncrypt encrypts data and stores it to the backend as type t. If data is small
|
// SaveAndEncrypt encrypts data and stores it to the backend as type t. If data is small
|
||||||
// enough, it will be packed together with other small blobs.
|
// enough, it will be packed together with other small blobs. When
|
||||||
func (r *Repository) SaveAndEncrypt(t pack.BlobType, data []byte, id *backend.ID) (backend.ID, error) {
|
// ignoreDuplicates is true, blobs already in the index will be saved again.
|
||||||
|
func (r *Repository) SaveAndEncrypt(t pack.BlobType, data []byte, id *backend.ID, ignoreDuplicates bool) (backend.ID, error) {
|
||||||
if id == nil {
|
if id == nil {
|
||||||
// compute plaintext hash
|
// compute plaintext hash
|
||||||
hashedID := backend.Hash(data)
|
hashedID := backend.Hash(data)
|
||||||
@ -241,7 +242,7 @@ func (r *Repository) SaveAndEncrypt(t pack.BlobType, data []byte, id *backend.ID
|
|||||||
|
|
||||||
// add this id to the list of in-flight chunk ids.
|
// add this id to the list of in-flight chunk ids.
|
||||||
debug.Log("Repo.Save", "add %v to list of in-flight IDs", id.Str())
|
debug.Log("Repo.Save", "add %v to list of in-flight IDs", id.Str())
|
||||||
err = r.idx.AddInFlight(*id)
|
err = r.idx.AddInFlight(*id, ignoreDuplicates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("Repo.Save", "another goroutine is already working on %v (%v) does already exist", id.Str, t)
|
debug.Log("Repo.Save", "another goroutine is already working on %v (%v) does already exist", id.Str, t)
|
||||||
return *id, nil
|
return *id, nil
|
||||||
@ -284,7 +285,7 @@ func (r *Repository) SaveFrom(t pack.BlobType, id *backend.ID, length uint, rd i
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = r.SaveAndEncrypt(t, buf, id)
|
_, err = r.SaveAndEncrypt(t, buf, id, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -308,7 +309,7 @@ func (r *Repository) SaveJSON(t pack.BlobType, item interface{}) (backend.ID, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf = wr.Bytes()
|
buf = wr.Bytes()
|
||||||
return r.SaveAndEncrypt(t, buf, nil)
|
return r.SaveAndEncrypt(t, buf, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveJSONUnpacked serialises item as JSON and encrypts and saves it in the
|
// SaveJSONUnpacked serialises item as JSON and encrypts and saves it in the
|
||||||
|
@ -83,7 +83,7 @@ func TestSave(t *testing.T) {
|
|||||||
id := backend.Hash(data)
|
id := backend.Hash(data)
|
||||||
|
|
||||||
// save
|
// save
|
||||||
sid, err := repo.SaveAndEncrypt(pack.Data, data, nil)
|
sid, err := repo.SaveAndEncrypt(pack.Data, data, nil, false)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
|
|
||||||
Equals(t, id, sid)
|
Equals(t, id, sid)
|
||||||
@ -253,7 +253,7 @@ func saveRandomDataBlobs(t testing.TB, repo *repository.Repository, num int, siz
|
|||||||
_, err := io.ReadFull(rand.Reader, buf)
|
_, err := io.ReadFull(rand.Reader, buf)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
|
|
||||||
_, err = repo.SaveAndEncrypt(pack.Data, buf, nil)
|
_, err = repo.SaveAndEncrypt(pack.Data, buf, nil, false)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,6 @@ type rndReader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *rndReader) Read(p []byte) (int, error) {
|
func (r *rndReader) Read(p []byte) (int, error) {
|
||||||
fmt.Printf("Read(%v)\n", len(p))
|
|
||||||
for i := range p {
|
for i := range p {
|
||||||
p[i] = byte(r.src.Uint32())
|
p[i] = byte(r.src.Uint32())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user