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 mkdirs(&self, path: &str, permission: u32, create_parent: bool) -> Result<()> {
150 self.block_on(self.inner.mkdirs(path, permission, create_parent))
151 }
152
153 pub fn rename(&self, src: &str, dst: &str, overwrite: bool) -> Result<()> {
155 self.block_on(self.inner.rename(src, dst, overwrite))
156 }
157
158 pub fn delete(&self, path: &str, recursive: bool) -> Result<bool> {
160 self.block_on(self.inner.delete(path, recursive))
161 }
162
163 pub fn trash(&self, path: &str) -> Result<Option<String>> {
165 self.block_on(self.inner.trash(path))
166 }
167
168 pub fn set_times(&self, path: &str, mtime: u64, atime: u64) -> Result<()> {
170 self.block_on(self.inner.set_times(path, mtime, atime))
171 }
172
173 pub fn set_owner(&self, path: &str, owner: Option<&str>, group: Option<&str>) -> Result<()> {
175 self.block_on(self.inner.set_owner(path, owner, group))
176 }
177
178 pub fn set_permission(&self, path: &str, permission: u32) -> Result<()> {
180 self.block_on(self.inner.set_permission(path, permission))
181 }
182
183 pub fn set_replication(&self, path: &str, replication: u32) -> Result<bool> {
185 self.block_on(self.inner.set_replication(path, replication))
186 }
187
188 pub fn get_content_summary(&self, path: &str) -> Result<ContentSummary> {
190 self.block_on(self.inner.get_content_summary(path))
191 }
192
193 pub fn modify_acl_entries(&self, path: &str, acl_spec: Vec<AclEntry>) -> Result<()> {
195 self.block_on(self.inner.modify_acl_entries(path, acl_spec))
196 }
197
198 pub fn remove_acl_entries(&self, path: &str, acl_spec: Vec<AclEntry>) -> Result<()> {
200 self.block_on(self.inner.remove_acl_entries(path, acl_spec))
201 }
202
203 pub fn remove_default_acl(&self, path: &str) -> Result<()> {
205 self.block_on(self.inner.remove_default_acl(path))
206 }
207
208 pub fn remove_acl(&self, path: &str) -> Result<()> {
210 self.block_on(self.inner.remove_acl(path))
211 }
212
213 pub fn set_acl(&self, path: &str, acl_spec: Vec<AclEntry>) -> Result<()> {
215 self.block_on(self.inner.set_acl(path, acl_spec))
216 }
217
218 pub fn get_acl_status(&self, path: &str) -> Result<AclStatus> {
220 self.block_on(self.inner.get_acl_status(path))
221 }
222
223 pub fn glob_status(&self, pattern: &str) -> Result<Vec<FileStatus>> {
225 self.block_on(self.inner.glob_status(pattern))
226 }
227}
228
229impl Default for Client {
230 fn default() -> Self {
231 ClientBuilder::new()
232 .build()
233 .expect("Failed to create default client")
234 }
235}
236
237pub struct ListStatusIterator {
239 inner: client::ListStatusIterator,
240 rt: Arc<Runtime>,
241}
242
243impl Iterator for ListStatusIterator {
244 type Item = Result<FileStatus>;
245
246 fn next(&mut self) -> Option<Self::Item> {
247 self.rt.block_on(self.inner.next())
248 }
249}
250
251pub struct FileReader {
253 inner: AsyncFileReader,
254 rt: Arc<Runtime>,
255}
256
257impl FileReader {
258 pub fn file_length(&self) -> usize {
260 self.inner.file_length()
261 }
262
263 pub fn remaining(&self) -> usize {
265 self.inner.remaining()
266 }
267
268 pub fn set_position(&mut self, pos: usize) {
270 self.inner.set_position(pos);
271 }
272
273 pub fn tell(&self) -> usize {
275 self.inner.tell()
276 }
277
278 pub fn read_bytes(&mut self, len: usize) -> Result<Bytes> {
280 self.rt.block_on(self.inner.read_bytes(len))
281 }
282
283 pub fn read_into(&mut self, buf: &mut [u8]) -> Result<usize> {
285 self.rt.block_on(self.inner.read_into(buf))
286 }
287
288 pub fn read_range(&self, offset: usize, len: usize) -> Result<Bytes> {
290 self.rt.block_on(self.inner.read_range(offset, len))
291 }
292
293 pub fn read_range_buf(&self, buf: &mut [u8], offset: usize) -> Result<()> {
295 self.rt.block_on(self.inner.read_range_buf(buf, offset))
296 }
297
298 pub fn read_range_stream(&self, offset: usize, len: usize) -> FileReadStream {
300 FileReadStream {
301 inner: Mutex::new(self.inner.read_range_stream(offset, len).boxed()),
302 rt: Arc::clone(&self.rt),
303 }
304 }
305}
306
307impl Read for FileReader {
308 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
309 self.read_into(buf).map_err(io_error)
310 }
311}
312
313impl Seek for FileReader {
314 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
315 let file_length = self.file_length() as i128;
316 let current = self.tell() as i128;
317 let new_pos = match pos {
318 SeekFrom::Start(pos) => i128::from(pos),
319 SeekFrom::End(offset) => file_length + i128::from(offset),
320 SeekFrom::Current(offset) => current + i128::from(offset),
321 };
322
323 if new_pos < 0 || new_pos > file_length {
324 return Err(io::Error::new(
325 io::ErrorKind::InvalidInput,
326 "cannot seek outside of file bounds",
327 ));
328 }
329
330 self.inner.set_position(new_pos as usize);
331 Ok(new_pos as u64)
332 }
333}
334
335pub struct FileReadStream {
337 inner: Mutex<BoxStream<'static, Result<Bytes>>>,
338 rt: Arc<Runtime>,
339}
340
341impl Iterator for FileReadStream {
342 type Item = Result<Bytes>;
343
344 fn next(&mut self) -> Option<Self::Item> {
345 self.rt.block_on(self.inner.lock().unwrap().next())
346 }
347}
348
349pub struct FileWriter {
351 inner: AsyncFileWriter,
352 rt: Arc<Runtime>,
353}
354
355impl FileWriter {
356 pub fn write_bytes(&mut self, buf: Bytes) -> Result<usize> {
358 self.rt.block_on(self.inner.write_bytes(buf))
359 }
360
361 pub fn close(&mut self) -> Result<()> {
363 self.rt.block_on(self.inner.close())
364 }
365}
366
367impl Write for FileWriter {
368 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
369 self.write_bytes(Bytes::copy_from_slice(buf))
370 .map_err(io_error)
371 }
372
373 fn flush(&mut self) -> io::Result<()> {
374 Ok(())
375 }
376}