block_manager and unit test

This commit is contained in:
Joe Thornber
2011-07-13 15:09:33 +01:00
parent c090bb88b5
commit 8a7f0214d3
4 changed files with 208 additions and 44 deletions

View File

@@ -16,7 +16,7 @@ using namespace std;
//----------------------------------------------------------------
template <uint32_t BlockSize>
block_manager<BlockSize>::read_ref::read_ref(block_manager::block_ptr b)
block_manager<BlockSize>::read_ref::read_ref(typename block_manager::block::ptr b)
: block_(b)
{
}
@@ -36,7 +36,7 @@ block_manager<BlockSize>::read_ref::data() const
}
template <uint32_t BlockSize>
block_manager<BlockSize>::write_ref::write_ref(block_manager::block_ptr b)
block_manager<BlockSize>::write_ref::write_ref(typename block_manager::block::ptr b)
: read_ref(b)
{
}
@@ -51,9 +51,10 @@ block_manager<BlockSize>::write_ref::data()
//----------------------------------------------------------------
template <uint32_t BlockSize>
block_manager<BlockSize>::block_manager(std::string const &path)
block_manager<BlockSize>::block_manager(std::string const &path, block_address nr_blocks)
: nr_blocks_(nr_blocks)
{
fd_ = ::open(path.c_str(), O_RDWR | O_EXCL);
fd_ = ::open(path.c_str(), O_RDWR | O_CREAT, 0666);
if (fd_ < 0)
throw std::runtime_error("couldn't open file");
}
@@ -66,16 +67,18 @@ block_manager<BlockSize>::~block_manager()
template <uint32_t BlockSize>
typename block_manager<BlockSize>::read_ref
block_manager<BlockSize>::read_lock(block_address location)
block_manager<BlockSize>::read_lock(block_address location) const
{
block_ptr b(new block(location));
check(location);
typename block::ptr b(new block(location));
read_block(*b);
return read_ref(b);
}
template <uint32_t BlockSize>
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) const
{
return read_lock(location);
}
@@ -84,7 +87,9 @@ template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock(block_address location)
{
block_ptr b(new block(location), bind(&block_manager::write_and_release, this, _1));
check(location);
typename block::ptr b(new block(location), bind(&block_manager::write_and_release, this, _1));
read_block(*b);
return write_ref(b);
}
@@ -93,7 +98,9 @@ template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock_zero(block_address location)
{
block_ptr b(new block(location), bind(&block_manager<BlockSize>::write_and_release, this, _1));
check(location);
typename block::ptr b(new block(location), bind(&block_manager<BlockSize>::write_and_release, this, _1));
zero_block(*b);
return write_ref(b);
}
@@ -101,9 +108,11 @@ block_manager<BlockSize>::write_lock_zero(block_address location)
template <uint32_t BlockSize>
typename block_manager<BlockSize>::read_ref
block_manager<BlockSize>::read_lock(block_address location,
typename block_manager<BlockSize>::block_validator::ptr const &v)
typename block_manager<BlockSize>::validator::ptr const &v) const
{
block_ptr b(new block(location, v));
check(location);
typename block::ptr b(new block(location, v));
read_block(*b);
return read_ref(b);
}
@@ -111,7 +120,7 @@ block_manager<BlockSize>::read_lock(block_address location,
template <uint32_t BlockSize>
optional<typename block_manager<BlockSize>::read_ref>
block_manager<BlockSize>::read_try_lock(block_address location,
typename block_manager<BlockSize>::block_validator::ptr const &v)
typename block_manager<BlockSize>::validator::ptr const &v) const
{
return read_lock(location, v);
}
@@ -119,9 +128,12 @@ block_manager<BlockSize>::read_try_lock(block_address location,
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock(block_address location,
typename block_manager<BlockSize>::block_validator::ptr const &v)
typename block_manager<BlockSize>::validator::ptr const &v)
{
block_ptr b(new block(location, v), write_and_release);
check(location);
typename block::ptr b(new block(location, v),
bind(&block_manager::write_and_release, this, _1));
read_block(*b);
return write_ref(b);
}
@@ -129,9 +141,12 @@ block_manager<BlockSize>::write_lock(block_address location,
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock_zero(block_address location,
typename block_manager<BlockSize>::block_validator::ptr const &v)
typename block_manager<BlockSize>::validator::ptr const &v)
{
block_ptr b(new block(location, v), write_and_release);
check(location);
typename block::ptr b(new block(location, v),
bind(&block_manager::write_and_release, this, _1));
zero_block(*b);
return write_ref(b);
}
@@ -140,16 +155,16 @@ template <uint32_t BlockSize>
void
block_manager<BlockSize>::flush(block_manager<BlockSize>::write_ref super_block)
{
// FIXME: the caller still holds the write_ref, so the superblock
// will get written twice
write_block(super_block);
::fsync(fd_);
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::read_block(block &b)
block_manager<BlockSize>::read_block(block &b) const
{
std::cerr << "reading block: " << b.location_ << std::endl;
off_t r;
r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
if (r == (off_t) -1)
@@ -168,15 +183,14 @@ block_manager<BlockSize>::read_block(block &b)
if (n < 0)
throw std::runtime_error("read failed");
b.initialised_ = true;
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::write_block(block const &b)
{
std::cerr << "writing block: " << b.location_ << std::endl;
off_t r;
r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
if (r == (off_t) -1)
@@ -202,14 +216,29 @@ void
block_manager<BlockSize>::zero_block(block &b)
{
memset(b.data_, 0, BlockSize);
b.initialised_ = true;
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::write_and_release(block *b)
{
write_block(*b);
if (b->initialised_) {
if (b->validator_)
(*b->validator_)->prepare(*b);
write_block(*b);
}
delete b;
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::check(block_address b) const
{
if (b >= nr_blocks_)
throw std::runtime_error("block address out of bounds");
}
//----------------------------------------------------------------