aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@ydb.tech>2023-11-14 09:58:56 +0300
committervitalyisaev <vitalyisaev@ydb.tech>2023-11-14 10:20:20 +0300
commitc2b2dfd9827a400a8495e172a56343462e3ceb82 (patch)
treecd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h
parentd4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (diff)
downloadydb-c2b2dfd9827a400a8495e172a56343462e3ceb82.tar.gz
YQ Connector: move tests from yql to ydb (OSS)
Перенос папки с тестами на Коннектор из папки yql в папку ydb (синхронизируется с github).
Diffstat (limited to 'contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h')
-rw-r--r--contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h84
1 files changed, 84 insertions, 0 deletions
diff --git a/contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h b/contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h
new file mode 100644
index 0000000000..d9c4f32d6d
--- /dev/null
+++ b/contrib/clickhouse/src/IO/ZstdDeflatingAppendableWriteBuffer.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#include <IO/BufferWithOwnMemory.h>
+#include <IO/CompressionMethod.h>
+#include <IO/WriteBuffer.h>
+#include <IO/WriteBufferDecorator.h>
+#include <IO/WriteBufferFromFile.h>
+#include <IO/ReadBufferFromFileBase.h>
+
+#include <zstd.h>
+
+
+namespace DB
+{
+
+/// Performs stream compression using zstd library and writes compressed data to out_ WriteBuffer.
+/// Main differences from ZstdDeflatingWriteBuffer:
+/// 1) Allows to continue to write to the same output even if finalize() (or destructor) was not called, for example
+/// when server was killed with 9 signal. Natively zstd doesn't support such feature because
+/// ZSTD_decompressStream expect to see empty block (3 bytes 0x01, 0x00, 0x00) at the end of each frame. There is not API function for it
+/// so we just use HACK and add empty block manually on the first write (see addEmptyBlock). Maintainers of zstd
+/// said that there is no risks of compatibility issues https://github.com/facebook/zstd/issues/2090#issuecomment-620158967.
+/// 2) Doesn't support internal ZSTD check-summing, because ZSTD checksums written at the end of frame (frame epilogue).
+///
+class ZstdDeflatingAppendableWriteBuffer : public BufferWithOwnMemory<WriteBuffer>
+{
+public:
+ using ZSTDLastBlock = const std::array<char, 3>;
+ /// Frame end block. If we read non-empty file and see no such flag we should add it.
+ static inline constexpr ZSTDLastBlock ZSTD_CORRECT_TERMINATION_LAST_BLOCK = {0x01, 0x00, 0x00};
+
+ ZstdDeflatingAppendableWriteBuffer(
+ std::unique_ptr<WriteBufferFromFileBase> out_,
+ int compression_level,
+ bool append_to_existing_file_,
+ std::function<std::unique_ptr<ReadBufferFromFileBase>()> read_buffer_creator_,
+ size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE,
+ char * existing_memory = nullptr,
+ size_t alignment = 0);
+
+ ~ZstdDeflatingAppendableWriteBuffer() override;
+
+ void sync() override
+ {
+ next();
+ out->sync();
+ }
+
+ WriteBuffer * getNestedBuffer() { return out.get(); }
+
+private:
+ /// NOTE: will fill compressed data to the out.working_buffer, but will not call out.next method until the buffer is full
+ void nextImpl() override;
+
+ /// Write terminating ZSTD_e_end: empty block + frame epilogue. BTW it
+ /// should be almost noop, because frame epilogue contains only checksums,
+ /// and they are disabled for this buffer.
+ /// Flush all pending data and write zstd footer to the underlying buffer.
+ /// After the first call to this function, subsequent calls will have no effect and
+ /// an attempt to write to this buffer will result in exception.
+ void finalizeImpl() override;
+ void finalizeBefore();
+ void finalizeAfter();
+ void finalizeZstd();
+
+ /// Read three last bytes from non-empty compressed file and compares them with
+ /// ZSTD_CORRECT_TERMINATION_LAST_BLOCK.
+ bool isNeedToAddEmptyBlock();
+
+ /// Adding zstd empty block (ZSTD_CORRECT_TERMINATION_LAST_BLOCK) to out.working_buffer
+ void addEmptyBlock();
+
+ std::unique_ptr<WriteBufferFromFileBase> out;
+ std::function<std::unique_ptr<ReadBufferFromFileBase>()> read_buffer_creator;
+
+ bool append_to_existing_file = false;
+ ZSTD_CCtx * cctx;
+ ZSTD_inBuffer input;
+ ZSTD_outBuffer output;
+ /// Flipped on the first nextImpl call
+ bool first_write = true;
+};
+
+}