opendal_service_monoiofs/
backend.rs1use std::fmt::Debug;
19use std::io;
20use std::path::PathBuf;
21use std::sync::Arc;
22
23use monoio::fs::OpenOptions;
24use opendal_core::raw::*;
25use opendal_core::*;
26
27use super::config::MonoiofsConfig;
28use super::core::BUFFER_SIZE;
29use super::core::MonoiofsCore;
30use super::deleter::MonoiofsDeleter;
31use super::reader::*;
32
33#[doc = include_str!("docs.md")]
35#[derive(Debug, Default)]
36pub struct MonoiofsBuilder {
37 pub(super) config: MonoiofsConfig,
38}
39
40impl MonoiofsBuilder {
41 pub fn root(mut self, root: &str) -> Self {
45 self.config.root = if root.is_empty() {
46 None
47 } else {
48 Some(root.to_string())
49 };
50 self
51 }
52}
53
54impl Builder for MonoiofsBuilder {
55 type Config = MonoiofsConfig;
56
57 fn build(self) -> Result<impl Service> {
58 let root = self.config.root.map(PathBuf::from).ok_or(
59 Error::new(ErrorKind::ConfigInvalid, "root is not specified")
60 .with_operation("Builder::build"),
61 )?;
62 if let Err(e) = std::fs::metadata(&root)
63 && e.kind() == io::ErrorKind::NotFound
64 {
65 std::fs::create_dir_all(&root).map_err(|e| {
66 Error::new(ErrorKind::Unexpected, "create root dir failed")
67 .with_operation("Builder::build")
68 .with_context("root", root.to_string_lossy())
69 .set_source(e)
70 })?;
71 }
72 let root = root.canonicalize().map_err(|e| {
73 Error::new(
74 ErrorKind::Unexpected,
75 "canonicalize of root directory failed",
76 )
77 .with_operation("Builder::build")
78 .with_context("root", root.to_string_lossy())
79 .set_source(e)
80 })?;
81 let worker_threads = 1; let io_uring_entries = 1024;
83 Ok(MonoiofsBackend {
84 core: Arc::new(MonoiofsCore::new(root, worker_threads, io_uring_entries)),
85 })
86 }
87}
88
89#[derive(Debug, Clone)]
90pub struct MonoiofsBackend {
91 pub(crate) core: Arc<MonoiofsCore>,
92}
93
94impl Service for MonoiofsBackend {
95 type Reader = oio::PositionReader<MonoiofsPositionReader>;
96 type Writer = MonoiofsLazyWriter;
97 type Lister = ();
98 type Deleter = oio::OneShotDeleter<MonoiofsDeleter>;
99 type Copier = oio::OneShotCopier;
100
101 fn info(&self) -> ServiceInfo {
102 self.core.info.clone()
103 }
104
105 fn capability(&self) -> Capability {
106 self.core.capability
107 }
108
109 async fn stat(&self, _ctx: &OperationContext, path: &str, _args: OpStat) -> Result<RpStat> {
110 let path = self.core.prepare_path(path)?;
111 let meta = self
112 .core
113 .dispatch(move || monoio::fs::metadata(path))
114 .await
115 .map_err(new_std_io_error)?;
116 let mode = if meta.is_dir() {
117 EntryMode::DIR
118 } else if meta.is_file() {
119 EntryMode::FILE
120 } else {
121 EntryMode::Unknown
122 };
123 let m = Metadata::new(mode)
124 .with_content_length(meta.len())
125 .with_last_modified(Timestamp::try_from(
126 meta.modified().map_err(new_std_io_error)?,
127 )?);
128 Ok(RpStat::new(m))
129 }
130 fn read(&self, _ctx: &OperationContext, path: &str, _args: OpRead) -> Result<Self::Reader> {
131 let path = self.core.prepare_path(path)?;
132 Ok(oio::PositionReader::new(MonoiofsPositionReader::new(
133 self.core.clone(),
134 path,
135 )))
136 }
137
138 fn write(&self, _ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
139 Ok(MonoiofsLazyWriter::new(self.core.clone(), path, args))
140 }
141
142 fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
143 let output: oio::OneShotDeleter<MonoiofsDeleter> = {
144 Ok(oio::OneShotDeleter::new(MonoiofsDeleter::new(
145 self.core.clone(),
146 )))
147 }?;
148
149 Ok(output)
150 }
151
152 fn list(&self, _ctx: &OperationContext, _path: &str, _args: OpList) -> Result<Self::Lister> {
153 Err(Error::new(
154 ErrorKind::Unsupported,
155 "operation is not supported",
156 ))
157 }
158
159 async fn rename(
160 &self,
161 _ctx: &OperationContext,
162 from: &str,
163 to: &str,
164 _args: OpRename,
165 ) -> Result<RpRename> {
166 let from = self.core.prepare_path(from)?;
167 self.core
169 .dispatch({
170 let from = from.clone();
171 move || monoio::fs::metadata(from)
172 })
173 .await
174 .map_err(new_std_io_error)?;
175 let to = self.core.prepare_write_path(to).await?;
176 self.core
177 .dispatch(move || monoio::fs::rename(from, to))
178 .await
179 .map_err(new_std_io_error)?;
180 Ok(RpRename::default())
181 }
182
183 async fn create_dir(
184 &self,
185 _ctx: &OperationContext,
186 path: &str,
187 _args: OpCreateDir,
188 ) -> Result<RpCreateDir> {
189 let path = self.core.prepare_path(path)?;
190 self.core
191 .dispatch(move || monoio::fs::create_dir_all(path))
192 .await
193 .map_err(new_std_io_error)?;
194 Ok(RpCreateDir::default())
195 }
196
197 fn copy(
198 &self,
199 _ctx: &OperationContext,
200 from: &str,
201 to: &str,
202 _args: OpCopy,
203 _opts: OpCopier,
204 ) -> Result<Self::Copier> {
205 let core = self.core.clone();
206 let from = self.core.prepare_path(from)?;
207 let to = to.to_string();
208
209 let copier = oio::OneShotCopier::new(async move {
210 core.dispatch({
212 let from = from.clone();
213 move || monoio::fs::metadata(from)
214 })
215 .await
216 .map_err(new_std_io_error)?;
217 let to = core.prepare_write_path(&to).await?;
218 core.dispatch({
219 let core = core.clone();
220 move || async move {
221 let from = OpenOptions::new().read(true).open(from).await?;
222 let to = OpenOptions::new()
223 .write(true)
224 .create(true)
225 .truncate(true)
226 .open(to)
227 .await?;
228
229 let mut pos = 0;
234 let mut buf = core.buf_pool.get();
236 buf.reserve(BUFFER_SIZE);
238 let _ = buf.split_off(BUFFER_SIZE);
239
240 loop {
241 let result;
242 (result, buf) = from.read_at(buf, pos).await;
243 if result? == 0 {
244 break;
246 }
247 let result;
248 (result, buf) = to.write_all_at(buf, pos).await;
249 result?;
250 pos += buf.len() as u64;
251 buf.clear();
252 }
253 core.buf_pool.put(buf);
254 Ok(())
255 }
256 })
257 .await
258 .map_err(new_std_io_error)?;
259 Ok(Metadata::default())
260 });
261
262 Ok(copier)
263 }
264
265 async fn presign(
266 &self,
267 _ctx: &OperationContext,
268 _path: &str,
269 _args: OpPresign,
270 ) -> Result<RpPresign> {
271 Err(Error::new(
272 ErrorKind::Unsupported,
273 "operation is not supported",
274 ))
275 }
276}