]> git.proxmox.com Git - ceph.git/blob - ceph/src/kv/KeyValueDB.h
update sources to 12.2.10
[ceph.git] / ceph / src / kv / KeyValueDB.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #ifndef KEY_VALUE_DB_H
4 #define KEY_VALUE_DB_H
5
6 #include "include/buffer.h"
7 #include <ostream>
8 #include <set>
9 #include <map>
10 #include <string>
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"
17
18 using std::string;
19 /**
20 * Defines virtual interface to be implemented by key value store
21 *
22 * Kyoto Cabinet or LevelDB should implement this
23 */
24 class KeyValueDB : public PriorityCache::PriCache {
25 public:
26 class TransactionImpl {
27 public:
28 /// Set Keys
29 void set(
30 const std::string &prefix, ///< [in] Prefix for keys
31 const std::map<std::string, bufferlist> &to_set ///< [in] keys/values to set
32 ) {
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);
36 }
37
38 /// Set Keys (via encoded bufferlist)
39 void set(
40 const std::string &prefix, ///< [in] prefix
41 bufferlist& to_set_bl ///< [in] encoded key/values to set
42 ) {
43 bufferlist::iterator p = to_set_bl.begin();
44 uint32_t num;
45 ::decode(num, p);
46 while (num--) {
47 string key;
48 bufferlist value;
49 ::decode(key, p);
50 ::decode(value, p);
51 set(prefix, key, value);
52 }
53 }
54
55 /// Set Key
56 virtual void set(
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
60 ) = 0;
61 virtual void set(
62 const std::string &prefix,
63 const char *k,
64 size_t keylen,
65 const bufferlist& bl) {
66 set(prefix, string(k, keylen), bl);
67 }
68
69 /// Removes Keys (via encoded bufferlist)
70 void rmkeys(
71 const std::string &prefix, ///< [in] Prefix to search for
72 bufferlist &keys_bl ///< [in] Keys to remove
73 ) {
74 bufferlist::iterator p = keys_bl.begin();
75 uint32_t num;
76 ::decode(num, p);
77 while (num--) {
78 string key;
79 ::decode(key, p);
80 rmkey(prefix, key);
81 }
82 }
83
84 /// Removes Keys
85 void rmkeys(
86 const std::string &prefix, ///< [in] Prefix to search for
87 const std::set<std::string> &keys ///< [in] Keys to remove
88 ) {
89 std::set<std::string>::const_iterator it;
90 for (it = keys.begin(); it != keys.end(); ++it)
91 rmkey(prefix, *it);
92 }
93
94 /// Remove Key
95 virtual void rmkey(
96 const std::string &prefix, ///< [in] Prefix to search for
97 const std::string &k ///< [in] Key to remove
98 ) = 0;
99 virtual void rmkey(
100 const std::string &prefix, ///< [in] Prefix to search for
101 const char *k, ///< [in] Key to remove
102 size_t keylen
103 ) {
104 rmkey(prefix, string(k, keylen));
105 }
106
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);}
116
117 /// Removes keys beginning with prefix
118 virtual void rmkeys_by_prefix(
119 const std::string &prefix ///< [in] Prefix by which to remove keys
120 ) = 0;
121
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
126 ) = 0;
127
128 /// Merge value into key
129 virtual void merge(
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"); }
134
135 virtual ~TransactionImpl() {}
136 };
137 typedef ceph::shared_ptr< TransactionImpl > Transaction;
138
139 /// create a new instance
140 static KeyValueDB *create(CephContext *cct, const std::string& type,
141 const std::string& dir,
142 void *p = NULL);
143
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() { }
150
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);
155 }
156
157 /// Retrieve Keys
158 virtual int get(
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
162 ) = 0;
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;
167 ks.insert(key);
168 std::map<std::string,bufferlist> om;
169 int r = get(prefix, ks, &om);
170 if (om.find(key) != om.end()) {
171 *value = om[key];
172 } else {
173 *value = bufferlist();
174 r = -ENOENT;
175 }
176 return r;
177 }
178 virtual int get(const string &prefix,
179 const char *key, size_t keylen,
180 bufferlist *value) {
181 return get(prefix, string(key, keylen), value);
182 }
183
184 class GenericIteratorImpl {
185 public:
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() {}
195 };
196
197 class WholeSpaceIteratorImpl {
198 public:
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();
214 if (bl.length()) {
215 return *bl.buffers().begin();
216 } else {
217 return bufferptr();
218 }
219 }
220 virtual int status() = 0;
221 virtual size_t key_size() {
222 return 0;
223 }
224 virtual size_t value_size() {
225 return 0;
226 }
227 virtual ~WholeSpaceIteratorImpl() { }
228 };
229 typedef ceph::shared_ptr< WholeSpaceIteratorImpl > WholeSpaceIterator;
230
231 class IteratorImpl : public GenericIteratorImpl {
232 const std::string prefix;
233 WholeSpaceIterator generic_iter;
234 public:
235 IteratorImpl(const std::string &prefix, WholeSpaceIterator iter) :
236 prefix(prefix), generic_iter(iter) { }
237 ~IteratorImpl() override { }
238
239 int seek_to_first() override {
240 return generic_iter->seek_to_first(prefix);
241 }
242 int seek_to_last() {
243 return generic_iter->seek_to_last(prefix);
244 }
245 int upper_bound(const std::string &after) override {
246 return generic_iter->upper_bound(prefix, after);
247 }
248 int lower_bound(const std::string &to) override {
249 return generic_iter->lower_bound(prefix, to);
250 }
251 bool valid() override {
252 if (!generic_iter->valid())
253 return false;
254 return generic_iter->raw_key_is_prefixed(prefix);
255 }
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 {
259 if (validate) {
260 if (valid())
261 return generic_iter->next();
262 return status();
263 } else {
264 return generic_iter->next();
265 }
266 }
267
268 int prev(bool validate=true) {
269 if (validate) {
270 if (valid())
271 return generic_iter->prev();
272 return status();
273 } else {
274 return generic_iter->prev();
275 }
276 }
277 std::string key() override {
278 return generic_iter->key();
279 }
280 std::pair<std::string, std::string> raw_key() {
281 return generic_iter->raw_key();
282 }
283 bufferlist value() override {
284 return generic_iter->value();
285 }
286 bufferptr value_as_ptr() {
287 return generic_iter->value_as_ptr();
288 }
289 int status() override {
290 return generic_iter->status();
291 }
292 };
293
294 typedef ceph::shared_ptr< IteratorImpl > Iterator;
295
296 WholeSpaceIterator get_iterator() {
297 return _get_iterator();
298 }
299
300 Iterator get_iterator(const std::string &prefix) {
301 return std::make_shared<IteratorImpl>(prefix, get_iterator());
302 }
303
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) {
306 return -EOPNOTSUPP;
307 }
308
309 virtual int set_cache_size(uint64_t) {
310 return -EOPNOTSUPP;
311 }
312
313 // PriCache
314 private:
315 int64_t cache_bytes[PriorityCache::Priority::LAST+1] = { 0 };
316 double cache_ratio = 0;
317
318 public:
319 virtual int64_t request_cache_bytes(PriorityCache::Priority pri, uint64_t chunk_bytes) const {
320 return -EOPNOTSUPP;
321 }
322
323 virtual int64_t get_cache_bytes(PriorityCache::Priority pri) const {
324 return cache_bytes[pri];
325 }
326
327 virtual int64_t get_cache_bytes() const {
328 int64_t total = 0;
329
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);
333 }
334 return total;
335 }
336
337 virtual void set_cache_bytes(PriorityCache::Priority pri, int64_t bytes) {
338 cache_bytes[pri] = bytes;
339 }
340
341 virtual void add_cache_bytes(PriorityCache::Priority pri, int64_t bytes) {
342 cache_bytes[pri] += bytes;
343 }
344
345 virtual int64_t commit_cache_size() {
346 return -EOPNOTSUPP;
347 }
348
349 virtual double get_cache_ratio() const {
350 return cache_ratio;
351 }
352
353 virtual void set_cache_ratio(double ratio) {
354 cache_ratio = ratio;
355 }
356
357 virtual string get_cache_name() const {
358 return "Unknown KeyValueDB Cache";
359 }
360
361 // End PriCache
362
363 virtual int set_cache_high_pri_pool_ratio(double ratio) {
364 return -EOPNOTSUPP;
365 }
366
367 virtual int64_t get_cache_usage() const {
368 return -EOPNOTSUPP;
369 }
370
371 virtual ~KeyValueDB() {}
372
373 /// compact the underlying store
374 virtual void compact() {}
375
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) {}
384
385 // See RocksDB merge operator definition, we support the basic
386 // associative merge only right now.
387 class MergeOperator {
388 public:
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
394 virtual void merge(
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;
400
401 virtual ~MergeOperator() {}
402 };
403
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) {
407 return -EOPNOTSUPP;
408 }
409
410 virtual void get_statistics(Formatter *f) {
411 return;
412 }
413
414 /**
415 * Return your perf counters if you have any. Subclasses are not
416 * required to implement this, and callers must respect a null return
417 * value.
418 */
419 virtual PerfCounters *get_perf_counters() {
420 return nullptr;
421 }
422 protected:
423 /// List of matching prefixes and merge operators
424 std::vector<std::pair<std::string,
425 std::shared_ptr<MergeOperator> > > merge_ops;
426
427 virtual WholeSpaceIterator _get_iterator() = 0;
428 };
429
430 #endif