]> git.proxmox.com Git - ceph.git/blame - ceph/src/osd/SnapMapper.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / osd / SnapMapper.cc
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/*
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
22using std::string;
23
24const string SnapMapper::MAPPING_PREFIX = "MAP_";
25const string SnapMapper::OBJECT_PREFIX = "OBJ_";
26
27int 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
34int 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
54struct 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};
73WRITE_CLASS_ENCODER(Mapping)
74
75string 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
85string 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
91pair<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
101pair<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
111bool SnapMapper::is_mapping(const string &to_test)
112{
113 return to_test.substr(0, MAPPING_PREFIX.size()) == MAPPING_PREFIX;
114}
115
116string SnapMapper::to_object_key(const hobject_t &hoid)
117{
118 return OBJECT_PREFIX + shard_prefix + hoid.to_str();
119}
120
121void 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
129void 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
137int 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
161void 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 backend.remove_keys(to_remove, t);
170}
171
172void SnapMapper::set_snaps(
173 const hobject_t &oid,
174 const object_snaps &in,
175 MapCacher::Transaction<std::string, bufferlist> *t)
176{
177 assert(check(oid));
178 map<string, bufferlist> to_set;
179 bufferlist bl;
180 ::encode(in, bl);
181 to_set[to_object_key(oid)] = bl;
182 dout(20) << __func__ << " " << oid << " " << in.snaps << dendl;
183 backend.set_keys(to_set, t);
184}
185
186int SnapMapper::update_snaps(
187 const hobject_t &oid,
188 const set<snapid_t> &new_snaps,
189 const set<snapid_t> *old_snaps_check,
190 MapCacher::Transaction<std::string, bufferlist> *t)
191{
192 dout(20) << __func__ << " " << oid << " " << new_snaps
193 << " was " << (old_snaps_check ? *old_snaps_check : set<snapid_t>())
194 << dendl;
195 assert(check(oid));
196 if (new_snaps.empty())
197 return remove_oid(oid, t);
198
199 object_snaps out;
200 int r = get_snaps(oid, &out);
201 if (r < 0)
202 return r;
203 if (old_snaps_check)
204 assert(out.snaps == *old_snaps_check);
205
206 object_snaps in(oid, new_snaps);
207 set_snaps(oid, in, t);
208
209 set<string> to_remove;
210 for (set<snapid_t>::iterator i = out.snaps.begin();
211 i != out.snaps.end();
212 ++i) {
213 if (!new_snaps.count(*i)) {
214 to_remove.insert(to_raw_key(make_pair(*i, oid)));
215 }
216 }
217 backend.remove_keys(to_remove, t);
218 return 0;
219}
220
221void SnapMapper::add_oid(
222 const hobject_t &oid,
223 const set<snapid_t>& snaps,
224 MapCacher::Transaction<std::string, bufferlist> *t)
225{
226 dout(20) << __func__ << " " << oid << " " << snaps << dendl;
227 assert(check(oid));
228 {
229 object_snaps out;
230 int r = get_snaps(oid, &out);
231 assert(r == -ENOENT);
232 }
233
234 object_snaps _snaps(oid, snaps);
235 set_snaps(oid, _snaps, t);
236
237 map<string, bufferlist> to_add;
238 for (set<snapid_t>::iterator i = snaps.begin();
239 i != snaps.end();
240 ++i) {
241 to_add.insert(to_raw(make_pair(*i, oid)));
242 }
243 backend.set_keys(to_add, t);
244}
245
246int SnapMapper::get_next_objects_to_trim(
247 snapid_t snap,
248 unsigned max,
249 vector<hobject_t> *out)
250{
251 assert(out);
252 assert(out->empty());
253 int r = 0;
254 for (set<string>::iterator i = prefixes.begin();
255 i != prefixes.end() && out->size() < max && r == 0;
256 ++i) {
257 string prefix(get_prefix(snap) + *i);
258 string pos = prefix;
259 while (out->size() < max) {
260 pair<string, bufferlist> next;
261 r = backend.get_next(pos, &next);
262 if (r != 0) {
263 break; // Done
264 }
265
266 if (next.first.substr(0, prefix.size()) !=
267 prefix) {
268 break; // Done with this prefix
269 }
270
271 assert(is_mapping(next.first));
272
273 pair<snapid_t, hobject_t> next_decoded(from_raw(next));
274 assert(next_decoded.first == snap);
275 assert(check(next_decoded.second));
276
277 out->push_back(next_decoded.second);
278 pos = next.first;
279 }
280 }
281 if (out->size() == 0) {
282 return -ENOENT;
283 } else {
284 return 0;
285 }
286}
287
288
289int SnapMapper::remove_oid(
290 const hobject_t &oid,
291 MapCacher::Transaction<std::string, bufferlist> *t)
292{
293 dout(20) << __func__ << " " << oid << dendl;
294 assert(check(oid));
295 return _remove_oid(oid, t);
296}
297
298int SnapMapper::_remove_oid(
299 const hobject_t &oid,
300 MapCacher::Transaction<std::string, bufferlist> *t)
301{
302 dout(20) << __func__ << " " << oid << dendl;
303 object_snaps out;
304 int r = get_snaps(oid, &out);
305 if (r < 0)
306 return r;
307
308 clear_snaps(oid, t);
309
310 set<string> to_remove;
311 for (set<snapid_t>::iterator i = out.snaps.begin();
312 i != out.snaps.end();
313 ++i) {
314 to_remove.insert(to_raw_key(make_pair(*i, oid)));
315 }
316 backend.remove_keys(to_remove, t);
317 return 0;
318}
319
320int SnapMapper::get_snaps(
321 const hobject_t &oid,
322 std::set<snapid_t> *snaps)
323{
324 assert(check(oid));
325 object_snaps out;
326 int r = get_snaps(oid, &out);
327 if (r < 0)
328 return r;
329 if (snaps)
330 snaps->swap(out.snaps);
331 return 0;
332}