Write the composite under a .part name until it is whole
The merge writes its outbox record before the DNG, which takes minutes, and a drain that ran in the meantime took whatever lay at the record's name: a sync pass that fired mid-merge uploaded the first part of the composite and cleared the record. The file is now written as x.dng.part and renamed into place once the last strip is in; the drain skips a record whose payload does not exist yet.
This commit is contained in:
+22
-1
@@ -617,8 +617,17 @@ fn run_inner(
|
||||
(path, true)
|
||||
}
|
||||
};
|
||||
// Written under a name of its own and renamed into place once the last
|
||||
// strip is in. The record above names `out_path`, and a drain that runs
|
||||
// while the merge is still writing — a sync pass fires one whenever the
|
||||
// sweep finishes — takes whatever is at that name: it uploaded the first
|
||||
// few hundred megabytes of a composite, cleared the record, and the file
|
||||
// on the server stayed truncated for good. `pending` skips a record whose
|
||||
// payload does not exist yet, so the rename is what releases it.
|
||||
let part_path = part_name(&out_path);
|
||||
let cleanup = |path: &Path| {
|
||||
let _ = std::fs::remove_file(path);
|
||||
let _ = std::fs::remove_file(part_name(path));
|
||||
if staged {
|
||||
let _ = std::fs::remove_file(crate::export::destination_record(path));
|
||||
}
|
||||
@@ -798,7 +807,7 @@ fn run_inner(
|
||||
let inscribed_for_writer = inscribed.clone();
|
||||
let fill_for_writer = fill_cam.is_some();
|
||||
let file =
|
||||
std::fs::File::create(&out_path).map_err(|e| format!("{}: {e}", out_path.display()))?;
|
||||
std::fs::File::create(&part_path).map_err(|e| format!("{}: {e}", part_path.display()))?;
|
||||
let writer = executors::spawn(Executor::Io, "dng-write", move || -> Result<(), String> {
|
||||
let mut file = std::io::BufWriter::new(file);
|
||||
dr_export::write_linear_dng(
|
||||
@@ -910,6 +919,10 @@ fn run_inner(
|
||||
cleanup(&out_path);
|
||||
return Err(e);
|
||||
}
|
||||
if let Err(e) = std::fs::rename(&part_path, &out_path) {
|
||||
cleanup(&out_path);
|
||||
return Err(format!("{}: {e}", out_path.display()));
|
||||
}
|
||||
log::info!(
|
||||
"merge: {}×{} written to {} in {:?}",
|
||||
out_w,
|
||||
@@ -1471,6 +1484,14 @@ fn stem(p: &Path) -> String {
|
||||
.unwrap_or_else(|| p.display().to_string())
|
||||
}
|
||||
|
||||
/// Where the composite is written until it is whole: `x.dng.part` for
|
||||
/// `x.dng`.
|
||||
fn part_name(path: &Path) -> PathBuf {
|
||||
let mut name = path.as_os_str().to_owned();
|
||||
name.push(".part");
|
||||
PathBuf::from(name)
|
||||
}
|
||||
|
||||
/// `name` in `dir`, numbered if that name is taken: a merge never
|
||||
/// overwrites (FR-MRG-3).
|
||||
fn unused_name(dir: &Path, name: &str) -> PathBuf {
|
||||
|
||||
Reference in New Issue
Block a user