82 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef PERSISTENT_DATA_DATA_STRUCTURES_BTREE_COUNTER_H
 | 
						|
#define PERSISTENT_DATA_DATA_STRUCTURES_BTREE_COUNTER_H
 | 
						|
 | 
						|
#include "persistent-data/block_counter.h"
 | 
						|
 | 
						|
//----------------------------------------------------------------
 | 
						|
 | 
						|
namespace persistent_data {
 | 
						|
	namespace btree_count_detail {
 | 
						|
		template <unsigned Levels, typename ValueTraits, typename ValueCounter>
 | 
						|
		class counting_visitor : public btree<Levels, ValueTraits>::visitor {
 | 
						|
		public:
 | 
						|
			typedef btree<Levels, ValueTraits> tree;
 | 
						|
 | 
						|
			counting_visitor(block_counter &bc, ValueCounter &vc)
 | 
						|
				: bc_(bc),
 | 
						|
				  vc_(vc) {
 | 
						|
			}
 | 
						|
 | 
						|
			virtual bool visit_internal(node_location const &l,
 | 
						|
						    typename tree::internal_node const &n) {
 | 
						|
				return visit_node(n);
 | 
						|
			}
 | 
						|
 | 
						|
			virtual bool visit_internal_leaf(node_location const &l,
 | 
						|
							 typename tree::internal_node const &n) {
 | 
						|
				return visit_node(n);
 | 
						|
			}
 | 
						|
 | 
						|
			virtual bool visit_leaf(node_location const &l,
 | 
						|
						typename tree::leaf_node const &n) {
 | 
						|
				if (visit_node(n)) {
 | 
						|
					unsigned nr = n.get_nr_entries();
 | 
						|
 | 
						|
					for (unsigned i = 0; i < nr; i++) {
 | 
						|
						// FIXME: confirm l2 is correct
 | 
						|
						node_location l2(l);
 | 
						|
						l2.push_key(i);
 | 
						|
						vc_.visit(l2, n.value_at(i));
 | 
						|
					}
 | 
						|
 | 
						|
					return true;
 | 
						|
				}
 | 
						|
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
		private:
 | 
						|
			template <typename Node>
 | 
						|
			bool visit_node(Node const &n) {
 | 
						|
				block_address b = n.get_location();
 | 
						|
				bool seen = bc_.get_count(b);
 | 
						|
				bc_.inc(b);
 | 
						|
				return !seen;
 | 
						|
			}
 | 
						|
 | 
						|
			block_counter &bc_;
 | 
						|
			ValueCounter &vc_;
 | 
						|
		};
 | 
						|
	}
 | 
						|
 | 
						|
	template <typename T>
 | 
						|
	struct noop_value_counter {
 | 
						|
		void visit(btree_detail::node_location const &loc, T const &v) {
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	// Counts how many times each metadata block is referenced in the
 | 
						|
	// tree.  Blocks already referenced in the block counter are not
 | 
						|
	// walked.  This walk should only be done once you're sure the tree
 | 
						|
	// is not corrupt.
 | 
						|
	template <unsigned Levels, typename ValueTraits, typename ValueCounter>
 | 
						|
	void count_btree_blocks(btree<Levels, ValueTraits> const &tree, block_counter &bc, ValueCounter &vc) {
 | 
						|
		btree_count_detail::counting_visitor<Levels, ValueTraits, ValueCounter> v(bc, vc);
 | 
						|
		tree.visit_depth_first(v);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------
 | 
						|
 | 
						|
#endif
 |