]>
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 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
.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
);
77 ldout(cct
, 10) << "cache get: name=" << name
<< " : hit (requested=0x"
78 << std::hex
<< mask
<< ", cached=0x" << src
.flags
79 << std::dec
<< ")" << dendl
;
83 cache_info
->cache_locator
= name
;
84 cache_info
->gen
= entry
->gen
;
86 if(perfcounter
) perfcounter
->inc(l_rgw_cache_hit
);
91 bool ObjectCache::chain_cache_entry(std::initializer_list
<rgw_cache_entry_info
*> cache_info_entries
,
92 RGWChainedCache::Entry
*chained_entry
)
94 std::unique_lock l
{lock
};
100 std::vector
<ObjectCacheEntry
*> entries
;
101 entries
.reserve(cache_info_entries
.size());
102 /* first verify that all entries are still valid */
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
);
107 if (iter
== cache_map
.end()) {
108 ldout(cct
, 20) << "chain_cache_entry: couldn't find cache locator" << dendl
;
112 auto entry
= &iter
->second
;
114 if (entry
->gen
!= cache_info
->gen
) {
115 ldout(cct
, 20) << "chain_cache_entry: entry.gen (" << entry
->gen
116 << ") != cache_info.gen (" << cache_info
->gen
<< ")"
120 entries
.push_back(entry
);
124 chained_entry
->cache
->chain_cb(chained_entry
->key
, chained_entry
->data
);
126 for (auto entry
: entries
) {
127 entry
->chained_entries
.push_back(make_pair(chained_entry
->cache
,
128 chained_entry
->key
));
134 void ObjectCache::put(const string
& name
, ObjectCacheInfo
& info
, rgw_cache_entry_info
*cache_info
)
136 std::unique_lock l
{lock
};
142 ldout(cct
, 10) << "cache put: name=" << name
<< " info.flags=0x"
143 << std::hex
<< info
.flags
<< std::dec
<< dendl
;
145 auto [iter
, inserted
] = cache_map
.emplace(name
, ObjectCacheEntry
{});
146 ObjectCacheEntry
& entry
= iter
->second
;
147 entry
.info
.time_added
= ceph::coarse_mono_clock::now();
149 entry
.lru_iter
= lru
.end();
151 ObjectCacheInfo
& target
= entry
.info
;
153 invalidate_lru(entry
);
155 entry
.chained_entries
.clear();
158 touch_lru(name
, entry
, entry
.lru_iter
);
160 target
.status
= info
.status
;
162 if (info
.status
< 0) {
164 target
.xattrs
.clear();
170 cache_info
->cache_locator
= name
;
171 cache_info
->gen
= entry
.gen
;
174 target
.flags
|= info
.flags
;
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
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
;
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
);
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
;
199 if (info
.flags
& CACHE_FLAG_DATA
)
200 target
.data
= info
.data
;
202 if (info
.flags
& CACHE_FLAG_OBJV
)
203 target
.version
= info
.version
;
206 bool ObjectCache::remove(const string
& name
)
208 std::unique_lock l
{lock
};
214 auto iter
= cache_map
.find(name
);
215 if (iter
== cache_map
.end())
218 ldout(cct
, 10) << "removing " << name
<< " from cache" << dendl
;
219 ObjectCacheEntry
& entry
= iter
->second
;
221 for (auto& kv
: entry
.chained_entries
) {
222 kv
.first
->invalidate(kv
.second
);
225 remove_lru(name
, iter
->second
.lru_iter
);
226 cache_map
.erase(iter
);
230 void ObjectCache::touch_lru(const string
& name
, ObjectCacheEntry
& entry
,
231 std::list
<string
>::iterator
& lru_iter
)
233 while (lru_size
> (size_t)cct
->_conf
->rgw_cache_lru_size
) {
234 auto iter
= lru
.begin();
235 if ((*iter
).compare(name
) == 0) {
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
242 auto map_iter
= cache_map
.find(*iter
);
243 ldout(cct
, 10) << "removing entry: name=" << *iter
<< " from cache LRU" << dendl
;
244 if (map_iter
!= cache_map
.end()) {
245 ObjectCacheEntry
& entry
= map_iter
->second
;
246 invalidate_lru(entry
);
247 cache_map
.erase(map_iter
);
253 if (lru_iter
== lru
.end()) {
257 ldout(cct
, 10) << "adding " << name
<< " to cache LRU end" << dendl
;
259 ldout(cct
, 10) << "moving " << name
<< " to cache LRU end" << dendl
;
262 lru_iter
= lru
.end();
267 entry
.lru_promotion_ts
= lru_counter
;
270 void ObjectCache::remove_lru(const string
& name
,
271 std::list
<string
>::iterator
& lru_iter
)
273 if (lru_iter
== lru
.end())
278 lru_iter
= lru
.end();
281 void ObjectCache::invalidate_lru(ObjectCacheEntry
& entry
)
283 for (auto iter
= entry
.chained_entries
.begin();
284 iter
!= entry
.chained_entries
.end(); ++iter
) {
285 RGWChainedCache
*chained_cache
= iter
->first
;
286 chained_cache
->invalidate(iter
->second
);
290 void ObjectCache::set_enabled(bool status
)
292 std::unique_lock l
{lock
};
301 void ObjectCache::invalidate_all()
303 std::unique_lock l
{lock
};
308 void ObjectCache::do_invalidate_all()
317 for (auto& cache
: chained_cache
) {
318 cache
->invalidate_all();
322 void ObjectCache::chain_cache(RGWChainedCache
*cache
) {
323 std::unique_lock l
{lock
};
324 chained_cache
.push_back(cache
);
327 void ObjectCache::unchain_cache(RGWChainedCache
*cache
) {
328 std::unique_lock l
{lock
};
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();
340 ObjectCache::~ObjectCache()
342 for (auto cache
: chained_cache
) {
343 cache
->unregistered();