diff --git a/caching/metadata.cc b/caching/metadata.cc index 5985080..f9c02f2 100644 --- a/caching/metadata.cc +++ b/caching/metadata.cc @@ -1,17 +1,80 @@ #include "caching/metadata.h" +#include "persistent-data/space-maps/core.h" using namespace caching; //---------------------------------------------------------------- -metadata::metadata(block_manager<>::ptr bm, open_type ot) -{ +namespace { + using namespace superblock_detail; -} + unsigned const METADATA_CACHE_SIZE = 1024; -metadata::metadata(block_manager<>::ptr bm, block_address metadata_snap) -{ + // FIXME: duplication + transaction_manager::ptr + open_tm(block_manager<>::ptr bm) { + space_map::ptr sm(new core_map(bm->get_nr_blocks())); + sm->inc(SUPERBLOCK_LOCATION); + transaction_manager::ptr tm(new transaction_manager(bm, sm)); + return tm; + } + void + copy_space_maps(space_map::ptr lhs, space_map::ptr rhs) { + for (block_address b = 0; b < rhs->get_nr_blocks(); b++) { + uint32_t count = rhs->get_count(b); + if (count > 0) + lhs->set_count(b, rhs->get_count(b)); + } + } + + void init_superblock(superblock &sb) { +#if 0 + sb.magic_ = SUPERBLOCK_MAGIC; + sb.version_ = 1; + sb.data_mapping_root_ = mappings_->get_root(); + sb.device_details_root_ = details_->get_root(); + sb.data_block_size_ = data_block_size; + sb.metadata_block_size_ = MD_BLOCK_SIZE; + sb.metadata_nr_blocks_ = tm_->get_bm()->get_nr_blocks(); +#endif + } +} + +//---------------------------------------------------------------- + +metadata::metadata(block_manager<>::ptr bm, open_type ot) +{ + switch (ot) { + case OPEN: + throw runtime_error("not implemented"); + break; + + case CREATE: + tm_ = open_tm(bm); + space_map::ptr core = tm_->get_sm(); + metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); + copy_space_maps(metadata_sm_, core); + tm_->set_sm(metadata_sm_); + + mappings_ = mapping_array::ptr(new mapping_array(tm_, mapping_array::ref_counter())); +// hints_ = hint_array::ptr(new hint_array(tm_)); + + ::memset(&sb_, 0, sizeof(sb_)); + init_superblock(sb_); + } +} + +void +metadata::commit() +{ + metadata_sm_->commit(); + metadata_sm_->copy_root(&sb_.metadata_space_map_root, sizeof(sb_.metadata_space_map_root)); + sb_.mapping_root = mappings_->get_root(); + + write_ref superblock = tm_->get_bm()->superblock_zero(SUPERBLOCK_LOCATION, superblock_validator()); + superblock_disk *disk = reinterpret_cast(superblock.data().raw()); + superblock_traits::pack(sb_, *disk); } //---------------------------------------------------------------- diff --git a/caching/metadata.h b/caching/metadata.h index e94bea2..7b956a5 100644 --- a/caching/metadata.h +++ b/caching/metadata.h @@ -26,7 +26,8 @@ namespace caching { typedef boost::shared_ptr ptr; metadata(block_manager<>::ptr bm, open_type ot); - metadata(block_manager<>::ptr bm, block_address metadata_snap); + + void commit(); typedef persistent_data::transaction_manager tm; tm::ptr tm_; diff --git a/caching/restore_emitter.cc b/caching/restore_emitter.cc index 499f13b..efca1de 100644 --- a/caching/restore_emitter.cc +++ b/caching/restore_emitter.cc @@ -12,27 +12,70 @@ namespace { class restorer : public emitter { public: restorer(metadata::ptr md) - : md_(md) { + : in_superblock_(false), + md_(md) { + } + + virtual ~restorer() { } virtual void begin_superblock(std::string const &uuid, pd::block_address block_size, pd::block_address nr_cache_blocks, std::string const &policy) { + + superblock &sb = md_->sb_; + + sb.flags = 0; + memset(sb.uuid, 0, sizeof(sb.uuid)); + sb.magic = caching::superblock_detail::SUPERBLOCK_MAGIC; + sb.version = 0; // FIXME: fix + // strncpy(sb.policy_name, policy.c_str(), sizeof(sb.policy_name)); + memset(sb.policy_version, 0, sizeof(sb.policy_version)); + sb.policy_hint_size = 0; // FIXME: fix + + memset(sb.metadata_space_map_root, 0, sizeof(sb.metadata_space_map_root)); + sb.mapping_root = 0; + sb.hint_root = 0; + + sb.discard_root = 0; + sb.discard_block_size = 0; + sb.discard_nr_blocks = 0; + + sb.data_block_size = block_size; + sb.metadata_block_size = 0; + sb.cache_blocks = nr_cache_blocks; + + sb.compat_flags = 0; + sb.compat_ro_flags = 0; + sb.incompat_flags = 0; + + sb.read_hits = 0; + sb.read_misses = 0; + sb.write_hits = 0; + sb.write_misses = 0; } virtual void end_superblock() { + md_->commit(); } virtual void begin_mappings() { + // noop } virtual void end_mappings() { + // noop } virtual void mapping(pd::block_address cblock, pd::block_address oblock, bool dirty) { + mapping_array_detail::mapping m; + m.oblock_ = oblock; + m.flags_ = 0; + + md_->mappings_->set(cblock, m); } virtual void begin_hints() { @@ -46,6 +89,7 @@ namespace { } private: + bool in_superblock_; metadata::ptr md_; }; } diff --git a/persistent-data/data-structures/array.h b/persistent-data/data-structures/array.h index f69d627..9b4c9bd 100644 --- a/persistent-data/data-structures/array.h +++ b/persistent-data/data-structures/array.h @@ -128,9 +128,9 @@ namespace persistent_data { typedef boost::shared_ptr > ptr; typedef typename ValueTraits::value_type value_type; + typedef typename ValueTraits::ref_counter ref_counter; - array(tm_ptr tm, - typename ValueTraits::ref_counter rc) + array(tm_ptr tm, ref_counter rc) : tm_(tm), entries_per_block_(rblock::calc_max_entries()), nr_entries_(0), @@ -140,8 +140,7 @@ namespace persistent_data { validator_(new block_manager<>::noop_validator()) { } - array(tm_ptr tm, - typename ValueTraits::ref_counter rc, + array(tm_ptr tm, ref_counter rc, block_address root, unsigned nr_entries) : tm_(tm),