32 static void rs_block_sig_init(
rs_block_sig_t *sig, rs_weak_sum_t weak_sum,
33 rs_strong_sum_t *strong_sum,
int strong_len)
37 memcpy(sig->
strong_sum, strong_sum, strong_len);
40 static inline unsigned rs_block_sig_hash(
const rs_block_sig_t *sig)
53 rs_weak_sum_t weak_sum,
54 rs_strong_sum_t *strong_sum,
const void *buf,
57 rs_block_sig_init(&match->block_sig, weak_sum, strong_sum,
59 match->signature = sig;
69 #ifndef HASHTABLE_NSTATS
72 rs_signature_calc_strong_sum(match->signature, match->buf, match->len,
82 #define HASHTABLE_NMIX32
84 #define ENTRY rs_block_sig
85 #define MATCH rs_block_match
86 #define NAME hashtable
96 sizeof(rs_weak_sum_t)-
97 1) /
sizeof(rs_weak_sum_t)) *
98 sizeof(rs_weak_sum_t);
106 block_idx * rs_block_sig_size(sig));
113 return ((
char *)block_sig -
114 (
char *)sig->
block_sigs) / rs_block_sig_size(sig);
118 size_t *block_len,
size_t *strong_len)
120 size_t rec_block_len;
122 size_t min_strong_len;
124 size_t max_strong_len;
131 max_strong_len = RS_BLAKE2_SUM_LENGTH;
135 max_strong_len = RS_MD4_SUM_LENGTH;
138 rs_error(
"invalid magic %#x", *magic);
149 old_fsize <= 256 * 256 ? 256 : rs_long_sqrt(old_fsize) & ~127;
152 *block_len = rec_block_len;
167 2 + (rs_long_ln2(old_fsize + ((rs_long_t)1 << 24)) +
168 rs_long_ln2(old_fsize / *block_len + 1) + 7) / 8;
170 if (*strong_len == 0)
171 *strong_len = max_strong_len;
172 else if (*strong_len == -1)
173 *strong_len = min_strong_len;
174 else if (old_fsize >= 0 && *strong_len < min_strong_len) {
176 "strong_len=" FMT_SIZE
" smaller than recommended minimum "
177 FMT_SIZE
" for old_fsize=" FMT_LONG
" with block_len=" FMT_SIZE,
178 *strong_len, min_strong_len, old_fsize, *block_len);
179 }
else if (*strong_len > max_strong_len) {
180 rs_error(
"invalid strong_len=" FMT_SIZE
" for magic=%#x", *strong_len,
184 rs_sig_args_check(*magic, *block_len, *strong_len);
189 size_t block_len,
size_t strong_len,
205 sig->
size = (int)(sig_fsize < 12 ? 0 : (sig_fsize - 12) / (4 + strong_len));
208 rs_alloc(sig->
size * rs_block_sig_size(sig),
209 "signature->block_sigs");
213 #ifndef HASHTABLE_NSTATS
216 rs_signature_check(sig);
224 rs_bzero(sig,
sizeof(*sig));
228 rs_weak_sum_t weak_sum,
229 rs_strong_sum_t *strong_sum)
231 rs_signature_check(sig);
233 if (rs_signature_weaksum_kind(sig) == RS_ROLLSUM)
234 weak_sum =
mix32(weak_sum);
240 "signature->block_sigs");
247 rs_long_t rs_signature_find_match(
rs_signature_t *sig, rs_weak_sum_t weak_sum,
248 void const *buf,
size_t len)
253 rs_signature_check(sig);
254 rs_block_match_init(&m, sig, weak_sum, NULL, buf, len);
255 if ((b = hashtable_find(sig->
hashtable, &m))) {
256 return (rs_long_t)rs_block_sig_idx(sig, b) * sig->
block_len;
263 #ifndef HASHTABLE_NSTATS
267 "match statistics: signature[%ld searches, %ld (%.3f%%) matches, "
268 "%ld (%.3fx) weak sum compares, %ld (%.3f%%) strong sum compares, "
284 rs_signature_check(sig);
288 for (i = 0; i < sig->
count; i++) {
289 b = rs_block_sig_ptr(sig, i);
300 rs_signature_done(psums);
308 char strong_hex[RS_MAX_STRONG_SUM_LENGTH * 3];
311 "sumset info: magic=%#x, block_len=%d, block_num=%d", sums->
magic,
314 for (i = 0; i < sums->
count; i++) {
315 b = rs_block_sig_ptr(sums, i);
318 "sum %6d: weak=" FMT_WEAKSUM
", strong=%s", i, b->
weak_sum,
int size
Total number of blocks allocated.
hashtable_t * hashtable
The hashtable for finding matches.
int count
Total number of blocks.
long hashcmp_count
The count of hash compares done.
int block_len
The block length.
A signature file using the BLAKE2 hash.
Bad value passed in to library, probably an application bug.
long match_count
The count of matches found.
Bad magic number at start of stream.
LIBRSYNC_EXPORT void rs_sumset_dump(rs_signature_t const *)
Dump signatures to the log.
rs_weak_sum_t weak_sum
Block's weak checksum.
int strong_sum_len
The block strong sum length.
A signature file with MD4 signatures.
long entrycmp_count
The count of entry compares done.
static unsigned mix32(unsigned h)
MurmurHash3 finalization mix function.
void * block_sigs
The packed block_sigs for all blocks.
Public header for librsync.
Signature of a whole file.
LIBRSYNC_EXPORT void rs_free_sumset(rs_signature_t *)
Deep deallocation of checksums.
Don't show function name in message.
LIBRSYNC_EXPORT rs_result rs_build_hash_table(rs_signature_t *sums)
Call this after loading a signature to index it.
rs_result
Return codes from nonblocking rsync operations.
A signature file with RabinKarp rollsum and MD4 hash.
int magic
The signature magic value.
#define RS_DEFAULT_BLOCK_LEN
Default block length, if not determined by any other factors.
long calc_strong_count
The count of strongsum calcs done.
Signature of a single block.
rs_magic_number
A uint32 magic number, emitted in bigendian/network order at the start of librsync files...
#define RS_DEFAULT_MIN_STRONG_LEN
Default minimum strong sum length, if the filesize is unknown.
long find_count
The count of finds tried.
LIBRSYNC_EXPORT void rs_signature_log_stats(rs_signature_t const *sig)
Log the rs_signature_delta match stats.
LIBRSYNC_EXPORT rs_result rs_sig_args(rs_long_t old_fsize, rs_magic_number *magic, size_t *block_len, size_t *strong_len)
Get or check signature arguments for a given file size.
A generic open addressing hashtable.
rs_strong_sum_t strong_sum
Block's strong checksum.
A signature file with RabinKarp rollsum and BLAKE2 hash.
LIBRSYNC_EXPORT void rs_hexify(char *to_buf, void const *from_buf, int from_len)
Convert from_len bytes at from_buf into a hex representation in to_buf, which must be twice as long p...