Skip to content

Commit e0f9806

Browse files
xhochywesm
authored andcommitted
PARQUET-769: Add support for Brotli compression
Author: Uwe L. Korn <uwelk@xhochy.com> Closes apache#194 from xhochy/PARQUET-769 and squashes the following commits: aad390f [Uwe L. Korn] Pass buffer sizes also as in parameter 9847171 [Uwe L. Korn] make format 855250d [Uwe L. Korn] make format 40e93de [Uwe L. Korn] Add FindBrotli 47b9d03 [Uwe L. Korn] PARQUET-769: Add support for Brotli compression Change-Id: I2f6b1c03f0b7e7d83f64d0e34859eb09f2702838
1 parent a414be7 commit e0f9806

7 files changed

Lines changed: 88 additions & 2 deletions

File tree

cpp/src/parquet/column/column-writer-test.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ TYPED_TEST(TestPrimitiveWriter, RequiredPlainWithSnappyCompression) {
259259
Encoding::PLAIN, Compression::SNAPPY, false, false, LARGE_SIZE);
260260
}
261261

262+
TYPED_TEST(TestPrimitiveWriter, RequiredPlainWithBrotliCompression) {
263+
this->TestRequiredWithSettings(
264+
Encoding::PLAIN, Compression::BROTLI, false, false, LARGE_SIZE);
265+
}
266+
262267
TYPED_TEST(TestPrimitiveWriter, RequiredPlainWithGzipCompression) {
263268
this->TestRequiredWithSettings(
264269
Encoding::PLAIN, Compression::GZIP, false, false, LARGE_SIZE);
@@ -274,6 +279,11 @@ TYPED_TEST(TestPrimitiveWriter, RequiredPlainWithStatsAndSnappyCompression) {
274279
Encoding::PLAIN, Compression::SNAPPY, false, true, LARGE_SIZE);
275280
}
276281

282+
TYPED_TEST(TestPrimitiveWriter, RequiredPlainWithStatsAndBrotliCompression) {
283+
this->TestRequiredWithSettings(
284+
Encoding::PLAIN, Compression::BROTLI, false, true, LARGE_SIZE);
285+
}
286+
277287
TYPED_TEST(TestPrimitiveWriter, RequiredPlainWithStatsAndGzipCompression) {
278288
this->TestRequiredWithSettings(
279289
Encoding::PLAIN, Compression::GZIP, false, true, LARGE_SIZE);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include <cstdint>
19+
#include <cstdlib>
20+
#include <brotli/decode.h>
21+
#include <brotli/encode.h>
22+
23+
#include "parquet/compression/codec.h"
24+
#include "parquet/exception.h"
25+
26+
namespace parquet {
27+
28+
void BrotliCodec::Decompress(
29+
int64_t input_len, const uint8_t* input, int64_t output_len, uint8_t* output_buffer) {
30+
size_t output_size = output_len;
31+
if (BrotliDecoderDecompress(input_len, input, &output_size, output_buffer) !=
32+
BROTLI_DECODER_RESULT_SUCCESS) {
33+
throw parquet::ParquetException("Corrupt brotli compressed data.");
34+
}
35+
}
36+
37+
int64_t BrotliCodec::MaxCompressedLen(int64_t input_len, const uint8_t* input) {
38+
return BrotliEncoderMaxCompressedSize(input_len);
39+
}
40+
41+
int64_t BrotliCodec::Compress(int64_t input_len, const uint8_t* input,
42+
int64_t output_buffer_len, uint8_t* output_buffer) {
43+
size_t output_len = output_buffer_len;
44+
// TODO: Make quality configurable. We use 8 as a default as it is the best
45+
// trade-off for Parquet workload
46+
if (BrotliEncoderCompress(8, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, input_len,
47+
input, &output_len, output_buffer) == BROTLI_FALSE) {
48+
throw parquet::ParquetException("Brotli compression failure.");
49+
}
50+
return output_len;
51+
}
52+
53+
} // namespace parquet

cpp/src/parquet/compression/codec-test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ TEST(TestCompressors, Snappy) {
7373
CheckCodec<SnappyCodec>();
7474
}
7575

76+
TEST(TestCompressors, Brotli) {
77+
CheckCodec<BrotliCodec>();
78+
}
79+
7680
TEST(TestCompressors, GZip) {
7781
CheckCodec<GZipCodec>();
7882
}

cpp/src/parquet/compression/codec.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ std::unique_ptr<Codec> Codec::Create(Compression::type codec_type) {
3838
ParquetException::NYI("LZO codec not implemented");
3939
break;
4040
case Compression::BROTLI:
41-
ParquetException::NYI("BROTLI codec not implemented");
41+
result.reset(new BrotliCodec());
4242
break;
4343
default:
4444
ParquetException::NYI("Unrecognized codec");

cpp/src/parquet/compression/codec.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ class SnappyCodec : public Codec {
5959
virtual const char* name() const { return "snappy"; }
6060
};
6161

62+
// Brotli codec.
63+
class BrotliCodec : public Codec {
64+
public:
65+
void Decompress(int64_t input_len, const uint8_t* input, int64_t output_len,
66+
uint8_t* output_buffer) override;
67+
68+
int64_t Compress(int64_t input_len, const uint8_t* input,
69+
int64_t output_buffer_len, uint8_t* output_buffer) override;
70+
71+
int64_t MaxCompressedLen(int64_t input_len, const uint8_t* input) override;
72+
73+
const char* name() const override { return "brotli"; }
74+
};
75+
6276
// GZip codec.
6377
class GZipCodec : public Codec {
6478
public:

cpp/src/parquet/file/file-deserialize-test.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ TEST_F(TestPageSerde, TestFailLargePageHeaders) {
165165
}
166166

167167
TEST_F(TestPageSerde, Compression) {
168-
Compression::type codec_types[2] = {Compression::GZIP, Compression::SNAPPY};
168+
Compression::type codec_types[3] = {
169+
Compression::GZIP, Compression::SNAPPY, Compression::BROTLI};
169170

170171
// This is a dummy number
171172
data_page_header_.num_values = 32;

cpp/src/parquet/file/file-serialize-test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ TYPED_TEST(TestSerialize, SmallFileSnappy) {
119119
this->FileSerializeTest(Compression::SNAPPY);
120120
}
121121

122+
TYPED_TEST(TestSerialize, SmallFileBrotli) {
123+
this->FileSerializeTest(Compression::BROTLI);
124+
}
125+
122126
TYPED_TEST(TestSerialize, SmallFileGzip) {
123127
this->FileSerializeTest(Compression::GZIP);
124128
}

0 commit comments

Comments
 (0)