Coverage Report

Created: 2026-03-15 17:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/lru_multi_cache.inline.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
// This file is copied from
19
// https://github.com/apache/impala/blob/master/be/src/util/lru-multi-cache.inline.h
20
// and modified by Doris
21
22
#pragma once
23
24
#include <glog/logging.h>
25
26
#include "util/hash_util.hpp" // IWYU pragma: keep
27
#include "util/lru_multi_cache.h"
28
#include "util/time.h"
29
30
namespace doris {
31
32
template <typename KeyType, typename ValueType>
33
template <typename... Args>
34
LruMultiCache<KeyType, ValueType>::ValueType_internal::ValueType_internal(
35
        LruMultiCache& cache, const KeyType& key, Container_internal& container, Args&&... args)
36
123
        : cache(cache),
37
123
          key(key),
38
123
          container(container),
39
123
          value(std::forward<Args>(args)...),
40
123
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJRifEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
5
        : cache(cache),
37
5
          key(key),
38
5
          container(container),
39
5
          value(std::forward<Args>(args)...),
40
5
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJifEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
9
        : cache(cache),
37
9
          key(key),
38
9
          container(container),
39
9
          value(std::forward<Args>(args)...),
40
9
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJRmfEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
40
        : cache(cache),
37
40
          key(key),
38
40
          container(container),
39
40
          value(std::forward<Args>(args)...),
40
40
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJmfEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
59
        : cache(cache),
37
59
          key(key),
38
59
          container(container),
39
59
          value(std::forward<Args>(args)...),
40
59
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE18ValueType_internalC2IJRifEEERS3_RKS1_RNSt7__cxx114listIS4_SaIS4_EEEDpOT_
Line
Count
Source
36
5
        : cache(cache),
37
5
          key(key),
38
5
          container(container),
39
5
          value(std::forward<Args>(args)...),
40
5
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE18ValueType_internalC2IJifEEERS3_RKS1_RNSt7__cxx114listIS4_SaIS4_EEEDpOT_
Line
Count
Source
36
5
        : cache(cache),
37
5
          key(key),
38
5
          container(container),
39
5
          value(std::forward<Args>(args)...),
40
5
          timestamp_seconds(MonotonicSeconds()) {}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE18ValueType_internalC2IJRKP13hdfs_internalRKS7_RlEEERSB_RKS8_RNS2_4listISC_SaISC_EEEDpOT_
41
42
template <typename KeyType, typename ValueType>
43
352
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
352
    return member_hook.is_linked();
45
352
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internal12is_availableEv
Line
Count
Source
43
277
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
277
    return member_hook.is_linked();
45
277
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE18ValueType_internal12is_availableEv
Line
Count
Source
43
75
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
75
    return member_hook.is_linked();
45
75
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE18ValueType_internal12is_availableEv
46
47
template <typename KeyType, typename ValueType>
48
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(ValueType_internal* p_value_internal)
49
222
        : _p_value_internal(p_value_internal) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessorC2EPNS8_18ValueType_internalE
Line
Count
Source
49
172
        : _p_value_internal(p_value_internal) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8AccessorC2EPNS3_18ValueType_internalE
Line
Count
Source
49
50
        : _p_value_internal(p_value_internal) {}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8AccessorC2EPNSB_18ValueType_internalE
50
51
template <typename KeyType, typename ValueType>
52
25
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
25
    _p_value_internal = std::move(rhs._p_value_internal);
54
25
    rhs._p_value_internal = nullptr;
55
25
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessorC2EOS9_
Line
Count
Source
52
25
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
25
    _p_value_internal = std::move(rhs._p_value_internal);
54
25
    rhs._p_value_internal = nullptr;
55
25
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8AccessorC2EOSC_
56
template <typename KeyType, typename ValueType>
57
45
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
45
    _p_value_internal = std::move(rhs._p_value_internal);
59
45
    rhs._p_value_internal = nullptr;
60
45
    return (*this);
61
45
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessoraSEOS9_
Line
Count
Source
57
25
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
25
    _p_value_internal = std::move(rhs._p_value_internal);
59
25
    rhs._p_value_internal = nullptr;
60
25
    return (*this);
61
25
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8AccessoraSEOS4_
Line
Count
Source
57
20
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
20
    _p_value_internal = std::move(rhs._p_value_internal);
59
20
    rhs._p_value_internal = nullptr;
60
20
    return (*this);
61
20
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8AccessoraSEOSC_
62
63
template <typename KeyType, typename ValueType>
64
247
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
247
    release();
66
247
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessorD2Ev
Line
Count
Source
64
197
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
197
    release();
66
197
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8AccessorD2Ev
Line
Count
Source
64
50
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
50
    release();
66
50
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8AccessorD2Ev
67
68
template <typename KeyType, typename ValueType>
69
101
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
101
    if (_p_value_internal) {
71
81
        return &(_p_value_internal->value);
72
81
    }
73
74
20
    return nullptr;
75
101
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8Accessor3getEv
Line
Count
Source
69
61
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
61
    if (_p_value_internal) {
71
51
        return &(_p_value_internal->value);
72
51
    }
73
74
10
    return nullptr;
75
61
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8Accessor3getEv
Line
Count
Source
69
40
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
40
    if (_p_value_internal) {
71
30
        return &(_p_value_internal->value);
72
30
    }
73
74
10
    return nullptr;
75
40
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8Accessor3getEv
76
77
template <typename KeyType, typename ValueType>
78
0
const KeyType* LruMultiCache<KeyType, ValueType>::Accessor::get_key() const {
79
0
    if (_p_value_internal) {
80
0
        return &(_p_value_internal->key);
81
0
    }
82
83
0
    return nullptr;
84
0
}
85
86
template <typename KeyType, typename ValueType>
87
403
void LruMultiCache<KeyType, ValueType>::Accessor::release() {
88
    /// Nullptr check as it has to be dereferenced to get the cache reference
89
    /// No nullptr check is needed inside LruMultiCache::Release()
90
403
    if (_p_value_internal) {
91
200
        LruMultiCache& cache = _p_value_internal->cache;
92
200
        cache.release(_p_value_internal);
93
200
        _p_value_internal = nullptr;
94
200
    }
95
403
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8Accessor7releaseEv
Line
Count
Source
87
313
void LruMultiCache<KeyType, ValueType>::Accessor::release() {
88
    /// Nullptr check as it has to be dereferenced to get the cache reference
89
    /// No nullptr check is needed inside LruMultiCache::Release()
90
313
    if (_p_value_internal) {
91
160
        LruMultiCache& cache = _p_value_internal->cache;
92
160
        cache.release(_p_value_internal);
93
160
        _p_value_internal = nullptr;
94
160
    }
95
313
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8Accessor7releaseEv
Line
Count
Source
87
90
void LruMultiCache<KeyType, ValueType>::Accessor::release() {
88
    /// Nullptr check as it has to be dereferenced to get the cache reference
89
    /// No nullptr check is needed inside LruMultiCache::Release()
90
90
    if (_p_value_internal) {
91
40
        LruMultiCache& cache = _p_value_internal->cache;
92
40
        cache.release(_p_value_internal);
93
40
        _p_value_internal = nullptr;
94
40
    }
95
90
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8Accessor7releaseEv
96
97
template <typename KeyType, typename ValueType>
98
2
void LruMultiCache<KeyType, ValueType>::Accessor::destroy() {
99
    /// Nullptr check as it has to be dereferenced to get the cache reference
100
    /// No nullptr check is needed inside LruMultiCache::destroy()
101
2
    if (_p_value_internal) {
102
2
        LruMultiCache& cache = _p_value_internal->cache;
103
2
        cache.destroy(_p_value_internal);
104
2
        _p_value_internal = nullptr;
105
2
    }
106
2
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8Accessor7destroyEv
Line
Count
Source
98
2
void LruMultiCache<KeyType, ValueType>::Accessor::destroy() {
99
    /// Nullptr check as it has to be dereferenced to get the cache reference
100
    /// No nullptr check is needed inside LruMultiCache::destroy()
101
2
    if (_p_value_internal) {
102
2
        LruMultiCache& cache = _p_value_internal->cache;
103
2
        cache.destroy(_p_value_internal);
104
2
        _p_value_internal = nullptr;
105
2
    }
106
2
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE8Accessor7destroyEv
107
108
template <typename KeyType, typename ValueType>
109
6
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEEC2Em
Line
Count
Source
109
5
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEEC2Em
Line
Count
Source
109
1
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEEC2Em
110
111
template <typename KeyType, typename ValueType>
112
118
size_t LruMultiCache<KeyType, ValueType>::size() {
113
118
    std::lock_guard<std::mutex> g(_lock);
114
118
    return _size;
115
118
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE4sizeEv
Line
Count
Source
112
117
size_t LruMultiCache<KeyType, ValueType>::size() {
113
117
    std::lock_guard<std::mutex> g(_lock);
114
117
    return _size;
115
117
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE4sizeEv
Line
Count
Source
112
1
size_t LruMultiCache<KeyType, ValueType>::size() {
113
1
    std::lock_guard<std::mutex> g(_lock);
114
1
    return _size;
115
1
}
116
117
template <typename KeyType, typename ValueType>
118
14
size_t LruMultiCache<KeyType, ValueType>::number_of_keys() {
119
14
    std::lock_guard<std::mutex> g(_lock);
120
14
    return _hash_table.size();
121
14
}
122
123
template <typename KeyType, typename ValueType>
124
0
void LruMultiCache<KeyType, ValueType>::set_capacity(size_t new_capacity) {
125
0
    std::lock_guard<std::mutex> g(_lock);
126
0
    _capacity = new_capacity;
127
0
}
128
129
template <typename KeyType, typename ValueType>
130
99
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
99
    std::lock_guard<std::mutex> g(_lock);
132
99
    auto hash_table_it = _hash_table.find(key);
133
134
    // No owning list found with this key, the caller will have to create a new object
135
    // with EmplaceAndGet()
136
99
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
89
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
89
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
89
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
89
    if (!container_it->is_available()) return Accessor();
149
150
    // Move the object to the back of the owning list as it is no longer available.
151
79
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
79
    container_it->member_hook.unlink();
155
156
79
    return Accessor(&(*container_it));
157
89
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE3getERKS6_
Line
Count
Source
130
59
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
59
    std::lock_guard<std::mutex> g(_lock);
132
59
    auto hash_table_it = _hash_table.find(key);
133
134
    // No owning list found with this key, the caller will have to create a new object
135
    // with EmplaceAndGet()
136
59
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
54
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
54
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
54
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
54
    if (!container_it->is_available()) return Accessor();
149
150
    // Move the object to the back of the owning list as it is no longer available.
151
49
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
49
    container_it->member_hook.unlink();
155
156
49
    return Accessor(&(*container_it));
157
54
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE3getERKS1_
Line
Count
Source
130
40
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
40
    std::lock_guard<std::mutex> g(_lock);
132
40
    auto hash_table_it = _hash_table.find(key);
133
134
    // No owning list found with this key, the caller will have to create a new object
135
    // with EmplaceAndGet()
136
40
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
35
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
35
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
35
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
35
    if (!container_it->is_available()) return Accessor();
149
150
    // Move the object to the back of the owning list as it is no longer available.
151
30
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
30
    container_it->member_hook.unlink();
155
156
30
    return Accessor(&(*container_it));
157
35
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE3getERKS8_
158
159
template <typename KeyType, typename ValueType>
160
template <typename... Args>
161
auto LruMultiCache<KeyType, ValueType>::emplace_and_get(const KeyType& key, Args&&... args)
162
123
        -> Accessor {
163
123
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
123
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
123
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
123
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
123
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
123
    container_it->it = container_it;
178
179
123
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
123
    _evict_one_if_needed();
183
184
123
    return Accessor(&(*container_it));
185
123
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJRifEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
5
        -> Accessor {
163
5
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
5
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
5
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
5
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
5
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
5
    container_it->it = container_it;
178
179
5
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
5
    _evict_one_if_needed();
183
184
5
    return Accessor(&(*container_it));
185
5
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJifEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
9
        -> Accessor {
163
9
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
9
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
9
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
9
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
9
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
9
    container_it->it = container_it;
178
179
9
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
9
    _evict_one_if_needed();
183
184
9
    return Accessor(&(*container_it));
185
9
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJRmfEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
40
        -> Accessor {
163
40
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
40
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
40
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
40
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
40
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
40
    container_it->it = container_it;
178
179
40
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
40
    _evict_one_if_needed();
183
184
40
    return Accessor(&(*container_it));
185
40
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJmfEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
59
        -> Accessor {
163
59
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
59
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
59
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
59
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
59
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
59
    container_it->it = container_it;
178
179
59
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
59
    _evict_one_if_needed();
183
184
59
    return Accessor(&(*container_it));
185
59
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE15emplace_and_getIJRifEEENS3_8AccessorERKS1_DpOT_
Line
Count
Source
162
5
        -> Accessor {
163
5
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
5
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
5
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
5
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
5
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
5
    container_it->it = container_it;
178
179
5
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
5
    _evict_one_if_needed();
183
184
5
    return Accessor(&(*container_it));
185
5
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE15emplace_and_getIJifEEENS3_8AccessorERKS1_DpOT_
Line
Count
Source
162
5
        -> Accessor {
163
5
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
5
    Container& container = _hash_table[key];
167
168
    // Get the reference of the key stored in unordered_map, the parameter could be
169
    // temporary object but std::unordered_map has stable references
170
5
    const KeyType& stored_key = _hash_table.find(key)->first;
171
172
    // Place it as the last entry for the owning list, as it just got reserved
173
5
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
5
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
5
    container_it->it = container_it;
178
179
5
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
5
    _evict_one_if_needed();
183
184
5
    return Accessor(&(*container_it));
185
5
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE15emplace_and_getIJRKP13hdfs_internalRKS7_RlEEENSB_8AccessorERKS8_DpOT_
186
187
template <typename KeyType, typename ValueType>
188
200
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
200
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
200
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
200
    DCHECK(!p_value_internal->is_available());
196
197
    // DO NOT update timestamp_seconds when release.
198
    // Because we are about to evict cache value after a certain period.
199
200
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
200
    Container& container = p_value_internal->container;
202
203
    // Move the object to the front, keep LRU relation in owning list too to
204
    // be able to age out unused objects
205
200
    container.splice(container.begin(), container, p_value_internal->it);
206
207
    // Add the object to LRU list too as it is now available for usage
208
200
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
200
    _evict_one_if_needed();
212
200
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE7releaseEPNS8_18ValueType_internalE
Line
Count
Source
188
160
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
160
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
160
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
160
    DCHECK(!p_value_internal->is_available());
196
197
    // DO NOT update timestamp_seconds when release.
198
    // Because we are about to evict cache value after a certain period.
199
160
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
160
    Container& container = p_value_internal->container;
202
203
    // Move the object to the front, keep LRU relation in owning list too to
204
    // be able to age out unused objects
205
160
    container.splice(container.begin(), container, p_value_internal->it);
206
207
    // Add the object to LRU list too as it is now available for usage
208
160
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
160
    _evict_one_if_needed();
212
160
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE7releaseEPNS3_18ValueType_internalE
Line
Count
Source
188
40
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
40
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
40
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
40
    DCHECK(!p_value_internal->is_available());
196
197
    // DO NOT update timestamp_seconds when release.
198
    // Because we are about to evict cache value after a certain period.
199
40
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
40
    Container& container = p_value_internal->container;
202
203
    // Move the object to the front, keep LRU relation in owning list too to
204
    // be able to age out unused objects
205
40
    container.splice(container.begin(), container, p_value_internal->it);
206
207
    // Add the object to LRU list too as it is now available for usage
208
40
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
40
    _evict_one_if_needed();
212
40
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE7releaseEPNSB_18ValueType_internalE
213
214
template <typename KeyType, typename ValueType>
215
2
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
2
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
2
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
2
    DCHECK(!p_value_internal->is_available());
223
224
2
    Container& container = p_value_internal->container;
225
226
2
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
1
        _hash_table.erase(p_value_internal->key);
229
1
    } else {
230
        // Remove from owning list
231
1
        container.erase(p_value_internal->it);
232
1
    }
233
234
2
    _size--;
235
2
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE7destroyEPNS8_18ValueType_internalE
Line
Count
Source
215
2
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
2
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
2
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
2
    DCHECK(!p_value_internal->is_available());
223
224
2
    Container& container = p_value_internal->container;
225
226
2
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
1
        _hash_table.erase(p_value_internal->key);
229
1
    } else {
230
        // Remove from owning list
231
1
        container.erase(p_value_internal->it);
232
1
    }
233
234
2
    _size--;
235
2
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE7destroyEPNSB_18ValueType_internalE
236
237
template <typename KeyType, typename ValueType>
238
118
size_t LruMultiCache<KeyType, ValueType>::number_of_available_objects() {
239
118
    std::lock_guard<std::mutex> g(_lock);
240
118
    return _lru_list.size();
241
118
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE27number_of_available_objectsEv
Line
Count
Source
238
117
size_t LruMultiCache<KeyType, ValueType>::number_of_available_objects() {
239
117
    std::lock_guard<std::mutex> g(_lock);
240
117
    return _lru_list.size();
241
117
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE27number_of_available_objectsEv
Line
Count
Source
238
1
size_t LruMultiCache<KeyType, ValueType>::number_of_available_objects() {
239
1
    std::lock_guard<std::mutex> g(_lock);
240
1
    return _lru_list.size();
241
1
}
242
243
template <typename KeyType, typename ValueType>
244
21
void LruMultiCache<KeyType, ValueType>::rehash() {
245
21
    std::lock_guard<std::mutex> g(_lock);
246
21
    _hash_table.rehash(_hash_table.bucket_count() + 1);
247
21
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE6rehashEv
Line
Count
Source
244
11
void LruMultiCache<KeyType, ValueType>::rehash() {
245
11
    std::lock_guard<std::mutex> g(_lock);
246
11
    _hash_table.rehash(_hash_table.bucket_count() + 1);
247
11
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE6rehashEv
Line
Count
Source
244
10
void LruMultiCache<KeyType, ValueType>::rehash() {
245
10
    std::lock_guard<std::mutex> g(_lock);
246
10
    _hash_table.rehash(_hash_table.bucket_count() + 1);
247
10
}
248
249
template <typename KeyType, typename ValueType>
250
61
void LruMultiCache<KeyType, ValueType>::_evict_one(ValueType_internal& value_internal) {
251
    // std::mutex is locked by the caller evicting function
252
    // _lock.DCheckLocked();
253
254
    // Has to be available to evict
255
61
    DCHECK(value_internal.is_available());
256
257
    // Remove from LRU cache
258
61
    value_internal.member_hook.unlink();
259
260
61
    Container& container = value_internal.container;
261
262
61
    if (container.size() == 1) {
263
        // Last element, owning list can be removed to prevent aging
264
1
        _hash_table.erase(value_internal.key);
265
60
    } else {
266
        // Remove from owning list
267
60
        container.erase(value_internal.it);
268
60
    }
269
270
61
    _size--;
271
61
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE10_evict_oneERNS8_18ValueType_internalE
Line
Count
Source
250
61
void LruMultiCache<KeyType, ValueType>::_evict_one(ValueType_internal& value_internal) {
251
    // std::mutex is locked by the caller evicting function
252
    // _lock.DCheckLocked();
253
254
    // Has to be available to evict
255
61
    DCHECK(value_internal.is_available());
256
257
    // Remove from LRU cache
258
61
    value_internal.member_hook.unlink();
259
260
61
    Container& container = value_internal.container;
261
262
61
    if (container.size() == 1) {
263
        // Last element, owning list can be removed to prevent aging
264
1
        _hash_table.erase(value_internal.key);
265
60
    } else {
266
        // Remove from owning list
267
60
        container.erase(value_internal.it);
268
60
    }
269
270
61
    _size--;
271
61
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE10_evict_oneERNS3_18ValueType_internalE
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE10_evict_oneERNSB_18ValueType_internalE
272
273
template <typename KeyType, typename ValueType>
274
323
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
323
    if (!_lru_list.empty() && _size > _capacity) {
279
61
        _evict_one(_lru_list.back());
280
61
    }
281
323
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE20_evict_one_if_neededEv
Line
Count
Source
274
273
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
273
    if (!_lru_list.empty() && _size > _capacity) {
279
61
        _evict_one(_lru_list.back());
280
61
    }
281
273
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE20_evict_one_if_neededEv
Line
Count
Source
274
50
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
50
    if (!_lru_list.empty() && _size > _capacity) {
279
0
        _evict_one(_lru_list.back());
280
0
    }
281
50
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElENS_2io20CachedHdfsFileHandleEE20_evict_one_if_neededEv
282
283
template <typename KeyType, typename ValueType>
284
0
void LruMultiCache<KeyType, ValueType>::evict_older_than(uint64_t oldest_allowed_timestamp) {
285
0
    std::lock_guard<std::mutex> g(_lock);
286
287
    // Stop eviction if
288
    //   - there are no more available (i.e. evictable) objects
289
    //   - cache size is below capacity and the oldest object is not older than the limit
290
0
    while (!_lru_list.empty() &&
291
0
           (_size > _capacity || _lru_list.back().timestamp_seconds < oldest_allowed_timestamp)) {
292
0
        _evict_one(_lru_list.back());
293
0
    }
294
0
}
295
296
} // namespace doris