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 type Composer = ();
120
121 fn info(&self) -> ServiceInfo {
122 self.info.clone()
123 }
124
125 fn capability(&self) -> Capability {
126 self.capability
127 }
128
129 async fn create_dir(
130 &self,
131 _ctx: &OperationContext,
132 _path: &str,
133 _args: OpCreateDir,
134 ) -> Result<RpCreateDir> {
135 Err(Error::new(
136 ErrorKind::Unsupported,
137 "operation is not supported",
138 ))
139 }
140
141 async fn stat(&self, _ctx: &OperationContext, path: &str, _: OpStat) -> Result<RpStat> {
142 let p = build_abs_path(&self.root, path);
143
144 match self.core.get(&p)? {
145 Some(value) => {
146 let metadata = value.metadata;
147 Ok(RpStat::new(metadata))
148 }
149 None => {
150 if p.ends_with('/') {
151 let has_children = self.core.cache.iter().any(|kv| kv.key().starts_with(&p));
152 if has_children {
153 return Ok(RpStat::new(MetadataBuilder::dir().build()));
154 }
155 }
156 Err(Error::new(ErrorKind::NotFound, "key not found in dashmap"))
157 }
158 }
159 }
160 fn read(&self, _ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
161 let output: oio::StreamReader<DashmapReader> = {
162 Ok(oio::StreamReader::new(DashmapReader::new(
163 self.clone(),
164 path,
165 args,
166 )))
167 }?;
168
169 Ok(output)
170 }
171
172 fn write(&self, _ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
173 let output: DashmapWriter = {
174 let p = build_abs_path(&self.root, path);
175 Ok(DashmapWriter::new(self.core.clone(), p, args))
176 }?;
177
178 Ok(output)
179 }
180
181 fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
182 let output: oio::OneShotDeleter<DashmapDeleter> = {
183 Ok(oio::OneShotDeleter::new(DashmapDeleter::new(
184 self.core.clone(),
185 self.root.clone(),
186 )))
187 }?;
188
189 Ok(output)
190 }
191
192 fn list(&self, _ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
193 let output: oio::HierarchyLister<DashmapLister> = {
194 let lister = DashmapLister::new(self.core.clone(), self.root.clone(), path.to_string());
195 let lister = oio::HierarchyLister::new(lister, path, args.recursive());
196 Ok(lister)
197 }?;
198
199 Ok(output)
200 }
201
202 fn copy(
203 &self,
204 _ctx: &OperationContext,
205 _from: &str,
206 _to: &str,
207 _args: OpCopy,
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}