Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / osd / SnapMapper.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "SnapMapper.h"
16
17 #define dout_context cct
18 #define dout_subsys ceph_subsys_osd
19 #undef dout_prefix
20 #define dout_prefix *_dout << "snap_mapper."
21
22 using std::string;
23
24 const string SnapMapper::MAPPING_PREFIX = "MAP_";
25 const string SnapMapper::OBJECT_PREFIX = "OBJ_";
26
27 int OSDriver::get_keys(
28   const std::set<std::string> &keys,
29   std::map<std::string, bufferlist> *out)
30 {
31   return os->omap_get_values(cid, hoid, keys, out);
32 }
33
34 int OSDriver::get_next(
35   const std::string &key,
36   pair<std::string, bufferlist> *next)
37 {
38   ObjectMap::ObjectMapIterator iter =
39     os->get_omap_iterator(cid, hoid);
40   if (!iter) {
41     ceph_abort();
42     return -EINVAL;
43   }
44   iter->upper_bound(key);
45   if (iter->valid()) {
46     if (next)
47       *next = make_pair(iter->key(), iter->value());
48     return 0;
49   } else {
50     return -ENOENT;
51   }
52 }
53
54 struct Mapping {
55   snapid_t snap;
56   hobject_t hoid;
57   explicit Mapping(const pair<snapid_t, hobject_t> &in)
58     : snap(in.first), hoid(in.second) {}
59   Mapping() : snap(0) {}
60   void encode(bufferlist &bl) const {
61     ENCODE_START(1, 1, bl);
62     ::encode(snap, bl);
63     ::encode(hoid, bl);
64     ENCODE_FINISH(bl);
65   }
66   void decode(bufferlist::iterator &bl) {
67     DECODE_START(1, bl);
68     ::decode(snap, bl);
69     ::decode(hoid, bl);
70     DECODE_FINISH(bl);
71   }
72 };
73 WRITE_CLASS_ENCODER(Mapping)
74
75 string SnapMapper::get_prefix(snapid_t snap)
76 {
77   char buf[100];
78   int len = snprintf(
79     buf, sizeof(buf),
80     "%.*X_", (int)(sizeof(snap)*2),
81     static_cast<unsigned>(snap));
82   return MAPPING_PREFIX + string(buf, len);
83 }
84
85 string SnapMapper::to_raw_key(
86   const pair<snapid_t, hobject_t> &in)
87 {
88   return get_prefix(in.first) + shard_prefix + in.second.to_str();
89 }
90
91 pair<string, bufferlist> SnapMapper::to_raw(
92   const pair<snapid_t, hobject_t> &in)
93 {
94   bufferlist bl;
95   ::encode(Mapping(in), bl);
96   return make_pair(
97     to_raw_key(in),
98     bl);
99 }
100
101 pair<snapid_t, hobject_t> SnapMapper::from_raw(
102   const pair<std::string, bufferlist> &image)
103 {
104   Mapping map;
105   bufferlist bl(image.second);
106   bufferlist::iterator bp(bl.begin());
107   ::decode(map, bp);
108   return make_pair(map.snap, map.hoid);
109 }
110
111 bool SnapMapper::is_mapping(const string &to_test)
112 {
113   return to_test.substr(0, MAPPING_PREFIX.size()) == MAPPING_PREFIX;
114 }
115
116 string SnapMapper::to_object_key(const hobject_t &hoid)
117 {
118   return OBJECT_PREFIX + shard_prefix + hoid.to_str();
119 }
120
121 void SnapMapper::object_snaps::encode(bufferlist &bl) const
122 {
123   ENCODE_START(1, 1, bl);
124   ::encode(oid, bl);
125   ::encode(snaps, bl);
126   ENCODE_FINISH(bl);
127 }
128
129 void SnapMapper::object_snaps::decode(bufferlist::iterator &bl)
130 {
131   DECODE_START(1, bl);
132   ::decode(oid, bl);
133   ::decode(snaps, bl);
134   DECODE_FINISH(bl);
135 }
136
137 int SnapMapper::get_snaps(
138   const hobject_t &oid,
139   object_snaps *out)
140 {
141   assert(check(oid));
142   set<string> keys;
143   map<string, bufferlist> got;
144   keys.insert(to_object_key(oid));
145   int r = backend.get_keys(keys, &got);
146   if (r < 0)
147     return r;
148   if (got.empty())
149     return -ENOENT;
150   if (out) {
151     bufferlist::iterator bp = got.begin()->second.begin();
152     ::decode(*out, bp);
153     dout(20) << __func__ << " " << oid << " " << out->snaps << dendl;
154     assert(!out->snaps.empty());
155   } else {
156     dout(20) << __func__ << " " << oid << " (out == NULL)" << dendl;
157   }
158   return 0;
159 }
160
161 void SnapMapper::clear_snaps(
162   const hobject_t &oid,
163   MapCacher::Transaction<std::string, bufferlist> *t)
164 {
165   dout(20) << __func__ << " " << oid << dendl;
166   assert(check(oid));
167   set<string> to_remove;
168   to_remove.insert(to_object_key(oid));
169   if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
170     for (auto& i : to_remove) {
171       dout(20) << __func__ << " rm " << i << dendl;
172     }
173   }
174   backend.remove_keys(to_remove, t);
175 }
176
177 void SnapMapper::set_snaps(
178   const hobject_t &oid,
179   const object_snaps &in,
180   MapCacher::Transaction<std::string, bufferlist> *t)
181 {
182   assert(check(oid));
183   map<string, bufferlist> to_set;
184   bufferlist bl;
185   ::encode(in, bl);
186   to_set[to_object_key(oid)] = bl;
187   dout(20) << __func__ << " " << oid << " " << in.snaps << dendl;
188   if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
189     for (auto& i : to_set) {
190       dout(20) << __func__ << " set " << i.first << dendl;
191     }
192   }
193   backend.set_keys(to_set, t);
194 }
195
196 int SnapMapper::update_snaps(
197   const hobject_t &oid,
198   const set<snapid_t> &new_snaps,
199   const set<snapid_t> *old_snaps_check,
200   MapCacher::Transaction<std::string, bufferlist> *t)
201 {
202   dout(20) << __func__ << " " << oid << " " << new_snaps
203            << " was " << (old_snaps_check ? *old_snaps_check : set<snapid_t>())
204            << dendl;
205   assert(check(oid));
206   if (new_snaps.empty())
207     return remove_oid(oid, t);
208
209   object_snaps out;
210   int r = get_snaps(oid, &out);
211   if (r < 0)
212     return r;
213   if (old_snaps_check)
214     assert(out.snaps == *old_snaps_check);
215
216   object_snaps in(oid, new_snaps);
217   set_snaps(oid, in, t);
218
219   set<string> to_remove;
220   for (set<snapid_t>::iterator i = out.snaps.begin();
221        i != out.snaps.end();
222        ++i) {
223     if (!new_snaps.count(*i)) {
224       to_remove.insert(to_raw_key(make_pair(*i, oid)));
225     }
226   }
227   if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
228     for (auto& i : to_remove) {
229       dout(20) << __func__ << " rm " << i << dendl;
230     }
231   }
232   backend.remove_keys(to_remove, t);
233   return 0;
234 }
235
236 void SnapMapper::add_oid(
237   const hobject_t &oid,
238   const set<snapid_t>& snaps,
239   MapCacher::Transaction<std::string, bufferlist> *t)
240 {
241   dout(20) << __func__ << " " << oid << " " << snaps << dendl;
242   assert(check(oid));
243   {
244     object_snaps out;
245     int r = get_snaps(oid, &out);
246     assert(r == -ENOENT);
247   }
248
249   object_snaps _snaps(oid, snaps);
250   set_snaps(oid, _snaps, t);
251
252   map<string, bufferlist> to_add;
253   for (set<snapid_t>::iterator i = snaps.begin();
254        i != snaps.end();
255        ++i) {
256     to_add.insert(to_raw(make_pair(*i, oid)));
257   }
258   if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
259     for (auto& i : to_add) {
260       dout(20) << __func__ << " set " << i.first << dendl;
261     }
262   }
263   backend.set_keys(to_add, t);
264 }
265
266 int SnapMapper::get_next_objects_to_trim(
267   snapid_t snap,
268   unsigned max,
269   vector<hobject_t> *out)
270 {
271   assert(out);
272   assert(out->empty());
273   int r = 0;
274   for (set<string>::iterator i = prefixes.begin();
275        i != prefixes.end() && out->size() < max && r == 0;
276        ++i) {
277     string prefix(get_prefix(snap) + *i);
278     string pos = prefix;
279     while (out->size() < max) {
280       pair<string, bufferlist> next;
281       r = backend.get_next(pos, &next);
282       dout(20) << __func__ << " get_next(" << pos << ") returns " << r
283                << " " << next << dendl;
284       if (r != 0) {
285         break; // Done
286       }
287
288       if (next.first.substr(0, prefix.size()) !=
289           prefix) {
290         break; // Done with this prefix
291       }
292
293       assert(is_mapping(next.first));
294
295       dout(20) << __func__ << " " << next.first << dendl;
296       pair<snapid_t, hobject_t> next_decoded(from_raw(next));
297       assert(next_decoded.first == snap);
298       assert(check(next_decoded.second));
299
300       out->push_back(next_decoded.second);
301       pos = next.first;
302     }
303   }
304   if (out->size() == 0) {
305     return -ENOENT;
306   } else {
307     return 0;
308   }
309 }
310
311
312 int SnapMapper::remove_oid(
313   const hobject_t &oid,
314   MapCacher::Transaction<std::string, bufferlist> *t)
315 {
316   dout(20) << __func__ << " " << oid << dendl;
317   assert(check(oid));
318   return _remove_oid(oid, t);
319 }
320
321 int SnapMapper::_remove_oid(
322   const hobject_t &oid,
323   MapCacher::Transaction<std::string, bufferlist> *t)
324 {
325   dout(20) << __func__ << " " << oid << dendl;
326   object_snaps out;
327   int r = get_snaps(oid, &out);
328   if (r < 0)
329     return r;
330
331   clear_snaps(oid, t);
332
333   set<string> to_remove;
334   for (set<snapid_t>::iterator i = out.snaps.begin();
335        i != out.snaps.end();
336        ++i) {
337     to_remove.insert(to_raw_key(make_pair(*i, oid)));
338   }
339   if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
340     for (auto& i : to_remove) {
341       dout(20) << __func__ << " rm " << i << dendl;
342     }
343   }
344   backend.remove_keys(to_remove, t);
345   return 0;
346 }
347
348 int SnapMapper::get_snaps(
349   const hobject_t &oid,
350   std::set<snapid_t> *snaps)
351 {
352   assert(check(oid));
353   object_snaps out;
354   int r = get_snaps(oid, &out);
355   if (r < 0)
356     return r;
357   if (snaps)
358     snaps->swap(out.snaps);
359   return 0;
360 }