Skip to content

Commit b6e2f92

Browse files
committed
feat: avoid holding individual file handler for each chunk
1 parent 607bcaf commit b6e2f92

1 file changed

Lines changed: 20 additions & 31 deletions

File tree

src/stream_file.rs

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ where
267267
chunk_infos.sort_by_key(|info| info.index);
268268
let src_hashes = crate::extract_hashes(&root_map);
269269

270+
let mut has_initialized_file = false;
271+
270272
for batch_start in (0..chunk_infos.len()).step_by(*STREAM_DECRYPT_BATCH_SIZE) {
271273
let batch_end = (batch_start + *STREAM_DECRYPT_BATCH_SIZE).min(chunk_infos.len());
272274
let batch_infos = &chunk_infos[batch_start..batch_end];
@@ -288,41 +290,28 @@ where
288290
.collect::<Vec<_>>();
289291

290292
// Process and write this batch immediately to disk
291-
for (i, (info, chunk)) in batch_infos.iter().zip(batch_chunks.iter()).enumerate() {
293+
let mut batch_file = if !has_initialized_file {
294+
has_initialized_file = true;
295+
OpenOptions::new()
296+
.write(true)
297+
.create(true)
298+
.truncate(true)
299+
.open(output_filepath)?
300+
} else {
301+
OpenOptions::new()
302+
.append(true)
303+
.create(true)
304+
.open(output_filepath)?
305+
};
306+
307+
for (info, chunk) in batch_infos.iter().zip(batch_chunks.iter()) {
292308
let decrypted_chunk = decrypt_chunk(info.index, &chunk.content, &src_hashes)?;
293309

294-
// For the first chunk in the entire process, create/overwrite the file
295-
// For subsequent chunks, append to the file
296-
if batch_start == 0 && i == 0 {
297-
// First chunk: create/overwrite the file
298-
let mut file = OpenOptions::new()
299-
.write(true)
300-
.create(true)
301-
.truncate(true) // Ensure we start with a clean file
302-
.open(output_filepath)?;
303-
file.write_all(&decrypted_chunk)?;
304-
file.sync_all()?;
305-
} else {
306-
// Subsequent chunks: append to the file
307-
append_to_file(output_filepath, &decrypted_chunk)?;
308-
}
310+
batch_file.write_all(&decrypted_chunk)?;
309311
}
310-
}
311312

312-
Ok(())
313-
}
314-
315-
/// Appends content to an existing file.
316-
/// This function is memory-efficient as it doesn't keep the file handle open.
317-
/// Note: This should only be used for chunks after the first one, as it appends to existing content.
318-
fn append_to_file(file_path: &Path, content: &Bytes) -> std::io::Result<()> {
319-
let mut file = OpenOptions::new()
320-
.append(true)
321-
.create(true)
322-
.open(file_path)?;
323-
324-
file.write_all(content)?;
325-
file.sync_all()?; // Ensure data is written to disk
313+
batch_file.sync_all()?;
314+
}
326315

327316
Ok(())
328317
}

0 commit comments

Comments
 (0)