X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fosd%2FSnapMapper.cc;fp=src%2Fceph%2Fsrc%2Fosd%2FSnapMapper.cc;h=81c548510045272a19784f389e49884a75d015d8;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/osd/SnapMapper.cc b/src/ceph/src/osd/SnapMapper.cc new file mode 100644 index 0000000..81c5485 --- /dev/null +++ b/src/ceph/src/osd/SnapMapper.cc @@ -0,0 +1,360 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "SnapMapper.h" + +#define dout_context cct +#define dout_subsys ceph_subsys_osd +#undef dout_prefix +#define dout_prefix *_dout << "snap_mapper." + +using std::string; + +const string SnapMapper::MAPPING_PREFIX = "MAP_"; +const string SnapMapper::OBJECT_PREFIX = "OBJ_"; + +int OSDriver::get_keys( + const std::set &keys, + std::map *out) +{ + return os->omap_get_values(cid, hoid, keys, out); +} + +int OSDriver::get_next( + const std::string &key, + pair *next) +{ + ObjectMap::ObjectMapIterator iter = + os->get_omap_iterator(cid, hoid); + if (!iter) { + ceph_abort(); + return -EINVAL; + } + iter->upper_bound(key); + if (iter->valid()) { + if (next) + *next = make_pair(iter->key(), iter->value()); + return 0; + } else { + return -ENOENT; + } +} + +struct Mapping { + snapid_t snap; + hobject_t hoid; + explicit Mapping(const pair &in) + : snap(in.first), hoid(in.second) {} + Mapping() : snap(0) {} + void encode(bufferlist &bl) const { + ENCODE_START(1, 1, bl); + ::encode(snap, bl); + ::encode(hoid, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::iterator &bl) { + DECODE_START(1, bl); + ::decode(snap, bl); + ::decode(hoid, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(Mapping) + +string SnapMapper::get_prefix(snapid_t snap) +{ + char buf[100]; + int len = snprintf( + buf, sizeof(buf), + "%.*X_", (int)(sizeof(snap)*2), + static_cast(snap)); + return MAPPING_PREFIX + string(buf, len); +} + +string SnapMapper::to_raw_key( + const pair &in) +{ + return get_prefix(in.first) + shard_prefix + in.second.to_str(); +} + +pair SnapMapper::to_raw( + const pair &in) +{ + bufferlist bl; + ::encode(Mapping(in), bl); + return make_pair( + to_raw_key(in), + bl); +} + +pair SnapMapper::from_raw( + const pair &image) +{ + Mapping map; + bufferlist bl(image.second); + bufferlist::iterator bp(bl.begin()); + ::decode(map, bp); + return make_pair(map.snap, map.hoid); +} + +bool SnapMapper::is_mapping(const string &to_test) +{ + return to_test.substr(0, MAPPING_PREFIX.size()) == MAPPING_PREFIX; +} + +string SnapMapper::to_object_key(const hobject_t &hoid) +{ + return OBJECT_PREFIX + shard_prefix + hoid.to_str(); +} + +void SnapMapper::object_snaps::encode(bufferlist &bl) const +{ + ENCODE_START(1, 1, bl); + ::encode(oid, bl); + ::encode(snaps, bl); + ENCODE_FINISH(bl); +} + +void SnapMapper::object_snaps::decode(bufferlist::iterator &bl) +{ + DECODE_START(1, bl); + ::decode(oid, bl); + ::decode(snaps, bl); + DECODE_FINISH(bl); +} + +int SnapMapper::get_snaps( + const hobject_t &oid, + object_snaps *out) +{ + assert(check(oid)); + set keys; + map got; + keys.insert(to_object_key(oid)); + int r = backend.get_keys(keys, &got); + if (r < 0) + return r; + if (got.empty()) + return -ENOENT; + if (out) { + bufferlist::iterator bp = got.begin()->second.begin(); + ::decode(*out, bp); + dout(20) << __func__ << " " << oid << " " << out->snaps << dendl; + assert(!out->snaps.empty()); + } else { + dout(20) << __func__ << " " << oid << " (out == NULL)" << dendl; + } + return 0; +} + +void SnapMapper::clear_snaps( + const hobject_t &oid, + MapCacher::Transaction *t) +{ + dout(20) << __func__ << " " << oid << dendl; + assert(check(oid)); + set to_remove; + to_remove.insert(to_object_key(oid)); + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_remove) { + dout(20) << __func__ << " rm " << i << dendl; + } + } + backend.remove_keys(to_remove, t); +} + +void SnapMapper::set_snaps( + const hobject_t &oid, + const object_snaps &in, + MapCacher::Transaction *t) +{ + assert(check(oid)); + map to_set; + bufferlist bl; + ::encode(in, bl); + to_set[to_object_key(oid)] = bl; + dout(20) << __func__ << " " << oid << " " << in.snaps << dendl; + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_set) { + dout(20) << __func__ << " set " << i.first << dendl; + } + } + backend.set_keys(to_set, t); +} + +int SnapMapper::update_snaps( + const hobject_t &oid, + const set &new_snaps, + const set *old_snaps_check, + MapCacher::Transaction *t) +{ + dout(20) << __func__ << " " << oid << " " << new_snaps + << " was " << (old_snaps_check ? *old_snaps_check : set()) + << dendl; + assert(check(oid)); + if (new_snaps.empty()) + return remove_oid(oid, t); + + object_snaps out; + int r = get_snaps(oid, &out); + if (r < 0) + return r; + if (old_snaps_check) + assert(out.snaps == *old_snaps_check); + + object_snaps in(oid, new_snaps); + set_snaps(oid, in, t); + + set to_remove; + for (set::iterator i = out.snaps.begin(); + i != out.snaps.end(); + ++i) { + if (!new_snaps.count(*i)) { + to_remove.insert(to_raw_key(make_pair(*i, oid))); + } + } + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_remove) { + dout(20) << __func__ << " rm " << i << dendl; + } + } + backend.remove_keys(to_remove, t); + return 0; +} + +void SnapMapper::add_oid( + const hobject_t &oid, + const set& snaps, + MapCacher::Transaction *t) +{ + dout(20) << __func__ << " " << oid << " " << snaps << dendl; + assert(check(oid)); + { + object_snaps out; + int r = get_snaps(oid, &out); + assert(r == -ENOENT); + } + + object_snaps _snaps(oid, snaps); + set_snaps(oid, _snaps, t); + + map to_add; + for (set::iterator i = snaps.begin(); + i != snaps.end(); + ++i) { + to_add.insert(to_raw(make_pair(*i, oid))); + } + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_add) { + dout(20) << __func__ << " set " << i.first << dendl; + } + } + backend.set_keys(to_add, t); +} + +int SnapMapper::get_next_objects_to_trim( + snapid_t snap, + unsigned max, + vector *out) +{ + assert(out); + assert(out->empty()); + int r = 0; + for (set::iterator i = prefixes.begin(); + i != prefixes.end() && out->size() < max && r == 0; + ++i) { + string prefix(get_prefix(snap) + *i); + string pos = prefix; + while (out->size() < max) { + pair next; + r = backend.get_next(pos, &next); + dout(20) << __func__ << " get_next(" << pos << ") returns " << r + << " " << next << dendl; + if (r != 0) { + break; // Done + } + + if (next.first.substr(0, prefix.size()) != + prefix) { + break; // Done with this prefix + } + + assert(is_mapping(next.first)); + + dout(20) << __func__ << " " << next.first << dendl; + pair next_decoded(from_raw(next)); + assert(next_decoded.first == snap); + assert(check(next_decoded.second)); + + out->push_back(next_decoded.second); + pos = next.first; + } + } + if (out->size() == 0) { + return -ENOENT; + } else { + return 0; + } +} + + +int SnapMapper::remove_oid( + const hobject_t &oid, + MapCacher::Transaction *t) +{ + dout(20) << __func__ << " " << oid << dendl; + assert(check(oid)); + return _remove_oid(oid, t); +} + +int SnapMapper::_remove_oid( + const hobject_t &oid, + MapCacher::Transaction *t) +{ + dout(20) << __func__ << " " << oid << dendl; + object_snaps out; + int r = get_snaps(oid, &out); + if (r < 0) + return r; + + clear_snaps(oid, t); + + set to_remove; + for (set::iterator i = out.snaps.begin(); + i != out.snaps.end(); + ++i) { + to_remove.insert(to_raw_key(make_pair(*i, oid))); + } + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_remove) { + dout(20) << __func__ << " rm " << i << dendl; + } + } + backend.remove_keys(to_remove, t); + return 0; +} + +int SnapMapper::get_snaps( + const hobject_t &oid, + std::set *snaps) +{ + assert(check(oid)); + object_snaps out; + int r = get_snaps(oid, &out); + if (r < 0) + return r; + if (snaps) + snaps->swap(out.snaps); + return 0; +}