Skip to content

Commit 03851e1

Browse files
Second round of improvements (#54)
1 parent 3114bee commit 03851e1

File tree

4 files changed

+42
-88
lines changed

4 files changed

+42
-88
lines changed

Cargo.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ features = ["full"]
2121
default = ["localfs", "memfs"]
2222
actix-compat = [ "actix-web" ]
2323
warp-compat = [ "warp", "hyper" ]
24-
caldav = [ "icalendar", "chrono" ]
24+
caldav = [ "icalendar" ]
2525
all = [ "actix-compat", "warp-compat", "caldav" ]
26-
localfs = ["libc", "lru", "parking_lot", "reflink-copy"]
26+
localfs = ["libc", "lru", "tokio/rt-multi-thread", "parking_lot", "reflink-copy"]
2727
memfs = ["libc"]
2828

2929
[[example]]
@@ -55,8 +55,8 @@ mime_guess = "2.0.0"
5555
parking_lot = { version = "0.12.0", optional = true }
5656
percent-encoding = "2.1.0"
5757
pin-project-lite = "0.2.16"
58-
tokio = { version = "1.3.0", features = [ "rt-multi-thread", "io-util", "net", "time", "sync" ] }
59-
time = { version = "0.3.2", default-features = false, features = [ "macros", "formatting" ] }
58+
tokio = { version = "1.22.0", features = [ "rt" ] }
59+
chrono = { version = "0.4", default-features = false, features = [ "clock" ] }
6060
url = "2.2.0"
6161
uuid = { version = "1.1.2", features = ["v4"] }
6262
xml-rs = "1"
@@ -67,7 +67,6 @@ warp = { version = "0.3.0", optional = true, default-features = false }
6767
actix-web = { version = "4.0.0-beta.15", default-features = false, optional = true }
6868
reflink-copy = { version = "0.1.14", optional = true }
6969
icalendar = { version = "0.17.1", optional = true }
70-
chrono = { version = "0.4", default-features = false, features = ["now"], optional = true }
7170
derive-where = "1.6.0"
7271

7372
[dev-dependencies]

src/handle_gethead.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::cmp;
22
use std::io::Write;
33

4+
use chrono::{DateTime, Utc};
45
use futures_util::StreamExt;
56
use headers::HeaderMapExt;
67
use http::{Request, Response, status::StatusCode};
@@ -14,7 +15,6 @@ use crate::davheaders;
1415
use crate::davpath::DavPath;
1516
use crate::errors::*;
1617
use crate::fs::*;
17-
use crate::util::systemtime_to_offsetdatetime;
1818
use crate::{DavInner, DavMethod};
1919

2020
struct Range {
@@ -439,17 +439,9 @@ impl<C: Clone + Send + Sync + 'static> DavInner<C> {
439439

440440
for dirent in &dirents {
441441
let modified = match dirent.meta.modified() {
442-
Ok(t) => {
443-
let tm = systemtime_to_offsetdatetime(t);
444-
format!(
445-
"{:04}-{:02}-{:02} {:02}:{:02}",
446-
tm.year(),
447-
tm.month(),
448-
tm.day(),
449-
tm.hour(),
450-
tm.minute(),
451-
)
452-
}
442+
Ok(t) => DateTime::<Utc>::from(t)
443+
.format("%Y-%m-%d %H:%M")
444+
.to_string(),
453445
Err(_) => "".to_string(),
454446
};
455447
let size = match dirent.meta.is_file() {

src/localfs.rs

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::any::Any;
88
use std::collections::VecDeque;
99
use std::future::{self, Future};
1010
use std::io::{self, Read, Seek, SeekFrom, Write};
11+
use std::mem;
1112
#[cfg(unix)]
1213
use std::os::unix::{
1314
ffi::OsStrExt,
@@ -19,7 +20,6 @@ use std::path::{Path, PathBuf};
1920
use std::pin::Pin;
2021
use std::pin::pin;
2122
use std::sync::Arc;
22-
use std::sync::atomic::{AtomicU32, Ordering};
2323
use std::task::{Context, Poll};
2424
use std::time::{Duration, SystemTime, UNIX_EPOCH};
2525

@@ -34,51 +34,21 @@ use crate::davpath::DavPath;
3434
use crate::fs::*;
3535
use crate::localfs_macos::DUCacheBuilder;
3636

37-
const RUNTIME_TYPE_BASIC: u32 = 1;
38-
const RUNTIME_TYPE_THREADPOOL: u32 = 2;
39-
static RUNTIME_TYPE: AtomicU32 = AtomicU32::new(0);
40-
41-
#[derive(Clone, Copy)]
42-
#[repr(u32)]
43-
enum RuntimeType {
44-
Basic = RUNTIME_TYPE_BASIC,
45-
ThreadPool = RUNTIME_TYPE_THREADPOOL,
46-
}
47-
48-
impl RuntimeType {
49-
#[inline]
50-
fn get() -> RuntimeType {
51-
match RUNTIME_TYPE.load(Ordering::Relaxed) {
52-
RUNTIME_TYPE_BASIC => RuntimeType::Basic,
53-
RUNTIME_TYPE_THREADPOOL => RuntimeType::ThreadPool,
54-
_ => {
55-
let dbg = format!("{:?}", tokio::runtime::Handle::current());
56-
let rt = if dbg.contains("ThreadPool") {
57-
RuntimeType::ThreadPool
58-
} else {
59-
RuntimeType::Basic
60-
};
61-
RUNTIME_TYPE.store(rt as u32, Ordering::SeqCst);
62-
rt
63-
}
64-
}
65-
}
66-
}
67-
6837
// Run some code via block_in_place() or spawn_blocking().
6938
//
7039
// There's also a method on LocalFs for this, use the freestanding
7140
// function if you do not want the fs_access_guard() closure to be used.
41+
#[cfg(feature = "localfs")]
7242
#[inline]
7343
async fn blocking<F, R>(func: F) -> R
7444
where
7545
F: FnOnce() -> R,
7646
F: Send + 'static,
7747
R: Send + 'static,
7848
{
79-
match RuntimeType::get() {
80-
RuntimeType::Basic => task::spawn_blocking(func).await.unwrap(),
81-
RuntimeType::ThreadPool => task::block_in_place(func),
49+
match tokio::runtime::Handle::current().runtime_flavor() {
50+
tokio::runtime::RuntimeFlavor::MultiThread => task::block_in_place(func),
51+
_ => task::spawn_blocking(func).await.unwrap(),
8252
}
8353
}
8454

@@ -103,7 +73,10 @@ pub(crate) struct LocalFsInner {
10373
}
10474

10575
#[derive(Debug)]
106-
struct LocalFsFile(Option<std::fs::File>);
76+
struct LocalFsFile {
77+
file: Option<std::fs::File>,
78+
buf: BytesMut,
79+
}
10780

10881
struct LocalFsReadDir {
10982
fs: LocalFs,
@@ -340,7 +313,10 @@ impl DavFileSystem for LocalFs {
340313
.create_new(options.create_new)
341314
.open(path);
342315
match res {
343-
Ok(file) => Ok(Box::new(LocalFsFile(Some(file))) as Box<dyn DavFile>),
316+
Ok(file) => Ok(Box::new(LocalFsFile {
317+
file: Some(file),
318+
buf: BytesMut::new(),
319+
}) as Box<dyn DavFile>),
344320
Err(e) => Err(e.into()),
345321
}
346322
})
@@ -676,27 +652,27 @@ impl DavDirEntry for LocalFsDirEntry {
676652
impl DavFile for LocalFsFile {
677653
fn metadata(&'_ mut self) -> FsFuture<'_, Box<dyn DavMetaData>> {
678654
async move {
679-
let file = self.0.take().unwrap();
655+
let file = self.file.take().unwrap();
680656
let (meta, file) = blocking(move || (file.metadata(), file)).await;
681-
self.0 = Some(file);
657+
self.file = Some(file);
682658
Ok(Box::new(LocalFsMetaData(meta?)) as Box<dyn DavMetaData>)
683659
}
684660
.boxed()
685661
}
686662

687663
fn write_bytes(&'_ mut self, buf: Bytes) -> FsFuture<'_, ()> {
688664
async move {
689-
let mut file = self.0.take().unwrap();
665+
let mut file = self.file.take().unwrap();
690666
let (res, file) = blocking(move || (file.write_all(&buf), file)).await;
691-
self.0 = Some(file);
667+
self.file = Some(file);
692668
res.map_err(|e| e.into())
693669
}
694670
.boxed()
695671
}
696672

697673
fn write_buf(&'_ mut self, mut buf: Box<dyn Buf + Send>) -> FsFuture<'_, ()> {
698674
async move {
699-
let mut file = self.0.take().unwrap();
675+
let mut file = self.file.take().unwrap();
700676
let (res, file) = blocking(move || {
701677
while buf.remaining() > 0 {
702678
let n = match file.write(buf.chunk()) {
@@ -708,48 +684,50 @@ impl DavFile for LocalFsFile {
708684
(Ok(()), file)
709685
})
710686
.await;
711-
self.0 = Some(file);
687+
self.file = Some(file);
712688
res.map_err(|e| e.into())
713689
}
714690
.boxed()
715691
}
716692

717693
fn read_bytes(&'_ mut self, count: usize) -> FsFuture<'_, Bytes> {
718694
async move {
719-
let mut file = self.0.take().unwrap();
720-
let (res, file) = blocking(move || {
721-
let mut buf = BytesMut::with_capacity(count);
695+
let mut file = self.file.take().unwrap();
696+
let mut buf = mem::take(&mut self.buf);
697+
let (res, file, buf) = blocking(move || {
698+
buf.reserve(count);
722699
let res = unsafe {
723700
buf.set_len(count);
724701
file.read(&mut buf).map(|n| {
725702
buf.set_len(n);
726-
buf.freeze()
703+
buf.split().freeze()
727704
})
728705
};
729-
(res, file)
706+
(res, file, buf)
730707
})
731708
.await;
732-
self.0 = Some(file);
709+
self.file = Some(file);
710+
self.buf = buf;
733711
res.map_err(|e| e.into())
734712
}
735713
.boxed()
736714
}
737715

738716
fn seek(&'_ mut self, pos: SeekFrom) -> FsFuture<'_, u64> {
739717
async move {
740-
let mut file = self.0.take().unwrap();
718+
let mut file = self.file.take().unwrap();
741719
let (res, file) = blocking(move || (file.seek(pos), file)).await;
742-
self.0 = Some(file);
720+
self.file = Some(file);
743721
res.map_err(|e| e.into())
744722
}
745723
.boxed()
746724
}
747725

748726
fn flush(&'_ mut self) -> FsFuture<'_, ()> {
749727
async move {
750-
let mut file = self.0.take().unwrap();
728+
let mut file = self.file.take().unwrap();
751729
let (res, file) = blocking(move || (file.flush(), file)).await;
752-
self.0 = Some(file);
730+
self.file = Some(file);
753731
res.map_err(|e| e.into())
754732
}
755733
.boxed()

src/util.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::io::{Cursor, Write};
2-
use std::time::{SystemTime, UNIX_EPOCH};
2+
use std::time::SystemTime;
33

44
use bytes::Bytes;
5+
use chrono::{DateTime, SecondsFormat, Utc};
56
use headers::Header;
67
use http::method::InvalidMethod;
7-
use time::format_description::well_known::Rfc3339;
8-
use time::macros::offset;
98

109
use crate::DavResult;
1110
use crate::body::Body;
@@ -157,16 +156,6 @@ pub(crate) fn dav_xml_error(body: &str) -> Body {
157156
Body::from(xml)
158157
}
159158

160-
pub(crate) fn systemtime_to_offsetdatetime(t: SystemTime) -> time::OffsetDateTime {
161-
match t.duration_since(UNIX_EPOCH) {
162-
Ok(t) => {
163-
let tm = time::OffsetDateTime::from_unix_timestamp(t.as_secs() as i64).unwrap();
164-
tm.to_offset(offset!(UTC))
165-
}
166-
Err(_) => time::OffsetDateTime::UNIX_EPOCH.to_offset(offset!(UTC)),
167-
}
168-
}
169-
170159
pub(crate) fn systemtime_to_httpdate(t: SystemTime) -> String {
171160
let d = headers::Date::from(t);
172161
let mut v = Vec::new();
@@ -176,11 +165,7 @@ pub(crate) fn systemtime_to_httpdate(t: SystemTime) -> String {
176165

177166
pub(crate) fn systemtime_to_rfc3339_without_nanosecond(t: SystemTime) -> String {
178167
// 1996-12-19T16:39:57Z
179-
systemtime_to_offsetdatetime(t)
180-
.replace_nanosecond(0)
181-
.ok()
182-
.and_then(|x| x.format(&Rfc3339).ok())
183-
.unwrap_or("1970-01-01T00:00:00Z".into())
168+
DateTime::<Utc>::from(t).to_rfc3339_opts(SecondsFormat::Secs, true)
184169
}
185170

186171
// A buffer that implements "Write".

0 commit comments

Comments
 (0)