]> git.proxmox.com Git - ceph.git/blame - ceph/src/kv/KeyValueDB.h
update sources to v12.1.0
[ceph.git] / ceph / src / kv / KeyValueDB.h
CommitLineData
7c673cae
FG
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
16using std::string;
17/**
18 * Defines virtual interface to be implemented by key value store
19 *
20 * Kyoto Cabinet or LevelDB should implement this
21 */
22class KeyValueDB {
23public:
24 class TransactionImpl {
25 public:
26 /// Set Keys
27 void set(
28 const std::string &prefix, ///< [in] Prefix for keys
29 const std::map<std::string, bufferlist> &to_set ///< [in] keys/values to set
30 ) {
31 std::map<std::string, bufferlist>::const_iterator it;
32 for (it = to_set.begin(); it != to_set.end(); ++it)
33 set(prefix, it->first, it->second);
34 }
35
36 /// Set Keys (via encoded bufferlist)
37 void set(
38 const std::string &prefix, ///< [in] prefix
39 bufferlist& to_set_bl ///< [in] encoded key/values to set
40 ) {
41 bufferlist::iterator p = to_set_bl.begin();
42 uint32_t num;
43 ::decode(num, p);
44 while (num--) {
45 string key;
46 bufferlist value;
47 ::decode(key, p);
48 ::decode(value, p);
49 set(prefix, key, value);
50 }
51 }
52
53 /// Set Key
54 virtual void set(
55 const std::string &prefix, ///< [in] Prefix for the key
56 const std::string &k, ///< [in] Key to set
57 const bufferlist &bl ///< [in] Value to set
58 ) = 0;
59 virtual void set(
60 const std::string &prefix,
61 const char *k,
62 size_t keylen,
63 const bufferlist& bl) {
64 set(prefix, string(k, keylen), bl);
65 }
66
67 /// Removes Keys (via encoded bufferlist)
68 void rmkeys(
69 const std::string &prefix, ///< [in] Prefix to search for
70 bufferlist &keys_bl ///< [in] Keys to remove
71 ) {
72 bufferlist::iterator p = keys_bl.begin();
73 uint32_t num;
74 ::decode(num, p);
75 while (num--) {
76 string key;
77 ::decode(key, p);
78 rmkey(prefix, key);
79 }
80 }
81
82 /// Removes Keys
83 void rmkeys(
84 const std::string &prefix, ///< [in] Prefix to search for
85 const std::set<std::string> &keys ///< [in] Keys to remove
86 ) {
87 std::set<std::string>::const_iterator it;
88 for (it = keys.begin(); it != keys.end(); ++it)
89 rmkey(prefix, *it);
90 }
91
92 /// Remove Key
93 virtual void rmkey(
94 const std::string &prefix, ///< [in] Prefix to search for
95 const std::string &k ///< [in] Key to remove
96 ) = 0;
97 virtual void rmkey(
98 const std::string &prefix, ///< [in] Prefix to search for
99 const char *k, ///< [in] Key to remove
100 size_t keylen
101 ) {
102 rmkey(prefix, string(k, keylen));
103 }
104
105 /// Remove Single Key which exists and was not overwritten.
106 /// This API is only related to performance optimization, and should only be
107 /// re-implemented by log-insert-merge tree based keyvalue stores(such as RocksDB).
108 /// If a key is overwritten (by calling set multiple times), then the result
109 /// of calling rm_single_key on this key is undefined.
110 virtual void rm_single_key(
111 const std::string &prefix, ///< [in] Prefix to search for
112 const std::string &k ///< [in] Key to remove
113 ) { return rmkey(prefix, k);}
114
115 /// Removes keys beginning with prefix
116 virtual void rmkeys_by_prefix(
117 const std::string &prefix ///< [in] Prefix by which to remove keys
118 ) = 0;
119
120 virtual void rm_range_keys(
121 const string &prefix, ///< [in] Prefix by which to remove keys
122 const string &start, ///< [in] The start bound of remove keys
123 const string &end ///< [in] The start bound of remove keys
124 ) = 0;
125
126 /// Merge value into key
127 virtual void merge(
128 const std::string &prefix, ///< [in] Prefix ==> MUST match some established merge operator
129 const std::string &key, ///< [in] Key to be merged
130 const bufferlist &value ///< [in] value to be merged into key
131 ) { assert(0 == "Not implemented"); }
132
133 virtual ~TransactionImpl() {}
134 };
135 typedef ceph::shared_ptr< TransactionImpl > Transaction;
136
137 /// create a new instance
138 static KeyValueDB *create(CephContext *cct, const std::string& type,
139 const std::string& dir,
140 void *p = NULL);
141
142 /// test whether we can successfully initialize; may have side effects (e.g., create)
143 static int test_init(const std::string& type, const std::string& dir);
144 virtual int init(string option_str="") = 0;
145 virtual int open(std::ostream &out) = 0;
146 virtual int create_and_open(std::ostream &out) = 0;
147 virtual void close() { }
148
149 virtual Transaction get_transaction() = 0;
150 virtual int submit_transaction(Transaction) = 0;
151 virtual int submit_transaction_sync(Transaction t) {
152 return submit_transaction(t);
153 }
154
155 /// Retrieve Keys
156 virtual int get(
157 const std::string &prefix, ///< [in] Prefix for key
158 const std::set<std::string> &key, ///< [in] Key to retrieve
159 std::map<std::string, bufferlist> *out ///< [out] Key value retrieved
160 ) = 0;
161 virtual int get(const std::string &prefix, ///< [in] prefix
162 const std::string &key, ///< [in] key
163 bufferlist *value) { ///< [out] value
164 std::set<std::string> ks;
165 ks.insert(key);
166 std::map<std::string,bufferlist> om;
167 int r = get(prefix, ks, &om);
168 if (om.find(key) != om.end()) {
169 *value = om[key];
170 } else {
171 *value = bufferlist();
172 r = -ENOENT;
173 }
174 return r;
175 }
176 virtual int get(const string &prefix,
177 const char *key, size_t keylen,
178 bufferlist *value) {
179 return get(prefix, string(key, keylen), value);
180 }
181
182 class GenericIteratorImpl {
183 public:
184 virtual int seek_to_first() = 0;
185 virtual int upper_bound(const std::string &after) = 0;
186 virtual int lower_bound(const std::string &to) = 0;
187 virtual bool valid() = 0;
188 virtual int next(bool validate=true) = 0;
189 virtual std::string key() = 0;
190 virtual bufferlist value() = 0;
191 virtual int status() = 0;
192 virtual ~GenericIteratorImpl() {}
193 };
194
195 class WholeSpaceIteratorImpl {
196 public:
197 virtual int seek_to_first() = 0;
198 virtual int seek_to_first(const std::string &prefix) = 0;
199 virtual int seek_to_last() = 0;
200 virtual int seek_to_last(const std::string &prefix) = 0;
201 virtual int upper_bound(const std::string &prefix, const std::string &after) = 0;
202 virtual int lower_bound(const std::string &prefix, const std::string &to) = 0;
203 virtual bool valid() = 0;
204 virtual int next() = 0;
205 virtual int prev() = 0;
206 virtual std::string key() = 0;
207 virtual std::pair<std::string,std::string> raw_key() = 0;
208 virtual bool raw_key_is_prefixed(const std::string &prefix) = 0;
209 virtual bufferlist value() = 0;
210 virtual bufferptr value_as_ptr() {
211 bufferlist bl = value();
212 if (bl.length()) {
213 return *bl.buffers().begin();
214 } else {
215 return bufferptr();
216 }
217 }
218 virtual int status() = 0;
219 virtual size_t key_size() {
220 return 0;
221 }
222 virtual size_t value_size() {
223 return 0;
224 }
225 virtual ~WholeSpaceIteratorImpl() { }
226 };
227 typedef ceph::shared_ptr< WholeSpaceIteratorImpl > WholeSpaceIterator;
228
229 class IteratorImpl : public GenericIteratorImpl {
230 const std::string prefix;
231 WholeSpaceIterator generic_iter;
232 public:
233 IteratorImpl(const std::string &prefix, WholeSpaceIterator iter) :
234 prefix(prefix), generic_iter(iter) { }
235 ~IteratorImpl() override { }
236
237 int seek_to_first() override {
238 return generic_iter->seek_to_first(prefix);
239 }
240 int seek_to_last() {
241 return generic_iter->seek_to_last(prefix);
242 }
243 int upper_bound(const std::string &after) override {
244 return generic_iter->upper_bound(prefix, after);
245 }
246 int lower_bound(const std::string &to) override {
247 return generic_iter->lower_bound(prefix, to);
248 }
249 bool valid() override {
250 if (!generic_iter->valid())
251 return false;
252 return generic_iter->raw_key_is_prefixed(prefix);
253 }
254 // Note that next() and prev() shouldn't validate iters,
255 // it's responsibility of caller to ensure they're valid.
256 int next(bool validate=true) override {
257 if (validate) {
258 if (valid())
259 return generic_iter->next();
260 return status();
261 } else {
262 return generic_iter->next();
263 }
264 }
265
266 int prev(bool validate=true) {
267 if (validate) {
268 if (valid())
269 return generic_iter->prev();
270 return status();
271 } else {
272 return generic_iter->prev();
273 }
274 }
275 std::string key() override {
276 return generic_iter->key();
277 }
278 std::pair<std::string, std::string> raw_key() {
279 return generic_iter->raw_key();
280 }
281 bufferlist value() override {
282 return generic_iter->value();
283 }
284 bufferptr value_as_ptr() {
285 return generic_iter->value_as_ptr();
286 }
287 int status() override {
288 return generic_iter->status();
289 }
290 };
291
292 typedef ceph::shared_ptr< IteratorImpl > Iterator;
293
294 WholeSpaceIterator get_iterator() {
295 return _get_iterator();
296 }
297
298 Iterator get_iterator(const std::string &prefix) {
299 return std::make_shared<IteratorImpl>(prefix, get_iterator());
300 }
301
302 virtual uint64_t get_estimated_size(std::map<std::string,uint64_t> &extra) = 0;
303 virtual int get_statfs(struct store_statfs_t *buf) {
304 return -EOPNOTSUPP;
305 }
306
31f18b77
FG
307 virtual int set_cache_size(uint64_t) {
308 return -EOPNOTSUPP;
309 }
310
7c673cae
FG
311 virtual ~KeyValueDB() {}
312
313 /// compact the underlying store
314 virtual void compact() {}
315
316 /// compact db for all keys with a given prefix
317 virtual void compact_prefix(const std::string& prefix) {}
318 /// compact db for all keys with a given prefix, async
319 virtual void compact_prefix_async(const std::string& prefix) {}
320 virtual void compact_range(const std::string& prefix,
321 const std::string& start, const std::string& end) {}
322 virtual void compact_range_async(const std::string& prefix,
323 const std::string& start, const std::string& end) {}
324
325 // See RocksDB merge operator definition, we support the basic
326 // associative merge only right now.
327 class MergeOperator {
328 public:
329 /// Merge into a key that doesn't exist
330 virtual void merge_nonexistent(
331 const char *rdata, size_t rlen,
332 std::string *new_value) = 0;
333 /// Merge into a key that does exist
334 virtual void merge(
335 const char *ldata, size_t llen,
336 const char *rdata, size_t rlen,
337 std::string *new_value) = 0;
338 /// We use each operator name and each prefix to construct the overall RocksDB operator name for consistency check at open time.
339 virtual string name() const = 0;
340
341 virtual ~MergeOperator() {}
342 };
343
344 /// Setup one or more operators, this needs to be done BEFORE the DB is opened.
345 virtual int set_merge_operator(const std::string& prefix,
346 std::shared_ptr<MergeOperator> mop) {
347 return -EOPNOTSUPP;
348 }
349
350 virtual void get_statistics(Formatter *f) {
351 return;
352 }
353protected:
354 /// List of matching prefixes and merge operators
355 std::vector<std::pair<std::string,
356 std::shared_ptr<MergeOperator> > > merge_ops;
357
358 virtual WholeSpaceIterator _get_iterator() = 0;
359};
360
361#endif