]> git.proxmox.com Git - ceph.git/blame - ceph/src/compressor/zlib/ZlibCompressor.cc
update sources to v12.1.1
[ceph.git] / ceph / src / compressor / zlib / ZlibCompressor.cc
CommitLineData
7c673cae
FG
1/*
2 * Ceph - scalable distributed file system
3 *
4 * Copyright (C) 2015 Mirantis, Inc.
5 *
6 * Author: Alyona Kiseleva <akiselyova@mirantis.com>
7 *
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.
12 *
13 */
14
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// -----------------------------------------------------------------------------
21
22#include <zlib.h>
23
24// -----------------------------------------------------------------------------
224ce89b 25#define dout_context cct
7c673cae
FG
26#define dout_subsys ceph_subsys_compressor
27#undef dout_prefix
28#define dout_prefix _prefix(_dout)
29// -----------------------------------------------------------------------------
30
31// -----------------------------------------------------------------------------
32
33static ostream&
34_prefix(std::ostream* _dout)
35{
36 return *_dout << "ZlibCompressor: ";
37}
38// -----------------------------------------------------------------------------
39
40#define MAX_LEN (CEPH_PAGE_SIZE)
41
42// default window size for Zlib 1.2.8, negated for raw deflate
43#define ZLIB_DEFAULT_WIN_SIZE -15
44
45// desired memory usage level. increasing to 9 doesn't speed things up
46// significantly (helps only on >=16K blocks) and sometimes degrades
47// compression ratio.
48#define ZLIB_MEMORY_LEVEL 8
49
50int ZlibCompressor::zlib_compress(const bufferlist &in, bufferlist &out)
51{
52 int ret;
53 unsigned have;
54 z_stream strm;
55 unsigned char* c_in;
56 int begin = 1;
57
58 /* allocate deflate state */
59 strm.zalloc = Z_NULL;
60 strm.zfree = Z_NULL;
61 strm.opaque = Z_NULL;
224ce89b 62 ret = deflateInit2(&strm, cct->_conf->compressor_zlib_level, Z_DEFLATED, ZLIB_DEFAULT_WIN_SIZE, ZLIB_MEMORY_LEVEL, Z_DEFAULT_STRATEGY);
7c673cae
FG
63 if (ret != Z_OK) {
64 dout(1) << "Compression init error: init return "
65 << ret << " instead of Z_OK" << dendl;
66 return -1;
67 }
68
69 for (std::list<buffer::ptr>::const_iterator i = in.buffers().begin();
70 i != in.buffers().end();) {
71
72 c_in = (unsigned char*) (*i).c_str();
73 long unsigned int len = (*i).length();
74 ++i;
75
76 strm.avail_in = len;
77 int flush = i != in.buffers().end() ? Z_NO_FLUSH : Z_FINISH;
78
79 strm.next_in = c_in;
80 do {
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;
84 if (begin) {
85 // put a compressor variation mark in front of compressed stream, not used at the moment
86 ptr.c_str()[0] = 0;
87 begin = 0;
88 }
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;
93 deflateEnd(&strm);
94 return -1;
95 }
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;
101 deflateEnd(&strm);
102 return -1;
103 }
104 }
105
106 deflateEnd(&strm);
107 return 0;
108}
109
110#if __x86_64__ && defined(HAVE_BETTER_YASM_ELF64)
111int ZlibCompressor::isal_compress(const bufferlist &in, bufferlist &out)
112{
113 int ret;
114 unsigned have;
115 isal_zstream strm;
116 unsigned char* c_in;
117 int begin = 1;
118
119 /* allocate deflate state */
120 isal_deflate_init(&strm);
121 strm.end_of_stream = 0;
122
123 for (std::list<buffer::ptr>::const_iterator i = in.buffers().begin();
124 i != in.buffers().end();) {
125
126 c_in = (unsigned char*) (*i).c_str();
127 long unsigned int len = (*i).length();
128 ++i;
129
130 strm.avail_in = len;
131 strm.end_of_stream = (i == in.buffers().end());
132 strm.flush = FINISH_FLUSH;
133
134 strm.next_in = c_in;
135
136 do {
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;
140 if (begin) {
141 // put a compressor variation mark in front of compressed stream, not used at the moment
142 ptr.c_str()[0] = 1;
143 begin = 0;
144 }
145 ret = isal_deflate(&strm);
146 if (ret != COMP_OK) {
147 dout(1) << "Compression error: isal_deflate return error ("
148 << ret << ")" << dendl;
149 return -1;
150 }
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;
156 return -1;
157 }
158 }
159
160 return 0;
161}
162#endif
163
164int ZlibCompressor::compress(const bufferlist &in, bufferlist &out)
165{
166#if __x86_64__ && defined(HAVE_BETTER_YASM_ELF64)
167 if (isal_enabled)
168 return isal_compress(in, out);
169 else
170 return zlib_compress(in, out);
171#else
172 return zlib_compress(in, out);
173#endif
174}
175
176int ZlibCompressor::decompress(bufferlist::iterator &p, size_t compressed_size, bufferlist &out)
177{
178 int ret;
179 unsigned have;
180 z_stream strm;
181 const char* c_in;
182 int begin = 1;
183
184 /* allocate inflate state */
185 strm.zalloc = Z_NULL;
186 strm.zfree = Z_NULL;
187 strm.opaque = Z_NULL;
188 strm.avail_in = 0;
189 strm.next_in = Z_NULL;
190
191 // choose the variation of compressor
192 ret = inflateInit2(&strm, ZLIB_DEFAULT_WIN_SIZE);
193 if (ret != Z_OK) {
194 dout(1) << "Decompression init error: init return "
195 << ret << " instead of Z_OK" << dendl;
196 return -1;
197 }
198
199 size_t remaining = MIN(p.get_remaining(), compressed_size);
200
201 while(remaining) {
202 long unsigned int len = p.get_ptr_and_advance(remaining, &c_in);
203 remaining -= len;
204 strm.avail_in = len - begin;
205 strm.next_in = (unsigned char*)c_in + begin;
206 begin = 0;
207
208 do {
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 "
215 << ret << dendl;
216 inflateEnd(&strm);
217 return -1;
218 }
219 have = MAX_LEN - strm.avail_out;
220 out.append(ptr, 0, have);
221 } while (strm.avail_out == 0);
222 }
223
224 /* clean up and return */
225 (void)inflateEnd(&strm);
226 return 0;
227}
228
229int ZlibCompressor::decompress(const bufferlist &in, bufferlist &out)
230{
231 bufferlist::iterator i = const_cast<bufferlist&>(in).begin();
232 return decompress(i, in.length(), out);
233}