#include #include #include "damage_generator.h" using namespace thin_provisioning; //---------------------------------------------------------------- namespace { void find_blocks(space_map::ptr sm, block_address nr_blocks, ref_t expected, std::set &found) { block_address sm_size = sm->get_nr_blocks(); base::run_set visited; block_address nr_visited = 0; uint64_t rand_seed(std::chrono::high_resolution_clock::now().time_since_epoch().count()); std::mt19937 rand_engine(rand_seed); while (nr_blocks) { if (nr_visited == sm_size) break; block_address b = rand_engine() % sm_size; if (visited.member(b)) continue; ref_t c = sm->get_count(b); if (c == expected) { found.insert(b); --nr_blocks; } visited.add(b); ++nr_visited; } if (nr_blocks) { ostringstream out; out << "cannot find " << (nr_blocks + found.size()) << " blocks of ref-count " << expected; throw runtime_error(out.str()); } } } //---------------------------------------------------------------- damage_generator::damage_generator(block_manager::ptr bm) { md_ = metadata::ptr(new metadata(bm, true)); } void damage_generator::commit() { md_->commit(); } void damage_generator::create_metadata_leaks(block_address nr_leaks, ref_t expected, ref_t actual) { std::set leaks; find_blocks(md_->metadata_sm_, nr_leaks, expected, leaks); for (auto const &b : leaks) md_->metadata_sm_->set_count(b, actual); } //----------------------------------------------------------------