]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_cache.cc
bump version to 12.2.5-pve1
[ceph.git] / ceph / src / rgw / rgw_cache.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "rgw_cache.h"
5
6#include <errno.h>
7
8#define dout_subsys ceph_subsys_rgw
9
10using namespace std;
11
3a9019d9 12int ObjectCache::get(const string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cache_entry_info *cache_info)
7c673cae
FG
13{
14 RWLock::RLocker l(lock);
15
16 if (!enabled) {
17 return -ENOENT;
18 }
19
b32b8144
FG
20 auto iter = cache_map.find(name);
21 if (iter == cache_map.end() ||
22 (expiry.count() &&
23 (ceph::coarse_mono_clock::now() - iter->second.info.time_added) > expiry)) {
7c673cae 24 ldout(cct, 10) << "cache get: name=" << name << " : miss" << dendl;
b32b8144
FG
25 if (perfcounter)
26 perfcounter->inc(l_rgw_cache_miss);
7c673cae
FG
27 return -ENOENT;
28 }
29
30 ObjectCacheEntry *entry = &iter->second;
31
32 if (lru_counter - entry->lru_promotion_ts > lru_window) {
33 ldout(cct, 20) << "cache get: touching lru, lru_counter=" << lru_counter
34 << " promotion_ts=" << entry->lru_promotion_ts << dendl;
35 lock.unlock();
36 lock.get_write(); /* promote lock to writer */
37
38 /* need to redo this because entry might have dropped off the cache */
39 iter = cache_map.find(name);
40 if (iter == cache_map.end()) {
41 ldout(cct, 10) << "lost race! cache get: name=" << name << " : miss" << dendl;
42 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
43 return -ENOENT;
44 }
45
46 entry = &iter->second;
47 /* check again, we might have lost a race here */
48 if (lru_counter - entry->lru_promotion_ts > lru_window) {
49 touch_lru(name, *entry, iter->second.lru_iter);
50 }
51 }
52
53 ObjectCacheInfo& src = iter->second.info;
54 if ((src.flags & mask) != mask) {
55 ldout(cct, 10) << "cache get: name=" << name << " : type miss (requested=0x"
56 << std::hex << mask << ", cached=0x" << src.flags
57 << std::dec << ")" << dendl;
58 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
59 return -ENOENT;
60 }
61 ldout(cct, 10) << "cache get: name=" << name << " : hit (requested=0x"
62 << std::hex << mask << ", cached=0x" << src.flags
63 << std::dec << ")" << dendl;
64
65 info = src;
66 if (cache_info) {
67 cache_info->cache_locator = name;
68 cache_info->gen = entry->gen;
69 }
70 if(perfcounter) perfcounter->inc(l_rgw_cache_hit);
71
72 return 0;
73}
74
75bool ObjectCache::chain_cache_entry(list<rgw_cache_entry_info *>& cache_info_entries, RGWChainedCache::Entry *chained_entry)
76{
77 RWLock::WLocker l(lock);
78
79 if (!enabled) {
80 return false;
81 }
82
83 list<rgw_cache_entry_info *>::iterator citer;
84
85 list<ObjectCacheEntry *> cache_entry_list;
86
87 /* first verify that all entries are still valid */
88 for (citer = cache_info_entries.begin(); citer != cache_info_entries.end(); ++citer) {
89 rgw_cache_entry_info *cache_info = *citer;
90
91 ldout(cct, 10) << "chain_cache_entry: cache_locator=" << cache_info->cache_locator << dendl;
92 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(cache_info->cache_locator);
93 if (iter == cache_map.end()) {
94 ldout(cct, 20) << "chain_cache_entry: couldn't find cache locator" << dendl;
95 return false;
96 }
97
98 ObjectCacheEntry *entry = &iter->second;
99
100 if (entry->gen != cache_info->gen) {
101 ldout(cct, 20) << "chain_cache_entry: entry.gen (" << entry->gen << ") != cache_info.gen (" << cache_info->gen << ")" << dendl;
102 return false;
103 }
104
105 cache_entry_list.push_back(entry);
106 }
107
108
109 chained_entry->cache->chain_cb(chained_entry->key, chained_entry->data);
110
111 list<ObjectCacheEntry *>::iterator liter;
112
113 for (liter = cache_entry_list.begin(); liter != cache_entry_list.end(); ++liter) {
114 ObjectCacheEntry *entry = *liter;
115
116 entry->chained_entries.push_back(make_pair(chained_entry->cache, chained_entry->key));
117 }
118
119 return true;
120}
121
3a9019d9 122void ObjectCache::put(const string& name, ObjectCacheInfo& info, rgw_cache_entry_info *cache_info)
7c673cae
FG
123{
124 RWLock::WLocker l(lock);
125
126 if (!enabled) {
127 return;
128 }
129
130 ldout(cct, 10) << "cache put: name=" << name << " info.flags=0x"
131 << std::hex << info.flags << std::dec << dendl;
132 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
133 if (iter == cache_map.end()) {
134 ObjectCacheEntry entry;
135 entry.lru_iter = lru.end();
136 cache_map.insert(pair<string, ObjectCacheEntry>(name, entry));
137 iter = cache_map.find(name);
138 }
139 ObjectCacheEntry& entry = iter->second;
140 ObjectCacheInfo& target = entry.info;
141
b32b8144 142 invalidate_lru(entry);
7c673cae
FG
143
144 entry.chained_entries.clear();
145 entry.gen++;
146
147 touch_lru(name, entry, entry.lru_iter);
148
149 target.status = info.status;
150
151 if (info.status < 0) {
152 target.flags = 0;
153 target.xattrs.clear();
154 target.data.clear();
155 return;
156 }
157
158 if (cache_info) {
159 cache_info->cache_locator = name;
160 cache_info->gen = entry.gen;
161 }
162
163 target.flags |= info.flags;
164
165 if (info.flags & CACHE_FLAG_META)
166 target.meta = info.meta;
167 else if (!(info.flags & CACHE_FLAG_MODIFY_XATTRS))
168 target.flags &= ~CACHE_FLAG_META; // non-meta change should reset meta
169
170 if (info.flags & CACHE_FLAG_XATTRS) {
171 target.xattrs = info.xattrs;
172 map<string, bufferlist>::iterator iter;
173 for (iter = target.xattrs.begin(); iter != target.xattrs.end(); ++iter) {
174 ldout(cct, 10) << "updating xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
175 }
176 } else if (info.flags & CACHE_FLAG_MODIFY_XATTRS) {
177 map<string, bufferlist>::iterator iter;
178 for (iter = info.rm_xattrs.begin(); iter != info.rm_xattrs.end(); ++iter) {
179 ldout(cct, 10) << "removing xattr: name=" << iter->first << dendl;
180 target.xattrs.erase(iter->first);
181 }
182 for (iter = info.xattrs.begin(); iter != info.xattrs.end(); ++iter) {
183 ldout(cct, 10) << "appending xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
184 target.xattrs[iter->first] = iter->second;
185 }
186 }
187
188 if (info.flags & CACHE_FLAG_DATA)
189 target.data = info.data;
190
191 if (info.flags & CACHE_FLAG_OBJV)
192 target.version = info.version;
193}
194
3a9019d9 195bool ObjectCache::remove(const string& name)
7c673cae
FG
196{
197 RWLock::WLocker l(lock);
198
199 if (!enabled) {
3a9019d9 200 return false;
7c673cae
FG
201 }
202
203 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
204 if (iter == cache_map.end())
3a9019d9 205 return false;
7c673cae
FG
206
207 ldout(cct, 10) << "removing " << name << " from cache" << dendl;
208 ObjectCacheEntry& entry = iter->second;
209
210 for (list<pair<RGWChainedCache *, string> >::iterator iiter = entry.chained_entries.begin();
211 iiter != entry.chained_entries.end(); ++iiter) {
212 RGWChainedCache *chained_cache = iiter->first;
213 chained_cache->invalidate(iiter->second);
214 }
215
216 remove_lru(name, iter->second.lru_iter);
217 cache_map.erase(iter);
3a9019d9 218 return true;
7c673cae
FG
219}
220
3a9019d9
FG
221void ObjectCache::touch_lru(const string& name, ObjectCacheEntry& entry,
222 std::list<string>::iterator& lru_iter)
7c673cae
FG
223{
224 while (lru_size > (size_t)cct->_conf->rgw_cache_lru_size) {
225 list<string>::iterator iter = lru.begin();
226 if ((*iter).compare(name) == 0) {
227 /*
228 * if the entry we're touching happens to be at the lru end, don't remove it,
229 * lru shrinking can wait for next time
230 */
231 break;
232 }
233 map<string, ObjectCacheEntry>::iterator map_iter = cache_map.find(*iter);
234 ldout(cct, 10) << "removing entry: name=" << *iter << " from cache LRU" << dendl;
b32b8144
FG
235 if (map_iter != cache_map.end()) {
236 ObjectCacheEntry& entry = map_iter->second;
237 invalidate_lru(entry);
7c673cae 238 cache_map.erase(map_iter);
b32b8144 239 }
7c673cae
FG
240 lru.pop_front();
241 lru_size--;
242 }
243
244 if (lru_iter == lru.end()) {
245 lru.push_back(name);
246 lru_size++;
247 lru_iter--;
248 ldout(cct, 10) << "adding " << name << " to cache LRU end" << dendl;
249 } else {
250 ldout(cct, 10) << "moving " << name << " to cache LRU end" << dendl;
251 lru.erase(lru_iter);
252 lru.push_back(name);
253 lru_iter = lru.end();
254 --lru_iter;
255 }
256
257 lru_counter++;
258 entry.lru_promotion_ts = lru_counter;
259}
260
3a9019d9
FG
261void ObjectCache::remove_lru(const string& name,
262 std::list<string>::iterator& lru_iter)
7c673cae
FG
263{
264 if (lru_iter == lru.end())
265 return;
266
267 lru.erase(lru_iter);
268 lru_size--;
269 lru_iter = lru.end();
270}
271
b32b8144
FG
272void ObjectCache::invalidate_lru(ObjectCacheEntry& entry)
273{
274 for (list<pair<RGWChainedCache *, string> >::iterator iter = entry.chained_entries.begin();
275 iter != entry.chained_entries.end(); ++iter) {
276 RGWChainedCache *chained_cache = iter->first;
277 chained_cache->invalidate(iter->second);
278 }
279}
280
7c673cae
FG
281void ObjectCache::set_enabled(bool status)
282{
283 RWLock::WLocker l(lock);
284
285 enabled = status;
286
287 if (!enabled) {
288 do_invalidate_all();
289 }
290}
291
292void ObjectCache::invalidate_all()
293{
294 RWLock::WLocker l(lock);
295
296 do_invalidate_all();
297}
298
299void ObjectCache::do_invalidate_all()
300{
301 cache_map.clear();
302 lru.clear();
303
304 lru_size = 0;
305 lru_counter = 0;
306 lru_window = 0;
307
308 for (list<RGWChainedCache *>::iterator iter = chained_cache.begin(); iter != chained_cache.end(); ++iter) {
309 (*iter)->invalidate_all();
310 }
311}
312
313void ObjectCache::chain_cache(RGWChainedCache *cache) {
314 RWLock::WLocker l(lock);
315 chained_cache.push_back(cache);
316}
317