1use std::future::Future;
8use std::io::{self, Read, Seek, SeekFrom, Write};
9use std::sync::{Arc, Mutex};
10
11use bytes::Bytes;
12use futures::StreamExt;
13use futures::stream::BoxStream;
14use tokio::runtime::Runtime;
15
16use crate::acl::{AclEntry, AclStatus};
17use crate::client::{self, ContentSummary, FileStatus, WriteOptions};
18use crate::file::{FileReader as AsyncFileReader, FileWriter as AsyncFileWriter};
19use crate::{Result, client::IORuntime};
20
21fn io_error(error: crate::HdfsError) -> io::Error {
22 io::Error::other(error)
23}
24
25#[derive(Default)]
27pub struct ClientBuilder {
28 inner: client::ClientBuilder,
29}
30
31impl ClientBuilder {
32 pub fn new() -> Self {
34 Self::default()
35 }
36
37 pub fn with_url(mut self, url: impl Into<String>) -> Self {
39 self.inner = self.inner.with_url(url);
40 self
41 }
42
43 pub fn with_config(
45 mut self,
46 config: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
47 ) -> Self {
48 self.inner = self.inner.with_config(config);
49 self
50 }
51
52 pub fn with_config_dir(mut self, config_dir: impl Into<String>) -> Self {
54 self.inner = self.inner.with_config_dir(config_dir);
55 self
56 }
57
58 pub fn with_user(mut self, user: impl Into<String>) -> Self {
61 self.inner = self.inner.with_user(user);
62 self
63 }
64
65 pub fn with_kerberos_principal(mut self, principal: impl Into<String>) -> Self {
67 self.inner = self.inner.with_kerberos_principal(principal);
68 self
69 }
70
71 pub fn with_kerberos_keytab(mut self, keytab: impl Into<String>) -> Self {
73 self.inner = self.inner.with_kerberos_keytab(keytab);
74 self
75 }
76
77 pub fn with_kerberos_cache(mut self, cache: impl Into<String>) -> Self {
79 self.inner = self.inner.with_kerberos_cache(cache);
80 self
81 }
82
83 pub fn build(self) -> Result<Client> {
85 let rt = Arc::new(Runtime::new()?);
86 let inner = self
87 .inner
88 .with_io_runtime(IORuntime::from(rt.handle().clone()))
89 .build()?;
90 Ok(Client { inner, rt })
91 }
92}
93
94#[derive(Clone, Debug)]
96pub struct Client {
97 inner: client::Client,
98 rt: Arc<Runtime>,
99}
100
101impl Client {
102 fn block_on<F: Future>(&self, future: F) -> F::Output {
103 self.rt.block_on(future)
104 }
105
106 pub fn get_file_info(&self, path: &str) -> Result<FileStatus> {
108 self.block_on(self.inner.get_file_info(path))
109 }
110
111 pub fn list_status(&self, path: &str, recursive: bool) -> Result<Vec<FileStatus>> {
113 self.block_on(self.inner.list_status(path, recursive))
114 }
115
116 pub fn list_status_iter(&self, path: &str, recursive: bool) -> ListStatusIterator {
118 ListStatusIterator {
119 inner: self.inner.list_status_iter(path, recursive),
120 rt: Arc::clone(&self.rt),
121 }
122 }
123
124 pub fn read(&self, path: &str) -> Result<FileReader> {
126 Ok(FileReader {
127 inner: self.block_on(self.inner.read(path))?,
128 rt: Arc::clone(&self.rt),
129 })
130 }
131
132 pub fn create(&self, src: &str, write_options: impl AsRef<WriteOptions>) -> Result<FileWriter> {
134 Ok(FileWriter {
135 inner: self.block_on(self.inner.create(src, write_options))?,
136 rt: Arc::clone(&self.rt),
137 })
138 }
139
140 pub fn append(&self, src: &str) -> Result<FileWriter> {
142 Ok(FileWriter {
143 inner: self.block_on(self.inner.append(src))?,
144 rt: Arc::clone(&self.rt),
145 })
146 }
147
148 pub fn recover_lease(&self, src: &str) -> Result<bool> {
152 self.block_on(self.inner.recover_lease(src))
153 }
154
155 pub fn mkdirs(&self, path: &str, permission: u32, create_parent: bool) -> Result<()> {
157 self.block_on(self.inner.mkdirs(path, permission, create_parent))
158 }
159
160 pub fn rename(&self, src: &str, dst: &str, overwrite: bool) -> Result<()> {
162 self.block_on(self.inner.rename(src, dst, overwrite))
163 }
164
165 pub fn delete(&self, path: &str, recursive: bool) -> Result<bool> {
167 self.block_on(self.inner.delete(path, recursive))
168 }
169
170 pub fn trash(&self, path: &str) -> Result<Option<String>> {
172 self.block_on(self.inner.trash(path))
173 }
174
175 pub fn set_times(&self, path: &str, mtime: u64, atime: u64) -> Result<()> {
177 self.block_on(self.inner.set_times(path, mtime, atime))
178 }
179
180 pub fn set_owner(&self, path: &str, owner: Option<&str>, group: Option<&str>) -> Result<()> {
182 self.block_on(self.inner.set_owner(path, owner, group))
183 }
184
185 pub fn set_permission(&self, path: &str, permission: u32) -> Result<()> {
187 self.block_on(self.inner.set_permission(path, permission))
188 }
189
190 pub fn set_replication(&self, path: &str, replication: u32) -> Result<bool> {
192 self.block_on(self.inner.set_replication(path, replication))
193 }
194
195 pub fn get_content_summary(&self, path: &str) -> Result<ContentSummary> {
197 self.block_on(self.inner.get_content_summary(path))
198 }
199
200 pub fn modify_acl_entries(&self, path: &str, acl_spec: Vec<AclEntry>) -> Result<()> {
202 self.block_on(self.inner.modify_acl_entries(path, acl_spec))
203 }
204
205 pub fn remove_acl_entries(&self, path: &str, acl_spec: Vec<AclEntry>) -> Result<()> {
207 self.block_on(self.inner.remove_acl_entries(path, acl_spec))
208 }
209
210 pub fn remove_default_acl(&self, path: &str) -> Result<()> {
212 self.block_on(self.inner.remove_default_acl(path))
213 }
214
215 pub fn remove_acl(&self, path: &str) -> Result<()> {
217 self.block_on(self.inner.remove_acl(path))
218 }
219
220 pub fn set_acl(&self, path: &str, acl_spec: Vec<AclEntry>) -> Result<()> {
222 self.block_on(self.inner.set_acl(path, acl_spec))
223 }
224
225 pub fn get_acl_status(&self, path: &str) -> Result<AclStatus> {
227 self.block_on(self.inner.get_acl_status(path))
228 }
229
230 pub fn glob_status(&self, pattern: &str) -> Result<Vec<FileStatus>> {
232 self.block_on(self.inner.glob_status(pattern))
233 }
234}
235
236impl Default for Client {
237 fn default() -> Self {
238 ClientBuilder::new()
239 .build()
240 .expect("Failed to create default client")
241 }
242}
243
244pub struct ListStatusIterator {
246 inner: client::ListStatusIterator,
247 rt: Arc<Runtime>,
248}
249
250impl Iterator for ListStatusIterator {
251 type Item = Result<FileStatus>;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 self.rt.block_on(self.inner.next())
255 }
256}
257
258pub struct FileReader {
260 inner: AsyncFileReader,
261 rt: Arc<Runtime>,
262}
263
264impl FileReader {
265 pub fn file_length(&self) -> usize {
267 self.inner.file_length()
268 }
269
270 pub fn remaining(&self) -> usize {
272 self.inner.remaining()
273 }
274
275 pub fn set_position(&mut self, pos: usize) {
277 self.inner.set_position(pos);
278 }
279
280 pub fn tell(&self) -> usize {
282 self.inner.tell()
283 }
284
285 pub fn read_bytes(&mut self, len: usize) -> Result<Bytes> {
287 self.rt.block_on(self.inner.read_bytes(len))
288 }
289
290 pub fn read_into(&mut self, buf: &mut [u8]) -> Result<usize> {
292 self.rt.block_on(self.inner.read_into(buf))
293 }
294
295 pub fn read_range(&self, offset: usize, len: usize) -> Result<Bytes> {
297 self.rt.block_on(self.inner.read_range(offset, len))
298 }
299
300 pub fn read_range_buf(&self, buf: &mut [u8], offset: usize) -> Result<()> {
302 self.rt.block_on(self.inner.read_range_buf(buf, offset))
303 }
304
305 pub fn read_range_stream(&self, offset: usize, len: usize) -> FileReadStream {
307 FileReadStream {
308 inner: Mutex::new(self.inner.read_range_stream(offset, len).boxed()),
309 rt: Arc::clone(&self.rt),
310 }
311 }
312}
313
314impl Read for FileReader {
315 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
316 self.read_into(buf).map_err(io_error)
317 }
318}
319
320impl Seek for FileReader {
321 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
322 let file_length = self.file_length() as i128;
323 let current = self.tell() as i128;
324 let new_pos = match pos {
325 SeekFrom::Start(pos) => i128::from(pos),
326 SeekFrom::End(offset) => file_length + i128::from(offset),
327 SeekFrom::Current(offset) => current + i128::from(offset),
328 };
329
330 if new_pos < 0 || new_pos > file_length {
331 return Err(io::Error::new(
332 io::ErrorKind::InvalidInput,
333 "cannot seek outside of file bounds",
334 ));
335 }
336
337 self.inner.set_position(new_pos as usize);
338 Ok(new_pos as u64)
339 }
340}
341
342pub struct FileReadStream {
344 inner: Mutex<BoxStream<'static, Result<Bytes>>>,
345 rt: Arc<Runtime>,
346}
347
348impl Iterator for FileReadStream {
349 type Item = Result<Bytes>;
350
351 fn next(&mut self) -> Option<Self::Item> {
352 self.rt.block_on(self.inner.lock().unwrap().next())
353 }
354}
355
356pub struct FileWriter {
358 inner: AsyncFileWriter,
359 rt: Arc<Runtime>,
360}
361
362impl FileWriter {
363 pub fn write_bytes(&mut self, buf: Bytes) -> Result<usize> {
365 self.rt.block_on(self.inner.write_bytes(buf))
366 }
367
368 pub fn hsync(&mut self) -> Result<()> {
370 self.rt.block_on(self.inner.hsync())
371 }
372
373 pub fn close(&mut self) -> Result<()> {
375 self.rt.block_on(self.inner.close())
376 }
377}
378
379impl Write for FileWriter {
380 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
381 self.write_bytes(Bytes::copy_from_slice(buf))
382 .map_err(io_error)
383 }
384
385 fn flush(&mut self) -> io::Result<()> {
386 Ok(())
387 }
388}