1 | #include "duckdb/common/serializer/buffered_file_reader.hpp" |
2 | #include "duckdb/common/serializer/buffered_file_writer.hpp" |
3 | #include "duckdb/common/exception.hpp" |
4 | |
5 | #include <cstring> |
6 | #include <algorithm> |
7 | |
8 | namespace duckdb { |
9 | |
10 | BufferedFileReader::BufferedFileReader(FileSystem &fs, const char *path, optional_ptr<ClientContext> context, |
11 | FileLockType lock_type, optional_ptr<FileOpener> opener) |
12 | : fs(fs), data(make_unsafe_uniq_array<data_t>(FILE_BUFFER_SIZE)), offset(0), read_data(0), total_read(0), |
13 | context(context) { |
14 | handle = fs.OpenFile(path, flags: FileFlags::FILE_FLAGS_READ, lock: lock_type, compression: FileSystem::DEFAULT_COMPRESSION, opener: opener.get()); |
15 | file_size = fs.GetFileSize(handle&: *handle); |
16 | } |
17 | |
18 | void BufferedFileReader::ReadData(data_ptr_t target_buffer, uint64_t read_size) { |
19 | // first copy anything we can from the buffer |
20 | data_ptr_t end_ptr = target_buffer + read_size; |
21 | while (true) { |
22 | idx_t to_read = MinValue<idx_t>(a: end_ptr - target_buffer, b: read_data - offset); |
23 | if (to_read > 0) { |
24 | memcpy(dest: target_buffer, src: data.get() + offset, n: to_read); |
25 | offset += to_read; |
26 | target_buffer += to_read; |
27 | } |
28 | if (target_buffer < end_ptr) { |
29 | D_ASSERT(offset == read_data); |
30 | total_read += read_data; |
31 | // did not finish reading yet but exhausted buffer |
32 | // read data into buffer |
33 | offset = 0; |
34 | read_data = fs.Read(handle&: *handle, buffer: data.get(), FILE_BUFFER_SIZE); |
35 | if (read_data == 0) { |
36 | throw SerializationException("not enough data in file to deserialize result" ); |
37 | } |
38 | } else { |
39 | return; |
40 | } |
41 | } |
42 | } |
43 | |
44 | bool BufferedFileReader::Finished() { |
45 | return total_read + offset == file_size; |
46 | } |
47 | |
48 | void BufferedFileReader::Seek(uint64_t location) { |
49 | D_ASSERT(location <= file_size); |
50 | handle->Seek(location); |
51 | total_read = location; |
52 | read_data = offset = 0; |
53 | } |
54 | |
55 | uint64_t BufferedFileReader::CurrentOffset() { |
56 | return total_read + offset; |
57 | } |
58 | |
59 | ClientContext &BufferedFileReader::GetContext() { |
60 | if (!context) { |
61 | throw InternalException("Trying to acquire a client context that does not exist" ); |
62 | } |
63 | return *context; |
64 | } |
65 | |
66 | optional_ptr<Catalog> BufferedFileReader::GetCatalog() { |
67 | return catalog; |
68 | } |
69 | |
70 | void BufferedFileReader::SetCatalog(Catalog &catalog_p) { |
71 | D_ASSERT(!catalog); |
72 | this->catalog = &catalog_p; |
73 | } |
74 | |
75 | } // namespace duckdb |
76 | |