]>
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 ft=cpp
5 #include "rgw_perf_counters.h"
9 #define dout_subsys ceph_subsys_rgw
12 int ObjectCache::get(const DoutPrefixProvider
*dpp
, const string
& name
, ObjectCacheInfo
& info
, uint32_t mask
, rgw_cache_entry_info
*cache_info
)
15 std::shared_lock rl
{lock
};
19 auto iter
= cache_map
.find(name
);
20 if (iter
== cache_map
.end()) {
21 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : miss" << dendl
;
23 perfcounter
->inc(l_rgw_cache_miss
);
29 (ceph::coarse_mono_clock::now() - iter
->second
.info
.time_added
) > expiry
) {
30 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : expiry miss" << dendl
;
32 std::unique_lock wl
{lock
}; // write lock for insertion
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
);
42 perfcounter
->inc(l_rgw_cache_miss
);
47 ObjectCacheEntry
*entry
= &iter
->second
;
49 if (lru_counter
- entry
->lru_promotion_ts
> lru_window
) {
50 ldpp_dout(dpp
, 20) << "cache get: touching lru, lru_counter=" << lru_counter
51 << " promotion_ts=" << entry
->lru_promotion_ts
<< dendl
;
53 std::unique_lock wl
{lock
}; // write lock for insertion
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 ldpp_dout(dpp
, 10) << "lost race! cache get: name=" << name
<< " : miss" << dendl
;
58 if(perfcounter
) perfcounter
->inc(l_rgw_cache_miss
);
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(dpp
, name
, *entry
, iter
->second
.lru_iter
);
69 ObjectCacheInfo
& src
= iter
->second
.info
;
70 if(src
.status
== -ENOENT
) {
71 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : hit (negative entry)" << dendl
;
72 if (perfcounter
) perfcounter
->inc(l_rgw_cache_hit
);
75 if ((src
.flags
& mask
) != mask
) {
76 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : type miss (requested=0x"
77 << std::hex
<< mask
<< ", cached=0x" << src
.flags
78 << std::dec
<< ")" << dendl
;
79 if(perfcounter
) perfcounter
->inc(l_rgw_cache_miss
);
82 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : hit (requested=0x"
83 << std::hex
<< mask
<< ", cached=0x" << src
.flags
84 << std::dec
<< ")" << dendl
;
88 cache_info
->cache_locator
= name
;
89 cache_info
->gen
= entry
->gen
;
91 if(perfcounter
) perfcounter
->inc(l_rgw_cache_hit
);
96 bool ObjectCache::chain_cache_entry(const DoutPrefixProvider
*dpp
,
97 std::initializer_list
<rgw_cache_entry_info
*> cache_info_entries
,
98 RGWChainedCache::Entry
*chained_entry
)
100 std::unique_lock l
{lock
};
106 std::vector
<ObjectCacheEntry
*> entries
;
107 entries
.reserve(cache_info_entries
.size());
108 /* first verify that all entries are still valid */
109 for (auto cache_info
: cache_info_entries
) {
110 ldpp_dout(dpp
, 10) << "chain_cache_entry: cache_locator="
111 << cache_info
->cache_locator
<< dendl
;
112 auto iter
= cache_map
.find(cache_info
->cache_locator
);
113 if (iter
== cache_map
.end()) {
114 ldpp_dout(dpp
, 20) << "chain_cache_entry: couldn't find cache locator" << dendl
;
118 auto entry
= &iter
->second
;
120 if (entry
->gen
!= cache_info
->gen
) {
121 ldpp_dout(dpp
, 20) << "chain_cache_entry: entry.gen (" << entry
->gen
122 << ") != cache_info.gen (" << cache_info
->gen
<< ")"
126 entries
.push_back(entry
);
130 chained_entry
->cache
->chain_cb(chained_entry
->key
, chained_entry
->data
);
132 for (auto entry
: entries
) {
133 entry
->chained_entries
.push_back(make_pair(chained_entry
->cache
,
134 chained_entry
->key
));
140 void ObjectCache::put(const DoutPrefixProvider
*dpp
, const string
& name
, ObjectCacheInfo
& info
, rgw_cache_entry_info
*cache_info
)
142 std::unique_lock l
{lock
};
148 ldpp_dout(dpp
, 10) << "cache put: name=" << name
<< " info.flags=0x"
149 << std::hex
<< info
.flags
<< std::dec
<< dendl
;
151 auto [iter
, inserted
] = cache_map
.emplace(name
, ObjectCacheEntry
{});
152 ObjectCacheEntry
& entry
= iter
->second
;
153 entry
.info
.time_added
= ceph::coarse_mono_clock::now();
155 entry
.lru_iter
= lru
.end();
157 ObjectCacheInfo
& target
= entry
.info
;
159 invalidate_lru(entry
);
161 entry
.chained_entries
.clear();
164 touch_lru(dpp
, name
, entry
, entry
.lru_iter
);
166 target
.status
= info
.status
;
168 if (info
.status
< 0) {
170 target
.xattrs
.clear();
176 cache_info
->cache_locator
= name
;
177 cache_info
->gen
= entry
.gen
;
180 // put() must include the latest version if we're going to keep caching it
181 target
.flags
&= ~CACHE_FLAG_OBJV
;
183 target
.flags
|= info
.flags
;
185 if (info
.flags
& CACHE_FLAG_META
)
186 target
.meta
= info
.meta
;
187 else if (!(info
.flags
& CACHE_FLAG_MODIFY_XATTRS
))
188 target
.flags
&= ~CACHE_FLAG_META
; // non-meta change should reset meta
190 if (info
.flags
& CACHE_FLAG_XATTRS
) {
191 target
.xattrs
= info
.xattrs
;
192 map
<string
, bufferlist
>::iterator iter
;
193 for (iter
= target
.xattrs
.begin(); iter
!= target
.xattrs
.end(); ++iter
) {
194 ldpp_dout(dpp
, 10) << "updating xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
196 } else if (info
.flags
& CACHE_FLAG_MODIFY_XATTRS
) {
197 map
<string
, bufferlist
>::iterator iter
;
198 for (iter
= info
.rm_xattrs
.begin(); iter
!= info
.rm_xattrs
.end(); ++iter
) {
199 ldpp_dout(dpp
, 10) << "removing xattr: name=" << iter
->first
<< dendl
;
200 target
.xattrs
.erase(iter
->first
);
202 for (iter
= info
.xattrs
.begin(); iter
!= info
.xattrs
.end(); ++iter
) {
203 ldpp_dout(dpp
, 10) << "appending xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
204 target
.xattrs
[iter
->first
] = iter
->second
;
208 if (info
.flags
& CACHE_FLAG_DATA
)
209 target
.data
= info
.data
;
211 if (info
.flags
& CACHE_FLAG_OBJV
)
212 target
.version
= info
.version
;
215 bool ObjectCache::remove(const DoutPrefixProvider
*dpp
, const string
& name
)
217 std::unique_lock l
{lock
};
223 auto iter
= cache_map
.find(name
);
224 if (iter
== cache_map
.end())
227 ldpp_dout(dpp
, 10) << "removing " << name
<< " from cache" << dendl
;
228 ObjectCacheEntry
& entry
= iter
->second
;
230 for (auto& kv
: entry
.chained_entries
) {
231 kv
.first
->invalidate(kv
.second
);
234 remove_lru(name
, iter
->second
.lru_iter
);
235 cache_map
.erase(iter
);
239 void ObjectCache::touch_lru(const DoutPrefixProvider
*dpp
, const string
& name
, ObjectCacheEntry
& entry
,
240 std::list
<string
>::iterator
& lru_iter
)
242 while (lru_size
> (size_t)cct
->_conf
->rgw_cache_lru_size
) {
243 auto iter
= lru
.begin();
244 if ((*iter
).compare(name
) == 0) {
246 * if the entry we're touching happens to be at the lru end, don't remove it,
247 * lru shrinking can wait for next time
251 auto map_iter
= cache_map
.find(*iter
);
252 ldout(cct
, 10) << "removing entry: name=" << *iter
<< " from cache LRU" << dendl
;
253 if (map_iter
!= cache_map
.end()) {
254 ObjectCacheEntry
& entry
= map_iter
->second
;
255 invalidate_lru(entry
);
256 cache_map
.erase(map_iter
);
262 if (lru_iter
== lru
.end()) {
266 ldpp_dout(dpp
, 10) << "adding " << name
<< " to cache LRU end" << dendl
;
268 ldpp_dout(dpp
, 10) << "moving " << name
<< " to cache LRU end" << dendl
;
271 lru_iter
= lru
.end();
276 entry
.lru_promotion_ts
= lru_counter
;
279 void ObjectCache::remove_lru(const string
& name
,
280 std::list
<string
>::iterator
& lru_iter
)
282 if (lru_iter
== lru
.end())
287 lru_iter
= lru
.end();
290 void ObjectCache::invalidate_lru(ObjectCacheEntry
& entry
)
292 for (auto iter
= entry
.chained_entries
.begin();
293 iter
!= entry
.chained_entries
.end(); ++iter
) {
294 RGWChainedCache
*chained_cache
= iter
->first
;
295 chained_cache
->invalidate(iter
->second
);
299 void ObjectCache::set_enabled(bool status
)
301 std::unique_lock l
{lock
};
310 void ObjectCache::invalidate_all()
312 std::unique_lock l
{lock
};
317 void ObjectCache::do_invalidate_all()
326 for (auto& cache
: chained_cache
) {
327 cache
->invalidate_all();
331 void ObjectCache::chain_cache(RGWChainedCache
*cache
) {
332 std::unique_lock l
{lock
};
333 chained_cache
.push_back(cache
);
336 void ObjectCache::unchain_cache(RGWChainedCache
*cache
) {
337 std::unique_lock l
{lock
};
339 auto iter
= chained_cache
.begin();
340 for (; iter
!= chained_cache
.end(); ++iter
) {
341 if (cache
== *iter
) {
342 chained_cache
.erase(iter
);
343 cache
->unregistered();
349 ObjectCache::~ObjectCache()
351 for (auto cache
: chained_cache
) {
352 cache
->unregistered();