Возьмите сценарий, который я хочу создать по пути, работая с файлом (photoshop / word / powerpoint et c (например, двоичные данные)), поэтому каждый раз, когда я создаю v0.x, я создаю резервную копию это тоже. Однако я хочу использовать для этого rdiff, так что мне нужно только хранить фрагменты, которые отличаются между исходной версией и текущей версией.
Я , используя код, найденный здесь и мой код (который запускается) выглядит следующим образом
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"github.com/jbreiding/rsync-go"
)
var originalFile string
var newFile string
var patchFile string
var signatureFile string
var appliedFile string
func openFile(path string) ([]byte, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
fmt.Println("File reading error", err)
}
return data, err
}
func writeFile(path string, data []byte) error {
err := ioutil.WriteFile(path, data, 0644)
return err
}
func main() {
originalFile = "./profile-shot.jpg"
newFile = "./profile-shot-to.jpg"
patchFile = "./profile-shot.patch"
signatureFile = "./profile-shot.sig"
appliedFile = "./profile-shot-applied.jpg"
//create a signature based on the original file
originalFileReader, _ := os.Open(originalFile)
defer originalFileReader.Close()
rs := &rsync.RSync{}
//take a signature of the new
//apply it to the original
//get a delta
//apply the delta to the original
//get the new??
// 1. prepare a signature
sig := make([]rsync.BlockHash, 0, 10)
writeSignature := func(bl rsync.BlockHash) error {
sig = append(sig, bl)
return nil
}
//2. take the new file
newFileReader, _ := os.Open(newFile)
//3. create the signature
rs.CreateSignature(originalFileReader, writeSignature)
sigBytes, err := json.Marshal(sig)
if err != nil {
fmt.Println("error ", err)
} else {
writeFile(signatureFile, sigBytes)
}
opsOut := make(chan rsync.Operation)
dataWriter := bufio.NewWriter(&dataBuffer)
//4. specify a write operation for the delta
writeOperation := func(op rsync.Operation) error {
opsOut <- op
data, err := json.Marshal(op.Data)
if err != nil {
fmt.Println("error ", err)
}
if _, err := dataWriter.Write(data); err != nil {
fmt.Println("error writing data ", err)
}
return nil
}
var dataBuffer bytes.Buffer
go func() {
defer close(opsOut)
//5. in a routine, create a delta from the new image and the signature of the original
err := rs.CreateDelta(newFileReader, sig, writeOperation)
fmt.Println("err creating delta ", err)
writeFile(patchFile, dataBuffer.Bytes())
fmt.Println("length of signature ", len(sig))
//now we have written the patch to file, we can open the applied file and write the data from the patch to it, by passing the struct(s) to a new opsOut channel, and calling apply delta using that channel
}()
// saving the applied delta resulting file
newFileWriter, err := os.OpenFile(appliedFile, os.O_RDWR|os.O_CREATE, 0600)
if err != nil {
fmt.Println("error source writer ", err)
}
originalFileReader.Seek(0, os.SEEK_SET)
//6. apply the delta
rs.ApplyDelta(newFileWriter, originalFileReader, opsOut)
}
Выше, в основном, то, что я думаю от rdiff.
- Чтение в исходном файле (v0.1)
- Создайте подпись из этого файла (v0.1 sig)
- Создайте дельту, основанную на новом файле (v0.x) и подписи
- Примените дельту к v0.1, и вы получите v0.x
Проблема в том, что в действительности у меня, скорее всего, будет резервная копия v0.1 и всех подписей каждой следующей версии, и не имеют резервные копии каждой полной версии (что бессмысленно).
Однако для создания дельты требуется новая версия, а не исходная версия. Таким образом, в действительности я не могу go задом наперед, потому что я не могу создавать дельты, когда они мне нужны, без более новой версии и новой версии, которую я пытаюсь получить с помощью rsyn c.
Я понимаю, что решение состоит в том, чтобы сохранить дельту, однако пока (с использованием изображений) дельта равна размеру самих файлов (для тестирования я использую изображения размером от 20 до 100 МБ). Следовательно, использование этого метода также не стоит.
Примечание. Я также использовал bsdiff в Go, и это делает свое дело (примерно в 0,5 раза больше размера реальных файлов), однако это очень медленно из-за алгоритма сортировки, который генерирует индекс. Этот индекс необходим для создания различий. Это примерно в 10 раз больше оригинальных файлов, поэтому хранить их тоже нельзя.
Буду очень признателен за любые идеи относительно лучшего подхода.