#ifndef MAPPING_TREE_H #define MAPPING_TREE_H #include "base/run.h" #include "persistent-data/data-structures/btree.h" //---------------------------------------------------------------- namespace thin_provisioning { namespace mapping_tree_detail { class space_map_ref_counter { public: space_map_ref_counter(space_map::ptr sm); void inc(block_address b); void dec(block_address b); private: space_map::ptr sm_; }; struct block_time { uint64_t block_; uint32_t time_; }; class block_time_ref_counter { public: block_time_ref_counter(space_map::ptr sm); void inc(block_time bt); void dec(block_time bt); private: space_map::ptr sm_; }; struct block_traits { typedef base::le64 disk_type; typedef block_time value_type; typedef block_time_ref_counter ref_counter; static void unpack(disk_type const &disk, value_type &value); static void pack(value_type const &value, disk_type &disk); }; class mtree_ref_counter final : public ref_counter { public: mtree_ref_counter(transaction_manager &tm); void set(block_address const &b, uint32_t rc); void inc(block_address const &b); void dec(block_address const &b); private: transaction_manager &tm_; }; // This value type is itself a tree containing mappings. // Used when manipulating the top level of the mapping // tree. struct mtree_traits { typedef base::le64 disk_type; typedef uint64_t value_type; typedef mtree_ref_counter ref_counter; static void unpack(disk_type const &disk, value_type &value); static void pack(value_type const &value, disk_type &disk); }; //-------------------------------- class damage_visitor; struct damage { virtual ~damage() {} virtual void visit(damage_visitor &v) const = 0; }; struct missing_devices : public damage { missing_devices(std::string const &desc, run const &keys); virtual void visit(damage_visitor &v) const; std::string desc_; run keys_; }; struct missing_mappings : public damage { missing_mappings(std::string const &desc, uint64_t thin_dev, run const &keys); virtual void visit(damage_visitor &v) const; std::string desc_; uint64_t thin_dev_; run keys_; }; class damage_visitor { public: typedef std::shared_ptr ptr; virtual ~damage_visitor() {} void visit(damage const &d) { d.visit(*this); } virtual void visit(missing_devices const &d) = 0; virtual void visit(missing_mappings const &d) = 0; }; class mapping_visitor { public: virtual ~mapping_visitor() {} // path contains 2 elements, the dev key, then the oblock virtual void visit(btree_path const &path, block_time const &m) = 0; }; class device_visitor { public: virtual ~device_visitor() {} virtual void visit(btree_path const &path, block_address dtree_root) = 0; }; } typedef persistent_data::btree<2, mapping_tree_detail::block_traits> mapping_tree; typedef persistent_data::btree<1, mapping_tree_detail::mtree_traits> dev_tree; typedef persistent_data::btree<1, mapping_tree_detail::block_traits> single_mapping_tree; void walk_mapping_tree(dev_tree const &tree, mapping_tree_detail::device_visitor &dev_v, mapping_tree_detail::damage_visitor &dv, bool ignore_non_fatal = false); void walk_mapping_tree(mapping_tree const &tree, mapping_tree_detail::mapping_visitor &mv, mapping_tree_detail::damage_visitor &dv, bool ignore_non_fatal = false); void 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 = false); void check_mapping_tree(single_mapping_tree const &tree, uint64_t dev_id, mapping_tree_detail::damage_visitor &visitor, bool ignore_non_fatal = false); void check_mapping_tree(dev_tree const &tree, mapping_tree_detail::damage_visitor &visitor, bool ignore_non_fatal = false); void check_mapping_tree(mapping_tree const &tree, mapping_tree_detail::damage_visitor &visitor, bool ignore_non_fatal = false); } //---------------------------------------------------------------- #endif