2011-06-23 19:17:08 +05:30
|
|
|
#include "block.h"
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2011-06-27 15:15:30 +05:30
|
|
|
#include <boost/bind.hpp>
|
2011-06-23 19:17:08 +05:30
|
|
|
#include <iostream>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
using namespace boost;
|
|
|
|
using namespace persistent_data;
|
2011-06-27 15:15:30 +05:30
|
|
|
using namespace std;
|
2011-06-23 19:17:08 +05:30
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
block_manager<BlockSize>::read_ref::read_ref(block_manager::block_ptr b)
|
|
|
|
: block_(b)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
block_address
|
|
|
|
block_manager<BlockSize>::read_ref::get_location() const
|
|
|
|
{
|
|
|
|
return block_->location_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::const_buffer &
|
|
|
|
block_manager<BlockSize>::read_ref::data() const
|
|
|
|
{
|
|
|
|
return block_->data_;
|
|
|
|
}
|
|
|
|
|
2011-06-27 15:15:30 +05:30
|
|
|
template <uint32_t BlockSize>
|
|
|
|
block_manager<BlockSize>::write_ref::write_ref(block_manager::block_ptr b)
|
|
|
|
: read_ref(b)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-06-23 19:17:08 +05:30
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::buffer &
|
|
|
|
block_manager<BlockSize>::write_ref::data()
|
|
|
|
{
|
|
|
|
return read_ref::block_->data_;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
block_manager<BlockSize>::block_manager(std::string const &path)
|
|
|
|
{
|
|
|
|
fd_ = ::open(path.c_str(), O_RDWR | O_EXCL);
|
|
|
|
if (fd_ < 0)
|
|
|
|
throw std::runtime_error("couldn't open file");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
block_manager<BlockSize>::~block_manager()
|
|
|
|
{
|
|
|
|
::close(fd_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::read_ref
|
|
|
|
block_manager<BlockSize>::read_lock(block_address location)
|
|
|
|
{
|
|
|
|
block_ptr b(new block(location));
|
2011-06-27 15:15:30 +05:30
|
|
|
read_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
return read_ref(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
optional<typename block_manager<BlockSize>::read_ref>
|
|
|
|
block_manager<BlockSize>::read_try_lock(block_address location)
|
|
|
|
{
|
|
|
|
return read_lock(location);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::write_ref
|
|
|
|
block_manager<BlockSize>::write_lock(block_address location)
|
|
|
|
{
|
2011-06-27 15:15:30 +05:30
|
|
|
block_ptr b(new block(location), bind(&block_manager::write_and_release, this, _1));
|
|
|
|
read_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
return write_ref(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::write_ref
|
|
|
|
block_manager<BlockSize>::write_lock_zero(block_address location)
|
|
|
|
{
|
2011-06-27 15:15:30 +05:30
|
|
|
block_ptr b(new block(location), bind(&block_manager<BlockSize>::write_and_release, this, _1));
|
|
|
|
zero_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
return write_ref(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::read_ref
|
|
|
|
block_manager<BlockSize>::read_lock(block_address location,
|
2011-06-27 15:15:30 +05:30
|
|
|
typename block_manager<BlockSize>::block_validator::ptr const &v)
|
2011-06-23 19:17:08 +05:30
|
|
|
{
|
|
|
|
block_ptr b(new block(location, v));
|
2011-06-27 15:15:30 +05:30
|
|
|
read_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
return read_ref(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
optional<typename block_manager<BlockSize>::read_ref>
|
|
|
|
block_manager<BlockSize>::read_try_lock(block_address location,
|
2011-06-27 15:15:30 +05:30
|
|
|
typename block_manager<BlockSize>::block_validator::ptr const &v)
|
2011-06-23 19:17:08 +05:30
|
|
|
{
|
|
|
|
return read_lock(location, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::write_ref
|
|
|
|
block_manager<BlockSize>::write_lock(block_address location,
|
2011-06-27 15:15:30 +05:30
|
|
|
typename block_manager<BlockSize>::block_validator::ptr const &v)
|
2011-06-23 19:17:08 +05:30
|
|
|
{
|
|
|
|
block_ptr b(new block(location, v), write_and_release);
|
2011-06-27 15:15:30 +05:30
|
|
|
read_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
return write_ref(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
typename block_manager<BlockSize>::write_ref
|
|
|
|
block_manager<BlockSize>::write_lock_zero(block_address location,
|
2011-06-27 15:15:30 +05:30
|
|
|
typename block_manager<BlockSize>::block_validator::ptr const &v)
|
2011-06-23 19:17:08 +05:30
|
|
|
{
|
|
|
|
block_ptr b(new block(location, v), write_and_release);
|
2011-06-27 15:15:30 +05:30
|
|
|
zero_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
return write_ref(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
void
|
|
|
|
block_manager<BlockSize>::flush(block_manager<BlockSize>::write_ref super_block)
|
|
|
|
{
|
|
|
|
write_block(super_block);
|
|
|
|
::fsync(fd_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
void
|
|
|
|
block_manager<BlockSize>::read_block(block &b)
|
|
|
|
{
|
2011-06-27 15:15:30 +05:30
|
|
|
std::cerr << "reading block: " << b.location_ << std::endl;
|
2011-06-23 19:17:08 +05:30
|
|
|
|
|
|
|
off_t r;
|
2011-06-27 15:15:30 +05:30
|
|
|
r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
|
2011-06-23 19:17:08 +05:30
|
|
|
if (r == (off_t) -1)
|
|
|
|
throw std::runtime_error("lseek failed");
|
|
|
|
|
|
|
|
ssize_t n;
|
|
|
|
size_t remaining = BlockSize;
|
2011-06-27 15:15:30 +05:30
|
|
|
unsigned char *buf = b.data_;
|
2011-06-23 19:17:08 +05:30
|
|
|
do {
|
|
|
|
n = ::read(fd_, buf, remaining);
|
|
|
|
if (n > 0) {
|
|
|
|
remaining -= n;
|
|
|
|
buf += n;
|
|
|
|
}
|
|
|
|
} while (remaining && ((n > 0) || (n == EINTR) || (n == EAGAIN)));
|
|
|
|
|
|
|
|
if (n < 0)
|
|
|
|
throw std::runtime_error("read failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
void
|
|
|
|
block_manager<BlockSize>::write_block(block const &b)
|
|
|
|
{
|
|
|
|
|
2011-06-27 15:15:30 +05:30
|
|
|
std::cerr << "writing block: " << b.location_ << std::endl;
|
2011-06-23 19:17:08 +05:30
|
|
|
|
|
|
|
off_t r;
|
2011-06-27 15:15:30 +05:30
|
|
|
r = ::lseek(fd_, BlockSize * b.location_, SEEK_SET);
|
2011-06-23 19:17:08 +05:30
|
|
|
if (r == (off_t) -1)
|
|
|
|
throw std::runtime_error("lseek failed");
|
|
|
|
|
|
|
|
ssize_t n;
|
|
|
|
size_t remaining = BlockSize;
|
2011-06-27 15:15:30 +05:30
|
|
|
unsigned char const *buf = b.data_;
|
2011-06-23 19:17:08 +05:30
|
|
|
do {
|
2011-06-27 15:15:30 +05:30
|
|
|
n = ::write(fd_, buf, remaining);
|
2011-06-23 19:17:08 +05:30
|
|
|
if (n > 0) {
|
|
|
|
remaining -= n;
|
|
|
|
buf += n;
|
|
|
|
}
|
|
|
|
} while (remaining && ((n > 0) || (n == EINTR) || (n == EAGAIN)));
|
|
|
|
|
|
|
|
if (n < 0)
|
|
|
|
throw std::runtime_error("write failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
void
|
|
|
|
block_manager<BlockSize>::zero_block(block &b)
|
|
|
|
{
|
2011-06-27 15:15:30 +05:30
|
|
|
memset(b.data_, 0, BlockSize);
|
2011-06-23 19:17:08 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
template <uint32_t BlockSize>
|
|
|
|
void
|
|
|
|
block_manager<BlockSize>::write_and_release(block *b)
|
|
|
|
{
|
2011-06-27 15:15:30 +05:30
|
|
|
write_block(*b);
|
2011-06-23 19:17:08 +05:30
|
|
|
delete b;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|