always a size

This commit is contained in:
2025-11-12 22:11:29 +01:00
parent 8b9e09ab81
commit bca85fbdc1
3 changed files with 68 additions and 84 deletions
+54 -76
View File
@@ -391,7 +391,7 @@ impl PeerGameDB {
.and_then(|p| p.files.get(game_id))
&& let Some(file_desc) = files
.iter()
.find(|f| f.relative_path == relative_path && f.size == Some(size))
.find(|f| f.relative_path == relative_path && f.size == size)
{
return Some(file_desc.clone());
}
@@ -427,9 +427,8 @@ fn collect_file_sizes(
for (peer_addr, files) in game_files {
let mut peer_file_sizes = HashMap::new();
for file in files {
if !file.is_dir
&& let Some(size) = file.size
{
if !file.is_dir {
let size = file.size;
file_size_map
.entry(file.relative_path.clone())
.or_default()
@@ -587,23 +586,22 @@ async fn prepare_game_storage(
.open(&validated_path)
.await?;
// Pre-allocate the file if we have size information
if let Some(size) = desc.size {
if let Err(e) = file.set_len(size).await {
log::warn!(
"Failed to pre-allocate file {} (size: {}): {}",
desc.relative_path,
size,
e
);
// Continue without pre-allocation - the file will grow as chunks are written
} else {
log::debug!(
"Pre-allocated file {} with {} bytes",
desc.relative_path,
size
);
}
// Pre-allocate the file with the expected size
let size = desc.size;
if let Err(e) = file.set_len(size).await {
log::warn!(
"Failed to pre-allocate file {} (size: {}): {}",
desc.relative_path,
size,
e
);
// Continue without pre-allocation - the file will grow as chunks are written
} else {
log::debug!(
"Pre-allocated file {} with {} bytes",
desc.relative_path,
size
);
}
}
}
@@ -622,42 +620,33 @@ fn build_peer_plans(
let mut peer_index = 0usize;
for desc in file_descs.iter().filter(|d| !d.is_dir) {
if let Some(size) = desc.file_size() {
if size == 0 {
let peer = peers[peer_index % peers.len()];
peer_index += 1;
plans.entry(peer).or_default().chunks.push(DownloadChunk {
relative_path: desc.relative_path.clone(),
offset: 0,
length: 0,
retry_count: 0,
last_peer: Some(peer),
});
continue;
}
let mut offset = 0u64;
while offset < size {
let length = std::cmp::min(CHUNK_SIZE, size - offset);
let peer = peers[peer_index % peers.len()];
peer_index += 1;
plans.entry(peer).or_default().chunks.push(DownloadChunk {
relative_path: desc.relative_path.clone(),
offset,
length,
retry_count: 0,
last_peer: Some(peer),
});
offset += length;
}
} else {
let size = desc.file_size();
if size == 0 {
let peer = peers[peer_index % peers.len()];
peer_index += 1;
plans
.entry(peer)
.or_default()
.whole_files
.push(desc.clone());
plans.entry(peer).or_default().chunks.push(DownloadChunk {
relative_path: desc.relative_path.clone(),
offset: 0,
length: 0,
retry_count: 0,
last_peer: Some(peer),
});
continue;
}
let mut offset = 0u64;
while offset < size {
let length = std::cmp::min(CHUNK_SIZE, size - offset);
let peer = peers[peer_index % peers.len()];
peer_index += 1;
plans.entry(peer).or_default().chunks.push(DownloadChunk {
relative_path: desc.relative_path.clone(),
offset,
length,
retry_count: 0,
last_peer: Some(peer),
});
offset += length;
}
}
@@ -673,24 +662,13 @@ async fn download_chunk(
let stream = conn.open_bidirectional_stream().await?;
let (mut rx, mut tx) = stream.split();
if chunk.length == 0 {
// fall back to whole file download when size is unknown
let request = Request::GetGameFileData(GameFileDescription {
game_id: game_id.to_string(),
relative_path: chunk.relative_path.clone(),
is_dir: false,
size: None,
});
tx.write_all(&request.encode()).await?;
} else {
let request = Request::GetGameFileChunk {
game_id: game_id.to_string(),
relative_path: chunk.relative_path.clone(),
offset: chunk.offset,
length: chunk.length,
};
tx.write_all(&request.encode()).await?;
}
let request = Request::GetGameFileChunk {
game_id: game_id.to_string(),
relative_path: chunk.relative_path.clone(),
offset: chunk.offset,
length: chunk.length,
};
tx.write_all(&request.encode()).await?;
tx.close().await?;
@@ -1905,13 +1883,13 @@ async fn get_game_file_descriptions(
let is_dir = entry.file_type().is_dir();
let size = if is_dir {
None
0
} else {
match tokio::fs::metadata(entry.path()).await {
Ok(metadata) => Some(metadata.len()),
Ok(metadata) => metadata.len(),
Err(e) => {
log::error!("Failed to read metadata for {relative_path}: {e}");
None
eyre::bail!("Failed to read metadata for {relative_path}: {e}");
}
}
};