Skip to content

Commit 705ce20

Browse files
authored
Merge branch 'main' into support_avro_read
2 parents 1376cb3 + 4291b6e commit 705ce20

37 files changed

Lines changed: 1194 additions & 120 deletions

.gitattributes

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
*.jar filter=lfs diff=lfs merge=lfs -text
44
*.tar filter=lfs diff=lfs merge=lfs -text
55
*.gz filter=lfs diff=lfs merge=lfs -text
6-
79d01717-8380-4504-86e1-387e6c058d0a filter=lfs diff=lfs merge=lfs -text
6+
test/test_data/sst/none/79d01717-8380-4504-86e1-387e6c058d0a filter=lfs diff=lfs merge=lfs -text
7+
test/test_data/sst/lz4/10540951-41d3-4216-aa2c-b15dfd25eb75 filter=lfs diff=lfs merge=lfs -text
8+
test/test_data/sst/zstd/83d05c53-2353-4160-b756-d50dd851b474 filter=lfs diff=lfs merge=lfs -text

include/paimon/utils/read_ahead_cache.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,33 +42,53 @@ class PAIMON_EXPORT CacheConfig {
4242
public:
4343
CacheConfig();
4444
CacheConfig(uint64_t buffer_size_limit, uint64_t range_size_limit, uint64_t hole_size_limit,
45-
uint32_t pre_buffer_range_count);
45+
uint64_t pre_buffer_limit);
4646

4747
/// Returns the maximum total size (in bytes) of cached data.
4848
uint64_t GetBufferSizeLimit() const {
4949
return buffer_size_limit_;
5050
}
5151

52+
/// Sets the maximum total size (in bytes) of cached data.
53+
void SetBufferSizeLimit(uint64_t buffer_size_limit) {
54+
buffer_size_limit_ = buffer_size_limit;
55+
}
56+
5257
/// Returns the maximum allowed size (in bytes) for a single cached range.
5358
uint64_t GetRangeSizeLimit() const {
5459
return range_size_limit_;
5560
}
5661

62+
/// Sets the maximum allowed size (in bytes) for a single cached range.
63+
void SetRangeSizeLimit(uint64_t range_size_limit) {
64+
range_size_limit_ = range_size_limit;
65+
}
66+
5767
/// Returns the maximum gap size (in bytes) considered mergeable between adjacent ranges.
5868
uint64_t GetHoleSizeLimit() const {
5969
return hole_size_limit_;
6070
}
6171

62-
/// Returns the number of ranges to pre-buffer ahead of the current read position.
63-
uint32_t GetPreBufferRangeCount() const {
64-
return pre_buffer_range_count_;
72+
/// Sets the maximum gap size (in bytes) considered mergeable between adjacent ranges.
73+
void SetHoleSizeLimit(uint64_t hole_size_limit) {
74+
hole_size_limit_ = hole_size_limit;
75+
}
76+
77+
/// Returns the maximum size to pre-buffer ahead of the current read position.
78+
uint64_t GetPreBufferLimit() const {
79+
return pre_buffer_limit_;
80+
}
81+
82+
/// Sets the maximum size to pre-buffer ahead of the current read position.
83+
void SetPreBufferLimit(uint64_t pre_buffer_limit) {
84+
pre_buffer_limit_ = pre_buffer_limit;
6585
}
6686

6787
private:
6888
uint64_t buffer_size_limit_;
6989
uint64_t range_size_limit_;
7090
uint64_t hole_size_limit_;
71-
uint32_t pre_buffer_range_count_;
91+
uint64_t pre_buffer_limit_;
7292
};
7393

7494
/// A byte range with offset and length.

src/paimon/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
# limitations under the License.
1414

