]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_cache.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 #include "rgw_perf_counters.h"
9 #define dout_subsys ceph_subsys_rgw
12 int ObjectCache::get(const string
& name
, ObjectCacheInfo
& info
, uint32_t mask
, rgw_cache_entry_info
*cache_info
)
14 RWLock::RLocker
l(lock
);
20 auto iter
= cache_map
.find(name
);
21 if (iter
== cache_map
.end()) {
22 ldout(cct
, 10) << "cache get: name=" << name
<< " : miss" << dendl
;
24 perfcounter
->inc(l_rgw_cache_miss
);
28 (ceph::coarse_mono_clock::now() - iter
->second
.info
.time_added
) > expiry
) {
29 ldout(cct
, 10) << "cache get: name=" << name
<< " : expiry miss" << dendl
;
32 // check that wasn't already removed by other thread
33 iter
= cache_map
.find(name
);
34 if (iter
!= cache_map
.end()) {
35 for (auto &kv
: iter
->second
.chained_entries
)
36 kv
.first
->invalidate(kv
.second
);
37 remove_lru(name
, iter
->second
.lru_iter
);
38 cache_map
.erase(iter
);
41 perfcounter
->inc(l_rgw_cache_miss
);
45 ObjectCacheEntry
*entry
= &iter
->second
;
47 if (lru_counter
- entry
->lru_promotion_ts
> lru_window
) {
48 ldout(cct
, 20) << "cache get: touching lru, lru_counter=" << lru_counter
49 << " promotion_ts=" << entry
->lru_promotion_ts
<< dendl
;
51 lock
.get_write(); /* promote lock to writer */
53 /* need to redo this because entry might have dropped off the cache */
54 iter
= cache_map
.find(name
);
55 if (iter
== cache_map
.end()) {
56 ldout(cct
, 10) << "lost race! cache get: name=" << name
<< " : miss" << dendl
;
57 if(perfcounter
) perfcounter
->inc(l_rgw_cache_miss
);
61 entry
= &iter
->second
;
62 /* check again, we might have lost a race here */
63 if (lru_counter
- entry
->lru_promotion_ts
> lru_window
) {
64 touch_lru(name
, *entry
, iter
->second
.lru_iter
);
68 ObjectCacheInfo
& src
= iter
->second
.info
;
69 if ((src
.flags
& mask
) != mask
) {
70 ldout(cct
, 10) << "cache get: name=" << name
<< " : type miss (requested=0x"
71 << std::hex
<< mask
<< ", cached=0x" << src
.flags
72 << std::dec
<< ")" << dendl
;
73 if(perfcounter
) perfcounter
->inc(l_rgw_cache_miss
);
76 ldout(cct
, 10) << "cache get: name=" << name
<< " : hit (requested=0x"
77 << std::hex
<< mask
<< ", cached=0x" << src
.flags
78 << std::dec
<< ")" << dendl
;
82 cache_info
->cache_locator
= name
;
83 cache_info
->gen
= entry
->gen
;
85 if(perfcounter
) perfcounter
->inc(l_rgw_cache_hit
);
90 bool ObjectCache::chain_cache_entry(std::initializer_list
<rgw_cache_entry_info
*> cache_info_entries
,
91 RGWChainedCache::Entry
*chained_entry
)
93 RWLock::WLocker
l(lock
);
99 std::vector
<ObjectCacheEntry
*> entries
;
100 entries
.reserve(cache_info_entries
.size());
101 /* first verify that all entries are still valid */
102 for (auto cache_info
: cache_info_entries
) {
103 ldout(cct
, 10) << "chain_cache_entry: cache_locator="
104 << cache_info
->cache_locator
<< dendl
;
105 auto iter
= cache_map
.find(cache_info
->cache_locator
);
106 if (iter
== cache_map
.end()) {
107 ldout(cct
, 20) << "chain_cache_entry: couldn't find cache locator" << dendl
;
111 auto entry
= &iter
->second
;
113 if (entry
->gen
!= cache_info
->gen
) {
114 ldout(cct
, 20) << "chain_cache_entry: entry.gen (" << entry
->gen
115 << ") != cache_info.gen (" << cache_info
->gen
<< ")"
119 entries
.push_back(entry
);
123 chained_entry
->cache
->chain_cb(chained_entry
->key
, chained_entry
->data
);
125 for (auto entry
: entries
) {
126 entry
->chained_entries
.push_back(make_pair(chained_entry
->cache
,
127 chained_entry
->key
));
133 void ObjectCache::put(const string
& name
, ObjectCacheInfo
& info
, rgw_cache_entry_info
*cache_info
)
135 RWLock::WLocker
l(lock
);
141 ldout(cct
, 10) << "cache put: name=" << name
<< " info.flags=0x"
142 << std::hex
<< info
.flags
<< std::dec
<< dendl
;
144 auto [iter
, inserted
] = cache_map
.emplace(name
, ObjectCacheEntry
{});
145 ObjectCacheEntry
& entry
= iter
->second
;
146 entry
.info
.time_added
= ceph::coarse_mono_clock::now();
148 entry
.lru_iter
= lru
.end();
150 ObjectCacheInfo
& target
= entry
.info
;
152 invalidate_lru(entry
);
154 entry
.chained_entries
.clear();
157 touch_lru(name
, entry
, entry
.lru_iter
);
159 target
.status
= info
.status
;
161 if (info
.status
< 0) {
163 target
.xattrs
.clear();
169 cache_info
->cache_locator
= name
;
170 cache_info
->gen
= entry
.gen
;
173 target
.flags
|= info
.flags
;
175 if (info
.flags
& CACHE_FLAG_META
)
176 target
.meta
= info
.meta
;
177 else if (!(info
.flags
& CACHE_FLAG_MODIFY_XATTRS
))
178 target
.flags
&= ~CACHE_FLAG_META
; // non-meta change should reset meta
180 if (info
.flags
& CACHE_FLAG_XATTRS
) {
181 target
.xattrs
= info
.xattrs
;
182 map
<string
, bufferlist
>::iterator iter
;
183 for (iter
= target
.xattrs
.begin(); iter
!= target
.xattrs
.end(); ++iter
) {
184 ldout(cct
, 10) << "updating xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
186 } else if (info
.flags
& CACHE_FLAG_MODIFY_XATTRS
) {
187 map
<string
, bufferlist
>::iterator iter
;
188 for (iter
= info
.rm_xattrs
.begin(); iter
!= info
.rm_xattrs
.end(); ++iter
) {
189 ldout(cct
, 10) << "removing xattr: name=" << iter
->first
<< dendl
;
190 target
.xattrs
.erase(iter
->first
);
192 for (iter
= info
.xattrs
.begin(); iter
!= info
.xattrs
.end(); ++iter
) {
193 ldout(cct
, 10) << "appending xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
194 target
.xattrs
[iter
->first
] = iter
->second
;
198 if (info
.flags
& CACHE_FLAG_DATA
)
199 target
.data
= info
.data
;
201 if (info
.flags
& CACHE_FLAG_OBJV
)
202 target
.version
= info
.version
;
205 bool ObjectCache::remove(const string
& name
)
207 RWLock::WLocker
l(lock
);
213 auto iter
= cache_map
.find(name
);
214 if (iter
== cache_map
.end())
217 ldout(cct
, 10) << "removing " << name
<< " from cache" << dendl
;
218 ObjectCacheEntry
& entry
= iter
->second
;
220 for (auto& kv
: entry
.chained_entries
) {
221 kv
.first
->invalidate(kv
.second
);
224 remove_lru(name
, iter
->second
.lru_iter
);
225 cache_map
.erase(iter
);
229 void ObjectCache::touch_lru(const string
& name
, ObjectCacheEntry
& entry
,
230 std::list
<string
>::iterator
& lru_iter
)
232 while (lru_size
> (size_t)cct
->_conf
->rgw_cache_lru_size
) {
233 auto iter
= lru
.begin();
234 if ((*iter
).compare(name
) == 0) {
236 * if the entry we're touching happens to be at the lru end, don't remove it,
237 * lru shrinking can wait for next time
241 auto map_iter
= cache_map
.find(*iter
);
242 ldout(cct
, 10) << "removing entry: name=" << *iter
<< " from cache LRU" << dendl
;
243 if (map_iter
!= cache_map
.end()) {
244 ObjectCacheEntry
& entry
= map_iter
->second
;
245 invalidate_lru(entry
);
246 cache_map
.erase(map_iter
);
252 if (lru_iter
== lru
.end()) {
256 ldout(cct
, 10) << "adding " << name
<< " to cache LRU end" << dendl
;
258 ldout(cct
, 10) << "moving " << name
<< " to cache LRU end" << dendl
;
261 lru_iter
= lru
.end();
266 entry
.lru_promotion_ts
= lru_counter
;
269 void ObjectCache::remove_lru(const string
& name
,
270 std::list
<string
>::iterator
& lru_iter
)
272 if (lru_iter
== lru
.end())
277 lru_iter
= lru
.end();
280 void ObjectCache::invalidate_lru(ObjectCacheEntry
& entry
)
282 for (auto iter
= entry
.chained_entries
.begin();
283 iter
!= entry
.chained_entries
.end(); ++iter
) {
284 RGWChainedCache
*chained_cache
= iter
->first
;
285 chained_cache
->invalidate(iter
->second
);
289 void ObjectCache::set_enabled(bool status
)
291 RWLock::WLocker
l(lock
);
300 void ObjectCache::invalidate_all()
302 RWLock::WLocker
l(lock
);
307 void ObjectCache::do_invalidate_all()
316 for (auto& cache
: chained_cache
) {
317 cache
->invalidate_all();
321 void ObjectCache::chain_cache(RGWChainedCache
*cache
) {
322 RWLock::WLocker
l(lock
);
323 chained_cache
.push_back(cache
);
326 void ObjectCache::unchain_cache(RGWChainedCache
*cache
) {
327 RWLock::WLocker
l(lock
);
329 auto iter
= chained_cache
.begin();
330 for (; iter
!= chained_cache
.end(); ++iter
) {
331 if (cache
== *iter
) {
332 chained_cache
.erase(iter
);
333 cache
->unregistered();
339 ObjectCache::~ObjectCache()
341 for (auto cache
: chained_cache
) {
342 cache
->unregistered();