[thin_show_metadata] ncurses render
This commit is contained in:
parent
c4215c0cf6
commit
e78de5d3ad
@ -106,7 +106,8 @@ SOURCE=\
|
||||
DEVTOOLS_SOURCE=\
|
||||
thin-provisioning/thin_generate_metadata.cc \
|
||||
thin-provisioning/variable_chunk_stream.cc \
|
||||
thin-provisioning/thin_show_metadata.cc
|
||||
thin-provisioning/thin_show_metadata.cc \
|
||||
ui/ui.cc
|
||||
|
||||
ifeq ("@DEVTOOLS@", "yes")
|
||||
SOURCE+=$(DEVTOOLS_SOURCE)
|
||||
@ -133,6 +134,10 @@ CXXFLAGS+=@LFS_FLAGS@
|
||||
INCLUDES+=-I$(TOP_BUILDDIR) -I$(TOP_DIR) -I$(TOP_DIR)/thin-provisioning
|
||||
LIBS:=-laio -lexpat
|
||||
|
||||
ifeq ("@DEVTOOLS@", "yes")
|
||||
LIBS+=-lncurses
|
||||
endif
|
||||
|
||||
ifeq ("@STATIC_CXX@", "yes")
|
||||
CXXLIB+=-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -Wl,--as-needed
|
||||
else
|
||||
|
@ -146,22 +146,32 @@ namespace thin_provisioning {
|
||||
}
|
||||
}
|
||||
|
||||
superblock_detail::superblock read_superblock(block_manager<>::ptr bm, block_address location)
|
||||
superblock_detail::superblock read_superblock(block_manager<> const &bm, block_address location)
|
||||
{
|
||||
using namespace superblock_detail;
|
||||
|
||||
superblock sb;
|
||||
block_manager<>::read_ref r = bm->read_lock(location, superblock_validator());
|
||||
block_manager<>::read_ref r = bm.read_lock(location, superblock_validator());
|
||||
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(r.data());
|
||||
superblock_traits::unpack(*sbd, sb);
|
||||
return sb;
|
||||
}
|
||||
|
||||
superblock_detail::superblock read_superblock(block_manager<>::ptr bm, block_address location)
|
||||
{
|
||||
return read_superblock(*bm, location);
|
||||
}
|
||||
|
||||
superblock_detail::superblock read_superblock(block_manager<>::ptr bm)
|
||||
{
|
||||
return read_superblock(bm, SUPERBLOCK_LOCATION);
|
||||
}
|
||||
|
||||
superblock_detail::superblock read_superblock(block_manager<> const &bm)
|
||||
{
|
||||
return read_superblock(bm, SUPERBLOCK_LOCATION);
|
||||
}
|
||||
|
||||
void write_superblock(block_manager<>::ptr bm, superblock_detail::superblock const &sb)
|
||||
{
|
||||
block_manager<>::write_ref w = bm->write_lock(SUPERBLOCK_LOCATION, superblock_validator());
|
||||
|
@ -128,6 +128,8 @@ namespace thin_provisioning {
|
||||
|
||||
// FIXME: should we put init_superblock in here too?
|
||||
|
||||
// FIXME: make the bm const, and pass by reference rather than ptr
|
||||
superblock_detail::superblock read_superblock(persistent_data::block_manager<> const &bm);
|
||||
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm);
|
||||
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm,
|
||||
persistent_data::block_address location);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "thin-provisioning/commands.h"
|
||||
#include "thin-provisioning/metadata.h"
|
||||
#include "thin-provisioning/superblock.h"
|
||||
#include "ui/ui.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <iostream>
|
||||
@ -12,82 +13,282 @@
|
||||
#include <libgen.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
using namespace persistent_data;
|
||||
using namespace sm_disk_detail;
|
||||
using namespace std;
|
||||
using namespace thin_provisioning;
|
||||
using namespace ui;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
bool is_superblock(block_manager<>::read_ref &rr) {
|
||||
using namespace superblock_detail;
|
||||
class examiner {
|
||||
public:
|
||||
examiner(string const &name, int colour_pair, char rep)
|
||||
: name_(name),
|
||||
colour_pair_(colour_pair),
|
||||
rep_(rep) {
|
||||
}
|
||||
|
||||
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(rr.data());
|
||||
if (to_cpu<uint64_t>(sbd->magic_) == SUPERBLOCK_MAGIC) {
|
||||
superblock sb;
|
||||
superblock_traits::unpack(*sbd, sb);
|
||||
cout << "metadata nr blocks: " << sb.metadata_nr_blocks_ << endl;
|
||||
virtual ~examiner() {}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const = 0;
|
||||
// virtual void render_block(text_ui &ui, block_manager<>::read_ref rr) = 0;
|
||||
|
||||
string const &get_name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
int get_color_pair() const {
|
||||
return colour_pair_;
|
||||
}
|
||||
|
||||
char get_rep() const {
|
||||
return rep_;
|
||||
}
|
||||
|
||||
private:
|
||||
string name_;
|
||||
int colour_pair_;
|
||||
char rep_;
|
||||
};
|
||||
|
||||
class raw_examiner : public examiner {
|
||||
public:
|
||||
raw_examiner()
|
||||
: examiner("raw", 5, '?') {
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_bitmap_block(block_manager<>::read_ref &rr) {
|
||||
bitmap_header const *data = reinterpret_cast<bitmap_header const *>(rr.data());
|
||||
crc32c sum(BITMAP_CSUM_XOR);
|
||||
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||
return sum.get_sum() == to_cpu<uint32_t>(data->csum);
|
||||
}
|
||||
|
||||
bool is_index_block(block_manager<>::read_ref &rr) {
|
||||
metadata_index const *mi = reinterpret_cast<metadata_index const *>(rr.data());
|
||||
crc32c sum(INDEX_CSUM_XOR);
|
||||
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||
return sum.get_sum() == to_cpu<uint32_t>(mi->csum_);
|
||||
}
|
||||
|
||||
bool is_btree_node(block_manager<>::read_ref &rr) {
|
||||
using namespace btree_detail;
|
||||
|
||||
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
||||
node_header const *n = &data->header;
|
||||
crc32c sum(BTREE_CSUM_XOR);
|
||||
sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||
return sum.get_sum() == to_cpu<uint32_t>(n->csum);
|
||||
}
|
||||
|
||||
void show_blocks(string const &dev) {
|
||||
block_manager<>::ptr bm = open_bm(dev, block_manager<>::READ_ONLY);
|
||||
|
||||
metadata md(bm, metadata::OPEN);
|
||||
cout << "Metadata space map: nr_blocks = " << md.metadata_sm_->get_nr_blocks()
|
||||
<< ", nr_free_blocks = " << md.metadata_sm_->get_nr_free()
|
||||
<< endl;
|
||||
cout << "Data space map: nr_blocks = " << md.data_sm_->get_nr_blocks()
|
||||
<< ", nr_free_blocks = " << md.data_sm_->get_nr_free()
|
||||
<< endl;
|
||||
|
||||
block_address nr_blocks = bm->get_nr_blocks();
|
||||
for (block_address b = 0; b < nr_blocks; b++) {
|
||||
block_manager<>::read_ref rr = bm->read_lock(b);
|
||||
|
||||
if (is_superblock(rr))
|
||||
cout << b << ": superblock" << endl;
|
||||
|
||||
else if (is_bitmap_block(rr))
|
||||
cout << b << ": bitmap block" << endl;
|
||||
|
||||
else if (is_btree_node(rr))
|
||||
cout << b << ": btree_node" << endl;
|
||||
|
||||
else
|
||||
cout << b << ": unknown" << endl;
|
||||
class superblock_examiner : public examiner {
|
||||
public:
|
||||
superblock_examiner()
|
||||
: examiner("superblock", 1, 'S') {
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
using namespace superblock_detail;
|
||||
|
||||
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(rr.data());
|
||||
if (to_cpu<uint64_t>(sbd->magic_) == SUPERBLOCK_MAGIC) {
|
||||
superblock sb;
|
||||
superblock_traits::unpack(*sbd, sb);
|
||||
cout << "metadata nr blocks: " << sb.metadata_nr_blocks_ << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class bitmap_examiner : public examiner {
|
||||
public:
|
||||
bitmap_examiner()
|
||||
: examiner("bitmap", 2, ':') {
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
bitmap_header const *data = reinterpret_cast<bitmap_header const *>(rr.data());
|
||||
crc32c sum(BITMAP_CSUM_XOR);
|
||||
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||
return sum.get_sum() == to_cpu<uint32_t>(data->csum);
|
||||
}
|
||||
};
|
||||
|
||||
class index_examiner : public examiner {
|
||||
public:
|
||||
index_examiner()
|
||||
: examiner("index", 3, 'i') {
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
metadata_index const *mi = reinterpret_cast<metadata_index const *>(rr.data());
|
||||
crc32c sum(INDEX_CSUM_XOR);
|
||||
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||
return sum.get_sum() == to_cpu<uint32_t>(mi->csum_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class btree_examiner : public examiner {
|
||||
public:
|
||||
btree_examiner(string const &name, int colour_pair, char c)
|
||||
: examiner(name, colour_pair, c) {
|
||||
}
|
||||
|
||||
bool is_btree_node(block_manager<>::read_ref rr) const {
|
||||
using namespace btree_detail;
|
||||
|
||||
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
||||
node_header const *n = &data->header;
|
||||
crc32c sum(BTREE_CSUM_XOR);
|
||||
sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||
return sum.get_sum() == to_cpu<uint32_t>(n->csum);
|
||||
}
|
||||
};
|
||||
|
||||
class dev_detail_examiner : public btree_examiner {
|
||||
public:
|
||||
dev_detail_examiner()
|
||||
: btree_examiner("dev_details", 4, 'd') {
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
if (!btree_examiner::is_btree_node(rr))
|
||||
return false;
|
||||
|
||||
using namespace btree_detail;
|
||||
|
||||
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
||||
node_header const *n = &data->header;
|
||||
return to_cpu<uint32_t>(n->value_size) == sizeof(device_tree_detail::device_details_disk);
|
||||
}
|
||||
};
|
||||
|
||||
class ref_count_examiner : public btree_examiner {
|
||||
public:
|
||||
ref_count_examiner()
|
||||
: btree_examiner("ref_count node", 6, 'r') {
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
if (!btree_examiner::is_btree_node(rr))
|
||||
return false;
|
||||
|
||||
using namespace btree_detail;
|
||||
|
||||
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
||||
node_header const *n = &data->header;
|
||||
return to_cpu<uint32_t>(n->value_size) == sizeof(uint32_t);
|
||||
}
|
||||
};
|
||||
|
||||
class mapping_examiner : public btree_examiner {
|
||||
public:
|
||||
mapping_examiner()
|
||||
: btree_examiner("mapping node", 7, 'm') {
|
||||
}
|
||||
|
||||
virtual bool recognise(block_manager<>::read_ref rr) const {
|
||||
if (!btree_examiner::is_btree_node(rr))
|
||||
return false;
|
||||
|
||||
using namespace btree_detail;
|
||||
|
||||
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
||||
node_header const *n = &data->header;
|
||||
return to_cpu<uint32_t>(n->value_size) == sizeof(uint64_t);
|
||||
}
|
||||
};
|
||||
|
||||
class main_dialog {
|
||||
public:
|
||||
main_dialog(text_ui &ui,
|
||||
block_manager<> const &bm)
|
||||
: ui_(ui),
|
||||
bm_(bm),
|
||||
raw_examiner_(new raw_examiner()) {
|
||||
|
||||
examiners_.push_back(shared_ptr<examiner>(new superblock_examiner()));
|
||||
examiners_.push_back(shared_ptr<examiner>(new bitmap_examiner()));
|
||||
examiners_.push_back(shared_ptr<examiner>(new index_examiner()));
|
||||
examiners_.push_back(shared_ptr<examiner>(new dev_detail_examiner()));
|
||||
examiners_.push_back(shared_ptr<examiner>(new ref_count_examiner()));
|
||||
examiners_.push_back(shared_ptr<examiner>(new mapping_examiner()));
|
||||
}
|
||||
|
||||
void run() {
|
||||
auto line_length = 80;
|
||||
for (block_address b = 0; b < 2000; b++) {
|
||||
block_manager<>::read_ref rr = bm_.read_lock(b);
|
||||
|
||||
if (!(b % line_length)) {
|
||||
if (b > 0)
|
||||
printw("\n");
|
||||
|
||||
printw("%8llu: ", b);
|
||||
}
|
||||
|
||||
auto e = find_examiner(rr);
|
||||
attron(COLOR_PAIR(e->get_color_pair()));
|
||||
printw("%c", e->get_rep());
|
||||
attroff(COLOR_PAIR(e->get_color_pair()));
|
||||
}
|
||||
|
||||
printw("\n");
|
||||
show_superblock();
|
||||
}
|
||||
|
||||
private:
|
||||
void show_superblock() {
|
||||
auto sb = read_superblock(bm_);
|
||||
|
||||
printw("\n\nSuperblock at 0\n");
|
||||
printw("data mapping root: %llu\n", sb.data_mapping_root_);
|
||||
printw("device details root: %llu\n", sb.device_details_root_);
|
||||
printw("data block size: %u\n", sb.data_block_size_);
|
||||
printw("metadata nr blocks: %llu\n", sb.metadata_nr_blocks_);
|
||||
}
|
||||
|
||||
shared_ptr<examiner> &find_examiner(block_manager<>::read_ref const &rr) {
|
||||
for (shared_ptr<examiner> &e : examiners_) {
|
||||
if (e->recognise(rr))
|
||||
return e;
|
||||
}
|
||||
|
||||
return raw_examiner_;
|
||||
}
|
||||
|
||||
text_ui &ui_;
|
||||
block_manager<> const &bm_;
|
||||
list<shared_ptr<examiner>> examiners_;
|
||||
shared_ptr<examiner> raw_examiner_;
|
||||
|
||||
|
||||
#if 0
|
||||
void show_superblock(text_ui &ui, superblock_detail::superblock const &sb) {
|
||||
}
|
||||
|
||||
void show_blocks(text_ui &ui, string const &dev) {
|
||||
metadata md(bm);
|
||||
|
||||
show_superblock(ui, md.sb_);
|
||||
|
||||
#if 0
|
||||
cout << "Metadata space map: nr_blocks = " << md.metadata_sm_->get_nr_blocks()
|
||||
<< ", nr_free_blocks = " << md.metadata_sm_->get_nr_free()
|
||||
<< endl;
|
||||
cout << "Data space map: nr_blocks = " << md.data_sm_->get_nr_blocks()
|
||||
<< ", nr_free_blocks = " << md.data_sm_->get_nr_free()
|
||||
<< endl;
|
||||
|
||||
block_address nr_blocks = bm->get_nr_blocks();
|
||||
for (block_address b = 0; b < nr_blocks; b++) {
|
||||
block_manager<>::read_ref rr = bm->read_lock(b);
|
||||
|
||||
if (is_superblock(rr))
|
||||
cout << b << ": superblock" << endl;
|
||||
|
||||
else if (is_bitmap_block(rr))
|
||||
cout << b << ": bitmap block" << endl;
|
||||
|
||||
else if (is_btree_node(rr))
|
||||
cout << b << ": btree_node" << endl;
|
||||
|
||||
else
|
||||
cout << b << ": unknown" << endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
@ -135,7 +336,25 @@ thin_show_metadata_cmd::run(int argc, char **argv)
|
||||
}
|
||||
|
||||
try {
|
||||
show_blocks(argv[optind]);
|
||||
ui::text_ui ui;
|
||||
|
||||
block_manager<>::ptr bm = open_bm(argv[optind], block_manager<>::READ_ONLY, true);
|
||||
main_dialog dialog(ui, *bm);
|
||||
dialog.run();
|
||||
#if 0
|
||||
// show_blocks(ui, argv[optind]);
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
attron(COLOR_PAIR(1));
|
||||
printw("Hello, ");
|
||||
attron(A_BOLD);
|
||||
printw("world!\n");
|
||||
attroff(A_BOLD);
|
||||
attroff(COLOR_PAIR(1));
|
||||
#endif
|
||||
getch();
|
||||
|
||||
} catch (std::exception const &e) {
|
||||
cerr << e.what() << endl;
|
||||
|
36
ui/ui.cc
Normal file
36
ui/ui.cc
Normal file
@ -0,0 +1,36 @@
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
using namespace ui;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
text_ui::text_ui()
|
||||
{
|
||||
initscr();
|
||||
noecho();
|
||||
|
||||
start_color();
|
||||
init_pair(1, COLOR_RED, COLOR_BLACK);
|
||||
init_pair(2, COLOR_YELLOW, COLOR_BLACK);
|
||||
init_pair(3, COLOR_BLUE, COLOR_BLACK);
|
||||
init_pair(4, COLOR_GREEN, COLOR_BLACK);
|
||||
init_pair(5, COLOR_YELLOW, COLOR_BLACK);
|
||||
init_pair(6, COLOR_BLACK, COLOR_RED);
|
||||
init_pair(7, COLOR_WHITE, COLOR_BLACK);
|
||||
|
||||
}
|
||||
|
||||
text_ui::~text_ui()
|
||||
{
|
||||
endwin();
|
||||
}
|
||||
|
||||
void
|
||||
text_ui::refresh()
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
20
ui/ui.h
Normal file
20
ui/ui.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef UI_UI_H
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace ui {
|
||||
class text_ui {
|
||||
public:
|
||||
text_ui();
|
||||
~text_ui();
|
||||
|
||||
void refresh();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user