int ObjectCache::get(string& name, ObjectCacheInfo& info, uint32_t mask)
{
- Mutex::Locker l(lock);
+ RWLock::RLocker l(lock);
map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
if (iter == cache_map.end()) {
return -ENOENT;
}
- touch_lru(name, iter->second.lru_iter);
+ ObjectCacheEntry& entry = iter->second;
+
+ if (lru_counter - entry.lru_promotion_ts > lru_window) {
+ ldout(cct, 20) << "cache get: touching lru, lru_counter=" << lru_counter << " promotion_ts=" << entry.lru_promotion_ts << dendl;
+ lock.unlock();
+ lock.get_write(); /* promote lock to writer */
+
+ /* check again, we might have lost a race here */
+ if (lru_counter - entry.lru_promotion_ts > lru_window) {
+ touch_lru(name, entry, iter->second.lru_iter);
+ }
+ }
ObjectCacheInfo& src = iter->second.info;
if ((src.flags & mask) != mask) {
void ObjectCache::put(string& name, ObjectCacheInfo& info)
{
- Mutex::Locker l(lock);
+ RWLock::WLocker l(lock);
ldout(cct, 10) << "cache put: name=" << name << dendl;
map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
ObjectCacheEntry& entry = iter->second;
ObjectCacheInfo& target = entry.info;
- touch_lru(name, entry.lru_iter);
+ touch_lru(name, entry, entry.lru_iter);
target.status = info.status;
void ObjectCache::remove(string& name)
{
- Mutex::Locker l(lock);
+ RWLock::WLocker l(lock);
map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
if (iter == cache_map.end())
cache_map.erase(iter);
}
-void ObjectCache::touch_lru(string& name, std::list<string>::iterator& lru_iter)
+void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter)
{
while (lru_size > (size_t)cct->_conf->rgw_cache_lru_size) {
list<string>::iterator iter = lru.begin();
lru_iter = lru.end();
--lru_iter;
}
+
+ lru_counter++;
+ entry.lru_promotion_ts = lru_counter;
}
void ObjectCache::remove_lru(string& name, std::list<string>::iterator& lru_iter)
#include "include/types.h"
#include "include/utime.h"
#include "include/assert.h"
+#include "common/RWLock.h"
enum {
UPDATE_OBJ,
struct ObjectCacheEntry {
ObjectCacheInfo info;
std::list<string>::iterator lru_iter;
+ uint64_t lru_promotion_ts;
+
+ ObjectCacheEntry() : lru_promotion_ts(0) {}
};
class ObjectCache {
std::map<string, ObjectCacheEntry> cache_map;
std::list<string> lru;
unsigned long lru_size;
- Mutex lock;
+ unsigned long lru_counter;
+ unsigned long lru_window;
+ RWLock lock;
CephContext *cct;
- void touch_lru(string& name, std::list<string>::iterator& lru_iter);
+ void touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter);
void remove_lru(string& name, std::list<string>::iterator& lru_iter);
public:
- ObjectCache() : lru_size(0), lock("ObjectCache"), cct(NULL) { }
+ ObjectCache() : lru_size(0), lru_counter(0), lru_window(0), lock("ObjectCache"), cct(NULL) { }
int get(std::string& name, ObjectCacheInfo& bl, uint32_t mask);
void put(std::string& name, ObjectCacheInfo& bl);
void remove(std::string& name);
- void set_ctx(CephContext *_cct) { cct = _cct; }
+ void set_ctx(CephContext *_cct) {
+ cct = _cct;
+ lru_window = cct->_conf->rgw_cache_lru_size / 2;
+ }
};
template <class T>