]>
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
13 int ObjectCache::get(const DoutPrefixProvider
*dpp
, const string
& name
, ObjectCacheInfo
& info
, uint32_t mask
, rgw_cache_entry_info
*cache_info
)
16 std::shared_lock rl
{lock
};
17 std::unique_lock wl
{lock
, std::defer_lock
}; // may be promoted to write lock
21 auto iter
= cache_map
.find(name
);
22 if (iter
== cache_map
.end()) {
23 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : miss" << dendl
;
25 perfcounter
->inc(l_rgw_cache_miss
);
31 (ceph::coarse_mono_clock::now() - iter
->second
.info
.time_added
) > expiry
) {
32 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : expiry miss" << dendl
;
34 wl
.lock(); // write lock for expiration
35 // check that wasn't already removed by other thread
36 iter
= cache_map
.find(name
);
37 if (iter
!= cache_map
.end()) {
38 for (auto &kv
: iter
->second
.chained_entries
)
39 kv
.first
->invalidate(kv
.second
);
40 remove_lru(name
, iter
->second
.lru_iter
);
41 cache_map
.erase(iter
);
44 perfcounter
->inc(l_rgw_cache_miss
);
49 ObjectCacheEntry
*entry
= &iter
->second
;
51 if (lru_counter
- entry
->lru_promotion_ts
> lru_window
) {
52 ldpp_dout(dpp
, 20) << "cache get: touching lru, lru_counter=" << lru_counter
53 << " promotion_ts=" << entry
->lru_promotion_ts
<< dendl
;
55 wl
.lock(); // write lock for touch_lru()
56 /* need to redo this because entry might have dropped off the cache */
57 iter
= cache_map
.find(name
);
58 if (iter
== cache_map
.end()) {
59 ldpp_dout(dpp
, 10) << "lost race! cache get: name=" << name
<< " : miss" << dendl
;
60 if(perfcounter
) perfcounter
->inc(l_rgw_cache_miss
);
64 entry
= &iter
->second
;
65 /* check again, we might have lost a race here */
66 if (lru_counter
- entry
->lru_promotion_ts
> lru_window
) {
67 touch_lru(dpp
, name
, *entry
, iter
->second
.lru_iter
);
71 ObjectCacheInfo
& src
= iter
->second
.info
;
72 if(src
.status
== -ENOENT
) {
73 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : hit (negative entry)" << dendl
;
74 if (perfcounter
) perfcounter
->inc(l_rgw_cache_hit
);
77 if ((src
.flags
& mask
) != mask
) {
78 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : type miss (requested=0x"
79 << std::hex
<< mask
<< ", cached=0x" << src
.flags
80 << std::dec
<< ")" << dendl
;
81 if(perfcounter
) perfcounter
->inc(l_rgw_cache_miss
);
84 ldpp_dout(dpp
, 10) << "cache get: name=" << name
<< " : hit (requested=0x"
85 << std::hex
<< mask
<< ", cached=0x" << src
.flags
86 << std::dec
<< ")" << dendl
;
90 cache_info
->cache_locator
= name
;
91 cache_info
->gen
= entry
->gen
;
93 if(perfcounter
) perfcounter
->inc(l_rgw_cache_hit
);
98 bool ObjectCache::chain_cache_entry(const DoutPrefixProvider
*dpp
,
99 std::initializer_list
<rgw_cache_entry_info
*> cache_info_entries
,
100 RGWChainedCache::Entry
*chained_entry
)
102 std::unique_lock l
{lock
};
108 std::vector
<ObjectCacheEntry
*> entries
;
109 entries
.reserve(cache_info_entries
.size());
110 /* first verify that all entries are still valid */
111 for (auto cache_info
: cache_info_entries
) {
112 ldpp_dout(dpp
, 10) << "chain_cache_entry: cache_locator="
113 << cache_info
->cache_locator
<< dendl
;
114 auto iter
= cache_map
.find(cache_info
->cache_locator
);
115 if (iter
== cache_map
.end()) {
116 ldpp_dout(dpp
, 20) << "chain_cache_entry: couldn't find cache locator" << dendl
;
120 auto entry
= &iter
->second
;
122 if (entry
->gen
!= cache_info
->gen
) {
123 ldpp_dout(dpp
, 20) << "chain_cache_entry: entry.gen (" << entry
->gen
124 << ") != cache_info.gen (" << cache_info
->gen
<< ")"
128 entries
.push_back(entry
);
132 chained_entry
->cache
->chain_cb(chained_entry
->key
, chained_entry
->data
);
134 for (auto entry
: entries
) {
135 entry
->chained_entries
.push_back(make_pair(chained_entry
->cache
,
136 chained_entry
->key
));
142 void ObjectCache::put(const DoutPrefixProvider
*dpp
, const string
& name
, ObjectCacheInfo
& info
, rgw_cache_entry_info
*cache_info
)
144 std::unique_lock l
{lock
};
150 ldpp_dout(dpp
, 10) << "cache put: name=" << name
<< " info.flags=0x"
151 << std::hex
<< info
.flags
<< std::dec
<< dendl
;
153 auto [iter
, inserted
] = cache_map
.emplace(name
, ObjectCacheEntry
{});
154 ObjectCacheEntry
& entry
= iter
->second
;
155 entry
.info
.time_added
= ceph::coarse_mono_clock::now();
157 entry
.lru_iter
= lru
.end();
159 ObjectCacheInfo
& target
= entry
.info
;
161 invalidate_lru(entry
);
163 entry
.chained_entries
.clear();
166 touch_lru(dpp
, name
, entry
, entry
.lru_iter
);
168 target
.status
= info
.status
;
170 if (info
.status
< 0) {
172 target
.xattrs
.clear();
178 cache_info
->cache_locator
= name
;
179 cache_info
->gen
= entry
.gen
;
182 // put() must include the latest version if we're going to keep caching it
183 target
.flags
&= ~CACHE_FLAG_OBJV
;
185 target
.flags
|= info
.flags
;
187 if (info
.flags
& CACHE_FLAG_META
)
188 target
.meta
= info
.meta
;
189 else if (!(info
.flags
& CACHE_FLAG_MODIFY_XATTRS
))
190 target
.flags
&= ~CACHE_FLAG_META
; // non-meta change should reset meta
192 if (info
.flags
& CACHE_FLAG_XATTRS
) {
193 target
.xattrs
= info
.xattrs
;
194 map
<string
, bufferlist
>::iterator iter
;
195 for (iter
= target
.xattrs
.begin(); iter
!= target
.xattrs
.end(); ++iter
) {
196 ldpp_dout(dpp
, 10) << "updating xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
198 } else if (info
.flags
& CACHE_FLAG_MODIFY_XATTRS
) {
199 map
<string
, bufferlist
>::iterator iter
;
200 for (iter
= info
.rm_xattrs
.begin(); iter
!= info
.rm_xattrs
.end(); ++iter
) {
201 ldpp_dout(dpp
, 10) << "removing xattr: name=" << iter
->first
<< dendl
;
202 target
.xattrs
.erase(iter
->first
);
204 for (iter
= info
.xattrs
.begin(); iter
!= info
.xattrs
.end(); ++iter
) {
205 ldpp_dout(dpp
, 10) << "appending xattr: name=" << iter
->first
<< " bl.length()=" << iter
->second
.length() << dendl
;
206 target
.xattrs
[iter
->first
] = iter
->second
;
210 if (info
.flags
& CACHE_FLAG_DATA
)
211 target
.data
= info
.data
;
213 if (info
.flags
& CACHE_FLAG_OBJV
)
214 target
.version
= info
.version
;
217 // WARNING: This function /must not/ be modified to cache a
218 // negative lookup. It must only invalidate.
219 bool ObjectCache::invalidate_remove(const DoutPrefixProvider
*dpp
, const string
& name
)
221 std::unique_lock l
{lock
};
227 auto iter
= cache_map
.find(name
);
228 if (iter
== cache_map
.end())
231 ldpp_dout(dpp
, 10) << "removing " << name
<< " from cache" << dendl
;
232 ObjectCacheEntry
& entry
= iter
->second
;
234 for (auto& kv
: entry
.chained_entries
) {
235 kv
.first
->invalidate(kv
.second
);
238 remove_lru(name
, iter
->second
.lru_iter
);
239 cache_map
.erase(iter
);
243 void ObjectCache::touch_lru(const DoutPrefixProvider
*dpp
, const string
& name
, ObjectCacheEntry
& entry
,
244 std::list
<string
>::iterator
& lru_iter
)
246 while (lru_size
> (size_t)cct
->_conf
->rgw_cache_lru_size
) {
247 auto iter
= lru
.begin();
248 if ((*iter
).compare(name
) == 0) {
250 * if the entry we're touching happens to be at the lru end, don't remove it,
251 * lru shrinking can wait for next time
255 auto map_iter
= cache_map
.find(*iter
);
256 ldout(cct
, 10) << "removing entry: name=" << *iter
<< " from cache LRU" << dendl
;
257 if (map_iter
!= cache_map
.end()) {
258 ObjectCacheEntry
& entry
= map_iter
->second
;
259 invalidate_lru(entry
);
260 cache_map
.erase(map_iter
);
266 if (lru_iter
== lru
.end()) {
270 ldpp_dout(dpp
, 10) << "adding " << name
<< " to cache LRU end" << dendl
;
272 ldpp_dout(dpp
, 10) << "moving " << name
<< " to cache LRU end" << dendl
;
275 lru_iter
= lru
.end();
280 entry
.lru_promotion_ts
= lru_counter
;
283 void ObjectCache::remove_lru(const string
& name
,
284 std::list
<string
>::iterator
& lru_iter
)
286 if (lru_iter
== lru
.end())
291 lru_iter
= lru
.end();
294 void ObjectCache::invalidate_lru(ObjectCacheEntry
& entry
)
296 for (auto iter
= entry
.chained_entries
.begin();
297 iter
!= entry
.chained_entries
.end(); ++iter
) {
298 RGWChainedCache
*chained_cache
= iter
->first
;
299 chained_cache
->invalidate(iter
->second
);
303 void ObjectCache::set_enabled(bool status
)
305 std::unique_lock l
{lock
};
314 void ObjectCache::invalidate_all()
316 std::unique_lock l
{lock
};
321 void ObjectCache::do_invalidate_all()
330 for (auto& cache
: chained_cache
) {
331 cache
->invalidate_all();
335 void ObjectCache::chain_cache(RGWChainedCache
*cache
) {
336 std::unique_lock l
{lock
};
337 chained_cache
.push_back(cache
);
340 void ObjectCache::unchain_cache(RGWChainedCache
*cache
) {
341 std::unique_lock l
{lock
};
343 auto iter
= chained_cache
.begin();
344 for (; iter
!= chained_cache
.end(); ++iter
) {
345 if (cache
== *iter
) {
346 chained_cache
.erase(iter
);
347 cache
->unregistered();
353 ObjectCache::~ObjectCache()
355 for (auto cache
: chained_cache
) {
356 cache
->unregistered();
360 void ObjectMetaInfo::generate_test_instances(list
<ObjectMetaInfo
*>& o
)
362 ObjectMetaInfo
*m
= new ObjectMetaInfo
;
363 m
->size
= 1024 * 1024;
365 o
.push_back(new ObjectMetaInfo
);
368 void ObjectMetaInfo::dump(Formatter
*f
) const
370 encode_json("size", size
, f
);
371 encode_json("mtime", utime_t(mtime
), f
);
374 void ObjectCacheInfo::generate_test_instances(list
<ObjectCacheInfo
*>& o
)
377 ObjectCacheInfo
*i
= new ObjectCacheInfo
;
379 i
->flags
= CACHE_FLAG_MODIFY_XATTRS
;
380 string s
= "this is a string";
381 string s2
= "this is a another string";
382 bufferlist data
, data2
;
386 i
->xattrs
["x1"] = data
;
387 i
->xattrs
["x2"] = data2
;
388 i
->rm_xattrs
["r2"] = data2
;
389 i
->rm_xattrs
["r3"] = data
;
390 i
->meta
.size
= 512 * 1024;
392 o
.push_back(new ObjectCacheInfo
);
395 void ObjectCacheInfo::dump(Formatter
*f
) const
397 encode_json("status", status
, f
);
398 encode_json("flags", flags
, f
);
399 encode_json("data", data
, f
);
400 encode_json_map("xattrs", "name", "value", "length", xattrs
, f
);
401 encode_json_map("rm_xattrs", "name", "value", "length", rm_xattrs
, f
);
402 encode_json("meta", meta
, f
);
406 void RGWCacheNotifyInfo::generate_test_instances(list
<RGWCacheNotifyInfo
*>& o
)
408 o
.push_back(new RGWCacheNotifyInfo
);
411 void RGWCacheNotifyInfo::dump(Formatter
*f
) const
413 encode_json("op", op
, f
);
414 encode_json("obj", obj
, f
);
415 encode_json("obj_info", obj_info
, f
);
416 encode_json("ofs", ofs
, f
);
417 encode_json("ns", ns
, f
);