Fastresume: check at least one piece from each file
This commit is contained in:
parent
225e9a9491
commit
816838cdf0
1 changed files with 44 additions and 11 deletions
|
|
@ -100,27 +100,60 @@ impl TorrentStateInitializing {
|
||||||
|
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
|
|
||||||
let mut have_pieces = hp
|
let mut to_validate = BF::from_boxed_slice(
|
||||||
.as_slice()
|
vec![0u8; self.shared.lengths.piece_bitfield_bytes()].into_boxed_slice(),
|
||||||
.iter_ones()
|
);
|
||||||
.filter_map(|i| self.shared.lengths.validate_piece_index(i.try_into().ok()?))
|
let mut queue = hp.as_slice().to_owned();
|
||||||
.collect_vec();
|
|
||||||
have_pieces.shuffle(&mut rand::thread_rng());
|
|
||||||
|
|
||||||
// Validate a certain threshold of fastresume pieces with decreasing probability of actual disk reads.
|
// Validate at least one piece from each file, if we claim we have it.
|
||||||
for (tmp_id, hpiece) in have_pieces.iter().enumerate() {
|
for fi in self.shared.file_infos.iter() {
|
||||||
|
let prange = fi.piece_range_usize();
|
||||||
|
let offset = prange.start;
|
||||||
|
for piece_id in hp
|
||||||
|
.as_slice()
|
||||||
|
.get(fi.piece_range_usize())
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|s| s.iter_ones())
|
||||||
|
.map(|pid| pid + offset)
|
||||||
|
.take(1)
|
||||||
|
{
|
||||||
|
to_validate.set(piece_id, true);
|
||||||
|
queue.set(piece_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all the remaining pieces we claim we have, validate them with decreasing probability.
|
||||||
|
let mut queue = queue.iter_ones().collect_vec();
|
||||||
|
queue.shuffle(&mut rand::thread_rng());
|
||||||
|
for (tmp_id, piece_id) in queue.into_iter().enumerate() {
|
||||||
let denom: u32 = (tmp_id + 1).min(50).try_into().unwrap();
|
let denom: u32 = (tmp_id + 1).min(50).try_into().unwrap();
|
||||||
if rand::thread_rng().gen_ratio(1, denom) && fo.check_piece(*hpiece).is_err() {
|
if rand::thread_rng().gen_ratio(1, denom) {
|
||||||
|
to_validate.set(piece_id, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let to_validate_count = to_validate.count_ones();
|
||||||
|
for (id, piece_id) in to_validate
|
||||||
|
.iter_ones()
|
||||||
|
.filter_map(|id| {
|
||||||
|
self.shared
|
||||||
|
.lengths
|
||||||
|
.validate_piece_index(id.try_into().ok()?)
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if fo.check_piece(piece_id).is_err() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
let progress = (self.shared.lengths.total_length() as f64
|
let progress = (self.shared.lengths.total_length() as f64
|
||||||
/ have_pieces.len() as f64
|
/ to_validate_count as f64
|
||||||
* (tmp_id + 1) as f64) as u64;
|
* (id + 1) as f64) as u64;
|
||||||
let progress = progress.min(self.shared.lengths.total_length());
|
let progress = progress.min(self.shared.lengths.total_length());
|
||||||
self.checked_bytes.store(progress, Ordering::Relaxed);
|
self.checked_bytes.store(progress, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue