Coverage Report

Created: 2026-06-24 17:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/io/fs/file_meta_cache.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 <cstdint>
21
#include <memory>
22
#include <string>
23
#include <string_view>
24
25
#include "io/file_factory.h"
26
#include "io/fs/file_reader_writer_fwd.h"
27
#include "util/obj_lru_cache.h"
28
29
namespace doris {
30
31
namespace io {
32
class BlockFileCache;
33
struct UInt128Wrapper;
34
} // namespace io
35
36
enum class FileMetaCacheFormat : uint8_t {
37
    PARQUET = 1,
38
    ORC = 2,
39
};
40
41
struct FileMetaCacheContext {
42
    FileMetaCacheFormat format;
43
    const std::string& key;
44
    int64_t modification_time = 0;
45
    int64_t file_size = 0;
46
    bool enable_memory_cache = true;
47
};
48
49
enum class FileMetaCacheLookupState {
50
    MEMORY_HIT,
51
    PERSISTED_HIT,
52
    MISS,
53
};
54
55
struct FileMetaCacheLookupResult {
56
    FileMetaCacheLookupState state = FileMetaCacheLookupState::MISS;
57
};
58
59
struct FileMetaCacheInsertResult {
60
    bool memory_inserted = false;
61
    bool persisted_inserted = false;
62
};
63
64
struct FileMetaCacheProfile {
65
    int64_t* hit_cache = nullptr;
66
    int64_t* hit_memory_cache = nullptr;
67
    int64_t* hit_disk_cache = nullptr;
68
    int64_t* miss_disk_cache = nullptr;
69
    int64_t* write_disk_cache = nullptr;
70
    int64_t* read_disk_cache_time = nullptr;
71
    int64_t* write_disk_cache_time = nullptr;
72
};
73
74
// A file meta cache depends on a LRU cache.
75
// Such as parsed parquet footer.
76
// The capacity will limit the number of cache entries in cache.
77
class FileMetaCache {
78
public:
79
    explicit FileMetaCache(int64_t capacity, io::BlockFileCache* block_file_cache = nullptr);
80
81
    FileMetaCache(const FileMetaCache&) = delete;
82
    const FileMetaCache& operator=(const FileMetaCache&) = delete;
83
84
0
    ObjLRUCache& cache() { return _cache; }
85
86
    static std::string get_key(const std::string& file_name, int64_t modification_time,
87
                               int64_t file_size);
88
89
    static std::string get_key(io::FileReaderSPtr file_reader,
90
                               const io::FileDescription& _file_description);
91
92
    static bool is_persistent_cache_enabled();
93
    static bool is_persistent_cache_payload_size_allowed(uint64_t payload_size);
94
95
64.1k
    bool lookup(const std::string& key, ObjLRUCache::CacheHandle* handle) {
96
64.1k
        return _cache.lookup({key}, handle);
97
64.1k
    }
98
99
    template <typename T>
100
    void insert(const std::string& key, T* value, ObjLRUCache::CacheHandle* handle) {
101
        _cache.insert({key}, value, handle);
102
    }
103
104
    template <typename T>
105
    bool insert(const std::string& key, std::unique_ptr<T>& value,
106
12.8k
                ObjLRUCache::CacheHandle* handle) {
107
12.8k
        DCHECK(value != nullptr);
108
12.8k
        if (!_cache.enabled()) {
109
0
            return false;
110
0
        }
111
12.8k
        _cache.insert({key}, value.release(), handle);
112
12.8k
        return true;
113
12.8k
    }
_ZN5doris13FileMetaCache6insertINS_12FileMetaDataEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT_St14default_deleteISC_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
106
8.85k
                ObjLRUCache::CacheHandle* handle) {
107
8.85k
        DCHECK(value != nullptr);
108
8.85k
        if (!_cache.enabled()) {
109
0
            return false;
110
0
        }
111
8.85k
        _cache.insert({key}, value.release(), handle);
112
8.85k
        return true;
113
8.85k
    }
_ZN5doris13FileMetaCache6insertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKS7_RSt10unique_ptrIT_St14default_deleteISB_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
106
4.03k
                ObjLRUCache::CacheHandle* handle) {
107
4.03k
        DCHECK(value != nullptr);
108
4.03k
        if (!_cache.enabled()) {
109
0
            return false;
110
0
        }
111
4.03k
        _cache.insert({key}, value.release(), handle);
112
4.03k
        return true;
113
4.03k
    }
