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