#include <string>
#include <mutex>
+#include <boost/circular_buffer.hpp>
#include "ShardedCache.h"
-
#include "common/autovector.h"
+#include "common/dout.h"
+#include "include/ceph_assert.h"
+#include "common/ceph_context.h"
namespace rocksdb_cache {
// RUCache::Release (to move into state 2) or BinnedLRUCacheShard::Erase (for state 3)
std::shared_ptr<rocksdb::Cache> NewBinnedLRUCache(
+ CephContext *c,
size_t capacity,
int num_shard_bits = -1,
bool strict_capacity_limit = false,
double high_pri_pool_ratio = 0.0);
struct BinnedLRUHandle {
+ std::shared_ptr<uint64_t> age_bin;
void* value;
- void (*deleter)(const rocksdb::Slice&, void* value);
+ DeleterFn deleter;
BinnedLRUHandle* next_hash;
BinnedLRUHandle* next;
BinnedLRUHandle* prev;
uint32_t hash; // Hash of key(); used for fast sharding and comparisons
- char key_data[1]; // Beginning of key
+ char* key_data = nullptr; // Beginning of key
rocksdb::Slice key() const {
// For cheaper lookups, we allow a temporary Handle object
void SetHit() { flags |= 8; }
void Free() {
- assert((refs == 1 && InCache()) || (refs == 0 && !InCache()));
+ ceph_assert((refs == 1 && InCache()) || (refs == 0 && !InCache()));
if (deleter) {
(*deleter)(key(), value);
}
- delete[] reinterpret_cast<char*>(this);
+ delete[] key_data;
+ delete this;
}
};
BinnedLRUHandle* h = list_[i];
while (h != nullptr) {
auto n = h->next_hash;
- assert(h->InCache());
+ ceph_assert(h->InCache());
func(h);
h = n;
}
// A single shard of sharded cache.
class alignas(CACHE_LINE_SIZE) BinnedLRUCacheShard : public CacheShard {
public:
- BinnedLRUCacheShard(size_t capacity, bool strict_capacity_limit,
+ BinnedLRUCacheShard(CephContext *c, size_t capacity, bool strict_capacity_limit,
double high_pri_pool_ratio);
virtual ~BinnedLRUCacheShard();
// Like Cache methods, but with an extra "hash" parameter.
virtual rocksdb::Status Insert(const rocksdb::Slice& key, uint32_t hash, void* value,
size_t charge,
- void (*deleter)(const rocksdb::Slice& key, void* value),
+ DeleterFn deleter,
rocksdb::Cache::Handle** handle,
rocksdb::Cache::Priority priority) override;
virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key, uint32_t hash) override;
virtual size_t GetUsage() const override;
virtual size_t GetPinnedUsage() const override;
- virtual void ApplyToAllCacheEntries(void (*callback)(void*, size_t),
- bool thread_safe) override;
+ virtual void ApplyToAllCacheEntries(
+ const std::function<void(const rocksdb::Slice& key,
+ void* value,
+ size_t charge,
+ DeleterFn)>& callback,
+ bool thread_safe) override;
virtual void EraseUnRefEntries() override;
virtual std::string GetPrintableOptions() const override;
+ virtual DeleterFn GetDeleter(rocksdb::Cache::Handle* handle) const override;
+
void TEST_GetLRUList(BinnedLRUHandle** lru, BinnedLRUHandle** lru_low_pri);
// Retrieves number of elements in LRU, for unit test purpose only
// not threadsafe
size_t TEST_GetLRUSize();
- // Retrives high pri pool ratio
+ // Retrieves high pri pool ratio
double GetHighPriPoolRatio() const;
- // Retrives high pri pool usage
+ // Retrieves high pri pool usage
size_t GetHighPriPoolUsage() const;
+ // Rotate the bins
+ void shift_bins();
+
+ // Get the bin count
+ uint32_t get_bin_count() const;
+
+ // Set the bin count
+ void set_bin_count(uint32_t count);
+
+ // Get the byte counts for a range of age bins
+ uint64_t sum_bins(uint32_t start, uint32_t end) const;
+
private:
+ CephContext *cct;
void LRU_Remove(BinnedLRUHandle* e);
void LRU_Insert(BinnedLRUHandle* e);
// We don't count mutex_ as the cache's internal state so semantically we
// don't mind mutex_ invoking the non-const actions.
mutable std::mutex mutex_;
+
+ // Circular buffer of byte counters for age binning
+ boost::circular_buffer<std::shared_ptr<uint64_t>> age_bins;
};
class BinnedLRUCache : public ShardedCache {
public:
- BinnedLRUCache(size_t capacity, int num_shard_bits, bool strict_capacity_limit,
- double high_pri_pool_ratio);
+ BinnedLRUCache(CephContext *c, size_t capacity, int num_shard_bits,
+ bool strict_capacity_limit, double high_pri_pool_ratio);
virtual ~BinnedLRUCache();
virtual const char* Name() const override { return "BinnedLRUCache"; }
virtual CacheShard* GetShard(int shard) override;
virtual size_t GetCharge(Handle* handle) const override;
virtual uint32_t GetHash(Handle* handle) const override;
virtual void DisownData() override;
-
+#if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
+ virtual DeleterFn GetDeleter(Handle* handle) const override;
+#endif
// Retrieves number of elements in LRU, for unit test purpose only
size_t TEST_GetLRUSize();
// Sets the high pri pool ratio
void SetHighPriPoolRatio(double high_pri_pool_ratio);
- // Retrives high pri pool ratio
+ // Retrieves high pri pool ratio
double GetHighPriPoolRatio() const;
// Retrieves high pri pool usage
size_t GetHighPriPoolUsage() const;
+ // PriorityCache
+ virtual int64_t request_cache_bytes(
+ PriorityCache::Priority pri, uint64_t total_cache) const;
+ virtual int64_t commit_cache_size(uint64_t total_cache);
+ virtual int64_t get_committed_size() const {
+ return GetCapacity();
+ }
+ virtual void shift_bins();
+ uint64_t sum_bins(uint32_t start, uint32_t end) const;
+ uint32_t get_bin_count() const;
+ void set_bin_count(uint32_t count);
+
+ virtual std::string get_cache_name() const {
+ return "RocksDB Binned LRU Cache";
+ }
+
private:
+ CephContext *cct;
BinnedLRUCacheShard* shards_;
int num_shards_ = 0;
};