fix: implement lazy reading to prevent avoid fd limit
drawback: through put reduced to 50% Signed-off-by: ClSlaid <cailue@bupt.edu.cn>
This commit is contained in:
parent
251245d315
commit
7a802726fb
@ -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<Vec<LocalFile>, CliprdrError> {
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user