Coverage Report

Created: 2026-09-29 12:58

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
264
        : cache(cache),
37
264
          key(key),
38
264
          container(container),
39
264
          value(std::forward<Args>(args)...),
40
264
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJRifEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
10
        : cache(cache),
37
10
          key(key),
38
10
          container(container),
39
10
          value(std::forward<Args>(args)...),
40
10
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJifEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
18
        : cache(cache),
37
18
          key(key),
38
18
          container(container),
39
18
          value(std::forward<Args>(args)...),
40
18
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJRmfEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
80
        : cache(cache),
37
80
          key(key),
38
80
          container(container),
39
80
          value(std::forward<Args>(args)...),
40
80
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internalC2IJmfEEERS8_RKS6_RNS1_4listIS9_SaIS9_EEEDpOT_
Line
Count
Source
36
118
        : cache(cache),
37
118
          key(key),
38
118
          container(container),
39
118
          value(std::forward<Args>(args)...),
40
118
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE18ValueType_internalC2IJRifEEERS3_RKS1_RNSt7__cxx114listIS4_SaIS4_EEEDpOT_
Line
Count
Source
36
10
        : cache(cache),
37
10
          key(key),
38
10
          container(container),
39
10
          value(std::forward<Args>(args)...),
40
10
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE18ValueType_internalC2IJifEEERS3_RKS1_RNSt7__cxx114listIS4_SaIS4_EEEDpOT_
Line
Count
Source
36
10
        : cache(cache),
37
10
          key(key),
38
10
          container(container),
39
10
          value(std::forward<Args>(args)...),
40
10
          timestamp_seconds(MonotonicSeconds()) {}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE18ValueType_internalC2IJRKS3_RKS9_RlEEERSE_RKSB_RNS4_4listISF_SaISF_EEEDpOT_
Line
Count
Source
36
18
        : cache(cache),
37
18
          key(key),
38
18
          container(container),
39
18
          value(std::forward<Args>(args)...),
40
18
          timestamp_seconds(MonotonicSeconds()) {}
41
42
template <typename KeyType, typename ValueType>
43
726
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
726
    return member_hook.is_linked();
45
726
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE18ValueType_internal12is_availableEv
Line
Count
Source
43
22
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
22
    return member_hook.is_linked();
45
22
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE18ValueType_internal12is_availableEv
Line
Count
Source
43
554
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
554
    return member_hook.is_linked();
45
554
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE18ValueType_internal12is_availableEv
Line
Count
Source
43
150
bool LruMultiCache<KeyType, ValueType>::ValueType_internal::is_available() {
44
150
    return member_hook.is_linked();
45
150
}
46
47
template <typename KeyType, typename ValueType>
48
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(ValueType_internal* p_value_internal)
49
502
        : _p_value_internal(p_value_internal) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessorC2EPNS8_18ValueType_internalE
Line
Count
Source
49
344
        : _p_value_internal(p_value_internal) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8AccessorC2EPNS3_18ValueType_internalE
Line
Count
Source
49
100
        : _p_value_internal(p_value_internal) {}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessorC2EPNSE_18ValueType_internalE
Line
Count
Source
49
58
        : _p_value_internal(p_value_internal) {}
50
51
template <typename KeyType, typename ValueType>
52
74
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
74
    _p_value_internal = std::move(rhs._p_value_internal);
54
74
    rhs._p_value_internal = nullptr;
55
74
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessorC2EOSF_
Line
Count
Source
52
24
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
24
    _p_value_internal = std::move(rhs._p_value_internal);
54
24
    rhs._p_value_internal = nullptr;
55
24
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessorC2EOS9_
Line
Count
Source
52
50
LruMultiCache<KeyType, ValueType>::Accessor::Accessor(Accessor&& rhs) {
53
50
    _p_value_internal = std::move(rhs._p_value_internal);
54
50
    rhs._p_value_internal = nullptr;
55
50
}
56
template <typename KeyType, typename ValueType>
57
110
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
110
    _p_value_internal = std::move(rhs._p_value_internal);
59
110
    rhs._p_value_internal = nullptr;
60
110
    return (*this);
61
110
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessoraSEOS9_
Line
Count
Source
57
50
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
50
    _p_value_internal = std::move(rhs._p_value_internal);
59
50
    rhs._p_value_internal = nullptr;
60
50
    return (*this);
