diff options
author | n-peugnet <n.peugnet@free.fr> | 2021-10-06 14:46:38 +0200 |
---|---|---|
committer | n-peugnet <n.peugnet@free.fr> | 2021-10-06 14:46:38 +0200 |
commit | 763c6b985da74078e8683fa83b3f599619deb00d (patch) | |
tree | 06dbaad6b565481942fb024f16354b93bcaa21dd /repo/repo.go | |
parent | 21a8ea292cc715fd22df7ef52bf6e1675bfc7dc4 (diff) | |
download | dna-backup-763c6b985da74078e8683fa83b3f599619deb00d.tar.gz dna-backup-763c6b985da74078e8683fa83b3f599619deb00d.zip |
use repo deltacodec for recipe and files
this should not only be more efficient in space but also in time
drop old Commit and Restore tests that do not use compression
Diffstat (limited to 'repo/repo.go')
-rw-r--r-- | repo/repo.go | 124 |
1 files changed, 50 insertions, 74 deletions
diff --git a/repo/repo.go b/repo/repo.go index 97d0b5c..ab96dbe 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -43,7 +43,6 @@ import ( "github.com/n-peugnet/dna-backup/delta" "github.com/n-peugnet/dna-backup/logger" "github.com/n-peugnet/dna-backup/sketch" - "github.com/n-peugnet/dna-backup/slice" "github.com/n-peugnet/dna-backup/utils" ) @@ -335,40 +334,33 @@ func concatFiles(files *[]File, stream io.WriteCloser) { *files = actual } -func storeBasicStruct(dest string, wrapper utils.WriteWrapper, obj interface{}) { - file, err := os.Create(dest) - if err != nil { - logger.Panic(err) - } - out := wrapper(file) - encoder := gob.NewEncoder(out) - err = encoder.Encode(obj) - if err != nil { +func storeDelta(prev interface{}, curr interface{}, dest string, differ delta.Differ, wrapper utils.WriteWrapper) { + var prevBytes, currBytes, deltaBytes bytes.Buffer + var encoder *gob.Encoder + var err error + + encoder = gob.NewEncoder(&prevBytes) + if err = encoder.Encode(prev); err != nil { logger.Panic(err) } - if err = out.Close(); err != nil { + encoder = gob.NewEncoder(&currBytes) + if err = encoder.Encode(curr); err != nil { logger.Panic(err) } - if err = file.Close(); err != nil { + if err = differ.Diff(&prevBytes, &currBytes, &deltaBytes); err != nil { logger.Panic(err) } -} -func loadBasicStruct(path string, wrapper utils.ReadWrapper, obj interface{}) { - file, err := os.Open(path) - if err != nil { - logger.Panic(err) - } - in, err := wrapper(file) + file, err := os.Create(dest) if err != nil { logger.Panic(err) } - decoder := gob.NewDecoder(in) - err = decoder.Decode(obj) + out := wrapper(file) + n, err := io.Copy(out, &deltaBytes) if err != nil { - logger.Panic(err) + logger.Panic(n, err) } - if err = in.Close(); err != nil { + if err = out.Close(); err != nil { logger.Panic(err) } if err = file.Close(); err != nil { @@ -376,48 +368,53 @@ func loadBasicStruct(path string, wrapper utils.ReadWrapper, obj interface{}) { } } -func (r *Repo) loadDeltas(versions []string, wrapper utils.ReadWrapper, name string) (ret slice.Slice) { - for _, v := range versions { - path := filepath.Join(v, name) - var delta slice.Delta - loadBasicStruct(path, wrapper, &delta) - ret = slice.Patch(ret, delta) - } - return -} +func loadDeltas(target interface{}, versions []string, patcher delta.Patcher, wrapper utils.ReadWrapper, name string) { + var prev bytes.Buffer + var encoder *gob.Encoder + var err error -func fileList2slice(l []File) (ret slice.Slice) { - ret = make(slice.Slice, len(l)) - for i := range l { - ret[i] = l[i] + encoder = gob.NewEncoder(&prev) + if err = encoder.Encode(target); err != nil { + logger.Panic(err) } - return -} -func slice2fileList(s slice.Slice) (ret []File) { - ret = make([]File, len(s)) - for i := range s { - if f, ok := s[i].(File); ok { - ret[i] = f - } else { - logger.Warningf("could not convert %s into a File", s[i]) + for _, v := range versions { + var curr bytes.Buffer + path := filepath.Join(v, name) + file, err := os.Open(path) + if err != nil { + logger.Panic(err) + } + in, err := wrapper(file) + if err != nil { + logger.Panic(err) + } + if err = patcher.Patch(&prev, &curr, in); err != nil { + logger.Panic(err) + } + prev = curr + if err = in.Close(); err != nil { + logger.Panic(err) } } - return + decoder := gob.NewDecoder(&prev) + if err = decoder.Decode(target); err != nil { + logger.Panic(err) + } } // 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) - delta := slice.Diff(fileList2slice(r.files), fileList2slice(list)) - logger.Infof("files delta %s", delta.String()) - storeBasicStruct(dest, r.chunkWriteWrapper, delta) + storeDelta(r.files, list, dest, r.differ, r.chunkWriteWrapper) } // loadFileLists loads incrementally the file lists' delta of each given version. func (r *Repo) loadFileLists(versions []string) { - r.files = slice2fileList(r.loadDeltas(versions, r.chunkReadWrapper, filesName)) + var files []File + loadDeltas(&files, versions, r.patcher, r.chunkReadWrapper, filesName) + r.files = files } // storageWorker is meant to be started in a goroutine and stores each new chunk's @@ -736,35 +733,14 @@ func (r *Repo) restoreStream(stream io.WriteCloser, recipe []Chunk) { stream.Close() } -func recipe2slice(r []Chunk) (ret slice.Slice) { - ret = make(slice.Slice, len(r)) - for i := range r { - ret[i] = r[i] - } - return -} - -func slice2recipe(s slice.Slice) (ret []Chunk) { - ret = make([]Chunk, len(s)) - for i := range s { - if c, ok := s[i].(Chunk); ok { - ret[i] = c - } else { - logger.Warningf("could not convert %s into a Chunk", s[i]) - } - } - return -} - func (r *Repo) storeRecipe(version int, recipe []Chunk) { dest := filepath.Join(r.path, fmt.Sprintf(versionFmt, version), recipeName) - delta := slice.Diff(recipe2slice(r.recipe), recipe2slice(recipe)) - logger.Infof("recipe delta %s", delta.String()) - storeBasicStruct(dest, r.chunkWriteWrapper, delta) + storeDelta(r.recipe, recipe, dest, r.differ, r.chunkWriteWrapper) } func (r *Repo) loadRecipes(versions []string) { - recipe := slice2recipe(r.loadDeltas(versions, r.chunkReadWrapper, recipeName)) + var recipe []Chunk + loadDeltas(&recipe, versions, r.patcher, r.chunkReadWrapper, recipeName) for _, c := range recipe { if rc, isRepo := c.(RepoChunk); isRepo { rc.SetRepo(r) |