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 assert(!out->snaps.empty());
156 dout(20) << __func__ << " " << oid << " (out == NULL)" << dendl;
161 void SnapMapper::clear_snaps(
162 const hobject_t &oid,
163 MapCacher::Transaction<std::string, bufferlist> *t)
165 dout(20) << __func__ << " " << oid << dendl;
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;
174 backend.remove_keys(to_remove, t);
177 void SnapMapper::set_snaps(
178 const hobject_t &oid,
179 const object_snaps &in,
180 MapCacher::Transaction<std::string, bufferlist> *t)
183 map<string, bufferlist> to_set;
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;
193 backend.set_keys(to_set, t);
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)
202 dout(20) << __func__ << " " << oid << " " << new_snaps
203 << " was " << (old_snaps_check ? *old_snaps_check : set<snapid_t>())
206 if (new_snaps.empty())
207 return remove_oid(oid, t);
210 int r = get_snaps(oid, &out);
214 assert(out.snaps == *old_snaps_check);
216 object_snaps in(oid, new_snaps);
217 set_snaps(oid, in, t);
219 set<string> to_remove;
220 for (set<snapid_t>::iterator i = out.snaps.begin();
221 i != out.snaps.end();
223 if (!new_snaps.count(*i)) {
224 to_remove.insert(to_raw_key(make_pair(*i, oid)));
227 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
228 for (auto& i : to_remove) {
229 dout(20) << __func__ << " rm " << i << dendl;
232 backend.remove_keys(to_remove, t);
236 void SnapMapper::add_oid(
237 const hobject_t &oid,
238 const set<snapid_t>& snaps,
239 MapCacher::Transaction<std::string, bufferlist> *t)
241 dout(20) << __func__ << " " << oid << " " << snaps << dendl;
245 int r = get_snaps(oid, &out);
246 assert(r == -ENOENT);
249 object_snaps _snaps(oid, snaps);
250 set_snaps(oid, _snaps, t);
252 map<string, bufferlist> to_add;
253 for (set<snapid_t>::iterator i = snaps.begin();
256 to_add.insert(to_raw(make_pair(*i, oid)));
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;
263 backend.set_keys(to_add, t);
266 int SnapMapper::get_next_objects_to_trim(
269 vector<hobject_t> *out)
272 assert(out->empty());
274 for (set<string>::iterator i = prefixes.begin();
275 i != prefixes.end() && out->size() < max && r == 0;
277 string prefix(get_prefix(snap) + *i);
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;
288 if (next.first.substr(0, prefix.size()) !=
290 break; // Done with this prefix
293 assert(is_mapping(next.first));
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));
300 out->push_back(next_decoded.second);
304 if (out->size() == 0) {
312 int SnapMapper::remove_oid(
313 const hobject_t &oid,
314 MapCacher::Transaction<std::string, bufferlist> *t)
316 dout(20) << __func__ << " " << oid << dendl;
318 return _remove_oid(oid, t);
321 int SnapMapper::_remove_oid(
322 const hobject_t &oid,
323 MapCacher::Transaction<std::string, bufferlist> *t)
325 dout(20) << __func__ << " " << oid << dendl;
327 int r = get_snaps(oid, &out);
333 set<string> to_remove;
334 for (set<snapid_t>::iterator i = out.snaps.begin();
335 i != out.snaps.end();
337 to_remove.insert(to_raw_key(make_pair(*i, oid)));
339 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
340 for (auto& i : to_remove) {
341 dout(20) << __func__ << " rm " << i << dendl;
344 backend.remove_keys(to_remove, t);
348 int SnapMapper::get_snaps(
349 const hobject_t &oid,
350 std::set<snapid_t> *snaps)
354 int r = get_snaps(oid, &out);
358 snaps->swap(out.snaps);