change sm->new_block() to return an optional
This commit is contained in:
parent
404ca5ba30
commit
876dd2427f
10
space_map.h
10
space_map.h
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user