|
18 | 18 |
|
19 | 19 | namespace paimon { |
20 | 20 |
|
21 | | -LruCache::LruCache(int64_t max_weight) : max_weight_(max_weight), current_weight_(0) {} |
| 21 | +LruCache::LruCache(int64_t max_weight) |
| 22 | + : inner_cache_(InnerCache::Options{ |
| 23 | + .max_weight = max_weight, |
| 24 | + .expire_after_access_ms = -1, |
| 25 | + .weigh_func = [](const std::shared_ptr<CacheKey>& /*key*/, |
| 26 | + const std::shared_ptr<CacheValue>& value) -> int64_t { |
| 27 | + return value ? value->GetSegment().Size() : 0; |
| 28 | + }, |
| 29 | + .removal_callback = |
| 30 | + [](const std::shared_ptr<CacheKey>& key, const std::shared_ptr<CacheValue>& value, |
| 31 | + auto cause) { |
| 32 | + if (value) { |
| 33 | + value->OnEvict(key); |
| 34 | + } |
| 35 | + }}) {} |
22 | 36 |
|
23 | 37 | Result<std::shared_ptr<CacheValue>> LruCache::Get( |
24 | 38 | const std::shared_ptr<CacheKey>& key, |
25 | 39 | std::function<Result<std::shared_ptr<CacheValue>>(const std::shared_ptr<CacheKey>&)> supplier) { |
26 | | - { |
27 | | - std::unique_lock<std::shared_mutex> write_lock(mutex_); |
28 | | - auto cached = FindAndPromote(key); |
29 | | - if (cached) { |
30 | | - return cached.value(); |
31 | | - } |
32 | | - } |
33 | | - // Cache miss: load via supplier (outside lock) |
34 | | - PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<CacheValue> value, supplier(key)); |
35 | | - if (GetWeight(value) > max_weight_) { |
36 | | - return value; |
37 | | - } |
38 | | - |
39 | | - std::unique_lock<std::shared_mutex> write_lock(mutex_); |
40 | | - // Another thread may have inserted the key while we were loading |
41 | | - auto cached = FindAndPromote(key); |
42 | | - if (cached) { |
43 | | - return cached.value(); |
44 | | - } |
45 | | - |
46 | | - Insert(key, value); |
47 | | - EvictIfNeeded(); |
48 | | - return value; |
| 40 | + return inner_cache_.Get(key, std::move(supplier)); |
49 | 41 | } |
50 | 42 |
|
51 | | -void LruCache::Put(const std::shared_ptr<CacheKey>& key, const std::shared_ptr<CacheValue>& value) { |
52 | | - if (GetWeight(value) > max_weight_) { |
53 | | - return; |
54 | | - } |
55 | | - std::unique_lock<std::shared_mutex> write_lock(mutex_); |
56 | | - |
57 | | - auto it = lru_map_.find(key); |
58 | | - if (it != lru_map_.end()) { |
59 | | - // Update existing entry: adjust weight |
60 | | - current_weight_ -= GetWeight(it->second->second); |
61 | | - it->second->second = value; |
62 | | - current_weight_ += GetWeight(value); |
63 | | - lru_list_.splice(lru_list_.begin(), lru_list_, it->second); |
64 | | - } else { |
65 | | - Insert(key, value); |
66 | | - } |
67 | | - |
68 | | - EvictIfNeeded(); |
| 43 | +Status LruCache::Put(const std::shared_ptr<CacheKey>& key, |
| 44 | + const std::shared_ptr<CacheValue>& value) { |
| 45 | + return inner_cache_.Put(key, value); |
69 | 46 | } |
70 | 47 |
|
71 | 48 | void LruCache::Invalidate(const std::shared_ptr<CacheKey>& key) { |
72 | | - std::unique_lock<std::shared_mutex> write_lock(mutex_); |
73 | | - |
74 | | - auto it = lru_map_.find(key); |
75 | | - if (it != lru_map_.end()) { |
76 | | - RemoveEntry(it->second); |
77 | | - } |
| 49 | + inner_cache_.Invalidate(key); |
78 | 50 | } |
79 | 51 |
|
80 | 52 | void LruCache::InvalidateAll() { |
81 | | - std::unique_lock<std::shared_mutex> write_lock(mutex_); |
82 | | - |
83 | | - while (!lru_list_.empty()) { |
84 | | - RemoveEntry(std::prev(lru_list_.end())); |
85 | | - } |
86 | | - current_weight_ = 0; |
| 53 | + inner_cache_.InvalidateAll(); |
87 | 54 | } |
88 | 55 |
|
89 | 56 | size_t LruCache::Size() const { |
90 | | - std::shared_lock<std::shared_mutex> read_lock(mutex_); |
91 | | - return lru_map_.size(); |
| 57 | + return inner_cache_.Size(); |
92 | 58 | } |
93 | 59 |
|
94 | 60 | int64_t LruCache::GetCurrentWeight() const { |
95 | | - std::shared_lock<std::shared_mutex> read_lock(mutex_); |
96 | | - return current_weight_; |
| 61 | + return inner_cache_.GetCurrentWeight(); |
97 | 62 | } |
98 | 63 |
|
99 | 64 | int64_t LruCache::GetMaxWeight() const { |
100 | | - return max_weight_; |
101 | | -} |
102 | | - |
103 | | -std::optional<std::shared_ptr<CacheValue>> LruCache::FindAndPromote( |
104 | | - const std::shared_ptr<CacheKey>& key) { |
105 | | - auto it = lru_map_.find(key); |
106 | | - if (it != lru_map_.end()) { |
107 | | - lru_list_.splice(lru_list_.begin(), lru_list_, it->second); |
108 | | - return it->second->second; |
109 | | - } |
110 | | - return std::nullopt; |
| 65 | + return inner_cache_.GetMaxWeight(); |
111 | 66 | } |
112 | 67 |
|
113 | | -void LruCache::Insert(const std::shared_ptr<CacheKey>& key, |
114 | | - const std::shared_ptr<CacheValue>& value) { |
115 | | - // Insert at front of LRU list |
116 | | - lru_list_.emplace_front(key, value); |
117 | | - lru_map_[key] = lru_list_.begin(); |
118 | | - current_weight_ += GetWeight(value); |
119 | | -} |
120 | | - |
121 | | -void LruCache::RemoveEntry(LruList::iterator list_it) { |
122 | | - auto entry_key = list_it->first; |
123 | | - auto entry_value = list_it->second; |
124 | | - current_weight_ -= GetWeight(entry_value); |
125 | | - lru_map_.erase(entry_key); |
126 | | - lru_list_.erase(list_it); |
127 | | - |
128 | | - if (entry_value) { |
129 | | - entry_value->OnEvict(entry_key); |
130 | | - } |
131 | | -} |
132 | | - |
133 | | -void LruCache::EvictIfNeeded() { |
134 | | - while (current_weight_ > max_weight_ && !lru_list_.empty()) { |
135 | | - RemoveEntry(std::prev(lru_list_.end())); |
136 | | - } |
137 | | -} |
138 | | - |
139 | | -int64_t LruCache::GetWeight(const std::shared_ptr<CacheValue>& value) { |
140 | | - if (!value) { |
141 | | - return 0; |
142 | | - } |
143 | | - return value->GetSegment().Size(); |
144 | | -} |
145 | 68 | } // namespace paimon |
0 commit comments