Coverage Report

Created: 2026-10-15 15:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/io/io_common.h
Line
Count
Source
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
#pragma once
19
20
#include <gen_cpp/Types_types.h>
21
22
#include <array>
23
#include <cstddef>
24
#include <cstdint>
25
#include <optional>
26
#include <set>
27
#include <string>
28
29
namespace doris {
30
31
enum class ReaderType : uint8_t {
32
    READER_QUERY = 0,
33
    READER_ALTER_TABLE = 1,
34
    READER_BASE_COMPACTION = 2,
35
    READER_CUMULATIVE_COMPACTION = 3,
36
    READER_CHECKSUM = 4,
37
    READER_COLD_DATA_COMPACTION = 5,
38
    READER_SEGMENT_COMPACTION = 6,
39
    READER_FULL_COMPACTION = 7,
40
    UNKNOWN = 8
41
};
42
43
namespace io {
44
45
class RemoteScanCacheWriteLimiter;
46
enum class CacheWriteMode : uint8_t;
47
48
enum class FileCacheMissPolicy : uint8_t {
49
    READ_THROUGH_AND_WRITE_BACK = 0,
50
    REMOTE_ONLY_ON_MISS = 1,
51
};
52
53
/// Provenance for opt-in physical IO diagnostics. NORMAL keeps synchronous query reads and
54
/// unrelated background reads distinguishable via reader_type.
55
enum class FileReadTraceSource : uint8_t { NORMAL, READ_AHEAD, HOLE_FILL };
56
57
struct FileReaderStats {
58
    size_t read_calls = 0;
59
    size_t read_bytes = 0;
60
    int64_t read_time_ns = 0;
61
    size_t read_rows = 0;
62
63
0
    void merge_from(const FileReaderStats& other) {
64
0
        read_calls += other.read_calls;
65
0
        read_bytes += other.read_bytes;
66
0
        read_time_ns += other.read_time_ns;
67
0
        read_rows += other.read_rows;
68
0
    }
69
};
70
71
struct FileCacheStatistics {
72
    int64_t num_local_io_total = 0;
73
    int64_t num_remote_io_total = 0;
74
    int64_t num_peer_io_total = 0;
75
    int64_t local_io_timer = 0;
76
    int64_t bytes_read_from_local = 0;
77
    int64_t bytes_read_from_remote = 0;
78
    int64_t bytes_read_from_peer = 0;
79
    int64_t remote_io_timer = 0;
80
    int64_t peer_io_timer = 0;
81
    int64_t remote_wait_timer = 0;
82
    int64_t write_cache_io_timer = 0;
83
    int64_t bytes_write_into_cache = 0;
84
    int64_t num_skip_cache_io_total = 0;
85
    int64_t read_cache_file_directly_timer = 0;
86
    int64_t cache_get_or_set_timer = 0;
87
    int64_t lock_wait_timer = 0;
88
    int64_t get_timer = 0;
89
    int64_t set_timer = 0;
90
    int64_t async_cache_write_submitted = 0;
91
    int64_t async_cache_write_rejected = 0;
92
    int64_t async_cache_write_buffer_alloc_fail = 0;
93
    int64_t async_cache_write_drop_stale_epoch = 0;
94
    int64_t inflight_write_buffer_index_hit = 0;
95
    int64_t inflight_write_buffer_index_miss = 0;
96
    int64_t probe_downloaded_hit = 0;
97
    int64_t probe_downloading_hit = 0;
98
    int64_t probe_miss = 0;
99
    int64_t block_wait_success = 0;
100
    int64_t block_wait_timeout = 0;
101
102
    int64_t inverted_index_num_local_io_total = 0;
103
    int64_t inverted_index_num_remote_io_total = 0;
104
    int64_t inverted_index_num_peer_io_total = 0;
105
    int64_t inverted_index_bytes_read_from_local = 0;
106
    int64_t inverted_index_bytes_read_from_remote = 0;
107
    int64_t inverted_index_bytes_read_from_peer = 0;
108
    int64_t inverted_index_remote_physical_read_bytes = 0;
109
    int64_t inverted_index_bytes_write_into_cache = 0;
110
    int64_t inverted_index_local_io_timer = 0;
111
    int64_t inverted_index_remote_io_timer = 0;
112
    int64_t inverted_index_peer_io_timer = 0;
113
    int64_t inverted_index_io_timer = 0;
114
    int64_t inverted_index_write_cache_io_timer = 0;
115
    int64_t inverted_index_request_bytes = 0;
116
    int64_t inverted_index_read_bytes = 0;
117
    int64_t inverted_index_range_read_count = 0;
118
    int64_t inverted_index_serial_read_rounds = 0;
119
120
    int64_t segment_footer_index_num_local_io_total = 0;
121
    int64_t segment_footer_index_num_remote_io_total = 0;
122
    int64_t segment_footer_index_num_peer_io_total = 0;
123
    int64_t segment_footer_index_bytes_read_from_local = 0;
124
    int64_t segment_footer_index_bytes_read_from_remote = 0;
125
    int64_t segment_footer_index_bytes_read_from_peer = 0;
126
    int64_t segment_footer_index_local_io_timer = 0;
127
    int64_t segment_footer_index_remote_io_timer = 0;
128
    int64_t segment_footer_index_peer_io_timer = 0;
129
    int64_t segment_footer_index_write_cache_io_timer = 0;
130
    int64_t segment_footer_index_bytes_write_into_cache = 0;
131
    int64_t remote_only_on_miss_triggered = 0;
132
    int64_t remote_only_on_miss_threshold_bytes = 0;
133
134
    // Cross-CG / Same-CG peer read statistics
135
    int64_t num_cross_cg_peer_io_total = 0;
136
    int64_t bytes_read_from_cross_cg_peer = 0;
137
    int64_t cross_cg_peer_io_timer = 0; // nanoseconds
138
    int64_t num_same_cg_peer_io_total = 0;
139
    int64_t bytes_read_from_same_cg_peer = 0;
140
    int64_t same_cg_peer_io_timer = 0; // nanoseconds
141
    int64_t num_peer_race_peer_win = 0;
142
    int64_t num_peer_race_s3_win = 0;
143
    int64_t num_peer_lazy_fetch = 0;
144
    int64_t peer_lazy_fetch_timer = 0; // nanoseconds
145
146
    std::set<std::string> peer_hosts;
147
148
47
    void merge_from(const FileCacheStatistics& other) {
149
47
        num_local_io_total += other.num_local_io_total;
150
47
        num_remote_io_total += other.num_remote_io_total;
151
47
        num_peer_io_total += other.num_peer_io_total;
152
47
        local_io_timer += other.local_io_timer;
153
47
        bytes_read_from_local += other.bytes_read_from_local;
154
47
        bytes_read_from_remote += other.bytes_read_from_remote;
155
47
        bytes_read_from_peer += other.bytes_read_from_peer;
156
47
        remote_io_timer += other.remote_io_timer;
157
47
        peer_io_timer += other.peer_io_timer;
158
47
        remote_wait_timer += other.remote_wait_timer;
159
47
        write_cache_io_timer += other.write_cache_io_timer;
160
47
        bytes_write_into_cache += other.bytes_write_into_cache;
161
47
        num_skip_cache_io_total += other.num_skip_cache_io_total;
162
47
        read_cache_file_directly_timer += other.read_cache_file_directly_timer;
163
47
        cache_get_or_set_timer += other.cache_get_or_set_timer;
164
47
        lock_wait_timer += other.lock_wait_timer;
165
47
        get_timer += other.get_timer;
166
47
        set_timer += other.set_timer;
167
47
        async_cache_write_submitted += other.async_cache_write_submitted;
168
47
        async_cache_write_rejected += other.async_cache_write_rejected;
169
47
        async_cache_write_buffer_alloc_fail += other.async_cache_write_buffer_alloc_fail;
170
47
        async_cache_write_drop_stale_epoch += other.async_cache_write_drop_stale_epoch;
171
47
        inflight_write_buffer_index_hit += other.inflight_write_buffer_index_hit;
172
47
        inflight_write_buffer_index_miss += other.inflight_write_buffer_index_miss;
173
47
        probe_downloaded_hit += other.probe_downloaded_hit;
174
47
        probe_downloading_hit += other.probe_downloading_hit;
175
47
        probe_miss += other.probe_miss;
176
47
        block_wait_success += other.block_wait_success;
177
47
        block_wait_timeout += other.block_wait_timeout;
178
179
47
        inverted_index_num_local_io_total += other.inverted_index_num_local_io_total;
180
47
        inverted_index_num_remote_io_total += other.inverted_index_num_remote_io_total;
181
47
        inverted_index_num_peer_io_total += other.inverted_index_num_peer_io_total;
182
47
        inverted_index_bytes_read_from_local += other.inverted_index_bytes_read_from_local;
183
47
        inverted_index_bytes_read_from_remote += other.inverted_index_bytes_read_from_remote;
184
47
        inverted_index_bytes_read_from_peer += other.inverted_index_bytes_read_from_peer;
185
47
        inverted_index_remote_physical_read_bytes +=
186
47
                other.inverted_index_remote_physical_read_bytes;
187
47
        inverted_index_local_io_timer += other.inverted_index_local_io_timer;
188
47
        inverted_index_remote_io_timer += other.inverted_index_remote_io_timer;
189
47
        inverted_index_peer_io_timer += other.inverted_index_peer_io_timer;
190
47
        inverted_index_io_timer += other.inverted_index_io_timer;
191
47
        inverted_index_write_cache_io_timer += other.inverted_index_write_cache_io_timer;
192
47
        inverted_index_bytes_write_into_cache += other.inverted_index_bytes_write_into_cache;
193
47
        inverted_index_request_bytes += other.inverted_index_request_bytes;
194
47
        inverted_index_read_bytes += other.inverted_index_read_bytes;
195
47
        inverted_index_range_read_count += other.inverted_index_range_read_count;
196
47
        inverted_index_serial_read_rounds += other.inverted_index_serial_read_rounds;
197
198
47
        segment_footer_index_num_local_io_total += other.segment_footer_index_num_local_io_total;
199
47
        segment_footer_index_num_remote_io_total += other.segment_footer_index_num_remote_io_total;
200
47
        segment_footer_index_num_peer_io_total += other.segment_footer_index_num_peer_io_total;
201
47
        segment_footer_index_bytes_read_from_local +=
202
47
                other.segment_footer_index_bytes_read_from_local;
203
47
        segment_footer_index_bytes_read_from_remote +=
204
47
                other.segment_footer_index_bytes_read_from_remote;
205
47
        segment_footer_index_bytes_read_from_peer +=
206
47
                other.segment_footer_index_bytes_read_from_peer;
207
47
        segment_footer_index_local_io_timer += other.segment_footer_index_local_io_timer;
208
47
        segment_footer_index_remote_io_timer += other.segment_footer_index_remote_io_timer;
209
47
        segment_footer_index_peer_io_timer += other.segment_footer_index_peer_io_timer;
210
47
        segment_footer_index_write_cache_io_timer +=
211
47
                other.segment_footer_index_write_cache_io_timer;
212
47
        segment_footer_index_bytes_write_into_cache +=
213
47
                other.segment_footer_index_bytes_write_into_cache;
214
47
        remote_only_on_miss_triggered =
215
48
                remote_only_on_miss_triggered || other.remote_only_on_miss_triggered;
216
47
        if (other.remote_only_on_miss_threshold_bytes > remote_only_on_miss_threshold_bytes) {
217
1
            remote_only_on_miss_threshold_bytes = other.remote_only_on_miss_threshold_bytes;
218
1
        }
219
220
47
        num_cross_cg_peer_io_total += other.num_cross_cg_peer_io_total;
221
47
        bytes_read_from_cross_cg_peer += other.bytes_read_from_cross_cg_peer;
222
47
        cross_cg_peer_io_timer += other.cross_cg_peer_io_timer;
223
47
        num_same_cg_peer_io_total += other.num_same_cg_peer_io_total;
224
47
        bytes_read_from_same_cg_peer += other.bytes_read_from_same_cg_peer;
225
47
        same_cg_peer_io_timer += other.same_cg_peer_io_timer;
226
47
        num_peer_race_peer_win += other.num_peer_race_peer_win;
227
47
        num_peer_race_s3_win += other.num_peer_race_s3_win;
228
47
        num_peer_lazy_fetch += other.num_peer_lazy_fetch;
229
47
        peer_lazy_fetch_timer += other.peer_lazy_fetch_timer;
230
231
47
        peer_hosts.insert(other.peer_hosts.begin(), other.peer_hosts.end());
232
47
    }
233
};
234
235
struct IOContext {
236
    FileReadTraceSource read_trace_source {FileReadTraceSource::NORMAL};
237
    uint64_t read_trace_id {0}; // read-ahead range or hole-fill task; zero when not traced
238
    ReaderType reader_type = ReaderType::UNKNOWN;
239
    // FIXME(plat1ko): Seems `is_disposable` can be inferred from the `reader_type`?
240
    bool is_disposable = false;
241
    bool is_index_data = false;
242
    bool read_file_cache = true;
243
    // TODO(lightman): use following member variables to control file cache
244
    bool is_persistent = false;
245
    // stop reader when reading, used in some interrupted operations
246
    bool should_stop = false;
247
    int64_t expiration_time = 0;
248
    const TUniqueId* query_id = nullptr;             // Ref
249
    FileCacheStatistics* file_cache_stats = nullptr; // Ref
250
    FileReaderStats* file_reader_stats = nullptr;    // Ref
251
    bool is_inverted_index = false;
252
    // if is_dryrun, read IO will download data to cache but return no data to reader
253
    // useful to skip cache data read from local disk to accelarate warm up
254
    bool is_dryrun = false;
255
    // if `is_warmup` == true, this I/O request is from a warm up task
256
    bool is_warmup {false};
257
    int64_t condition_cache_filtered_rows = 0;
258
    // Rows removed by file-local predicate conjuncts inside FileReader/TableReader. Scanner-level
259
    // output filtering already records its own unselected rows; this counter carries the rows that
260
    // were filtered before the block returned to Scanner.
261
    int64_t predicate_filtered_rows = 0;
262
    // if true, bypass peer read / peer-vs-S3 race and read directly from remote storage
263
    bool bypass_peer_read {false};
264
    // Per-call override for cache write completion semantics. An unset value follows the reader
265
    // option and the global async file-cache write switch.
266
    std::optional<CacheWriteMode> cache_write_mode_override = std::nullopt;
267
    FileCacheMissPolicy file_cache_miss_policy = FileCacheMissPolicy::READ_THROUGH_AND_WRITE_BACK;
268
    // From session variable inverted_index_snii_read_no_write_file_cache: SNII index
269
    // reads of this query take REMOTE_ONLY_ON_MISS (hit served, miss reads remote
270
    // and skips the cache write-back). Carried down to the SNII adapter, which is
271
    // the sole place that turns it into a file_cache_miss_policy -- keeping CLucene
272
    // index reads and data reads on the normal write-back path.
273
    bool inverted_index_snii_read_no_write_file_cache = false;
274
    RemoteScanCacheWriteLimiter* remote_scan_cache_write_limiter = nullptr; // Ref
275
};
276
277
} // namespace io
278
} // namespace doris