61
50
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8AccessoraSEOS4_
Line
Count
Source
57
40
auto LruMultiCache<KeyType, ValueType>::Accessor::operator=(Accessor&& rhs) -> Accessor& {
58
40
    _p_value_internal = std::move(rhs._p_value_internal);
59
40
    rhs._p_value_internal = nullptr;
60
40
    return (*this);
61
40
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessoraSEOSF_
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
}
62
63
template <typename KeyType, typename ValueType>
64
576
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
576
    release();
66
576
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8AccessorD2Ev
Line
Count
Source
64
394
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
394
    release();
66
394
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8AccessorD2Ev
Line
Count
Source
64
100
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
100
    release();
66
100
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8AccessorD2Ev
Line
Count
Source
64
82
LruMultiCache<KeyType, ValueType>::Accessor::~Accessor() {
65
82
    release();
66
82
}
67
68
template <typename KeyType, typename ValueType>
69
342
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
342
    if (_p_value_internal) {
71
258
        return &(_p_value_internal->value);
72
258
    }
73
74
84
    return nullptr;
75
342
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8Accessor3getEv
Line
Count
Source
69
122
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
122
    if (_p_value_internal) {
71
102
        return &(_p_value_internal->value);
72
102
    }
73
74
20
    return nullptr;
75
122
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8Accessor3getEv
Line
Count
Source
69
80
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
80
    if (_p_value_internal) {
71
60
        return &(_p_value_internal->value);
72
60
    }
73
74
20
    return nullptr;
75
80
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8Accessor3getEv
Line
Count
Source
69
140
ValueType* LruMultiCache<KeyType, ValueType>::Accessor::get() {
70
140
    if (_p_value_internal) {
71
96
        return &(_p_value_internal->value);
72
96
    }
73
74
44
    return nullptr;
75
140
}
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
892
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
892
    if (_p_value_internal) {
91
404
        LruMultiCache& cache = _p_value_internal->cache;
92
404
        cache.release(_p_value_internal);
93
404
        _p_value_internal = nullptr;
94
404
    }
95
892
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8Accessor7releaseEv
Line
Count
Source
87
86
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
86
    if (_p_value_internal) {
91
4
        LruMultiCache& cache = _p_value_internal->cache;
92
4
        cache.release(_p_value_internal);
93
4
        _p_value_internal = nullptr;
94
4
    }
95
86
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8Accessor7releaseEv
Line
Count
Source
87
626
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
626
    if (_p_value_internal) {
91
320
        LruMultiCache& cache = _p_value_internal->cache;
92
320
        cache.release(_p_value_internal);
93
320
        _p_value_internal = nullptr;
94
320
    }
95
626
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE8Accessor7releaseEv
Line
Count
Source
87
180
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
180
    if (_p_value_internal) {
91
80
        LruMultiCache& cache = _p_value_internal->cache;
92
80
        cache.release(_p_value_internal);
93
80
        _p_value_internal = nullptr;
94
80
    }
95
180
}
96
97
template <typename KeyType, typename ValueType>
98
20
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
20
    if (_p_value_internal) {
102
20
        LruMultiCache& cache = _p_value_internal->cache;
103
20
        cache.destroy(_p_value_internal);
104
20
        _p_value_internal = nullptr;
105
20
    }
106
20
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE8Accessor7destroyEv
Line
Count
Source
98
4
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
4
    if (_p_value_internal) {
102
4
        LruMultiCache& cache = _p_value_internal->cache;
103
4
        cache.destroy(_p_value_internal);
104
4
        _p_value_internal = nullptr;
105
4
    }
106
4
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE8Accessor7destroyEv
Line
Count
Source
98
16
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
16
    if (_p_value_internal) {
102
16
        LruMultiCache& cache = _p_value_internal->cache;
103
16
        cache.destroy(_p_value_internal);
104
16
        _p_value_internal = nullptr;
105
16
    }
