1#include "duckdb/common/serializer/buffered_file_writer.hpp"
2#include "duckdb/common/exception.hpp"
3#include "duckdb/common/algorithm.hpp"
4#include <cstring>
5
6namespace duckdb {
7
8// Remove this when we switch C++17: https://stackoverflow.com/a/53350948
9constexpr uint8_t BufferedFileWriter::DEFAULT_OPEN_FLAGS;
10
11BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path_p, uint8_t open_flags)
12 : fs(fs), path(path_p), data(make_unsafe_uniq_array<data_t>(FILE_BUFFER_SIZE)), offset(0), total_written(0) {
13 handle = fs.OpenFile(path, flags: open_flags, lock: FileLockType::WRITE_LOCK);
14}
15
16int64_t BufferedFileWriter::GetFileSize() {
17 return fs.GetFileSize(handle&: *handle) + offset;
18}
19
20idx_t BufferedFileWriter::GetTotalWritten() {
21 return total_written + offset;
22}
23
24void BufferedFileWriter::WriteData(const_data_ptr_t buffer, uint64_t write_size) {
25 // first copy anything we can from the buffer
26 const_data_ptr_t end_ptr = buffer + write_size;
27 while (buffer < end_ptr) {
28 idx_t to_write = MinValue<idx_t>(a: (end_ptr - buffer), FILE_BUFFER_SIZE - offset);
29 D_ASSERT(to_write > 0);
30 memcpy(dest: data.get() + offset, src: buffer, n: to_write);
31 offset += to_write;
32 buffer += to_write;
33 if (offset == FILE_BUFFER_SIZE) {
34 Flush();
35 }
36 }
37}
38
39void BufferedFileWriter::Flush() {
40 if (offset == 0) {
41 return;
42 }
43 fs.Write(handle&: *handle, buffer: data.get(), nr_bytes: offset);
44 total_written += offset;
45 offset = 0;
46}
47
48void BufferedFileWriter::Sync() {
49 Flush();
50 handle->Sync();
51}
52
53void BufferedFileWriter::Truncate(int64_t size) {
54 uint64_t persistent = fs.GetFileSize(handle&: *handle);
55 D_ASSERT((uint64_t)size <= persistent + offset);
56 if (persistent <= (uint64_t)size) {
57 // truncating into the pending write buffer.
58 offset = size - persistent;
59 } else {
60 // truncate the physical file on disk
61 handle->Truncate(new_size: size);
62 // reset anything written in the buffer
63 offset = 0;
64 }
65}
66
67} // namespace duckdb
68