1 /* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef COMPRESSION_BASE_INCLUDED
24 #define COMPRESSION_BASE_INCLUDED
25 
26 #include <cstddef>
27 #include <string>
28 #include <tuple>
29 
30 namespace binary_log {
31 namespace transaction {
32 namespace compression {
33 
34 const static size_t BLOCK_BYTES = 8 * 1024;
35 
36 enum type {
37   /* ZSTD compression. */
38   ZSTD = 0,
39 
40   /* No compression. */
41   NONE = 255,
42 };
43 
44 std::string type_to_string(type t);
45 
46 /**
47   Base class for compressors and decompressors.
48 
49   It establishes the interface and implements part of the shared
50   behavior.
51  */
52 class Base_compressor_decompressor {
53  protected:
54   /**
55     The pointer to the buffer holding the data to compress/decompress.
56    */
57   unsigned char *m_buffer{nullptr};
58 
59   /**
60     The buffer capacity.
61    */
62   std::size_t m_buffer_capacity{0};
63 
64   /**
65     A cursor over the buffer. It is used internally to calculate the
66     amount of buffer used for instance.
67    */
68   unsigned char *m_buffer_cursor{nullptr};
69 
70  public:
71   Base_compressor_decompressor();
72   virtual ~Base_compressor_decompressor();
73 
74   /**
75     The compression algorithm type. E.g., LZ4, ZSTD, ZLIB.
76     @return the compression type.
77    */
78   virtual type compression_type_code() = 0;
79 
80   /**
81    This member function SHALL open the compressor or decompressor.
82    Every compressor/decompressor must be opened before it is utilized.
83 
84    @return false on success, true otherwise
85   */
86   virtual bool open() = 0;
87 
88   /**
89    This member function SHALL close the compressor/decompressor.
90    Every compressor/decompressor MUST be closed once the stream
91    is over.
92    */
93   virtual bool close() = 0;
94 
95   /**
96    This member function returns the size of the compressed/decompressed
97    data.
98 
99    @return the size of the actual data.
100    */
101   virtual size_t size();
102 
103   /**
104    This member function returns the capacity of the buffer.
105 
106    @return the capacity of the buffer.
107   */
108   virtual std::size_t capacity();
109 
110   /**
111     This member function SHALL set the buffer into which the compressor or
112     decompressor shall write the data after it processes the stream.
113 
114     @param buffer the buffer itself.
115     @param capacity   the capacity of the buffer.
116 
117     @return true if something went wrong, false otherwise.
118   */
119   virtual bool set_buffer(unsigned char *buffer, std::size_t capacity);
120 
121   /**
122      This member function SHALL return the buffer, the size of its data
123      and its capacity.
124 
125      @return a tuple containing the buffer, size and capacity.
126    */
127   virtual std::tuple<unsigned char *, std::size_t, std::size_t> get_buffer();
128 
129   /**
130    This member function expands the buffer by a number of bytes.
131    Expansion is aligned to the block size and it is only done if
132    needed.
133 
134    @param bytes The number of bytes to expand the buffer.
135    @return false on success, true otherwise.
136    */
137   virtual bool reserve(std::size_t bytes);
138 };
139 
140 /**
141   The base compressor abstract class.
142 
143   It establishes the interface for compressors.
144  */
145 class Compressor : public Base_compressor_decompressor {
146  public:
147   /**
148     Sets the compression level for this compressor. It is
149     only effective if done before opening the compressor.
150     After opening the compressor setting the compression
151     level, it is only effective when the compressor is
152     closed and opened again.
153 
154     @param compression_level the compression level for this compressor.
155   */
156   virtual void set_compression_level(unsigned int compression_level) = 0;
157 
158   /**
159     This member function SHALL compress the data provided with the given
160     length. Note that the buffer to store the compressed data must have
161     already have been set through @c set_buffer.
162 
163     If the output buffer is not large enough an error shall be returned.
164     The contents of the output buffer may still have been modified in
165     that case.
166 
167     @param data the data to compress
168     @param length the length of the data.
169 
170     @return a tuple containing the bytes not compressed and an error state. If
171             all bytes were decompressed, then it is returned 0 in the first
172             element and false in the second. If not all bytes were compressed,
173             it returns the number of remaining bytes not processed and false on
174             the second element. If there was an error, then the second element
175             returns true and the first  elemement returns the number of bytes
176             processed until the error happened.
177 
178    */
179   virtual std::tuple<std::size_t, bool> compress(const unsigned char *data,
180                                                  size_t length) = 0;
181 };
182 
183 /**
184   The base decompressor abstract class.
185 
186   It establishes the interface for decompressors.
187  */
188 class Decompressor : public Base_compressor_decompressor {
189  public:
190   /**
191     This member function SHALL decompress the data provided with the given
192     length. Note that the buffer to store the compressed data must have
193     already have been set through @c set_buffer.
194 
195     If the output buffer is not large enough an error shall be returned.
196     The contents of the output buffer may still have been modified in
197     that case.
198 
199     @param data the data to compress
200     @param length the length of the data.
201 
202     @return a tuple containing the bytes not decompressed and an error state. If
203             all bytes were decompressed, then it is returned 0 in the first
204             element and false in the second. If not all bytes were decompressed,
205             it returns the number of remaining bytes not processed and false on
206             the second element. If there was an error, then the second element
207             returns true and the first  elemement returns the number of bytes
208             processed until the error happened.
209    */
210   virtual std::tuple<std::size_t, bool> decompress(const unsigned char *data,
211                                                    size_t length) = 0;
212 };
213 
214 }  // namespace compression
215 }  // namespace transaction
216 }  // namespace binary_log
217 
218 #endif
219