[block_manager] Track the number of superblocks, throw an exception if someone tries to open two a once.

This commit is contained in:
Joe Thornber 2014-08-21 11:17:20 +01:00
parent 94356a1648
commit 6f804cab24
2 changed files with 54 additions and 19 deletions

View File

@ -78,17 +78,17 @@ namespace persistent_data {
class write_ref : public read_ref { class write_ref : public read_ref {
public: public:
write_ref(block_cache::block &b); write_ref(block_cache::block &b);
write_ref(block_cache::block &b, unsigned &ref_count);
write_ref(write_ref const &rhs);
~write_ref();
write_ref const &operator =(write_ref const &rhs);
using read_ref::data; using read_ref::data;
void *data(); void *data();
};
class super_ref : public write_ref { private:
public: unsigned *ref_count_;
super_ref(block_cache::block &b);
using read_ref::data;
using write_ref::data;
}; };
// Locking methods // Locking methods
@ -140,6 +140,7 @@ namespace persistent_data {
int fd_; int fd_;
mutable block_cache bc_; mutable block_cache bc_;
unsigned superblock_ref_count_;
}; };
// A little utility to help build validators // A little utility to help build validators

View File

@ -152,10 +152,51 @@ namespace persistent_data {
template <uint32_t BlockSize> template <uint32_t BlockSize>
block_manager<BlockSize>::write_ref::write_ref(block_cache::block &b) block_manager<BlockSize>::write_ref::write_ref(block_cache::block &b)
: read_ref(b) : read_ref(b),
ref_count_(NULL)
{ {
} }
template <uint32_t BlockSize>
block_manager<BlockSize>::write_ref::write_ref(block_cache::block &b, unsigned &ref_count)
: read_ref(b),
ref_count_(&ref_count) {
if (*ref_count_)
throw std::runtime_error("superblock already locked");
(*ref_count_)++;
}
template <uint32_t BlockSize>
block_manager<BlockSize>::write_ref::write_ref(write_ref const &rhs)
: read_ref(rhs),
ref_count_(rhs.ref_count_) {
if (ref_count_)
(*ref_count_)++;
}
template <uint32_t BlockSize>
block_manager<BlockSize>::write_ref::~write_ref()
{
if (ref_count_) {
if (!*ref_count_)
throw std::runtime_error("write_ref ref_count going below zero");
(*ref_count_)--;
}
}
template <uint32_t BlockSize>
typename block_manager<BlockSize>::write_ref const &
block_manager<BlockSize>::write_ref::operator =(write_ref const &rhs)
{
if (&rhs != this) {
read_ref::operator =(rhs);
ref_count_ = rhs.ref_count_;
if (ref_count_)
(*ref_count_)++;
}
}
template <uint32_t BlockSize> template <uint32_t BlockSize>
void * void *
block_manager<BlockSize>::write_ref::data() block_manager<BlockSize>::write_ref::data()
@ -163,14 +204,6 @@ namespace persistent_data {
return read_ref::b_.get_data(); return read_ref::b_.get_data();
} }
//--------------------------------
template <uint32_t BlockSize>
block_manager<BlockSize>::super_ref::super_ref(block_cache::block &b)
: write_ref(b)
{
}
//---------------------------------------------------------------- //----------------------------------------------------------------
template <uint32_t BlockSize> template <uint32_t BlockSize>
@ -179,7 +212,8 @@ namespace persistent_data {
unsigned max_concurrent_blocks, unsigned max_concurrent_blocks,
mode m) mode m)
: fd_(open_or_create_block_file(path, nr_blocks * BlockSize, m)), : fd_(open_or_create_block_file(path, nr_blocks * BlockSize, m)),
bc_(fd_, BlockSize >> SECTOR_SHIFT, nr_blocks, 1024u * 1024u * 16) bc_(fd_, BlockSize >> SECTOR_SHIFT, nr_blocks, 1024u * 1024u * 16),
superblock_ref_count_(0)
{ {
} }
@ -235,7 +269,7 @@ namespace persistent_data {
typename bcache::validator::ptr v) typename bcache::validator::ptr v)
{ {
block_cache::block &b = bc_.get(location, block_cache::GF_BARRIER, v); block_cache::block &b = bc_.get(location, block_cache::GF_BARRIER, v);
return super_ref(b); return write_ref(b, superblock_ref_count_);
} }
template <uint32_t BlockSize> template <uint32_t BlockSize>
@ -244,7 +278,7 @@ namespace persistent_data {
typename bcache::validator::ptr v) typename bcache::validator::ptr v)
{ {
block_cache::block &b = bc_.get(location, block_cache::GF_ZERO | block_cache::GF_BARRIER, v); block_cache::block &b = bc_.get(location, block_cache::GF_ZERO | block_cache::GF_BARRIER, v);
return super_ref(b); return write_ref(b, superblock_ref_count_);
} }
template <uint32_t BlockSize> template <uint32_t BlockSize>