opendal/services/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::writer::FoundationdbWriter;
28use crate::raw::*;
29use crate::*;
30
31#[doc = include_str!("docs.md")]
32#[derive(Debug, Default)]
33pub struct FoundationdbBuilder {
34 pub(super) config: FoundationdbConfig,
35}
36
37impl FoundationdbBuilder {
38 pub fn root(mut self, path: &str) -> Self {
40 self.config.root = Some(path.into());
41 self
42 }
43
44 pub fn config_path(mut self, path: &str) -> Self {
46 self.config.config_path = Some(path.into());
47 self
48 }
49}
50
51impl Builder for FoundationdbBuilder {
52 type Config = FoundationdbConfig;
53
54 fn build(self) -> Result<impl Access> {
55 let _network = Arc::new(unsafe { foundationdb::boot() });
56 let db;
57 if let Some(cfg_path) = &self.config.config_path {
58 db = Database::from_path(cfg_path).map_err(|e| {
59 Error::new(ErrorKind::ConfigInvalid, "open foundation db")
60 .with_context("service", FOUNDATIONDB_SCHEME)
61 .set_source(e)
62 })?;
63 } else {
64 db = Database::default().map_err(|e| {
65 Error::new(ErrorKind::ConfigInvalid, "open foundation db")
66 .with_context("service", FOUNDATIONDB_SCHEME)
67 .set_source(e)
68 })?
69 }
70
71 let db = Arc::new(db);
72
73 let root = normalize_root(
74 self.config
75 .root
76 .clone()
77 .unwrap_or_else(|| "/".to_string())
78 .as_str(),
79 );
80
81 Ok(FoundationdbBackend::new(FoundationdbCore { db, _network }).with_normalized_root(root))
82 }
83}
84
85#[derive(Clone, Debug)]
87pub struct FoundationdbBackend {
88 core: Arc<FoundationdbCore>,
89 root: String,
90 info: Arc<AccessorInfo>,
91}
92
93impl FoundationdbBackend {
94 pub fn new(core: FoundationdbCore) -> Self {
95 let info = AccessorInfo::default();
96 info.set_scheme(FOUNDATIONDB_SCHEME);
97 info.set_name("foundationdb");
98 info.set_root("/");
99 info.set_native_capability(Capability {
100 read: true,
101 stat: true,
102 write: true,
103 write_can_empty: true,
104 delete: true,
105 shared: true,
106 ..Default::default()
107 });
108
109 Self {
110 core: Arc::new(core),
111 root: "/".to_string(),
112 info: Arc::new(info),
113 }
114 }
115
116 fn with_normalized_root(mut self, root: String) -> Self {
117 self.info.set_root(&root);
118 self.root = root;
119 self
120 }
121}
122
123impl Access for FoundationdbBackend {
124 type Reader = Buffer;
125 type Writer = FoundationdbWriter;
126 type Lister = ();
127 type Deleter = oio::OneShotDeleter<FoundationdbDeleter>;
128
129 fn info(&self) -> Arc<AccessorInfo> {
130 self.info.clone()
131 }
132
133 async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> {
134 let p = build_abs_path(&self.root, path);
135
136 if p == build_abs_path(&self.root, "") {
137 Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
138 } else {
139 let bs = self.core.get(&p).await?;
140 match bs {
141 Some(bs) => Ok(RpStat::new(
142 Metadata::new(EntryMode::FILE).with_content_length(bs.len() as u64),
143 )),
144 None => Err(Error::new(
145 ErrorKind::NotFound,
146 "kv not found in foundationdb",
147 )),
148 }
149 }
150 }
151
152 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
153 let p = build_abs_path(&self.root, path);
154 let bs = match self.core.get(&p).await? {
155 Some(bs) => bs,
156 None => {
157 return Err(Error::new(
158 ErrorKind::NotFound,
159 "kv not found in foundationdb",
160 ));
161 }
162 };
163 Ok((RpRead::new(), bs.slice(args.range().to_range_as_usize())))
164 }
165
166 async fn write(&self, path: &str, _: OpWrite) -> Result<(RpWrite, Self::Writer)> {
167 let p = build_abs_path(&self.root, path);
168 Ok((
169 RpWrite::new(),
170 FoundationdbWriter::new(self.core.clone(), p),
171 ))
172 }
173
174 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
175 Ok((
176 RpDelete::default(),
177 oio::OneShotDeleter::new(FoundationdbDeleter::new(
178 self.core.clone(),
179 self.root.clone(),
180 )),
181 ))
182 }
183
184 async fn list(&self, path: &str, _: OpList) -> Result<(RpList, Self::Lister)> {
185 let _ = build_abs_path(&self.root, path);
186 Ok((RpList::default(), ()))
187 }
188}