Created
November 11, 2017 09:23
-
-
Save Cyan4973/1d1d104b64f5903fc6200f0712ff570a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- | |
// vim: ts=8 sw=2 smarttab | |
/* | |
* Ceph - scalable distributed file system | |
* | |
* Copyright (C) 2015 Haomai Wang <[email protected]> | |
* | |
* This is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
* License version 2.1, as published by the Free Software | |
* Foundation. See file COPYING. | |
* | |
*/ | |
#ifndef CEPH_ZSTDCOMPRESSOR_H | |
#define CEPH_ZSTDCOMPRESSOR_H | |
#define ZSTD_STATIC_LINKING_ONLY | |
#include "zstd/lib/zstd.h" | |
#include "include/buffer.h" | |
#include "include/encoding.h" | |
#include "compressor/Compressor.h" | |
#define COMPRESSION_LEVEL 2 | |
#define ZSTD_CHECK(f) { \ | |
size_t const r = f; \ | |
if (ZSTD_isError(r)) return -EINVAL; \ | |
} | |
class ZstdCompressor : public Compressor { | |
public: | |
ZSTD_CStream* cctx; | |
/* ZSTD_DStream* could be here too */ | |
ZstdCompressor() : Compressor(COMP_ALG_ZSTD, "zstd") { | |
cctx = NULL; | |
} | |
~ZstdCompressor() { | |
ZSTD_freeCStream(cctx); | |
} | |
int compress(const bufferlist &src, bufferlist &dst) override { | |
if (cctx==NULL) cctx = ZSTD_createCStream(); | |
if (cctx==NULL) return -EINVAL; | |
ZSTD_CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, COMPRESSION_LEVEL) ); | |
ZSTD_CHECK( ZSTD_CCtx_setPledgedSrcSize(cctx, src.length()) ); | |
auto p = src.begin(); | |
size_t left = src.length(); | |
size_t const neededOutSize = ZSTD_compressBound(left); | |
bufferptr outptr = buffer::create_page_aligned(neededOutSize); | |
ZSTD_outBuffer_s outbuf; | |
outbuf.dst = outptr.c_str(); | |
outbuf.size = outptr.length(); | |
outbuf.pos = 0; | |
while (left) { | |
assert(!p.end()); | |
struct ZSTD_inBuffer_s inbuf; | |
inbuf.pos = 0; | |
inbuf.size = p.get_ptr_and_advance(left, (const char**)&inbuf.src); | |
left -= inbuf.size; | |
ZSTD_EndDirective const zed = (left==0) ? ZSTD_e_end : ZSTD_e_continue; | |
ZSTD_CHECK( ZSTD_compress_generic(cctx, &outbuf, &inbuf, zed) ); | |
} | |
assert(p.end()); | |
// prefix with decompressed length | |
::encode((uint32_t)src.length(), dst); | |
dst.append(outptr, 0, outbuf.pos); | |
return 0; | |
} | |
int decompress(const bufferlist &src, bufferlist &dst) override { | |
bufferlist::iterator i = const_cast<bufferlist&>(src).begin(); | |
return decompress(i, src.length(), dst); | |
} | |
int decompress(bufferlist::iterator &p, | |
size_t compressed_len, | |
bufferlist &dst) override { | |
if (compressed_len < 4) { | |
return -1; | |
} | |
compressed_len -= 4; | |
uint32_t dst_len; | |
::decode(dst_len, p); | |
bufferptr dstptr(dst_len); | |
ZSTD_outBuffer_s outbuf; | |
outbuf.dst = dstptr.c_str(); | |
outbuf.size = dstptr.length(); | |
outbuf.pos = 0; | |
ZSTD_DStream* const s = ZSTD_createDStream(); /* should check result != NULL */ | |
ZSTD_initDStream(s); | |
while (compressed_len > 0) { | |
if (p.end()) { | |
return -1; | |
} | |
ZSTD_inBuffer_s inbuf; | |
inbuf.pos = 0; | |
inbuf.size = p.get_ptr_and_advance(compressed_len, | |
(const char**)&inbuf.src); | |
ZSTD_decompressStream(s, &outbuf, &inbuf); | |
compressed_len -= inbuf.size; | |
} | |
ZSTD_freeDStream(s); | |
dst.append(dstptr, 0, outbuf.pos); | |
return 0; | |
} | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment