opendal/services/sled/
backend.rs1use std::sync::Arc;
19
20use super::SLED_SCHEME;
21use super::config::SledConfig;
22use super::core::*;
23use super::deleter::SledDeleter;
24use super::lister::SledLister;
25use super::writer::SledWriter;
26use crate::raw::*;
27use crate::*;
28
29const DEFAULT_TREE_ID: &str = r#"__sled__default"#;
31
32#[doc = include_str!("docs.md")]
34#[derive(Debug, Default)]
35pub struct SledBuilder {
36 pub(super) config: SledConfig,
37}
38
39impl SledBuilder {
40 pub fn datadir(mut self, path: &str) -> Self {
42 self.config.datadir = Some(path.into());
43 self
44 }
45
46 pub fn tree(mut self, tree: &str) -> Self {
48 self.config.tree = Some(tree.into());
49 self
50 }
51
52 pub fn root(mut self, root: &str) -> Self {
54 self.config.root = if root.is_empty() {
55 None
56 } else {
57 Some(root.to_string())
58 };
59
60 self
61 }
62}
63
64impl Builder for SledBuilder {
65 type Config = SledConfig;
66
67 fn build(self) -> Result<impl Access> {
68 let datadir_path = self.config.datadir.ok_or_else(|| {
69 Error::new(ErrorKind::ConfigInvalid, "datadir is required but not set")
70 .with_context("service", SLED_SCHEME)
71 })?;
72
73 let db = sled::open(&datadir_path).map_err(|e| {
74 Error::new(ErrorKind::ConfigInvalid, "open db")
75 .with_context("service", SLED_SCHEME)
76 .with_context("datadir", datadir_path.clone())
77 .set_source(e)
78 })?;
79
80 let tree_name = self
82 .config
83 .tree
84 .unwrap_or_else(|| DEFAULT_TREE_ID.to_string());
85
86 let tree = db.open_tree(&tree_name).map_err(|e| {
87 Error::new(ErrorKind::ConfigInvalid, "open tree")
88 .with_context("service", SLED_SCHEME)
89 .with_context("datadir", datadir_path.clone())
90 .with_context("tree", tree_name.clone())
91 .set_source(e)
92 })?;
93
94 let root = normalize_root(&self.config.root.unwrap_or_default());
95
96 Ok(SledBackend::new(SledCore {
97 datadir: datadir_path,
98 tree,
99 })
100 .with_normalized_root(root))
101 }
102}
103
104#[derive(Clone, Debug)]
106pub struct SledBackend {
107 core: Arc<SledCore>,
108 root: String,
109 info: Arc<AccessorInfo>,
110}
111
112impl SledBackend {
113 pub fn new(core: SledCore) -> Self {
114 let info = AccessorInfo::default();
115 info.set_scheme(SLED_SCHEME)
116 .set_name(&core.datadir)
117 .set_root("/")
118 .set_native_capability(Capability {
119 read: true,
120 stat: true,
121 write: true,
122 write_can_empty: true,
123 delete: true,
124 list: true,
125 list_with_recursive: true,
126 shared: false,
127 ..Default::default()
128 });
129
130 Self {
131 core: Arc::new(core),
132 root: "/".to_string(),
133 info: Arc::new(info),
134 }
135 }
136
137 fn with_normalized_root(mut self, root: String) -> Self {
138 self.info.set_root(&root);
139 self.root = root;
140 self
141 }
142}
143
144impl Access for SledBackend {
145 type Reader = Buffer;
146 type Writer = SledWriter;
147 type Lister = oio::HierarchyLister<SledLister>;
148 type Deleter = oio::OneShotDeleter<SledDeleter>;
149
150 fn info(&self) -> Arc<AccessorInfo> {
151 self.info.clone()
152 }
153
154 async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> {
155 let p = build_abs_path(&self.root, path);
156
157 if p == build_abs_path(&self.root, "") {
158 Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
159 } else {
160 let bs = self.core.get(&p)?;
161 match bs {
162 Some(bs) => Ok(RpStat::new(
163 Metadata::new(EntryMode::FILE).with_content_length(bs.len() as u64),
164 )),
165 None => Err(Error::new(ErrorKind::NotFound, "kv not found in sled")),
166 }
167 }
168 }
169
170 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
171 let p = build_abs_path(&self.root, path);
172 let bs = match self.core.get(&p)? {
173 Some(bs) => bs,
174 None => {
175 return Err(Error::new(ErrorKind::NotFound, "kv not found in sled"));
176 }
177 };
178 Ok((RpRead::new(), bs.slice(args.range().to_range_as_usize())))
179 }
180
181 async fn write(&self, path: &str, _: OpWrite) -> Result<(RpWrite, Self::Writer)> {
182 let p = build_abs_path(&self.root, path);
183 let writer = SledWriter::new(self.core.clone(), p);
184 Ok((RpWrite::new(), writer))
185 }
186
187 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
188 let deleter = SledDeleter::new(self.core.clone(), self.root.clone());
189 Ok((RpDelete::default(), oio::OneShotDeleter::new(deleter)))
190 }
191
192 async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> {
193 let p = build_abs_path(&self.root, path);
194 let lister = SledLister::new(self.core.clone(), self.root.clone(), p)?;
195 Ok((
196 RpList::default(),
197 oio::HierarchyLister::new(lister, path, args.recursive()),
198 ))
199 }
200}