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
+4 -5
View File
@@ -179,8 +179,7 @@ pub struct GameFileDescription {
pub game_id: String, pub game_id: String,
pub relative_path: String, pub relative_path: String,
pub is_dir: bool, pub is_dir: bool,
#[serde(default)] pub size: u64,
pub size: Option<u64>,
} }
impl GameFileDescription { impl GameFileDescription {
@@ -190,8 +189,8 @@ impl GameFileDescription {
} }
#[must_use] #[must_use]
pub fn file_size(&self) -> Option<u64> { pub fn file_size(&self) -> u64 {
if self.is_dir { None } else { self.size } if self.is_dir { 0 } else { self.size }
} }
} }
@@ -204,7 +203,7 @@ impl fmt::Debug for GameFileDescription {
self.game_id, self.game_id,
if self.is_dir { 'D' } else { 'F' }, if self.is_dir { 'D' } else { 'F' },
self.relative_path, self.relative_path,
self.size.unwrap_or_default(), self.size,
) )
} }
} }
+9 -31
View File
@@ -391,7 +391,7 @@ impl PeerGameDB {
.and_then(|p| p.files.get(game_id)) .and_then(|p| p.files.get(game_id))
&& let Some(file_desc) = files && let Some(file_desc) = files
.iter() .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()); return Some(file_desc.clone());
} }
@@ -427,9 +427,8 @@ fn collect_file_sizes(
for (peer_addr, files) in game_files { for (peer_addr, files) in game_files {
let mut peer_file_sizes = HashMap::new(); let mut peer_file_sizes = HashMap::new();
for file in files { for file in files {
if !file.is_dir if !file.is_dir {
&& let Some(size) = file.size let size = file.size;
{
file_size_map file_size_map
.entry(file.relative_path.clone()) .entry(file.relative_path.clone())
.or_default() .or_default()
@@ -587,8 +586,8 @@ async fn prepare_game_storage(
.open(&validated_path) .open(&validated_path)
.await?; .await?;
// Pre-allocate the file if we have size information // Pre-allocate the file with the expected size
if let Some(size) = desc.size { let size = desc.size;
if let Err(e) = file.set_len(size).await { if let Err(e) = file.set_len(size).await {
log::warn!( log::warn!(
"Failed to pre-allocate file {} (size: {}): {}", "Failed to pre-allocate file {} (size: {}): {}",
@@ -606,7 +605,6 @@ async fn prepare_game_storage(
} }
} }
} }
}
Ok(()) Ok(())
} }
@@ -622,7 +620,7 @@ fn build_peer_plans(
let mut peer_index = 0usize; let mut peer_index = 0usize;
for desc in file_descs.iter().filter(|d| !d.is_dir) { for desc in file_descs.iter().filter(|d| !d.is_dir) {
if let Some(size) = desc.file_size() { let size = desc.file_size();
if size == 0 { if size == 0 {
let peer = peers[peer_index % peers.len()]; let peer = peers[peer_index % peers.len()];
peer_index += 1; peer_index += 1;
@@ -650,15 +648,6 @@ fn build_peer_plans(
}); });
offset += length; offset += length;
} }
} else {
let peer = peers[peer_index % peers.len()];
peer_index += 1;
plans
.entry(peer)
.or_default()
.whole_files
.push(desc.clone());
}
} }
plans plans
@@ -673,16 +662,6 @@ async fn download_chunk(
let stream = conn.open_bidirectional_stream().await?; let stream = conn.open_bidirectional_stream().await?;
let (mut rx, mut tx) = stream.split(); 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 { let request = Request::GetGameFileChunk {
game_id: game_id.to_string(), game_id: game_id.to_string(),
relative_path: chunk.relative_path.clone(), relative_path: chunk.relative_path.clone(),
@@ -690,7 +669,6 @@ async fn download_chunk(
length: chunk.length, length: chunk.length,
}; };
tx.write_all(&request.encode()).await?; tx.write_all(&request.encode()).await?;
}
tx.close().await?; tx.close().await?;
@@ -1905,13 +1883,13 @@ async fn get_game_file_descriptions(
let is_dir = entry.file_type().is_dir(); let is_dir = entry.file_type().is_dir();
let size = if is_dir { let size = if is_dir {
None 0
} else { } else {
match tokio::fs::metadata(entry.path()).await { match tokio::fs::metadata(entry.path()).await {
Ok(metadata) => Some(metadata.len()), Ok(metadata) => metadata.len(),
Err(e) => { Err(e) => {
log::error!("Failed to read metadata for {relative_path}: {e}"); log::error!("Failed to read metadata for {relative_path}: {e}");
None eyre::bail!("Failed to read metadata for {relative_path}: {e}");
} }
} }
}; };
+10 -3
View File
@@ -80,16 +80,23 @@ impl RequestHandler {
Some(relative_path) => { Some(relative_path) => {
let is_dir = entry.file_type().is_dir(); let is_dir = entry.file_type().is_dir();
let size = if is_dir { let size = if is_dir {
None 0
} else { } else {
match entry.metadata() { match entry.metadata() {
Ok(metadata) => Some(metadata.len()), Ok(metadata) => metadata.len(),
Err(e) => { Err(e) => {
tracing::error!( tracing::error!(
"Failed to read metadata for {}: {e}", "Failed to read metadata for {}: {e}",
relative_path relative_path
); );
None // Return early since we can't proceed without file size
return Response::InvalidRequest(
format!("Failed to read metadata for {relative_path}")
.as_bytes()
.to_vec()
.into(),
"File size unavailable".to_string(),
);
} }
} }
}; };