opendal_service_dashmap/
backend.rs1use std::sync::Arc;
19
20use dashmap::DashMap;
21use log::debug;
22use opendal_core::raw::*;
23use opendal_core::*;
24
25use super::DASHMAP_SCHEME;
26use super::config::DashmapConfig;
27use super::core::DashmapCore;
28use super::deleter::DashmapDeleter;
29use super::lister::DashmapLister;
30use super::reader::*;
31use super::writer::DashmapWriter;
32
33#[doc = include_str!("docs.md")]
35#[derive(Debug, Default)]
36pub struct DashmapBuilder {
37 pub(super) config: DashmapConfig,
38}
39
40impl DashmapBuilder {
41 pub fn root(mut self, path: &str) -> Self {
43 self.config.root = if path.is_empty() {
44 None
45 } else {
46 Some(path.to_string())
47 };
48
49 self
50 }
51}
52
53impl Builder for DashmapBuilder {
54 type Config = DashmapConfig;
55
56 fn build(self) -> Result<impl Service> {
57 debug!("backend build started: {:?}", self);
58
59 let root = normalize_root(
60 self.config
61 .root
62 .clone()
63 .unwrap_or_else(|| "/".to_string())
64 .as_str(),
65 );
66
67 debug!("backend build finished: {:?}", self.config);
68
69 let core = DashmapCore {
70 cache: DashMap::new(),
71 };
72
73 Ok(DashmapBackend::new(core, root))
74 }
75}
76
77#[derive(Debug, Clone)]
78pub struct DashmapBackend {
79 pub(crate) core: Arc<DashmapCore>,
80 pub(crate) root: String,
81 pub(crate) info: ServiceInfo,
82 pub(crate) capability: Capability,
83}
84
85impl DashmapBackend {
86 fn new(core: DashmapCore, root: String) -> Self {
87 let info = ServiceInfo::new(DASHMAP_SCHEME, &root, "dashmap");
88 let capability = Capability {
89 read: true,
90
91 write: true,
92 write_can_empty: true,
93 write_with_cache_control: true,
94 write_with_content_type: true,
95 write_with_content_disposition: true,
96 write_with_content_encoding: true,
97
98 delete: true,
99 stat: true,
100 list: true,
101 ..Default::default()
102 };
103
104 Self {
105 core: Arc::new(core),
106 root,
107 info,
108 capability,
109 }
110 }
111}
112
113impl Service for DashmapBackend {
114 type Reader = oio::StreamReader<DashmapReader>;
115 type Writer = DashmapWriter;
116 type Lister = oio::HierarchyLister<DashmapLister>;
117 type Deleter = oio::OneShotDeleter<DashmapDeleter>;
118 type Copier = ();
119
120 fn info(&self) -> ServiceInfo {
121 self.info.clone()
122 }
123
124 fn capability(&self) -> Capability {
125 self.capability
126 }
127
128 async fn create_dir(
129 &self,
130 _ctx: &OperationContext,
131 _path: &str,
132 _args: OpCreateDir,
133 ) -> Result<RpCreateDir> {
134 Err(Error::new(
135 ErrorKind::Unsupported,
136 "operation is not supported",
137 ))
138 }
139
140 async fn stat(&self, _ctx: &OperationContext, path: &str, _: OpStat) -> Result<RpStat> {
141 let p = build_abs_path(&self.root, path);
142
143 match self.core.get(&p)? {
144 Some(value) => {
145 let metadata = value.metadata;
146 Ok(RpStat::new(metadata))
147 }
148 None => {
149 if p.ends_with('/') {
150 let has_children = self.core.cache.iter().any(|kv| kv.key().starts_with(&p));
151 if has_children {
152 return Ok(RpStat::new(Metadata::new(EntryMode::DIR)));
153 }
154 }
155 Err(Error::new(ErrorKind::NotFound, "key not found in dashmap"))
156 }
157 }
158 }
159 fn read(&self, _ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
160 let output: oio::StreamReader<DashmapReader> = {
161 Ok(oio::StreamReader::new(DashmapReader::new(
162 self.clone(),
163 path,
164 args,
165 )))
166 }?;
167
168 Ok(output)
169 }
170
171 fn write(&self, _ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
172 let output: DashmapWriter = {
173 let p = build_abs_path(&self.root, path);
174 Ok(DashmapWriter::new(self.core.clone(), p, args))
175 }?;
176
177 Ok(output)
178 }
179
180 fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
181 let output: oio::OneShotDeleter<DashmapDeleter> = {
182 Ok(oio::OneShotDeleter::new(DashmapDeleter::new(
183 self.core.clone(),
184 self.root.clone(),
185 )))
186 }?;
187
188 Ok(output)
189 }
190
191 fn list(&self, _ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
192 let output: oio::HierarchyLister<DashmapLister> = {
193 let lister = DashmapLister::new(self.core.clone(), self.root.clone(), path.to_string());
194 let lister = oio::HierarchyLister::new(lister, path, args.recursive());
195 Ok(lister)
196 }?;
197
198 Ok(output)
199 }
200
201 fn copy(
202 &self,
203 _ctx: &OperationContext,
204 _from: &str,
205 _to: &str,
206 _args: OpCopy,
207 _opts: OpCopier,
208 ) -> Result<Self::Copier> {
209 Err(Error::new(
210 ErrorKind::Unsupported,
211 "operation is not supported",
212 ))
213 }
214
215 async fn rename(
216 &self,
217 _ctx: &OperationContext,
218 _from: &str,
219 _to: &str,
220 _args: OpRename,
221 ) -> Result<RpRename> {
222 Err(Error::new(
223 ErrorKind::Unsupported,
224 "operation is not supported",
225 ))
226 }
227
228 async fn presign(
229 &self,
230 _ctx: &OperationContext,
231 _path: &str,
232 _args: OpPresign,
233 ) -> Result<RpPresign> {
234 Err(Error::new(
235 ErrorKind::Unsupported,
236 "operation is not supported",
237 ))
238 }
239}