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 type Composer = ();
130
131 fn info(&self) -> ServiceInfo {
132 self.info.clone()
133 }
134
135 fn capability(&self) -> Capability {
136 self.capability
137 }
138
139 async fn create_dir(
140 &self,
141 _ctx: &OperationContext,
142 _path: &str,
143 _args: OpCreateDir,
144 ) -> Result<RpCreateDir> {
145 Err(Error::new(
146 ErrorKind::Unsupported,
147 "operation is not supported",
148 ))
149 }
150
151 async fn stat(&self, _ctx: &OperationContext, path: &str, _: OpStat) -> Result<RpStat> {
152 let p = build_abs_path(&self.root, path);
153
154 if p == build_abs_path(&self.root, "") {
155 Ok(RpStat::new(MetadataBuilder::dir().build()))
156 } else {
157 let bs = self.core.get(&p).await?;
158 match bs {
159 Some(bs) => Ok(RpStat::new({
160 let metadata = MetadataBuilder::file(bs.len() as u64);
161 metadata.build()
162 })),
163 None => Err(Error::new(
164 ErrorKind::NotFound,
165 "kv not found in foundationdb",
166 )),
167 }
168 }
169 }
170 fn read(&self, _ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
171 let output: oio::StreamReader<FoundationdbReader> = {
172 Ok(oio::StreamReader::new(FoundationdbReader::new(
173 self.clone(),
174 path,
175 args,
176 )))
177 }?;
178
179 Ok(output)
180 }
181
182 fn write(&self, _ctx: &OperationContext, path: &str, _: OpWrite) -> Result<Self::Writer> {
183 let output: FoundationdbWriter = {
184 let p = build_abs_path(&self.root, path);
185 Ok(FoundationdbWriter::new(self.core.clone(), p))
186 }?;
187
188 Ok(output)
189 }
190
191 fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
192 let output: oio::OneShotDeleter<FoundationdbDeleter> = {
193 Ok(oio::OneShotDeleter::new(FoundationdbDeleter::new(
194 self.core.clone(),
195 self.root.clone(),
196 )))
197 }?;
198
199 Ok(output)
200 }
201
202 fn list(&self, _ctx: &OperationContext, _path: &str, _args: OpList) -> Result<Self::Lister> {
203 Err(Error::new(
204 ErrorKind::Unsupported,
205 "operation is not supported",
206 ))
207 }
208
209 fn copy(
210 &self,
211 _ctx: &OperationContext,
212 _from: &str,
213 _to: &str,
214 _args: OpCopy,
215 ) -> Result<Self::Copier> {
216 Err(Error::new(
217 ErrorKind::Unsupported,
218 "operation is not supported",
219 ))
220 }
221
222 async fn rename(
223 &self,
224 _ctx: &OperationContext,
225 _from: &str,
226 _to: &str,
227 _args: OpRename,
228 ) -> Result<RpRename> {
229 Err(Error::new(
230 ErrorKind::Unsupported,
231 "operation is not supported",
232 ))
233 }
234
235 async fn presign(
236 &self,
237 _ctx: &OperationContext,
238 _path: &str,
239 _args: OpPresign,
240 ) -> Result<RpPresign> {
241 Err(Error::new(
242 ErrorKind::Unsupported,
243 "operation is not supported",
244 ))
245 }
246}