]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/utilities/persistent_cache/volatile_tier_impl.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / utilities / persistent_cache / volatile_tier_impl.cc
CommitLineData
7c673cae 1// Copyright (c) 2013, Facebook, Inc. All rights reserved.
11fdf7f2
TL
2// This source code is licensed under both the GPLv2 (found in the
3// COPYING file in the root directory) and Apache 2.0 License
4// (found in the LICENSE.Apache file in the root directory).
7c673cae
FG
5//
6#ifndef ROCKSDB_LITE
7
8#include "utilities/persistent_cache/volatile_tier_impl.h"
9
10#include <string>
11
f67539c2 12namespace ROCKSDB_NAMESPACE {
7c673cae
FG
13
14void VolatileCacheTier::DeleteCacheData(VolatileCacheTier::CacheData* data) {
15 assert(data);
16 delete data;
17}
18
19VolatileCacheTier::~VolatileCacheTier() { index_.Clear(&DeleteCacheData); }
20
21PersistentCache::StatsType VolatileCacheTier::Stats() {
22 std::map<std::string, double> stat;
23 stat.insert({"persistent_cache.volatile_cache.hits",
24 static_cast<double>(stats_.cache_hits_)});
25 stat.insert({"persistent_cache.volatile_cache.misses",
26 static_cast<double>(stats_.cache_misses_)});
27 stat.insert({"persistent_cache.volatile_cache.inserts",
28 static_cast<double>(stats_.cache_inserts_)});
29 stat.insert({"persistent_cache.volatile_cache.evicts",
30 static_cast<double>(stats_.cache_evicts_)});
31 stat.insert({"persistent_cache.volatile_cache.hit_pct",
32 static_cast<double>(stats_.CacheHitPct())});
33 stat.insert({"persistent_cache.volatile_cache.miss_pct",
34 static_cast<double>(stats_.CacheMissPct())});
35
36 auto out = PersistentCacheTier::Stats();
37 out.push_back(stat);
38 return out;
39}
40
41Status VolatileCacheTier::Insert(const Slice& page_key, const char* data,
42 const size_t size) {
43 // precondition
44 assert(data);
45 assert(size);
46
47 // increment the size
48 size_ += size;
49
50 // check if we have overshot the limit, if so evict some space
51 while (size_ > max_size_) {
52 if (!Evict()) {
53 // unable to evict data, we give up so we don't spike read
54 // latency
55 assert(size_ >= size);
56 size_ -= size;
57 return Status::TryAgain("Unable to evict any data");
58 }
59 }
60
61 assert(size_ >= size);
62
63 // insert order: LRU, followed by index
64 std::string key(page_key.data(), page_key.size());
65 std::string value(data, size);
66 std::unique_ptr<CacheData> cache_data(
67 new CacheData(std::move(key), std::move(value)));
68 bool ok = index_.Insert(cache_data.get());
69 if (!ok) {
70 // decrement the size that we incremented ahead of time
71 assert(size_ >= size);
72 size_ -= size;
73 // failed to insert to cache, block already in cache
74 return Status::TryAgain("key already exists in volatile cache");
75 }
76
77 cache_data.release();
78 stats_.cache_inserts_++;
79 return Status::OK();
80}
81
82Status VolatileCacheTier::Lookup(const Slice& page_key,
83 std::unique_ptr<char[]>* result,
84 size_t* size) {
85 CacheData key(std::move(page_key.ToString()));
86 CacheData* kv;
87 bool ok = index_.Find(&key, &kv);
88 if (ok) {
89 // set return data
90 result->reset(new char[kv->value.size()]);
91 memcpy(result->get(), kv->value.c_str(), kv->value.size());
92 *size = kv->value.size();
93 // drop the reference on cache data
94 kv->refs_--;
95 // update stats
96 stats_.cache_hits_++;
97 return Status::OK();
98 }
99
100 stats_.cache_misses_++;
101
102 if (next_tier()) {
103 return next_tier()->Lookup(page_key, result, size);
104 }
105
106 return Status::NotFound("key not found in volatile cache");
107}
108
11fdf7f2 109bool VolatileCacheTier::Erase(const Slice& /*key*/) {
7c673cae
FG
110 assert(!"not supported");
111 return true;
112}
113
114bool VolatileCacheTier::Evict() {
115 CacheData* edata = index_.Evict();
116 if (!edata) {
117 // not able to evict any object
118 return false;
119 }
120
121 stats_.cache_evicts_++;
122
123 // push the evicted object to the next level
124 if (next_tier()) {
20effc67
TL
125 // TODO: Should the insert error be ignored?
126 Status s = next_tier()->Insert(Slice(edata->key), edata->value.c_str(),
127 edata->value.size());
128 s.PermitUncheckedError();
7c673cae
FG
129 }
130
131 // adjust size and destroy data
132 size_ -= edata->value.size();
133 delete edata;
134
135 return true;
136}
137
f67539c2 138} // namespace ROCKSDB_NAMESPACE
7c673cae
FG
139
140#endif