change sm->new_block() to return an optional

This commit is contained in:
Joe Thornber 2011-11-16 12:53:37 +00:00
parent 404ca5ba30
commit 876dd2427f
6 changed files with 59 additions and 22 deletions

View File

@ -5,6 +5,7 @@
#include "block_counter.h" #include "block_counter.h"
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -25,7 +26,14 @@ namespace persistent_data {
virtual void inc(block_address b) = 0; virtual void inc(block_address b) = 0;
virtual void dec(block_address b) = 0; virtual void dec(block_address b) = 0;
virtual block_address new_block() = 0;
// FIXME: change these to return an optional, failure is
// not that rare if we're restricting the area that's
// searched.
typedef boost::optional<block_address> maybe_block;
virtual maybe_block new_block() = 0;
virtual maybe_block new_block(block_address begin, block_address end) = 0;
virtual bool count_possibly_greater_than_one(block_address b) const = 0; virtual bool count_possibly_greater_than_one(block_address b) const = 0;

View File

@ -52,15 +52,19 @@ namespace persistent_data {
nr_free_++; nr_free_++;
} }
block_address new_block() { maybe_block new_block() {
for (block_address i = 0; i < counts_.size(); i++) return new_block(0, counts_.size());
}
maybe_block new_block(block_address begin, block_address end) {
for (block_address i = begin; i < min(end, counts_.size()); i++)
if (counts_[i] == 0) { if (counts_[i] == 0) {
counts_[i] = 1; counts_[i] = 1;
nr_free_--; nr_free_--;
return i; return i;
} }
throw std::runtime_error("no space"); return maybe_block();
} }
bool count_possibly_greater_than_one(block_address b) const { bool count_possibly_greater_than_one(block_address b) const {

View File

@ -290,16 +290,22 @@ namespace {
set_count(b, old - 1); set_count(b, old - 1);
} }
block_address new_block() { maybe_block new_block() {
// FIXME: silly to always start searching from the // FIXME: keep track of the lowest free block so we
// beginning. // can start searching from a suitable place.
block_address nr_indexes = div_up<block_address>(nr_blocks_, ENTRIES_PER_BLOCK); return new_block(0, nr_blocks_);
for (block_address index = 0; index < nr_indexes; index++) { }
maybe_block new_block(block_address begin, block_address end) {
block_address begin_index = begin / ENTRIES_PER_BLOCK;
block_address end_index = div_up<block_address>(end, ENTRIES_PER_BLOCK);
for (block_address index = begin_index; index < end_index; index++) {
index_entry ie = indexes_->find_ie(index); index_entry ie = indexes_->find_ie(index);
bitmap bm(tm_, ie); bitmap bm(tm_, ie);
optional<unsigned> maybe_b = bm.find_free(0, (index == nr_indexes - 1) ? optional<unsigned> maybe_b = bm.find_free((index == begin_index) ? (begin % ENTRIES_PER_BLOCK) : 0,
nr_blocks_ % ENTRIES_PER_BLOCK : ENTRIES_PER_BLOCK); (index == end_index - 1) ? (end % ENTRIES_PER_BLOCK) : ENTRIES_PER_BLOCK);
if (maybe_b) { if (maybe_b) {
block_address b = *maybe_b; block_address b = *maybe_b;
indexes_->save_ie(index, bm.get_ie()); indexes_->save_ie(index, bm.get_ie());
@ -310,7 +316,7 @@ namespace {
} }
} }
throw runtime_error("out of space"); return maybe_block();
} }
bool count_possibly_greater_than_one(block_address b) const { bool count_possibly_greater_than_one(block_address b) const {

View File

@ -85,14 +85,21 @@ namespace {
} }
} }
virtual block_address new_block() { // new_block must not recurse.
// new_block can recurse, because we know it's virtual boost::optional<block_address>
// looking up entries in the _previous_ new_block() {
// transaction. cant_recurse("new_block");
recursing_lock lock(*this); recursing_lock lock(*this);
return sm_->new_block(); return sm_->new_block();
} }
virtual boost::optional<block_address>
new_block(block_address begin, block_address end) {
cant_recurse("new_block(range)");
recursing_lock lock(*this);
return sm_->new_block(begin, end);
}
virtual bool count_possibly_greater_than_one(block_address b) const { virtual bool count_possibly_greater_than_one(block_address b) const {
if (depth_) if (depth_)
return true; return true;

View File

@ -167,7 +167,11 @@ thin_pool::get_held_root() const
block_address block_address
thin_pool::alloc_data_block() thin_pool::alloc_data_block()
{ {
return md_->data_sm_->new_block(); optional<block_address> mb = md_->data_sm_->new_block();
if (!mb)
throw runtime_error("couldn't allocate new block");
return *mb;
} }
void void

View File

@ -30,10 +30,13 @@ transaction_manager::begin(block_address superblock, validator v)
transaction_manager::write_ref transaction_manager::write_ref
transaction_manager::new_block(validator v) transaction_manager::new_block(validator v)
{ {
block_address b = sm_->new_block(); optional<block_address> mb = sm_->new_block();
sm_decrementer decrementer(sm_, b); if (!mb)
write_ref wr = bm_->write_lock_zero(b, v); throw runtime_error("couldn't allocate new block");
add_shadow(b);
sm_decrementer decrementer(sm_, *mb);
write_ref wr = bm_->write_lock_zero(*mb, v);
add_shadow(*mb);
decrementer.dont_bother(); decrementer.dont_bother();
return wr; return wr;
} }
@ -46,7 +49,12 @@ transaction_manager::shadow(block_address orig, validator v)
return make_pair(bm_->write_lock(orig, v), false); return make_pair(bm_->write_lock(orig, v), false);
read_ref src = bm_->read_lock(orig, v); read_ref src = bm_->read_lock(orig, v);
write_ref dest = bm_->write_lock_zero(sm_->new_block(), v);
optional<block_address> mb = sm_->new_block();
if (!mb)
throw runtime_error("couldn't allocate new block");
write_ref dest = bm_->write_lock_zero(*mb, v);
::memcpy(dest.data(), src.data(), MD_BLOCK_SIZE); ::memcpy(dest.data(), src.data(), MD_BLOCK_SIZE);
ref_t count = sm_->get_count(orig); ref_t count = sm_->get_count(orig);