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