aboutsummaryrefslogtreecommitdiff
path: root/repo/repo.go
diff options
context:
space:
mode:
Diffstat (limited to 'repo/repo.go')
-rw-r--r--repo/repo.go124
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)