From 326134a7aa0db54cf8678e41f64c8f91e4fbdfe8 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 2 Oct 2013 10:44:57 +0100 Subject: [PATCH] [array] add visit method for values and damage --- persistent-data/data-structures/array.h | 85 ++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/persistent-data/data-structures/array.h b/persistent-data/data-structures/array.h index 7c4c4fe..c5ed021 100644 --- a/persistent-data/data-structures/array.h +++ b/persistent-data/data-structures/array.h @@ -21,12 +21,11 @@ #include "persistent-data/math_utils.h" #include "persistent-data/data-structures/btree.h" +#include "persistent-data/data-structures/btree_damage_visitor.h" #include "persistent-data/data-structures/array_block.h" //---------------------------------------------------------------- -// FIXME: we need an array checker - namespace persistent_data { namespace array_detail { uint32_t const ARRAY_CSUM_XOR = 595846735; @@ -65,6 +64,25 @@ namespace persistent_data { unsigned nr_entries_in_last_block; unsigned nr_total_blocks; }; + + struct damage { + typedef boost::shared_ptr ptr; + + damage(run lost_keys, + std::string const &desc) + : lost_keys_(lost_keys), + desc_(desc) { + } + + run lost_keys_; + std::string desc_; + }; + + inline std::ostream &operator <<(std::ostream &out, damage const &d) { + out << "array damage[lost_keys = " << d.lost_keys_ + << ", \"" << d.desc_ << "\"]"; + return out; + } } class array_base { @@ -125,6 +143,60 @@ namespace persistent_data { } }; + template + struct block_value_visitor { + block_value_visitor(array const &a, ValueVisitor &vv) + : a_(a), + vv_(vv) { + } + + void visit(btree_path const &p, + typename block_traits::value_type const &v) { + a_.visit_value(vv_, p, v); + } + + private: + array const &a_; + ValueVisitor &vv_; + }; + + template + void visit_value(ValueVisitor &vv, + btree_path const &p, + typename block_traits::value_type const &v) const { + rblock rb(tm_->read_lock(v, validator_), rc_); + + for (uint32_t i = 0; i < rb.nr_entries(); i++) + vv.visit(p[0] * rb.max_entries() + i, rb.get(i)); + } + + template + struct block_damage_visitor { + block_damage_visitor(DamageVisitor &dv, unsigned entries_per_block) + : dv_(dv), + entries_per_block_(entries_per_block) { + } + + void visit(btree_path const &path, btree_detail::damage const &d) { + dv_.visit(array_detail::damage(convert_run(d.lost_keys_), d.desc_)); + } + + private: + run::maybe convert_maybe(run::maybe const &v) const { + if (v) + return run::maybe(*v * entries_per_block_); + + return run::maybe(); + } + + run convert_run(run const &v) const { + return run(convert_maybe(v.begin_), convert_maybe(v.end_)); + } + + DamageVisitor &dv_; + unsigned entries_per_block_; + }; + typedef typename persistent_data::transaction_manager::ptr tm_ptr; typedef block_manager<>::write_ref write_ref; @@ -191,6 +263,15 @@ namespace persistent_data { b.set(index % entries_per_block_, value); } + template + void visit_values(ValueVisitor &value_visitor, + DamageVisitor &damage_visitor) const { + block_counter counter; + block_value_visitor bvisitor(*this, value_visitor); + block_damage_visitor dvisitor(damage_visitor, entries_per_block_); + btree_visit_values(block_tree_, counter, bvisitor, dvisitor); + } + private: struct resizer {