aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorn-peugnet <n.peugnet@free.fr>2021-10-07 11:56:37 +0200
committern-peugnet <n.peugnet@free.fr>2021-10-07 11:56:37 +0200
commit459343932d9673fc69ce1363ccb70d5f78f2e3e7 (patch)
tree29514fb9a369d023a7c797bea75aeefe715d7ca5
parent5be8ba4dff6c181fd78b5922be27c599c6b8d842 (diff)
downloaddna-backup-459343932d9673fc69ce1363ccb70d5f78f2e3e7.tar.gz
dna-backup-459343932d9673fc69ce1363ccb70d5f78f2e3e7.zip
fix storeDelta by keeping previous raw bytes
this ensures that the last patch is created on top of the previous one. This way we know that it will be correctly applied on loadDelta Also directly write to wrapper instead of using an intermediate buffer.
-rw-r--r--delta/delta.go7
-rw-r--r--repo/repo.go42
2 files changed, 28 insertions, 21 deletions
diff --git a/delta/delta.go b/delta/delta.go
index 439da1d..4be57c2 100644
--- a/delta/delta.go
+++ b/delta/delta.go
@@ -1,6 +1,7 @@
package delta
import (
+ "fmt"
"io"
"github.com/gabstv/go-bsdiff/pkg/bsdiff"
@@ -44,15 +45,15 @@ func (Fdelta) Diff(source io.Reader, target io.Reader, patch io.Writer) error {
func (Fdelta) Patch(source io.Reader, target io.Writer, patch io.Reader) error {
sourceBuf, err := io.ReadAll(source)
if err != nil {
- return err
+ return fmt.Errorf("source read all: %s", err)
}
patchBuf, err := io.ReadAll(patch)
if err != nil {
- return err
+ return fmt.Errorf("patch read all: %s", err)
}
targetBuf, err := fdelta.Apply(sourceBuf, patchBuf)
if err != nil {
- return err
+ return fmt.Errorf("apply patch: %s", err)
}
_, err = target.Write(targetBuf)
return err
diff --git a/repo/repo.go b/repo/repo.go
index ab96dbe..678b091 100644
--- a/repo/repo.go
+++ b/repo/repo.go
@@ -79,7 +79,9 @@ type Repo struct {
fingerprints FingerprintMap
sketches SketchMap
recipe []Chunk
+ recipeRaw []byte
files []File
+ filesRaw []byte
chunkCache cache.Cacher
chunkReadWrapper utils.ReadWrapper
chunkWriteWrapper utils.WriteWrapper
@@ -334,31 +336,30 @@ func concatFiles(files *[]File, stream io.WriteCloser) {
*files = actual
}
-func storeDelta(prev interface{}, curr interface{}, dest string, differ delta.Differ, wrapper utils.WriteWrapper) {
- var prevBytes, currBytes, deltaBytes bytes.Buffer
+func storeDelta(prevRaw []byte, curr interface{}, dest string, differ delta.Differ, wrapper utils.WriteWrapper) {
+ var prevBuff, currBuff bytes.Buffer
var encoder *gob.Encoder
var err error
- encoder = gob.NewEncoder(&prevBytes)
- if err = encoder.Encode(prev); err != nil {
- logger.Panic(err)
+ if len(prevRaw) == 0 {
+ encoder = gob.NewEncoder(&prevBuff)
+ if err = encoder.EncodeValue(reflect.ValueOf(curr)); err != nil {
+ logger.Panic(err)
+ }
+ } else {
+ prevBuff = *bytes.NewBuffer(prevRaw)
}
- encoder = gob.NewEncoder(&currBytes)
+ encoder = gob.NewEncoder(&currBuff)
if err = encoder.Encode(curr); err != nil {
logger.Panic(err)
}
- if err = differ.Diff(&prevBytes, &currBytes, &deltaBytes); err != nil {
- logger.Panic(err)
- }
-
file, err := os.Create(dest)
if err != nil {
logger.Panic(err)
}
out := wrapper(file)
- n, err := io.Copy(out, &deltaBytes)
- if err != nil {
- logger.Panic(n, err)
+ if err = differ.Diff(&prevBuff, &currBuff, out); err != nil {
+ logger.Panic(err)
}
if err = out.Close(); err != nil {
logger.Panic(err)
@@ -368,7 +369,7 @@ func storeDelta(prev interface{}, curr interface{}, dest string, differ delta.Di
}
}
-func loadDeltas(target interface{}, versions []string, patcher delta.Patcher, wrapper utils.ReadWrapper, name string) {
+func loadDeltas(target interface{}, versions []string, patcher delta.Patcher, wrapper utils.ReadWrapper, name string) []byte {
var prev bytes.Buffer
var encoder *gob.Encoder
var err error
@@ -396,24 +397,29 @@ func loadDeltas(target interface{}, versions []string, patcher delta.Patcher, wr
if err = in.Close(); err != nil {
logger.Panic(err)
}
+ if err = file.Close(); err != nil {
+ logger.Panic(err)
+ }
}
+ ret := prev.Bytes()
decoder := gob.NewDecoder(&prev)
if err = decoder.Decode(target); err != nil {
logger.Panic(err)
}
+ return ret
}
// storeFileList stores the given list in the repo dir as a delta against the
// previous version's one.
func (r *Repo) storeFileList(version int, list []File) {
dest := filepath.Join(r.path, fmt.Sprintf(versionFmt, version), filesName)
- storeDelta(r.files, list, dest, r.differ, r.chunkWriteWrapper)
+ storeDelta(r.filesRaw, list, dest, r.differ, r.chunkWriteWrapper)
}
// loadFileLists loads incrementally the file lists' delta of each given version.
func (r *Repo) loadFileLists(versions []string) {
var files []File
- loadDeltas(&files, versions, r.patcher, r.chunkReadWrapper, filesName)
+ r.filesRaw = loadDeltas(&files, versions, r.patcher, r.chunkReadWrapper, filesName)
r.files = files
}
@@ -735,12 +741,12 @@ func (r *Repo) restoreStream(stream io.WriteCloser, recipe []Chunk) {
func (r *Repo) storeRecipe(version int, recipe []Chunk) {
dest := filepath.Join(r.path, fmt.Sprintf(versionFmt, version), recipeName)
- storeDelta(r.recipe, recipe, dest, r.differ, r.chunkWriteWrapper)
+ storeDelta(r.recipeRaw, recipe, dest, r.differ, r.chunkWriteWrapper)
}
func (r *Repo) loadRecipes(versions []string) {
var recipe []Chunk
- loadDeltas(&recipe, versions, r.patcher, r.chunkReadWrapper, recipeName)
+ r.recipeRaw = loadDeltas(&recipe, versions, r.patcher, r.chunkReadWrapper, recipeName)
for _, c := range recipe {
if rc, isRepo := c.(RepoChunk); isRepo {
rc.SetRepo(r)