1515
set(PAIMON_COMMON_SRCS
16+
common/compression/block_compression_factory.cpp
17+
common/compression/block_compressor.cpp
18+
common/compression/block_decompressor.cpp
1619
common/data/abstract_binary_writer.cpp
1720
common/data/binary_array.cpp
1821
common/data/binary_array_writer.cpp
@@ -116,6 +119,7 @@ set(PAIMON_COMMON_SRCS
116119
common/utils/bloom_filter.cpp
117120
common/utils/bloom_filter64.cpp
118121
common/utils/bucket_id_calculator.cpp
122+
common/utils/crc32c.cpp
119123
common/utils/decimal_utils.cpp
120124
common/utils/delta_varint_compressor.cpp
121125
common/utils/path_util.cpp
@@ -441,7 +445,9 @@ if(PAIMON_BUILD_TESTS)
441445

442446
add_paimon_test(common_sst_file_format_test
443447
SOURCES
448+
common/compression/block_compression_factory_test.cpp
444449
common/sst/sst_file_io_test.cpp
450+
common/utils/crc32c_test.cpp
445451
STATIC_LINK_LIBS
446452
paimon_shared
447453
test_utils_static
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "paimon/common/compression/block_compression_factory.h"
18+
19+
#include "paimon/common/compression/lz4/lz4_block_compression_factory.h"
20+
#include "paimon/common/compression/none_block_compression_factory.h"
21+
#include "paimon/common/compression/zstd/zstd_block_compression_factory.h"
22+
23+
namespace paimon {
24+
25+
Result<std::shared_ptr<BlockCompressionFactory>> BlockCompressionFactory::Create(
26+
BlockCompressionType compression) {
27+
switch (compression) {
28+
case BlockCompressionType::NONE:
29+
return std::make_shared<NoneBlockCompressionFactory>();
30+
case BlockCompressionType::LZ4:
31+
return std::make_shared<Lz4BlockCompressionFactory>();
32+
case BlockCompressionType::ZSTD:
33+
return std::make_shared<ZstdBlockCompressionFactory>(ZSTD_COMPRESSION_LEVEL);
34+
default:
35+
// TODO(liangzi): LZO support
36+
return Status::Invalid("Unsupported compression type: " +
37+
std::to_string(static_cast<int8_t>(compression)));
38+
}
39+
}
40+
41+
} // namespace paimon
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <memory>
20+
21+
#include "paimon/common/compression/block_compression_type.h"
22+
#include "paimon/common/compression/block_compressor.h"
23+
#include "paimon/common/compression/block_decompressor.h"
24+
#include "paimon/result.h"
25+
26+
namespace paimon {
27+
28+
/// Each compression codec has an implementation of {@link BlockCompressionFactory} to create
29+
/// compressors and decompressors.
30+
class BlockCompressionFactory {
31+
public:
32+
static Result<std::shared_ptr<BlockCompressionFactory>> Create(
33+
BlockCompressionType compression);
34+
35+
BlockCompressionFactory() = default;
36+
virtual ~BlockCompressionFactory() = default;
37+
38+
public:
39+
virtual BlockCompressionType GetCompressionType() const = 0;
40+
41+
virtual std::shared_ptr<BlockCompressor> GetCompressor() = 0;
42+
43+
virtual std::shared_ptr<BlockDecompressor> GetDecompressor() = 0;
44+
45+
private:
46+
// Align java implementation
47+
static constexpr int32_t ZSTD_COMPRESSION_LEVEL = 1;
48+
};
49+
} // namespace paimon
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "paimon/common/compression/block_compression_factory.h"
18+
19+
#include <cstdint>
20+
#include <string>
21+
#include <utility>
22+
#include <vector>
23+
24+
#include "gtest/gtest.h"
25+
#include "paimon/defs.h"
26+
#include "paimon/memory/memory_pool.h"
27+
#include "paimon/status.h"
28+
#include "paimon/testing/mock/mock_file_batch_reader.h"
29+
#include "paimon/testing/utils/read_result_collector.h"
30+
#include "paimon/testing/utils/testharness.h"
31+
32+
namespace paimon {
33+
class Predicate;
34+
} // namespace paimon
35+
36+
namespace paimon::test {
37+
class CompressionFactoryTest : public ::testing::TestWithParam<BlockCompressionType> {};
38+
39+
TEST_P(CompressionFactoryTest, TESTCompressThenDecompress) {
40+
int32_t original_len = 16;
41+
BlockCompressionType type = GetParam();
42+
43+
std::string data(original_len, '\0');
44+
for (int32_t i = 0; i < original_len; i++) {
45+
data[i] = static_cast<char>(i);
46+
}
47+
48+
ASSERT_OK_AND_ASSIGN(auto factory, BlockCompressionFactory::Create(type));
49+
ASSERT_EQ(type, factory->GetCompressionType());
50+
51+
// compress
52+
auto compressor = factory->GetCompressor();
53+
auto max_len = compressor->GetMaxCompressedSize(data.size());
54+
std::string compressed_data(max_len, '\0');
55+
auto compressed_size =
56+
compressor->Compress(data.data(), data.size(), compressed_data.data(), max_len);
57+
ASSERT_OK(compressed_size);
58+
ASSERT_GT(compressed_size.value(), 0);
59+
compressed_data.resize(compressed_size.value());
60+
61+
// decompress
62+
auto decompressor = factory->GetDecompressor();
63+
std::string decompressed_data(original_len, '\0');
64+
auto decompressed_size =
65+
decompressor->Decompress(compressed_data.data(), compressed_data.size(),
66+
decompressed_data.data(), decompressed_data.size());
67+
ASSERT_OK(decompressed_size);
68+
ASSERT_GT(decompressed_size.value(), 0);
69+
ASSERT_EQ(data, decompressed_data);
70+
71+
std::string read_write_le{4, '\0'};
72+
compressor->WriteIntLE(123, read_write_le.data());
73+
ASSERT_EQ(123, decompressor->ReadIntLE(read_write_le.data()));
74+
compressor->WriteIntLE(100000, read_write_le.data());
75+
ASSERT_EQ(100000, decompressor->ReadIntLE(read_write_le.data()));
76+
compressor->WriteIntLE(-6555, read_write_le.data());
77+
ASSERT_EQ(-6555, decompressor->ReadIntLE(read_write_le.data()));
78+
compressor->WriteIntLE(0, read_write_le.data());
79+
ASSERT_EQ(0, decompressor->ReadIntLE(read_write_le.data()));
80+
}
81+
82+
INSTANTIATE_TEST_SUITE_P(BlockCompressionTypeGroup, CompressionFactoryTest,
83+
::testing::Values(BlockCompressionType::LZ4, BlockCompressionType::ZSTD));
84+
85+
} // namespace paimon::test
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include "paimon/result.h"
20+
21+
namespace paimon {
22+
23+
/// Block Compression type.
24+
enum class BlockCompressionType { NONE = 0, ZSTD = 1, LZ4 = 2, LZO = 3 };
25+
26+
} // namespace paimon
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "paimon/common/compression/block_compressor.h"
18+
19+
namespace paimon {
20+
21+
void BlockCompressor::WriteIntLE(int32_t val, char* buf) {
22+
buf[0] = static_cast<char>(val);
23+
buf[1] = static_cast<char>(val >> 8);
24+
buf[2] = static_cast<char>(val >> 16);
25+
buf[3] = static_cast<char>(val >> 24);
26+
}
27+
28+
} // namespace paimon
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include "paimon/result.h"
20+
21+
namespace paimon {
22+
23+
/// A compressor which compresses a whole byte array each time.
24+
class BlockCompressor {
25+
public:
26+
static void WriteIntLE(int32_t val, char* buf);
27+
28+
public:
29+
virtual ~BlockCompressor() = default;
30+
31+
public:
32+
/**
33+
* Get the max compressed size for a given original size.
34+
* @param src_size The original size
35+
* @return The max compressed size
36+
*/
37+
virtual int32_t GetMaxCompressedSize(int32_t src_size) = 0;
38+
39+
/**
40+
* Compress data read from src, and write the compressed data to dst.
41+
*
42+
* @param src Uncompressed data to read from
43+
* @param src_length The length of data which want to be compressed
44+
* @param dst The target to write compressed data
45+
* @param dst_length The max length of data
46+
* @return Length of compressed data
47+
*/
48+
/// Compress data read from src, and write the compressed data to dst.
49+
virtual Result<int32_t> Compress(const char* src, int32_t src_length, char* dst,
50+
int32_t dst_length) = 0;
51+
52+
public:
53+
/**
54+
* We put two integers before each compressed block, the first integer represents the compressed
55+
* length of the block, and the second one represents the original length of the block.
56+
*/
57+
static constexpr int32_t HEADER_LENGTH = 8;
58+
};
59+
} // namespace paimon

0 commit comments

Comments
 (0)