opendal/services/compfs/
core.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::future::Future;
19use std::path::PathBuf;
20use std::sync::Arc;
21
22use compio::buf::IoBuf;
23use compio::dispatcher::Dispatcher;
24
25use crate::raw::*;
26use crate::*;
27
28unsafe impl IoBuf for Buffer {
29    fn as_buf_ptr(&self) -> *const u8 {
30        self.current().as_ptr()
31    }
32
33    fn buf_len(&self) -> usize {
34        self.current().len()
35    }
36
37    fn buf_capacity(&self) -> usize {
38        // `Bytes` doesn't expose uninitialized capacity, so treat it as the same as `len`
39        self.current().len()
40    }
41}
42
43#[derive(Debug)]
44pub(super) struct CompfsCore {
45    pub info: Arc<AccessorInfo>,
46
47    pub root: PathBuf,
48    pub dispatcher: Dispatcher,
49    pub buf_pool: oio::PooledBuf,
50}
51
52impl CompfsCore {
53    pub fn prepare_path(&self, path: &str) -> PathBuf {
54        self.root.join(path.trim_end_matches('/'))
55    }
56
57    pub async fn exec<Fn, Fut, R>(&self, f: Fn) -> crate::Result<R>
58    where
59        Fn: FnOnce() -> Fut + Send + 'static,
60        Fut: Future<Output = std::io::Result<R>> + 'static,
61        R: Send + 'static,
62    {
63        self.dispatcher
64            .dispatch(f)
65            .map_err(|_| Error::new(ErrorKind::Unexpected, "compio spawn io task failed"))?
66            .await
67            .map_err(|_| Error::new(ErrorKind::Unexpected, "compio task cancelled"))?
68            .map_err(new_std_io_error)
69    }
70
71    pub async fn exec_blocking<Fn, R>(&self, f: Fn) -> Result<R>
72    where
73        Fn: FnOnce() -> R + Send + 'static,
74        R: Send + 'static,
75    {
76        self.dispatcher
77            .dispatch_blocking(f)
78            .map_err(|_| Error::new(ErrorKind::Unexpected, "compio spawn blocking task failed"))?
79            .await
80            .map_err(|_| Error::new(ErrorKind::Unexpected, "compio task cancelled"))
81    }
82}
83
84// TODO: impl IoVectoredBuf for Buffer
85// impl IoVectoredBuf for Buffer {
86//     fn as_dyn_bufs(&self) -> impl Iterator<Item = &dyn IoBuf> {}
87//
88//     fn owned_iter(self) -> Result<OwnedIter<impl OwnedIterator<Inner = Self>>, Self> {
89//         Ok(OwnedIter::new(BufferIter {
90//             current: self.current(),
91//             buf: self,
92//         }))
93//     }
94// }
95
96// #[derive(Debug, Clone)]
97// struct BufferIter {
98//     buf: Buffer,
99//     current: Bytes,
100// }
101
102// impl IntoInner for BufferIter {
103//     type Inner = Buffer;
104//
105//     fn into_inner(self) -> Self::Inner {
106//         self.buf
107//     }
108// }
109
110// impl OwnedIterator for BufferIter {
111//     fn next(mut self) -> Result<Self, Self::Inner> {
112//         let Some(current) = self.buf.next() else {
113//             return Err(self.buf);
114//         };
115//         self.current = current;
116//         Ok(self)
117//     }
118//
119//     fn current(&self) -> &dyn IoBuf {
120//         &self.current
121//     }
122// }
123
124#[cfg(test)]
125mod tests {
126    use bytes::Buf;
127    use bytes::Bytes;
128    use rand::thread_rng;
129    use rand::Rng;
130
131    use super::*;
132
133    fn setup_buffer() -> (Buffer, usize, Bytes) {
134        let mut rng = thread_rng();
135
136        let bs = (0..100)
137            .map(|_| {
138                let len = rng.gen_range(1..100);
139                let mut buf = vec![0; len];
140                rng.fill(&mut buf[..]);
141                Bytes::from(buf)
142            })
143            .collect::<Vec<_>>();
144
145        let total_size = bs.iter().map(|b| b.len()).sum::<usize>();
146        let total_content = bs.iter().flatten().copied().collect::<Bytes>();
147        let buf = Buffer::from(bs);
148
149        (buf, total_size, total_content)
150    }
151
152    #[test]
153    fn test_io_buf() {
154        let (buf, _len, _bytes) = setup_buffer();
155        let slice = IoBuf::as_slice(&buf);
156
157        assert_eq!(slice, buf.current().chunk())
158    }
159}