Coverage Report

Created: 2026-08-31 18:59

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
129
        : cache(cache),
37
129
          key(key),
38
129
          container(container),
39
129
          value(std::forward<Args>(args)...),
40
129
          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()) {}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE18ValueType_internalC2IJRKS3_RKS9_RlEEERSE_RKSB_RNS4_4listISF_SaISF_EEEDpOT_
Line
Count
Source
36
6
        : cache(cache),
37
6
          key(key),
38
6
          container(container),
39
6
          value(std::forward<Args>(args)...),
40
6
          timestamp_seconds(MonotonicSeconds()) {}
41
42
template <typename KeyType, typename ValueType>
43
360
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
360
    return member_hook.is_linked();
45
360
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE18ValueType_internal12is_availableEv
Line
Count
Source
43
8
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
8
    return member_hook.is_linked();
45
8
}
_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
}
46
47
template <typename KeyType, typename ValueType>
48
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(ValueType_internal* p_value_internal)
49
242
        : _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) {}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessorC2EPNSE_18ValueType_internalE
Line
Count
Source
49
20
        : _p_value_internal(p_value_internal) {}
50
51
template <typename KeyType, typename ValueType>
52
29
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
29
    _p_value_internal = std::move(rhs._p_value_internal);
54
29
    rhs._p_value_internal = nullptr;
55
29
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessorC2EOSF_
Line
Count
Source
52
4
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
4
    _p_value_internal = std::move(rhs._p_value_internal);
54
4
    rhs._p_value_internal = nullptr;
55
4
}
_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
}
56
template <typename KeyType, typename ValueType>
57
52
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
52
    _p_value_internal = std::move(rhs._p_value_internal);
59
52
    rhs._p_value_internal = nullptr;
60
52
    return (*this);
61
52
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessoraSEOSF_
Line
Count
Source
57
7
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
7
    _p_value_internal = std::move(rhs._p_value_internal);
59
7
    rhs._p_value_internal = nullptr;
60
7
    return (*this);
61
7
}
62
63
template <typename KeyType, typename ValueType>
64
271
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
271
    release();
66
271
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessorD2Ev
Line
Count
Source
64
24
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
24
    release();
66
24
}
67
68
template <typename KeyType, typename ValueType>
69
145
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
145
    if (_p_value_internal) {
71
114
        return &(_p_value_internal->value);
72
114
    }
73
74
31
    return nullptr;
75
145
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8Accessor3getEv
Line
Count
Source
69
44
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
44
    if (_p_value_internal) {
71
33
        return &(_p_value_internal->value);
72
33
    }
73
74
11
    return nullptr;
75
44
}
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
429
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
429
    if (_p_value_internal) {
91
202
        LruMultiCache& cache = _p_value_internal->cache;
92
202
        cache.release(_p_value_internal);
93
202
        _p_value_internal = nullptr;
94
202
    }
95
429
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8Accessor7releaseEv
Line
Count
Source
87
26
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
26
    if (_p_value_internal) {
91
2
        LruMultiCache& cache = _p_value_internal->cache;
92
2
        cache.release(_p_value_internal);
93
2
        _p_value_internal = nullptr;
94
2
    }
95
26
}
_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
}
96
97
template <typename KeyType, typename ValueType>
98
7
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
7
    if (_p_value_internal) {
102
7
        LruMultiCache& cache = _p_value_internal->cache;
103
7
        cache.destroy(_p_value_internal);
104
7
        _p_value_internal = nullptr;
105
7
    }
106
7
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8Accessor7destroyEv
Line
Count
Source
98
5
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
5
    if (_p_value_internal) {
102
5
        LruMultiCache& cache = _p_value_internal->cache;
103
5
        cache.destroy(_p_value_internal);
104
5
        _p_value_internal = nullptr;
105
5
    }
106
5
}
107
108
template <typename KeyType, typename ValueType>
109
10
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) {}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEEC2Em
Line
Count
Source
109
4
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
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
4
void LruMultiCache<KeyType, ValueType>::set_capacity(size_t new_capacity) {
125
4
    std::lock_guard<std::mutex> g(_lock);
126
4
    _capacity = new_capacity;
127
4
}
128
129
template <typename KeyType, typename ValueType>
130
106
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
106
    std::lock_guard<std::mutex> g(_lock);
132
106
    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
106
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
90
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
90
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
90
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
90
    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
80
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
80
    container_it->member_hook.unlink();
155
156
80
    return Accessor(&(*container_it));
157
90
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE3getERKSB_
Line
Count
Source
130
7
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
7
    std::lock_guard<std::mutex> g(_lock);
132
7
    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
7
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
1
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
1
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
1
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
1
    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
1
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
1
    container_it->member_hook.unlink();
155
156
1
    return Accessor(&(*container_it));
157
1
}
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
129
        -> Accessor {
163
129
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
129
    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
129
    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
129
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
129
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
129
    container_it->it = container_it;
178
179
129
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
129
    _evict_one_if_needed();
183
184
129
    return Accessor(&(*container_it));
185
129
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE15emplace_and_getIJRKS3_RKS9_RlEEENSE_8AccessorERKSB_DpOT_
Line
Count
Source
162
6
        -> Accessor {
163
6
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
6
    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
6
    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
6
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
6
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
6
    container_it->it = container_it;
178
179
6
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
6
    _evict_one_if_needed();
183
184
6
    return Accessor(&(*container_it));
185
6
}
186
187
template <typename KeyType, typename ValueType>
188
202
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
202
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
202
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
202
    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
202
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
202
    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
202
    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
202
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
202
    _evict_one_if_needed();
212
202
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE7releaseEPNSE_18ValueType_internalE
Line
Count
Source
188
2
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
2
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
2
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
2
    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
2
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
2
    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
2
    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
2
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
2
    _evict_one_if_needed();
212
2
}
_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
}
213
214
template <typename KeyType, typename ValueType>
215
7
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
7
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
7
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
7
    DCHECK(!p_value_internal->is_available());
223
224
7
    Container& container = p_value_internal->container;
225
226
7
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
6
        _hash_table.erase(p_value_internal->key);
229
6
    } else {
230
        // Remove from owning list
231
1
        container.erase(p_value_internal->it);
232
1
    }
233
234
7
    _size--;
235
7
}
_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
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE7destroyEPNSE_18ValueType_internalE
Line
Count
Source
215
5
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
5
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
5
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
5
    DCHECK(!p_value_internal->is_available());
223
224
5
    Container& container = p_value_internal->container;
225
226
5
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
5
        _hash_table.erase(p_value_internal->key);
229
5
    } else {
230
        // Remove from owning list
231
0
        container.erase(p_value_internal->it);
232
0
    }
233
234
5
    _size--;
235
5
}
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
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE10_evict_oneERNSE_18ValueType_internalE
_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
272
273
template <typename KeyType, typename ValueType>
274
331
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
331
    if (!_lru_list.empty() && _size > _capacity) {
279
61
        _evict_one(_lru_list.back());
280
61
    }
281
331
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE20_evict_one_if_neededEv
Line
Count
Source
274
8
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
8
    if (!_lru_list.empty() && _size > _capacity) {
279
0
        _evict_one(_lru_list.back());
280
0
    }
281
8
}
_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
}
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