114
115
63.3k
    bool enabled() const { return _cache.enabled(); }
116
117
    FileMetaCacheLookupResult lookup(const FileMetaCacheContext& context,
118
                                     ObjLRUCache::CacheHandle* handle, std::string* serialized_meta,
119
                                     FileMetaCacheProfile* profile = nullptr);
120
121
    template <typename T>
122
    FileMetaCacheInsertResult insert(const FileMetaCacheContext& context, std::unique_ptr<T>& value,
123
                                     ObjLRUCache::CacheHandle* handle,
124
                                     std::string_view serialized_meta,
125
8.74k
                                     FileMetaCacheProfile* profile = nullptr) {
126
8.74k
        FileMetaCacheInsertResult result;
127
8.74k
        int64_t persisted_write_time = 0;
128
8.74k
        result.persisted_inserted =
129
8.74k
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
130
8.74k
        if (result.persisted_inserted && profile != nullptr) {
131
8.67k
            if (profile->write_disk_cache != nullptr) {
132
8.67k
                ++(*profile->write_disk_cache);
133
8.67k
            }
134
8.66k
            if (profile->write_disk_cache_time != nullptr) {
135
8.66k
                *profile->write_disk_cache_time += persisted_write_time;
136
8.66k
            }
137
8.66k
        }
138
8.75k
        if (context.enable_memory_cache) {
139
8.75k
            result.memory_inserted = insert(context.key, value, handle);
140
8.75k
        }
141
8.74k
        return result;
142
8.74k
    }
_ZN5doris13FileMetaCache6insertINS_12FileMetaDataEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteIS8_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcSt11char_traitsIcEEPNS_20FileMetaCacheProfileE
Line
Count
Source
125
6.12k
                                     FileMetaCacheProfile* profile = nullptr) {
126
6.12k
        FileMetaCacheInsertResult result;
127
6.12k
        int64_t persisted_write_time = 0;
128
6.12k
        result.persisted_inserted =
129
6.12k
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
130
6.12k
        if (result.persisted_inserted && profile != nullptr) {
131
6.09k
            if (profile->write_disk_cache != nullptr) {
132
6.09k
                ++(*profile->write_disk_cache);
133
6.09k
            }
134
6.09k
            if (profile->write_disk_cache_time != nullptr) {
135
6.09k
                *profile->write_disk_cache_time += persisted_write_time;
136
6.09k
            }
137
6.09k
        }
138
6.13k
        if (context.enable_memory_cache) {
139
6.13k
            result.memory_inserted = insert(context.key, value, handle);
140
6.13k
        }
141
6.12k
        return result;
142
6.12k
    }
_ZN5doris13FileMetaCache6insertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteISD_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcS5_EPNS_20FileMetaCacheProfileE
Line
Count
Source
125
2.62k
                                     FileMetaCacheProfile* profile = nullptr) {
126
2.62k
        FileMetaCacheInsertResult result;
127
2.62k
        int64_t persisted_write_time = 0;
128
2.62k
        result.persisted_inserted =
129
2.62k
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
130
2.62k
        if (result.persisted_inserted && profile != nullptr) {
131
2.57k
            if (profile->write_disk_cache != nullptr) {
132
2.57k
                ++(*profile->write_disk_cache);
133
2.57k
            }
134
2.57k
            if (profile->write_disk_cache_time != nullptr) {
135
2.57k
                *profile->write_disk_cache_time += persisted_write_time;
136
2.57k
            }
137
2.57k
        }
138
2.62k
        if (context.enable_memory_cache) {
139
2.62k
            result.memory_inserted = insert(context.key, value, handle);
140
2.62k
        }
141
2.62k
        return result;
142
2.62k
    }
143
144
private:
145
    static std::string get_persistent_cache_key(FileMetaCacheFormat format,
146
                                                std::string_view file_meta_cache_key);
147
    bool lookup_persistent_cache(const FileMetaCacheContext& context, std::string* payload,
148
                                 int64_t* read_time);
149
    bool insert_persistent_cache(const FileMetaCacheContext& context, std::string_view payload,
150
                                 int64_t* write_time);
151
    io::BlockFileCache* get_block_file_cache(const io::UInt128Wrapper& hash) const;
152
153
    ObjLRUCache _cache;
154
    io::BlockFileCache* _block_file_cache = nullptr;
155
};
156
157
} // namespace doris