Skip to main content

parallel_processor/memory_fs/file/
reader.rs

1use crate::memory_fs::file::internal::{FileChunk, MemoryFileInternal, OpenMode};
2use crate::utils::vec_reader::VecReaderInner;
3use parking_lot::lock_api::ArcRwLockReadGuard;
4use parking_lot::{RawRwLock, RwLock};
5use std::io;
6use std::io::{ErrorKind, Read, Seek, SeekFrom};
7use std::ops::Range;
8use std::path::{Path, PathBuf};
9use std::sync::Arc;
10
11use super::writer::FileWriter;
12
13const MIN_UNBUFFERED_READ: usize = 2048;
14const FILE_READ_BUFFER_SIZE: usize = 4096;
15
16#[derive(Clone)]
17pub struct FileRangeReference {
18    file: Arc<RwLock<MemoryFileInternal>>,
19    start_chunk: usize,
20    start_chunk_offset: usize,
21    bytes_count: usize,
22}
23
24impl FileRangeReference {
25    pub unsafe fn copy_to_unsync(&self, other: &FileWriter) {
26        let file = self.file.read();
27        let mut chunk_index = self.start_chunk;
28        let mut chunk_offset = self.start_chunk_offset;
29        let mut written_bytes = 0;
30
31        while written_bytes < self.bytes_count {
32            let underlying_file = file.get_underlying_file();
33            let chunk = file.get_chunk(chunk_index);
34            let chunk = chunk.read();
35            let to_copy = (chunk.get_length() - chunk_offset).min(self.bytes_count - written_bytes);
36
37            other.write_all_unsync_from_readfn(
38                |buffer| {
39                    let amount = chunk
40                        .read_at(underlying_file, chunk_offset as u64, buffer)
41                        .unwrap();
42                    chunk_offset += amount;
43                    amount
44                },
45                to_copy,
46            );
47
48            written_bytes += to_copy;
49            chunk_index += 1;
50            chunk_offset = 0;
51        }
52    }
53}
54
55pub struct FileReader {
56    path: PathBuf,
57    file: Arc<RwLock<MemoryFileInternal>>,
58    current_chunk_ref: Option<ArcRwLockReadGuard<RawRwLock, FileChunk>>,
59    current_chunk_index: usize,
60    chunks_count: usize,
61    current_position: usize,
62    current_len: usize,
63    current_file_position: usize,
64    is_on_disk: bool,
65    buffer: Option<VecReaderInner>,
66    buffer_position: usize,
67}
68
69unsafe impl Sync for FileReader {}
70unsafe impl Send for FileReader {}
71
72impl Clone for FileReader {
73    fn clone(&self) -> Self {
74        Self {
75            path: self.path.clone(),
76            file: self.file.clone(),
77            current_chunk_ref: self
78                .current_chunk_ref
79                .as_ref()
80                .map(|c| ArcRwLockReadGuard::rwlock(&c).read_arc()),
81            current_chunk_index: self.current_chunk_index,
82            chunks_count: self.chunks_count,
83            current_position: self.current_position,
84            current_len: self.current_len,
85            current_file_position: self.current_file_position,
86            is_on_disk: self.is_on_disk,
87            buffer: self.buffer.clone(),
88            buffer_position: self.buffer_position,
89        }
90    }
91}
92
93impl FileReader {
94    fn set_chunk_info(&mut self, index: usize) {
95        let file = self.file.read();
96
97        let chunk = file.get_chunk(index);
98        let chunk_guard = chunk.read_arc();
99
100        self.current_position = 0;
101        self.buffer_position = 0;
102        self.current_len = chunk_guard.get_length();
103        self.is_on_disk = chunk_guard.is_on_disk();
104        self.current_chunk_ref = Some(chunk_guard);
105
106        if self.is_on_disk && self.buffer.is_none() {
107            self.buffer = Some(VecReaderInner::new(FILE_READ_BUFFER_SIZE))
108        }
109
110        self.buffer.as_mut().map(|b| b.reset());
111    }
112
113    pub fn open(path: impl AsRef<Path>) -> Option<Self> {
114        let file = match MemoryFileInternal::retrieve_reference(&path) {
115            None => MemoryFileInternal::create_from_fs(&path)?,
116            Some(x) => x,
117        };
118
119        let mut file_lock = file.write();
120
121        file_lock.open(OpenMode::Read).unwrap();
122        let chunks_count = file_lock.get_chunks_count();
123        drop(file_lock);
124
125        let mut reader = Self {
126            path: path.as_ref().into(),
127            file,
128            current_chunk_ref: None,
129            current_chunk_index: 0,
130            chunks_count,
131            current_position: 0,
132            current_len: 0,
133            current_file_position: 0,
134            is_on_disk: false,
135            buffer: None,
136            buffer_position: 0,
137        };
138
139        if reader.chunks_count > 0 {
140            reader.set_chunk_info(0);
141        }
142
143        Some(reader)
144    }
145
146    pub fn get_unique_file_id(&self) -> usize {
147        self.file.data_ptr() as usize
148    }
149
150    pub fn total_file_size(&self) -> usize {
151        self.file.read().len()
152    }
153
154    pub fn get_file_path(&self) -> &Path {
155        &self.path
156    }
157
158    pub fn close_and_remove(self, remove_fs: bool) -> bool {
159        MemoryFileInternal::delete(self.path, remove_fs)
160    }
161
162    pub fn get_range_reference(&self, file_range: Range<u64>) -> FileRangeReference {
163        let file = self.file.read();
164        let mut chunk_index = 0;
165        let mut chunk_offset = 0;
166        let mut start = file_range.start;
167
168        while start > 0 {
169            let chunk = file.get_chunk(chunk_index);
170            let chunk = chunk.read();
171            let len = chunk.get_length() as u64;
172            if start < len {
173                chunk_offset = start as usize;
174                break;
175            }
176            start -= len;
177            chunk_index += 1;
178        }
179
180        FileRangeReference {
181            file: self.file.clone(),
182            start_chunk: chunk_index,
183            start_chunk_offset: chunk_offset,
184            bytes_count: file_range.end as usize - file_range.start as usize,
185        }
186    }
187
188    // pub fn get_typed_chunks_mut<T>(&mut self) -> Option<impl Iterator<Item = &mut [T]>> {
189    //     todo!();
190    //     Some((0..1).into_iter().map(|_| &mut [0, 1][..]))
191    // }
192}
193
194impl Read for FileReader {
195    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
196        let mut bytes_written = 0;
197
198        while bytes_written != buf.len() {
199            if self.current_len == 0 {
200                self.current_chunk_index += 1;
201                if self.current_chunk_index >= self.chunks_count {
202                    // End of file
203                    return Ok(bytes_written);
204                }
205                self.set_chunk_info(self.current_chunk_index);
206            }
207
208            let file = self.file.read();
209            let underlying_file = file.get_underlying_file();
210
211            let copyable_bytes = buf.len() - bytes_written;
212
213            let copyable_bytes = if self.is_on_disk && copyable_bytes < MIN_UNBUFFERED_READ {
214                let buffer = self.buffer.as_mut().unwrap();
215                let copyable_bytes = buffer.read_bytes(&mut buf[bytes_written..], |buffer| {
216                    let read_amount = self.current_chunk_ref.as_ref().unwrap().read_at(
217                        underlying_file,
218                        self.buffer_position as u64,
219                        buffer,
220                    )?;
221                    self.buffer_position += read_amount;
222                    Ok(read_amount)
223                });
224                copyable_bytes
225            } else {
226                let copyable_bytes = self.current_chunk_ref.as_ref().unwrap().read_at(
227                    underlying_file,
228                    self.current_position as u64,
229                    &mut buf[bytes_written..],
230                )?;
231                self.buffer
232                    .as_mut()
233                    .map(|b| self.buffer_position += b.discard(copyable_bytes));
234                copyable_bytes
235            };
236
237            self.current_position += copyable_bytes;
238            self.current_len -= copyable_bytes;
239            self.current_file_position += copyable_bytes;
240            bytes_written += copyable_bytes;
241        }
242
243        Ok(bytes_written)
244    }
245
246    #[inline(always)]
247    fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
248        match self.read(buf) {
249            Ok(count) => {
250                if count == buf.len() {
251                    Ok(())
252                } else {
253                    Err(io::Error::new(
254                        io::ErrorKind::Other,
255                        "Unexpected error while reading",
256                    ))
257                }
258            }
259            Err(err) => Err(err),
260        }
261    }
262}
263
264impl Seek for FileReader {
265    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
266        match pos {
267            SeekFrom::Start(mut offset) => {
268                let mut chunk_idx = 0;
269
270                let file = self.file.read();
271                while chunk_idx < self.chunks_count {
272                    let len = file.get_chunk(chunk_idx).read().get_length();
273                    if offset < (len as u64) {
274                        break;
275                    }
276                    chunk_idx += 1;
277                    offset -= len as u64;
278                }
279
280                if chunk_idx == self.chunks_count {
281                    return Err(std::io::Error::new(
282                        ErrorKind::UnexpectedEof,
283                        "Unexpected eof",
284                    ));
285                }
286
287                self.current_chunk_index = chunk_idx;
288                drop(file);
289                self.set_chunk_info(chunk_idx);
290
291                self.current_position += offset as usize;
292                self.buffer
293                    .as_mut()
294                    .map(|b| self.buffer_position += b.discard(offset as usize));
295                self.current_len -= offset as usize;
296                self.current_file_position = offset as usize;
297
298                return Ok(offset);
299            }
300            SeekFrom::Current(offset) => {
301                assert!(offset >= 0); // < 0  not supported yet
302                let mut offset = offset as usize;
303                loop {
304                    let clen_offset = offset.min(self.current_len);
305                    offset -= clen_offset;
306                    self.current_len -= clen_offset;
307                    self.current_position += clen_offset;
308                    self.buffer
309                        .as_mut()
310                        .map(|b| self.buffer_position += b.discard(clen_offset as usize));
311                    self.current_file_position += clen_offset;
312
313                    if offset == 0 {
314                        break Ok(self.current_file_position as u64);
315                    }
316
317                    if self.current_chunk_index >= self.chunks_count - 1 {
318                        break Err(std::io::Error::new(
319                            ErrorKind::UnexpectedEof,
320                            "Unexpected eof",
321                        ));
322                    }
323
324                    self.current_chunk_index += 1;
325                    self.set_chunk_info(self.current_chunk_index);
326                }
327            }
328            _ => {
329                unimplemented!()
330            }
331        }
332    }
333
334    fn stream_position(&mut self) -> io::Result<u64> {
335        let mut position = 0;
336
337        let file_read = self.file.read();
338
339        for i in 0..self.current_chunk_index {
340            position += file_read.get_chunk(i).read().get_length();
341        }
342
343        position += file_read
344            .get_chunk(self.current_chunk_index)
345            .read()
346            .get_length()
347            - self.current_len;
348
349        Ok(position as u64)
350    }
351}