mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-27 02:31:45 +02:00
Work on adding overall checksum support
This commit is contained in:
@@ -14,6 +14,8 @@ import (
|
|||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/zeebo/xxh3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// If no BlockSize is specified in the rsync instance, this value is used.
|
// If no BlockSize is specified in the rsync instance, this value is used.
|
||||||
@@ -32,6 +34,36 @@ const (
|
|||||||
OpBlockRange
|
OpBlockRange
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type xxh3_128 struct {
|
||||||
|
xxh3.Hasher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *xxh3_128) Sum(b []byte) []byte {
|
||||||
|
s := self.Sum128()
|
||||||
|
pos := len(b)
|
||||||
|
if len(b)+16 < cap(b) {
|
||||||
|
var x [16]byte
|
||||||
|
b = append(b, x[:]...)
|
||||||
|
} else {
|
||||||
|
b = b[:len(b)+16]
|
||||||
|
}
|
||||||
|
binary.BigEndian.PutUint64(b[pos:], s.Hi)
|
||||||
|
binary.BigEndian.PutUint64(b[pos+8:], s.Lo)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func new_xxh3_64() hash.Hash64 {
|
||||||
|
ans := xxh3.New()
|
||||||
|
ans.Reset()
|
||||||
|
return ans
|
||||||
|
}
|
||||||
|
|
||||||
|
func new_xxh3_128() hash.Hash {
|
||||||
|
ans := new(xxh3_128)
|
||||||
|
ans.Reset()
|
||||||
|
return ans
|
||||||
|
}
|
||||||
|
|
||||||
// Instruction to mutate target to align to source.
|
// Instruction to mutate target to align to source.
|
||||||
type Operation struct {
|
type Operation struct {
|
||||||
Type OpType
|
Type OpType
|
||||||
@@ -163,9 +195,11 @@ type rsync struct {
|
|||||||
BlockSize int
|
BlockSize int
|
||||||
|
|
||||||
// This must be non-nil before using any functions
|
// This must be non-nil before using any functions
|
||||||
hasher hash.Hash64
|
hasher hash.Hash64
|
||||||
hasher_constructor func() hash.Hash64
|
hasher_constructor func() hash.Hash64
|
||||||
buffer []byte
|
checksummer_constructor func() hash.Hash
|
||||||
|
checksummer hash.Hash
|
||||||
|
buffer []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rsync) SetHasher(c func() hash.Hash64) {
|
func (r *rsync) SetHasher(c func() hash.Hash64) {
|
||||||
@@ -173,6 +207,11 @@ func (r *rsync) SetHasher(c func() hash.Hash64) {
|
|||||||
r.hasher = c()
|
r.hasher = c()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *rsync) SetChecksummer(c func() hash.Hash) {
|
||||||
|
r.checksummer_constructor = c
|
||||||
|
r.checksummer = c()
|
||||||
|
}
|
||||||
|
|
||||||
// If the target length is known the number of hashes in the
|
// If the target length is known the number of hashes in the
|
||||||
// signature can be determined.
|
// signature can be determined.
|
||||||
func (r *rsync) BlockHashCount(targetLength int64) (count int64) {
|
func (r *rsync) BlockHashCount(targetLength int64) (count int64) {
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
|
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
// First create a patcher with:
|
||||||
|
// p = NewPatcher()
|
||||||
|
// Create a signature for the file you want to update using
|
||||||
|
// p.CreateSignatureIterator(file_to_update)
|
||||||
|
// Now create a Differ with the created signature
|
||||||
|
// d = NewDiffer()
|
||||||
|
// d.AddSignatureData(signature_data_from_previous_step)
|
||||||
|
// Now create a delta based on the signature and the reference file
|
||||||
|
// d.CreateDelta(reference_file)
|
||||||
|
// Finally, apply this delta using the patcher to produce a file identical to reference_file
|
||||||
|
// based ont he delta data and file_to_update
|
||||||
|
// p.StartDelta(output_file, file_to_update)
|
||||||
|
// p.UpdateDelta(...)
|
||||||
|
// p.FinishDelta()
|
||||||
package rsync
|
package rsync
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/zeebo/xxh3"
|
|
||||||
|
|
||||||
"kitty/tools/utils"
|
"kitty/tools/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,10 +30,14 @@ const MaxBlockSize int = 1024 * 1024 // sqrt of 1TB
|
|||||||
|
|
||||||
type StrongHashType uint16
|
type StrongHashType uint16
|
||||||
type WeakHashType uint16
|
type WeakHashType uint16
|
||||||
|
type ChecksumType uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XXH3 StrongHashType = iota
|
XXH3 StrongHashType = iota
|
||||||
)
|
)
|
||||||
|
const (
|
||||||
|
XXH3128Sum ChecksumType = iota
|
||||||
|
)
|
||||||
const (
|
const (
|
||||||
Rsync WeakHashType = iota
|
Rsync WeakHashType = iota
|
||||||
)
|
)
|
||||||
@@ -33,6 +48,7 @@ type Api struct {
|
|||||||
rsync rsync
|
rsync rsync
|
||||||
signature []BlockHash
|
signature []BlockHash
|
||||||
|
|
||||||
|
Checksum_type ChecksumType
|
||||||
Strong_hash_type StrongHashType
|
Strong_hash_type StrongHashType
|
||||||
Weak_hash_type WeakHashType
|
Weak_hash_type WeakHashType
|
||||||
Grow_buffer_func GrowBufferFunction
|
Grow_buffer_func GrowBufferFunction
|
||||||
@@ -57,13 +73,20 @@ func (self *Api) read_signature_header(data []byte) (consumed int, err error) {
|
|||||||
if len(data) < 12 {
|
if len(data) < 12 {
|
||||||
return -1, io.ErrShortBuffer
|
return -1, io.ErrShortBuffer
|
||||||
}
|
}
|
||||||
if version := bin.Uint32(data); version != 0 {
|
if version := bin.Uint16(data); version != 0 {
|
||||||
return consumed, fmt.Errorf("Invalid version in signature header: %d", version)
|
return consumed, fmt.Errorf("Invalid version in signature header: %d", version)
|
||||||
}
|
}
|
||||||
|
switch csum := ChecksumType(bin.Uint16(data[2:])); csum {
|
||||||
|
case XXH3128Sum:
|
||||||
|
self.Checksum_type = XXH3128Sum
|
||||||
|
self.rsync.SetChecksummer(new_xxh3_128)
|
||||||
|
default:
|
||||||
|
return consumed, fmt.Errorf("Invalid checksum_type in signature header: %d", csum)
|
||||||
|
}
|
||||||
switch strong_hash := StrongHashType(bin.Uint16(data[4:])); strong_hash {
|
switch strong_hash := StrongHashType(bin.Uint16(data[4:])); strong_hash {
|
||||||
case XXH3:
|
case XXH3:
|
||||||
self.Strong_hash_type = strong_hash
|
self.Strong_hash_type = strong_hash
|
||||||
self.rsync.SetHasher(func() hash.Hash64 { return xxh3.New() })
|
self.rsync.SetHasher(new_xxh3_64)
|
||||||
default:
|
default:
|
||||||
return consumed, fmt.Errorf("Invalid strong_hash in signature header: %d", strong_hash)
|
return consumed, fmt.Errorf("Invalid strong_hash in signature header: %d", strong_hash)
|
||||||
}
|
}
|
||||||
@@ -206,7 +229,8 @@ func (self *Patcher) CreateSignatureIterator(src io.Reader) OutputIterator {
|
|||||||
var b []byte
|
var b []byte
|
||||||
it = self.rsync.CreateSignatureIterator(src)
|
it = self.rsync.CreateSignatureIterator(src)
|
||||||
output, b = ensure_size(output, 12, gbf)
|
output, b = ensure_size(output, 12, gbf)
|
||||||
bin.PutUint32(b, 0)
|
bin.PutUint16(b, 0)
|
||||||
|
bin.PutUint16(b[2:], uint16(self.Checksum_type))
|
||||||
bin.PutUint16(b[4:], uint16(self.Strong_hash_type))
|
bin.PutUint16(b[4:], uint16(self.Strong_hash_type))
|
||||||
bin.PutUint16(b[6:], uint16(self.Weak_hash_type))
|
bin.PutUint16(b[6:], uint16(self.Weak_hash_type))
|
||||||
bin.PutUint32(b[8:], uint32(self.rsync.BlockSize))
|
bin.PutUint32(b[8:], uint32(self.rsync.BlockSize))
|
||||||
@@ -288,7 +312,8 @@ func NewPatcher(expected_input_size int64) (ans *Patcher) {
|
|||||||
}
|
}
|
||||||
ans = &Patcher{}
|
ans = &Patcher{}
|
||||||
ans.rsync.BlockSize = utils.Min(bs, MaxBlockSize)
|
ans.rsync.BlockSize = utils.Min(bs, MaxBlockSize)
|
||||||
ans.rsync.SetHasher(func() hash.Hash64 { return xxh3.New() })
|
ans.rsync.SetHasher(new_xxh3_64)
|
||||||
|
ans.rsync.SetChecksummer(new_xxh3_128)
|
||||||
|
|
||||||
if ans.rsync.HashBlockSize() > 0 && ans.rsync.HashBlockSize() < ans.rsync.BlockSize {
|
if ans.rsync.HashBlockSize() > 0 && ans.rsync.HashBlockSize() < ans.rsync.BlockSize {
|
||||||
ans.rsync.BlockSize = (ans.rsync.BlockSize / ans.rsync.HashBlockSize()) * ans.rsync.HashBlockSize()
|
ans.rsync.BlockSize = (ans.rsync.BlockSize / ans.rsync.HashBlockSize()) * ans.rsync.HashBlockSize()
|
||||||
|
|||||||
Reference in New Issue
Block a user