thin dump now does something useful
This commit is contained in:
parent
16539b59ff
commit
d255180e37
2
Makefile
2
Makefile
@ -7,7 +7,9 @@ SOURCE=\
|
||||
endian_utils.cc \
|
||||
error_set.cc \
|
||||
hex_dump.cc \
|
||||
human_readable_format.cc \
|
||||
metadata.cc \
|
||||
metadata_dump.cc \
|
||||
metadata_disk_structures.cc \
|
||||
space_map_disk.cc \
|
||||
transaction_manager.cc
|
||||
|
@ -57,7 +57,8 @@ block_manager<BlockSize>::block_manager(std::string const &path, block_address n
|
||||
superblock_count_(0),
|
||||
ordinary_count_(0)
|
||||
{
|
||||
fd_ = ::open(path.c_str(), O_RDWR | O_CREAT, 0666);
|
||||
//fd_ = ::open(path.c_str(), O_RDWR | O_CREAT, 0666);
|
||||
fd_ = ::open(path.c_str(), O_RDONLY, 0666);
|
||||
if (fd_ < 0)
|
||||
throw std::runtime_error("couldn't open file");
|
||||
}
|
||||
|
10
btree.h
10
btree.h
@ -332,12 +332,14 @@ namespace persistent_data {
|
||||
|
||||
// The bool return values indicate whether the walk
|
||||
// should be continued into sub trees of the node (true == continue).
|
||||
virtual bool visit_internal(unsigned level, boost::optional<uint64_t> key,
|
||||
virtual bool visit_internal(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
internal_node const &n) = 0;
|
||||
virtual bool visit_internal_leaf(unsigned level, boost::optional<uint64_t> key,
|
||||
virtual bool visit_internal_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
internal_node const &n) = 0;
|
||||
virtual bool visit_leaf(unsigned level, boost::optional<uint64_t> key,
|
||||
virtual bool visit_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
leaf_node const &n) = 0;
|
||||
|
||||
virtual void visit_complete() {}
|
||||
};
|
||||
|
||||
// Walks the tree in depth first order
|
||||
@ -366,7 +368,7 @@ namespace persistent_data {
|
||||
int *index);
|
||||
|
||||
void walk_tree(typename visitor::ptr visitor,
|
||||
unsigned level, boost::optional<uint64_t> key,
|
||||
unsigned level, bool root, boost::optional<uint64_t> key,
|
||||
block_address b) const;
|
||||
|
||||
typename persistent_data::transaction_manager::ptr tm_;
|
||||
|
16
btree.tcc
16
btree.tcc
@ -599,14 +599,16 @@ template <unsigned Levels, typename ValueTraits>
|
||||
void
|
||||
btree<Levels, ValueTraits>::visit(typename visitor::ptr visitor) const
|
||||
{
|
||||
walk_tree(visitor, 0, boost::optional<uint64_t>(), root_);
|
||||
walk_tree(visitor, 0, true, boost::optional<uint64_t>(), root_);
|
||||
visitor->visit_complete();
|
||||
}
|
||||
|
||||
template <unsigned Levels, typename ValueTraits>
|
||||
void
|
||||
btree<Levels, ValueTraits>::
|
||||
walk_tree(typename visitor::ptr visitor,
|
||||
unsigned level, boost::optional<uint64_t> key,
|
||||
unsigned level, bool sub_root,
|
||||
boost::optional<uint64_t> key,
|
||||
block_address b) const
|
||||
{
|
||||
using namespace btree_detail;
|
||||
@ -614,18 +616,18 @@ walk_tree(typename visitor::ptr visitor,
|
||||
read_ref blk = tm_->read_lock(b);
|
||||
internal_node o = to_node<uint64_traits>(blk);
|
||||
if (o.get_type() == INTERNAL) {
|
||||
if (visitor->visit_internal(level, key, o))
|
||||
if (visitor->visit_internal(level, sub_root, key, o))
|
||||
for (unsigned i = 0; i < o.get_nr_entries(); i++)
|
||||
walk_tree(visitor, level, o.key_at(i), o.value_at(i));
|
||||
walk_tree(visitor, level, false, o.key_at(i), o.value_at(i));
|
||||
|
||||
} else if (level < Levels - 1) {
|
||||
if (visitor->visit_internal_leaf(level, key, o))
|
||||
if (visitor->visit_internal_leaf(level, sub_root, key, o))
|
||||
for (unsigned i = 0; i < o.get_nr_entries(); i++)
|
||||
walk_tree(visitor, level + 1, boost::optional<uint64_t>(), o.value_at(i));
|
||||
walk_tree(visitor, level + 1, true, boost::optional<uint64_t>(o.key_at(i)), o.value_at(i));
|
||||
|
||||
} else {
|
||||
leaf_node ov = to_node<ValueTraits>(blk);
|
||||
visitor->visit_leaf(level, key, ov);
|
||||
visitor->visit_leaf(level, sub_root, key, ov);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ namespace persistent_data {
|
||||
}
|
||||
|
||||
bool visit_internal(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
if (already_visited(n))
|
||||
@ -94,6 +95,7 @@ namespace persistent_data {
|
||||
}
|
||||
|
||||
bool visit_internal_leaf(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
if (already_visited(n))
|
||||
@ -115,6 +117,7 @@ namespace persistent_data {
|
||||
}
|
||||
|
||||
bool visit_leaf(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<ValueTraits> const &n) {
|
||||
if (already_visited(n))
|
||||
|
53
emitter.h
Normal file
53
emitter.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef EMITTER_H
|
||||
#define EMITTER_H
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace thin_provisioning {
|
||||
|
||||
//------------------------------------------------
|
||||
// Here's a little grammar for how this all hangs together:
|
||||
//
|
||||
// superblock := <uuid> <time> <trans_id> <data_block_size> device*
|
||||
// device := <dev id> <transaction id> <creation time> <snap time> <binding>
|
||||
// binding := (<identifier> | <mapping>)*
|
||||
// mapping := range_map | single_map
|
||||
// range_map := <origin_begin> <origin_end> <data_begin>
|
||||
// single_map := <origin> <data>
|
||||
// named_mapping := <identifier> <mapping>
|
||||
//------------------------------------------------
|
||||
class emitter {
|
||||
public:
|
||||
typedef boost::shared_ptr<emitter> ptr;
|
||||
|
||||
virtual ~emitter() {}
|
||||
|
||||
virtual void begin_superblock(std::string const &uuid,
|
||||
uint64_t time,
|
||||
uint64_t trans_id,
|
||||
uint32_t data_block_size) = 0;
|
||||
virtual void end_superblock() = 0;
|
||||
|
||||
virtual void begin_device(uint32_t dev_id,
|
||||
uint64_t mapped_blocks,
|
||||
uint64_t trans_id,
|
||||
uint64_t creation_time,
|
||||
uint64_t snap_time) = 0;
|
||||
virtual void end_device() = 0;
|
||||
|
||||
virtual void begin_named_mapping(std::string const &name) = 0;
|
||||
virtual void end_named_mapping() = 0;
|
||||
|
||||
virtual void identifier(std::string const &name) = 0;
|
||||
virtual void range_map(uint64_t origin_begin, uint64_t data_begin, uint64_t len) = 0;
|
||||
virtual void single_map(uint64_t origin_block, uint64_t ddata_block) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
89
human_readable_format.cc
Normal file
89
human_readable_format.cc
Normal file
@ -0,0 +1,89 @@
|
||||
#include "human_readable_format.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace thin_provisioning;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
class hr_emitter : public emitter {
|
||||
public:
|
||||
hr_emitter(ostream &out)
|
||||
: out_(out) {
|
||||
}
|
||||
|
||||
void begin_superblock(string const &uuid,
|
||||
uint64_t time,
|
||||
uint64_t trans_id,
|
||||
uint32_t data_block_size) {
|
||||
out_ << "begin superblock: " << uuid
|
||||
<< ", " << time
|
||||
<< ", " << trans_id
|
||||
<< ", " << data_block_size
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void end_superblock() {
|
||||
out_ << "end superblock" << endl;
|
||||
}
|
||||
|
||||
void begin_device(uint32_t dev_id,
|
||||
uint64_t mapped_blocks,
|
||||
uint64_t trans_id,
|
||||
uint64_t creation_time,
|
||||
uint64_t snap_time) {
|
||||
out_ << "device: " << dev_id << endl
|
||||
<< "mapped_blocks: " << mapped_blocks << endl
|
||||
<< "transaction: " << trans_id << endl
|
||||
<< "creation time: " << creation_time << endl
|
||||
<< "snap time: " << snap_time << endl;
|
||||
}
|
||||
|
||||
void end_device() {
|
||||
out_ << endl;
|
||||
}
|
||||
|
||||
void begin_named_mapping(string const &name) {
|
||||
out_ << "begin named mapping"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void end_named_mapping() {
|
||||
out_ << "end named mapping"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void identifier(string const &name) {
|
||||
out_ << "identifier: " << name << endl;
|
||||
}
|
||||
|
||||
void range_map(uint64_t origin_begin, uint64_t data_begin, uint64_t len) {
|
||||
out_ << " (" << origin_begin
|
||||
<< ".." << origin_begin + len - 1
|
||||
<< ") -> (" << data_begin
|
||||
<< ".." << data_begin + len - 1
|
||||
<< ")" << endl;
|
||||
}
|
||||
|
||||
void single_map(uint64_t origin_block, uint64_t data_block) {
|
||||
out_ << " " << origin_block
|
||||
<< " -> " << data_block
|
||||
<< endl;
|
||||
}
|
||||
|
||||
private:
|
||||
ostream &out_;
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
thin_provisioning::emitter::ptr
|
||||
thin_provisioning::create_human_readable_emitter(ostream &out)
|
||||
{
|
||||
return emitter::ptr(new hr_emitter(out));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
16
human_readable_format.h
Normal file
16
human_readable_format.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef HUMAN_READABLE_H
|
||||
#define HUMAN_READABLE_H
|
||||
|
||||
#include "emitter.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace thin_provisioning {
|
||||
emitter::ptr create_human_readable_emitter(std::ostream &out);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
@ -105,10 +105,11 @@ namespace {
|
||||
// Sharing can only occur in level 1 nodes.
|
||||
// FIXME: not true once we start having held roots.
|
||||
bool visit_internal_leaf(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
|
||||
bool r = btree_checker<2, block_traits>::visit_internal_leaf(level, key, n);
|
||||
bool r = btree_checker<2, block_traits>::visit_internal_leaf(level, sub_root, key, n);
|
||||
if (!r && level == 0) {
|
||||
throw runtime_error("unexpected sharing in level 0 of mapping tree.");
|
||||
}
|
||||
@ -120,9 +121,10 @@ namespace {
|
||||
}
|
||||
|
||||
bool visit_leaf(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<block_traits> const &n) {
|
||||
bool r = btree_checker<2, block_traits>::visit_leaf(level, key, n);
|
||||
bool r = btree_checker<2, block_traits>::visit_leaf(level, sub_root, key, n);
|
||||
|
||||
if (r)
|
||||
for (unsigned i = 0; i < n.get_nr_entries(); i++)
|
||||
@ -149,9 +151,10 @@ namespace {
|
||||
}
|
||||
|
||||
bool visit_leaf(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<device_details_traits> const &n) {
|
||||
bool r = btree_checker<1, device_details_traits>::visit_leaf(level, key, n);
|
||||
bool r = btree_checker<1, device_details_traits>::visit_leaf(level, sub_root, key, n);
|
||||
|
||||
if (r)
|
||||
for (unsigned i = 0; i < n.get_nr_entries(); i++)
|
||||
|
153
metadata_dump.cc
Normal file
153
metadata_dump.cc
Normal file
@ -0,0 +1,153 @@
|
||||
#include "metadata.h"
|
||||
|
||||
#include "human_readable_format.h"
|
||||
|
||||
using namespace persistent_data;
|
||||
using namespace thin_provisioning;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
class mappings_extractor : public btree<2, block_traits>::visitor {
|
||||
public:
|
||||
typedef boost::shared_ptr<mappings_extractor> ptr;
|
||||
|
||||
mappings_extractor(uint64_t dev_id, emitter::ptr e,
|
||||
space_map::ptr md_sm, space_map::ptr data_sm)
|
||||
: dev_id_(dev_id),
|
||||
e_(e),
|
||||
md_sm_(md_sm),
|
||||
data_sm_(data_sm),
|
||||
in_range_(false) {
|
||||
}
|
||||
|
||||
bool visit_internal(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
return (sub_root && key) ? (*key == dev_id_) : true;
|
||||
}
|
||||
|
||||
bool visit_internal_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> maybe_key,
|
||||
btree_detail::node_ref<block_traits> const &n) {
|
||||
for (unsigned i = 0; i < n.get_nr_entries(); i++) {
|
||||
add_mapping(n.key_at(i), n.value_at(i).block_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void visit_complete() {
|
||||
end_mapping();
|
||||
}
|
||||
|
||||
private:
|
||||
void start_mapping(uint64_t origin_block, uint64_t dest_block) {
|
||||
origin_start_ = origin_block;
|
||||
dest_start_ = dest_block;
|
||||
len_ = 1;
|
||||
in_range_ = true;
|
||||
}
|
||||
|
||||
void end_mapping() {
|
||||
if (in_range_) {
|
||||
if (len_ == 1)
|
||||
e_->single_map(origin_start_, dest_start_);
|
||||
else
|
||||
e_->range_map(origin_start_, dest_start_, len_);
|
||||
|
||||
in_range_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void add_mapping(uint64_t origin_block, uint64_t dest_block) {
|
||||
if (!in_range_)
|
||||
start_mapping(origin_block, dest_block);
|
||||
|
||||
else if (origin_block == origin_start_ + len_ &&
|
||||
dest_block == dest_start_ + len_)
|
||||
len_++;
|
||||
|
||||
else {
|
||||
end_mapping();
|
||||
start_mapping(origin_block, dest_block);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t dev_id_;
|
||||
emitter::ptr e_;
|
||||
space_map::ptr md_sm_;
|
||||
space_map::ptr data_sm_;
|
||||
|
||||
bool in_range_;
|
||||
uint64_t origin_start_, dest_start_, len_;
|
||||
|
||||
};
|
||||
|
||||
class details_extractor : public btree<1, device_details_traits>::visitor {
|
||||
public:
|
||||
typedef boost::shared_ptr<details_extractor> ptr;
|
||||
|
||||
details_extractor() {
|
||||
}
|
||||
|
||||
bool visit_internal(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_internal_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> key,
|
||||
btree_detail::node_ref<uint64_traits> const &n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> maybe_key,
|
||||
btree_detail::node_ref<device_details_traits> const &n) {
|
||||
for (unsigned i = 0; i < n.get_nr_entries(); i++)
|
||||
devices_.insert(make_pair(n.key_at(i), n.value_at(i)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
map<uint64_t, device_details> const &get_devices() const {
|
||||
return devices_;
|
||||
}
|
||||
|
||||
private:
|
||||
map<uint64_t, device_details> devices_;
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
metadata::dump()
|
||||
{
|
||||
emitter::ptr e = create_human_readable_emitter(cout);
|
||||
|
||||
details_extractor::ptr de(new details_extractor);
|
||||
|
||||
details_.visit(de);
|
||||
map<uint64_t, device_details> const &devs = de->get_devices();
|
||||
|
||||
map<uint64_t, device_details>::const_iterator it, end = devs.end();
|
||||
for (it = devs.begin(); it != end; ++it) {
|
||||
uint64_t dev_id = it->first;
|
||||
device_details const &dd = it->second;
|
||||
|
||||
e->begin_device(dev_id,
|
||||
dd.mapped_blocks_,
|
||||
dd.transaction_id_,
|
||||
dd.creation_time_,
|
||||
dd.snapshotted_time_);
|
||||
|
||||
mappings_extractor::ptr me(new mappings_extractor(dev_id, e, metadata_sm_, data_sm_));
|
||||
mappings_.visit(me);
|
||||
|
||||
e->end_device();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
@ -321,9 +321,10 @@ namespace {
|
||||
}
|
||||
|
||||
bool visit_leaf(unsigned level,
|
||||
bool sub_root,
|
||||
optional<uint64_t> key,
|
||||
btree_detail::node_ref<index_entry_traits> const &n) {
|
||||
bool r = btree_checker<1, index_entry_traits>::visit_leaf(level, key, n);
|
||||
bool r = btree_checker<1, index_entry_traits>::visit_leaf(level, sub_root, key, n);
|
||||
if (!r)
|
||||
return r;
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace {
|
||||
void dump(string const &path) {
|
||||
metadata md(path);
|
||||
//human_readable::ptr emitter(new human_readable);
|
||||
// md.dump();
|
||||
md.dump();
|
||||
}
|
||||
|
||||
void usage(string const &cmd) {
|
||||
|
Loading…
Reference in New Issue
Block a user