]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/ObjectMap/KeyValueDBMemory.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / ObjectMap / KeyValueDBMemory.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #include "include/encoding.h"
4 #include "KeyValueDBMemory.h"
5 #include <map>
6 #include <set>
7 #include <iostream>
8
9 using namespace std;
10
11 /**
12 * Iterate over the whole key space of the in-memory store
13 *
14 * @note Removing keys from the store while iterating over the store key-space
15 * may result in unspecified behavior.
16 * If one wants to safely iterate over the store while updating the
17 * store, one should instead use a snapshot iterator, which provides
18 * strong read-consistency.
19 */
20 class WholeSpaceMemIterator : public KeyValueDB::WholeSpaceIteratorImpl {
21 protected:
22 KeyValueDBMemory *db;
23 bool ready;
24
25 map<pair<string,string>, bufferlist>::iterator it;
26
27 public:
28 explicit WholeSpaceMemIterator(KeyValueDBMemory *db) : db(db), ready(false) { }
29 ~WholeSpaceMemIterator() override { }
30
31 int seek_to_first() override {
32 if (db->db.empty()) {
33 it = db->db.end();
34 ready = false;
35 return 0;
36 }
37 it = db->db.begin();
38 ready = true;
39 return 0;
40 }
41
42 int seek_to_first(const string &prefix) override {
43 it = db->db.lower_bound(make_pair(prefix, ""));
44 if (db->db.empty() || (it == db->db.end())) {
45 it = db->db.end();
46 ready = false;
47 return 0;
48 }
49 ready = true;
50 return 0;
51 }
52
53 int seek_to_last() override {
54 it = db->db.end();
55 if (db->db.empty()) {
56 ready = false;
57 return 0;
58 }
59 --it;
60 ceph_assert(it != db->db.end());
61 ready = true;
62 return 0;
63 }
64
65 int seek_to_last(const string &prefix) override {
66 string tmp(prefix);
67 tmp.append(1, (char) 0);
68 it = db->db.upper_bound(make_pair(tmp,""));
69
70 if (db->db.empty() || (it == db->db.end())) {
71 seek_to_last();
72 }
73 else {
74 ready = true;
75 prev();
76 }
77 return 0;
78 }
79
80 int lower_bound(const string &prefix, const string &to) override {
81 it = db->db.lower_bound(make_pair(prefix,to));
82 if ((db->db.empty()) || (it == db->db.end())) {
83 it = db->db.end();
84 ready = false;
85 return 0;
86 }
87
88 ceph_assert(it != db->db.end());
89
90 ready = true;
91 return 0;
92 }
93
94 int upper_bound(const string &prefix, const string &after) override {
95 it = db->db.upper_bound(make_pair(prefix,after));
96 if ((db->db.empty()) || (it == db->db.end())) {
97 it = db->db.end();
98 ready = false;
99 return 0;
100 }
101 ceph_assert(it != db->db.end());
102 ready = true;
103 return 0;
104 }
105
106 bool valid() override {
107 return ready && (it != db->db.end());
108 }
109
110 bool begin() {
111 return ready && (it == db->db.begin());
112 }
113
114 int prev() override {
115 if (!begin() && ready)
116 --it;
117 else
118 it = db->db.end();
119 return 0;
120 }
121
122 int next() override {
123 if (valid())
124 ++it;
125 return 0;
126 }
127
128 string key() override {
129 if (valid())
130 return (*it).first.second;
131 else
132 return "";
133 }
134
135 pair<string,string> raw_key() override {
136 if (valid())
137 return (*it).first;
138 else
139 return make_pair("", "");
140 }
141
142 bool raw_key_is_prefixed(const string &prefix) override {
143 return prefix == (*it).first.first;
144 }
145
146 bufferlist value() override {
147 if (valid())
148 return (*it).second;
149 else
150 return bufferlist();
151 }
152
153 int status() override {
154 return 0;
155 }
156 };
157
158 int KeyValueDBMemory::get(const string &prefix,
159 const std::set<string> &key,
160 map<string, bufferlist> *out) {
161 if (!exists_prefix(prefix))
162 return 0;
163
164 for (std::set<string>::const_iterator i = key.begin();
165 i != key.end();
166 ++i) {
167 pair<string,string> k(prefix, *i);
168 if (db.count(k))
169 (*out)[*i] = db[k];
170 }
171 return 0;
172 }
173
174 int KeyValueDBMemory::get_keys(const string &prefix,
175 const std::set<string> &key,
176 std::set<string> *out) {
177 if (!exists_prefix(prefix))
178 return 0;
179
180 for (std::set<string>::const_iterator i = key.begin();
181 i != key.end();
182 ++i) {
183 if (db.count(make_pair(prefix, *i)))
184 out->insert(*i);
185 }
186 return 0;
187 }
188
189 int KeyValueDBMemory::set(const string &prefix,
190 const string &key,
191 const bufferlist &bl) {
192 db[make_pair(prefix,key)] = bl;
193 return 0;
194 }
195
196 int KeyValueDBMemory::rmkey(const string &prefix,
197 const string &key) {
198 db.erase(make_pair(prefix,key));
199 return 0;
200 }
201
202 int KeyValueDBMemory::rmkeys_by_prefix(const string &prefix) {
203 map<std::pair<string,string>,bufferlist>::iterator i;
204 i = db.lower_bound(make_pair(prefix, ""));
205 if (i == db.end())
206 return 0;
207
208 while (i != db.end()) {
209 std::pair<string,string> key = (*i).first;
210 if (key.first != prefix)
211 break;
212
213 ++i;
214 rmkey(key.first, key.second);
215 }
216 return 0;
217 }
218
219 int KeyValueDBMemory::rm_range_keys(const string &prefix, const string &start, const string &end) {
220 map<std::pair<string,string>,bufferlist>::iterator i;
221 i = db.lower_bound(make_pair(prefix, start));
222 if (i == db.end())
223 return 0;
224
225 while (i != db.end()) {
226 std::pair<string,string> key = (*i).first;
227 if (key.first != prefix)
228 break;
229 if (key.second >= end)
230 break;
231 ++i;
232 rmkey(key.first, key.second);
233 }
234 return 0;
235 }
236
237 KeyValueDB::WholeSpaceIterator KeyValueDBMemory::get_wholespace_iterator(IteratorOpts opts) {
238 return std::shared_ptr<KeyValueDB::WholeSpaceIteratorImpl>(
239 new WholeSpaceMemIterator(this)
240 );
241 }
242
243 class WholeSpaceSnapshotMemIterator : public WholeSpaceMemIterator {
244 public:
245
246 /**
247 * @note
248 * We perform a copy of the db map, which is populated by bufferlists.
249 *
250 * These are designed as shallow containers, thus there is a chance that
251 * changing the underlying memory pages will lead to the iterator seeing
252 * erroneous states.
253 *
254 * Although we haven't verified this yet, there is this chance, so we should
255 * keep it in mind.
256 */
257
258 explicit WholeSpaceSnapshotMemIterator(KeyValueDBMemory *db) :
259 WholeSpaceMemIterator(db) { }
260 ~WholeSpaceSnapshotMemIterator() override {
261 delete db;
262 }
263 };
264