Updates to array_block

This commit is contained in:
Joe Thornber 2013-03-13 12:59:11 +00:00
parent 11a41c4cf4
commit 3c54e2b23a
2 changed files with 29 additions and 17 deletions

View File

@ -41,22 +41,26 @@ namespace persistent_data {
typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::value_type value_type;
typedef typename ValueTraits::ref_counter ref_counter; typedef typename ValueTraits::ref_counter ref_counter;
enum block_state {
BLOCK_NEW,
BLOCK_EXISTS
};
array_block(RefType ref, array_block(RefType ref,
ref_counter rc, ref_counter rc)
uint32_t value_size)
: ref_(ref), : ref_(ref),
rc_(rc) { rc_(rc) {
using namespace base;
struct array_block_disk *header = get_header();
header->max_entries = to_disk<__le32>(calc_max_entries(value_size));
header->nr_entries = to_disk<__le32>(static_cast<uint32_t>(0));
header->value_size = to_disk<__le32>(value_size);
} }
array_block(RefType ref, ref_counter rc) // I hate separate initialisation. But we can't have the
: ref_(ref), // constructor using non-const methods (get_header())
rc_(rc) { // otherwise we can't instance this with a read_ref.
void setup_empty() {
using namespace base;
struct array_block_disk *header = get_header();
header->max_entries = to_disk<__le32>(calc_max_entries());
header->nr_entries = to_disk<__le32>(static_cast<uint32_t>(0));
header->value_size = to_disk<__le32>(static_cast<uint32_t>(sizeof(disk_type)));
} }
uint32_t max_entries() const { uint32_t max_entries() const {
@ -74,8 +78,13 @@ namespace persistent_data {
void grow(uint32_t nr, value_type const &default_value) { void grow(uint32_t nr, value_type const &default_value) {
uint32_t old_nr = nr_entries(); uint32_t old_nr = nr_entries();
if (nr >= max_entries()) if (nr > max_entries()) {
throw runtime_error("array_block index out of bounds"); std::ostringstream out;
out << "array_block::grow called with more than max_entries ("
<< nr << " > " << max_entries();
throw runtime_error(out.str());
}
if (nr <= old_nr) if (nr <= old_nr)
throw runtime_error("array_block grow method called with smaller size"); throw runtime_error("array_block grow method called with smaller size");
@ -124,11 +133,12 @@ namespace persistent_data {
return rc_; return rc_;
} }
private: static uint32_t calc_max_entries() {
static uint32_t calc_max_entries(uint32_t value_size) { return (RefType::BLOCK_SIZE - sizeof(array_block_disk)) /
return (RefType::BLOCK_SIZE - sizeof(array_block_disk)) / value_size; sizeof(typename ValueTraits::disk_type);
} }
private:
void set_nr_entries(uint32_t nr) { void set_nr_entries(uint32_t nr) {
using namespace base; using namespace base;
array_block_disk *h = get_header(); array_block_disk *h = get_header();

View File

@ -98,7 +98,9 @@ namespace {
new_array_block(transaction_manager::ptr tm) { new_array_block(transaction_manager::ptr tm) {
uint64_traits::ref_counter rc(MAX_VALUE); uint64_traits::ref_counter rc(MAX_VALUE);
write_ref wr = tm->new_block(validator()); write_ref wr = tm->new_block(validator());
return make_pair(ablock64(wr, rc, sizeof(uint64_t)), wr.get_location()); ablock64 b(wr, rc);
b.setup_empty();
return make_pair(b, wr.get_location());
} }
ablock64 ablock64