13 #ifndef STXXL_CONTAINERS_BTREE_NODE_CACHE_HEADER
14 #define STXXL_CONTAINERS_BTREE_NODE_CACHE_HEADER
31 template <
class NodeType,
class BTreeType>
32 class node_cache :
private noncopyable
69 return (a.storage < b.storage) || (a.storage == b.storage && a.offset < b.offset);
105 typename std::vector<node_type*>::const_iterator it = nodes_.begin();
106 for ( ; it != 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 nodes_.reserve(nnodes);
135 reqs_.resize(nnodes);
136 free_nodes_.reserve(nnodes);
137 fixed_.resize(nnodes,
false);
138 dirty_.resize(nnodes,
true);
141 nodes_.push_back(
new node_type(btree_, comp_));
142 free_nodes_.push_back(i);
146 std::swap(pager_, tmp_pager);
151 return nodes_.size();
157 typename BID2node_type::const_iterator i = BID2node_.begin();
158 typename BID2node_type::const_iterator end = BID2node_.end();
160 for ( ; i != end; ++i)
162 if (fixed_[(*i).second])
171 typename BID2node_type::const_iterator i = BID2node_.begin();
172 typename BID2node_type::const_iterator end = BID2node_.end();
173 for ( ; i != end; ++i)
176 if (reqs_[p].valid())
190 if (free_nodes_.empty())
199 node2kick = pager_.kick();
203 "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
207 pager_.hit(node2kick);
208 }
while (fixed_[node2kick]);
211 if (reqs_[node2kick].valid())
212 reqs_[node2kick]->wait();
217 if (dirty_[node2kick])
228 assert(BID2node_.find(Node.my_bid()) != BID2node_.end());
229 BID2node_.erase(Node.my_bid());
230 bm->new_block(alloc_strategy_, new_bid);
232 BID2node_[new_bid] = node2kick;
236 dirty_[node2kick] =
true;
238 assert(size() == BID2node_.size() + free_nodes_.size());
240 STXXL_VERBOSE1(
"btree::node_cache get_new_node, need to kick node " << node2kick);
246 int_type free_node = free_nodes_.back();
247 free_nodes_.pop_back();
248 assert(fixed_[free_node] ==
false);
250 bm->new_block(alloc_strategy_, new_bid);
251 BID2node_[new_bid] = free_node;
257 pager_.hit(free_node);
259 dirty_[free_node] =
true;
261 assert(size() == BID2node_.size() + free_nodes_.size());
263 STXXL_VERBOSE1(
"btree::node_cache get_new_node, free node " << free_node <<
"available");
271 typename BID2node_type::const_iterator it = BID2node_.find(bid);
274 if (it != BID2node_.end())
277 const int_type nodeindex = it->second;
278 STXXL_VERBOSE1(
"btree::node_cache get_node, the node " << nodeindex <<
"is in cache , fix=" << fix);
279 fixed_[nodeindex] = fix;
280 pager_.hit(nodeindex);
281 dirty_[nodeindex] =
true;
283 if (reqs_[nodeindex].valid() && !reqs_[nodeindex]->poll())
284 reqs_[nodeindex]->wait();
288 return nodes_[nodeindex];
294 if (free_nodes_.empty())
303 node2kick = pager_.kick();
307 "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
311 pager_.hit(node2kick);
312 }
while (fixed_[node2kick]);
314 if (reqs_[node2kick].valid())
315 reqs_[node2kick]->wait();
320 if (dirty_[node2kick])
329 BID2node_.erase(Node.my_bid());
331 reqs_[node2kick] = Node.load(bid);
332 BID2node_[bid] = node2kick;
334 fixed_[node2kick] = fix;
336 dirty_[node2kick] =
true;
338 assert(size() == BID2node_.size() + free_nodes_.size());
340 STXXL_VERBOSE1(
"btree::node_cache get_node, need to kick node" << node2kick <<
" fix=" << fix);
345 int_type free_node = free_nodes_.back();
346 free_nodes_.pop_back();
347 assert(fixed_[free_node] ==
false);
350 reqs_[free_node] = Node.load(bid);
351 BID2node_[bid] = free_node;
353 pager_.hit(free_node);
355 fixed_[free_node] = fix;
357 dirty_[free_node] =
true;
359 assert(size() == BID2node_.size() + free_nodes_.size());
361 STXXL_VERBOSE1(
"btree::node_cache get_node, free node " << free_node <<
"available, fix=" << fix);
368 typename BID2node_type::const_iterator it = BID2node_.find(bid);
371 if (it != BID2node_.end())
374 const int_type nodeindex = it->second;
375 STXXL_VERBOSE1(
"btree::node_cache get_node, the node " << nodeindex <<
"is in cache , fix=" << fix);
376 fixed_[nodeindex] = fix;
377 pager_.hit(nodeindex);
379 if (reqs_[nodeindex].valid() && !reqs_[nodeindex]->poll())
380 reqs_[nodeindex]->wait();
384 return nodes_[nodeindex];
390 if (free_nodes_.empty())
399 node2kick = pager_.kick();
403 "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
407 pager_.hit(node2kick);
408 }
while (fixed_[node2kick]);
410 if (reqs_[node2kick].valid())
411 reqs_[node2kick]->wait();
415 if (dirty_[node2kick])
424 BID2node_.erase(Node.my_bid());
426 reqs_[node2kick] = Node.load(bid);
427 BID2node_[bid] = node2kick;
429 fixed_[node2kick] = fix;
431 dirty_[node2kick] =
false;
433 assert(size() == BID2node_.size() + free_nodes_.size());
435 STXXL_VERBOSE1(
"btree::node_cache get_node, need to kick node" << node2kick <<
" fix=" << fix);
440 int_type free_node = free_nodes_.back();
441 free_nodes_.pop_back();
442 assert(fixed_[free_node] ==
false);
445 reqs_[free_node] = Node.load(bid);
446 BID2node_[bid] = free_node;
448 pager_.hit(free_node);
450 fixed_[free_node] = fix;
452 dirty_[free_node] =
false;
454 assert(size() == BID2node_.size() + free_nodes_.size());
456 STXXL_VERBOSE1(
"btree::node_cache get_node, free node " << free_node <<
"available, fix=" << fix);
463 typename BID2node_type::const_iterator it = BID2node_.find(bid);
466 if (it != BID2node_.end())
469 const int_type nodeindex = it->second;
470 STXXL_VERBOSE1(
"btree::node_cache delete_node " << nodeindex <<
" from cache.");
471 if (reqs_[nodeindex].valid())
472 reqs_[nodeindex]->wait();
475 free_nodes_.push_back(nodeindex);
476 BID2node_.erase(bid);
477 fixed_[nodeindex] =
false;
482 bm->delete_block(bid);
485 bm->delete_block(bid);
491 if (BID2node_.find(bid) != BID2node_.end())
496 if (free_nodes_.empty())
505 node2kick = pager_.kick();
509 "The node cache is too small, no node can be kicked out (all nodes are fixed) !");
513 pager_.hit(node2kick);
514 }
while (fixed_[node2kick]);
516 if (reqs_[node2kick].valid())
517 reqs_[node2kick]->wait();
522 if (dirty_[node2kick])
531 BID2node_.erase(Node.my_bid());
533 reqs_[node2kick] = Node.prefetch(bid);
534 BID2node_[bid] = node2kick;
536 fixed_[node2kick] =
false;
538 dirty_[node2kick] =
false;
540 assert(size() == BID2node_.size() + free_nodes_.size());
542 STXXL_VERBOSE1(
"btree::node_cache prefetch_node, need to kick node" << node2kick <<
" ");
547 int_type free_node = free_nodes_.back();
548 free_nodes_.pop_back();
549 assert(fixed_[free_node] ==
false);
552 reqs_[free_node] = Node.prefetch(bid);
553 BID2node_[bid] = free_node;
555 pager_.hit(free_node);
557 fixed_[free_node] =
false;
559 dirty_[free_node] =
false;
561 assert(size() == BID2node_.size() + free_nodes_.size());
563 STXXL_VERBOSE1(
"btree::node_cache prefetch_node, free node " << free_node <<
"available");
570 assert(BID2node_.find(bid) != BID2node_.end());
571 fixed_[BID2node_[bid]] =
false;
572 STXXL_VERBOSE1(
"btree::node_cache unfix_node, node " << BID2node_[bid]);
577 std::swap(comp_, obj.comp_);
578 std::swap(nodes_, obj.nodes_);
579 std::swap(reqs_, obj.reqs_);
580 change_btree_pointers(btree_);
581 obj.change_btree_pointers(obj.btree_);
582 std::swap(fixed_, obj.fixed_);
583 std::swap(free_nodes_, obj.free_nodes_);
584 std::swap(BID2node_, obj.BID2node_);
585 std::swap(pager_, obj.pager_);
586 std::swap(alloc_strategy_, obj.alloc_strategy_);
587 std::swap(n_found, obj.n_found);
588 std::swap(n_not_found, obj.n_found);
589 std::swap(n_created, obj.n_created);
590 std::swap(n_deleted, obj.n_deleted);
591 std::swap(n_read, obj.n_read);
592 std::swap(n_written, obj.n_written);
593 std::swap(n_clean_forced, obj.n_clean_forced);
599 o <<
"Found blocks : " << n_found <<
" (" <<
600 100. * double(n_found) / double(n_read) <<
"%)" << std::endl;
603 o <<
"Found blocks : " << n_found <<
" (" <<
604 100 <<
"%)" << std::endl;
606 o <<
"Not found blocks : " << n_not_found << std::endl;
607 o <<
"Created in the cache blocks : " << n_created << std::endl;
608 o <<
"Deleted blocks : " << n_deleted << std::endl;
609 o <<
"Read blocks : " << n_read << std::endl;
610 o <<
"Written blocks : " << n_written << std::endl;
611 o <<
"Clean blocks forced from the cache: " << n_clean_forced << std::endl;
632 template <
class NodeType,
class BTreeType>
641 #endif // !STXXL_CONTAINERS_BTREE_NODE_CACHE_HEADER
stxxl::lru_pager pager_type
std::vector< bool > dirty_
node_type const * get_const_node(const bid_type &bid, bool fix=false)
unsigned long long int uint64
void change_btree_pointers(btree_type *b)
void swap(node_cache &obj)
node_type::block_type block_type
void prefetch_node(const bid_type &bid)
uint64 longhash1(uint64 key_)
void print_statistics(std::ostream &o) const
btree_type::alloc_strategy_type alloc_strategy_type
void unfix_node(const bid_type &bid)
btree_type::key_compare key_compare
choose_int_types< my_pointer_size >::int_type int_type
std::vector< bool > fixed_
unsigned_type nfixed() const
compat_hash_map< bid_type, int_type, bid_hash >::result hash_map_type
#define STXXL_BEGIN_NAMESPACE
#define STXXL_VERBOSE1(x)
hash_map_type BID2node_type
std::vector< request_ptr > reqs_
#define STXXL_THROW2(exception_type, location, error_message)
Throws exception_type with "Error in [location] : [error_message]".
alloc_strategy_type alloc_strategy_
std::vector< node_type * > nodes_
void delete_node(const bid_type &bid)
node_type * get_new_node(bid_type &new_bid)
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
node_type::bid_type bid_type
std::vector< int_type > free_nodes_
unsigned_type size() const
node_type * get_node(const bid_type &bid, bool fix=false)
__gnu_cxx::hash_map< _Key, _Tp, _Hash > result
#define STXXL_END_NAMESPACE
node_cache(unsigned_type cache_size_in_bytes, btree_type *btree__, key_compare comp__)