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
8namespace duckdb {
9
10BufferedFileReader::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
18void 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
44bool BufferedFileReader::Finished() {
45 return total_read + offset == file_size;
46}
47
48void 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
55uint64_t BufferedFileReader::CurrentOffset() {
56 return total_read + offset;
57}
58
59ClientContext &BufferedFileReader::GetContext() {
60 if (!context) {
61 throw InternalException("Trying to acquire a client context that does not exist");
62 }
63 return *context;
64}
65
66optional_ptr<Catalog> BufferedFileReader::GetCatalog() {
67 return catalog;
68}
69
70void BufferedFileReader::SetCatalog(Catalog &catalog_p) {
71 D_ASSERT(!catalog);
72 this->catalog = &catalog_p;
73}
74
75} // namespace duckdb
76