opendal_service_hdfs_native/
backend.rs1use std::collections::HashMap;
19use std::sync::Arc;
20
21use log::debug;
22
23use super::HDFS_NATIVE_SCHEME;
24use super::config::HDFS_DEFAULT_AUTHORITY;
25use super::config::HDFS_SCHEME_PREFIX;
26use super::config::HdfsNativeConfig;
27use super::config::init_hdfs_config;
28use super::core::HdfsNativeCore;
29use super::core::parse_hdfs_error;
30use super::deleter::HdfsNativeDeleter;
31use super::reader::*;
32use opendal_core::raw::*;
33use opendal_core::*;
34
35#[doc = include_str!("docs.md")]
38#[derive(Debug, Default)]
39pub struct HdfsNativeBuilder {
40 pub(super) config: HdfsNativeConfig,
41}
42
43impl HdfsNativeBuilder {
44 pub fn root(mut self, root: &str) -> Self {
48 self.config.root = if root.is_empty() {
49 None
50 } else {
51 Some(root.to_string())
52 };
53
54 self
55 }
56
57 pub fn name_node(mut self, name_node: &str) -> Self {
65 if !name_node.is_empty() {
66 self.config.name_node = Some(name_node.trim_end_matches('/').to_string())
68 }
69
70 self
71 }
72
73 #[deprecated(
75 since = "0.57.0",
76 note = "HDFS Native append capability is enabled by default and this option is no longer needed."
77 )]
78 pub fn enable_append(self, _enable_append: bool) -> Self {
79 self
80 }
81
82 pub fn options(mut self, options: HashMap<String, String>) -> Self {
87 self.config.options = Some(options);
88 self
89 }
90}
91
92impl Builder for HdfsNativeBuilder {
93 type Config = HdfsNativeConfig;
94
95 fn build(self) -> Result<impl Service> {
96 debug!("backend build started: {:?}", self);
97
98 let name_node = match &self.config.name_node {
99 Some(v) => v,
100 None => {
101 return Err(Error::new(ErrorKind::ConfigInvalid, "name_node is empty")
102 .with_context("service", HDFS_NATIVE_SCHEME));
103 }
104 };
105
106 let root = normalize_root(&self.config.root.unwrap_or_default());
107 debug!("backend use root {root}");
108
109 let mut hdfs_config = init_hdfs_config(name_node);
110 if let Some(options) = &self.config.options {
111 hdfs_config.extend(options.iter().map(|(k, v)| (k.clone(), v.clone())));
112 }
113
114 let client = hdfs_native::ClientBuilder::new()
115 .with_url(format!("{}{}", HDFS_SCHEME_PREFIX, HDFS_DEFAULT_AUTHORITY))
116 .with_config(hdfs_config)
117 .build()
118 .map_err(parse_hdfs_error)?;
119
120 Ok(HdfsNativeBackend {
122 core: Arc::new(HdfsNativeCore {
123 info: ServiceInfo::new(HDFS_NATIVE_SCHEME, &root, ""),
124 capability: Capability {
125 stat: true,
126
127 read: true,
128
129 write: true,
130 write_can_append: true,
131
132 create_dir: true,
133 delete: true,
134
135 list: true,
136
137 rename: true,
138
139 shared: true,
140
141 ..Default::default()
142 },
143 root,
144 client: Arc::new(client),
145 }),
146 })
147 }
148}
149
150#[derive(Debug, Clone)]
160pub struct HdfsNativeBackend {
161 pub(crate) core: Arc<HdfsNativeCore>,
162}
163
164impl Service for HdfsNativeBackend {
165 type Reader = oio::PositionReader<HdfsNativeReader>;
166 type Writer = HdfsNativeLazyWriter;
167 type Lister = HdfsNativeLazyLister;
168 type Deleter = oio::OneShotDeleter<HdfsNativeDeleter>;
169 type Copier = ();
170
171 fn info(&self) -> ServiceInfo {
172 self.core.info.clone()
173 }
174
175 fn capability(&self) -> Capability {
176 self.core.capability
177 }
178
179 async fn create_dir(
180 &self,
181 _ctx: &OperationContext,
182 path: &str,
183 _args: OpCreateDir,
184 ) -> Result<RpCreateDir> {
185 self.core.hdfs_create_dir(path).await?;
186 Ok(RpCreateDir::default())
187 }
188
189 async fn stat(&self, _ctx: &OperationContext, path: &str, _args: OpStat) -> Result<RpStat> {
190 let m = self.core.hdfs_stat(path).await?;
191 Ok(RpStat::new(m))
192 }
193 fn read(&self, _ctx: &OperationContext, path: &str, _: OpRead) -> Result<Self::Reader> {
194 Ok(oio::PositionReader::new(HdfsNativeReader::new(
195 self.core.clone(),
196 path,
197 )))
198 }
199
200 fn write(&self, _ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
201 Ok(HdfsNativeLazyWriter::new(self.core.clone(), path, args))
202 }
203
204 fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
205 let output: oio::OneShotDeleter<HdfsNativeDeleter> = {
206 Ok(oio::OneShotDeleter::new(HdfsNativeDeleter::new(
207 Arc::clone(&self.core),
208 )))
209 }?;
210
211 Ok(output)
212 }
213
214 fn list(&self, _ctx: &OperationContext, path: &str, _args: OpList) -> Result<Self::Lister> {
215 Ok(HdfsNativeLazyLister::new(self.core.clone(), path))
216 }
217
218 fn copy(
219 &self,
220 _ctx: &OperationContext,
221 _from: &str,
222 _to: &str,
223 _args: OpCopy,
224 _opts: OpCopier,
225 ) -> Result<Self::Copier> {
226 Err(Error::new(
227 ErrorKind::Unsupported,
228 "operation is not supported",
229 ))
230 }
231
232 async fn rename(
233 &self,
234 _ctx: &OperationContext,
235 from: &str,
236 to: &str,
237 _args: OpRename,
238 ) -> Result<RpRename> {
239 self.core.hdfs_rename(from, to).await?;
240 Ok(RpRename::default())
241 }
242
243 async fn presign(
244 &self,
245 _ctx: &OperationContext,
246 _path: &str,
247 _args: OpPresign,
248 ) -> Result<RpPresign> {
249 Err(Error::new(
250 ErrorKind::Unsupported,
251 "operation is not supported",
252 ))
253 }
254}