13 #ifndef STXXL_CONTAINERS_BTREE_NODE_CACHE_HEADER 
   14 #define STXXL_CONTAINERS_BTREE_NODE_CACHE_HEADER 
   26 #define STXXL_BTREE_CACHE_VERBOSE STXXL_VERBOSE2 
   32 template <
class NodeType, 
class BTreeType>
 
   33 class node_cache : 
private noncopyable
 
   64                 longhash1(bid.offset + reinterpret_cast<uint64>(bid.storage));
 
   70             return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset);
 
  106         for (
typename std::vector<node_type*>::const_iterator it = m_nodes.begin();
 
  107              it != m_nodes.end(); ++it)
 
  128         const unsigned_type nnodes = cache_size_in_bytes / block_type::raw_size;
 
  132             STXXL_THROW2(std::runtime_error, 
"btree::node_cache::node_cache", 
"Too few memory for a node cache (<3)");
 
  134         m_nodes.reserve(nnodes);
 
  135         m_reqs.resize(nnodes);
 
  136         m_free_nodes.reserve(nnodes);
 
  137         m_fixed.resize(nnodes, 
false);
 
  138         m_dirty.resize(nnodes, 
true);
 
  141             m_nodes.push_back(
new node_type(m_btree, m_cmp));
 
  142             m_free_nodes.push_back(i);
 
  146         std::swap(m_pager, tmp_pager);
 
  151         return m_nodes.size();
 
  157         typename bid2node_type::const_iterator i = m_bid2node.begin();
 
  158         typename bid2node_type::const_iterator end = m_bid2node.end();
 
  160         for ( ; i != end; ++i)
 
  162             if (m_fixed[(*i).second])
 
  171         typename bid2node_type::const_iterator i = m_bid2node.begin();
 
  172         typename bid2node_type::const_iterator end = m_bid2node.end();
 
  173         for ( ; i != end; ++i)
 
  176             if (m_reqs[p].valid())
 
  190         if (m_free_nodes.empty())
 
  199                 node2kick = m_pager.kick();
 
  203                         "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
 
  207                 m_pager.hit(node2kick);
 
  208             } 
while (m_fixed[node2kick]);
 
  210             if (m_reqs[node2kick].valid())
 
  211                 m_reqs[node2kick]->wait();
 
  215             if (m_dirty[node2kick])
 
  225             assert(m_bid2node.find(node.my_bid()) != m_bid2node.end());
 
  226             m_bid2node.erase(node.my_bid());
 
  227             m_bm->new_block(m_alloc_strategy, new_bid);
 
  229             m_bid2node[new_bid] = node2kick;
 
  233             m_dirty[node2kick] = 
true;
 
  235             assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  242         int_type free_node = m_free_nodes.back();
 
  243         m_free_nodes.pop_back();
 
  244         assert(m_fixed[free_node] == 
false);
 
  246         m_bm->new_block(m_alloc_strategy, new_bid);
 
  247         m_bid2node[new_bid] = free_node;
 
  253         m_pager.hit(free_node);
 
  255         m_dirty[free_node] = 
true;
 
  257         assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  266         typename bid2node_type::const_iterator it = m_bid2node.find(bid);
 
  269         if (it != m_bid2node.end())
 
  272             const int_type nodeindex = it->second;
 
  274             m_fixed[nodeindex] = fix;
 
  275             m_pager.hit(nodeindex);
 
  276             m_dirty[nodeindex] = 
true;
 
  278             if (m_reqs[nodeindex].valid() && !m_reqs[nodeindex]->poll())
 
  279                 m_reqs[nodeindex]->wait();
 
  282             return m_nodes[nodeindex];
 
  288         if (m_free_nodes.empty())
 
  297                 node2kick = m_pager.kick();
 
  301                         "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
 
  305                 m_pager.hit(node2kick);
 
  306             } 
