Coverage Report

Created: 2026-08-24 16:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/io/cache/cached_remote_file_reader.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 <cstddef>
21
#include <cstdint>
22
#include <map>
23
#include <shared_mutex>
24
#include <unordered_set>
25
#include <utility>
26
#include <vector>
27
28
#include "common/status.h"
29
#include "io/cache/block_file_cache.h"
30
#include "io/cache/file_block.h"
31
#include "io/cache/file_cache_common.h"
32
#include "io/fs/file_reader.h"
33
#include "io/fs/file_reader_writer_fwd.h"
34
#include "io/fs/path.h"
35
#include "util/slice.h"
36
37
namespace doris::io {
38
struct AsyncCacheWriteEpoch;
39
struct IOContext;
40
struct FileCacheStatistics;
41
struct PeerFetchResult;
42
43
} // namespace doris::io
44
45
namespace doris {
46
struct PeerCandidate;
47
}
48
49
namespace doris::io {
50
struct SourceReadBreakdown {
51
    int64_t local_bytes = 0;
52
    int64_t remote_bytes = 0;
53
    int64_t peer_bytes = 0;
54
};
55
using PeerFetchedBlockSet = std::unordered_set<const FileBlock*>;
56
57
class CachedRemoteFileReader final : public FileReader,
58
                                     public std::enable_shared_from_this<CachedRemoteFileReader> {
59
public:
60
    /// Construct a cached reader on top of a remote reader.
61
    /// @param[in] remote_file_reader Underlying reader used for remote/peer fallback reads.
62
    /// @param[in] opts File reader options used to initialize cache identity and policy.
63
    /// @return None.
64
    CachedRemoteFileReader(FileReaderSPtr remote_file_reader, const FileReaderOptions& opts);
65
66
    /// Destroy the cached reader and release direct cache-file ownership tracked by this reader.
67
    /// @return None.
68
    ~CachedRemoteFileReader() override;
69
70
    /// Close the underlying remote reader.
71
    /// @return OK on success; otherwise the close error from the underlying reader.
72
    Status close() override;
73
74
    /// Get the path of the underlying file.
75
    /// @return Reference to the remote reader path.
76
7.23k
    const Path& path() const override { return _remote_file_reader->path(); }
77
78
    /// Get the logical size of the underlying file.
79
    /// @return File size in bytes.
80
2.15M
    size_t size() const override { return _remote_file_reader->size(); }
81
82
    /// Check whether the underlying reader has been closed.
83
    /// @return true if the underlying reader is closed; otherwise false.
84
718k
    bool closed() const override { return _remote_file_reader->closed(); }
85
86
    /// Expose the wrapped remote reader.
87
    /// @return Raw pointer to the underlying reader owned by this object.
88
1.00k
    FileReader* get_remote_reader() { return _remote_file_reader.get(); }
89
90
    /// Align a read range to file-cache block boundaries.
91
    /// @param[in] offset Requested read offset in bytes.
92
    /// @param[in] size Requested read size in bytes.
93
    /// @param[in] length Total file length in bytes.
94
    /// @return Pair of aligned start offset and aligned size.
95
    static std::pair<size_t, size_t> s_align_size(size_t offset, size_t size, size_t length);
96
97
0
    int64_t mtime() const override { return _remote_file_reader->mtime(); }
98
99
    // Asynchronously prefetch a range of file cache blocks.
100
    // This method triggers read file cache in dryrun mode to warm up the cache
101
    // without actually reading the data into user buffers.
102
    //
103
    // Parameters:
104
    //   offset: Starting offset in the file
105
    //   size: Number of bytes to prefetch
106
    //   io_ctx: IO context (can be nullptr, will create a dryrun context internally)
107
    //
108
    // Note: This is a best-effort operation. Errors are logged but not returned.
109
    void prefetch_range(size_t offset, size_t size, const IOContext* io_ctx = nullptr);
110
111
protected:
112
    /// Read bytes from cache when possible and fall back to peer/S3 when needed.
113
    /// @param[in] offset Start offset in the file.
114
    /// @param[out] result Destination buffer for the requested bytes.
115
    /// @param[out] bytes_read Number of bytes copied into result.
116
    /// @param[in] io_ctx IO context carrying dry-run, warmup and statistics options.
117
    /// @return OK on success; otherwise an error from cache lookup or remote read.
118
    Status read_at_impl(size_t offset, Slice result, size_t* bytes_read,
119
                        const IOContext* io_ctx) override;
120
121
private:
122
    struct AsyncReadBlock;
123
    struct AsyncReadPlan;
124
125
    enum class FileCacheReadType {
126
        DATA,
127
        INVERTED_INDEX,
128
        SEGMENT_FOOTER_INDEX,
129
    };
130
131
    /// Initialize cache metadata for Doris-table files.
132
    /// @return None.
133
    void _init_doris_table_cache();
134
135
    /// Initialize cache metadata for external-table files.
136
    /// @param[in] opts Reader options used to choose cache key and cache base path.
137
    /// @return None.
138
    void _init_external_table_cache(const FileReaderOptions& opts);
139
140
    /// Check whether this reader can read cache files directly without get_or_set.
141
    /// @return true when direct cache-file reads are enabled for Doris-table files.
142
    bool _can_read_cache_file_directly() const;
143
144
    /// Decide whether remote cache miss reads should try peer cache first.
145
    /// @param[in] io_ctx IO context for warmup and request-mode checks.
146
    /// @return true if peer read is enabled for this request; otherwise false.
147
    bool _should_read_from_peer(const IOContext* io_ctx) const;
148
149
    /// Resolve the write policy for the current read instead of freezing a global setting in the
150
    /// reader constructor. Explicit cache-population reads always remain synchronous.
151
    /// @param[in] io_ctx Per-read flags and an optional write-mode override.
152
    /// @return The effective synchronous or asynchronous cache-write mode for this read.
153
    CacheWriteMode _resolve_cache_write_mode(const IOContext* io_ctx) const;
154
155
    /// Serve a normal read while moving cache-miss writes off the query thread. The method uses
156
    /// the first and last remotely covered blocks as one range, matching the synchronous path's
157
    /// preference for a single remote operation over fine-grained hole processing.
158
    /// @param[in] offset Original user read offset.
159
    /// @param[out] result Destination buffer for the complete user request.
160
    /// @param[in] bytes_req Requested user bytes.
161
    /// @param[in] already_read Prefix bytes already filled by the direct-cache path.
162
    /// @param[out] bytes_read Total completed user bytes.
163
    /// @param[in,out] stats Per-read cache statistics.
164
    /// @param[in,out] source_read_breakdown Local/remote byte attribution for query profiles.
165
    /// @param[in] io_ctx Context passed to cache lookup and remote IO.
166
    /// @return OK on success; otherwise the remote-read error.
167
    Status _read_async_write_path(size_t offset, Slice result, size_t bytes_req,
168
                                  size_t already_read, size_t* bytes_read, ReadStatistics& stats,
169
                                  SourceReadBreakdown& source_read_breakdown,
170
                                  const IOContext* io_ctx);
171
172
    /// Build ordered, gap-free cache-block coverage for the unread suffix. Block offsets are
173
    /// cache-block aligned; only the physical EOF block may be short. Vector indexes remain
174
    /// identical across inflight lookup, cache probe, materialization, remote slicing, and task
175
    /// submission. A fully inflight-covered request skips BlockFileCache::probe; otherwise one
176
    /// whole-range probe returns exactly one entry per logical block.
177
    /// @param[in] remaining_offset First user byte not filled by the direct-cache path.
178
    /// @param[in] remaining_size Number of unread user bytes.
179
    /// @param[in] write_epoch Epoch captured before any lookup or remote IO.
180
    /// @param[in] io_ctx Context used to build the cache admission/probe context.
181
    /// @param[in,out] stats Lookup and probe counters updated during planning.
182
    /// @return Plan that owns any retained probe blocks and first-to-last remote range.
183
    AsyncReadPlan _build_async_read_plan(size_t remaining_offset, size_t remaining_size,
184
                                         AsyncCacheWriteEpoch write_epoch, const IOContext* io_ctx,
185
                                         ReadStatistics& stats);
186
187
    /// Copy one block already available from an inflight buffer or downloaded cache file. Cache
188
    /// state is revalidated before IO; a race is reported to the caller as a simple full-range
189
    /// remote fallback.
190
    /// @param[in] plan Plan owning the probed blocks and user boundaries.
191
    /// @param[in] block_index Index of the aligned block and its matching probe result.
192
    /// @param[in] user_offset Original user request offset used to locate the destination slice.
193
    /// @param[out] result Destination buffer for the complete user request.
194
    /// @param[in] cache_context Context used only when a successful local read touches LRU.
195
    /// @param[in,out] stats Local-read timing counters.
196
    /// @param[in,out] materialized_bytes User bytes copied from cache or inflight memory.
197
    /// @param[in,out] need_self_heal Set when a cache file disappears during a local read.
198
    /// @return true when the block was copied; false when the caller should use remote fallback.
199
    bool _materialize_async_block(const AsyncReadPlan& plan, size_t block_index, size_t user_offset,
200
                                  Slice result, const CacheContext& cache_context,
201
                                  ReadStatistics& stats, size_t* materialized_bytes,
202
                                  bool* need_self_heal);
203
204
    /// Copy only blocks before the first and after the last REMOTE block. When no REMOTE block
205
    /// exists, copy the entire request. DOWNLOADING blocks outside the remote span keep the
206
    /// existing wait behavior; blocks inside the span are covered by the same remote read.
207
    /// @param[in] plan Classified block list and remote boundaries.
208
    /// @param[in] user_offset Original user request offset.
209
    /// @param[out] result Destination buffer for side data.
210
    /// @param[in] cache_context Context used for successful local-cache touches.
211
    /// @param[in,out] stats Local-read statistics.
212
    /// @param[in,out] source_read_breakdown Local bytes copied from the covered sides.
213
    /// @param[in,out] indirect_read_bytes User bytes copied from the covered sides.
214
    /// @param[in,out] need_self_heal Whether a missing local cache file requires async cleanup.
215
    /// @return true when all selected cache/inflight blocks were copied; false on a race/read error.
216
    bool _materialize_async_cached_sides(const AsyncReadPlan& plan, size_t user_offset,
217
                                         Slice result, const CacheContext& cache_context,
218
                                         ReadStatistics& stats,
219
                                         SourceReadBreakdown& source_read_breakdown,
220
                                         size_t* indirect_read_bytes, bool* need_self_heal);
221
222
    /// Read the planned middle span once and copy only its overlap with the unread user range.
223
    /// @param[in] plan Source plan containing user boundaries.
224
    /// @param[in] user_offset Original user request offset.
225
    /// @param[out] result Destination buffer for the complete user request.
226
    /// @param[in] need_self_heal Whether stale cache metadata should be removed before remote IO.
227
    /// @param[in] io_ctx Context passed to remote storage.
228
    /// @param[in,out] stats Remote-read timing and source flags.
229
    /// @param[in,out] source_read_breakdown Remote user bytes copied from this span.
230
    /// @param[in,out] indirect_read_bytes User bytes copied by the indirect path.
231
    /// @param[out] remote_buffer Full aligned middle-span payload retained for async tasks.
232
    /// @return OK on success; otherwise the remote-read error.
233
    Status _read_async_remote_range(const AsyncReadPlan& plan, size_t user_offset, Slice result,
234
                                    bool need_self_heal, const IOContext* io_ctx,
235
                                    ReadStatistics& stats,
236
                                    SourceReadBreakdown& source_read_breakdown,
237
                                    size_t* indirect_read_bytes,
238
                                    std::unique_ptr<char[]>* remote_buffer);
239
240
    /// Copy each real cache-miss block from the remote span into one fixed cache-block-sized
241
    /// tracked buffer and enqueue a per-block write task. `write_size` records the valid prefix for
242
    /// a short physical EOF block. A final insert-if-absent prevents duplicate ownership after IO.
243
    /// @param[in] plan Classified blocks, remote boundaries, and the epoch captured before IO.
244
    /// @param[in] remote_buffer Full payload for the plan's first-to-last remote span.
245
    /// @param[in] io_ctx Context converted to the worker's admission context.
246
    /// @param[in,out] stats Submission, rejection, allocation, and dedup counters.
247
    /// @return None.
248
    void _submit_async_write_tasks(const AsyncReadPlan& plan,
249
                                   const std::unique_ptr<char[]>& remote_buffer,
250
                                   const IOContext* io_ctx, ReadStatistics& stats);
251
252
    /// Register a downloaded block in the direct-read map owned by this reader.
253
    /// @param[in] file_block Downloaded cache block to insert.
254
    /// @return None.
255
    void _insert_file_reader(FileBlockSPtr file_block);
256
257
    /// Try to satisfy the request by reading already downloaded cache files directly.
258
    /// @param[in] offset Requested file offset.
259
    /// @param[out] result Destination buffer for the request.
260
    /// @param[in] bytes_req Requested byte count.
261
    /// @param[in] is_dryrun True if local cache IO should be skipped.
262
    /// @param[in,out] stats Read statistics updated during the attempt.
263
    /// @param[in,out] already_read Bytes already filled into result by direct cache reads.
264
    /// @param[out] bytes_read Total bytes read when the whole request is satisfied directly.
265
    /// @return true if the whole request is completed by direct cache-file reads; otherwise false.
266
    bool _try_read_from_cached_files_directly(size_t offset, Slice result, size_t bytes_req,
267
                                              bool is_dryrun, ReadStatistics& stats,
268
                                              SourceReadBreakdown& source_read_breakdown,
269
                                              size_t& already_read, size_t* bytes_read);
270
271
    /// Collect blocks that still need remote data and update cache-hit statistics.
272
    /// @param[in] holder Cache blocks covering the aligned request range.
273
    /// @param[in,out] stats Read statistics updated according to block states.
274
    /// @return Blocks that should be fetched from peer/S3 by the current reader.
275
    std::vector<FileBlockSPtr> _collect_remote_read_blocks(const FileBlocksHolder& holder,
276
                                                           ReadStatistics& stats);
277
278
    /// Fetch missing blocks from peer/S3, write them into cache, and copy the overlap to result.
279
    /// @param[in] empty_blocks Blocks selected for remote fetch.
280
    /// @param[in] offset Original request offset.
281
    /// @param[in] bytes_req Original request size.
282
    /// @param[in] already_read Bytes already produced before this step.
283
    /// @param[out] result Destination buffer for the original request.
284
    /// @param[in] is_dryrun True if cache-file writes and local buffer copies should be skipped.
285
    /// @param[in,out] stats Read statistics updated for remote and local cache work.
286
    /// @param[in] io_ctx IO context passed to peer/S3 reads.
287
    /// @param[in,out] indirect_read_bytes Bytes copied into result through the indirect path.
288
    /// @param[out] empty_start Left boundary of the fetched contiguous empty range.
289
    /// @param[out] empty_end Right boundary of the fetched contiguous empty range.
290
    /// @param[out] peer_fetched_blocks Exact blocks fetched by peer in sparse mode; empty for S3.
291
    /// @return OK on success; otherwise an error from peer/S3 read.
292
    Status _read_remote_blocks_into_cache(const std::vector<FileBlockSPtr>& empty_blocks,
293
                                          size_t offset, size_t bytes_req, size_t already_read,
294
                                          Slice result, bool is_dryrun, ReadStatistics& stats,
295
                                          SourceReadBreakdown& source_read_breakdown,
296
                                          const IOContext* io_ctx, size_t& indirect_read_bytes,
297
                                          size_t& empty_start, size_t& empty_end,
298
                                          PeerFetchedBlockSet& peer_fetched_blocks);
299
300
    /// Read cached blocks that were not covered by the remote-fetch range, with remote fallback.
301
    /// @param[in] holder Cache blocks covering the aligned request range.
302
    /// @param[in] offset Original request offset.
303
    /// @param[in] bytes_req Original request size.
304
    /// @param[out] result Destination buffer for the original request.
305
    /// @param[in] is_dryrun True if local cache IO should be skipped.
306
    /// @param[in] empty_start Left boundary of the range already handled by remote fetch.
307
    /// @param[in] empty_end Right boundary of the range already handled by remote fetch.
308
    /// @param[in] peer_fetched_blocks Exact blocks already filled by peer; empty for S3 path.
309
    /// @param[in,out] stats Read statistics updated for wait, cache, and remote fallback paths.
310
    /// @param[in,out] indirect_read_bytes Bytes copied into result through this indirect stage.
311
    /// @param[out] bytes_read Total bytes covered for the original request after this stage.
312
    /// @return OK on success; otherwise an error from cache read or remote fallback read.
313
    Status _read_remaining_blocks_from_cache(const FileBlocksHolder& holder, size_t offset,
314
                                             size_t bytes_req, Slice result, bool is_dryrun,
315
                                             size_t empty_start, size_t empty_end,
316
                                             const PeerFetchedBlockSet& peer_fetched_blocks,
317
                                             ReadStatistics& stats,
318
                                             SourceReadBreakdown& source_read_breakdown,
319
                                             size_t& indirect_read_bytes, size_t* bytes_read,
320
                                             const IOContext* io_ctx);
321
322
    /// Read through the block-cache metadata path when direct cache-file reads are insufficient.
323
    /// @param[in] offset Original request offset.
324
    /// @param[out] result Destination buffer for the original request.
325
    /// @param[in] bytes_req Original request size.
326
    /// @param[in] already_read Bytes already produced by direct cache-file reads.
327
    /// @param[in] is_dryrun True if local cache IO should be skipped.
328
    /// @param[out] bytes_read Total bytes read for the request.
329
    /// @param[in,out] stats Read statistics updated across the indirect path.
330
    /// @param[in] io_ctx IO context passed to cache lookup and remote read.
331
    /// @return OK on success; otherwise an error from cache lookup or remote read.
332
    Status _read_from_indirect_cache(size_t offset, Slice result, size_t bytes_req,
333
                                     size_t already_read, bool is_dryrun, size_t* bytes_read,
334
                                     ReadStatistics& stats,
335
                                     SourceReadBreakdown& source_read_breakdown,
336
                                     const IOContext* io_ctx);
337
338
    /// Read local cache only when downloaded blocks fully cover the request; otherwise read remote
339
    /// data directly without writing file cache.
340
    /// @param[in] offset Original request offset.
341
    /// @param[out] result Destination buffer for the original request.
342
    /// @param[in] bytes_req Original request size.
343
    /// @param[in] is_dryrun True if local cache IO should be skipped.
344
    /// @param[out] bytes_read Total bytes read for the request.
345
    /// @param[in,out] stats Read statistics updated for local or remote work.
346
    /// @param[in,out] source_read_breakdown Source bytes used by profile metrics.
347
    /// @param[in] io_ctx IO context passed to cache lookup and remote read.
348
    /// @return OK on success; otherwise an error from cache lookup, cache read, or remote read.
349
    Status _read_remote_only_on_cache_miss(size_t offset, Slice result, size_t bytes_req,
350
                                           bool is_dryrun, size_t* bytes_read,
351
                                           ReadStatistics& stats,
352
                                           SourceReadBreakdown& source_read_breakdown,
353
                                           const IOContext* io_ctx);
354
355
    /// Fall back to S3: clear peer_result, allocate buffer, and read from remote storage.
356
    /// @param[in] empty_start Start offset of the contiguous remote-read range.
357
    /// @param[in] span_size Size of the remote-read range in bytes.
358
    /// @param[in,out] buffer Span buffer that receives S3 data.
359
    /// @param[in,out] peer_result Cleared when non-null.
360
    /// @param[in,out] stats Read statistics updated for S3 execution.
361
    /// @param[in] io_ctx IO context passed to the remote reader.
362
    /// @return OK on success; otherwise the S3 read error.
363
    Status _execute_s3_fallback(size_t empty_start, size_t span_size,
364
                                std::unique_ptr<char[]>& buffer, PeerFetchResult* peer_result,
365
                                ReadStatistics& stats, const IOContext* io_ctx);
366
367
    /// Sequential peer-then-S3 fallback: try the best peer candidate, update affinity on
368
    /// success/failure, and fall back to S3 if peer fails.
369
    /// @param[in] empty_blocks Blocks whose data is missing from local cache.
370
    /// @param[in] empty_start Start offset of the contiguous remote-read range.
371
    /// @param[in] span_size Size of the remote-read range in bytes.
372
    /// @param[in,out] buffer Span buffer that receives S3 data on S3 fallback.
373
    /// @param[in,out] peer_result Peer payloads populated on peer success.
374
    /// @param[in,out] stats Read statistics updated for peer/S3 execution.
375
    /// @param[in] io_ctx IO context passed to the remote reader.
376
    /// @param[in] candidates Peer candidates sorted by affinity.
377
    /// @param[in] tablet_id Tablet ID for affinity tracking.
378
    /// @return OK on success; otherwise the S3 read error.
379
    Status _execute_sequential_peer_read(const std::vector<FileBlockSPtr>& empty_blocks,
380
                                         size_t empty_start, size_t span_size,
381
                                         std::unique_ptr<char[]>& buffer,
382
                                         PeerFetchResult* peer_result, ReadStatistics& stats,
383
                                         const IOContext* io_ctx,
384
                                         const std::vector<doris::PeerCandidate>& candidates,
385
                                         int64_t tablet_id);
386
387
    /// Execute a remote fetch for the contiguous empty range, trying peer first when enabled.
388
    /// @param[in] empty_blocks Blocks whose data is missing from local cache.
389
    /// @param[in] empty_start Start offset of the contiguous remote-read range for S3 fallback.
390
    /// @param[in] span_size Size of the enclosing contiguous remote-read range for S3 fallback.
391
    /// @param[in,out] buffer Temporary span buffer receiving S3 data.
392
    /// @param[in,out] peer_result Segmented peer payloads when the peer path succeeds.
393
    /// @param[in,out] stats Read statistics updated for peer/S3 execution.
394
    /// @param[in] io_ctx IO context passed to the remote reader.
395
    /// @return OK on success; otherwise the peer/S3 read error.
396
    Status _execute_remote_read(const std::vector<FileBlockSPtr>& empty_blocks, size_t empty_start,
397
                                size_t span_size, std::unique_ptr<char[]>& buffer,
398
                                PeerFetchResult* peer_result, ReadStatistics& stats,
399
                                const IOContext* io_ctx);
400
401
    /// Execute a winner race between peer read and S3 read for cross compute group scenarios.
402
    /// Launches both peer and S3 reads concurrently in bthreads and returns the first successful
403
    /// result. Uses bthread::Mutex and bthread::ConditionVariable for synchronization.
404
    /// @param[in] empty_blocks Blocks whose data is missing from local cache.
405
    /// @param[in] empty_start Start offset of the contiguous remote-read range.
406
    /// @param[in] span_size Size of the contiguous range for the S3 fallback read.
407
    /// @param[in,out] buffer Temporary span buffer that receives S3 data on S3 win.
408
    /// @param[out] peer_result Peer fetch payloads populated when peer wins.
409
    /// @param[in,out] stats Read statistics updated for the winning path.
410
    /// @param[in] io_ctx IO context passed to both peer and S3 reads.
411
    /// @param[in] candidates All peer candidates for the tablet.
412
    /// @return OK on success with buffer or peer_result populated; otherwise an error.
413
    Status _execute_winner_race(const std::vector<FileBlockSPtr>& empty_blocks, size_t empty_start,
414
                                size_t span_size, std::unique_ptr<char[]>& buffer,
415
                                PeerFetchResult* peer_result, ReadStatistics& stats,
416
                                const IOContext* io_ctx,
417
                                const std::vector<doris::PeerCandidate>& candidates,
418
                                int64_t tablet_id);
419
420
    /// Merge per-read statistics into the external file-cache statistics accumulator.
421
    /// @param[in] stats Statistics produced by the current read.
422
    /// @param[in,out] state Destination statistics accumulator; ignored when null.
423
    /// @param[in] read_type Logical file-cache read type used for fine-grained profile counters.
424
    /// @return None.
425
    void _update_stats(const ReadStatistics& stats,
426
                       const SourceReadBreakdown& source_read_breakdown, FileCacheStatistics* state,
427
                       FileCacheReadType read_type) const;
428
429
    bool _is_doris_table = false;
430
    CacheAlignMode _cache_align_mode {CacheAlignMode::ALIGN_TO_BLOCK};
431
    CacheWriteMode _cache_write_mode {CacheWriteMode::DEFAULT};
432
    int64_t _tablet_id = -1;
433
    std::string _storage_resource_id;
434
    FileReaderSPtr _remote_file_reader;
435
    UInt128Wrapper _cache_hash;
436
    BlockFileCache* _cache = nullptr;
437
    std::shared_mutex _mtx;
438
    std::map<size_t, FileBlockSPtr> _cache_file_readers;
439
};
440
441
} // namespace doris::io