Coverage Report

Created: 2026-07-12 20:33

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 "common/status.h"
26
#include "io/file_factory.h"
27
#include "io/fs/file_reader_writer_fwd.h"
28
#include "util/obj_lru_cache.h"
29
30
namespace doris {
31
32
enum class FileMetaCacheFormat : uint8_t {
33
    PARQUET = 1,
34
    ORC = 2,
35
    PARQUET_V2 = 3,
36
    ORC_V2 = 4,
37
};
38
39
struct FileMetaCacheContext {
40
    FileMetaCacheFormat format;
41
    const std::string& key;
42
    int64_t modification_time = 0;
43
    int64_t file_size = 0;
44
    bool enable_memory_cache = true;
45
};
46
47
enum class FileMetaCacheLookupState {
48
    MEMORY_HIT,
49
    PERSISTED_HIT,
50
    MISS,
51
};
52
53
struct FileMetaCacheLookupResult {
54
    FileMetaCacheLookupState state = FileMetaCacheLookupState::MISS;
55
};
56
57
struct FileMetaCacheInsertResult {
58
    bool memory_inserted = false;
59
    bool persisted_inserted = false;
60
};
61
62
struct FileMetaCacheProfile {
63
    int64_t* hit_cache = nullptr;
64
    int64_t* hit_memory_cache = nullptr;
65
    int64_t* hit_disk_cache = nullptr;
66
    int64_t* miss_disk_cache = nullptr;
67
    int64_t* write_disk_cache = nullptr;
68
    int64_t* read_disk_cache_time = nullptr;
69
    int64_t* write_disk_cache_time = nullptr;
70
};
71
72
class FileMetaPersistentCache {
73
public:
74
15
    virtual ~FileMetaPersistentCache() = default;
75
76
    virtual Status read(FileMetaCacheFormat format, const std::string& key,
77
                        int64_t modification_time, int64_t file_size, std::string* payload) = 0;
78
79
    virtual Status write(FileMetaCacheFormat format, const std::string& key,
80
                         int64_t modification_time, int64_t file_size,
81
                         std::string_view payload) = 0;
82
83
    virtual void remove(FileMetaCacheFormat format, const std::string& key) = 0;
84
};
85
86
// A file meta cache depends on a LRU cache.
87
// Such as parsed parquet footer.
88
// The capacity will limit the number of cache entries in cache.
89
class FileMetaCache {
90
public:
91
    explicit FileMetaCache(int64_t capacity,
92
                           std::unique_ptr<FileMetaPersistentCache> persistent_cache = nullptr);
93
94
    FileMetaCache(const FileMetaCache&) = delete;
95
    const FileMetaCache& operator=(const FileMetaCache&) = delete;
96
97
0
    ObjLRUCache& cache() { return _cache; }
98
99
    static std::string get_key(const std::string file_name, int64_t modification_time,
100
                               int64_t file_size);
101
102
    static std::string get_key(io::FileReaderSPtr file_reader,
103
                               const io::FileDescription& _file_description);
104
    static std::string get_memory_cache_key(FileMetaCacheFormat format, std::string_view key);
105
254k
    static std::string get_memory_cache_key(const FileMetaCacheContext& context) {
106
254k
        return get_memory_cache_key(context.format, context.key);
107
254k
    }
108
109
    static bool is_persistent_cache_configured();
110
    static bool is_persistent_cache_enabled();
111
    static bool is_persistent_cache_payload_size_allowed(uint64_t payload_size);
112
113
120k
    bool lookup(const std::string& key, ObjLRUCache::CacheHandle* handle) {
114
120k
        return _cache.lookup({key}, handle);
115
120k
    }
116
117
    template <typename T>
118
0
    void insert(const std::string& key, T* value, ObjLRUCache::CacheHandle* handle) {
119
0
        _cache.insert({key}, value, handle);
120
0
    }
121
122
    template <typename T>
123
    bool insert(const std::string& key, std::unique_ptr<T>& value,
124
10.5k
                ObjLRUCache::CacheHandle* handle) {
125
10.5k
        DCHECK(value != nullptr);
126
10.5k
        if (!_cache.enabled()) {
127
0
            return false;
128
0
        }
129
10.5k
        _cache.insert({key}, value.release(), handle);
130
10.5k
        return true;
131
10.5k
    }
_ZN5doris13FileMetaCache6insertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKS7_RSt10unique_ptrIT_St14default_deleteISB_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
124
3.16k
                ObjLRUCache::CacheHandle* handle) {
125
3.16k
        DCHECK(value != nullptr);
126
3.16k
        if (!_cache.enabled()) {
127
0
            return false;
128
0
        }
129
3.16k
        _cache.insert({key}, value.release(), handle);
130
3.16k
        return true;
131
3.16k
    }
_ZN5doris13FileMetaCache6insertISt10shared_ptrIN7parquet12FileMetaDataEEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT_St14default_deleteISF_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
124
7.33k
                ObjLRUCache::CacheHandle* handle) {
125
7.33k
        DCHECK(value != nullptr);
126
7.33k
        if (!_cache.enabled()) {
127
0
            return false;
128
0
        }
129
7.33k
        _cache.insert({key}, value.release(), handle);
130
7.33k
        return true;
131
7.33k
    }
