Template array exist in the namespace persistent_data as well as in std of C++11. Explicitly use the one from persistent_data. This fixes compilation bugs with CXXFLAGS=-std=gnu++11 together with gcc 4.8.3 and boost 1.55.
		
			
				
	
	
		
			296 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "caching/hint_array.h"
 | 
						|
 | 
						|
using namespace boost;
 | 
						|
using namespace caching;
 | 
						|
using namespace caching::hint_array_damage;
 | 
						|
using namespace persistent_data;
 | 
						|
 | 
						|
//----------------------------------------------------------------
 | 
						|
 | 
						|
namespace {
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	struct hint_traits {
 | 
						|
		typedef unsigned char byte;
 | 
						|
		typedef byte disk_type[WIDTH];
 | 
						|
		typedef vector<byte> value_type;
 | 
						|
		typedef no_op_ref_counter<value_type> ref_counter;
 | 
						|
 | 
						|
		// FIXME: slow copying for now
 | 
						|
		static void unpack(disk_type const &disk, value_type &value) {
 | 
						|
			value.resize(WIDTH);
 | 
						|
			for (unsigned byte = 0; byte < WIDTH; byte++)
 | 
						|
				value.at(byte) = disk[byte];
 | 
						|
		}
 | 
						|
 | 
						|
		static void pack(value_type const &value, disk_type &disk) {
 | 
						|
			for (unsigned byte = 0; byte < WIDTH; byte++)
 | 
						|
				disk[byte] = value.at(byte);
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
 | 
						|
	// 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);
 | 
						|
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	boost::shared_ptr<array_base> mk_array(transaction_manager &tm) {
 | 
						|
		typedef hint_traits<WIDTH> traits;
 | 
						|
		typedef persistent_data::array<traits> ha;
 | 
						|
 | 
						|
		boost::shared_ptr<array_base> r = typename ha::ptr(new ha(tm, typename traits::ref_counter()));
 | 
						|
 | 
						|
		return r;
 | 
						|
	}
 | 
						|
 | 
						|
	boost::shared_ptr<array_base> mk_array(transaction_manager &tm, uint32_t width) {
 | 
						|
		switch (width) {
 | 
						|
#define xx(n)	case n:	return mk_array<n>(tm)
 | 
						|
 | 
						|
			all_widths
 | 
						|
#undef xx
 | 
						|
		default:
 | 
						|
			throw runtime_error("invalid hint width");
 | 
						|
		}
 | 
						|
 | 
						|
		// never get here
 | 
						|
		return boost::shared_ptr<array_base>();
 | 
						|
	}
 | 
						|
 | 
						|
	//--------------------------------
 | 
						|
 | 
						|
	template <typename HA>
 | 
						|
	boost::shared_ptr<HA>
 | 
						|
	downcast_array(boost::shared_ptr<array_base> base) {
 | 
						|
		boost::shared_ptr<HA> a = dynamic_pointer_cast<HA>(base);
 | 
						|
		if (!a)
 | 
						|
			throw runtime_error("internal error: couldn't cast hint array");
 | 
						|
 | 
						|
		return a;
 | 
						|
	}
 | 
						|
 | 
						|
	//--------------------------------
 | 
						|
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	boost::shared_ptr<array_base> mk_array(transaction_manager &tm, block_address root, unsigned nr_entries) {
 | 
						|
		typedef hint_traits<WIDTH> traits;
 | 
						|
		typedef persistent_data::array<traits> ha;
 | 
						|
 | 
						|
		boost::shared_ptr<array_base> r = typename ha::ptr(new ha(tm, typename traits::ref_counter(), root, nr_entries));
 | 
						|
 | 
						|
		return r;
 | 
						|
	}
 | 
						|
 | 
						|
	boost::shared_ptr<array_base> mk_array(transaction_manager &tm, uint32_t width, block_address root, unsigned nr_entries) {
 | 
						|
		switch (width) {
 | 
						|
#define xx(n)	case n:	return mk_array<n>(tm, root, nr_entries)
 | 
						|
			all_widths
 | 
						|
#undef xx
 | 
						|
		default:
 | 
						|
			throw runtime_error("invalid hint width");
 | 
						|
		}
 | 
						|
 | 
						|
		// never get here
 | 
						|
		return boost::shared_ptr<array_base>();
 | 
						|
	}
 | 
						|
 | 
						|
	//--------------------------------
 | 
						|
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	void get_hint(boost::shared_ptr<array_base> base, unsigned index, vector<unsigned char> &data) {
 | 
						|
		typedef hint_traits<WIDTH> traits;
 | 
						|
		typedef persistent_data::array<traits> ha;
 | 
						|
 | 
						|
		boost::shared_ptr<ha> a = downcast_array<ha>(base);
 | 
						|
		data = a->get(index);
 | 
						|
	}
 | 
						|
 | 
						|
	void get_hint_(uint32_t width, boost::shared_ptr<array_base> base, unsigned index, vector<unsigned char> &data) {
 | 
						|
		switch (width) {
 | 
						|
#define xx(n) case n: return get_hint<n>(base, index, data)
 | 
						|
			all_widths
 | 
						|
#undef xx
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//--------------------------------
 | 
						|
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	void set_hint(boost::shared_ptr<array_base> base, unsigned index, vector<unsigned char> const &data) {
 | 
						|
		typedef hint_traits<WIDTH> traits;
 | 
						|
		typedef persistent_data::array<traits> ha;
 | 
						|
 | 
						|
		boost::shared_ptr<ha> a = downcast_array<ha>(base);
 | 
						|
		a->set(index, data);
 | 
						|
	}
 | 
						|
 | 
						|
        void set_hint_(uint32_t width, boost::shared_ptr<array_base> base,
 | 
						|
		      unsigned index, vector<unsigned char> const &data) {
 | 
						|
		switch (width) {
 | 
						|
#define xx(n) case n: return set_hint<n>(base, index, data)
 | 
						|
		all_widths
 | 
						|
#undef xx
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//--------------------------------
 | 
						|
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	void grow(boost::shared_ptr<array_base> base, unsigned new_nr_entries, vector<unsigned char> const &value) {
 | 
						|
		typedef hint_traits<WIDTH> traits;
 | 
						|
		typedef persistent_data::array<traits> ha;
 | 
						|
 | 
						|
		boost::shared_ptr<ha> a = downcast_array<ha>(base);
 | 
						|
		a->grow(new_nr_entries, value);
 | 
						|
	}
 | 
						|
 | 
						|
	void grow_(uint32_t width, boost::shared_ptr<array_base> base,
 | 
						|
		   unsigned new_nr_entries, vector<unsigned char> const &value)
 | 
						|
	{
 | 
						|
		switch (width) {
 | 
						|
#define xx(n) case n: return grow<n>(base, new_nr_entries, value)
 | 
						|
		all_widths
 | 
						|
#undef xx
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//--------------------------------
 | 
						|
 | 
						|
	class value_adapter {
 | 
						|
	public:
 | 
						|
		value_adapter(hint_visitor &v)
 | 
						|
		: v_(v) {
 | 
						|
		}
 | 
						|
 | 
						|
		virtual void visit(uint32_t index, std::vector<unsigned char> const &v) {
 | 
						|
			v_.visit(static_cast<block_address>(index), v);
 | 
						|
		}
 | 
						|
 | 
						|
	private:
 | 
						|
		hint_visitor &v_;
 | 
						|
	};
 | 
						|
 | 
						|
	struct no_op_visitor : public hint_visitor {
 | 
						|
		virtual void visit(block_address cblock, std::vector<unsigned char> const &v) {
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	class ll_damage_visitor {
 | 
						|
	public:
 | 
						|
		ll_damage_visitor(damage_visitor &v)
 | 
						|
		: v_(v) {
 | 
						|
		}
 | 
						|
 | 
						|
		virtual void visit(array_detail::damage const &d) {
 | 
						|
			v_.visit(missing_hints(d.desc_, d.lost_keys_));
 | 
						|
		}
 | 
						|
 | 
						|
	private:
 | 
						|
		damage_visitor &v_;
 | 
						|
	};
 | 
						|
 | 
						|
	template <uint32_t WIDTH>
 | 
						|
	void walk_hints(boost::shared_ptr<array_base> base, hint_visitor &hv, damage_visitor &dv) {
 | 
						|
		typedef hint_traits<WIDTH> traits;
 | 
						|
		typedef persistent_data::array<traits> ha;
 | 
						|
 | 
						|
		boost::shared_ptr<ha> a = downcast_array<ha>(base);
 | 
						|
		value_adapter vv(hv);
 | 
						|
		ll_damage_visitor ll(dv);
 | 
						|
		a->visit_values(vv, ll);
 | 
						|
	}
 | 
						|
 | 
						|
	void walk_hints_(uint32_t width, boost::shared_ptr<array_base> base,
 | 
						|
			 hint_visitor &hv, damage_visitor &dv) {
 | 
						|
		switch (width) {
 | 
						|
#define xx(n) case n: walk_hints<n>(base, hv, dv); break
 | 
						|
			all_widths
 | 
						|
#undef xx
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------
 | 
						|
 | 
						|
missing_hints::missing_hints(std::string const desc, run<uint32_t> const &keys)
 | 
						|
	: damage(desc),
 | 
						|
	  keys_(keys)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
missing_hints::visit(damage_visitor &v) const
 | 
						|
{
 | 
						|
	v.visit(*this);
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------
 | 
						|
 | 
						|
hint_array::hint_array(transaction_manager &tm, unsigned width)
 | 
						|
	: width_(check_width(width)),
 | 
						|
	  impl_(mk_array(tm, width))
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
hint_array::hint_array(transaction_manager &tm, unsigned width,
 | 
						|
		       block_address root, unsigned nr_entries)
 | 
						|
	: width_(check_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<unsigned char> &data) const
 | 
						|
{
 | 
						|
	get_hint_(width_, impl_, index, data);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
hint_array::set_hint(unsigned index, vector<unsigned char> const &data)
 | 
						|
{
 | 
						|
	set_hint_(width_, impl_, index, data);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
hint_array::grow(unsigned new_nr_entries, vector<unsigned char> const &value)
 | 
						|
{
 | 
						|
	grow_(width_, impl_, new_nr_entries, value);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
hint_array::walk(hint_visitor &hv, hint_array_damage::damage_visitor &dv)
 | 
						|
{
 | 
						|
	walk_hints_(width_, impl_, hv, dv);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
hint_array::check(hint_array_damage::damage_visitor &visitor)
 | 
						|
{
 | 
						|
	no_op_visitor vv;
 | 
						|
	walk(vv, visitor);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t
 | 
						|
hint_array::check_width(uint32_t width)
 | 
						|
{
 | 
						|
	if (width % 4 || width == 0 || width > 128) {
 | 
						|
		ostringstream msg;
 | 
						|
		msg << "invalid hint width: " << width;
 | 
						|
		throw runtime_error(msg.str());
 | 
						|
	}
 | 
						|
 | 
						|
	return width;
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------
 |