Coverage Report

Created: 2026-05-26 00:46

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
};
47
48
enum class FileMetaCacheLookupState {
49
    MEMORY_HIT,
50
    PERSISTED_HIT,
51
    MISS,
52
};
53
54
struct FileMetaCacheLookupResult {
55
    FileMetaCacheLookupState state = FileMetaCacheLookupState::MISS;
56
};
57
58
struct FileMetaCacheInsertResult {
59
    bool memory_inserted = false;
60
    bool persisted_inserted = false;
61
};
62
63
struct FileMetaCacheProfile {
64
    int64_t* hit_cache = nullptr;
65
    int64_t* hit_memory_cache = nullptr;
66
    int64_t* hit_disk_cache = nullptr;
67
    int64_t* miss_disk_cache = nullptr;
68
    int64_t* write_disk_cache = nullptr;
69
    int64_t* read_disk_cache_time = nullptr;
70
    int64_t* write_disk_cache_time = nullptr;
71
};
72
73
// A file meta cache depends on a LRU cache.
74
// Such as parsed parquet footer.
75
// The capacity will limit the number of cache entries in cache.
76
class FileMetaCache {
77
public:
78
    explicit FileMetaCache(int64_t capacity, io::BlockFileCache* block_file_cache = nullptr);
79
80
    FileMetaCache(const FileMetaCache&) = delete;
81
    const FileMetaCache& operator=(const FileMetaCache&) = delete;
82
83
0
    ObjLRUCache& cache() { return _cache; }
84
85
    static std::string get_key(const std::string file_name, int64_t modification_time,
86
                               int64_t file_size);
87
88
    static std::string get_key(io::FileReaderSPtr file_reader,
89
                               const io::FileDescription& _file_description);
90
91
76
    bool lookup(const std::string& key, ObjLRUCache::CacheHandle* handle) {
92
76
        return _cache.lookup({key}, handle);
93
76
    }
94
95
    template <typename T>
96
1
    void insert(const std::string& key, T* value, ObjLRUCache::CacheHandle* handle) {
97
1
        _cache.insert({key}, value, handle);
98
1
    }
99
100
    template <typename T>
101
    bool insert(const std::string& key, std::unique_ptr<T>& value,
102
45
                ObjLRUCache::CacheHandle* handle) {
103
45
        DCHECK(value != nullptr);
104
45
        if (!_cache.enabled()) {
105
0
            return false;
106
0
        }
107
45
        _cache.insert({key}, value.release(), handle);
108
45
        return true;
109
45
    }
_ZN5doris13FileMetaCache6insertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEbRKS7_RSt10unique_ptrIT_St14default_deleteISB_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
102
21
                ObjLRUCache::CacheHandle* handle) {
103
21
        DCHECK(value != nullptr);
104
21
        if (!_cache.enabled()) {
105
0
            return false;
106
0
        }
107
21
        _cache.insert({key}, value.release(), handle);
108
21
        return true;
109
21
    }
_ZN5doris13FileMetaCache6insertINS_12FileMetaDataEEEbRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERSt10unique_ptrIT_St14default_deleteISC_EEPNS_11ObjLRUCache11CacheHandleE
Line
Count
Source
102
24
                ObjLRUCache::CacheHandle* handle) {
103
24
        DCHECK(value != nullptr);
104
24
        if (!_cache.enabled()) {
105
0
            return false;
106
0
        }
107
24
        _cache.insert({key}, value.release(), handle);
108
24
        return true;
109
24
    }
110
111
0
    bool enabled() const { return _cache.enabled(); }
112
113
    bool should_enable_for_reader() const;
114
115
    FileMetaCacheLookupResult lookup(const FileMetaCacheContext& context,
116
                                     ObjLRUCache::CacheHandle* handle, std::string* serialized_meta,
117
                                     FileMetaCacheProfile* profile = nullptr);
118
119
    template <typename T>
120
    FileMetaCacheInsertResult insert(const FileMetaCacheContext& context, std::unique_ptr<T>& value,
121
                                     ObjLRUCache::CacheHandle* handle,
122
                                     std::string_view serialized_meta,
123
44
                                     FileMetaCacheProfile* profile = nullptr) {
124
44
        FileMetaCacheInsertResult result;
125
44
        int64_t persisted_write_time = 0;
126
44
        result.persisted_inserted =
127
44
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
128
44
        if (result.persisted_inserted && profile != nullptr) {
129
2
            if (profile->write_disk_cache != nullptr) {
130
2
                ++(*profile->write_disk_cache);
131
2
            }
132
2
            if (profile->write_disk_cache_time != nullptr) {
133
2
                *profile->write_disk_cache_time += persisted_write_time;
134
2
            }
135
2
        }
136
44
        result.memory_inserted = insert(context.key, value, handle);
137
44
        return result;
138
44
    }
_ZN5doris13FileMetaCache6insertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteISD_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcS5_EPNS_20FileMetaCacheProfileE
Line
Count
Source
123
20
                                     FileMetaCacheProfile* profile = nullptr) {
124
20
        FileMetaCacheInsertResult result;
125
20
        int64_t persisted_write_time = 0;
126
20
        result.persisted_inserted =
127
20
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
128
20
        if (result.persisted_inserted && profile != nullptr) {
129
2
            if (profile->write_disk_cache != nullptr) {
130
2
                ++(*profile->write_disk_cache);
131
2
            }
132
2
            if (profile->write_disk_cache_time != nullptr) {
133
2
                *profile->write_disk_cache_time += persisted_write_time;
134
2
            }
135
2
        }
136
20
        result.memory_inserted = insert(context.key, value, handle);
137
20
        return result;
138
20
    }
_ZN5doris13FileMetaCache6insertINS_12FileMetaDataEEENS_25FileMetaCacheInsertResultERKNS_20FileMetaCacheContextERSt10unique_ptrIT_St14default_deleteIS8_EEPNS_11ObjLRUCache11CacheHandleESt17basic_string_viewIcSt11char_traitsIcEEPNS_20FileMetaCacheProfileE
Line
Count
Source
123
24
                                     FileMetaCacheProfile* profile = nullptr) {
124
24
        FileMetaCacheInsertResult result;
125
24
        int64_t persisted_write_time = 0;
126
24
        result.persisted_inserted =
127
24
                insert_persistent_cache(context, serialized_meta, &persisted_write_time);
128
24
        if (result.persisted_inserted && profile != nullptr) {
129
0
            if (profile->write_disk_cache != nullptr) {
130
0
                ++(*profile->write_disk_cache);
131
0
            }
132
0
            if (profile->write_disk_cache_time != nullptr) {
133
0
                *profile->write_disk_cache_time += persisted_write_time;
134
0
            }
135
0
        }
136
24
        result.memory_inserted = insert(context.key, value, handle);
137
24
        return result;
138
24
    }
139
140
private:
141
    static std::string get_persistent_cache_key(FileMetaCacheFormat format,
142
                                                std::string_view file_meta_cache_key);
143
    bool lookup_persistent_cache(const FileMetaCacheContext& context, std::string* payload,
144
                                 int64_t* read_time);
145
    bool insert_persistent_cache(const FileMetaCacheContext& context, std::string_view payload,
146
                                 int64_t* write_time);
147
    io::BlockFileCache* get_block_file_cache(const io::UInt128Wrapper& hash) const;
148
149
    ObjLRUCache _cache;
150
    io::BlockFileCache* _block_file_cache = nullptr;
151
};
152
153
} // namespace doris