ClickHouse/dbms/include/DB/IO/CompressedWriteBuffer.h

88 lines
1.8 KiB
C
Raw Normal View History

2010-06-04 18:25:25 +00:00
#ifndef DBMS_COMMON_COMPRESSED_WRITEBUFFER_H
#define DBMS_COMMON_COMPRESSED_WRITEBUFFER_H
#include <vector>
#include <city.h>
2011-06-17 21:19:39 +00:00
#include <quicklz/quicklz_level1.h>
2010-06-04 18:25:25 +00:00
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/BufferWithOwnMemory.h>
2011-06-17 21:19:39 +00:00
#include <DB/IO/CompressedStream.h>
2010-06-04 18:25:25 +00:00
namespace DB
{
class CompressedWriteBuffer : public BufferWithOwnMemory<WriteBuffer>
2010-06-04 18:25:25 +00:00
{
private:
WriteBuffer & out;
std::vector<char> compressed_buffer;
2011-06-17 21:19:39 +00:00
char scratch[QLZ_SCRATCH_COMPRESS];
void nextImpl()
2010-06-04 18:25:25 +00:00
{
2011-06-27 19:34:03 +00:00
if (!offset())
return;
size_t uncompressed_size = offset();
compressed_buffer.resize(uncompressed_size + QUICKLZ_ADDITIONAL_SPACE);
2011-06-26 21:30:59 +00:00
2011-06-17 21:19:39 +00:00
size_t compressed_size = qlz_compress(
2011-05-13 19:40:56 +00:00
working_buffer.begin(),
&compressed_buffer[0],
uncompressed_size,
2011-06-17 21:19:39 +00:00
scratch);
2010-06-04 18:25:25 +00:00
uint128 checksum = CityHash128(&compressed_buffer[0], compressed_size);
out.write(reinterpret_cast<const char *>(&checksum), sizeof(checksum));
out.write(&compressed_buffer[0], compressed_size);
2011-05-05 19:10:17 +00:00
}
2011-06-26 21:30:59 +00:00
public:
CompressedWriteBuffer(WriteBuffer & out_) : out(out_) {}
2011-06-26 21:30:59 +00:00
/// Объём сжатых данных
2011-05-05 19:10:17 +00:00
size_t getCompressedBytes()
{
nextIfAtEnd();
return out.count();
2011-05-05 19:10:17 +00:00
}
/// Сколько несжатых байт было записано в буфер
2011-05-05 19:10:17 +00:00
size_t getUncompressedBytes()
{
return count();
}
/// Сколько байт находится в буфере (ещё не сжато)
size_t getRemainingBytes()
2011-05-05 19:10:17 +00:00
{
nextIfAtEnd();
return offset();
2010-06-04 18:25:25 +00:00
}
~CompressedWriteBuffer()
{
bool uncaught_exception = std::uncaught_exception();
try
{
next();
}
catch (...)
{
/// Если до этого уже было какое-то исключение, то второе исключение проигнорируем.
if (!uncaught_exception)
throw;
}
2010-06-04 18:25:25 +00:00
}
};
}
#endif