From 7a802726fb1cf1ec8487a4af1868b7d065163f08 Mon Sep 17 00:00:00 2001 From: ClSlaid Date: Sat, 28 Oct 2023 20:52:08 +0800 Subject: [PATCH] fix: implement lazy reading to prevent avoid fd limit drawback: through put reduced to 50% Signed-off-by: ClSlaid --- .../src/platform/linux/local_file.rs | 48 ++++++++++++++----- libs/clipboard/src/platform/linux/mod.rs | 28 ++--------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/libs/clipboard/src/platform/linux/local_file.rs b/libs/clipboard/src/platform/linux/local_file.rs index f49274b7a99a..c585758dfbec 100644 --- a/libs/clipboard/src/platform/linux/local_file.rs +++ b/libs/clipboard/src/platform/linux/local_file.rs @@ -1,5 +1,9 @@ use std::{ - collections::HashSet, fs::File, os::unix::prelude::PermissionsExt, path::PathBuf, + collections::HashSet, + fs::File, + io::{Read, Seek}, + os::unix::prelude::PermissionsExt, + path::PathBuf, time::SystemTime, }; @@ -63,16 +67,8 @@ impl LocalFile { .trim_start_matches('/') .replace('/', "\\"); - let handle = if is_dir { - None - } else { - let file = std::fs::File::open(path).map_err(|e| CliprdrError::FileError { - path: path.clone(), - err: e, - })?; - let reader = file; - Some(reader) - }; + // NOTE: open files lazily + let handle = None; Ok(Self { name, @@ -163,6 +159,36 @@ impl LocalFile { buf.to_vec() } + + pub fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> Result<(), CliprdrError> { + if self.handle.is_none() { + let handle = std::fs::File::open(&self.path).map_err(|e| CliprdrError::FileError { + path: self.path.clone(), + err: e, + })?; + self.handle = Some(handle); + }; + + let handle = self.handle.as_mut().unwrap(); + + handle + .seek(std::io::SeekFrom::Start(offset)) + .map_err(|e| CliprdrError::FileError { + path: self.path.clone(), + err: e, + })?; + handle + .read_exact(buf) + .map_err(|e| CliprdrError::FileError { + path: self.path.clone(), + err: e, + })?; + // gc + if offset + (buf.len() as u64) >= self.size { + self.handle = None; + } + Ok(()) + } } pub(super) fn construct_file_list(paths: &[PathBuf]) -> Result, CliprdrError> { diff --git a/libs/clipboard/src/platform/linux/mod.rs b/libs/clipboard/src/platform/linux/mod.rs index 14ae0a164924..f1f429946e53 100644 --- a/libs/clipboard/src/platform/linux/mod.rs +++ b/libs/clipboard/src/platform/linux/mod.rs @@ -1,5 +1,4 @@ use std::{ - os::unix::prelude::FileExt, path::PathBuf, sync::{mpsc::Sender, Arc}, time::Duration, @@ -189,7 +188,7 @@ impl ClipboardContext { conn_id: i32, request: FileContentsRequest, ) -> Result<(), CliprdrError> { - let file_list = self.local_files.lock(); + let mut file_list = self.local_files.lock(); let file_contents_resp = match request { FileContentsRequest::Size { @@ -239,7 +238,7 @@ impl ClipboardContext { length, conn_id ); - let Some(file) = file_list.get(file_idx) else { + let Some(file) = file_list.get_mut(file_idx) else { log::error!( "invalid file index {} requested from conn: {}", file_idx, @@ -260,22 +259,6 @@ impl ClipboardContext { file.name ); - let Some(handle) = &file.handle else { - log::error!( - "invalid file index {} requested from conn: {}", - file_idx, - conn_id - ); - resp_file_contents_fail(conn_id, stream_id); - - return Err(CliprdrError::InvalidRequest { - description: format!( - "request to read directory on index {} as file from conn: {}", - file_idx, conn_id - ), - }); - }; - if offset > file.size { log::error!("invalid reading offset requested from conn: {}", conn_id); resp_file_contents_fail(conn_id, stream_id); @@ -295,12 +278,7 @@ impl ClipboardContext { let mut buf = vec![0u8; read_size as usize]; - handle - .read_exact_at(&mut buf, offset) - .map_err(|e| CliprdrError::FileError { - path: file.path.clone(), - err: e, - })?; + file.read_exact_at(&mut buf, offset)?; ClipboardFile::FileContentsResponse { msg_flags: 0x1,