1#include <IO/WriteBufferFromTemporaryFile.h>
2#include <IO/ReadBufferFromFile.h>
3
4#include <fcntl.h>
5
6
7namespace DB
8{
9
10namespace ErrorCodes
11{
12 extern const int CANNOT_OPEN_FILE;
13 extern const int CANNOT_SEEK_THROUGH_FILE;
14}
15
16
17WriteBufferFromTemporaryFile::WriteBufferFromTemporaryFile(std::unique_ptr<TemporaryFile> && tmp_file_)
18 : WriteBufferFromFile(tmp_file_->path(), DBMS_DEFAULT_BUFFER_SIZE, O_RDWR | O_TRUNC | O_CREAT, 0600), tmp_file(std::move(tmp_file_))
19{}
20
21
22WriteBufferFromTemporaryFile::Ptr WriteBufferFromTemporaryFile::create(const std::string & tmp_dir)
23{
24 return Ptr{new WriteBufferFromTemporaryFile(createTemporaryFile(tmp_dir))};
25}
26
27
28class ReadBufferFromTemporaryWriteBuffer : public ReadBufferFromFile
29{
30public:
31 static ReadBufferPtr createFrom(WriteBufferFromTemporaryFile * origin)
32 {
33 int fd = origin->getFD();
34 std::string file_name = origin->getFileName();
35
36 off_t res = lseek(fd, 0, SEEK_SET);
37 if (-1 == res)
38 throwFromErrnoWithPath("Cannot reread temporary file " + file_name, file_name,
39 ErrorCodes::CANNOT_SEEK_THROUGH_FILE);
40
41 return std::make_shared<ReadBufferFromTemporaryWriteBuffer>(fd, file_name, std::move(origin->tmp_file));
42 }
43
44 ReadBufferFromTemporaryWriteBuffer(int fd_, const std::string & file_name_, std::unique_ptr<TemporaryFile> && tmp_file_)
45 : ReadBufferFromFile(fd_, file_name_), tmp_file(std::move(tmp_file_))
46 {}
47
48 std::unique_ptr<TemporaryFile> tmp_file;
49};
50
51
52ReadBufferPtr WriteBufferFromTemporaryFile::getReadBufferImpl()
53{
54 /// ignore buffer, write all data to file and reread it
55 next();
56
57 auto res = ReadBufferFromTemporaryWriteBuffer::createFrom(this);
58
59 /// invalidate FD to avoid close(fd) in destructor
60 setFD(-1);
61 file_name = {};
62
63 return res;
64}
65
66
67WriteBufferFromTemporaryFile::~WriteBufferFromTemporaryFile() = default;
68
69
70}
71