106
16
}
107
108
template <typename KeyType, typename ValueType>
109
54
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEEC2Em
Line
Count
Source
109
10
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEEC2Em
Line
Count
Source
109
2
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEEC2Em
Line
Count
Source
109
42
LruMultiCache<KeyType, ValueType>::LruMultiCache(size_t capacity) : _capacity(capacity), _size(0) {}
110
111
template <typename KeyType, typename ValueType>
112
236
size_t LruMultiCache<KeyType, ValueType>::size() {
113
236
    std::lock_guard<std::mutex> g(_lock);
114
236
    return _size;
115
236
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE4sizeEv
Line
Count
Source
112
234
size_t LruMultiCache<KeyType, ValueType>::size() {
113
234
    std::lock_guard<std::mutex> g(_lock);
114
234
    return _size;
115
234
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE4sizeEv
Line
Count
Source
112
2
size_t LruMultiCache<KeyType, ValueType>::size() {
113
2
    std::lock_guard<std::mutex> g(_lock);
114
2
    return _size;
115
2
}
116
117
template <typename KeyType, typename ValueType>
118
28
size_t LruMultiCache<KeyType, ValueType>::number_of_keys() {
119
28
    std::lock_guard<std::mutex> g(_lock);
120
28
    return _hash_table.size();
121
28
}
122
123
template <typename KeyType, typename ValueType>
124
42
void LruMultiCache<KeyType, ValueType>::set_capacity(size_t new_capacity) {
125
42
    std::lock_guard<std::mutex> g(_lock);
126
42
    _capacity = new_capacity;
127
42
}
128
129
template <typename KeyType, typename ValueType>
130
218
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
218
    std::lock_guard<std::mutex> g(_lock);
132
218
    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
218
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
180
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
180
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
180
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
180
    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
160
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
160
    container_it->member_hook.unlink();
155
156
160
    return Accessor(&(*container_it));
157
180
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE3getERKS6_
Line
Count
Source
130
118
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
118
    std::lock_guard<std::mutex> g(_lock);
132
118
    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
118
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
108
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
108
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
108
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
108
    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
98
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
98
    container_it->member_hook.unlink();
155
156
98
    return Accessor(&(*container_it));
157
108
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE3getERKS1_
Line
Count
Source
130
80
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
80
    std::lock_guard<std::mutex> g(_lock);
132
80
    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
80
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
70
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
70
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
70
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
70
    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
60
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
60
    container_it->member_hook.unlink();
155
156
60
    return Accessor(&(*container_it));
157
70
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE3getERKSB_
Line
Count
Source
130
20
auto LruMultiCache<KeyType, ValueType>::get(const KeyType& key) -> Accessor {
131
20
    std::lock_guard<std::mutex> g(_lock);
132
20
    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
20
    if (hash_table_it == _hash_table.end()) return Accessor();
137
138
2
    Container& container = hash_table_it->second;
139
140
    // Empty containers are deleted automatiacally
141
2
    DCHECK(!container.empty());
142
143
    // All the available elements are in the front, only need to check the first
144
2
    auto container_it = container.begin();
145
146
    // No available object found, the caller will have to create a new one with
147
    // EmplaceAndGet()
148
2
    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
2
    container.splice(container.end(), container, container_it);
152
153
    // Remove the element from the LRU list as it is no longer available
154
2
    container_it->member_hook.unlink();
155
156
2
    return Accessor(&(*container_it));
157
2
}
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
264
        -> Accessor {
163
264
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
264
    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
264
    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
264
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
264
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
264
    container_it->it = container_it;
178
179
264
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
264
    _evict_one_if_needed();
183
184
264
    return Accessor(&(*container_it));
185
264
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJRifEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
10
        -> Accessor {
163
10
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
10
    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
10
    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
10
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
10
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
10
    container_it->it = container_it;
178
179
10
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
10
    _evict_one_if_needed();
183
184
10
    return Accessor(&(*container_it));
185
10
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJifEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
18
        -> Accessor {
163
18
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
18
    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
18
    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
18
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
18
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
18
    container_it->it = container_it;
178
179
18
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
18
    _evict_one_if_needed();
183
184
18
    return Accessor(&(*container_it));
185
18
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJRmfEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
80
        -> Accessor {
163
80
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
80
    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
80
    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
80
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
80
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
80
    container_it->it = container_it;
178
179
80
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
80
    _evict_one_if_needed();
183
184
80
    return Accessor(&(*container_it));
185
80
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE15emplace_and_getIJmfEEENS8_8AccessorERKS6_DpOT_
Line
Count
Source
162
118
        -> Accessor {
163
118
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
118
    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
118
    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
118
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
118
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
118
    container_it->it = container_it;
178
179
118
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
118
    _evict_one_if_needed();
183
184
118
    return Accessor(&(*container_it));
185
118
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE15emplace_and_getIJRifEEENS3_8AccessorERKS1_DpOT_
Line
Count
Source
162
10
        -> Accessor {
163
10
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
10
    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
10
    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
10
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
10
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
10
    container_it->it = container_it;
178
179
10
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
10
    _evict_one_if_needed();
183
184
10
    return Accessor(&(*container_it));
185
10
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE15emplace_and_getIJifEEENS3_8AccessorERKS1_DpOT_
Line
Count
Source
162
10
        -> Accessor {
163
10
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
10
    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
10
    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
10
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
10
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
10
    container_it->it = container_it;
178
179
10
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
10
    _evict_one_if_needed();
183
184
10
    return Accessor(&(*container_it));
185
10
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE15emplace_and_getIJRKS3_RKS9_RlEEENSE_8AccessorERKSB_DpOT_
Line
Count
Source
162
18
        -> Accessor {
163
18
    std::lock_guard<std::mutex> g(_lock);
164
165
    // creates default container if there isn't one
166
18
    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
18
    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
18
    auto container_it = container.emplace(container.end(), (*this), stored_key, container,
174
18
                                          std::forward<Args>(args)...);
175
176
    // Only can set this after emplace
177
18
    container_it->it = container_it;
178
179
18
    _size++;
180
181
    // Need to remove the oldest available if the cache is over the capacity
182
18
    _evict_one_if_needed();
183
184
18
    return Accessor(&(*container_it));
185
18
}
186
187
template <typename KeyType, typename ValueType>
188
404
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
404
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
404
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
404
    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
404
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
404
    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
404
    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
404
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
404
    _evict_one_if_needed();
212
404
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE7releaseEPNSE_18ValueType_internalE
Line
Count
Source
188
4
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
4
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
4
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
4
    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
4
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
4
    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
4
    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
4
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
4
    _evict_one_if_needed();
212
4
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE7releaseEPNS8_18ValueType_internalE
Line
Count
Source
188
320
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
320
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
320
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
320
    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
320
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
320
    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
320
    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
320
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
320
    _evict_one_if_needed();
212
320
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE7releaseEPNS3_18ValueType_internalE
Line
Count
Source
188
80
void LruMultiCache<KeyType, ValueType>::release(ValueType_internal* p_value_internal) {
189
80
    std::lock_guard<std::mutex> g(_lock);
190
191
    // This only can be used by the accessor, which already checks for nullptr
192
80
    DCHECK(p_value_internal);
193
194
    // Has to be currently not available
195
80
    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
80
    p_value_internal->timestamp_seconds = MonotonicSeconds();
200
201
80
    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
80
    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
80
    _lru_list.push_front(container.front());
209
210
    // In case we overshot the capacity already, the cache can evict the oldest one
211
80
    _evict_one_if_needed();
212
80
}
213
214
template <typename KeyType, typename ValueType>
215
20
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
20
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
20
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
20
    DCHECK(!p_value_internal->is_available());
223
224
20
    Container& container = p_value_internal->container;
225
226
20
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
18
        _hash_table.erase(p_value_internal->key);
229
18
    } else {
230
        // Remove from owning list
231
2
        container.erase(p_value_internal->it);
232
2
    }
233
234
20
    _size--;
235
20
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE7destroyEPNS8_18ValueType_internalE
Line
Count
Source
215
4
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
4
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
4
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
4
    DCHECK(!p_value_internal->is_available());
223
224
4
    Container& container = p_value_internal->container;
225
226
4
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
2
        _hash_table.erase(p_value_internal->key);
229
2
    } else {
230
        // Remove from owning list
231
2
        container.erase(p_value_internal->it);
232
2
    }
233
234
4
    _size--;
235
4
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE7destroyEPNSE_18ValueType_internalE
Line
Count
Source
215
16
void LruMultiCache<KeyType, ValueType>::destroy(ValueType_internal* p_value_internal) {
216
16
    std::lock_guard<std::mutex> g(_lock);
217
218
    // This only can be used by the accessor, which already checks for nullptr
219
16
    DCHECK(p_value_internal);
220
221
    // Has to be currently not available
222
16
    DCHECK(!p_value_internal->is_available());
223
224
16
    Container& container = p_value_internal->container;
225
226
16
    if (container.size() == 1) {
227
        // Last element, owning list can be removed to prevent aging
228
16
        _hash_table.erase(p_value_internal->key);
229
16
    } else {
230
        // Remove from owning list
231
0
        container.erase(p_value_internal->it);
232
0
    }
233
234
16
    _size--;
235
16
}
236
237
template <typename KeyType, typename ValueType>
238
236
size_t LruMultiCache<KeyType, ValueType>::number_of_available_objects() {
239
236
    std::lock_guard<std::mutex> g(_lock);
240
236
    return _lru_list.size();
241
236
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE27number_of_available_objectsEv
Line
Count
Source
238
234
size_t LruMultiCache<KeyType, ValueType>::number_of_available_objects() {
239
234
    std::lock_guard<std::mutex> g(_lock);
240
234
    return _lru_list.size();
241
234
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE27number_of_available_objectsEv
Line
Count
Source
238
2
size_t LruMultiCache<KeyType, ValueType>::number_of_available_objects() {
239
2
    std::lock_guard<std::mutex> g(_lock);
240
2
    return _lru_list.size();
241
2
}
242
243
template <typename KeyType, typename ValueType>
244
42
void LruMultiCache<KeyType, ValueType>::rehash() {
245
42
    std::lock_guard<std::mutex> g(_lock);
246
42
    _hash_table.rehash(_hash_table.bucket_count() + 1);
247
42
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE6rehashEv
Line
Count
Source
244
22
void LruMultiCache<KeyType, ValueType>::rehash() {
245
22
    std::lock_guard<std::mutex> g(_lock);
246
22
    _hash_table.rehash(_hash_table.bucket_count() + 1);
247
22
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE6rehashEv
Line
Count
Source
244
20
void LruMultiCache<KeyType, ValueType>::rehash() {
245
20
    std::lock_guard<std::mutex> g(_lock);
246
20
    _hash_table.rehash(_hash_table.bucket_count() + 1);
247
20
}
248
249
template <typename KeyType, typename ValueType>
250
122
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
122
    DCHECK(value_internal.is_available());
256
257
    // Remove from LRU cache
258
122
    value_internal.member_hook.unlink();
259
260
122
    Container& container = value_internal.container;
261
262
122
    if (container.size() == 1) {
263
        // Last element, owning list can be removed to prevent aging
264
2
        _hash_table.erase(value_internal.key);
265
120
    } else {
266
        // Remove from owning list
267
120
        container.erase(value_internal.it);
268
120
    }
269
270
122
    _size--;
271
122
}
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
122
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
122
    DCHECK(value_internal.is_available());
256
257
    // Remove from LRU cache
258
122
    value_internal.member_hook.unlink();
259
260
122
    Container& container = value_internal.container;
261
262
122
    if (container.size() == 1) {
263
        // Last element, owning list can be removed to prevent aging
264
2
        _hash_table.erase(value_internal.key);
265
120
    } else {
266
        // Remove from owning list
267
120
        container.erase(value_internal.it);
268
120
    }
269
270
122
    _size--;
271
122
}
Unexecuted instantiation: _ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE10_evict_oneERNS3_18ValueType_internalE
272
273
template <typename KeyType, typename ValueType>
274
668
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
668
    if (!_lru_list.empty() && _size > _capacity) {
279
122
        _evict_one(_lru_list.back());
280
122
    }
281
668
}
_ZN5doris13LruMultiCacheISt4pairIP13hdfs_internalS1_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEElEENS_2io20CachedHdfsFileHandleEE20_evict_one_if_neededEv
Line
Count
Source
274
22
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
22
    if (!_lru_list.empty() && _size > _capacity) {
279
0
        _evict_one(_lru_list.back());
280
0
    }
281
22
}
_ZN5doris13LruMultiCacheINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8TestTypeEE20_evict_one_if_neededEv
Line
Count
Source
274
546
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
546
    if (!_lru_list.empty() && _size > _capacity) {
279
122
        _evict_one(_lru_list.back());
280
122
    }
281
546
}
_ZN5doris13LruMultiCacheI12CollidingKeyNS_8TestTypeEE20_evict_one_if_neededEv
Line
Count
Source
274
100
void LruMultiCache<KeyType, ValueType>::_evict_one_if_needed() {
275
    // std::mutex is locked by the caller public function
276
    // _lock.DCheckLocked();
277
278
100
    if (!_lru_list.empty() && _size > _capacity) {
279
0
        _evict_one(_lru_list.back());
280
0
    }
281
100
}
282
283
template <typename KeyType, typename ValueType>
284
113k
void LruMultiCache<KeyType, ValueType>::evict_older_than(uint64_t oldest_allowed_timestamp) {
285
113k
    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
113k
    while (!_lru_list.empty() &&
291
113k
           (_size > _capacity || _lru_list.back().timestamp_seconds < oldest_allowed_timestamp)) {
292
0
        _evict_one(_lru_list.back());
293
0
    }
294
113k
}
295
296
} // namespace doris