write some code

This commit is contained in:
Joe Thornber 2011-06-27 10:45:30 +01:00
parent 2e39670ff9
commit c090bb88b5
9 changed files with 366 additions and 99 deletions

View File

@ -1,16 +1,18 @@
SOURCE=\ SOURCE=\
block.cc \
main.cc \ main.cc \
metadata.cc \ metadata.cc
transaction_manager.cc
OBJECTS=$(subst .cc,.o,$(SOURCE)) OBJECTS=$(subst .cc,.o,$(SOURCE))
CPPFLAGS=-Wall -std=c++0x CPPFLAGS=-Wall -std=c++0x
INCLUDES= INCLUDES=
LIBS=-lstdc++ LIBS=-lstdc++
.SUFFIXES: .cc .o .d
.SUFFIXES: .cc .o %.d: %.cc
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
.cc.o: .cc.o:
g++ -c $(CPPFLAGS) $(INCLUDES) -o $@ $< g++ -c $(CPPFLAGS) $(INCLUDES) -o $@ $<
@ -18,7 +20,4 @@ LIBS=-lstdc++
multisnap_display: $(OBJECTS) multisnap_display: $(OBJECTS)
g++ -o $@ $+ $(LIBS) g++ -o $@ $+ $(LIBS)
main.o: block.h include $(subst .cc,.d,$(SOURCE))
block.o: block.h
transaction_manager.o: transaction_manager.h block.h
metadata.o: block.h transaction_manager.h btree.h metadata.h

22
block.h
View File

