]>
git.proxmox.com Git - ceph.git/blob - 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
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
15 #include "SnapMapper.h"
17 #define dout_context cct
18 #define dout_subsys ceph_subsys_osd
20 #define dout_prefix *_dout << "snap_mapper."
24 const string
SnapMapper::MAPPING_PREFIX
= "MAP_";
25 const string
SnapMapper::OBJECT_PREFIX
= "OBJ_";
27 int OSDriver::get_keys(
28 const std::set
<std::string
> &keys
,
29 std::map
<std::string
, bufferlist
> *out
)
31 return os
->omap_get_values(cid
, hoid
, keys
, out
);
34 int OSDriver::get_next(
35 const std::string
&key
,
36 pair
<std::string
, bufferlist
> *next
)
38 ObjectMap::ObjectMapIterator iter
=
39 os
->get_omap_iterator(cid
, hoid
);
44 iter
->upper_bound(key
);
47 *next
= make_pair(iter
->key(), iter
->value());
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
);
66 void decode(bufferlist::iterator
&bl
) {
73 WRITE_CLASS_ENCODER(Mapping
)
75 string
SnapMapper::get_prefix(snapid_t snap
)
80 "%.*X_", (int)(sizeof(snap
)*2),
81 static_cast<unsigned>(snap
));
82 return MAPPING_PREFIX
+ string(buf
, len
);
85 string
SnapMapper::to_raw_key(
86 const pair
<snapid_t
, hobject_t
> &in
)
88 return get_prefix(in
.first
) + shard_prefix
+ in
.second
.to_str();
91 pair
<string
, bufferlist
> SnapMapper::to_raw(
92 const pair
<snapid_t
, hobject_t
> &in
)
95 ::encode(Mapping(in
), bl
);
101 pair
<snapid_t
, hobject_t
> SnapMapper::from_raw(
102 const pair
<std::string
, bufferlist
> &image
)
105 bufferlist
bl(image
.second
);
106 bufferlist::iterator
bp(bl
.begin());
108 return make_pair(map
.snap
, map
.hoid
);
111 bool SnapMapper::is_mapping(const string
&to_test
)
113 return to_test
.substr(0, MAPPING_PREFIX
.size()) == MAPPING_PREFIX
;
116 string
SnapMapper::to_object_key(const hobject_t
&hoid
)
118 return OBJECT_PREFIX
+ shard_prefix
+ hoid
.to_str();
121 void SnapMapper::object_snaps::encode(bufferlist
&bl
) const
123 ENCODE_START(1, 1, bl
);
129 void SnapMapper::object_snaps::decode(bufferlist::iterator
&bl
)
137 int SnapMapper::get_snaps(
138 const hobject_t
&oid
,
143 map
<string
, bufferlist
> got
;
144 keys
.insert(to_object_key(oid
));
145 int r
= backend
.get_keys(keys
, &got
);
151 bufferlist::iterator bp
= got
.begin()->second
.begin();
153 dout(20) << __func__
<< " " << oid
<< " " << out
->snaps
<< dendl
;
154 if (out
->snaps
.empty()) {
155 dout(1) << __func__
<< " " << oid
<< " empty snapset" << dendl
;
156 assert(!cct
->_conf
->osd_debug_verify_snaps
);
159 dout(20) << __func__
<< " " << oid
<< " (out == NULL)" << dendl
;
164 void SnapMapper::clear_snaps(
165 const hobject_t
&oid
,
166 MapCacher::Transaction
<std::string
, bufferlist
> *t
)
168 dout(20) << __func__
<< " " << oid
<< dendl
;
170 set
<string
> to_remove
;
171 to_remove
.insert(to_object_key(oid
));
172 if (g_conf
->subsys
.should_gather(ceph_subsys_osd
, 20)) {
173 for (auto& i
: to_remove
) {
174 dout(20) << __func__
<< " rm " << i
<< dendl
;
177 backend
.remove_keys(to_remove
, t
);
180 void SnapMapper::set_snaps(
181 const hobject_t
&oid
,
182 const object_snaps
&in
,
183 MapCacher::Transaction
<std::string
, bufferlist
> *t
)
186 map
<string
, bufferlist
> to_set
;
189 to_set
[to_object_key(oid
)] = bl
;
190 dout(20) << __func__
<< " " << oid
<< " " << in
.snaps
<< dendl
;
191 if (g_conf
->subsys
.should_gather(ceph_subsys_osd
, 20)) {
192 for (auto& i
: to_set
) {
193 dout(20) << __func__
<< " set " << i
.first
<< dendl
;
196 backend
.set_keys(to_set
, t
);
199 int SnapMapper::update_snaps(
200 const hobject_t
&oid
,
201 const set
<snapid_t
> &new_snaps
,
202 const set
<snapid_t
> *old_snaps_check
,
203 MapCacher::Transaction
<std::string
, bufferlist
> *t
)
205 dout(20) << __func__
<< " " << oid
<< " " << new_snaps
206 << " was " << (old_snaps_check
? *old_snaps_check
: set
<snapid_t
>())
209 if (new_snaps
.empty())
210 return remove_oid(oid
, t
);
213 int r
= get_snaps(oid
, &out
);
217 assert(out
.snaps
== *old_snaps_check
);
219 object_snaps
in(oid
, new_snaps
);
220 set_snaps(oid
, in
, t
);
222 set
<string
> to_remove
;
223 for (set
<snapid_t
>::iterator i
= out
.snaps
.begin();
224 i
!= out
.snaps
.end();
226 if (!new_snaps
.count(*i
)) {
227 to_remove
.insert(to_raw_key(make_pair(*i
, oid
)));
230 if (g_conf
->subsys
.should_gather(ceph_subsys_osd
, 20)) {
231 for (auto& i
: to_remove
) {
232 dout(20) << __func__
<< " rm " << i
<< dendl
;
235 backend
.remove_keys(to_remove
, t
);
239 void SnapMapper::add_oid(
240 const hobject_t
&oid
,
241 const set
<snapid_t
>& snaps
,
242 MapCacher::Transaction
<std::string
, bufferlist
> *t
)
244 dout(20) << __func__
<< " " << oid
<< " " << snaps
<< dendl
;
245 assert(!snaps
.empty());
249 int r
= get_snaps(oid
, &out
);
251 derr
<< __func__
<< " found existing snaps mapped on " << oid
252 << ", removing" << dendl
;
253 assert(!cct
->_conf
->osd_debug_verify_snaps
);
258 object_snaps
_snaps(oid
, snaps
);
259 set_snaps(oid
, _snaps
, t
);
261 map
<string
, bufferlist
> to_add
;
262 for (set
<snapid_t
>::iterator i
= snaps
.begin();
265 to_add
.insert(to_raw(make_pair(*i
, oid
)));
267 if (g_conf
->subsys
.should_gather(ceph_subsys_osd
, 20)) {
268 for (auto& i
: to_add
) {
269 dout(20) << __func__
<< " set " << i
.first
<< dendl
;
272 backend
.set_keys(to_add
, t
);
275 int SnapMapper::get_next_objects_to_trim(
278 vector
<hobject_t
> *out
)
281 assert(out
->empty());
283 for (set
<string
>::iterator i
= prefixes
.begin();
284 i
!= prefixes
.end() && out
->size() < max
&& r
== 0;
286 string
prefix(get_prefix(snap
) + *i
);
288 while (out
->size() < max
) {
289 pair
<string
, bufferlist
> next
;
290 r
= backend
.get_next(pos
, &next
);
291 dout(20) << __func__
<< " get_next(" << pos
<< ") returns " << r
292 << " " << next
<< dendl
;
297 if (next
.first
.substr(0, prefix
.size()) !=
299 break; // Done with this prefix
302 assert(is_mapping(next
.first
));
304 dout(20) << __func__
<< " " << next
.first
<< dendl
;
305 pair
<snapid_t
, hobject_t
> next_decoded(from_raw(next
));
306 assert(next_decoded
.first
== snap
);
307 assert(check(next_decoded
.second
));
309 out
->push_back(next_decoded
.second
);
313 if (out
->size() == 0) {
321 int SnapMapper::remove_oid(
322 const hobject_t
&oid
,
323 MapCacher::Transaction
<std::string
, bufferlist
> *t
)
325 dout(20) << __func__
<< " " << oid
<< dendl
;
327 return _remove_oid(oid
, t
);
330 int SnapMapper::_remove_oid(
331 const hobject_t
&oid
,
332 MapCacher::Transaction
<std::string
, bufferlist
> *t
)
334 dout(20) << __func__
<< " " << oid
<< dendl
;
336 int r
= get_snaps(oid
, &out
);
342 set
<string
> to_remove
;
343 for (set
<snapid_t
>::iterator i
= out
.snaps
.begin();
344 i
!= out
.snaps
.end();
346 to_remove
.insert(to_raw_key(make_pair(*i
, oid
)));
348 if (g_conf
->subsys
.should_gather(ceph_subsys_osd
, 20)) {
349 for (auto& i
: to_remove
) {
350 dout(20) << __func__
<< " rm " << i
<< dendl
;
353 backend
.remove_keys(to_remove
, t
);
357 int SnapMapper::get_snaps(
358 const hobject_t
&oid
,
359 std::set
<snapid_t
> *snaps
)
363 int r
= get_snaps(oid
, &out
);
367 snaps
->swap(out
.snaps
);