patch: faster preload with BufReader
1. seek avoided with self maintained offset 2. BufReader to read faster Signed-off-by: ClSlaid <cailue@bupt.edu.cn>
This commit is contained in:
parent
7a802726fb
commit
4cd8d8a4a5
@ -47,7 +47,7 @@ use super::LDAP_EPOCH_DELTA;
|
||||
const READ_RETRY: i32 = 3;
|
||||
|
||||
/// block size for fuse, align to our asynchronic request size over FileContentsRequest.
|
||||
const BLOCK_SIZE: u32 = 4 * 1024 * 1024;
|
||||
pub const BLOCK_SIZE: u32 = 4 * 1024 * 1024;
|
||||
|
||||
/// read only permission
|
||||
const PERM_READ: u16 = 0o444;
|
||||
|
@ -1,9 +1,10 @@
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fs::File,
|
||||
io::{Read, Seek},
|
||||
io::{BufReader, Read, Seek},
|
||||
os::unix::prelude::PermissionsExt,
|
||||
path::PathBuf,
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
@ -13,7 +14,10 @@ use hbb_common::{
|
||||
};
|
||||
use utf16string::WString;
|
||||
|
||||
use crate::{platform::LDAP_EPOCH_DELTA, CliprdrError};
|
||||
use crate::{
|
||||
platform::{fuse::BLOCK_SIZE, LDAP_EPOCH_DELTA},
|
||||
CliprdrError,
|
||||
};
|
||||
|
||||
/// has valid file attributes
|
||||
const FLAGS_FD_ATTRIBUTES: u32 = 0x04;
|
||||
@ -30,7 +34,9 @@ const FLAGS_FD_UNIX_MODE: u32 = 0x08;
|
||||
#[derive(Debug)]
|
||||
pub(super) struct LocalFile {
|
||||
pub path: PathBuf,
|
||||
pub handle: Option<File>,
|
||||
|
||||
pub handle: Option<BufReader<File>>,
|
||||
pub offset: AtomicU64,
|
||||
|
||||
pub name: String,
|
||||
pub size: u64,
|
||||
@ -69,11 +75,13 @@ impl LocalFile {
|
||||
|
||||
// NOTE: open files lazily
|
||||
let handle = None;
|
||||
let offset = AtomicU64::new(0);
|
||||
|
||||
Ok(Self {
|
||||
name,
|
||||
path: path.clone(),
|
||||
handle,
|
||||
offset,
|
||||
size,
|
||||
last_write_time,
|
||||
is_dir,
|
||||
@ -160,33 +168,47 @@ impl LocalFile {
|
||||
buf.to_vec()
|
||||
}
|
||||
|
||||
pub fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> Result<(), CliprdrError> {
|
||||
if self.handle.is_none() {
|
||||
#[inline]
|
||||
pub fn load_handle(&mut self) -> Result<(), CliprdrError> {
|
||||
if !self.is_dir && 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 reader = BufReader::with_capacity(BLOCK_SIZE as usize, handle);
|
||||
self.handle = Some(reader);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> Result<(), CliprdrError> {
|
||||
self.load_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,
|
||||
})?;
|
||||
if offset != self.offset.load(Ordering::Relaxed) {
|
||||
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 {
|
||||
let new_offset = offset + (buf.len() as u64);
|
||||
self.offset.store(new_offset, Ordering::Relaxed);
|
||||
|
||||
// gc file handle
|
||||
if new_offset >= self.size {
|
||||
self.offset.store(0, Ordering::Relaxed);
|
||||
self.handle = None;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ impl ClipboardContext {
|
||||
) -> Result<(), CliprdrError> {
|
||||
let mut file_list = self.local_files.lock();
|
||||
|
||||
let file_contents_resp = match request {
|
||||
let (file_idx, file_contents_resp) = match request {
|
||||
FileContentsRequest::Size {
|
||||
stream_id,
|
||||
file_idx,
|
||||
@ -220,11 +220,14 @@ impl ClipboardContext {
|
||||
);
|
||||
|
||||
let size = file.size;
|
||||
ClipboardFile::FileContentsResponse {
|
||||
msg_flags: 0x1,
|
||||
stream_id,
|
||||
requested_data: size.to_le_bytes().to_vec(),
|
||||
}
|
||||
(
|
||||
file_idx,
|
||||
ClipboardFile::FileContentsResponse {
|
||||
msg_flags: 0x1,
|
||||
stream_id,
|
||||
requested_data: size.to_le_bytes().to_vec(),
|
||||
},
|
||||
)
|
||||
}
|
||||
FileContentsRequest::Range {
|
||||
stream_id,
|
||||
@ -280,16 +283,26 @@ impl ClipboardContext {
|
||||
|
||||
file.read_exact_at(&mut buf, offset)?;
|
||||
|
||||
ClipboardFile::FileContentsResponse {
|
||||
msg_flags: 0x1,
|
||||
stream_id,
|
||||
requested_data: buf,
|
||||
}
|
||||
(
|
||||
file_idx,
|
||||
ClipboardFile::FileContentsResponse {
|
||||
msg_flags: 0x1,
|
||||
stream_id,
|
||||
requested_data: buf,
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
send_data(conn_id, file_contents_resp);
|
||||
log::debug!("file contents sent to conn: {}", conn_id);
|
||||
// hot reload next file
|
||||
for next_file in file_list.iter_mut().skip(file_idx + 1) {
|
||||
if !next_file.is_dir {
|
||||
next_file.load_handle()?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user