From 3c54e2b23ad2b699de1c488dd9b1dee7f62a0724 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 13 Mar 2013 12:59:11 +0000 Subject: [PATCH] Updates to array_block --- persistent-data/data-structures/array_block.h | 42 ++++++++++++------- unit-tests/array_block_t.cc | 4 +- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/persistent-data/data-structures/array_block.h b/persistent-data/data-structures/array_block.h index e09b105..74c062d 100644 --- a/persistent-data/data-structures/array_block.h +++ b/persistent-data/data-structures/array_block.h @@ -41,22 +41,26 @@ namespace persistent_data { typedef typename ValueTraits::value_type value_type; typedef typename ValueTraits::ref_counter ref_counter; + enum block_state { + BLOCK_NEW, + BLOCK_EXISTS + }; + array_block(RefType ref, - ref_counter rc, - uint32_t value_size) + ref_counter rc) : ref_(ref), 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(0)); - header->value_size = to_disk<__le32>(value_size); } - array_block(RefType ref, ref_counter rc) - : ref_(ref), - rc_(rc) { + // I hate separate initialisation. But we can't have the + // constructor using non-const methods (get_header()) + // 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(0)); + header->value_size = to_disk<__le32>(static_cast(sizeof(disk_type))); } uint32_t max_entries() const { @@ -74,8 +78,13 @@ namespace persistent_data { void grow(uint32_t nr, value_type const &default_value) { uint32_t old_nr = nr_entries(); - if (nr >= max_entries()) - throw runtime_error("array_block index out of bounds"); + if (nr > max_entries()) { + 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) throw runtime_error("array_block grow method called with smaller size"); @@ -124,11 +133,12 @@ namespace persistent_data { return rc_; } - private: - static uint32_t calc_max_entries(uint32_t value_size) { - return (RefType::BLOCK_SIZE - sizeof(array_block_disk)) / value_size; + static uint32_t calc_max_entries() { + return (RefType::BLOCK_SIZE - sizeof(array_block_disk)) / + sizeof(typename ValueTraits::disk_type); } + private: void set_nr_entries(uint32_t nr) { using namespace base; array_block_disk *h = get_header(); diff --git a/unit-tests/array_block_t.cc b/unit-tests/array_block_t.cc index 5cc8e33..a8cf355 100644 --- a/unit-tests/array_block_t.cc +++ b/unit-tests/array_block_t.cc @@ -98,7 +98,9 @@ namespace { new_array_block(transaction_manager::ptr tm) { uint64_traits::ref_counter rc(MAX_VALUE); 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