]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_cache.cc
bump version to 15.2.4-pve1
[ceph.git] / ceph / src / rgw / rgw_cache.cc
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae
FG
3
4#include "rgw_cache.h"
11fdf7f2 5#include "rgw_perf_counters.h"
7c673cae
FG
6
7#include <errno.h>
8
9#define dout_subsys ceph_subsys_rgw
10
7c673cae 11
3a9019d9 12int ObjectCache::get(const string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cache_entry_info *cache_info)
7c673cae 13{
7c673cae 14
9f95a23c 15 std::shared_lock rl{lock};
7c673cae
FG
16 if (!enabled) {
17 return -ENOENT;
18 }
b32b8144 19 auto iter = cache_map.find(name);
1adf2230 20 if (iter == cache_map.end()) {
7c673cae 21 ldout(cct, 10) << "cache get: name=" << name << " : miss" << dendl;
9f95a23c 22 if (perfcounter) {
b32b8144 23 perfcounter->inc(l_rgw_cache_miss);
9f95a23c 24 }
7c673cae
FG
25 return -ENOENT;
26 }
9f95a23c 27
1adf2230
AA
28 if (expiry.count() &&
29 (ceph::coarse_mono_clock::now() - iter->second.info.time_added) > expiry) {
30 ldout(cct, 10) << "cache get: name=" << name << " : expiry miss" << dendl;
9f95a23c
TL
31 rl.unlock();
32 std::unique_lock wl{lock}; // write lock for insertion
1adf2230
AA
33 // check that wasn't already removed by other thread
34 iter = cache_map.find(name);
35 if (iter != cache_map.end()) {
36 for (auto &kv : iter->second.chained_entries)
37 kv.first->invalidate(kv.second);
38 remove_lru(name, iter->second.lru_iter);
39 cache_map.erase(iter);
40 }
9f95a23c 41 if (perfcounter) {
1adf2230 42 perfcounter->inc(l_rgw_cache_miss);
9f95a23c 43 }
1adf2230
AA
44 return -ENOENT;
45 }
7c673cae
FG
46
47 ObjectCacheEntry *entry = &iter->second;
48
49 if (lru_counter - entry->lru_promotion_ts > lru_window) {
50 ldout(cct, 20) << "cache get: touching lru, lru_counter=" << lru_counter
51 << " promotion_ts=" << entry->lru_promotion_ts << dendl;
9f95a23c
TL
52 rl.unlock();
53 std::unique_lock wl{lock}; // write lock for insertion
7c673cae
FG
54 /* need to redo this because entry might have dropped off the cache */
55 iter = cache_map.find(name);
56 if (iter == cache_map.end()) {
57 ldout(cct, 10) << "lost race! cache get: name=" << name << " : miss" << dendl;
58 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
59 return -ENOENT;
60 }
61
62 entry = &iter->second;
63 /* check again, we might have lost a race here */
64 if (lru_counter - entry->lru_promotion_ts > lru_window) {
65 touch_lru(name, *entry, iter->second.lru_iter);
66 }
67 }
68
69 ObjectCacheInfo& src = iter->second.info;
70 if ((src.flags & mask) != mask) {
71 ldout(cct, 10) << "cache get: name=" << name << " : type miss (requested=0x"
72 << std::hex << mask << ", cached=0x" << src.flags
73 << std::dec << ")" << dendl;
74 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
75 return -ENOENT;
76 }
77 ldout(cct, 10) << "cache get: name=" << name << " : hit (requested=0x"
78 << std::hex << mask << ", cached=0x" << src.flags
79 << std::dec << ")" << dendl;
80
81 info = src;
82 if (cache_info) {
83 cache_info->cache_locator = name;
84 cache_info->gen = entry->gen;
85 }
86 if(perfcounter) perfcounter->inc(l_rgw_cache_hit);
87
88 return 0;
89}
90
11fdf7f2
TL
91bool ObjectCache::chain_cache_entry(std::initializer_list<rgw_cache_entry_info*> cache_info_entries,
92 RGWChainedCache::Entry *chained_entry)
7c673cae 93{
9f95a23c 94 std::unique_lock l{lock};
7c673cae
FG
95
96 if (!enabled) {
97 return false;
98 }
99
11fdf7f2
TL
100 std::vector<ObjectCacheEntry*> entries;
101 entries.reserve(cache_info_entries.size());
7c673cae 102 /* first verify that all entries are still valid */
11fdf7f2
TL
103 for (auto cache_info : cache_info_entries) {
104 ldout(cct, 10) << "chain_cache_entry: cache_locator="
105 << cache_info->cache_locator << dendl;
106 auto iter = cache_map.find(cache_info->cache_locator);
7c673cae
FG
107 if (iter == cache_map.end()) {
108 ldout(cct, 20) << "chain_cache_entry: couldn't find cache locator" << dendl;
109 return false;
110 }
111
11fdf7f2 112 auto entry = &iter->second;
7c673cae
FG
113
114 if (entry->gen != cache_info->gen) {
11fdf7f2
TL
115 ldout(cct, 20) << "chain_cache_entry: entry.gen (" << entry->gen
116 << ") != cache_info.gen (" << cache_info->gen << ")"
117 << dendl;
7c673cae
FG
118 return false;
119 }
11fdf7f2 120 entries.push_back(entry);
7c673cae
FG
121 }
122
123
124 chained_entry->cache->chain_cb(chained_entry->key, chained_entry->data);
125
11fdf7f2
TL
126 for (auto entry : entries) {
127 entry->chained_entries.push_back(make_pair(chained_entry->cache,
128 chained_entry->key));
7c673cae
FG
129 }
130
131 return true;
132}
133
3a9019d9 134void ObjectCache::put(const string& name, ObjectCacheInfo& info, rgw_cache_entry_info *cache_info)
7c673cae 135{
9f95a23c 136 std::unique_lock l{lock};
7c673cae
FG
137
138 if (!enabled) {
139 return;
140 }
141
142 ldout(cct, 10) << "cache put: name=" << name << " info.flags=0x"
143 << std::hex << info.flags << std::dec << dendl;
28e407b8 144
11fdf7f2
TL
145 auto [iter, inserted] = cache_map.emplace(name, ObjectCacheEntry{});
146 ObjectCacheEntry& entry = iter->second;
28e407b8
AA
147 entry.info.time_added = ceph::coarse_mono_clock::now();
148 if (inserted) {
7c673cae 149 entry.lru_iter = lru.end();
7c673cae 150 }
7c673cae
FG
151 ObjectCacheInfo& target = entry.info;
152
b32b8144 153 invalidate_lru(entry);
7c673cae
FG
154
155 entry.chained_entries.clear();
156 entry.gen++;
157
158 touch_lru(name, entry, entry.lru_iter);
159
160 target.status = info.status;
161
162 if (info.status < 0) {
163 target.flags = 0;
164 target.xattrs.clear();
165 target.data.clear();
166 return;
167 }
168
169 if (cache_info) {
170 cache_info->cache_locator = name;
171 cache_info->gen = entry.gen;
172 }
173
174 target.flags |= info.flags;
175
176 if (info.flags & CACHE_FLAG_META)
177 target.meta = info.meta;
178 else if (!(info.flags & CACHE_FLAG_MODIFY_XATTRS))
179 target.flags &= ~CACHE_FLAG_META; // non-meta change should reset meta
180
181 if (info.flags & CACHE_FLAG_XATTRS) {
182 target.xattrs = info.xattrs;
183 map<string, bufferlist>::iterator iter;
184 for (iter = target.xattrs.begin(); iter != target.xattrs.end(); ++iter) {
185 ldout(cct, 10) << "updating xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
186 }
187 } else if (info.flags & CACHE_FLAG_MODIFY_XATTRS) {
188 map<string, bufferlist>::iterator iter;
189 for (iter = info.rm_xattrs.begin(); iter != info.rm_xattrs.end(); ++iter) {
190 ldout(cct, 10) << "removing xattr: name=" << iter->first << dendl;
191 target.xattrs.erase(iter->first);
192 }
193 for (iter = info.xattrs.begin(); iter != info.xattrs.end(); ++iter) {
194 ldout(cct, 10) << "appending xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
195 target.xattrs[iter->first] = iter->second;
196 }
197 }
198
199 if (info.flags & CACHE_FLAG_DATA)
200 target.data = info.data;
201
202 if (info.flags & CACHE_FLAG_OBJV)
203 target.version = info.version;
204}
205
3a9019d9 206bool ObjectCache::remove(const string& name)
7c673cae 207{
9f95a23c 208 std::unique_lock l{lock};
7c673cae
FG
209
210 if (!enabled) {
3a9019d9 211 return false;
7c673cae
FG
212 }
213
11fdf7f2 214 auto iter = cache_map.find(name);
7c673cae 215 if (iter == cache_map.end())
3a9019d9 216 return false;
7c673cae
FG
217
218 ldout(cct, 10) << "removing " << name << " from cache" << dendl;
219 ObjectCacheEntry& entry = iter->second;
220
11fdf7f2
TL
221 for (auto& kv : entry.chained_entries) {
222 kv.first->invalidate(kv.second);
7c673cae
FG
223 }
224
225 remove_lru(name, iter->second.lru_iter);
226 cache_map.erase(iter);
3a9019d9 227 return true;
7c673cae
FG
228}
229
3a9019d9
FG
230void ObjectCache::touch_lru(const string& name, ObjectCacheEntry& entry,
231 std::list<string>::iterator& lru_iter)
7c673cae
FG
232{
233 while (lru_size > (size_t)cct->_conf->rgw_cache_lru_size) {
11fdf7f2 234 auto iter = lru.begin();
7c673cae
FG
235 if ((*iter).compare(name) == 0) {
236 /*
237 * if the entry we're touching happens to be at the lru end, don't remove it,
238 * lru shrinking can wait for next time
239 */
240 break;
241 }
11fdf7f2 242 auto map_iter = cache_map.find(*iter);
7c673cae 243 ldout(cct, 10) << "removing entry: name=" << *iter << " from cache LRU" << dendl;
b32b8144
FG
244 if (map_iter != cache_map.end()) {
245 ObjectCacheEntry& entry = map_iter->second;
246 invalidate_lru(entry);
7c673cae 247 cache_map.erase(map_iter);
b32b8144 248 }
7c673cae
FG
249 lru.pop_front();
250 lru_size--;
251 }
252
253 if (lru_iter == lru.end()) {
254 lru.push_back(name);
255 lru_size++;
256 lru_iter--;
257 ldout(cct, 10) << "adding " << name << " to cache LRU end" << dendl;
258 } else {
259 ldout(cct, 10) << "moving " << name << " to cache LRU end" << dendl;
260 lru.erase(lru_iter);
261 lru.push_back(name);
262 lru_iter = lru.end();
263 --lru_iter;
264 }
265
266 lru_counter++;
267 entry.lru_promotion_ts = lru_counter;
268}
269
3a9019d9
FG
270void ObjectCache::remove_lru(const string& name,
271 std::list<string>::iterator& lru_iter)
7c673cae
FG
272{
273 if (lru_iter == lru.end())
274 return;
275
276 lru.erase(lru_iter);
277 lru_size--;
278 lru_iter = lru.end();
279}
280
b32b8144
FG
281void ObjectCache::invalidate_lru(ObjectCacheEntry& entry)
282{
11fdf7f2 283 for (auto iter = entry.chained_entries.begin();
b32b8144
FG
284 iter != entry.chained_entries.end(); ++iter) {
285 RGWChainedCache *chained_cache = iter->first;
286 chained_cache->invalidate(iter->second);
287 }
288}
289
7c673cae
FG
290void ObjectCache::set_enabled(bool status)
291{
9f95a23c 292 std::unique_lock l{lock};
7c673cae
FG
293
294 enabled = status;
295
296 if (!enabled) {
297 do_invalidate_all();
298 }
299}
300
301void ObjectCache::invalidate_all()
302{
9f95a23c 303 std::unique_lock l{lock};
7c673cae
FG
304
305 do_invalidate_all();
306}
307
308void ObjectCache::do_invalidate_all()
309{
310 cache_map.clear();
311 lru.clear();
312
313 lru_size = 0;
314 lru_counter = 0;
315 lru_window = 0;
316
11fdf7f2
TL
317 for (auto& cache : chained_cache) {
318 cache->invalidate_all();
7c673cae
FG
319 }
320}
321
322void ObjectCache::chain_cache(RGWChainedCache *cache) {
9f95a23c 323 std::unique_lock l{lock};
7c673cae
FG
324 chained_cache.push_back(cache);
325}
326
11fdf7f2 327void ObjectCache::unchain_cache(RGWChainedCache *cache) {
9f95a23c 328 std::unique_lock l{lock};
11fdf7f2
TL
329
330 auto iter = chained_cache.begin();
331 for (; iter != chained_cache.end(); ++iter) {
332 if (cache == *iter) {
333 chained_cache.erase(iter);
334 cache->unregistered();
335 return;
336 }
337 }
338}
339
340ObjectCache::~ObjectCache()
341{
342 for (auto cache : chained_cache) {
343 cache->unregistered();
344 }
345}
346