Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache on the barrelhead #19581

Merged
merged 6 commits into from
Jan 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/common/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5617,14 +5617,14 @@ std::vector<Option> get_rgw_options() {
.set_default(10_min)
.set_description(""),

Option("rgw_bucket_info_cache_expiry_interval", Option::TYPE_UINT,
Option("rgw_cache_expiry_interval", Option::TYPE_UINT,
Option::LEVEL_ADVANCED)
.set_default(15_min)
.set_description("Number of seconds before entries in the bucket info "
"cache are assumed stale and re-fetched. Zero is never.")
.set_description("Number of seconds before entries in the cache are "
"assumed stale and re-fetched. Zero is never.")
.add_tag("performance")
.add_service("rgw")
.set_long_description("The Rados Gateway stores metadata about buckets in "
.set_long_description("The Rados Gateway stores metadata and objects in "
"an internal cache. This should be kept consistent "
"by the OSD's relaying notify events between "
"multiple watching RGW processes. In the event "
Expand Down
73 changes: 35 additions & 38 deletions src/rgw/rgw_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ int ObjectCache::get(string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cac
return -ENOENT;
}

map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
if (iter == cache_map.end()) {
auto iter = cache_map.find(name);
if (iter == cache_map.end() ||
(expiry.count() &&
(ceph::coarse_mono_clock::now() - iter->second.info.time_added) > expiry)) {
ldout(cct, 10) << "cache get: name=" << name << " : miss" << dendl;
if(perfcounter) perfcounter->inc(l_rgw_cache_miss);
if (perfcounter)
perfcounter->inc(l_rgw_cache_miss);
return -ENOENT;
}

Expand Down Expand Up @@ -68,48 +71,44 @@ int ObjectCache::get(string& name, ObjectCacheInfo& info, uint32_t mask, rgw_cac
return 0;
}

bool ObjectCache::chain_cache_entry(list<rgw_cache_entry_info *>& cache_info_entries, RGWChainedCache::Entry *chained_entry)
bool ObjectCache::chain_cache_entry(std::initializer_list<rgw_cache_entry_info*> cache_info_entries,
RGWChainedCache::Entry *chained_entry)
{
RWLock::WLocker l(lock);

if (!enabled) {
return false;
}

list<rgw_cache_entry_info *>::iterator citer;

list<ObjectCacheEntry *> cache_entry_list;

std::vector<ObjectCacheEntry*> entries;
entries.reserve(cache_info_entries.size());
/* first verify that all entries are still valid */
for (citer = cache_info_entries.begin(); citer != cache_info_entries.end(); ++citer) {
rgw_cache_entry_info *cache_info = *citer;

ldout(cct, 10) << "chain_cache_entry: cache_locator=" << cache_info->cache_locator << dendl;
map<string, ObjectCacheEntry>::iterator iter = cache_map.find(cache_info->cache_locator);
for (auto cache_info : cache_info_entries) {
ldout(cct, 10) << "chain_cache_entry: cache_locator="
<< cache_info->cache_locator << dendl;
auto iter = cache_map.find(cache_info->cache_locator);
if (iter == cache_map.end()) {
ldout(cct, 20) << "chain_cache_entry: couldn't find cache locator" << dendl;
return false;
}

ObjectCacheEntry *entry = &iter->second;
auto entry = &iter->second;

if (entry->gen != cache_info->gen) {
ldout(cct, 20) << "chain_cache_entry: entry.gen (" << entry->gen << ") != cache_info.gen (" << cache_info->gen << ")" << dendl;
ldout(cct, 20) << "chain_cache_entry: entry.gen (" << entry->gen
<< ") != cache_info.gen (" << cache_info->gen << ")"
<< dendl;
return false;
}

cache_entry_list.push_back(entry);
entries.push_back(entry);
}


chained_entry->cache->chain_cb(chained_entry->key, chained_entry->data);

list<ObjectCacheEntry *>::iterator liter;

for (liter = cache_entry_list.begin(); liter != cache_entry_list.end(); ++liter) {
ObjectCacheEntry *entry = *liter;

entry->chained_entries.push_back(make_pair(chained_entry->cache, chained_entry->key));
for (auto entry : entries) {
entry->chained_entries.push_back(make_pair(chained_entry->cache,
chained_entry->key));
}

return true;
Expand All @@ -125,7 +124,7 @@ void ObjectCache::put(string& name, ObjectCacheInfo& info, rgw_cache_entry_info

ldout(cct, 10) << "cache put: name=" << name << " info.flags=0x"
<< std::hex << info.flags << std::dec << dendl;
map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
auto iter = cache_map.find(name);
if (iter == cache_map.end()) {
ObjectCacheEntry entry;
entry.lru_iter = lru.end();
Expand All @@ -135,8 +134,6 @@ void ObjectCache::put(string& name, ObjectCacheInfo& info, rgw_cache_entry_info
ObjectCacheEntry& entry = iter->second;
ObjectCacheInfo& target = entry.info;

invalidate_lru(entry);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separately, it looks like the removal of this call is causing some failures in s3tests - added back in #19768

entry.chained_entries.clear();
entry.gen++;

Expand Down Expand Up @@ -196,35 +193,34 @@ void ObjectCache::remove(string& name)
return;
}

map<string, ObjectCacheEntry>::iterator iter = cache_map.find(name);
auto iter = cache_map.find(name);
if (iter == cache_map.end())
return;

ldout(cct, 10) << "removing " << name << " from cache" << dendl;
ObjectCacheEntry& entry = iter->second;

for (list<pair<RGWChainedCache *, string> >::iterator iiter = entry.chained_entries.begin();
iiter != entry.chained_entries.end(); ++iiter) {
RGWChainedCache *chained_cache = iiter->first;
chained_cache->invalidate(iiter->second);
for (auto& kv : entry.chained_entries) {
kv.first->invalidate(kv.second);
}

remove_lru(name, iter->second.lru_iter);
cache_map.erase(iter);
}

void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter)
void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry,
std::deque<string>::iterator& lru_iter)
{
while (lru_size > (size_t)cct->_conf->rgw_cache_lru_size) {
list<string>::iterator iter = lru.begin();
auto iter = lru.begin();
if ((*iter).compare(name) == 0) {
/*
* if the entry we're touching happens to be at the lru end, don't remove it,
* lru shrinking can wait for next time
*/
break;
}
map<string, ObjectCacheEntry>::iterator map_iter = cache_map.find(*iter);
auto map_iter = cache_map.find(*iter);
ldout(cct, 10) << "removing entry: name=" << *iter << " from cache LRU" << dendl;
if (map_iter != cache_map.end()) {
ObjectCacheEntry& entry = map_iter->second;
Expand Down Expand Up @@ -252,7 +248,8 @@ void ObjectCache::touch_lru(string& name, ObjectCacheEntry& entry, std::list<str
entry.lru_promotion_ts = lru_counter;
}

void ObjectCache::remove_lru(string& name, std::list<string>::iterator& lru_iter)
void ObjectCache::remove_lru(string& name,
std::deque<string>::iterator& lru_iter)
{
if (lru_iter == lru.end())
return;
Expand All @@ -264,7 +261,7 @@ void ObjectCache::remove_lru(string& name, std::list<string>::iterator& lru_iter

void ObjectCache::invalidate_lru(ObjectCacheEntry& entry)
{
for (list<pair<RGWChainedCache *, string> >::iterator iter = entry.chained_entries.begin();
for (auto iter = entry.chained_entries.begin();
iter != entry.chained_entries.end(); ++iter) {
RGWChainedCache *chained_cache = iter->first;
chained_cache->invalidate(iter->second);
Expand Down Expand Up @@ -298,8 +295,8 @@ void ObjectCache::do_invalidate_all()
lru_counter = 0;
lru_window = 0;

for (list<RGWChainedCache *>::iterator iter = chained_cache.begin(); iter != chained_cache.end(); ++iter) {
(*iter)->invalidate_all();
for (auto& cache : chained_cache) {
cache->invalidate_all();
}
}

Expand Down
46 changes: 28 additions & 18 deletions src/rgw/rgw_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "rgw_rados.h"
#include <string>
#include <map>
#include <unordered_map>
#include "include/types.h"
#include "include/utime.h"
#include "include/assert.h"
Expand Down Expand Up @@ -49,16 +50,17 @@ struct ObjectMetaInfo {
WRITE_CLASS_ENCODER(ObjectMetaInfo)

struct ObjectCacheInfo {
int status;
uint32_t flags;
uint64_t epoch;
int status = 0;
uint32_t flags = 0;
uint64_t epoch = 0;
bufferlist data;
map<string, bufferlist> xattrs;
map<string, bufferlist> rm_xattrs;
ObjectMetaInfo meta;
obj_version version;
obj_version version = {};
ceph::coarse_mono_time time_added = ceph::coarse_mono_clock::now();

ObjectCacheInfo() : status(0), flags(0), epoch(0), version() {}
ObjectCacheInfo() = default;

void encode(bufferlist& bl) const {
ENCODE_START(5, 3, bl);
Expand Down Expand Up @@ -126,29 +128,31 @@ WRITE_CLASS_ENCODER(RGWCacheNotifyInfo)

struct ObjectCacheEntry {
ObjectCacheInfo info;
std::list<string>::iterator lru_iter;
std::deque<string>::iterator lru_iter;
uint64_t lru_promotion_ts;
uint64_t gen;
std::list<pair<RGWChainedCache *, string> > chained_entries;
std::vector<pair<RGWChainedCache *, string> > chained_entries;

ObjectCacheEntry() : lru_promotion_ts(0), gen(0) {}
};

class ObjectCache {
std::map<string, ObjectCacheEntry> cache_map;
std::list<string> lru;
std::unordered_map<string, ObjectCacheEntry> cache_map;
std::deque<string> lru;
unsigned long lru_size;
unsigned long lru_counter;
unsigned long lru_window;
RWLock lock;
CephContext *cct;

list<RGWChainedCache *> chained_cache;
vector<RGWChainedCache *> chained_cache;

bool enabled;
ceph::timespan expiry;

void touch_lru(string& name, ObjectCacheEntry& entry, std::list<string>::iterator& lru_iter);
void remove_lru(string& name, std::list<string>::iterator& lru_iter);
void touch_lru(string& name, ObjectCacheEntry& entry,
std::deque<string>::iterator& lru_iter);
void remove_lru(string& name, std::deque<string>::iterator& lru_iter);
void invalidate_lru(ObjectCacheEntry& entry);

void do_invalidate_all();
Expand All @@ -160,8 +164,11 @@ class ObjectCache {
void set_ctx(CephContext *_cct) {
cct = _cct;
lru_window = cct->_conf->rgw_cache_lru_size / 2;
expiry = std::chrono::seconds(cct->_conf->get_val<uint64_t>(
"rgw_cache_expiry_interval"));
}
bool chain_cache_entry(list<rgw_cache_entry_info *>& cache_info_entries, RGWChainedCache::Entry *chained_entry);
bool chain_cache_entry(std::initializer_list<rgw_cache_entry_info*> cache_info_entries,
RGWChainedCache::Entry *chained_entry);

void set_enabled(bool status);

Expand Down Expand Up @@ -236,14 +243,15 @@ class RGWCache : public T
RGWObjVersionTracker *objv_tracker, rgw_raw_obj& obj,
bufferlist& bl, off_t ofs, off_t end,
map<string, bufferlist> *attrs,
rgw_cache_entry_info *cache_info) override;
rgw_cache_entry_info *cache_info,
boost::optional<obj_version> refresh_version = boost::none) override;

int raw_obj_stat(rgw_raw_obj& obj, uint64_t *psize, real_time *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs,
bufferlist *first_chunk, RGWObjVersionTracker *objv_tracker) override;

int delete_system_obj(rgw_raw_obj& obj, RGWObjVersionTracker *objv_tracker) override;

bool chain_cache_entry(list<rgw_cache_entry_info *>& cache_info_entries, RGWChainedCache::Entry *chained_entry) override {
bool chain_cache_entry(std::initializer_list<rgw_cache_entry_info *> cache_info_entries, RGWChainedCache::Entry *chained_entry) override {
return cache.chain_cache_entry(cache_info_entries, chained_entry);
}
};
Expand Down Expand Up @@ -281,7 +289,8 @@ int RGWCache<T>::get_system_obj(RGWObjectCtx& obj_ctx, RGWRados::SystemObject::R
RGWObjVersionTracker *objv_tracker, rgw_raw_obj& obj,
bufferlist& obl, off_t ofs, off_t end,
map<string, bufferlist> *attrs,
rgw_cache_entry_info *cache_info)
rgw_cache_entry_info *cache_info,
boost::optional<obj_version> refresh_version)
{
rgw_pool pool;
string oid;
Expand All @@ -298,8 +307,9 @@ int RGWCache<T>::get_system_obj(RGWObjectCtx& obj_ctx, RGWRados::SystemObject::R
flags |= CACHE_FLAG_OBJV;
if (attrs)
flags |= CACHE_FLAG_XATTRS;

if (cache.get(name, info, flags, cache_info) == 0) {

if ((cache.get(name, info, flags, cache_info) == 0) &&
(!refresh_version || !info.version.compare(&(*refresh_version)))) {
if (info.status < 0)
return info.status;

Expand Down