Skip to content

Commit b609cde

Browse files
author
Chojan Shang
authored
feat: try to support epoll (#478)
* feat: try to support iouring * chore: make cargo docs work * feat: all in epoll * chore: apply review * chore: fix tokio macros * chore: fix features
1 parent fd3ef54 commit b609cde

File tree

6 files changed

+110
-22
lines changed

6 files changed

+110
-22
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ required-features = ["services-hdfs"]
3838

3939
[dependencies]
4040
anyhow = "1.0.56"
41-
async-compat = "0.2.1"
4241
# Temp workaround, should come back to tagged version after https://github.com/Nemo157/async-compression/issues/150 resolved.
4342
async-compression = { package = "async-compression-issue-150-workaround", version = "0.3.15-issue-150", features = [
4443
"futures-io",
@@ -65,6 +64,7 @@ log = "0.4.16"
6564
md5 = "0.7.0"
6665
metrics = "0.20.0"
6766
minitrace = "0.4.0"
67+
nuclei = "0.2.1"
6868
once_cell = "1.10.0"
6969
parking_lot = "0.12.0"
7070
percent-encoding = "2.1.0"
@@ -75,7 +75,6 @@ reqsign = "0.3.0"
7575
serde = { version = "1.0.136", features = ["derive"] }
7676
thiserror = "1.0.30"
7777
time = "0.3.9"
78-
tokio = { version = "1.20.1", features = ["fs", "macros"] }
7978

8079
[dev-dependencies]
8180
anyhow = "1.0.56"

oay/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

oay/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ env_logger = "0.9.0"
1818
futures = "0.3.21"
1919
log = "0.4.17"
2020
opendal = "0.11.3"
21-
tokio = { version = "1.20.1", features = ["rt-multi-thread"] }
21+
tokio = { version = "1.20.1", features = ["rt-multi-thread", "macros"] }
2222

2323
# Please comment the following patch while releasing.
2424
[patch.crates-io]

src/services/fs/backend.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use std::path::PathBuf;
2020
use std::sync::Arc;
2121

2222
use anyhow::anyhow;
23-
use async_compat::Compat;
2423
use async_trait::async_trait;
2524
use futures::AsyncReadExt;
2625
use futures::AsyncSeekExt;
@@ -31,10 +30,10 @@ use log::warn;
3130
use metrics::increment_counter;
3231
use minitrace::trace;
3332
use time::OffsetDateTime;
34-
use tokio::fs;
3533

3634
use super::dir_stream::DirStream;
3735
use super::error::parse_io_error;
36+
use super::nfs;
3837
use crate::accessor::AccessorMetadata;
3938
use crate::error::other;
4039
use crate::error::BackendError;
@@ -98,9 +97,9 @@ impl Builder {
9897
};
9998

10099
// If root dir is not exist, we must create it.
101-
if let Err(e) = fs::metadata(&root).await {
100+
if let Err(e) = nfs::metadata(&root).await {
102101
if e.kind() == std::io::ErrorKind::NotFound {
103-
fs::create_dir_all(&root)
102+
nfs::create_dir_all(&root)
104103
.await
105104
.map_err(|e| parse_io_error(e, "build", &root))?;
106105
}
@@ -187,7 +186,7 @@ impl Accessor for Backend {
187186
})?
188187
.to_path_buf();
189188

190-
fs::create_dir_all(&parent).await.map_err(|e| {
189+
nfs::create_dir_all(&parent).await.map_err(|e| {
191190
let e = parse_io_error(e, "create", &parent.to_string_lossy());
192191
error!(
193192
"object {} create_dir_all for parent {:?}: {:?}",
@@ -196,11 +195,10 @@ impl Accessor for Backend {
196195
e
197196
})?;
198197

199-
fs::OpenOptions::new()
198+
std::fs::OpenOptions::new()
200199
.create(true)
201200
.write(true)
202201
.open(&path)
203-
.await
204202
.map_err(|e| {
205203
let e = parse_io_error(e, "create", &path);
206204
error!("object {} create: {:?}", &path, e);
@@ -211,7 +209,7 @@ impl Accessor for Backend {
211209
}
212210

213211
if args.mode() == ObjectMode::DIR {
214-
fs::create_dir_all(&path).await.map_err(|e| {
212+
nfs::create_dir_all(&path).await.map_err(|e| {
215213
let e = parse_io_error(e, "create", &path);
216214
error!("object {} create: {:?}", &path, e);
217215
e
@@ -235,17 +233,16 @@ impl Accessor for Backend {
235233
args.size()
236234
);
237235

238-
let f = fs::OpenOptions::new()
236+
let f = std::fs::OpenOptions::new()
239237
.read(true)
240238
.open(&path)
241-
.await
242239
.map_err(|e| {
243240
let e = parse_io_error(e, "read", &path);
244241
error!("object {} open: {:?}", &path, e);
245242
e
246243
})?;
247244

248-
let mut f = Compat::new(f);
245+
let mut f = nuclei::Handle::new(f)?;
249246

250247
if let Some(offset) = args.offset() {
251248
f.seek(SeekFrom::Start(offset)).await.map_err(|e| {
@@ -293,7 +290,7 @@ impl Accessor for Backend {
293290
})?
294291
.to_path_buf();
295292

296-
fs::create_dir_all(&parent).await.map_err(|e| {
293+
nfs::create_dir_all(&parent).await.map_err(|e| {
297294
let e = parse_io_error(e, "write", &parent.to_string_lossy());
298295
error!(
299296
"object {} create_dir_all for parent {}: {:?}",
@@ -304,19 +301,18 @@ impl Accessor for Backend {
304301
e
305302
})?;
306303

307-
let f = fs::OpenOptions::new()
304+
let f = std::fs::OpenOptions::new()
308305
.create(true)
309306
.write(true)
310307
.open(&path)
311-
.await
312308
.map_err(|e| {
313309
let e = parse_io_error(e, "write", &path);
314310
error!("object {} open: {:?}", &path, e);
315311
e
316312
})?;
317313

318314
debug!("object {} write finished: size {:?}", &path, args.size());
319-
Ok(Box::new(Compat::new(f)))
315+
Ok(Box::new(nuclei::Handle::new(f)?))
320316
}
321317

322318
#[trace("stat")]
@@ -326,7 +322,7 @@ impl Accessor for Backend {
326322
let path = self.get_abs_path(args.path());
327323
debug!("object {} stat start", &path);
328324

329-
let meta = fs::metadata(&path).await.map_err(|e| {
325+
let meta = nfs::metadata(&path).await.map_err(|e| {
330326
let e = parse_io_error(e, "stat", &path);
331327
warn!("object {} stat: {:?}", &path, e);
332328
e
@@ -359,7 +355,7 @@ impl Accessor for Backend {
359355
debug!("object {} delete start", &path);
360356

361357
// PathBuf.is_dir() is not free, call metadata directly instead.
362-
let meta = fs::metadata(&path).await;
358+
let meta = nfs::metadata(&path).await;
363359

364360
if let Err(err) = meta {
365361
return if err.kind() == ErrorKind::NotFound {
@@ -375,9 +371,9 @@ impl Accessor for Backend {
375371
let meta = meta.ok().unwrap();
376372

377373
let f = if meta.is_dir() {
378-
fs::remove_dir(&path).await
374+
nfs::remove_dir(&path).await
379375
} else {
380-
fs::remove_file(&path).await
376+
nfs::remove_file(&path).await
381377
};
382378

383379
f.map_err(|e| parse_io_error(e, "delete", &path))?;

src/services/fs/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,4 @@ pub use backend::Builder;
9292

9393
mod dir_stream;
9494
mod error;
95+
mod nfs;

src/services/fs/nfs.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright 2022 Datafuse Labs.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//! Async filesystem primitives.
16+
//! We use [`nuclei`] to support io-uring.
17+
//!
18+
//! [`nuclei`]: https://docs.rs/nuclei
19+
20+
#![warn(missing_docs)]
21+
use std::io;
22+
use std::path::Path;
23+
24+
use nuclei::spawn_blocking;
25+
26+
#[doc(no_inline)]
27+
pub use std::fs::{FileType, Metadata, Permissions};
28+
29+
/// Creates a directory and its parent directories if they are missing.
30+
///
31+
/// # Errors
32+
///
33+
/// An error will be returned in the following situations:
34+
///
35+
/// * `path` already points to an existing file or directory.
36+
/// * The current process lacks permissions to create the directory or its missing parents.
37+
/// * Some other I/O error occurred.
38+
pub async fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
39+
let path = path.as_ref().to_owned();
40+
spawn_blocking(move || std::fs::create_dir_all(&path)).await
41+
}
42+
43+
/// Reads metadata for a path.
44+
///
45+
/// This function will traverse symbolic links to read metadata for the target file or directory.
46+
/// If you want to read metadata without following symbolic links, use [`symlink_metadata()`]
47+
/// instead.
48+
///
49+
/// # Errors
50+
///
51+
/// An error will be returned in the following situations:
52+
///
53+
/// * `path` does not point to an existing file or directory.
54+
/// * The current process lacks permissions to read metadata for the path.
55+
/// * Some other I/O error occurred.
56+
pub async fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
57+
let path = path.as_ref().to_owned();
58+
spawn_blocking(move || std::fs::metadata(path)).await
59+
}
60+
61+
/// Removes an empty directory.
62+
///
63+
/// Note that this function can only delete an empty directory. If you want to delete a directory
64+
/// and all of its contents, use [`remove_dir_all()`] instead.
65+
///
66+
/// # Errors
67+
///
68+
/// An error will be returned in the following situations:
69+
///
70+
/// * `path` is not an existing and empty directory.
71+
/// * The current process lacks permissions to remove the directory.
72+
/// * Some other I/O error occurred.
73+
pub async fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
74+
let path = path.as_ref().to_owned();
75+
spawn_blocking(move || std::fs::remove_dir(&path)).await
76+
}
77+
78+
/// Removes a file.
79+
///
80+
/// # Errors
81+
///
82+
/// An error will be returned in the following situations:
83+
///
84+
/// * `path` does not point to an existing file.
85+
/// * The current process lacks permissions to remove the file.
86+
/// * Some other I/O error occurred.
87+
pub async fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
88+
let path = path.as_ref().to_owned();
89+
spawn_blocking(move || std::fs::remove_file(&path)).await
90+
}

0 commit comments

Comments
 (0)