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 <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
//----------------------------------------------------------------
@ -25,7 +26,14 @@ namespace persistent_data {
virtual void inc(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;

View File

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

View File

@ -290,16 +290,22 @@ namespace {
set_count(b, old - 1);
}
block_address new_block() {
// FIXME: silly to always start searching from the
// beginning.
block_address nr_indexes = div_up<block_address>(nr_blocks_, ENTRIES_PER_BLOCK);
for (block_address index = 0; index < nr_indexes; index++) {
maybe_block new_block() {
// FIXME: keep track of the lowest free block so we
// can start searching from a suitable place.
return new_block(0, nr_blocks_);
}
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);
bitmap bm(tm_, ie);
optional<unsigned> maybe_b = bm.find_free(0, (index == nr_indexes - 1) ?
nr_blocks_ % ENTRIES_PER_BLOCK : ENTRIES_PER_BLOCK);
optional<unsigned> maybe_b = bm.find_free((index == begin_index) ? (begin % ENTRIES_PER_BLOCK) : 0,
(index == end_index - 1) ? (end % ENTRIES_PER_BLOCK) : ENTRIES_PER_BLOCK);
if (maybe_b) {
block_address b = *maybe_b;
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 {

View File

@ -85,14 +85,21 @@ namespace {
}
}
virtual block_address new_block() {
// new_block can recurse, because we know it's
// looking up entries in the _previous_
// transaction.
// new_block must not recurse.
virtual boost::optional<block_address>
new_block() {
cant_recurse("new_block");
recursing_lock lock(*this);
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 {
if (depth_)
return true;

View File

@ -167,7 +167,11 @@ thin_pool::get_held_root() const
block_address
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

View File

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