while (m_fixed[node2kick]);
 
  308             if (m_reqs[node2kick].valid())
 
  309                 m_reqs[node2kick]->wait();
 
  313             if (m_dirty[node2kick])
 
  321             m_bid2node.erase(node.my_bid());
 
  323             m_reqs[node2kick] = node.load(bid);
 
  324             m_bid2node[bid] = node2kick;
 
  326             m_fixed[node2kick] = fix;
 
  328             m_dirty[node2kick] = 
true;
 
  330             assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  337         int_type free_node = m_free_nodes.back();
 
  338         m_free_nodes.pop_back();
 
  339         assert(m_fixed[free_node] == 
false);
 
  342         m_reqs[free_node] = node.load(bid);
 
  343         m_bid2node[bid] = free_node;
 
  345         m_pager.hit(free_node);
 
  347         m_fixed[free_node] = fix;
 
  349         m_dirty[free_node] = 
true;
 
  351         assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  360         typename bid2node_type::const_iterator it = m_bid2node.find(bid);
 
  363         if (it != m_bid2node.end())
 
  366             const int_type nodeindex = it->second;
 
  368             m_fixed[nodeindex] = fix;
 
  369             m_pager.hit(nodeindex);
 
  371             if (m_reqs[nodeindex].valid() && !m_reqs[nodeindex]->poll())
 
  372                 m_reqs[nodeindex]->wait();
 
  375             return m_nodes[nodeindex];
 
  381         if (m_free_nodes.empty())
 
  390                 node2kick = m_pager.kick();
 
  394                         "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
 
  398                 m_pager.hit(node2kick);
 
  399             } 
while (m_fixed[node2kick]);
 
  401             if (m_reqs[node2kick].valid())
 
  402                 m_reqs[node2kick]->wait();
 
  405             if (m_dirty[node2kick])
 
  413             m_bid2node.erase(node.my_bid());
 
  415             m_reqs[node2kick] = node.load(bid);
 
  416             m_bid2node[bid] = node2kick;
 
  418             m_fixed[node2kick] = fix;
 
  420             m_dirty[node2kick] = 
false;
 
  422             assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  429         int_type free_node = m_free_nodes.back();
 
  430         m_free_nodes.pop_back();
 
  431         assert(m_fixed[free_node] == 
false);
 
  434         m_reqs[free_node] = node.load(bid);
 
  435         m_bid2node[bid] = free_node;
 
  437         m_pager.hit(free_node);
 
  439         m_fixed[free_node] = fix;
 
  441         m_dirty[free_node] = 
false;
 
  443         assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  452         typename bid2node_type::const_iterator it = m_bid2node.find(bid);
 
  455             if (it != m_bid2node.end())
 
  458                 const int_type nodeindex = it->second;
 
  460                 if (m_reqs[nodeindex].valid())
 
  461                     m_reqs[nodeindex]->wait();
 
  464                 m_free_nodes.push_back(nodeindex);
 
  465                 m_bid2node.erase(bid);
 
  466                 m_fixed[nodeindex] = 
false;
 
  471             m_bm->delete_block(bid);
 
  474         m_bm->delete_block(bid);
 
  479         if (m_bid2node.find(bid) != m_bid2node.end())
 
  483         if (m_free_nodes.empty())
 
  492                 node2kick = m_pager.kick();
 
  496                         "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
 
  500                 m_pager.hit(node2kick);
 
  501             } 
while (m_fixed[node2kick]);
 
  503             if (m_reqs[node2kick].valid())
 
  504                 m_reqs[node2kick]->wait();
 
  508             if (m_dirty[node2kick])
 
  516             m_bid2node.erase(node.my_bid());
 
  518             m_reqs[node2kick] = node.prefetch(bid);
 
  519             m_bid2node[bid] = node2kick;
 
  521             m_fixed[node2kick] = 
false;
 
  523             m_dirty[node2kick] = 
false;
 
  525             assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  532         int_type free_node = m_free_nodes.back();
 
  533         m_free_nodes.pop_back();
 
  534         assert(m_fixed[free_node] == 
false);
 
  537         m_reqs[free_node] = node.prefetch(bid);
 
  538         m_bid2node[bid] = free_node;
 
  540         m_pager.hit(free_node);
 
  542         m_fixed[free_node] = 
