]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2015 Haomai Wang <haomaiwang@gmail.com> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef CEPH_ZSTDCOMPRESSOR_H | |
16 | #define CEPH_ZSTDCOMPRESSOR_H | |
17 | ||
11fdf7f2 | 18 | #define ZSTD_STATIC_LINKING_ONLY |
7c673cae | 19 | #include "zstd/lib/zstd.h" |
11fdf7f2 | 20 | |
7c673cae FG |
21 | #include "include/buffer.h" |
22 | #include "include/encoding.h" | |
23 | #include "compressor/Compressor.h" | |
24 | ||
25 | #define COMPRESSION_LEVEL 5 | |
26 | ||
27 | class ZstdCompressor : public Compressor { | |
28 | public: | |
29 | ZstdCompressor() : Compressor(COMP_ALG_ZSTD, "zstd") {} | |
30 | ||
31 | int compress(const bufferlist &src, bufferlist &dst) override { | |
11fdf7f2 TL |
32 | ZSTD_CStream *s = ZSTD_createCStream(); |
33 | ZSTD_initCStream_srcSize(s, COMPRESSION_LEVEL, src.length()); | |
34 | auto p = src.begin(); | |
35 | size_t left = src.length(); | |
36 | ||
37 | size_t const out_max = ZSTD_compressBound(left); | |
38 | bufferptr outptr = buffer::create_small_page_aligned(out_max); | |
7c673cae FG |
39 | ZSTD_outBuffer_s outbuf; |
40 | outbuf.dst = outptr.c_str(); | |
41 | outbuf.size = outptr.length(); | |
42 | outbuf.pos = 0; | |
43 | ||
7c673cae | 44 | while (left) { |
11fdf7f2 | 45 | ceph_assert(!p.end()); |
7c673cae FG |
46 | struct ZSTD_inBuffer_s inbuf; |
47 | inbuf.pos = 0; | |
48 | inbuf.size = p.get_ptr_and_advance(left, (const char**)&inbuf.src); | |
7c673cae | 49 | left -= inbuf.size; |
11fdf7f2 | 50 | ZSTD_EndDirective const zed = (left==0) ? ZSTD_e_end : ZSTD_e_continue; |
9f95a23c | 51 | size_t r = ZSTD_compressStream2(s, &outbuf, &inbuf, zed); |
11fdf7f2 TL |
52 | if (ZSTD_isError(r)) { |
53 | return -EINVAL; | |
54 | } | |
7c673cae | 55 | } |
11fdf7f2 TL |
56 | ceph_assert(p.end()); |
57 | ||
7c673cae FG |
58 | ZSTD_freeCStream(s); |
59 | ||
60 | // prefix with decompressed length | |
11fdf7f2 | 61 | encode((uint32_t)src.length(), dst); |
7c673cae FG |
62 | dst.append(outptr, 0, outbuf.pos); |
63 | return 0; | |
64 | } | |
65 | ||
66 | int decompress(const bufferlist &src, bufferlist &dst) override { | |
11fdf7f2 | 67 | auto i = std::cbegin(src); |
7c673cae FG |
68 | return decompress(i, src.length(), dst); |
69 | } | |
70 | ||
11fdf7f2 | 71 | int decompress(bufferlist::const_iterator &p, |
7c673cae FG |
72 | size_t compressed_len, |
73 | bufferlist &dst) override { | |
74 | if (compressed_len < 4) { | |
75 | return -1; | |
76 | } | |
77 | compressed_len -= 4; | |
78 | uint32_t dst_len; | |
11fdf7f2 | 79 | decode(dst_len, p); |
7c673cae FG |
80 | |
81 | bufferptr dstptr(dst_len); | |
82 | ZSTD_outBuffer_s outbuf; | |
83 | outbuf.dst = dstptr.c_str(); | |
84 | outbuf.size = dstptr.length(); | |
85 | outbuf.pos = 0; | |
86 | ZSTD_DStream *s = ZSTD_createDStream(); | |
87 | ZSTD_initDStream(s); | |
88 | while (compressed_len > 0) { | |
89 | if (p.end()) { | |
90 | return -1; | |
91 | } | |
92 | ZSTD_inBuffer_s inbuf; | |
93 | inbuf.pos = 0; | |
11fdf7f2 TL |
94 | inbuf.size = p.get_ptr_and_advance(compressed_len, |
95 | (const char**)&inbuf.src); | |
7c673cae FG |
96 | ZSTD_decompressStream(s, &outbuf, &inbuf); |
97 | compressed_len -= inbuf.size; | |
98 | } | |
99 | ZSTD_freeDStream(s); | |
100 | ||
101 | dst.append(dstptr, 0, outbuf.pos); | |
102 | return 0; | |
103 | } | |
104 | }; | |
105 | ||
106 | #endif |