some streamlining of the block interface

This commit is contained in:
Joe Thornber
2011-07-14 14:05:07 +01:00
parent e77ed189bb
commit a0cae447f6
3 changed files with 260 additions and 77 deletions

170
block.tcc
View File

@@ -52,7 +52,10 @@ block_manager<BlockSize>::write_ref::data()
template <uint32_t BlockSize>
block_manager<BlockSize>::block_manager(std::string const &path, block_address nr_blocks)
: nr_blocks_(nr_blocks)
: nr_blocks_(nr_blocks),
lock_count_(0),
superblock_count_(0),
ordinary_count_(0)
{
fd_ = ::open(path.c_str(), O_RDWR | O_CREAT, 0666);
if (fd_ < 0)
@@ -71,9 +74,12 @@ block_manager<BlockSize>::read_lock(block_address location) const
{
check(location);
typename block::ptr b(new block(location));
read_block(*b);
return read_ref(b);
buffer buf;
read_buffer(location, buf);
return read_ref(
typename block::ptr(
new block(location, buf, lock_count_, ordinary_count_)));
}
template <uint32_t BlockSize>
@@ -89,9 +95,12 @@ block_manager<BlockSize>::write_lock(block_address location)
{
check(location);
typename block::ptr b(new block(location), bind(&block_manager::write_and_release, this, _1));
read_block(*b);
return write_ref(b);
buffer buf;
read_buffer(location, buf);
return write_ref(
typename block::ptr(
new block(location, buf, lock_count_, ordinary_count_),
bind(&block_manager::write_release, this, _1)));
}
template <uint32_t BlockSize>
@@ -100,27 +109,30 @@ block_manager<BlockSize>::write_lock_zero(block_address location)
{
check(location);
typename block::ptr b(new block(location), bind(&block_manager<BlockSize>::write_and_release, this, _1));
zero_block(*b);
buffer buf;
zero_buffer(buf);
typename block::ptr b(new block(location, buf, lock_count_, ordinary_count_),
bind(&block_manager<BlockSize>::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::read_ref
block_manager<BlockSize>::read_lock(block_address location,
typename block_manager<BlockSize>::validator::ptr const &v) const
typename block_manager<BlockSize>::validator::ptr v) const
{
check(location);
typename block::ptr b(new block(location, v));
read_block(*b);
buffer buf;
read_buffer(location, buf);
typename block::ptr b(new block(location, buf, lock_count_, ordinary_count_, false, v));
return read_ref(b);
}
template <uint32_t BlockSize>
optional<typename block_manager<BlockSize>::read_ref>
block_manager<BlockSize>::read_try_lock(block_address location,
typename block_manager<BlockSize>::validator::ptr const &v) const
typename block_manager<BlockSize>::validator::ptr v) const
{
return read_lock(location, v);
}
@@ -128,51 +140,118 @@ 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>::validator::ptr const &v)
typename block_manager<BlockSize>::validator::ptr v)
{
check(location);
typename block::ptr b(new block(location, v),
bind(&block_manager::write_and_release, this, _1));
read_block(*b);
buffer buf;
read_buffer(location, buf);
typename block::ptr b(new block(location, buf, lock_count_, ordinary_count_, false, v),
bind(&block_manager::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::write_lock_zero(block_address location,
typename block_manager<BlockSize>::validator::ptr const &v)
typename block_manager<BlockSize>::validator::ptr v)
{
check(location);
typename block::ptr b(new block(location, v),
bind(&block_manager::write_and_release, this, _1));
zero_block(*b);
buffer buf;
zero_buffer(buf);
typename block::ptr b(new block(location, buf, lock_count_, ordinary_count_, false, v),
bind(&block_manager::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::superblock(block_address location)
{
check(location);
if (superblock_count_ > 0)
throw runtime_error("already have superblock");
buffer buf;
read_buffer(location, buf);
typename block::ptr b(new block(location, buf, lock_count_, superblock_count_, true),
bind(&block_manager::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::superblock_zero(block_address location)
{
check(location);
if (superblock_count_ > 0)
throw runtime_error("already have superblock");
buffer buf;
zero_buffer(buf);
typename block::ptr b(new block(location, buf, lock_count_, superblock_count_, true),
bind(&block_manager::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::superblock(block_address location,
typename block_manager<BlockSize>::validator::ptr v)
{
if (superblock_count_ > 0)
throw runtime_error("already have superblock");
check(location);
buffer buf;
read_buffer(location, buf);
typename block::ptr b(new block(location, buf, lock_count_, superblock_count_, true, v),
bind(&block_manager::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref
block_manager<BlockSize>::superblock_zero(block_address location,
typename block_manager<BlockSize>::validator::ptr v)
{
if (superblock_count_ > 0)
throw runtime_error("already have superblock");
check(location);
buffer buf;
zero_buffer(buf);
typename block::ptr b(new block(location, buf, lock_count_, superblock_count_, true, v),
bind(&block_manager::write_release, this, _1));
return write_ref(b);
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::flush(block_manager<BlockSize>::write_ref super_block)
block_manager<BlockSize>::flush()
{
// FIXME: the caller still holds the write_ref, so the superblock
// will get written twice
write_block(super_block);
if (lock_count_ > 0)
throw runtime_error("asked to flush while locks are still held");
::fsync(fd_);
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::read_block(block &b) const
block_manager<BlockSize>::read_buffer(block_address b, block_manager<BlockSize>::buffer &buffer) const
{
off_t r;
r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
r = ::lseek(fd_, BlockSize * b, SEEK_SET);
if (r == (off_t) -1)
throw std::runtime_error("lseek failed");
ssize_t n;
size_t remaining = BlockSize;
unsigned char *buf = b.data_;
unsigned char *buf = buffer;
do {
n = ::read(fd_, buf, remaining);
if (n > 0) {
@@ -183,22 +262,20 @@ block_manager<BlockSize>::read_block(block &b) const
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)
block_manager<BlockSize>::write_buffer(block_address b, block_manager<BlockSize>::const_buffer &buffer)
{
off_t r;
r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
r = ::lseek(fd_, BlockSize * b, SEEK_SET);
if (r == (off_t) -1)
throw std::runtime_error("lseek failed");
ssize_t n;
size_t remaining = BlockSize;
unsigned char const *buf = b.data_;
unsigned char const *buf = buffer;
do {
n = ::write(fd_, buf, remaining);
if (n > 0) {
@@ -213,23 +290,32 @@ block_manager<BlockSize>::write_block(block const &b)
template <uint32_t BlockSize>
void
block_manager<BlockSize>::zero_block(block &b)
block_manager<BlockSize>::zero_buffer(block_manager<BlockSize>::buffer &buffer) const
{
memset(b.data_, 0, BlockSize);
b.initialised_ = true;
memset(buffer, 0, BlockSize);
}
// FIXME: we don't need this anymore
template <uint32_t BlockSize>
void
block_manager<BlockSize>::read_release(block *b) const
{
delete b;
}
template <uint32_t BlockSize>
void
block_manager<BlockSize>::write_and_release(block *b)
block_manager<BlockSize>::write_release(block *b)
{
if (b->initialised_) {
if (b->validator_)
(*b->validator_)->prepare(*b);
write_block(*b);
if (b->is_superblock_) {
if (lock_count_ != 1)
throw runtime_error("superblock isn't the last block");
}
if (b->validator_)
(*b->validator_)->prepare(*b);
write_buffer(b->location_, b->data_);
delete b;
}