lib/scanner: Simplify, optimize and document Validate (#6674) (#6688)

This commit is contained in:
greatroar 2020-05-27 22:23:12 +02:00 committed by GitHub
parent f78133b8e9
commit 9c0825c0d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 13 deletions

View File

@ -108,26 +108,19 @@ func Blocks(ctx context.Context, r io.Reader, blocksize int, sizehint int64, cou
return blocks, nil
}
// Validate quickly validates buf against the cryptohash hash (if len(hash)>0)
// and the 32-bit hash weakHash (if not zero). It is satisfied if either hash
// matches, or neither is given.
func Validate(buf, hash []byte, weakHash uint32) bool {
rd := bytes.NewReader(buf)
if weakHash != 0 {
whf := adler32.New()
if _, err := io.Copy(whf, rd); err == nil && whf.Sum32() == weakHash {
return true
}
// Copy error or mismatch, go to next algo.
rd.Seek(0, io.SeekStart)
return adler32.Checksum(buf) == weakHash
}
if len(hash) > 0 {
hf := sha256.New()
if _, err := io.Copy(hf, rd); err == nil {
// Sum allocates, so let's hope we don't hit this often.
return bytes.Equal(hf.Sum(nil), hash)
}
hbuf := sha256.Sum256(buf)
return bytes.Equal(hbuf[:], hash)
}
// Both algos failed or no hashes were specified. Assume it's all good.
return true
}

View File

@ -12,11 +12,13 @@ import (
"crypto/rand"
"fmt"
origAdler32 "hash/adler32"
mrand "math/rand"
"testing"
"testing/quick"
rollingAdler32 "github.com/chmduquesne/rollinghash/adler32"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/sha256"
)
var blocksTestData = []struct {
@ -165,3 +167,43 @@ func TestAdler32Variants(t *testing.T) {
hf3.Roll(data[i])
}
}
func BenchmarkValidate(b *testing.B) {
type block struct {
data []byte
hash [sha256.Size]byte
weakhash uint32
}
var blocks []block
const blocksPerType = 100
r := mrand.New(mrand.NewSource(0x136bea689e851))
// Valid blocks.
for i := 0; i < blocksPerType; i++ {
var b block
b.data = make([]byte, 128<<10)
r.Read(b.data[:])
b.hash = sha256.Sum256(b.data[:])
b.weakhash = origAdler32.Checksum(b.data[:])
blocks = append(blocks, b)
}
// Blocks where the hash matches, but the weakhash doesn't.
for i := 0; i < blocksPerType; i++ {
var b block
b.data = make([]byte, 128<<10)
r.Read(b.data[:])
b.hash = sha256.Sum256(b.data[:])
b.weakhash = 1 // Zeros causes Validate to skip the weakhash.
blocks = append(blocks, b)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, b := range blocks {
Validate(b.data[:], b.hash[:], b.weakhash)
}
}
}