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