[block_manager] Track the number of superblocks, throw an exception if someone tries to open two a once.
This commit is contained in:
		@@ -78,17 +78,17 @@ namespace persistent_data {
 | 
			
		||||
		class write_ref : public read_ref {
 | 
			
		||||
		public:
 | 
			
		||||
			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;
 | 
			
		||||
			void *data();
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		class super_ref : public write_ref {
 | 
			
		||||
		public:
 | 
			
		||||
			super_ref(block_cache::block &b);
 | 
			
		||||
 | 
			
		||||
			using read_ref::data;
 | 
			
		||||
			using write_ref::data;
 | 
			
		||||
		private:
 | 
			
		||||
			unsigned *ref_count_;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		// Locking methods
 | 
			
		||||
@@ -140,6 +140,7 @@ namespace persistent_data {
 | 
			
		||||
 | 
			
		||||
		int fd_;
 | 
			
		||||
		mutable block_cache bc_;
 | 
			
		||||
		unsigned superblock_ref_count_;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// A little utility to help build validators
 | 
			
		||||
 
 | 
			
		||||
@@ -152,10 +152,51 @@ namespace persistent_data {
 | 
			
		||||
 | 
			
		||||
	template <uint32_t BlockSize>
 | 
			
		||||
	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>
 | 
			
		||||
	void *
 | 
			
		||||
	block_manager<BlockSize>::write_ref::data()
 | 
			
		||||
@@ -163,14 +204,6 @@ namespace persistent_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>
 | 
			
		||||
@@ -179,7 +212,8 @@ namespace persistent_data {
 | 
			
		||||
						unsigned max_concurrent_blocks,
 | 
			
		||||
						mode 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)
 | 
			
		||||
	{
 | 
			
		||||
		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>
 | 
			
		||||
@@ -244,7 +278,7 @@ namespace persistent_data {
 | 
			
		||||
						  typename bcache::validator::ptr 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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user