@ -30,6 +30,8 @@ namespace persistent_data {
class block_validator { class block_validator {
public: public:
typedef boost::shared_ptr<block_validator> ptr;
virtual ~block_validator() {} virtual ~block_validator() {}
virtual void check(block const &b) const = 0; virtual void check(block const &b) const = 0;
@ -37,7 +39,7 @@ namespace persistent_data {
}; };
struct block { struct block {
typedef boost::optional<block_validator> maybe_validator; typedef boost::optional<typename block_validator::ptr> maybe_validator;
block(block_address location, block(block_address location,
maybe_validator v = maybe_validator()) maybe_validator v = maybe_validator())
@ -47,7 +49,7 @@ namespace persistent_data {
block_address location_; block_address location_;
buffer data_; buffer data_;
boost::optional<block_validator> validator_; maybe_validator validator_;
}; };
typedef boost::shared_ptr<block> block_ptr; typedef boost::shared_ptr<block> block_ptr;
@ -67,6 +69,8 @@ namespace persistent_data {
// locked. // locked.
class write_ref : public read_ref { class write_ref : public read_ref {
public: public:
write_ref(block_ptr b);
using read_ref::data; using read_ref::data;
buffer &data(); buffer &data();
}; };
@ -86,16 +90,20 @@ namespace persistent_data {
// Validator variants // Validator variants
read_ref read_ref
read_lock(block_address location, block_validator const &v); read_lock(block_address location,
typename block_validator::ptr const &v);
boost::optional<read_ref> boost::optional<read_ref>
read_try_lock(block_address location, block_validator const &v); read_try_lock(block_address location,
typename block_validator::ptr const &v);
write_ref write_ref
write_lock(block_address location, block_validator const &v); write_lock(block_address location,
typename block_validator::ptr const &v);
write_ref write_ref
write_lock_zero(block_address location, block_validator const &v); write_lock_zero(block_address location,
typename block_validator::ptr const &v);
// Use this to commit changes // Use this to commit changes
void flush(write_ref super_block); void flush(write_ref super_block);
@ -111,6 +119,8 @@ namespace persistent_data {
}; };
} }
#include "block.tcc"
//---------------------------------------------------------------- //----------------------------------------------------------------
#endif #endif

View File

@ -5,11 +5,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <boost/bind.hpp>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
using namespace boost; using namespace boost;
using namespace persistent_data; using namespace persistent_data;
using namespace std;
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -33,6 +35,12 @@ block_manager<BlockSize>::read_ref::data() const
return block_->data_; return block_->data_;
} }
template <uint32_t BlockSize>
block_manager<BlockSize>::write_ref::write_ref(block_manager::block_ptr b)
: read_ref(b)
{
}
template <uint32_t BlockSize> template <uint32_t BlockSize>
typename block_manager<BlockSize>::buffer & typename block_manager<BlockSize>::buffer &
block_manager<BlockSize>::write_ref::data() block_manager<BlockSize>::write_ref::data()
@ -61,7 +69,7 @@ typename block_manager<BlockSize>::read_ref
block_manager<BlockSize>::read_lock(block_address location) block_manager<BlockSize>::read_lock(block_address location)
{ {
block_ptr b(new block(location)); block_ptr b(new block(location));
read_block(b); read_block(*b);
return read_ref(b); return read_ref(b);
} }
@ -76,8 +84,8 @@ template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock(block_address location) block_manager<BlockSize>::write_lock(block_address location)
{ {
block_ptr b(new block(location), write_and_release); block_ptr b(new block(location), bind(&block_manager::write_and_release, this, _1));
read_block(b); read_block(*b);
return write_ref(b); return write_ref(b);
} }
@ -85,25 +93,25 @@ template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock_zero(block_address location) block_manager<BlockSize>::write_lock_zero(block_address location)
{ {
block_ptr b(new block(location), write_and_release); block_ptr b(new block(location), bind(&block_manager<BlockSize>::write_and_release, this, _1));
zero_block(b); zero_block(*b);
return write_ref(b); return write_ref(b);
} }
template <uint32_t BlockSize> template <uint32_t BlockSize>
typename block_manager<BlockSize>::read_ref typename block_manager<BlockSize>::read_ref
block_manager<BlockSize>::read_lock(block_address location, block_manager<BlockSize>::read_lock(block_address location,
block_manager<BlockSize>::block_validator const &v) typename block_manager<BlockSize>::block_validator::ptr const &v)
{ {
block_ptr b(new block(location, v)); block_ptr b(new block(location, v));
read_block(b); read_block(*b);
return read_ref(b); return read_ref(b);
} }
template <uint32_t BlockSize> template <uint32_t BlockSize>
optional<typename block_manager<BlockSize>::read_ref> optional<typename block_manager<BlockSize>::read_ref>
block_manager<BlockSize>::read_try_lock(block_address location, block_manager<BlockSize>::read_try_lock(block_address location,
block_manager<BlockSize>::block_validator const &v) typename block_manager<BlockSize>::block_validator::ptr const &v)
{ {
return read_lock(location, v); return read_lock(location, v);
} }
@ -111,20 +119,20 @@ block_manager<BlockSize>::read_try_lock(block_address location,
template <uint32_t BlockSize> template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock(block_address location, block_manager<BlockSize>::write_lock(block_address location,
block_manager<BlockSize>::block_validator const &v) typename block_manager<BlockSize>::block_validator::ptr const &v)
{ {
block_ptr b(new block(location, v), write_and_release); block_ptr b(new block(location, v), write_and_release);
read_block(b); read_block(*b);
return write_ref(b); return write_ref(b);
} }
template <uint32_t BlockSize> template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock_zero(block_address location, block_manager<BlockSize>::write_lock_zero(block_address location,
block_manager<BlockSize>::block_validator const &v) typename block_manager<BlockSize>::block_validator::ptr const &v)
{ {
block_ptr b(new block(location, v), write_and_release); block_ptr b(new block(location, v), write_and_release);
zero_block(b); zero_block(*b);
return write_ref(b); return write_ref(b);
} }
@ -140,16 +148,16 @@ template <uint32_t BlockSize>
void void
block_manager<BlockSize>::read_block(block &b) block_manager<BlockSize>::read_block(block &b)
{ {
std::cerr << "reading block: " << b->location << std::endl; std::cerr << "reading block: " << b.location_ << std::endl;
off_t r; off_t r;
r = ::lseek(fd_, BlockSize * b->location_, SEEK_SET); r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
if (r == (off_t) -1) if (r == (off_t) -1)
throw std::runtime_error("lseek failed"); throw std::runtime_error("lseek failed");
ssize_t n; ssize_t n;
size_t remaining = BlockSize; size_t remaining = BlockSize;
unsigned char *buf = b->data_; unsigned char *buf = b.data_;
do { do {
n = ::read(fd_, buf, remaining); n = ::read(fd_, buf, remaining);
if (n > 0) { if (n > 0) {
@ -167,18 +175,18 @@ void
block_manager<BlockSize>::write_block(block const &b) block_manager<BlockSize>::write_block(block const &b)
{ {
std::cerr << "writing block: " << b->location << std::endl; std::cerr << "writing block: " << b.location_ << std::endl;
off_t r; off_t r;
r = ::lseek(fd_, BlockSize * b->location_, SEEK_SET); r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
if (r == (off_t) -1) if (r == (off_t) -1)
throw std::runtime_error("lseek failed"); throw std::runtime_error("lseek failed");
ssize_t n; ssize_t n;
size_t remaining = BlockSize; size_t remaining = BlockSize;
unsigned char *buf = b->data_; unsigned char const *buf = b.data_;
do { do {
n = ::read(fd_, buf, remaining); n = ::write(fd_, buf, remaining);
if (n > 0) { if (n > 0) {
remaining -= n; remaining -= n;
buf += n; buf += n;
@ -193,14 +201,14 @@ template <uint32_t BlockSize>
void void
block_manager<BlockSize>::zero_block(block &b) block_manager<BlockSize>::zero_block(block &b)
{ {
memset(b->data_, 0, BlockSize); memset(b.data_, 0, BlockSize);
} }
template <uint32_t BlockSize> template <uint32_t BlockSize>
void void
block_manager<BlockSize>::write_and_release(block *b) block_manager<BlockSize>::write_and_release(block *b)
{ {
write_block(b); write_block(*b);
delete b; delete b;
} }

20
btree.h
View File

@ -1,6 +1,7 @@
#ifndef BTREE_H #ifndef BTREE_H
#define BTREE_H #define BTREE_H
#include "endian.h"
#include "transaction_manager.h" #include "transaction_manager.h"
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -17,8 +18,8 @@ namespace persistent_data {
typedef typename block_manager<BlockSize>::read_ref read_ref; typedef typename block_manager<BlockSize>::read_ref read_ref;
typedef typename block_manager<BlockSize>::write_ref write_ref; typedef typename block_manager<BlockSize>::write_ref write_ref;
btree(boost::shared_ptr<transaction_manager<BlockSize> > tm); btree(typename persistent_data::transaction_manager<BlockSize>::ptr tm);
btree(boost::shared_ptr<transaction_manager<BlockSize> > tm, btree(typename transaction_manager<BlockSize>::ptr tm,
block_address root); block_address root);
~btree(); ~btree();
@ -42,7 +43,22 @@ namespace persistent_data {
bool destroy_; bool destroy_;
block_address root_; block_address root_;
}; };
struct uint64_traits {
typedef base::__le64 disk_type;
typedef uint64_t value_type;
static value_type construct(void *data) {
// extra memcpy because I'm paranoid about alignment issues
base::__le64 disk;
::memcpy(&disk, data, sizeof(disk));
return base::to_cpu<uint64_t>(disk);
}
}; };
};
#include "btree.tcc"
//---------------------------------------------------------------- //----------------------------------------------------------------

192
btree.tcc
View File

@ -1,14 +1,20 @@
#include "btree.h" #include "btree.h"
#include "endian.h"
#include "transaction_manager.h"
#include <list>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
// FIXME: can't have using clauses in a header
using namespace base;
using namespace boost; using namespace boost;
using namespace persistent_data; using namespace persistent_data;
//---------------------------------------------------------------- //----------------------------------------------------------------
namespace { namespace btree_detail {
//------------------------------------------------ //------------------------------------------------
// On disk data layout for btree nodes // On disk data layout for btree nodes
enum node_flags { enum node_flags {
@ -25,7 +31,7 @@ namespace {
__le32 max_entries; __le32 max_entries;
} __attribute__((packed)); } __attribute__((packed));
struct node { struct disk_node {
struct node_header header; struct node_header header;
__le64 keys[0]; __le64 keys[0];
} __attribute__((packed)); } __attribute__((packed));
@ -34,34 +40,76 @@ namespace {
//------------------------------------------------ //------------------------------------------------
// Class that acts as an interface over the raw little endian btree // Class that acts as an interface over the raw little endian btree
// node data. // node data.
class node { class node_ref {
public: public:
enum type { enum type {
INTERNAL, INTERNAL,
LEAF LEAF
}; };
type get_type() const; node_ref(disk_node *raw)
void set_type(type t); : raw_(raw) {
}
unsigned get_nr_entries() const; type get_type() const {
void set_nr_entries(unsigned n); uint32_t flags = to_cpu<uint32_t>(raw_->header.flags);
if (flags & INTERNAL_NODE)
return INTERNAL;
else if (flags & LEAF_NODE)
return LEAF;
else
throw runtime_error("unknow node type");
}
unsigned get_max_entries() const; void set_type(type t){
void set_max_entries(unsigned n); uint32_t flags = to_cpu<uint32_t>(raw_->header.flags);
switch (t) {
case INTERNAL:
flags |= INTERNAL_NODE;
break;
uint64_t key_at(unsigned i) const; case LEAF:
flags |= LEAF_NODE;
break;
}
raw_->header.flags = to_disk<__le32>(flags);
}
unsigned get_nr_entries() const {
return to_cpu<uint32_t>(raw_->header.nr_entries);
}
void set_nr_entries(unsigned n) {
raw_->header.nr_entries = to_disk<__le32>(n);
}
unsigned get_max_entries() const {
return to_cpu<uint32_t>(raw_->header.max_entries);
}
void set_max_entries(unsigned n) {
raw_->header.max_entries = to_disk<__le32>(n);
}
uint64_t key_at(unsigned i) const {
return to_cpu<uint64_t>(raw_->keys[i]);
}
template <typename ValueTraits> template <typename ValueTraits>
typename ValueTraits::value_type value_at(unsigned i) const; typename ValueTraits::value_type value_at(unsigned i) const {
void *value_base = &raw_->keys[to_cpu<uint32_t>(raw_->header.max_entries)];
void *value_ptr = static_cast<unsigned char *>(value_base) +
sizeof(typename ValueTraits::disk_type) * i;
return ValueTraits::construct(value_ptr);
}
private: private:
struct node *raw_; disk_node *raw_;
}; };
//------------------------------------------------ //------------------------------------------------
// Various searches // Various searches
int bsearch(node const &n, uint64_t key, int want_hi) int bsearch(node_ref const &n, uint64_t key, int want_hi)
{ {
int lo = -1, hi = n.get_nr_entries(); int lo = -1, hi = n.get_nr_entries();
@ -81,7 +129,7 @@ namespace {
return want_hi ? hi : lo; return want_hi ? hi : lo;
} }
optional<unsigned> exact_search(node const &n, uint64_t key) { optional<unsigned> exact_search(node_ref const &n, uint64_t key) {
int i = bsearch(n, key, 0); int i = bsearch(n, key, 0);
if (i < 0 || static_cast<unsigned>(i) >= n.get_nr_entries()) if (i < 0 || static_cast<unsigned>(i) >= n.get_nr_entries())
return optional<unsigned>(); return optional<unsigned>();
@ -92,7 +140,19 @@ namespace {
//------------------------------------------------ //------------------------------------------------
// //
template <uint32_t BlockSize> template <uint32_t BlockSize>
node &to_node(typename block_manager<BlockSize>::write_ref b); node_ref to_node(typename block_manager<BlockSize>::read_ref &b)
{
// FIXME: this should return a const read_ref somehow.
return node_ref(
reinterpret_cast<disk_node *>(const_cast<unsigned char *>(b.data())));
}
template <uint32_t BlockSize>
node_ref to_node(typename block_manager<BlockSize>::write_ref &b)
{
return node_ref(
reinterpret_cast<disk_node *>(const_cast<unsigned char *>(b.data())));
}
unsigned unsigned
calc_max_entries(uint32_t bs); calc_max_entries(uint32_t bs);
@ -101,62 +161,103 @@ namespace {
template <uint32_t BlockSize> template <uint32_t BlockSize>
class ro_spine : private noncopyable { class ro_spine : private noncopyable {
public: public:
void step(block_address b); ro_spine(typename transaction_manager<BlockSize>::ptr tm)
node get_node() const; : tm_(tm) {
}
void step(block_address b) {
spine_.push_back(tm_->read_lock(b));
if (spine_.size() > 2)
spine_.pop_front();
}
node_ref get_node() {
return to_node<BlockSize>(spine_.back());
}
private: private:
typename transaction_manager<BlockSize>::ptr tm_;
std::list<typename block_manager<BlockSize>::read_ref> spine_;
}; };
class internal_traits { template <uint32_t BlockSize>
class shadow_spine : private noncopyable {
public: public:
typedef uint64_t value_type; shadow_spine(typename transaction_manager<BlockSize>::ptr tm)
: tm_(tm) {
}
void step(block_address b) {
spine_.push_back(tm_->shadow(b));
if (spine_.size() == 1)
root_ = spine_.front().get_location();
else if (spine_.size() > 2)
spine_.pop_front();
}
node_ref get_node() {
return to_node<BlockSize>(spine_.back());
}
node_ref get_parent() {
if (spine_.size() < 2)
throw std::runtime_error("no parent");
return to_node<BlockSize>(spine_.front());
}
node_ref get_root() {
return root_;
}
private:
typename transaction_manager<BlockSize>::ptr tm_;
std::list<typename block_manager<BlockSize>::write_ref> spine_;
block_address root_;
}; };
template <typename ValueTraits, uint32_t BlockSize, typename Search> template <typename ValueTraits, uint32_t BlockSize> //, typename Search>
optional<typename ValueTraits::value_type> optional<typename ValueTraits::value_type>
lookup_raw(ro_spine<BlockSize> &spine, block_address block, uint64_t key) { lookup_raw(ro_spine<BlockSize> &spine, block_address block, uint64_t key) {
using namespace boost; using namespace boost;
typedef typename ValueTraits::value_type leaf_type; typedef typename ValueTraits::value_type leaf_type;
typedef typename internal_traits::value_type internal_type;
Search find;
for (;;) { for (;;) {
spine.step(block); spine.step(block);
node &n = spine.node(); node_ref const &n = spine.get_node();
auto mi = find(n, key); auto mi = exact_search(n, key);
if (!mi) if (!mi)
return optional<leaf_type>(); return optional<leaf_type>();
if (n.get_type() == node::LEAF) if (n.get_type() == node_ref::LEAF)
return optional<leaf_type>(n.value_at(*mi)); return optional<leaf_type>(n.value_at<ValueTraits>(*mi));
block = n.value_at<internal_type>(*mi); block = n.value_at<uint64_traits>(*mi);
} }
} }
} }
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize> template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
btree<Levels, ValueTraits, BlockSize>::btree(shared_ptr<transaction_manager<BlockSize> > tm) btree<Levels, ValueTraits, BlockSize>::btree(typename transaction_manager<BlockSize>::ptr tm)
: tm_(tm), : tm_(tm),
destroy_(false) destroy_(false)
{ {
write_ref root = tm_.new_block(); using namespace btree_detail;
node &n = to_node(root); write_ref root = tm_->new_block();
n.set_type(node::LEAF);
node_ref n = to_node<BlockSize>(root);
n.set_type(node_ref::LEAF);
n.set_nr_entries(0); n.set_nr_entries(0);
n.set_max_entries(calc_max_entries(BlockSize)); n.set_max_entries(calc_max_entries(BlockSize));
root_ = root.location(); root_ = root.get_location();
} }
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize> template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
btree<Levels, ValueTraits, BlockSize>::btree(shared_ptr<transaction_manager<BlockSize> > tm, btree<Levels, ValueTraits, BlockSize>::btree(typename transaction_manager<BlockSize>::ptr tm,
block_address root) block_address root)
: tm_(tm), : tm_(tm),
destroy_(false), destroy_(false),
@ -174,24 +275,29 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::maybe_value typename btree<Levels, ValueTraits, BlockSize>::maybe_value
btree<Levels, ValueTraits, BlockSize>::lookup(key const &key) const btree<Levels, ValueTraits, BlockSize>::lookup(key const &key) const
{ {
ro_spine<BlockSize> spine; using namespace btree_detail;
ro_spine<BlockSize> spine(tm_);
block_address root = root_; block_address root = root_;
for (unsigned level = 0; level < Levels - 1; ++level) { for (unsigned level = 0; level < Levels - 1; ++level) {
auto mroot = lookup_raw<internal_traits, BlockSize, exact_search>(spine, root, key[level]); optional<block_address> mroot =
lookup_raw<uint64_traits, BlockSize>(spine, root, key[level]);
if (!mroot) if (!mroot)
return maybe_value(); return maybe_value();
root = *mroot; root = *mroot;
} }
return lookup_raw<ValueTraits, BlockSize, exact_search>(spine, root, key[Levels - 1]); return lookup_raw<ValueTraits, BlockSize>(spine, root, key[Levels - 1]);
} }
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize> template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::maybe_pair typename btree<Levels, ValueTraits, BlockSize>::maybe_pair
btree<Levels, ValueTraits, BlockSize>::lookup_le(key const &key) const btree<Levels, ValueTraits, BlockSize>::lookup_le(key const &key) const
{ {
using namespace btree_detail;
return maybe_pair(); return maybe_pair();
} }
@ -199,6 +305,8 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::maybe_pair typename btree<Levels, ValueTraits, BlockSize>::maybe_pair
btree<Levels, ValueTraits, BlockSize>::lookup_ge(key const &key) const btree<Levels, ValueTraits, BlockSize>::lookup_ge(key const &key) const
{ {
using namespace btree_detail;
return maybe_pair(); return maybe_pair();
} }
@ -207,6 +315,7 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
void void
btree<Levels, ValueTraits, BlockSize>::insert(key const &key, typename ValueTraits::value_type const &value) btree<Levels, ValueTraits, BlockSize>::insert(key const &key, typename ValueTraits::value_type const &value)
{ {
using namespace btree_detail;
} }
@ -214,6 +323,7 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
void void
btree<Levels, ValueTraits, BlockSize>::remove(key const &key) btree<Levels, ValueTraits, BlockSize>::remove(key const &key)
{ {
using namespace btree_detail;
} }
@ -228,6 +338,7 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
void void
btree<Levels, ValueTraits, BlockSize>::set_root(block_address root) btree<Levels, ValueTraits, BlockSize>::set_root(block_address root)
{ {
using namespace btree_detail;
} }
@ -235,6 +346,7 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
block_address block_address
btree<Levels, ValueTraits, BlockSize>::get_root() const btree<Levels, ValueTraits, BlockSize>::get_root() const
{ {
using namespace btree_detail;
} }
@ -242,6 +354,7 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
ptr ptr
btree<Levels, ValueTraits, BlockSize>::clone() const btree<Levels, ValueTraits, BlockSize>::clone() const
{ {
using namespace btree_detail;
} }
@ -249,6 +362,7 @@ template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
void void
btree<Levels, ValueTraits, BlockSize>::destroy() btree<Levels, ValueTraits, BlockSize>::destroy()
{ {
using namespace btree_detail;
} }
#endif #endif

83
endian.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef ENDIAN_H
#define ENDIAN_H
#include <boost/static_assert.hpp>
//----------------------------------------------------------------
namespace base {
// These are just little wrapper types to make the compiler
// understand that the le types are not assignable to the
// corresponding cpu type.
struct __le16 {
explicit __le16(uint16_t v = 0.0)
: v_(v) {
}
uint16_t v_;
} __attribute__((packed));
struct __le32 {
explicit __le32(uint32_t v = 0.0)
: v_(v) {
}
uint32_t v_;
} __attribute__((packed));
struct __le64 {
explicit __le64(uint64_t v = 0.0)
: v_(v) {
}
uint64_t v_;
} __attribute__((packed));
//--------------------------------
template <typename CPUType, typename DiskType>
CPUType to_cpu(DiskType const &d) {
BOOST_STATIC_ASSERT(sizeof(d) == 0);
}
template <typename DiskType, typename CPUType>
DiskType to_disk(CPUType const &v) {
BOOST_STATIC_ASSERT(sizeof(v) == 0);
}
template <>
uint16_t to_cpu<uint16_t, __le16>(__le16 const &d) {
return d.v_;
}
template <>
__le16 to_disk<__le16, uint16_t>(uint16_t const &v) {
return __le16(v);
}
template <>
uint32_t to_cpu<uint32_t, __le32>(__le32 const &d) {
return d.v_;
}
template <>
__le32 to_disk<__le32, uint32_t>(uint32_t const &v) {
return __le32(v);
}
template <>
uint64_t to_cpu<uint64_t, __le64>(__le64 const &d) {
return d.v_;
}
template <>
__le64 to_disk<__le64, uint64_t>(uint64_t const &v) {
return __le64(v);
}
}
//----------------------------------------------------------------
#endif

View File

@ -115,7 +115,7 @@ metadata::create_thin(dev_t dev)
throw std::runtime_error("Device already exists"); throw std::runtime_error("Device already exists");
single_mapping_tree::ptr new_tree(new single_mapping_tree(tm_)); single_mapping_tree::ptr new_tree(new single_mapping_tree(tm_));
mappings_top_level_.insert(key, *new_tree); mappings_top_level_.insert(key, new_tree->get_root());
mappings_.set_root(mappings_top_level_.get_root()); // FIXME: ugly mappings_.set_root(mappings_top_level_.get_root()); // FIXME: ugly
} }
@ -125,12 +125,14 @@ metadata::create_snap(dev_t dev, dev_t origin)
uint64_t snap_key[1] = {dev}; uint64_t snap_key[1] = {dev};
uint64_t origin_key[1] = {origin}; uint64_t origin_key[1] = {origin};
auto mtree = mappings_top_level_.lookup(origin_key); auto mtree_root = mappings_top_level_.lookup(origin_key);
if (!mtree) if (!mtree_root)
throw std::runtime_error("unknown origin"); throw std::runtime_error("unknown origin");
single_mapping_tree::ptr clone(mtree->clone()); single_mapping_tree otree(tm_, *mtree_root);
mappings_top_level_.insert(snap_key, *clone);
single_mapping_tree::ptr clone(otree.clone());
mappings_top_level_.insert(snap_key, clone->get_root());
mappings_.set_root(mappings_top_level_.get_root()); // FIXME: ugly mappings_.set_root(mappings_top_level_.get_root()); // FIXME: ugly
time_++; time_++;

View File

@ -17,6 +17,54 @@
namespace multisnap { namespace multisnap {
typedef uint64_t sector_t; typedef uint64_t sector_t;
struct device_details_disk {
__le64 dev_size;
__le64 mapped_blocks;
__le64 transaction_id; /* when created */
__le32 creation_time;
__le32 snapshotted_time;
} __attribute__ ((packed));
struct device_details {
uint64_t dev_size;
uint64_t mapped_blocks;
uint64_t transaction_id; /* when created */
uint32_t creation_time;
uint32_t snapshotted_time;
};
struct detail_traits {
typedef device_details_disk disk_type;
typedef device_details value_type;
static value_type construct(void *data) {
struct device_details_disk disk;
struct device_details cpu;
::memcpy(&disk, data, sizeof(disk));
cpu.dev_size = to_cpu<uint64_t>(disk.dev_size);
cpu.mapped_blocks = to_cpu<uint64_t>(disk.mapped_blocks);
cpu.transaction_id = to_cpu<uint64_t>(disk.transaction_id);
cpu.creation_time = to_cpu<uint32_t>(disk.creation_time);
cpu.snapshotted_time = to_cpu<uint32_t>(disk.snapshotted_time);
return cpu;
}
};
#if 0
class dev_traits {
public:
typedef base::__le64 disk_type;
typedef persistent_data::btree<1, uint64_traits, BLOCK_SIZE> value_type;
static value_type construct(void *data) {
uint64_t root = uint64_traits::construct(data);
return value_type
}
};
#endif
class metadata { class metadata {
public: public:
typedef boost::shared_ptr<metadata> ptr; typedef boost::shared_ptr<metadata> ptr;
@ -75,29 +123,14 @@ namespace multisnap {
bool device_exists(dev_t dev) const; bool device_exists(dev_t dev) const;
class detail_traits {
public:
typedef uint64_t value_type;
};
class map_traits {
public:
typedef block_address value_type;
};
class dev_traits {
public:
typedef persistent_data::btree<1, map_traits, BLOCK_SIZE> value_type;
};
uint32_t time_; uint32_t time_;
persistent_data::transaction_manager<BLOCK_SIZE>::ptr tm_; persistent_data::transaction_manager<BLOCK_SIZE>::ptr tm_;
typedef persistent_data::btree<1, detail_traits, BLOCK_SIZE> detail_tree; typedef persistent_data::btree<1, detail_traits, BLOCK_SIZE> detail_tree;
typedef persistent_data::btree<1, dev_traits, BLOCK_SIZE> dev_tree; typedef persistent_data::btree<1, uint64_traits, BLOCK_SIZE> dev_tree;
typedef persistent_data::btree<2, map_traits, BLOCK_SIZE> mapping_tree; typedef persistent_data::btree<2, uint64_traits, BLOCK_SIZE> mapping_tree;
typedef persistent_data::btree<1, map_traits, BLOCK_SIZE> single_mapping_tree; typedef persistent_data::btree<1, uint64_traits, BLOCK_SIZE> single_mapping_tree;
detail_tree details_; detail_tree details_;
dev_tree mappings_top_level_; dev_tree mappings_top_level_;

View File

@ -54,6 +54,8 @@ namespace persistent_data {
}; };
} }
#include "transaction_manager.tcc"
//---------------------------------------------------------------- //----------------------------------------------------------------
#endif #endif