]>
Commit | Line | Data |
---|---|---|
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 | ||
10 | using namespace std; | |
11 | ||
12 | int ObjectCache::get(string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cache_entry_info *cache_info) | |
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 | ||
75 | bool 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 | ||
122 | void ObjectCache::put(string& name, ObjectCacheInfo& info, rgw_cache_entry_info *cache_info) | |
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 | ||
195 | void ObjectCache::remove(string& name) | |
196 | { | |
197 | RWLock::WLocker l(lock); | |
198 | ||
199 | if (!enabled) { | |
200 | return; | |
201 | } | |
202 | ||
203 | map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name); | |
204 | if (iter == cache_map.end()) | |
205 | return; | |
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); | |
218 | } | |
219 | ||
220 | void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter) | |
221 | { | |
222 | while (lru_size > (size_t)cct->_conf->rgw_cache_lru_size) { | |
223 | list<string>::iterator iter = lru.begin(); | |
224 | if ((*iter).compare(name) == 0) { | |
225 | /* | |
226 | * if the entry we're touching happens to be at the lru end, don't remove it, | |
227 | * lru shrinking can wait for next time | |
228 | */ | |
229 | break; | |
230 | } | |
231 | map<string, ObjectCacheEntry>::iterator map_iter = cache_map.find(*iter); | |
232 | ldout(cct, 10) << "removing entry: name=" << *iter << " from cache LRU" << dendl; | |
b32b8144 FG |
233 | if (map_iter != cache_map.end()) { |
234 | ObjectCacheEntry& entry = map_iter->second; | |
235 | invalidate_lru(entry); | |
7c673cae | 236 | cache_map.erase(map_iter); |
b32b8144 | 237 | } |
7c673cae FG |
238 | lru.pop_front(); |
239 | lru_size--; | |
240 | } | |
241 | ||
242 | if (lru_iter == lru.end()) { | |
243 | lru.push_back(name); | |
244 | lru_size++; | |
245 | lru_iter--; | |
246 | ldout(cct, 10) << "adding " << name << " to cache LRU end" << dendl; | |
247 | } else { | |
248 | ldout(cct, 10) << "moving " << name << " to cache LRU end" << dendl; | |
249 | lru.erase(lru_iter); | |
250 | lru.push_back(name); | |
251 | lru_iter = lru.end(); | |
252 | --lru_iter; | |
253 | } | |
254 | ||
255 | lru_counter++; | |
256 | entry.lru_promotion_ts = lru_counter; | |
257 | } | |
258 | ||
259 | void ObjectCache::remove_lru(string& name, std::list<string>::iterator& lru_iter) | |
260 | { | |
261 | if (lru_iter == lru.end()) | |
262 | return; | |
263 | ||
264 | lru.erase(lru_iter); | |
265 | lru_size--; | |
266 | lru_iter = lru.end(); | |
267 | } | |
268 | ||
b32b8144 FG |
269 | void ObjectCache::invalidate_lru(ObjectCacheEntry& entry) |
270 | { | |
271 | for (list<pair<RGWChainedCache *, string> >::iterator iter = entry.chained_entries.begin(); | |
272 | iter != entry.chained_entries.end(); ++iter) { | |
273 | RGWChainedCache *chained_cache = iter->first; | |
274 | chained_cache->invalidate(iter->second); | |
275 | } | |
276 | } | |
277 | ||
7c673cae FG |
278 | void ObjectCache::set_enabled(bool status) |
279 | { | |
280 | RWLock::WLocker l(lock); | |
281 | ||
282 | enabled = status; | |
283 | ||
284 | if (!enabled) { | |
285 | do_invalidate_all(); | |
286 | } | |
287 | } | |
288 | ||
289 | void ObjectCache::invalidate_all() | |
290 | { | |
291 | RWLock::WLocker l(lock); | |
292 | ||
293 | do_invalidate_all(); | |
294 | } | |
295 | ||
296 | void ObjectCache::do_invalidate_all() | |
297 | { | |
298 | cache_map.clear(); | |
299 | lru.clear(); | |
300 | ||
301 | lru_size = 0; | |
302 | lru_counter = 0; | |
303 | lru_window = 0; | |
304 | ||
305 | for (list<RGWChainedCache *>::iterator iter = chained_cache.begin(); iter != chained_cache.end(); ++iter) { | |
306 | (*iter)->invalidate_all(); | |
307 | } | |
308 | } | |
309 | ||
310 | void ObjectCache::chain_cache(RGWChainedCache *cache) { | |
311 | RWLock::WLocker l(lock); | |
312 | chained_cache.push_back(cache); | |
313 | } | |
314 |