false;
 
  544         m_dirty[free_node] = 
false;
 
  546         assert(size() == m_bid2node.size() + m_free_nodes.size());
 
  555         assert(m_bid2node.find(bid) != m_bid2node.end());
 
  556         m_fixed[m_bid2node[bid]] = 
false;
 
  562         std::swap(m_cmp, obj.m_cmp);
 
  563         std::swap(m_nodes, obj.m_nodes);
 
  564         std::swap(m_reqs, obj.m_reqs);
 
  565         change_btree_pointers(m_btree);
 
  566         obj.change_btree_pointers(obj.m_btree);
 
  567         std::swap(m_fixed, obj.m_fixed);
 
  568         std::swap(m_free_nodes, obj.m_free_nodes);
 
  569         std::swap(m_bid2node, obj.m_bid2node);
 
  570         std::swap(m_pager, obj.m_pager);
 
  571         std::swap(m_alloc_strategy, obj.m_alloc_strategy);
 
  572         std::swap(n_found, obj.n_found);
 
  573         std::swap(n_not_found, obj.n_found);
 
  574         std::swap(n_created, obj.n_created);
 
  575         std::swap(n_deleted, obj.n_deleted);
 
  576         std::swap(n_read, obj.n_read);
 
  577         std::swap(n_written, obj.n_written);
 
  578         std::swap(n_clean_forced, obj.n_clean_forced);
 
  584             o << 
"Found blocks                      : " << n_found << 
" (" <<
 
  585                 100. * double(n_found) / double(n_read) << 
"%)" << std::endl;
 
  587             o << 
"Found blocks                      : " << n_found << 
" (" <<
 
  588                 100 << 
"%)" << std::endl;
 
  590         o << 
"Not found blocks                  : " << n_not_found << std::endl;
 
  591         o << 
"Created in the cache blocks       : " << n_created << std::endl;
 
  592         o << 
"Deleted blocks                    : " << n_deleted << std::endl;
 
  593         o << 
"Read blocks                       : " << n_read << std::endl;
 
  594         o << 
"Written blocks                    : " << n_written << std::endl;
 
  595         o << 
"Clean blocks forced from the cache: " << n_clean_forced << std::endl;
 
  615 template <
class NodeType, 
class BTreeType>
 
  624 #endif // !STXXL_CONTAINERS_BTREE_NODE_CACHE_HEADER 
stxxl::lru_pager pager_type
__gnu_cxx::hash_map< KeyType, MappedType, HashType > result
size_t longhash1(uint64 key_)
node_type const * get_const_node(const bid_type &bid, bool fix=false)
void change_btree_pointers(btree_type *b)
void swap(node_cache &obj)
node_type::block_type block_type
std::vector< node_type * > m_nodes
void prefetch_node(const bid_type &bid)
void print_statistics(std::ostream &o) const 
btree_type::alloc_strategy_type alloc_strategy_type
void unfix_node(const bid_type &bid)
std::vector< bool > m_dirty
btree_type::key_compare key_compare
std::vector< bool > m_fixed
std::vector< int_type > m_free_nodes
hash_map_type bid2node_type
choose_int_types< my_pointer_size >::int_type int_type
unsigned_type nfixed() const 
node_cache(unsigned_type cache_size_in_bytes, btree_type *btree, key_compare cmp)
compat_hash_map< bid_type, int_type, bid_hash >::result hash_map_type
#define STXXL_BEGIN_NAMESPACE
#define STXXL_THROW2(exception_type, location, error_message)
Throws exception_type with "Error in [location] : [error_message]". 
std::vector< request_ptr > m_reqs
void delete_node(const bid_type &bid)
node_type * get_new_node(bid_type &new_bid)
#define STXXL_BTREE_CACHE_VERBOSE
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
alloc_strategy_type m_alloc_strategy
node_type::bid_type bid_type
unsigned_type size() const 
node_type * get_node(const bid_type &bid, bool fix=false)
#define STXXL_END_NAMESPACE