1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
8 #define dout_subsys ceph_subsys_rgw
12 int ObjectCache::get(string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cache_entry_info *cache_info)
14 RWLock::RLocker l(lock);
20 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
21 if (iter == cache_map.end()) {
22 ldout(cct, 10) << "cache get: name=" << name << " : miss" << dendl;
23 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
27 ObjectCacheEntry *entry = &iter->second;
29 if (lru_counter - entry->lru_promotion_ts > lru_window) {
30 ldout(cct, 20) << "cache get: touching lru, lru_counter=" << lru_counter
31 << " promotion_ts=" << entry->lru_promotion_ts << dendl;
33 lock.get_write(); /* promote lock to writer */
35 /* need to redo this because entry might have dropped off the cache */
36 iter = cache_map.find(name);
37 if (iter == cache_map.end()) {
38 ldout(cct, 10) << "lost race! cache get: name=" << name << " : miss" << dendl;
39 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
43 entry = &iter->second;
44 /* check again, we might have lost a race here */
45 if (lru_counter - entry->lru_promotion_ts > lru_window) {
46 touch_lru(name, *entry, iter->second.lru_iter);
50 ObjectCacheInfo& src = iter->second.info;
51 if ((src.flags & mask) != mask) {
52 ldout(cct, 10) << "cache get: name=" << name << " : type miss (requested=0x"
53 << std::hex << mask << ", cached=0x" << src.flags
54 << std::dec << ")" << dendl;
55 if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
58 ldout(cct, 10) << "cache get: name=" << name << " : hit (requested=0x"
59 << std::hex << mask << ", cached=0x" << src.flags
60 << std::dec << ")" << dendl;
64 cache_info->cache_locator = name;
65 cache_info->gen = entry->gen;
67 if(perfcounter) perfcounter->inc(l_rgw_cache_hit);
72 bool ObjectCache::chain_cache_entry(list<rgw_cache_entry_info *>& cache_info_entries, RGWChainedCache::Entry *chained_entry)
74 RWLock::WLocker l(lock);
80 list<rgw_cache_entry_info *>::iterator citer;
82 list<ObjectCacheEntry *> cache_entry_list;
84 /* first verify that all entries are still valid */
85 for (citer = cache_info_entries.begin(); citer != cache_info_entries.end(); ++citer) {
86 rgw_cache_entry_info *cache_info = *citer;
88 ldout(cct, 10) << "chain_cache_entry: cache_locator=" << cache_info->cache_locator << dendl;
89 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(cache_info->cache_locator);
90 if (iter == cache_map.end()) {
91 ldout(cct, 20) << "chain_cache_entry: couldn't find cache locator" << dendl;
95 ObjectCacheEntry *entry = &iter->second;
97 if (entry->gen != cache_info->gen) {
98 ldout(cct, 20) << "chain_cache_entry: entry.gen (" << entry->gen << ") != cache_info.gen (" << cache_info->gen << ")" << dendl;
102 cache_entry_list.push_back(entry);
106 chained_entry->cache->chain_cb(chained_entry->key, chained_entry->data);
108 list<ObjectCacheEntry *>::iterator liter;
110 for (liter = cache_entry_list.begin(); liter != cache_entry_list.end(); ++liter) {
111 ObjectCacheEntry *entry = *liter;
113 entry->chained_entries.push_back(make_pair(chained_entry->cache, chained_entry->key));
119 void ObjectCache::put(string& name, ObjectCacheInfo& info, rgw_cache_entry_info *cache_info)
121 RWLock::WLocker l(lock);
127 ldout(cct, 10) << "cache put: name=" << name << " info.flags=0x"
128 << std::hex << info.flags << std::dec << dendl;
129 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
130 if (iter == cache_map.end()) {
131 ObjectCacheEntry entry;
132 entry.lru_iter = lru.end();
133 cache_map.insert(pair<string, ObjectCacheEntry>(name, entry));
134 iter = cache_map.find(name);
136 ObjectCacheEntry& entry = iter->second;
137 ObjectCacheInfo& target = entry.info;
139 for (list<pair<RGWChainedCache *, string> >::iterator iiter = entry.chained_entries.begin();
140 iiter != entry.chained_entries.end(); ++iiter) {
141 RGWChainedCache *chained_cache = iiter->first;
142 chained_cache->invalidate(iiter->second);
145 entry.chained_entries.clear();
148 touch_lru(name, entry, entry.lru_iter);
150 target.status = info.status;
152 if (info.status < 0) {
154 target.xattrs.clear();
160 cache_info->cache_locator = name;
161 cache_info->gen = entry.gen;
164 target.flags |= info.flags;
166 if (info.flags & CACHE_FLAG_META)
167 target.meta = info.meta;
168 else if (!(info.flags & CACHE_FLAG_MODIFY_XATTRS))
169 target.flags &= ~CACHE_FLAG_META; // non-meta change should reset meta
171 if (info.flags & CACHE_FLAG_XATTRS) {
172 target.xattrs = info.xattrs;
173 map<string, bufferlist>::iterator iter;
174 for (iter = target.xattrs.begin(); iter != target.xattrs.end(); ++iter) {
175 ldout(cct, 10) << "updating xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
177 } else if (info.flags & CACHE_FLAG_MODIFY_XATTRS) {
178 map<string, bufferlist>::iterator iter;
179 for (iter = info.rm_xattrs.begin(); iter != info.rm_xattrs.end(); ++iter) {
180 ldout(cct, 10) << "removing xattr: name=" << iter->first << dendl;
181 target.xattrs.erase(iter->first);
183 for (iter = info.xattrs.begin(); iter != info.xattrs.end(); ++iter) {
184 ldout(cct, 10) << "appending xattr: name=" << iter->first << " bl.length()=" << iter->second.length() << dendl;
185 target.xattrs[iter->first] = iter->second;
189 if (info.flags & CACHE_FLAG_DATA)
190 target.data = info.data;
192 if (info.flags & CACHE_FLAG_OBJV)
193 target.version = info.version;
196 void ObjectCache::remove(string& name)
198 RWLock::WLocker l(lock);
204 map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
205 if (iter == cache_map.end())
208 ldout(cct, 10) << "removing " << name << " from cache" << dendl;
209 ObjectCacheEntry& entry = iter->second;
211 for (list<pair<RGWChainedCache *, string> >::iterator iiter = entry.chained_entries.begin();
212 iiter != entry.chained_entries.end(); ++iiter) {
213 RGWChainedCache *chained_cache = iiter->first;
214 chained_cache->invalidate(iiter->second);
217 remove_lru(name, iter->second.lru_iter);
218 cache_map.erase(iter);
221 void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter)
223 while (lru_size > (size_t)cct->_conf->rgw_cache_lru_size) {
224 list<string>::iterator iter = lru.begin();
225 if ((*iter).compare(name) == 0) {
227 * if the entry we're touching happens to be at the lru end, don't remove it,
228 * lru shrinking can wait for next time
232 map<string, ObjectCacheEntry>::iterator map_iter = cache_map.find(*iter);
233 ldout(cct, 10) << "removing entry: name=" << *iter << " from cache LRU" << dendl;
234 if (map_iter != cache_map.end())
235 cache_map.erase(map_iter);
240 if (lru_iter == lru.end()) {
244 ldout(cct, 10) << "adding " << name << " to cache LRU end" << dendl;
246 ldout(cct, 10) << "moving " << name << " to cache LRU end" << dendl;
249 lru_iter = lru.end();
254 entry.lru_promotion_ts = lru_counter;
257 void ObjectCache::remove_lru(string& name, std::list<string>::iterator& lru_iter)
259 if (lru_iter == lru.end())
264 lru_iter = lru.end();
267 void ObjectCache::set_enabled(bool status)
269 RWLock::WLocker l(lock);
278 void ObjectCache::invalidate_all()
280 RWLock::WLocker l(lock);
285 void ObjectCache::do_invalidate_all()
294 for (list<RGWChainedCache *>::iterator iter = chained_cache.begin(); iter != chained_cache.end(); ++iter) {
295 (*iter)->invalidate_all();
299 void ObjectCache::chain_cache(RGWChainedCache *cache) {
300 RWLock::WLocker l(lock);
301 chained_cache.push_back(cache);