1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 #include "include/buffer.h"
11 #include "include/memory.h"
12 #include <boost/scoped_ptr.hpp>
13 #include "include/encoding.h"
14 #include "common/Formatter.h"
15 #include "common/perf_counters.h"
16 #include "common/PriorityCache.h"
20 * Defines virtual interface to be implemented by key value store
22 * Kyoto Cabinet or LevelDB should implement this
24 class KeyValueDB
: public PriorityCache::PriCache
{
26 class TransactionImpl
{
30 const std::string
&prefix
, ///< [in] Prefix for keys
31 const std::map
<std::string
, bufferlist
> &to_set
///< [in] keys/values to set
33 std::map
<std::string
, bufferlist
>::const_iterator it
;
34 for (it
= to_set
.begin(); it
!= to_set
.end(); ++it
)
35 set(prefix
, it
->first
, it
->second
);
38 /// Set Keys (via encoded bufferlist)
40 const std::string
&prefix
, ///< [in] prefix
41 bufferlist
& to_set_bl
///< [in] encoded key/values to set
43 bufferlist::iterator p
= to_set_bl
.begin();
51 set(prefix
, key
, value
);
57 const std::string
&prefix
, ///< [in] Prefix for the key
58 const std::string
&k
, ///< [in] Key to set
59 const bufferlist
&bl
///< [in] Value to set
62 const std::string
&prefix
,
65 const bufferlist
& bl
) {
66 set(prefix
, string(k
, keylen
), bl
);
69 /// Removes Keys (via encoded bufferlist)
71 const std::string
&prefix
, ///< [in] Prefix to search for
72 bufferlist
&keys_bl
///< [in] Keys to remove
74 bufferlist::iterator p
= keys_bl
.begin();
86 const std::string
&prefix
, ///< [in] Prefix to search for
87 const std::set
<std::string
> &keys
///< [in] Keys to remove
89 std::set
<std::string
>::const_iterator it
;
90 for (it
= keys
.begin(); it
!= keys
.end(); ++it
)
96 const std::string
&prefix
, ///< [in] Prefix to search for
97 const std::string
&k
///< [in] Key to remove
100 const std::string
&prefix
, ///< [in] Prefix to search for
101 const char *k
, ///< [in] Key to remove
104 rmkey(prefix
, string(k
, keylen
));
107 /// Remove Single Key which exists and was not overwritten.
108 /// This API is only related to performance optimization, and should only be
109 /// re-implemented by log-insert-merge tree based keyvalue stores(such as RocksDB).
110 /// If a key is overwritten (by calling set multiple times), then the result
111 /// of calling rm_single_key on this key is undefined.
112 virtual void rm_single_key(
113 const std::string
&prefix
, ///< [in] Prefix to search for
114 const std::string
&k
///< [in] Key to remove
115 ) { return rmkey(prefix
, k
);}
117 /// Removes keys beginning with prefix
118 virtual void rmkeys_by_prefix(
119 const std::string
&prefix
///< [in] Prefix by which to remove keys
122 virtual void rm_range_keys(
123 const string
&prefix
, ///< [in] Prefix by which to remove keys
124 const string
&start
, ///< [in] The start bound of remove keys
125 const string
&end
///< [in] The start bound of remove keys
128 /// Merge value into key
130 const std::string
&prefix
, ///< [in] Prefix ==> MUST match some established merge operator
131 const std::string
&key
, ///< [in] Key to be merged
132 const bufferlist
&value
///< [in] value to be merged into key
133 ) { assert(0 == "Not implemented"); }
135 virtual ~TransactionImpl() {}
137 typedef ceph::shared_ptr
< TransactionImpl
> Transaction
;
139 /// create a new instance
140 static KeyValueDB
*create(CephContext
*cct
, const std::string
& type
,
141 const std::string
& dir
,
144 /// test whether we can successfully initialize; may have side effects (e.g., create)
145 static int test_init(const std::string
& type
, const std::string
& dir
);
146 virtual int init(string option_str
="") = 0;
147 virtual int open(std::ostream
&out
) = 0;
148 virtual int create_and_open(std::ostream
&out
) = 0;
149 virtual void close() { }
151 virtual Transaction
get_transaction() = 0;
152 virtual int submit_transaction(Transaction
) = 0;
153 virtual int submit_transaction_sync(Transaction t
) {
154 return submit_transaction(t
);
159 const std::string
&prefix
, ///< [in] Prefix for key
160 const std::set
<std::string
> &key
, ///< [in] Key to retrieve
161 std::map
<std::string
, bufferlist
> *out
///< [out] Key value retrieved
163 virtual int get(const std::string
&prefix
, ///< [in] prefix
164 const std::string
&key
, ///< [in] key
165 bufferlist
*value
) { ///< [out] value
166 std::set
<std::string
> ks
;
168 std::map
<std::string
,bufferlist
> om
;
169 int r
= get(prefix
, ks
, &om
);
170 if (om
.find(key
) != om
.end()) {
173 *value
= bufferlist();
178 virtual int get(const string
&prefix
,
179 const char *key
, size_t keylen
,
181 return get(prefix
, string(key
, keylen
), value
);
184 class GenericIteratorImpl
{
186 virtual int seek_to_first() = 0;
187 virtual int upper_bound(const std::string
&after
) = 0;
188 virtual int lower_bound(const std::string
&to
) = 0;
189 virtual bool valid() = 0;
190 virtual int next(bool validate
=true) = 0;
191 virtual std::string
key() = 0;
192 virtual bufferlist
value() = 0;
193 virtual int status() = 0;
194 virtual ~GenericIteratorImpl() {}
197 class WholeSpaceIteratorImpl
{
199 virtual int seek_to_first() = 0;
200 virtual int seek_to_first(const std::string
&prefix
) = 0;
201 virtual int seek_to_last() = 0;
202 virtual int seek_to_last(const std::string
&prefix
) = 0;
203 virtual int upper_bound(const std::string
&prefix
, const std::string
&after
) = 0;
204 virtual int lower_bound(const std::string
&prefix
, const std::string
&to
) = 0;
205 virtual bool valid() = 0;
206 virtual int next() = 0;
207 virtual int prev() = 0;
208 virtual std::string
key() = 0;
209 virtual std::pair
<std::string
,std::string
> raw_key() = 0;
210 virtual bool raw_key_is_prefixed(const std::string
&prefix
) = 0;
211 virtual bufferlist
value() = 0;
212 virtual bufferptr
value_as_ptr() {
213 bufferlist bl
= value();
215 return *bl
.buffers().begin();
220 virtual int status() = 0;
221 virtual size_t key_size() {
224 virtual size_t value_size() {
227 virtual ~WholeSpaceIteratorImpl() { }
229 typedef ceph::shared_ptr
< WholeSpaceIteratorImpl
> WholeSpaceIterator
;
231 class IteratorImpl
: public GenericIteratorImpl
{
232 const std::string prefix
;
233 WholeSpaceIterator generic_iter
;
235 IteratorImpl(const std::string
&prefix
, WholeSpaceIterator iter
) :
236 prefix(prefix
), generic_iter(iter
) { }
237 ~IteratorImpl() override
{ }
239 int seek_to_first() override
{
240 return generic_iter
->seek_to_first(prefix
);
243 return generic_iter
->seek_to_last(prefix
);
245 int upper_bound(const std::string
&after
) override
{
246 return generic_iter
->upper_bound(prefix
, after
);
248 int lower_bound(const std::string
&to
) override
{
249 return generic_iter
->lower_bound(prefix
, to
);
251 bool valid() override
{
252 if (!generic_iter
->valid())
254 return generic_iter
->raw_key_is_prefixed(prefix
);
256 // Note that next() and prev() shouldn't validate iters,
257 // it's responsibility of caller to ensure they're valid.
258 int next(bool validate
=true) override
{
261 return generic_iter
->next();
264 return generic_iter
->next();
268 int prev(bool validate
=true) {
271 return generic_iter
->prev();
274 return generic_iter
->prev();
277 std::string
key() override
{
278 return generic_iter
->key();
280 std::pair
<std::string
, std::string
> raw_key() {
281 return generic_iter
->raw_key();
283 bufferlist
value() override
{
284 return generic_iter
->value();
286 bufferptr
value_as_ptr() {
287 return generic_iter
->value_as_ptr();
289 int status() override
{
290 return generic_iter
->status();
294 typedef ceph::shared_ptr
< IteratorImpl
> Iterator
;
296 WholeSpaceIterator
get_iterator() {
297 return _get_iterator();
300 Iterator
get_iterator(const std::string
&prefix
) {
301 return std::make_shared
<IteratorImpl
>(prefix
, get_iterator());
304 virtual uint64_t get_estimated_size(std::map
<std::string
,uint64_t> &extra
) = 0;
305 virtual int get_statfs(struct store_statfs_t
*buf
) {
309 virtual int set_cache_size(uint64_t) {
315 int64_t cache_bytes
[PriorityCache::Priority::LAST
+1] = { 0 };
316 double cache_ratio
= 0;
319 virtual int64_t request_cache_bytes(PriorityCache::Priority pri
, uint64_t chunk_bytes
) const {
323 virtual int64_t get_cache_bytes(PriorityCache::Priority pri
) const {
324 return cache_bytes
[pri
];
327 virtual int64_t get_cache_bytes() const {
330 for (int i
= 0; i
< PriorityCache::Priority::LAST
+ 1; i
++) {
331 PriorityCache::Priority pri
= static_cast<PriorityCache::Priority
>(i
);
332 total
+= get_cache_bytes(pri
);
337 virtual void set_cache_bytes(PriorityCache::Priority pri
, int64_t bytes
) {
338 cache_bytes
[pri
] = bytes
;
341 virtual void add_cache_bytes(PriorityCache::Priority pri
, int64_t bytes
) {
342 cache_bytes
[pri
] += bytes
;
345 virtual int64_t commit_cache_size() {
349 virtual double get_cache_ratio() const {
353 virtual void set_cache_ratio(double ratio
) {
357 virtual string
get_cache_name() const {
358 return "Unknown KeyValueDB Cache";
363 virtual int set_cache_high_pri_pool_ratio(double ratio
) {
367 virtual int64_t get_cache_usage() const {
371 virtual ~KeyValueDB() {}
373 /// compact the underlying store
374 virtual void compact() {}
376 /// compact db for all keys with a given prefix
377 virtual void compact_prefix(const std::string
& prefix
) {}
378 /// compact db for all keys with a given prefix, async
379 virtual void compact_prefix_async(const std::string
& prefix
) {}
380 virtual void compact_range(const std::string
& prefix
,
381 const std::string
& start
, const std::string
& end
) {}
382 virtual void compact_range_async(const std::string
& prefix
,
383 const std::string
& start
, const std::string
& end
) {}
385 // See RocksDB merge operator definition, we support the basic
386 // associative merge only right now.
387 class MergeOperator
{
389 /// Merge into a key that doesn't exist
390 virtual void merge_nonexistent(
391 const char *rdata
, size_t rlen
,
392 std::string
*new_value
) = 0;
393 /// Merge into a key that does exist
395 const char *ldata
, size_t llen
,
396 const char *rdata
, size_t rlen
,
397 std::string
*new_value
) = 0;
398 /// We use each operator name and each prefix to construct the overall RocksDB operator name for consistency check at open time.
399 virtual const char *name() const = 0;
401 virtual ~MergeOperator() {}
404 /// Setup one or more operators, this needs to be done BEFORE the DB is opened.
405 virtual int set_merge_operator(const std::string
& prefix
,
406 std::shared_ptr
<MergeOperator
> mop
) {
410 virtual void get_statistics(Formatter
*f
) {
415 * Return your perf counters if you have any. Subclasses are not
416 * required to implement this, and callers must respect a null return
419 virtual PerfCounters
*get_perf_counters() {
423 /// List of matching prefixes and merge operators
424 std::vector
<std::pair
<std::string
,
425 std::shared_ptr
<MergeOperator
> > > merge_ops
;
427 virtual WholeSpaceIterator
_get_iterator() = 0;