]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_cache.cc
6908e7f9d252b119b03fe29b83cf4ca1def8365e
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 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 ldout(cct
, 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 ldout(cct
, 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 ldout(cct
, 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 ldout(cct
, 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(name
, *entry
, iter
->second
.lru_iter
);
69 ObjectCacheInfo
& src
= iter
->second
.info
;
70 if(src
.status
== -ENOENT
) {
71 ldout(cct
, 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 ldout(cct
, 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 ldout(cct
, 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(std::initializer_list
<rgw_cache_entry_info
*> cache_info_entries
,
97 RGWChainedCache::Entry
*chained_entry
)
99 std::unique_lock l
{lock
};
105 std::vector
<ObjectCacheEntry
*> entries
;
106 entries
.reserve(cache_info_entries
.size());
107 /* first verify that all entries are still valid */
108 for (auto cache_info
: cache_info_entries
) {
109 ldout(cct
, 10) << "chain_cache_entry: cache_locator="
110 << cache_info
->cache_locator
<< dendl
;
111 auto iter
= cache_map
.find(cache_info
->cache_locator
);
112 if (iter
== cache_map
.end()) {
113 ldout(cct
, 20) << "chain_cache_entry: couldn't find cache locator" << dendl
;
117 auto entry
= &iter
->second
;
119 if (entry
->gen
!= cache_info
->gen
) {
120 ldout(cct
, 20) << "chain_cache_entry: entry.gen (" << entry
->gen
121 << ") != cache_info.gen (" << cache_info
->gen
<< ")"
125 entries
.push_back(entry
);
129 chained_entry
->cache
->chain_cb(chained_entry
->key
, chained_entry
->data
);
131 for (auto entry
: entries
) {
132 entry
->chained_entries
.push_back(make_pair(chained_entry
->cache
,
133 chained_entry
->key
));
139 void ObjectCache::put(const string
& name
, ObjectCacheInfo
& info
, rgw_cache_entry_info
*cache_info
)
141 std::unique_lock l
{lock
};
147 ldout(cct
, 10) << "cache put: name=" << name
<< " info.flags=0x"
148 << std::hex
<< info
.flags
<< std::dec
<< dendl
;
150 auto [iter
, inserted
] = cache_map
.emplace(name
, ObjectCacheEntry
{});
151 ObjectCacheEntry
& entry
= iter
->second
;
152 entry
.info
.time_added
= ceph::coarse_mono_clock::now();
154 entry
.lru_iter
= lru
.end();
156 ObjectCacheInfo
& target
= entry
.info
;
158 invalidate_lru(entry
);
160 entry
.chained_entries
.clear();
163 touch_lru(name
, entry
, entry
.lru_iter
);
165 target
.status
= info
.status
;
167 if (info
.status
< 0) {
169 target
.xattrs
.clear();
175 cache_info
->cache_locator
= name
;
176 cache_info
->gen
= entry
.gen
;
179 // put() must include the latest version if we're going to keep caching it
180 target
.flags
&= ~CACHE_FLAG_OBJV
;
182 target
.flags
|= info
.flags
;
184 if (info
.flags
& CACHE_FLAG_META
)
185 target
.meta
= info
.meta
;
186 else if (!(info
.flags
& CACHE_FLAG_MODIFY_XATTRS
))
187 target
.flags
&= ~CACHE_FLAG_META
; // non-meta change should reset meta
189 if (info
.flags
& CACHE_FLAG_XATTRS
) {
190 target
.xattrs
= info
.xattrs
;
191 map
<string
, bufferlist
>::iterator iter
;
192 for (iter
= target
.xattrs
.begin(); iter
!= target
.xattrs
.end(); ++iter
) {
193 ldout(cct
, 10) << "updating xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
195 } else if (info
.flags
& CACHE_FLAG_MODIFY_XATTRS
) {
196 map
<string
, bufferlist
>::iterator iter
;
197 for (iter
= info
.rm_xattrs
.begin(); iter
!= info
.rm_xattrs
.end(); ++iter
) {
198 ldout(cct
, 10) << "removing xattr: name=" << iter
->first
<< dendl
;
199 target
.xattrs
.erase(iter
->first
);
201 for (iter
= info
.xattrs
.begin(); iter
!= info
.xattrs
.end(); ++iter
) {
202 ldout(cct
, 10) << "appending xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
203 target
.xattrs
[iter
->first
] = iter
->second
;
207 if (info
.flags
& CACHE_FLAG_DATA
)
208 target
.data
= info
.data
;
210 if (info
.flags
& CACHE_FLAG_OBJV
)
211 target
.version
= info
.version
;
214 bool ObjectCache::remove(const string
& name
)
216 std::unique_lock l
{lock
};
222 auto iter
= cache_map
.find(name
);
223 if (iter
== cache_map
.end())
226 ldout(cct
, 10) << "removing " << name
<< " from cache" << dendl
;
227 ObjectCacheEntry
& entry
= iter
->second
;
229 for (auto& kv
: entry
.chained_entries
) {
230 kv
.first
->invalidate(kv
.second
);
233 remove_lru(name
, iter
->second
.lru_iter
);
234 cache_map
.erase(iter
);
238 void ObjectCache::touch_lru(const string
& name
, ObjectCacheEntry
& entry
,
239 std::list
<string
>::iterator
& lru_iter
)
241 while (lru_size
> (size_t)cct
->_conf
->rgw_cache_lru_size
) {
242 auto iter
= lru
.begin();
243 if ((*iter
).compare(name
) == 0) {
245 * if the entry we're touching happens to be at the lru end, don't remove it,
246 * lru shrinking can wait for next time
250 auto map_iter
= cache_map
.find(*iter
);
251 ldout(cct
, 10) << "removing entry: name=" << *iter
<< " from cache LRU" << dendl
;
252 if (map_iter
!= cache_map
.end()) {
253 ObjectCacheEntry
& entry
= map_iter
->second
;
254 invalidate_lru(entry
);
255 cache_map
.erase(map_iter
);
261 if (lru_iter
== lru
.end()) {
265 ldout(cct
, 10) << "adding " << name
<< " to cache LRU end" << dendl
;
267 ldout(cct
, 10) << "moving " << name
<< " to cache LRU end" << dendl
;
270 lru_iter
= lru
.end();
275 entry
.lru_promotion_ts
= lru_counter
;
278 void ObjectCache::remove_lru(const string
& name
,
279 std::list
<string
>::iterator
& lru_iter
)
281 if (lru_iter
== lru
.end())
286 lru_iter
= lru
.end();
289 void ObjectCache::invalidate_lru(ObjectCacheEntry
& entry
)
291 for (auto iter
= entry
.chained_entries
.begin();
292 iter
!= entry
.chained_entries
.end(); ++iter
) {
293 RGWChainedCache
*chained_cache
= iter
->first
;
294 chained_cache
->invalidate(iter
->second
);
298 void ObjectCache::set_enabled(bool status
)
300 std::unique_lock l
{lock
};
309 void ObjectCache::invalidate_all()
311 std::unique_lock l
{lock
};
316 void ObjectCache::do_invalidate_all()
325 for (auto& cache
: chained_cache
) {
326 cache
->invalidate_all();
330 void ObjectCache::chain_cache(RGWChainedCache
*cache
) {
331 std::unique_lock l
{lock
};
332 chained_cache
.push_back(cache
);
335 void ObjectCache::unchain_cache(RGWChainedCache
*cache
) {
336 std::unique_lock l
{lock
};
338 auto iter
= chained_cache
.begin();
339 for (; iter
!= chained_cache
.end(); ++iter
) {
340 if (cache
== *iter
) {
341 chained_cache
.erase(iter
);
342 cache
->unregistered();
348 ObjectCache::~ObjectCache()
350 for (auto cache
: chained_cache
) {
351 cache
->unregistered();