Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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
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
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);
24     return -ENOENT;
25   }
26
27   ObjectCacheEntry *entry = &iter->second;
28
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;
32     lock.unlock();
33     lock.get_write(); /* promote lock to writer */
34
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);
40       return -ENOENT;
41     }
42
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);
47     }
48   }
49
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);
56     return -ENOENT;
57   }
58   ldout(cct, 10) << "cache get: name=" << name << " : hit (requested=0x"
59                  << std::hex << mask << ", cached=0x" << src.flags
60                  << std::dec << ")" << dendl;
61
62   info = src;
63   if (cache_info) {
64     cache_info->cache_locator = name;
65     cache_info->gen = entry->gen;
66   }
67   if(perfcounter) perfcounter->inc(l_rgw_cache_hit);
68
69   return 0;
70 }
71
72 bool ObjectCache::chain_cache_entry(list<rgw_cache_entry_info *>& cache_info_entries, RGWChainedCache::Entry *chained_entry)
73 {
74   RWLock::WLocker l(lock);
75
76   if (!enabled) {
77     return false;
78   }
79
80   list<rgw_cache_entry_info *>::iterator citer;
81
82   list<ObjectCacheEntry *> cache_entry_list;
83
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;
87
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;
92       return false;
93     }
94
95     ObjectCacheEntry *entry = &iter->second;
96
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;
99       return false;
100     }
101
102     cache_entry_list.push_back(entry);
103   }
104
105
106   chained_entry->cache->chain_cb(chained_entry->key, chained_entry->data);
107
108   list<ObjectCacheEntry *>::iterator liter;
109
110   for (liter = cache_entry_list.begin(); liter != cache_entry_list.end(); ++liter) {
111     ObjectCacheEntry *entry = *liter;
112
113     entry->chained_entries.push_back(make_pair(chained_entry->cache, chained_entry->key));
114   }
115
116   return true;
117 }
118
119 void ObjectCache::put(string& name, ObjectCacheInfo& info, rgw_cache_entry_info *cache_info)
120 {
121   RWLock::WLocker l(lock);
122
123   if (!enabled) {
124     return;
125   }
126
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);
135   }
136   ObjectCacheEntry& entry = iter->second;
137   ObjectCacheInfo& target = entry.info;
138
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);
143   }
144
145   entry.chained_entries.clear();
146   entry.gen++;
147
148   touch_lru(name, entry, entry.lru_iter);
149
150   target.status = info.status;
151
152   if (info.status < 0) {
153     target.flags = 0;
154     target.xattrs.clear();
155     target.data.clear();
156     return;
157   }
158
159   if (cache_info) {
160     cache_info->cache_locator = name;
161     cache_info->gen = entry.gen;
162   }
163
164   target.flags |= info.flags;
165
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
170
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;
176     }
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);
182     }
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;
186     }
187   }
188
189   if (info.flags & CACHE_FLAG_DATA)
190     target.data = info.data;
191
192   if (info.flags & CACHE_FLAG_OBJV)
193     target.version = info.version;
194 }
195
196 void ObjectCache::remove(string& name)
197 {
198   RWLock::WLocker l(lock);
199
200   if (!enabled) {
201     return;
202   }
203
204   map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
205   if (iter == cache_map.end())
206     return;
207
208   ldout(cct, 10) << "removing " << name << " from cache" << dendl;
209   ObjectCacheEntry& entry = iter->second;
210
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);
215   }
216
217   remove_lru(name, iter->second.lru_iter);
218   cache_map.erase(iter);
219 }
220
221 void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter)
222 {
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) {
226       /*
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
229        */
230       break;
231     }
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);
236     lru.pop_front();
237     lru_size--;
238   }
239
240   if (lru_iter == lru.end()) {
241     lru.push_back(name);
242     lru_size++;
243     lru_iter--;
244     ldout(cct, 10) << "adding " << name << " to cache LRU end" << dendl;
245   } else {
246     ldout(cct, 10) << "moving " << name << " to cache LRU end" << dendl;
247     lru.erase(lru_iter);
248     lru.push_back(name);
249     lru_iter = lru.end();
250     --lru_iter;
251   }
252
253   lru_counter++;
254   entry.lru_promotion_ts = lru_counter;
255 }
256
257 void ObjectCache::remove_lru(string& name, std::list<string>::iterator& lru_iter)
258 {
259   if (lru_iter == lru.end())
260     return;
261
262   lru.erase(lru_iter);
263   lru_size--;
264   lru_iter = lru.end();
265 }
266
267 void ObjectCache::set_enabled(bool status)
268 {
269   RWLock::WLocker l(lock);
270
271   enabled = status;
272
273   if (!enabled) {
274     do_invalidate_all();
275   }
276 }
277
278 void ObjectCache::invalidate_all()
279 {
280   RWLock::WLocker l(lock);
281
282   do_invalidate_all();
283 }
284
285 void ObjectCache::do_invalidate_all()
286 {
287   cache_map.clear();
288   lru.clear();
289
290   lru_size = 0;
291   lru_counter = 0;
292   lru_window = 0;
293
294   for (list<RGWChainedCache *>::iterator iter = chained_cache.begin(); iter != chained_cache.end(); ++iter) {
295     (*iter)->invalidate_all();
296   }
297 }
298
299 void ObjectCache::chain_cache(RGWChainedCache *cache) {
300   RWLock::WLocker l(lock);
301   chained_cache.push_back(cache);
302 }
303