[thin_show_metadata] ncurses render
This commit is contained in:
parent
c4215c0cf6
commit
e78de5d3ad
@ -106,7 +106,8 @@ SOURCE=\
|
|||||||
DEVTOOLS_SOURCE=\
|
DEVTOOLS_SOURCE=\
|
||||||
thin-provisioning/thin_generate_metadata.cc \
|
thin-provisioning/thin_generate_metadata.cc \
|
||||||
thin-provisioning/variable_chunk_stream.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")
|
ifeq ("@DEVTOOLS@", "yes")
|
||||||
SOURCE+=$(DEVTOOLS_SOURCE)
|
SOURCE+=$(DEVTOOLS_SOURCE)
|
||||||
@ -133,6 +134,10 @@ CXXFLAGS+=@LFS_FLAGS@
|
|||||||
INCLUDES+=-I$(TOP_BUILDDIR) -I$(TOP_DIR) -I$(TOP_DIR)/thin-provisioning
|
INCLUDES+=-I$(TOP_BUILDDIR) -I$(TOP_DIR) -I$(TOP_DIR)/thin-provisioning
|
||||||
LIBS:=-laio -lexpat
|
LIBS:=-laio -lexpat
|
||||||
|
|
||||||
|
ifeq ("@DEVTOOLS@", "yes")
|
||||||
|
LIBS+=-lncurses
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ("@STATIC_CXX@", "yes")
|
ifeq ("@STATIC_CXX@", "yes")
|
||||||
CXXLIB+=-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -Wl,--as-needed
|
CXXLIB+=-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -Wl,--as-needed
|
||||||
else
|
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;
|
using namespace superblock_detail;
|
||||||
|
|
||||||
superblock sb;
|
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_disk const *sbd = reinterpret_cast<superblock_disk const *>(r.data());
|
||||||
superblock_traits::unpack(*sbd, sb);
|
superblock_traits::unpack(*sbd, sb);
|
||||||
return 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)
|
superblock_detail::superblock read_superblock(block_manager<>::ptr bm)
|
||||||
{
|
{
|
||||||
return read_superblock(bm, SUPERBLOCK_LOCATION);
|
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)
|
void write_superblock(block_manager<>::ptr bm, superblock_detail::superblock const &sb)
|
||||||
{
|
{
|
||||||
block_manager<>::write_ref w = bm->write_lock(SUPERBLOCK_LOCATION, superblock_validator());
|
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: 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);
|
||||||
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);
|
persistent_data::block_address location);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "thin-provisioning/commands.h"
|
#include "thin-provisioning/commands.h"
|
||||||
#include "thin-provisioning/metadata.h"
|
#include "thin-provisioning/metadata.h"
|
||||||
#include "thin-provisioning/superblock.h"
|
#include "thin-provisioning/superblock.h"
|
||||||
|
#include "ui/ui.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -12,16 +13,66 @@
|
|||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
using namespace persistent_data;
|
using namespace persistent_data;
|
||||||
using namespace sm_disk_detail;
|
using namespace sm_disk_detail;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace thin_provisioning;
|
using namespace thin_provisioning;
|
||||||
|
using namespace ui;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool is_superblock(block_manager<>::read_ref &rr) {
|
class examiner {
|
||||||
|
public:
|
||||||
|
examiner(string const &name, int colour_pair, char rep)
|
||||||
|
: name_(name),
|
||||||
|
colour_pair_(colour_pair),
|
||||||
|
rep_(rep) {
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
using namespace superblock_detail;
|
||||||
|
|
||||||
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(rr.data());
|
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(rr.data());
|
||||||
@ -35,22 +86,44 @@ namespace {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool is_bitmap_block(block_manager<>::read_ref &rr) {
|
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());
|
bitmap_header const *data = reinterpret_cast<bitmap_header const *>(rr.data());
|
||||||
crc32c sum(BITMAP_CSUM_XOR);
|
crc32c sum(BITMAP_CSUM_XOR);
|
||||||
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||||
return sum.get_sum() == to_cpu<uint32_t>(data->csum);
|
return sum.get_sum() == to_cpu<uint32_t>(data->csum);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool is_index_block(block_manager<>::read_ref &rr) {
|
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());
|
metadata_index const *mi = reinterpret_cast<metadata_index const *>(rr.data());
|
||||||
crc32c sum(INDEX_CSUM_XOR);
|
crc32c sum(INDEX_CSUM_XOR);
|
||||||
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||||
return sum.get_sum() == to_cpu<uint32_t>(mi->csum_);
|
return sum.get_sum() == to_cpu<uint32_t>(mi->csum_);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool is_btree_node(block_manager<>::read_ref &rr) {
|
|
||||||
|
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;
|
using namespace btree_detail;
|
||||||
|
|
||||||
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
disk_node const *data = reinterpret_cast<disk_node const *>(rr.data());
|
||||||
@ -59,11 +132,136 @@ namespace {
|
|||||||
sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
|
sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
|
||||||
return sum.get_sum() == to_cpu<uint32_t>(n->csum);
|
return sum.get_sum() == to_cpu<uint32_t>(n->csum);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void show_blocks(string const &dev) {
|
class dev_detail_examiner : public btree_examiner {
|
||||||
block_manager<>::ptr bm = open_bm(dev, block_manager<>::READ_ONLY);
|
public:
|
||||||
|
dev_detail_examiner()
|
||||||
|
: btree_examiner("dev_details", 4, 'd') {
|
||||||
|
}
|
||||||
|
|
||||||
metadata md(bm, metadata::OPEN);
|
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()
|
cout << "Metadata space map: nr_blocks = " << md.metadata_sm_->get_nr_blocks()
|
||||||
<< ", nr_free_blocks = " << md.metadata_sm_->get_nr_free()
|
<< ", nr_free_blocks = " << md.metadata_sm_->get_nr_free()
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -87,7 +285,10 @@ namespace {
|
|||||||
else
|
else
|
||||||
cout << b << ": unknown" << endl;
|
cout << b << ": unknown" << endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -135,7 +336,25 @@ thin_show_metadata_cmd::run(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (std::exception const &e) {
|
||||||
cerr << e.what() << endl;
|
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