2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/WriteBufferFromTemporaryFile.h>
|
|
|
|
#include <IO/ReadBufferFromFile.h>
|
2017-02-22 15:29:43 +00:00
|
|
|
|
|
|
|
#include <Poco/Path.h>
|
2017-03-27 12:40:08 +00:00
|
|
|
#include <fcntl.h>
|
2017-02-22 15:29:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int CANNOT_OPEN_FILE;
|
|
|
|
extern const int CANNOT_SEEK_THROUGH_FILE;
|
2017-02-22 15:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-27 12:40:08 +00:00
|
|
|
WriteBufferFromTemporaryFile::WriteBufferFromTemporaryFile(std::unique_ptr<Poco::TemporaryFile> && tmp_file_)
|
2019-01-07 10:40:58 +00:00
|
|
|
: WriteBufferFromFile(tmp_file_->path(), DBMS_DEFAULT_BUFFER_SIZE, O_RDWR | O_TRUNC | O_CREAT, 0600), tmp_file(std::move(tmp_file_))
|
2017-03-27 12:40:08 +00:00
|
|
|
{}
|
2017-02-22 15:29:43 +00:00
|
|
|
|
|
|
|
|
2017-03-27 12:40:08 +00:00
|
|
|
WriteBufferFromTemporaryFile::Ptr WriteBufferFromTemporaryFile::create(const std::string & tmp_dir)
|
2017-02-22 15:29:43 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
Poco::File(tmp_dir).createDirectories();
|
2017-03-27 12:40:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/// NOTE: std::make_shared cannot use protected constructors
|
|
|
|
return Ptr{new WriteBufferFromTemporaryFile(std::make_unique<Poco::TemporaryFile>(tmp_dir))};
|
2017-02-22 15:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class ReadBufferFromTemporaryWriteBuffer : public ReadBufferFromFile
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static ReadBufferPtr createFrom(WriteBufferFromTemporaryFile * origin)
|
|
|
|
{
|
|
|
|
int fd = origin->getFD();
|
|
|
|
std::string file_name = origin->getFileName();
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
off_t res = lseek(fd, 0, SEEK_SET);
|
|
|
|
if (-1 == res)
|
|
|
|
throwFromErrno("Cannot reread temporary file " + file_name, ErrorCodes::CANNOT_SEEK_THROUGH_FILE);
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return std::make_shared<ReadBufferFromTemporaryWriteBuffer>(fd, file_name, std::move(origin->tmp_file));
|
|
|
|
}
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2019-01-07 10:40:58 +00:00
|
|
|
ReadBufferFromTemporaryWriteBuffer(int fd_, const std::string & file_name_, std::unique_ptr<Poco::TemporaryFile> && tmp_file_)
|
|
|
|
: ReadBufferFromFile(fd_, file_name_), tmp_file(std::move(tmp_file_))
|
2017-04-01 07:20:54 +00:00
|
|
|
{}
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
std::unique_ptr<Poco::TemporaryFile> tmp_file;
|
2017-02-22 15:29:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-02-28 14:15:13 +00:00
|
|
|
ReadBufferPtr WriteBufferFromTemporaryFile::getReadBufferImpl()
|
2017-02-22 15:29:43 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
/// ignore buffer, write all data to file and reread it
|
|
|
|
next();
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
auto res = ReadBufferFromTemporaryWriteBuffer::createFrom(this);
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/// invalidate FD to avoid close(fd) in destructor
|
|
|
|
setFD(-1);
|
|
|
|
file_name = {};
|
2017-02-22 15:29:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return res;
|
2017-02-22 15:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-27 12:40:08 +00:00
|
|
|
WriteBufferFromTemporaryFile::~WriteBufferFromTemporaryFile() = default;
|
|
|
|
|
|
|
|
|
2017-02-22 15:29:43 +00:00
|
|
|
}
|