#include "thin-provisioning/mapping_tree.h" #include "persistent-data/data-structures/btree_damage_visitor.h" #include "persistent-data/space_map.h" using namespace persistent_data; //---------------------------------------------------------------- namespace thin_provisioning { namespace mapping_tree_detail { space_map_ref_counter::space_map_ref_counter(space_map::ptr sm) : sm_(sm) { } void space_map_ref_counter::inc(block_address b) { sm_->inc(b); } void space_map_ref_counter::dec(block_address b) { sm_->dec(b); } //-------------------------------- block_time_ref_counter::block_time_ref_counter(space_map::ptr sm) : sm_(sm) { } void block_time_ref_counter::inc(block_time bt) { sm_->inc(bt.block_); } void block_time_ref_counter::dec(block_time bt) { sm_->dec(bt.block_); } //-------------------------------- void block_traits::unpack(disk_type const &disk, value_type &value) { uint64_t v = to_cpu(disk); value.block_ = v >> 24; value.time_ = v & ((1 << 24) - 1); } void block_traits::pack(value_type const &value, disk_type &disk) { uint64_t v = (value.block_ << 24) | value.time_; disk = base::to_disk(v); } //-------------------------------- mtree_ref_counter::mtree_ref_counter(transaction_manager &tm) : tm_(tm) { } void mtree_ref_counter::set(block_address const &b, uint32_t rc) { tm_.get_sm()->set_count(b, rc); } void mtree_ref_counter::inc(block_address const &b) { tm_.get_sm()->inc(b); } void mtree_ref_counter::dec(block_address const &b) { tm_.get_sm()->dec(b); } //-------------------------------- void mtree_traits::unpack(disk_type const &disk, value_type &value) { value = base::to_cpu(disk); } void mtree_traits::pack(value_type const &value, disk_type &disk) { disk = base::to_disk(value); } //-------------------------------- missing_devices::missing_devices(std::string const &desc, run const &keys) : desc_(desc), keys_(keys) { } void missing_devices::visit(damage_visitor &v) const { v.visit(*this); } //-------------------------------- missing_mappings::missing_mappings(std::string const &desc, uint64_t thin_dev, run const &keys) : desc_(desc), thin_dev_(thin_dev), keys_(keys) { } void missing_mappings::visit(damage_visitor &v) const { v.visit(*this); } } } //---------------------------------------------------------------- namespace { using namespace thin_provisioning; using namespace mapping_tree_detail; struct noop_block_time_visitor : public mapping_tree_detail::mapping_visitor { virtual void visit(btree_path const &, block_time const &) { } }; struct noop_block_visitor : public mapping_tree_detail::device_visitor { virtual void visit(btree_path const &, uint64_t) { } }; class dev_tree_damage_visitor { public: dev_tree_damage_visitor(damage_visitor &v) : v_(v) { } virtual void visit(btree_path const &path, btree_detail::damage const &d) { switch (path.size()) { case 0: v_.visit(missing_devices(d.desc_, d.lost_keys_)); break; case 1: v_.visit(missing_mappings(d.desc_, path[0], d.lost_keys_)); break; default: throw std::runtime_error("dev_tree_damage_visitor: path too long"); } } private: damage_visitor &v_; }; class mapping_tree_damage_visitor { public: mapping_tree_damage_visitor(damage_visitor &v) : v_(v) { } virtual void visit(btree_path const &path, btree_detail::damage const &d) { switch (path.size()) { case 0: v_.visit(missing_devices(d.desc_, d.lost_keys_)); break; case 1: v_.visit(missing_mappings(d.desc_, path[0], d.lost_keys_)); break; default: throw std::runtime_error("mapping_tree_damage_visitor: path too long"); } } private: damage_visitor &v_; }; class single_mapping_tree_damage_visitor { public: single_mapping_tree_damage_visitor(damage_visitor &v, uint64_t dev_id) : v_(v), dev_id_(dev_id) { } virtual void visit(btree_path const &path, btree_detail::damage const &d) { switch (path.size()) { case 0: v_.visit(missing_mappings(d.desc_, dev_id_, d.lost_keys_)); break; default: throw std::runtime_error("single_mapping_tree_damage_visitor: path too long"); } } private: damage_visitor &v_; uint64_t dev_id_; }; } void thin_provisioning::walk_mapping_tree(dev_tree const &tree, mapping_tree_detail::device_visitor &dev_v, mapping_tree_detail::damage_visitor &dv, bool ignore_non_fatal) { dev_tree_damage_visitor ll_dv(dv); btree_visit_values(tree, dev_v, ll_dv, ignore_non_fatal); } void thin_provisioning::check_mapping_tree(dev_tree const &tree, mapping_tree_detail::damage_visitor &visitor, bool ignore_non_fatal) { noop_block_visitor dev_v; walk_mapping_tree(tree, dev_v, visitor, ignore_non_fatal); } void thin_provisioning::walk_mapping_tree(mapping_tree const &tree, mapping_tree_detail::mapping_visitor &mv, mapping_tree_detail::damage_visitor &dv, bool ignore_non_fatal) { mapping_tree_damage_visitor ll_dv(dv); btree_visit_values(tree, mv, ll_dv, ignore_non_fatal); } void thin_provisioning::check_mapping_tree(mapping_tree const &tree, mapping_tree_detail::damage_visitor &visitor, bool ignore_non_fatal) { noop_block_time_visitor mv; walk_mapping_tree(tree, mv, visitor, ignore_non_fatal); } void thin_provisioning::walk_mapping_tree(single_mapping_tree const &tree, uint64_t dev_id, mapping_tree_detail::mapping_visitor &mv, mapping_tree_detail::damage_visitor &dv, bool ignore_non_fatal) { single_mapping_tree_damage_visitor ll_dv(dv, dev_id); btree_visit_values(tree, mv, ll_dv, ignore_non_fatal); } void thin_provisioning::check_mapping_tree(single_mapping_tree const &tree, uint64_t dev_id, mapping_tree_detail::damage_visitor &visitor, bool ignore_non_fatal) { noop_block_time_visitor mv; walk_mapping_tree(tree, dev_id, mv, visitor, ignore_non_fatal); } //----------------------------------------------------------------