2 * Ceph - scalable distributed file system
4 * Copyright (C) 2015 Mirantis, Inc.
6 * Author: Alyona Kiseleva <akiselyova@mirantis.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
15 // -----------------------------------------------------------------------------
16 #include "common/debug.h"
17 #include "ZlibCompressor.h"
18 #include "osd/osd_types.h"
19 #include "isa-l/include/igzip_lib.h"
20 // -----------------------------------------------------------------------------
24 // -----------------------------------------------------------------------------
25 #define dout_context cct
26 #define dout_subsys ceph_subsys_compressor
28 #define dout_prefix _prefix(_dout)
29 // -----------------------------------------------------------------------------
31 // -----------------------------------------------------------------------------
34 _prefix(std::ostream* _dout)
36 return *_dout << "ZlibCompressor: ";
38 // -----------------------------------------------------------------------------
40 #define MAX_LEN (CEPH_PAGE_SIZE)
42 // default window size for Zlib 1.2.8, negated for raw deflate
43 #define ZLIB_DEFAULT_WIN_SIZE -15
45 // desired memory usage level. increasing to 9 doesn't speed things up
46 // significantly (helps only on >=16K blocks) and sometimes degrades
48 #define ZLIB_MEMORY_LEVEL 8
50 int ZlibCompressor::zlib_compress(const bufferlist &in, bufferlist &out)
58 /* allocate deflate state */
62 ret = deflateInit2(&strm, cct->_conf->compressor_zlib_level, Z_DEFLATED, ZLIB_DEFAULT_WIN_SIZE, ZLIB_MEMORY_LEVEL, Z_DEFAULT_STRATEGY);
64 dout(1) << "Compression init error: init return "
65 << ret << " instead of Z_OK" << dendl;
69 for (std::list<buffer::ptr>::const_iterator i = in.buffers().begin();
70 i != in.buffers().end();) {
72 c_in = (unsigned char*) (*i).c_str();
73 long unsigned int len = (*i).length();
77 int flush = i != in.buffers().end() ? Z_NO_FLUSH : Z_FINISH;
81 bufferptr ptr = buffer::create_page_aligned(MAX_LEN);
82 strm.next_out = (unsigned char*)ptr.c_str() + begin;
83 strm.avail_out = MAX_LEN - begin;
85 // put a compressor variation mark in front of compressed stream, not used at the moment
89 ret = deflate(&strm, flush); /* no bad return value */
90 if (ret == Z_STREAM_ERROR) {
91 dout(1) << "Compression error: compress return Z_STREAM_ERROR("
92 << ret << ")" << dendl;
96 have = MAX_LEN - strm.avail_out;
97 out.append(ptr, 0, have);
98 } while (strm.avail_out == 0);
99 if (strm.avail_in != 0) {
100 dout(10) << "Compression error: unused input" << dendl;
110 #if __x86_64__ && defined(HAVE_BETTER_YASM_ELF64)
111 int ZlibCompressor::isal_compress(const bufferlist &in, bufferlist &out)
119 /* allocate deflate state */
120 isal_deflate_init(&strm);
121 strm.end_of_stream = 0;
123 for (std::list<buffer::ptr>::const_iterator i = in.buffers().begin();
124 i != in.buffers().end();) {
126 c_in = (unsigned char*) (*i).c_str();
127 long unsigned int len = (*i).length();
131 strm.end_of_stream = (i == in.buffers().end());
132 strm.flush = FINISH_FLUSH;
137 bufferptr ptr = buffer::create_page_aligned(MAX_LEN);
138 strm.next_out = (unsigned char*)ptr.c_str() + begin;
139 strm.avail_out = MAX_LEN - begin;
141 // put a compressor variation mark in front of compressed stream, not used at the moment
145 ret = isal_deflate(&strm);
146 if (ret != COMP_OK) {
147 dout(1) << "Compression error: isal_deflate return error ("
148 << ret << ")" << dendl;
151 have = MAX_LEN - strm.avail_out;
152 out.append(ptr, 0, have);
153 } while (strm.avail_out == 0);
154 if (strm.avail_in != 0) {
155 dout(10) << "Compression error: unused input" << dendl;
164 int ZlibCompressor::compress(const bufferlist &in, bufferlist &out)
166 #if __x86_64__ && defined(HAVE_BETTER_YASM_ELF64)
168 return isal_compress(in, out);
170 return zlib_compress(in, out);
172 return zlib_compress(in, out);
176 int ZlibCompressor::decompress(bufferlist::iterator &p, size_t compressed_size, bufferlist &out)
184 /* allocate inflate state */
185 strm.zalloc = Z_NULL;
187 strm.opaque = Z_NULL;
189 strm.next_in = Z_NULL;
191 // choose the variation of compressor
192 ret = inflateInit2(&strm, ZLIB_DEFAULT_WIN_SIZE);
194 dout(1) << "Decompression init error: init return "
195 << ret << " instead of Z_OK" << dendl;
199 size_t remaining = MIN(p.get_remaining(), compressed_size);
202 long unsigned int len = p.get_ptr_and_advance(remaining, &c_in);
204 strm.avail_in = len - begin;
205 strm.next_in = (unsigned char*)c_in + begin;
209 strm.avail_out = MAX_LEN;
210 bufferptr ptr = buffer::create_page_aligned(MAX_LEN);
211 strm.next_out = (unsigned char*)ptr.c_str();
212 ret = inflate(&strm, Z_NO_FLUSH);
213 if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
214 dout(1) << "Decompression error: decompress return "
219 have = MAX_LEN - strm.avail_out;
220 out.append(ptr, 0, have);
221 } while (strm.avail_out == 0);
224 /* clean up and return */
225 (void)inflateEnd(&strm);
229 int ZlibCompressor::decompress(const bufferlist &in, bufferlist &out)
231 bufferlist::iterator i = const_cast<bufferlist&>(in).begin();
232 return decompress(i, in.length(), out);