forked from alibaba/paimon-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathread_ahead_cache.h
More file actions
182 lines (155 loc) · 6.69 KB
/
Copy pathread_ahead_cache.h
File metadata and controls
182 lines (155 loc) · 6.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Adapted from Apache ORC
// https://github.com/apache/orc/blob/main/c%2B%2B/src/io/Cache.hh
#pragma once
#include <cstdint>
#include <memory>
#include <vector>
#include "paimon/fs/file_system.h"
#include "paimon/memory/bytes.h"
#include "paimon/memory/memory_pool.h"
#include "paimon/result.h"
#include "paimon/status.h"
#include "paimon/visibility.h"
namespace paimon {
/// PrefetchCacheMode
/// Cache prefetch switch modes.
/// Controls whether to enable cache prefetching under different circumstances, such as queries with
/// predicates or bitmap indexes.
///
/// - ALWAYS: Enable cache in all scenarios.
/// - EXCLUDE_PREDICATE: Disable cache when query has predicates.
/// - EXCLUDE_BITMAP: Disable cache when using bitmap index.
/// - EXCLUDE_BITMAP_OR_PREDICATE: Disable cache if query has predicates or bitmap index.
/// - NEVER: Always disable cache.
enum class PAIMON_EXPORT PrefetchCacheMode {
ALWAYS = 1,
EXCLUDE_PREDICATE = 2,
EXCLUDE_BITMAP = 3,
EXCLUDE_BITMAP_OR_PREDICATE = 4,
NEVER = 5
};
/// Configuration parameters for the read-ahead cache behavior.
///
/// This struct controls various limits and prefetching strategies used by
/// ReadAheadCache to balance memory usage, I/O efficiency, and latency hiding.
class PAIMON_EXPORT CacheConfig {
public:
CacheConfig();
CacheConfig(uint64_t buffer_size_limit, uint64_t range_size_limit, uint64_t hole_size_limit,
uint64_t pre_buffer_limit);
/// Returns the maximum total size (in bytes) of cached data.
uint64_t GetBufferSizeLimit() const {
return buffer_size_limit_;
}
/// Sets the maximum total size (in bytes) of cached data.
void SetBufferSizeLimit(uint64_t buffer_size_limit) {
buffer_size_limit_ = buffer_size_limit;
}
/// Returns the maximum allowed size (in bytes) for a single cached range.
uint64_t GetRangeSizeLimit() const {
return range_size_limit_;
}
/// Sets the maximum allowed size (in bytes) for a single cached range.
void SetRangeSizeLimit(uint64_t range_size_limit) {
range_size_limit_ = range_size_limit;
}
/// Returns the maximum gap size (in bytes) considered mergeable between adjacent ranges.
uint64_t GetHoleSizeLimit() const {
return hole_size_limit_;
}
/// Sets the maximum gap size (in bytes) considered mergeable between adjacent ranges.
void SetHoleSizeLimit(uint64_t hole_size_limit) {
hole_size_limit_ = hole_size_limit;
}
/// Returns the maximum size to pre-buffer ahead of the current read position.
uint64_t GetPreBufferLimit() const {
return pre_buffer_limit_;
}
/// Sets the maximum size to pre-buffer ahead of the current read position.
void SetPreBufferLimit(uint64_t pre_buffer_limit) {
pre_buffer_limit_ = pre_buffer_limit;
}
private:
uint64_t buffer_size_limit_;
uint64_t range_size_limit_;
uint64_t hole_size_limit_;
uint64_t pre_buffer_limit_;
};
/// A byte range with offset and length.
struct PAIMON_EXPORT ByteRange {
uint64_t offset;
uint64_t length;
ByteRange() = default;
ByteRange(uint64_t offset, uint64_t length) : offset(offset), length(length) {}
friend bool operator==(const ByteRange& left, const ByteRange& right) {
return (left.offset == right.offset && left.length == right.length);
}
friend bool operator!=(const ByteRange& left, const ByteRange& right) {
return !(left == right);
}
/// @param other The other byte range to check.
/// @return true if this range contains the other range
bool Contains(const ByteRange& other) const {
return (offset <= other.offset && offset + length >= other.offset + other.length);
}
};
/// A byte slice with buffer, offset and length.
struct PAIMON_EXPORT ByteSlice {
std::shared_ptr<Bytes> buffer = nullptr;
uint64_t offset = 0;
uint64_t length = 0;
};
/// A read cache designed to hide IO latencies when reading.
/// Prefetching strategy: When a range is read, the cache will prefetch up to
/// `pre_buffer_range_count` additional adjacent ranges ahead of the requested offset. This helps
/// hide I/O latency for sequential access. Example: If you read range [0, 100), and
/// pre_buffer_range_count=2, the next two configured ranges will also be prefetched.
///
/// Eviction policy: The cache uses a simple FIFO eviction policy based on total cached byte size.
/// When adding new ranges would exceed `buffer_size_limit`, the oldest cached ranges are evicted
/// first until there is enough space for the new data.
class PAIMON_EXPORT ReadAheadCache {
public:
/// Construct a read cache with given options
ReadAheadCache(const std::shared_ptr<InputStream>& stream, const CacheConfig& config,
const std::shared_ptr<MemoryPool>& memory_pool);
~ReadAheadCache();
/// Initialize the cache with given byte ranges to be cached.
/// @param ranges The byte ranges to be cached.
/// @return Status of the operation.
/// @note This method must be called before any Read() calls. Ranges will be coalesced based
/// on the cache configuration.
Status Init(std::vector<ByteRange>&& ranges);
/// Read a range previously provided to Init().
/// @param range The byte range to read.
/// @return The byte slice containing the requested data. If the data is not yet cached
/// (cache miss), the returned `ByteSlice` will have a null buffer (`buffer == nullptr`)
Result<ByteSlice> Read(const ByteRange& range);
/// Reset the cache to its initial state, clearing all cached data and configuration.
///
/// This method waits for all ongoing asynchronous read operations to complete,
/// clears all cached entries, and resets the internal state so that Init() can be called again.
/// After calling Reset, the cache can be safely re-initialized with new ranges.
void Reset();
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace paimon