Some work on thin_repair.
This commit is contained in:
parent
29c2831f3e
commit
511456f903
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,4 +2,6 @@
|
|||||||
*.o
|
*.o
|
||||||
*_t
|
*_t
|
||||||
*.d
|
*.d
|
||||||
test.data
|
test.data
|
||||||
|
thin_dump
|
||||||
|
thin_repair
|
||||||
|
11
Makefile
11
Makefile
@ -1,9 +1,8 @@
|
|||||||
SOURCE=\
|
SOURCE=\
|
||||||
endian_utils.cc \
|
endian_utils.cc \
|
||||||
|
metadata.cc \
|
||||||
metadata_disk_structures.cc
|
metadata_disk_structures.cc
|
||||||
|
|
||||||
# metadata.cc \
|
|
||||||
|
|
||||||
TEST_SOURCE=\
|
TEST_SOURCE=\
|
||||||
unit-tests/block_t.cc \
|
unit-tests/block_t.cc \
|
||||||
unit-tests/btree_t.cc \
|
unit-tests/btree_t.cc \
|
||||||
@ -12,8 +11,6 @@ TEST_SOURCE=\
|
|||||||
unit-tests/space_map_disk_t.cc \
|
unit-tests/space_map_disk_t.cc \
|
||||||
unit-tests/transaction_manager_t.cc \
|
unit-tests/transaction_manager_t.cc \
|
||||||
|
|
||||||
# unit-tests/metadata_t.cc \
|
|
||||||
|
|
||||||
OBJECTS=$(subst .cc,.o,$(SOURCE))
|
OBJECTS=$(subst .cc,.o,$(SOURCE))
|
||||||
TEST_PROGRAMS=$(subst .cc,,$(TEST_SOURCE))
|
TEST_PROGRAMS=$(subst .cc,,$(TEST_SOURCE))
|
||||||
TOP_DIR:=$(PWD)
|
TOP_DIR:=$(PWD)
|
||||||
@ -40,6 +37,12 @@ unit-test: $(TEST_PROGRAMS)
|
|||||||
multisnap_display: $(OBJECTS) main.o
|
multisnap_display: $(OBJECTS) main.o
|
||||||
g++ $(CPPFLAGS) -o $@ $+ $(LIBS)
|
g++ $(CPPFLAGS) -o $@ $+ $(LIBS)
|
||||||
|
|
||||||
|
thin_dump: $(OBJECTS) thin_dump.o
|
||||||
|
g++ $(CPPFLAGS) -o $@ $+ $(LIBS)
|
||||||
|
|
||||||
|
thin_repair: $(OBJECTS) thin_repair.o
|
||||||
|
g++ $(CPPFLAGS) -o $@ $+ $(LIBS)
|
||||||
|
|
||||||
unit-tests/block_t: unit-tests/block_t.o
|
unit-tests/block_t: unit-tests/block_t.o
|
||||||
g++ $(CPPFLAGS) -o $@ $+ $(LIBS)
|
g++ $(CPPFLAGS) -o $@ $+ $(LIBS)
|
||||||
|
|
||||||
|
6
btree.h
6
btree.h
@ -52,6 +52,8 @@ namespace persistent_data {
|
|||||||
|
|
||||||
__le32 nr_entries;
|
__le32 nr_entries;
|
||||||
__le32 max_entries;
|
__le32 max_entries;
|
||||||
|
__le32 value_size;
|
||||||
|
__le32 padding;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct disk_node {
|
struct disk_node {
|
||||||
@ -76,6 +78,8 @@ namespace persistent_data {
|
|||||||
return location_;
|
return location_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
block_address get_block_nr() const;
|
||||||
|
|
||||||
node_type get_type() const;
|
node_type get_type() const;
|
||||||
void set_type(node_type t);
|
void set_type(node_type t);
|
||||||
|
|
||||||
@ -88,6 +92,8 @@ namespace persistent_data {
|
|||||||
// FIXME: remove this, and get the constructor to do it.
|
// FIXME: remove this, and get the constructor to do it.
|
||||||
void set_max_entries(); // calculates the max for you.
|
void set_max_entries(); // calculates the max for you.
|
||||||
|
|
||||||
|
size_t get_value_size() const;
|
||||||
|
|
||||||
uint64_t key_at(unsigned i) const;
|
uint64_t key_at(unsigned i) const;
|
||||||
void set_key(unsigned i, uint64_t k);
|
void set_key(unsigned i, uint64_t k);
|
||||||
|
|
||||||
|
15
btree.tcc
15
btree.tcc
@ -16,6 +16,13 @@ node_ref<ValueTraits, BlockSize>::node_ref(block_address location, disk_node *ra
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ValueTraits, uint32_t BlockSize>
|
||||||
|
block_address
|
||||||
|
node_ref<ValueTraits, BlockSize>::get_block_nr() const
|
||||||
|
{
|
||||||
|
return to_cpu<uint64_t>(raw_->header.blocknr);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ValueTraits, uint32_t BlockSize>
|
template <typename ValueTraits, uint32_t BlockSize>
|
||||||
btree_detail::node_type
|
btree_detail::node_type
|
||||||
node_ref<ValueTraits, BlockSize>::get_type() const
|
node_ref<ValueTraits, BlockSize>::get_type() const
|
||||||
@ -81,6 +88,13 @@ node_ref<ValueTraits, BlockSize>::set_max_entries()
|
|||||||
set_max_entries(calc_max_entries());
|
set_max_entries(calc_max_entries());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ValueTraits, uint32_t BlockSize>
|
||||||
|
size_t
|
||||||
|
node_ref<ValueTraits, BlockSize>::get_value_size() const
|
||||||
|
{
|
||||||
|
return to_cpu<uint32_t>(raw_->header.value_size);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ValueTraits, uint32_t BlockSize>
|
template <typename ValueTraits, uint32_t BlockSize>
|
||||||
uint64_t
|
uint64_t
|
||||||
node_ref<ValueTraits, BlockSize>::key_at(unsigned i) const
|
node_ref<ValueTraits, BlockSize>::key_at(unsigned i) const
|
||||||
@ -610,6 +624,7 @@ walk_tree(typename visitor::ptr visitor,
|
|||||||
unsigned level, block_address b)
|
unsigned level, block_address b)
|
||||||
{
|
{
|
||||||
using namespace btree_detail;
|
using namespace btree_detail;
|
||||||
|
|
||||||
auto blk = tm_->read_lock(b);
|
auto blk = tm_->read_lock(b);
|
||||||
auto o = to_node<uint64_traits, BlockSize>(blk);
|
auto o = to_node<uint64_traits, BlockSize>(blk);
|
||||||
if (o.get_type() == INTERNAL) {
|
if (o.get_type() == INTERNAL) {
|
||||||
|
207
metadata.cc
207
metadata.cc
@ -1,7 +1,12 @@
|
|||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include "core_map.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
using namespace persistent_data;
|
using namespace persistent_data;
|
||||||
using namespace thin_provisioning;
|
using namespace thin_provisioning;
|
||||||
|
|
||||||
@ -13,6 +18,164 @@ namespace {
|
|||||||
uint32_t const VERSION = 1;
|
uint32_t const VERSION = 1;
|
||||||
unsigned const METADATA_CACHE_SIZE = 1024;
|
unsigned const METADATA_CACHE_SIZE = 1024;
|
||||||
unsigned const SECTOR_TO_BLOCK_SHIFT = 3;
|
unsigned const SECTOR_TO_BLOCK_SHIFT = 3;
|
||||||
|
|
||||||
|
// FIXME: get the file size
|
||||||
|
unsigned const NR_BLOCKS = 1024;
|
||||||
|
|
||||||
|
transaction_manager<4096>::ptr
|
||||||
|
open_tm(string const &dev_path) {
|
||||||
|
block_manager<4096>::ptr bm(new block_manager<4096>(dev_path, NR_BLOCKS));
|
||||||
|
space_map::ptr sm(new core_map(NR_BLOCKS));
|
||||||
|
transaction_manager<4096>::ptr tm(new transaction_manager<4096>(bm, sm));
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
superblock read_superblock(block_manager<4096>::ptr bm) {
|
||||||
|
superblock sb;
|
||||||
|
auto r = bm->read_lock(SUPERBLOCK_LOCATION);
|
||||||
|
superblock_disk const *sbd = reinterpret_cast<superblock_disk const *>(&r.data());
|
||||||
|
superblock_traits::unpack(*sbd, sb);
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// This class implements consistency checking for the
|
||||||
|
// btrees in general. It's worth summarising what is checked:
|
||||||
|
//
|
||||||
|
// Implemented
|
||||||
|
// -----------
|
||||||
|
//
|
||||||
|
// - No block appears in the tree more than once.
|
||||||
|
// - block_nr
|
||||||
|
// - nr_entries < max_entries
|
||||||
|
// - max_entries fits in block
|
||||||
|
// - max_entries is divisible by 3
|
||||||
|
//
|
||||||
|
// Not implemented
|
||||||
|
// ---------------
|
||||||
|
//
|
||||||
|
// - checksum
|
||||||
|
// - leaf | internal flags (this can be inferred from siblings)
|
||||||
|
// - nr_entries > minimum
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
template <uint32_t Levels, typename ValueTraits, uint32_t BlockSize>
|
||||||
|
class btree_validator : public btree<Levels, ValueTraits, BlockSize>::visitor {
|
||||||
|
public:
|
||||||
|
void visit_internal(unsigned level, btree_detail::node_ref<uint64_traits, BlockSize> const &n) {
|
||||||
|
check_duplicate_block(n.get_location());
|
||||||
|
check_block_nr(n);
|
||||||
|
check_max_entries(n);
|
||||||
|
check_nr_entries(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit_internal_leaf(unsigned level, btree_detail::node_ref<uint64_traits, BlockSize> const &n) {
|
||||||
|
check_duplicate_block(n.get_location());
|
||||||
|
check_block_nr(n);
|
||||||
|
check_max_entries(n);
|
||||||
|
check_nr_entries(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit_leaf(unsigned level, btree_detail::node_ref<ValueTraits, BlockSize> const &n) {
|
||||||
|
check_duplicate_block(n.get_location());
|
||||||
|
check_block_nr(n);
|
||||||
|
check_max_entries(n);
|
||||||
|
check_nr_entries(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void check_duplicate_block(block_address b) {
|
||||||
|
if (seen_.count(b)) {
|
||||||
|
ostringstream out;
|
||||||
|
out << "duplicate block in btree: " << b;
|
||||||
|
throw runtime_error(out.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
seen_.insert(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename node>
|
||||||
|
void check_block_nr(node const &n) const {
|
||||||
|
if (n.get_location() != n.get_block_nr()) {
|
||||||
|
ostringstream out;
|
||||||
|
out << "block number mismatch: actually "
|
||||||
|
<< n.get_location()
|
||||||
|
<< ", claims " << n.get_block_nr();
|
||||||
|
throw runtime_error(out.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename node>
|
||||||
|
void check_max_entries(node const &n) const {
|
||||||
|
size_t elt_size = sizeof(uint64_t) + n.get_value_size();
|
||||||
|
if (elt_size * n.get_max_entries() + sizeof(node_header) > BlockSize) {
|
||||||
|
ostringstream out;
|
||||||
|
out << "max entries too large: " << n.get_max_entries();
|
||||||
|
throw runtime_error(out.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.get_max_entries() % 3) {
|
||||||
|
ostringstream out;
|
||||||
|
out << "max entries is not divisible by 3: " << n.get_max_entries();
|
||||||
|
throw runtime_error(out.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename node>
|
||||||
|
void check_nr_entries(node const &n) const {
|
||||||
|
if (n.get_nr_entries() > n.get_max_entries()) {
|
||||||
|
ostringstream out;
|
||||||
|
out << "bad nr_entries: "
|
||||||
|
<< n.get_nr_entries() << " < "
|
||||||
|
<< n.get_max_entries();
|
||||||
|
throw runtime_error(out.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set<block_address> seen_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// As well as the standard btree checks, we build up a set of what
|
||||||
|
// devices having mappings defined, which can later be cross
|
||||||
|
// referenced with the details tree.
|
||||||
|
class mapping_validator : public btree_validator<2, block_traits, MD_BLOCK_SIZE> {
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<mapping_validator> ptr;
|
||||||
|
|
||||||
|
void visit_internal_leaf(unsigned level,
|
||||||
|
btree_detail::node_ref<uint64_traits, MD_BLOCK_SIZE> const &n) {
|
||||||
|
btree_validator<2, block_traits, MD_BLOCK_SIZE>::visit_internal_leaf(level, n);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < n.get_nr_entries(); i++)
|
||||||
|
devices_.insert(n.key_at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
set<uint64_t> get_devices() const {
|
||||||
|
return devices_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
set<uint64_t> devices_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class details_validator : public btree_validator<1, device_details_traits, MD_BLOCK_SIZE> {
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<details_validator> ptr;
|
||||||
|
|
||||||
|
void visit_leaf(unsigned level,
|
||||||
|
btree_detail::node_ref<device_details_traits, MD_BLOCK_SIZE> const &n) {
|
||||||
|
btree_validator<1, device_details_traits, MD_BLOCK_SIZE>::visit_leaf(level, n);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < n.get_nr_entries(); i++)
|
||||||
|
devices_.insert(n.key_at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
set<uint64_t> get_devices() const {
|
||||||
|
return devices_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
set<uint64_t> devices_;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -87,22 +250,20 @@ thin::set_mapped_blocks(block_address count)
|
|||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
metadata::metadata(transaction_manager<MD_BLOCK_SIZE>::ptr tm,
|
metadata::metadata(std::string const &dev_path)
|
||||||
block_address superblock,
|
: tm_(open_tm(dev_path)),
|
||||||
sector_t data_block_size,
|
sb_(read_superblock(tm_->get_bm())),
|
||||||
block_address nr_data_blocks,
|
details_(tm_, sb_.device_details_root_, typename device_details_traits::ref_counter()),
|
||||||
bool create)
|
mappings_top_level_(tm_, sb_.data_mapping_root_, mtree_ref_counter<MD_BLOCK_SIZE>(tm_)),
|
||||||
: superblock_(superblock),
|
mappings_(tm_, sb_.data_mapping_root_, space_map_ref_counter(data_sm_))
|
||||||
tm_(tm),
|
|
||||||
details_(tm, typename device_details_traits::ref_counter()),
|
|
||||||
mappings_top_level_(tm, mtree_ref_counter<MD_BLOCK_SIZE>(tm)),
|
|
||||||
mappings_(tm, space_map_ref_counter(data_sm_))
|
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
::memset(&sb_, 0, sizeof(sb_));
|
::memset(&sb_, 0, sizeof(sb_));
|
||||||
sb_.data_mapping_root_ = mappings_.get_root();
|
sb_.data_mapping_root_ = mappings_.get_root();
|
||||||
sb_.device_details_root_ = details_.get_root();
|
sb_.device_details_root_ = details_.get_root();
|
||||||
sb_.metadata_block_size_ = MD_BLOCK_SIZE;
|
sb_.metadata_block_size_ = MD_BLOCK_SIZE;
|
||||||
sb_.metadata_nr_blocks_ = tm->get_bm()->get_nr_blocks();
|
sb_.metadata_nr_blocks_ = tm_->get_bm()->get_nr_blocks();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata::~metadata()
|
metadata::~metadata()
|
||||||
@ -116,7 +277,7 @@ metadata::commit()
|
|||||||
sb_.data_mapping_root_ = mappings_.get_root();
|
sb_.data_mapping_root_ = mappings_.get_root();
|
||||||
sb_.device_details_root_ = details_.get_root();
|
sb_.device_details_root_ = details_.get_root();
|
||||||
|
|
||||||
auto superblock = tm_->get_bm()->superblock(superblock_);
|
auto superblock = tm_->get_bm()->superblock(SUPERBLOCK_LOCATION);
|
||||||
auto disk = reinterpret_cast<superblock_disk *>(superblock.data());
|
auto disk = reinterpret_cast<superblock_disk *>(superblock.data());
|
||||||
superblock_traits::pack(sb_, *disk);
|
superblock_traits::pack(sb_, *disk);
|
||||||
}
|
}
|
||||||
@ -235,4 +396,24 @@ metadata::device_exists(thin_dev_t dev) const
|
|||||||
return details_.lookup(key);
|
return details_.lookup(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
metadata::check()
|
||||||
|
{
|
||||||
|
mapping_validator::ptr mv(new mapping_validator);
|
||||||
|
mappings_.visit(mv);
|
||||||
|
auto mapped_devs = mv->get_devices();
|
||||||
|
|
||||||
|
details_validator::ptr dv(new details_validator);
|
||||||
|
details_.visit(dv);
|
||||||
|
auto details_devs = dv->get_devices();
|
||||||
|
|
||||||
|
for (auto it = mapped_devs.begin(); it != mapped_devs.end(); ++it)
|
||||||
|
if (details_devs.count(*it) == 0) {
|
||||||
|
ostringstream out;
|
||||||
|
out << "mapping exists for device " << *it
|
||||||
|
<< ", yet there is no entry in the details tree.";
|
||||||
|
throw runtime_error(out.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -143,13 +143,14 @@ namespace thin_provisioning {
|
|||||||
|
|
||||||
thin::ptr open_thin(thin_dev_t);
|
thin::ptr open_thin(thin_dev_t);
|
||||||
|
|
||||||
|
// Validation and repair
|
||||||
|
void check();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class thin;
|
friend class thin;
|
||||||
|
|
||||||
bool device_exists(thin_dev_t dev) const;
|
bool device_exists(thin_dev_t dev) const;
|
||||||
|
|
||||||
block_address superblock_;
|
|
||||||
|
|
||||||
typedef persistent_data::transaction_manager<MD_BLOCK_SIZE>::ptr tm_ptr;
|
typedef persistent_data::transaction_manager<MD_BLOCK_SIZE>::ptr tm_ptr;
|
||||||
|
|
||||||
typedef persistent_data::btree<1, device_details_traits, MD_BLOCK_SIZE> detail_tree;
|
typedef persistent_data::btree<1, device_details_traits, MD_BLOCK_SIZE> detail_tree;
|
||||||
@ -157,7 +158,9 @@ namespace thin_provisioning {
|
|||||||
typedef persistent_data::btree<2, block_traits, MD_BLOCK_SIZE> mapping_tree;
|
typedef persistent_data::btree<2, block_traits, MD_BLOCK_SIZE> mapping_tree;
|
||||||
typedef persistent_data::btree<1, block_traits, MD_BLOCK_SIZE> single_mapping_tree;
|
typedef persistent_data::btree<1, block_traits, MD_BLOCK_SIZE> single_mapping_tree;
|
||||||
|
|
||||||
|
// Declaration order is important here
|
||||||
tm_ptr tm_;
|
tm_ptr tm_;
|
||||||
|
superblock sb_;
|
||||||
|
|
||||||
// Ignoring the metadata sm for now, since we don't need it for the basic 'dump' tool
|
// Ignoring the metadata sm for now, since we don't need it for the basic 'dump' tool
|
||||||
// space_map::ptr metadata_sm_;
|
// space_map::ptr metadata_sm_;
|
||||||
@ -165,7 +168,6 @@ namespace thin_provisioning {
|
|||||||
detail_tree details_;
|
detail_tree details_;
|
||||||
dev_tree mappings_top_level_;
|
dev_tree mappings_top_level_;
|
||||||
mapping_tree mappings_;
|
mapping_tree mappings_;
|
||||||
superblock sb_;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
31
thin_dump.cc
Normal file
31
thin_dump.cc
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
using namespace persistent_data;
|
||||||
|
using namespace std;
|
||||||
|
using namespace thin_provisioning;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void dump(string const &path) {
|
||||||
|
metadata md(path);
|
||||||
|
|
||||||
|
md.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(string const &cmd) {
|
||||||
|
cerr << "Usage: " << cmd << " <metadata device>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(argv[1]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
31
thin_repair.cc
Normal file
31
thin_repair.cc
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
using namespace persistent_data;
|
||||||
|
using namespace std;
|
||||||
|
using namespace thin_provisioning;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void check(string const &path) {
|
||||||
|
metadata md(path);
|
||||||
|
|
||||||
|
md.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(string const &cmd) {
|
||||||
|
cerr << "Usage: " << cmd << " <metadata device>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
check(argv[1]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -15,14 +15,6 @@ namespace {
|
|||||||
block_address const NR_BLOCKS = 1024;
|
block_address const NR_BLOCKS = 1024;
|
||||||
block_address const SUPERBLOCK = 0;
|
block_address const SUPERBLOCK = 0;
|
||||||
|
|
||||||
transaction_manager<4096>::ptr
|
|
||||||
create_tm() {
|
|
||||||
block_manager<4096>::ptr bm(new block_manager<4096>("./test.data", NR_BLOCKS));
|
|
||||||
space_map::ptr sm(new core_map(NR_BLOCKS));
|
|
||||||
transaction_manager<4096>::ptr tm(new transaction_manager<4096>(bm, sm));
|
|
||||||
return tm;
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata::ptr
|
metadata::ptr
|
||||||
create_metadata() {
|
create_metadata() {
|
||||||
auto tm = create_tm();
|
auto tm = create_tm();
|
||||||
|
Loading…
Reference in New Issue
Block a user