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::{
|
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,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,16 +67,8 @@ impl LocalFile {
|
|||||||
.trim_start_matches('/')
|
.trim_start_matches('/')
|
||||||
.replace('/', "\\");
|
.replace('/', "\\");
|
||||||
|
|
||||||
let handle = if is_dir {
|
// NOTE: open files lazily
|
||||||
None
|
let handle = None;
|
||||||
} else {
|
|
||||||
let file = std::fs::File::open(path).map_err(|e| CliprdrError::FileError {
|
|
||||||
path: path.clone(),
|
|
||||||
err: e,
|
|
||||||
})?;
|
|
||||||
let reader = file;
|
|
||||||
Some(reader)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
name,
|
name,
|
||||||
@ -163,6 +159,36 @@ impl LocalFile {
|
|||||||
|
|
||||||
buf.to_vec()
|
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> {
|
pub(super) fn construct_file_list(paths: &[PathBuf]) -> Result<Vec<LocalFile>, CliprdrError> {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use std::{
|
use std::{
|
||||||
os::unix::prelude::FileExt,
|
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{mpsc::Sender, Arc},
|
sync::{mpsc::Sender, Arc},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
@ -189,7 +188,7 @@ impl ClipboardContext {
|
|||||||
conn_id: i32,
|
conn_id: i32,
|
||||||
request: FileContentsRequest,
|
request: FileContentsRequest,
|
||||||
) -> Result<(), CliprdrError> {
|
) -> Result<(), CliprdrError> {
|
||||||
let file_list = self.local_files.lock();
|
let mut file_list = self.local_files.lock();
|
||||||
|
|
||||||
let file_contents_resp = match request {
|
let file_contents_resp = match request {
|
||||||
FileContentsRequest::Size {
|
FileContentsRequest::Size {
|
||||||
@ -239,7 +238,7 @@ impl ClipboardContext {
|
|||||||
length,
|
length,
|
||||||
conn_id
|
conn_id
|
||||||
);
|
);
|
||||||
let Some(file) = file_list.get(file_idx) else {
|
let Some(file) = file_list.get_mut(file_idx) else {
|
||||||
log::error!(
|
log::error!(
|
||||||
"invalid file index {} requested from conn: {}",
|
"invalid file index {} requested from conn: {}",
|
||||||
file_idx,
|
file_idx,
|
||||||
@ -260,22 +259,6 @@ impl ClipboardContext {
|
|||||||
file.name
|
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 {
|
if offset > file.size {
|
||||||
log::error!("invalid reading offset requested from conn: {}", conn_id);
|
log::error!("invalid reading offset requested from conn: {}", conn_id);
|
||||||
resp_file_contents_fail(conn_id, stream_id);
|
resp_file_contents_fail(conn_id, stream_id);
|
||||||
@ -295,12 +278,7 @@ impl ClipboardContext {
|
|||||||
|
|
||||||
let mut buf = vec![0u8; read_size as usize];
|
let mut buf = vec![0u8; read_size as usize];
|
||||||
|
|
||||||
handle
|
file.read_exact_at(&mut buf, offset)?;
|
||||||
.read_exact_at(&mut buf, offset)
|
|
||||||
.map_err(|e| CliprdrError::FileError {
|
|
||||||
path: file.path.clone(),
|
|
||||||
err: e,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
ClipboardFile::FileContentsResponse {
|
ClipboardFile::FileContentsResponse {
|
||||||
msg_flags: 0x1,
|
msg_flags: 0x1,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user