[btree] allow people to visit all the nodes in a btree.
This commit is contained in:
		
							
								
								
									
										19
									
								
								btree.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								btree.h
									
									
									
									
									
								
							| @@ -299,6 +299,22 @@ namespace persistent_data { | ||||
| 		// free the on disk btree when the destructor is called | ||||
| 		void destroy(); | ||||
|  | ||||
|  | ||||
| 		// Derive a class from this base class if you need to | ||||
| 		// inspect the individual nodes that make up a btree. | ||||
| 		class visitor { | ||||
| 		public: | ||||
| 			virtual ~visitor() {} | ||||
| 			typedef boost::shared_ptr<visitor> ptr; | ||||
|  | ||||
| 			virtual void visit_internal(unsigned level, btree_detail::node_ref<uint64_traits, BlockSize> const &n) = 0; | ||||
| 			virtual void visit_internal_leaf(unsigned level, btree_detail::node_ref<uint64_traits, BlockSize> const &n) = 0; | ||||
| 			virtual void visit_leaf(unsigned level, btree_detail::node_ref<ValueTraits, BlockSize> const &n) = 0; | ||||
| 		}; | ||||
|  | ||||
| 		// Walks the tree in depth first order | ||||
| 		void visit(typename visitor::ptr visitor); | ||||
|  | ||||
| 	private: | ||||
| 		template <typename ValueTraits2> | ||||
| 		void split_node(btree_detail::shadow_spine<BlockSize> &spine, | ||||
| @@ -321,6 +337,9 @@ namespace persistent_data { | ||||
| 				uint64_t key, | ||||
| 				int *index); | ||||
|  | ||||
| 		void walk_tree(typename visitor::ptr visitor, | ||||
| 			       unsigned level, block_address b); | ||||
|  | ||||
| 		typename persistent_data::transaction_manager<BlockSize>::ptr tm_; | ||||
| 		bool destroy_; | ||||
| 		block_address root_; | ||||
|   | ||||
							
								
								
									
										31
									
								
								btree.tcc
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								btree.tcc
									
									
									
									
									
								
							| @@ -590,5 +590,36 @@ insert_location(btree_detail::shadow_spine<BlockSize> &spine, | ||||
| 		(leaf.key_at(i) != key)); | ||||
| } | ||||
|  | ||||
| template <unsigned Levels, typename ValueTraits, uint32_t BlockSize> | ||||
| void | ||||
| btree<Levels, ValueTraits, BlockSize>::visit(typename visitor::ptr visitor) | ||||
| { | ||||
| 	walk_tree(visitor, 0, root_); | ||||
| } | ||||
|  | ||||
| template <unsigned Levels, typename ValueTraits, uint32_t BlockSize> | ||||
| void | ||||
| btree<Levels, ValueTraits, BlockSize>:: | ||||
| walk_tree(typename visitor::ptr visitor, | ||||
| 	  unsigned level, block_address b) | ||||
| { | ||||
| 	using namespace btree_detail; | ||||
| 	auto blk = tm_->read_lock(b); | ||||
| 	auto o = to_node<uint64_traits, BlockSize>(blk); | ||||
| 	if (o.get_type() == INTERNAL) { | ||||
| 		visitor->visit_internal(level, o); | ||||
| 		for (unsigned i = 0; i < o.get_nr_entries(); i++) | ||||
| 			walk_tree(visitor, level, o.value_at(i)); | ||||
|  | ||||
| 	} else if (level < Levels - 1) { | ||||
| 		visitor->visit_internal_leaf(level, o); | ||||
| 		for (unsigned i = 0; i < o.get_nr_entries(); i++) | ||||
| 			walk_tree(visitor, level + 1, o.value_at(i)); | ||||
|  | ||||
| 	} else { | ||||
| 		auto ov = to_node<ValueTraits, BlockSize>(blk); | ||||
| 		visitor->visit_leaf(level, ov); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|   | ||||
| @@ -30,6 +30,28 @@ namespace { | ||||
| 			new btree<1, uint64_traits, 4096>( | ||||
| 				create_tm(), rc)); | ||||
| 	} | ||||
|  | ||||
| 	class constraint_visitor : public btree<1, uint64_traits, 4096>::visitor { | ||||
| 	private: | ||||
| 		void visit_internal(unsigned level, btree_detail::node_ref<uint64_traits, 4096> const &n) { | ||||
| 			// cout << "internal: level = " << level << ", nr_entries = " << n.get_nr_entries() << endl; | ||||
| 		} | ||||
|  | ||||
| 		void visit_internal_leaf(unsigned level, btree_detail::node_ref<uint64_traits, 4096> const &n) { | ||||
| 			// cout << "internal_leaf !" << endl; | ||||
| 		} | ||||
|  | ||||
| 		void visit_leaf(unsigned level, btree_detail::node_ref<uint64_traits, 4096> const &n) { | ||||
| 			// cout << "leaf: level = " << level << ", nr_entries = " << n.get_nr_entries() << endl; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	void check_constraints(btree<1, uint64_traits, 4096>::ptr tree) { | ||||
| 		typedef btree<1, uint64_traits, 4096> tree_type; | ||||
|  | ||||
| 		typename tree_type::visitor::ptr v(new constraint_visitor); | ||||
| 		tree->visit(v); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|   | ||||
		Reference in New Issue
	
	Block a user