_ZN5doris13FileMetaCache6insertINS_12FileMetaDataEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT_St14default_deleteISC_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
124
85
                ObjLRUCache::CacheHandle* handle) {
125
85
        DCHECK(value != nullptr);
126
85
        if (!_cache.enabled()) {
127
0
            return false;
128
0
        }
129
85
        _cache.insert({key}, value.release(), handle);
130
85
        return true;
131
85
    }
132
133
226k
    bool enabled() const { return _cache.enabled(); }
134
135
    FileMetaCacheLookupResult lookup(const FileMetaCacheContext& context,
136
                                     ObjLRUCache::CacheHandle* handle, std::string* serialized_meta,
137
                                     FileMetaCacheProfile* profile = nullptr);
138
139
    void invalidate_persistent_cache(const FileMetaCacheContext& context);
140
141
    template <typename T>
142
    FileMetaCacheInsertResult insert(const FileMetaCacheContext& context, std::unique_ptr<T>& value,
143
                                     ObjLRUCache::CacheHandle* handle,
144
                                     std::string_view serialized_meta,
145
10.7k
                                     FileMetaCacheProfile* profile = nullptr) {
146
10.7k
        FileMetaCacheInsertResult result;
147
10.7k
        int64_t persisted_write_time = 0;
148
10.7k
        result.persisted_inserted =
149
10.7k
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
150
10.7k
        if (result.persisted_inserted && profile != nullptr) {
151
2.17k
            if (profile->write_disk_cache != nullptr) {
152
2.17k
                ++(*profile->write_disk_cache);
153
2.17k
            }
154
2.17k
            if (profile->write_disk_cache_time != nullptr) {
155
2.17k
                *profile->write_disk_cache_time += persisted_write_time;
156
2.17k
            }
157
2.17k
        }
158
10.7k
        if (context.enable_memory_cache) {
159
10.1k
            result.memory_inserted = insert(get_memory_cache_key(context), value, handle);
160
10.1k
        }
161
10.7k
        return result;
162
10.7k
    }
_ZN5doris13FileMetaCache6insertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteISD_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcS5_EPNS_20FileMetaCacheProfileE
Line
Count
Source
145
3.29k
                                     FileMetaCacheProfile* profile = nullptr) {
146
3.29k
        FileMetaCacheInsertResult result;
147
3.29k
        int64_t persisted_write_time = 0;
148
3.29k
        result.persisted_inserted =
149
3.29k
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
150
3.29k
        if (result.persisted_inserted && profile != nullptr) {
151
1.09k
            if (profile->write_disk_cache != nullptr) {
152
1.09k
                ++(*profile->write_disk_cache);
153
1.09k
            }
154
1.08k
            if (profile->write_disk_cache_time != nullptr) {
155
1.08k
                *profile->write_disk_cache_time += persisted_write_time;
156
1.08k
            }
157
1.08k
        }
158
3.29k
        if (context.enable_memory_cache) {
159
2.98k
            result.memory_inserted = insert(get_memory_cache_key(context), value, handle);
160
2.98k
        }
161
3.29k
        return result;
162
3.29k
    }
_ZN5doris13FileMetaCache6insertISt10shared_ptrIN7parquet12FileMetaDataEEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteISB_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcSt11char_traitsIcEEPNS_20FileMetaCacheProfileE
Line
Count
Source
145
7.10k
                                     FileMetaCacheProfile* profile = nullptr) {
146
7.10k
        FileMetaCacheInsertResult result;
147
7.10k
        int64_t persisted_write_time = 0;
148
7.10k
        result.persisted_inserted =
149
7.10k
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
150
7.10k
        if (result.persisted_inserted && profile != nullptr) {
151
991
            if (profile->write_disk_cache != nullptr) {
152
991
                ++(*profile->write_disk_cache);
153
991
            }
154
989
            if (profile->write_disk_cache_time != nullptr) {
155
989
                *profile->write_disk_cache_time += persisted_write_time;
156
989
            }
157
989
        }
158
7.10k
        if (context.enable_memory_cache) {
159
7.10k
            result.memory_inserted = insert(get_memory_cache_key(context), value, handle);
160
7.10k
        }
161
7.10k
        return result;
162
7.10k
    }
_ZN5doris13FileMetaCache6insertINS_12FileMetaDataEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteIS8_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcSt11char_traitsIcEEPNS_20FileMetaCacheProfileE
Line
Count
Source
145
341
                                     FileMetaCacheProfile* profile = nullptr) {
146
341
        FileMetaCacheInsertResult result;
147
341
        int64_t persisted_write_time = 0;
148
341
        result.persisted_inserted =
149
341
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
150
341
        if (result.persisted_inserted && profile != nullptr) {
151
98
            if (profile->write_disk_cache != nullptr) {
152
98
                ++(*profile->write_disk_cache);
153
98
            }
154
98
            if (profile->write_disk_cache_time != nullptr) {
155
98
                *profile->write_disk_cache_time += persisted_write_time;
156
98
            }
157
98
        }
158
341
        if (context.enable_memory_cache) {
159
85
            result.memory_inserted = insert(get_memory_cache_key(context), value, handle);
160
85
        }
161
341
        return result;
162
341
    }
163
164
private:
165
    bool lookup_persistent_cache(const FileMetaCacheContext& context, std::string* payload,
166
                                 int64_t* read_time);
167
    bool insert_persistent_cache(const FileMetaCacheContext& context, std::string_view payload,
168
                                 int64_t* write_time);
169
170
    ObjLRUCache _cache;
171
    std::unique_ptr<FileMetaPersistentCache> _persistent_cache;
172
};
173
174
} // namespace doris