From 17f7c982f253a4a4739e11edc8302b905bee61b4 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 24 Sep 2013 12:00:09 +0100 Subject: [PATCH] [caching] hint support --- Makefile.in | 2 + caching/hint_array.cc | 147 ++++++++++++++++++++++++ caching/hint_array.h | 30 ++++- caching/metadata.cc | 7 ++ caching/metadata.h | 3 +- persistent-data/data-structures/array.h | 9 +- 6 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 caching/hint_array.cc diff --git a/Makefile.in b/Makefile.in index 058e32e..ddabacb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -36,6 +36,7 @@ all: $(PROGRAMS) SOURCE=\ base/error_state.cc \ \ + caching/hint_array.cc \ caching/superblock.cc \ caching/mapping_array.cc \ caching/metadata.cc \ @@ -236,6 +237,7 @@ CACHE_CHECK_SOURCE=\ persistent-data/space-maps/recursive.cc \ persistent-data/space-maps/careful_alloc.cc \ persistent-data/transaction_manager.cc \ + caching/hint_array.cc \ caching/superblock.cc \ caching/mapping_array.cc \ caching/metadata.cc \ diff --git a/caching/hint_array.cc b/caching/hint_array.cc new file mode 100644 index 0000000..f0cdddf --- /dev/null +++ b/caching/hint_array.cc @@ -0,0 +1,147 @@ +#include "caching/hint_array.h" + +using namespace boost; +using namespace caching; +using namespace persistent_data; + +//---------------------------------------------------------------- + +namespace { + using namespace caching::hint_array_detail; + + // We've got into a bit of a mess here. Templates are compile + // time, and we don't know the hint width until run time. We're + // going to have to provide specialisation for all legal widths and + // use the appropriate one. + +#define all_widths \ + xx(4); xx(8); xx(12); xx(16); xx(20); xx(24); xx(28); xx(32);\ + xx(36); xx(40); xx(44); xx(48); xx(52); xx(56); xx(60); xx(64); \ + xx(68); xx(72); xx(76); xx(80); xx(84); xx(88); xx(92); xx(96); \ + xx(100); xx(104); xx(108); xx(112); xx(116); xx(120); xx(124); xx(128); + + template + shared_ptr mk_array(transaction_manager::ptr tm) { + typedef hint_traits traits; + typedef array ha; + + shared_ptr r = typename ha::ptr(new ha(tm, typename traits::ref_counter())); + + return r; + } + + shared_ptr mk_array(transaction_manager::ptr tm, uint32_t width) { + switch (width) { +#define xx(n) case n: return mk_array(tm) + + all_widths +#undef xx + } + + // never get here + return shared_ptr(); + } + + //-------------------------------- + + template + shared_ptr mk_array(transaction_manager::ptr tm, block_address root, unsigned nr_entries) { + typedef hint_traits traits; + typedef array ha; + + shared_ptr r = typename ha::ptr(new ha(tm, typename traits::ref_counter(), root, nr_entries)); + + return r; + } + + shared_ptr mk_array(transaction_manager::ptr tm, uint32_t width, block_address root, unsigned nr_entries) { + switch (width) { +#define xx(n) case n: return mk_array(tm, root, nr_entries) + all_widths +#undef xx + } + + // never get here + return shared_ptr(); + } + + //-------------------------------- + + template + void get_hint(shared_ptr base, unsigned index, vector &data) { + typedef hint_traits traits; + typedef array ha; + + shared_ptr a = dynamic_pointer_cast(base); + if (!a) + throw runtime_error("internal error: couldn't cast hint array"); + + data = a->get(index); + } + + void get_hint_(uint32_t width, shared_ptr base, unsigned index, vector &data) { + switch (width) { +#define xx(n) case n: return get_hint(base, index, data) + all_widths +#undef xx + } + } + + //-------------------------------- + + template + void set_hint(shared_ptr base, unsigned index, vector const &data) { + typedef hint_traits traits; + typedef array ha; + + shared_ptr a = dynamic_pointer_cast(base); + if (!a) + throw runtime_error("internal error: couldn't cast hint array"); + + a->set(index, data); + } + + void set_hint_(uint32_t width, shared_ptr base, + unsigned index, vector const &data) { + switch (width) { +#define xx(n) case n: return set_hint(base, index, data) + all_widths +#undef xx + } + } +} + +//---------------------------------------------------------------- + +hint_array::hint_array(tm_ptr tm, unsigned width) + : width_(width), + impl_(mk_array(tm, width)) +{ +} + +hint_array::hint_array(typename hint_array::tm_ptr tm, unsigned width, + block_address root, unsigned nr_entries) + : width_(width), + impl_(mk_array(tm, width, root, nr_entries)) +{ +} + +block_address +hint_array::get_root() const +{ + return impl_->get_root(); +} + +void +hint_array::get_hint(unsigned index, vector &data) const +{ + get_hint_(width_, impl_, index, data); +} + +void +hint_array::set_hint(unsigned index, vector const &data) +{ + set_hint_(width_, impl_, index, data); +} + +//---------------------------------------------------------------- diff --git a/caching/hint_array.h b/caching/hint_array.h index ec89aeb..dab0613 100644 --- a/caching/hint_array.h +++ b/caching/hint_array.h @@ -13,22 +13,44 @@ namespace caching { struct hint_traits { typedef unsigned char byte; typedef byte disk_type[WIDTH]; - typedef byte value_type[WIDTH]; + typedef vector value_type; typedef no_op_ref_counter ref_counter; + // FIXME: slow copying for now static void unpack(disk_type const &disk, value_type &value) { - ::memcpy(value, disk, sizeof(value)); + for (unsigned byte = 0; byte < WIDTH; byte++) + value[byte] = disk[byte]; } static void pack(value_type const &value, disk_type &disk) { - ::memcpy(disk, value, sizeof(disk)); + for (unsigned byte = 0; byte < WIDTH; byte++) + disk[byte] = value[byte]; } }; // FIXME: data visitor stuff } -// typedef persistent_data::array hint_array; + class hint_array { + public: + typedef boost::shared_ptr ptr; + typedef typename persistent_data::transaction_manager::ptr tm_ptr; + + hint_array(tm_ptr tm, unsigned width); + hint_array(tm_ptr tm, unsigned width, block_address root, unsigned nr_entries); + + unsigned get_nr_entries() const; + + void grow(unsigned new_nr_entries, void const *v); + + block_address get_root() const; + void get_hint(unsigned index, vector &data) const; + void set_hint(unsigned index, vector const &data); + + private: + unsigned width_; + boost::shared_ptr impl_; + }; } //---------------------------------------------------------------- diff --git a/caching/metadata.cc b/caching/metadata.cc index 66954d5..4e26657 100644 --- a/caching/metadata.cc +++ b/caching/metadata.cc @@ -53,6 +53,7 @@ metadata::commit() { commit_space_map(); commit_mappings(); + commit_hints(); commit_superblock(); } @@ -113,6 +114,12 @@ metadata::commit_mappings() sb_.mapping_root = mappings_->get_root(); } +void +metadata::commit_hints() +{ + sb_.hint_root = hints_->get_root(); +} + void metadata::commit_superblock() { diff --git a/caching/metadata.h b/caching/metadata.h index 0556125..d4a6cd2 100644 --- a/caching/metadata.h +++ b/caching/metadata.h @@ -34,7 +34,7 @@ namespace caching { superblock_detail::superblock sb_; checked_space_map::ptr metadata_sm_; mapping_array::ptr mappings_; - //hint_array::ptr hints_; + hint_array::ptr hints_; private: void init_superblock(); @@ -44,6 +44,7 @@ namespace caching { void commit_space_map(); void commit_mappings(); + void commit_hints(); void commit_superblock(); }; }; diff --git a/persistent-data/data-structures/array.h b/persistent-data/data-structures/array.h index 9b4c9bd..7c4c4fe 100644 --- a/persistent-data/data-structures/array.h +++ b/persistent-data/data-structures/array.h @@ -67,8 +67,15 @@ namespace persistent_data { }; } + class array_base { + public: + virtual ~array_base() {} + virtual void set_root(block_address root) = 0; + virtual block_address get_root() const = 0; + }; + template - class array { + class array : public array_base { public: class block_ref_counter : public ref_counter { public: