From 36f8c622607e5f40c0930bb82c592c28c6496f36 Mon Sep 17 00:00:00 2001 From: Gaius Date: Tue, 12 Mar 2024 20:16:01 +0800 Subject: [PATCH] feat: add empty task handler for hard_link_or_copy (#310) Signed-off-by: Gaius --- dragonfly-client-storage/src/content.rs | 24 +++++++++++++++---- dragonfly-client-storage/src/lib.rs | 6 ++--- dragonfly-client-storage/src/metadata.rs | 11 +++++++++ .../src/grpc/dfdaemon_download.rs | 2 +- dragonfly-client/src/task/mod.rs | 6 ++--- 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/dragonfly-client-storage/src/content.rs b/dragonfly-client-storage/src/content.rs index 07fe2754..ed2b14e0 100644 --- a/dragonfly-client-storage/src/content.rs +++ b/dragonfly-client-storage/src/content.rs @@ -56,25 +56,41 @@ impl Content { // hard_link_or_copy_task hard links or copies the task content to the destination. pub async fn hard_link_or_copy_task( &self, - task_id: &str, + task: super::metadata::Task, to: &Path, range: Option, ) -> Result<()> { // Copy the task content to the destination by range // if the range is specified. if let Some(range) = range { - self.copy_task_by_range(task_id, to, range).await?; + // If the range length is 0, no need to copy. Need to open the file to + // ensure the file exists. + if range.length == 0 { + info!("range length is 0, no need to copy"); + File::create(to).await?; + return Ok(()); + } + + self.copy_task_by_range(task.id.as_str(), to, range).await?; info!("copy range of task success"); return Ok(()); } // If the hard link fails, // copy the task content to the destination. - if let Err(err) = self.hard_link_task(task_id, to).await { + if let Err(err) = self.hard_link_task(task.id.as_str(), to).await { info!("hard link task failed: {}", err); + // If the task is empty, no need to copy. Need to open the file to + // ensure the file exists. + if task.is_empty() { + info!("task is empty, no need to copy"); + File::create(to).await?; + return Ok(()); + } + fs::remove_file(to).await?; - self.copy_task(task_id, to).await?; + self.copy_task(task.id.as_str(), to).await?; info!("copy task success"); return Ok(()); } diff --git a/dragonfly-client-storage/src/lib.rs b/dragonfly-client-storage/src/lib.rs index ae50fe01..b21cb8c6 100644 --- a/dragonfly-client-storage/src/lib.rs +++ b/dragonfly-client-storage/src/lib.rs @@ -58,13 +58,11 @@ impl Storage { // hard_link_or_copy_task hard links or copies the task content to the destination. pub async fn hard_link_or_copy_task( &self, - task_id: &str, + task: metadata::Task, to: &Path, range: Option, ) -> Result<()> { - self.content - .hard_link_or_copy_task(task_id, to, range) - .await + self.content.hard_link_or_copy_task(task, to, range).await } // read_task_by_range returns the reader of the task by range. diff --git a/dragonfly-client-storage/src/metadata.rs b/dragonfly-client-storage/src/metadata.rs index dc40e89e..0b4a6335 100644 --- a/dragonfly-client-storage/src/metadata.rs +++ b/dragonfly-client-storage/src/metadata.rs @@ -100,6 +100,17 @@ impl Task { self.finished_at.is_some() } + // is_empty returns whether the task is empty. + pub fn is_empty(&self) -> bool { + if let Some(content_length) = self.content_length() { + if content_length == 0 { + return true; + } + } + + false + } + // content_length returns the content length of the task. pub fn content_length(&self) -> Option { match self.response_header.get(header::CONTENT_LENGTH.as_str()) { diff --git a/dragonfly-client/src/grpc/dfdaemon_download.rs b/dragonfly-client/src/grpc/dfdaemon_download.rs index 147f0f29..5f9b07eb 100644 --- a/dragonfly-client/src/grpc/dfdaemon_download.rs +++ b/dragonfly-client/src/grpc/dfdaemon_download.rs @@ -274,7 +274,7 @@ impl DfdaemonDownload for DfdaemonDownloadServerHandler { // Hard link or copy the task content to the destination. if let Err(err) = task_manager .hard_link_or_copy( - task_id.as_str(), + task, Path::new(output_path.as_str()), download.range.clone(), ) diff --git a/dragonfly-client/src/task/mod.rs b/dragonfly-client/src/task/mod.rs index 119a5d4e..da4d6e93 100644 --- a/dragonfly-client/src/task/mod.rs +++ b/dragonfly-client/src/task/mod.rs @@ -165,13 +165,11 @@ impl Task { // hard_link_or_copy hard links or copies the task content to the destination. pub async fn hard_link_or_copy( &self, - task_id: &str, + task: metadata::Task, to: &Path, range: Option, ) -> ClientResult<()> { - self.storage - .hard_link_or_copy_task(task_id, to, range) - .await + self.storage.hard_link_or_copy_task(task, to, range).await } // download downloads a task.