STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
btree.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/containers/btree/btree.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2006, 2008 Roman Dementiev <[email protected]>
7  *
8  * Distributed under the Boost Software License, Version 1.0.
9  * (See accompanying file LICENSE_1_0.txt or copy at
10  * http://www.boost.org/LICENSE_1_0.txt)
11  **************************************************************************/
12 
13 #ifndef STXXL_CONTAINERS_BTREE_BTREE_HEADER
14 #define STXXL_CONTAINERS_BTREE_BTREE_HEADER
15 
16 #include <limits>
17 #include <stxxl/bits/namespace.h>
24 #include <stxxl/vector>
25 
26 
28 
29 namespace btree {
30 
31 template <class KeyType,
32  class DataType,
33  class CompareType,
34  unsigned RawNodeSize,
35  unsigned RawLeafSize,
36  class PDAllocStrategy
37  >
38 class btree : private noncopyable
39 {
40 public:
41  typedef KeyType key_type;
42  typedef DataType data_type;
43  typedef CompareType key_compare;
44 
46 
47  typedef PDAllocStrategy alloc_strategy_type;
48 
51  typedef std::pair<const key_type, data_type> value_type;
53  typedef const value_type& const_reference;
54  typedef value_type* pointer;
55  typedef value_type const* const_pointer;
56 
57 
58  // leaf type declarations
60  friend class normal_leaf<key_type, data_type, key_compare, RawLeafSize, SelfType>;
64  friend class node_cache<leaf_type, SelfType>;
65  // iterator types
69  // iterator map type
71  // node type declarations
74  friend class normal_node<key_type, key_compare, RawNodeSize, SelfType>;
77  friend class node_cache<node_type, SelfType>;
78 
80 
81  enum {
82  min_node_size = node_type::min_size,
83  max_node_size = node_type::max_size,
84  min_leaf_size = leaf_type::min_size,
85  max_leaf_size = leaf_type::max_size
86  };
87 
88 private:
94  unsigned int height_;
98 
99  typedef std::map<key_type, node_bid_type, key_compare> root_node_type;
100  typedef typename root_node_type::iterator root_node_iterator_type;
101  typedef typename root_node_type::const_iterator root_node_const_iterator_type;
102  typedef std::pair<key_type, node_bid_type> root_node_pair_type;
103 
104 
107 
108 
109  void insert_into_root(const std::pair<key_type, node_bid_type>& splitter)
110  {
111  std::pair<root_node_iterator_type, bool> result =
112  root_node_.insert(splitter);
113  STXXL_ASSERT(result.second == true);
114  if (root_node_.size() > max_node_size) // root overflow
115  {
116  STXXL_VERBOSE1("btree::insert_into_root, overflow happened, splitting");
117 
118  node_bid_type LeftBid;
119  node_type* LeftNode = node_cache_.get_new_node(LeftBid);
120  assert(LeftNode);
121  node_bid_type RightBid;
122  node_type* RightNode = node_cache_.get_new_node(RightBid);
123  assert(RightNode);
124 
125  const unsigned_type old_size = root_node_.size();
126  const unsigned_type half = root_node_.size() / 2;
127  unsigned_type i = 0;
128  root_node_iterator_type it = root_node_.begin();
129  typename node_block_type::iterator block_it = LeftNode->block().begin();
130  while (i < half) // copy smaller part
131  {
132  *block_it = *it;
133  ++i;
134  ++block_it;
135  ++it;
136  }
137  LeftNode->block().info.cur_size = (unsigned int)half;
138  key_type LeftKey = (LeftNode->block()[half - 1]).first;
139 
140  block_it = RightNode->block().begin();
141  while (i < old_size) // copy larger part
142  {
143  *block_it = *it;
144  ++i;
145  ++block_it;
146  ++it;
147  }
148  unsigned_type right_size = RightNode->block().info.cur_size = (unsigned int)(old_size - half);
149  key_type RightKey = (RightNode->block()[right_size - 1]).first;
150 
151  assert(old_size == RightNode->size() + LeftNode->size());
152 
153  // create new root node
154  root_node_.clear();
155  root_node_.insert(root_node_pair_type(LeftKey, LeftBid));
156  root_node_.insert(root_node_pair_type(RightKey, RightBid));
157 
158 
159  ++height_;
160  STXXL_VERBOSE1("btree Increasing height to " << height_);
161  if (node_cache_.size() < (height_ - 1))
162  {
163  STXXL_THROW2(std::runtime_error, "btree::bulk_construction", "The height of the tree (" << height_ << ") has exceeded the required capacity (" << (node_cache_.size() + 1) << ") of the node cache. Increase the node cache size.");
164  }
165  }
166  }
167 
168  template <class CacheType>
169  void fuse_or_balance(root_node_iterator_type UIt, CacheType& cache_)
170  {
171  typedef typename CacheType::node_type local_node_type;
172  typedef typename local_node_type::bid_type local_bid_type;
173 
174  root_node_iterator_type leftIt, rightIt;
175  if (UIt->first == key_compare::max_value()) // UIt is the last entry in the root
176  {
177  assert(UIt != root_node_.begin());
178  rightIt = UIt;
179  leftIt = --UIt;
180  }
181  else
182  {
183  leftIt = UIt;
184  rightIt = ++UIt;
185  assert(rightIt != root_node_.end());
186  }
187 
188  // now fuse or balance nodes pointed by leftIt and rightIt
189  local_bid_type LeftBid = (local_bid_type)leftIt->second;
190  local_bid_type RightBid = (local_bid_type)rightIt->second;
191  local_node_type* LeftNode = cache_.get_node(LeftBid, true);
192  local_node_type* RightNode = cache_.get_node(RightBid, true);
193 
194  const unsigned_type TotalSize = LeftNode->size() + RightNode->size();
195  if (TotalSize <= RightNode->max_nelements())
196  {
197  // fuse
198  RightNode->fuse(*LeftNode); // add the content of LeftNode to RightNode
199 
200  cache_.unfix_node(RightBid);
201  cache_.delete_node(LeftBid); // 'delete_node' unfixes LeftBid also
202 
203  root_node_.erase(leftIt); // delete left BID from the root
204  }
205  else
206  {
207  // balance
208 
209  key_type NewSplitter = RightNode->balance(*LeftNode);
210 
211  root_node_.erase(leftIt); // delete left BID from the root
212  // reinsert with the new key
213  root_node_.insert(root_node_pair_type(NewSplitter, (node_bid_type)LeftBid));
214 
215  cache_.unfix_node(LeftBid);
216  cache_.unfix_node(RightBid);
217  }
218  }
219 
221  {
222  leaf_bid_type NewBid;
223  leaf_type* NewLeaf = leaf_cache_.get_new_node(NewBid);
224  assert(NewLeaf);
225  end_iterator = NewLeaf->end(); // initialize end() iterator
226  root_node_.insert(root_node_pair_type(key_compare::max_value(), (node_bid_type)NewBid));
227  }
228 
230  {
231  if (height_ == 2)
232  {
233  // we have children leaves here
234  root_node_const_iterator_type it = root_node_.begin();
235  for ( ; it != root_node_.end(); ++it)
236  {
237  // delete from leaf cache and deallocate bid
238  leaf_cache_.delete_node((leaf_bid_type)it->second);
239  }
240  }
241  else
242  {
243  root_node_const_iterator_type it = root_node_.begin();
244  for ( ; it != root_node_.end(); ++it)
245  {
246  node_type* Node = node_cache_.get_node((node_bid_type)it->second);
247  assert(Node);
248  Node->deallocate_children(height_ - 1);
249  // delete from node cache and deallocate bid
250  node_cache_.delete_node((node_bid_type)it->second);
251  }
252  }
253  }
254 
255  template <class InputIterator>
256  void bulk_construction(InputIterator b, InputIterator e, double node_fill_factor, double leaf_fill_factor)
257  {
258  assert(node_fill_factor >= 0.5);
259  assert(leaf_fill_factor >= 0.5);
260  key_type lastKey = key_compare::max_value();
261 
262  typedef std::pair<key_type, node_bid_type> key_bid_pair;
263  typedef typename stxxl::VECTOR_GENERATOR<key_bid_pair, 1, 1,
264  node_block_type::raw_size>::result key_bid_vector_type;
265 
266  key_bid_vector_type Bids;
267 
268  leaf_bid_type NewBid;
269  leaf_type* Leaf = leaf_cache_.get_new_node(NewBid);
270  const unsigned_type max_leaf_elements = unsigned_type(double(Leaf->max_nelements()) * leaf_fill_factor);
271 
272  while (b != e)
273  {
274  // write data in leaves
275 
276  // if *b not equal to the last element
277  if (key_compare_(b->first, lastKey) || key_compare_(lastKey, b->first))
278  {
279  ++size_;
280  if (Leaf->size() == max_leaf_elements)
281  {
282  // overflow, need a new block
283  Bids.push_back(key_bid_pair(Leaf->back().first, (node_bid_type)NewBid));
284 
285  leaf_type* NewLeaf = leaf_cache_.get_new_node(NewBid);
286  assert(NewLeaf);
287  // Setting links
288  Leaf->succ() = NewLeaf->my_bid();
289  NewLeaf->pred() = Leaf->my_bid();
290 
291  Leaf = NewLeaf;
292  }
293  Leaf->push_back(*b);
294  lastKey = b->first;
295  }
296  ++b;
297  }
298 
299  // rebalance the last leaf
300  if (Leaf->underflows() && !Bids.empty())
301  {
302  leaf_type* LeftLeaf = leaf_cache_.get_node((leaf_bid_type)(Bids.back().second));
303  assert(LeftLeaf);
304  if (LeftLeaf->size() + Leaf->size() <= Leaf->max_nelements()) // can fuse
305  {
306  Leaf->fuse(*LeftLeaf);
307  leaf_cache_.delete_node((leaf_bid_type)(Bids.back().second));
308  Bids.pop_back();
309  assert(!Leaf->overflows() && !Leaf->underflows());
310  }
311  else
312  {
313  // need to rebalance
314  const key_type NewSplitter = Leaf->balance(*LeftLeaf);
315  Bids.back().first = NewSplitter;
316  assert(!LeftLeaf->overflows() && !LeftLeaf->underflows());
317  }
318  }
319 
320  assert(!Leaf->overflows() && (!Leaf->underflows() || size_ <= max_leaf_size));
321 
322  end_iterator = Leaf->end(); // initialize end() iterator
323 
324  Bids.push_back(key_bid_pair(key_compare::max_value(), (node_bid_type)NewBid));
325 
326  const unsigned_type max_node_elements = unsigned_type(double(max_node_size) * node_fill_factor);
327 
328  while (Bids.size() > max_node_elements)
329  {
330  key_bid_vector_type ParentBids;
331 
332  stxxl::uint64 nparents = div_ceil(Bids.size(), max_node_elements);
333  assert(nparents >= 2);
334  STXXL_VERBOSE1("btree bulk constructBids.size() " << Bids.size() << " nparents: " << nparents << " max_ns: "
335  << max_node_elements);
336  STXXL_UNUSED(nparents);
337  typename key_bid_vector_type::const_iterator it = Bids.begin();
338 
339  do
340  {
341  node_bid_type NewBid;
342  node_type* Node = node_cache_.get_new_node(NewBid);
343  assert(Node);
344  unsigned_type cnt = 0;
345  for ( ; cnt < max_node_elements && it != Bids.end(); ++cnt, ++it)
346  {
347  Node->push_back(*it);
348  }
349  STXXL_VERBOSE1("btree bulk construct Node size : " << Node->size() << " limits: " <<
350  Node->min_nelements() << " " << Node->max_nelements() << " max_node_elements: " << max_node_elements);
351 
352  if (Node->underflows())
353  {
354  assert(it == Bids.end()); // this can happen only at the end
355  assert(!ParentBids.empty());
356 
357  node_type* LeftNode = node_cache_.get_node(ParentBids.back().second);
358  assert(LeftNode);
359  if (LeftNode->size() + Node->size() <= Node->max_nelements()) // can fuse
360  {
361  Node->fuse(*LeftNode);
362  node_cache_.delete_node(ParentBids.back().second);
363  ParentBids.pop_back();
364  }
365  else
366  { // need to rebalance
367  const key_type NewSplitter = Node->balance(*LeftNode);
368  ParentBids.back().first = NewSplitter;
369  assert(!LeftNode->overflows() && !LeftNode->underflows());
370  }
371  }
372  assert(!Node->overflows() && !Node->underflows());
373 
374  ParentBids.push_back(key_bid_pair(Node->back().first, NewBid));
375  } while (it != Bids.end());
376 
377  std::swap(ParentBids, Bids);
378 
379  assert(nparents == Bids.size() || (nparents - 1) == Bids.size());
380 
381  ++height_;
382  STXXL_VERBOSE1("Increasing height to " << height_);
383  if (node_cache_.size() < (height_ - 1))
384  {
385  STXXL_THROW2(std::runtime_error, "btree::bulk_construction", "The height of the tree (" << height_ << ") has exceeded the required capacity (" << (node_cache_.size() + 1) << ") of the node cache. Increase the node cache size.");
386  }
387  }
388 
389  root_node_.insert(Bids.begin(), Bids.end());
390  }
391 
392 public:
393  btree(unsigned_type node_cache_size_in_bytes,
394  unsigned_type leaf_cache_size_in_bytes
395  ) :
396  node_cache_(node_cache_size_in_bytes, this, key_compare_),
397  leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
398  iterator_map_(this),
399  size_(0),
400  height_(2),
401  prefetching_enabled_(true),
402  bm_(block_manager::get_instance())
403  {
404  STXXL_VERBOSE1("Creating a btree, addr=" << this);
405  STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size);
406  STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size);
407  STXXL_VERBOSE1(" elements in a node: " << node_block_type::size);
408  STXXL_VERBOSE1(" elements in a leaf: " << leaf_block_type::size);
409  STXXL_VERBOSE1(" size of a node element: " << sizeof(typename node_block_type::value_type));
410  STXXL_VERBOSE1(" size of a leaf element: " << sizeof(typename leaf_block_type::value_type));
411 
412 
413  create_empty_leaf();
414  }
415 
416  btree(const key_compare& c_,
417  unsigned_type node_cache_size_in_bytes,
418  unsigned_type leaf_cache_size_in_bytes
419  ) :
420  key_compare_(c_),
421  node_cache_(node_cache_size_in_bytes, this, key_compare_),
422  leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
423  iterator_map_(this),
424  size_(0),
425  height_(2),
426  prefetching_enabled_(true),
427  bm_(block_manager::get_instance())
428  {
429  STXXL_VERBOSE1("Creating a btree, addr=" << this);
430  STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size);
431  STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size);
432 
433  create_empty_leaf();
434  }
435 
436  virtual ~btree()
437  {
438  try
439  {
440  deallocate_children();
441  } catch (...)
442  {
443  // no exceptions in destructor
444  }
445  }
446 
447  size_type size() const
448  {
449  return size_;
450  }
451 
453  {
455  }
456 
457  bool empty() const
458  {
459  return !size_;
460  }
461 
462  std::pair<iterator, bool> insert(const value_type& x)
463  {
464  root_node_iterator_type it = root_node_.lower_bound(x.first);
465  assert(!root_node_.empty());
466  assert(it != root_node_.end());
467  if (height_ == 2) // 'it' points to a leaf
468  {
469  STXXL_VERBOSE1("Inserting new value into a leaf");
470  leaf_type* Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true);
471  assert(Leaf);
472  std::pair<key_type, leaf_bid_type> Splitter;
473  std::pair<iterator, bool> result = Leaf->insert(x, Splitter);
474  if (result.second)
475  ++size_;
476 
477  leaf_cache_.unfix_node((leaf_bid_type)it->second);
478  //if(key_compare::max_value() == Splitter.first)
479  if (!(key_compare_(key_compare::max_value(), Splitter.first) ||
480  key_compare_(Splitter.first, key_compare::max_value())))
481  return result;
482  // no overflow/splitting happened
483 
484  STXXL_VERBOSE1("Inserting new value into root node");
485 
486  insert_into_root(std::make_pair(Splitter.first, node_bid_type(Splitter.second)));
487 
488  assert(leaf_cache_.nfixed() == 0);
489  assert(node_cache_.nfixed() == 0);
490  return result;
491  }
492 
493  // 'it' points to a node
494  STXXL_VERBOSE1("Inserting new value into a node");
495  node_type* Node = node_cache_.get_node((node_bid_type)it->second, true);
496  assert(Node);
497  std::pair<key_type, node_bid_type> Splitter;
498  std::pair<iterator, bool> result = Node->insert(x, height_ - 1, Splitter);
499  if (result.second)
500  ++size_;
501 
502  node_cache_.unfix_node((node_bid_type)it->second);
503  //if(key_compare::max_value() == Splitter.first)
504  if (!(key_compare_(key_compare::max_value(), Splitter.first) ||
505  key_compare_(Splitter.first, key_compare::max_value())))
506  return result;
507  // no overflow/splitting happened
508 
509  STXXL_VERBOSE1("Inserting new value into root node");
510 
511  insert_into_root(Splitter);
512 
513  assert(leaf_cache_.nfixed() == 0);
514  assert(node_cache_.nfixed() == 0);
515 
516  return result;
517  }
518 
520  {
521  root_node_iterator_type it = root_node_.begin();
522  assert(it != root_node_.end());
523 
524  if (height_ == 2) // 'it' points to a leaf
525  {
526  STXXL_VERBOSE1("btree: retrieving begin() from the first leaf");
527  leaf_type* Leaf = leaf_cache_.get_node((leaf_bid_type)it->second);
528  assert(Leaf);
529 
530  assert(leaf_cache_.nfixed() == 0);
531  assert(node_cache_.nfixed() == 0);
532  return Leaf->begin();
533  }
534 
535  // 'it' points to a node
536  STXXL_VERBOSE1("btree: retrieving begin() from the first node");
537  node_type* Node = node_cache_.get_node((node_bid_type)it->second, true);
538  assert(Node);
539  iterator result = Node->begin(height_ - 1);
540  node_cache_.unfix_node((node_bid_type)it->second);
541 
542  assert(leaf_cache_.nfixed() == 0);
543  assert(node_cache_.nfixed() == 0);
544 
545  return result;
546  }
547 
549  {
550  root_node_const_iterator_type it = root_node_.begin();
551  assert(it != root_node_.end());
552 
553  if (height_ == 2) // 'it' points to a leaf
554  {
555  STXXL_VERBOSE1("btree: retrieving begin() from the first leaf");
556  leaf_type const* Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second);
557  assert(Leaf);
558  assert(leaf_cache_.nfixed() == 0);
559  assert(node_cache_.nfixed() == 0);
560  return Leaf->begin();
561  }
562 
563  // 'it' points to a node
564  STXXL_VERBOSE1("btree: retrieving begin() from the first node");
565  node_type const* Node = node_cache_.get_const_node((node_bid_type)it->second, true);
566  assert(Node);
567  const_iterator result = Node->begin(height_ - 1);
568  node_cache_.unfix_node((node_bid_type)it->second);
569  assert(leaf_cache_.nfixed() == 0);
570  assert(node_cache_.nfixed() == 0);
571  return result;
572  }
573 
575  {
576  return end_iterator;
577  }
578 
580  {
581  return end_iterator;
582  }
583 
584  data_type& operator [] (const key_type& k)
585  {
586  return (*((insert(value_type(k, data_type()))).first)).second;
587  }
588 
590  {
591  root_node_iterator_type it = root_node_.lower_bound(k);
592  assert(it != root_node_.end());
593 
594  if (height_ == 2) // 'it' points to a leaf
595  {
596  STXXL_VERBOSE1("Searching in a leaf");
597  leaf_type* Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true);
598  assert(Leaf);
599  iterator result = Leaf->find(k);
600  leaf_cache_.unfix_node((leaf_bid_type)it->second);
601  assert(result == end() || result->first == k);
602  assert(leaf_cache_.nfixed() == 0);
603  assert(node_cache_.nfixed() == 0);
604  return result;
605  }
606 
607  // 'it' points to a node
608  STXXL_VERBOSE1("Searching in a node");
609  node_type* Node = node_cache_.get_node((node_bid_type)it->second, true);
610  assert(Node);
611  iterator result = Node->find(k, height_ - 1);
612  node_cache_.unfix_node((node_bid_type)it->second);
613 
614  assert(result == end() || result->first == k);
615  assert(leaf_cache_.nfixed() == 0);
616  assert(node_cache_.nfixed() == 0);
617  return result;
618  }
619 
620  const_iterator find(const key_type& k) const
621  {
622  root_node_const_iterator_type it = root_node_.lower_bound(k);
623  assert(it != root_node_.end());
624 
625  if (height_ == 2) // 'it' points to a leaf
626  {
627  STXXL_VERBOSE1("Searching in a leaf");
628  leaf_type const* Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second, true);
629  assert(Leaf);
630  const_iterator result = Leaf->find(k);
631  leaf_cache_.unfix_node((leaf_bid_type)it->second);
632  assert(result == end() || result->first == k);
633  assert(leaf_cache_.nfixed() == 0);
634  assert(node_cache_.nfixed() == 0);
635  return result;
636  }
637 
638  // 'it' points to a node
639  STXXL_VERBOSE1("Searching in a node");
640  node_type const* Node = node_cache_.get_const_node((node_bid_type)it->second, true);
641  assert(Node);
642  const_iterator result = Node->find(k, height_ - 1);
643  node_cache_.unfix_node((node_bid_type)it->second);
644 
645  assert(result == end() || result->first == k);
646  assert(leaf_cache_.nfixed() == 0);
647  assert(node_cache_.nfixed() == 0);
648  return result;
649  }
650 
652  {
653  root_node_iterator_type it = root_node_.lower_bound(k);
654  assert(it != root_node_.end());
655 
656  if (height_ == 2) // 'it' points to a leaf
657  {
658  STXXL_VERBOSE1("Searching lower bound in a leaf");
659  leaf_type* Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true);
660  assert(Leaf);
661  iterator result = Leaf->lower_bound(k);
662  leaf_cache_.unfix_node((leaf_bid_type)it->second);
663  assert(leaf_cache_.nfixed() == 0);
664  assert(node_cache_.nfixed() == 0);
665  return result;
666  }
667 
668  // 'it' points to a node
669  STXXL_VERBOSE1("Searching lower bound in a node");
670  node_type* Node = node_cache_.get_node((node_bid_type)it->second, true);
671  assert(Node);
672  iterator result = Node->lower_bound(k, height_ - 1);
673  node_cache_.unfix_node((node_bid_type)it->second);
674 
675  assert(leaf_cache_.nfixed() == 0);
676  assert(node_cache_.nfixed() == 0);
677  return result;
678  }
679 
681  {
682  root_node_const_iterator_type it = root_node_.lower_bound(k);
683  assert(it != root_node_.end());
684 
685  if (height_ == 2) // 'it' points to a leaf
686  {
687  STXXL_VERBOSE1("Searching lower bound in a leaf");
688  leaf_type const* Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second, true);
689  assert(Leaf);
690  const_iterator result = Leaf->lower_bound(k);
691  leaf_cache_.unfix_node((leaf_bid_type)it->second);
692 
693  assert(leaf_cache_.nfixed() == 0);
694  assert(node_cache_.nfixed() == 0);
695  return result;
696  }
697 
698  // 'it' points to a node
699  STXXL_VERBOSE1("Searching lower bound in a node");
700  node_type const* Node = node_cache_.get_const_node((node_bid_type)it->second, true);
701  assert(Node);
702  const_iterator result = Node->lower_bound(k, height_ - 1);
703  node_cache_.unfix_node((node_bid_type)it->second);
704 
705  assert(leaf_cache_.nfixed() == 0);
706  assert(node_cache_.nfixed() == 0);
707  return result;
708  }
709 
711  {
712  root_node_iterator_type it = root_node_.upper_bound(k);
713  assert(it != root_node_.end());
714 
715  if (height_ == 2) // 'it' points to a leaf
716  {
717  STXXL_VERBOSE1("Searching upper bound in a leaf");
718  leaf_type* Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true);
719  assert(Leaf);
720  iterator result = Leaf->upper_bound(k);
721  leaf_cache_.unfix_node((leaf_bid_type)it->second);
722 
723  assert(leaf_cache_.nfixed() == 0);
724  assert(node_cache_.nfixed() == 0);
725  return result;
726  }
727 
728  // 'it' points to a node
729  STXXL_VERBOSE1("Searching upper bound in a node");
730  node_type* Node = node_cache_.get_node((node_bid_type)it->second, true);
731  assert(Node);
732  iterator result = Node->upper_bound(k, height_ - 1);
733  node_cache_.unfix_node((node_bid_type)it->second);
734 
735  assert(leaf_cache_.nfixed() == 0);
736  assert(node_cache_.nfixed() == 0);
737  return result;
738  }
739 
741  {
742  root_node_const_iterator_type it = root_node_.upper_bound(k);
743  assert(it != root_node_.end());
744 
745  if (height_ == 2) // 'it' points to a leaf
746  {
747  STXXL_VERBOSE1("Searching upper bound in a leaf");
748  leaf_type const* Leaf = leaf_cache_.get_const_node((leaf_bid_type)it->second, true);
749  assert(Leaf);
750  const_iterator result = Leaf->upper_bound(k);
751  leaf_cache_.unfix_node((leaf_bid_type)it->second);
752 
753  assert(leaf_cache_.nfixed() == 0);
754  assert(node_cache_.nfixed() == 0);
755  return result;
756  }
757 
758  // 'it' points to a node
759  STXXL_VERBOSE1("Searching upper bound in a node");
760  node_type const* Node = node_cache_.get_const_node((node_bid_type)it->second, true);
761  assert(Node);
762  const_iterator result = Node->upper_bound(k, height_ - 1);
763  node_cache_.unfix_node((node_bid_type)it->second);
764 
765  assert(leaf_cache_.nfixed() == 0);
766  assert(node_cache_.nfixed() == 0);
767  return result;
768  }
769 
770  std::pair<iterator, iterator> equal_range(const key_type& k)
771  {
772  iterator l = lower_bound(k); // l->first >= k
773 
774  if (l == end() || key_compare_(k, l->first)) // if (k < l->first)
775  return std::pair<iterator, iterator>(l, l);
776  // then upper_bound == lower_bound
777 
778  iterator u = l;
779  ++u; // only one element ==k can exist
780 
781  assert(leaf_cache_.nfixed() == 0);
782  assert(node_cache_.nfixed() == 0);
783 
784  return std::pair<iterator, iterator>(l, u); // then upper_bound == (lower_bound+1)
785  }
786 
787  std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
788  {
789  const_iterator l = lower_bound(k); // l->first >= k
790 
791  if (l == end() || key_compare_(k, l->first)) // if (k < l->first)
792  return std::pair<const_iterator, const_iterator>(l, l);
793  // then upper_bound == lower_bound
794 
795  const_iterator u = l;
796  ++u; // only one element ==k can exist
797 
798  assert(leaf_cache_.nfixed() == 0);
799  assert(node_cache_.nfixed() == 0);
800  return std::pair<const_iterator, const_iterator>(l, u); // then upper_bound == (lower_bound+1)
801  }
802 
804  {
805  root_node_iterator_type it = root_node_.lower_bound(k);
806  assert(it != root_node_.end());
807  if (height_ == 2) // 'it' points to a leaf
808  {
809  STXXL_VERBOSE1("Deleting key from a leaf");
810  leaf_type* Leaf = leaf_cache_.get_node((leaf_bid_type)it->second, true);
811  assert(Leaf);
812  size_type result = Leaf->erase(k);
813  size_ -= result;
814  leaf_cache_.unfix_node((leaf_bid_type)it->second);
815  assert(leaf_cache_.nfixed() == 0);
816  assert(node_cache_.nfixed() == 0);
817 
818  if ((!Leaf->underflows()) || root_node_.size() == 1)
819  return result;
820  // no underflow or root has a special degree 1 (too few elements)
821 
822  STXXL_VERBOSE1("btree: Fusing or rebalancing a leaf");
823  fuse_or_balance(it, leaf_cache_);
824 
825  assert(leaf_cache_.nfixed() == 0);
826  assert(node_cache_.nfixed() == 0);
827 
828  return result;
829  }
830 
831  // 'it' points to a node
832  STXXL_VERBOSE1("Deleting key from a node");
833  assert(root_node_.size() >= 2);
834  node_type* Node = node_cache_.get_node((node_bid_type)it->second, true);
835  assert(Node);
836  size_type result = Node->erase(k, height_ - 1);
837  size_ -= result;
838  node_cache_.unfix_node((node_bid_type)it->second);
839  assert(leaf_cache_.nfixed() == 0);
840  assert(node_cache_.nfixed() == 0);
841  if (!Node->underflows())
842  return result;
843  // no underflow happened
844 
845  STXXL_VERBOSE1("Fusing or rebalancing a node");
846  fuse_or_balance(it, node_cache_);
847 
848  if (root_node_.size() == 1)
849  {
850  STXXL_VERBOSE1("btree Root has size 1 and height > 2");
851  STXXL_VERBOSE1("btree Deallocate root and decrease height");
852  it = root_node_.begin();
853  node_bid_type RootBid = it->second;
854  assert(it->first == key_compare::max_value());
855  node_type* RootNode = node_cache_.get_node(RootBid);
856  assert(RootNode);
857  assert(RootNode->back().first == key_compare::max_value());
858  root_node_.clear();
859  root_node_.insert(RootNode->block().begin(),
860  RootNode->block().begin() + RootNode->size());
861 
862  node_cache_.delete_node(RootBid);
863  --height_;
864  STXXL_VERBOSE1("btree Decreasing height to " << height_);
865  }
866 
867  assert(leaf_cache_.nfixed() == 0);
868  assert(node_cache_.nfixed() == 0);
869 
870  return result;
871  }
872 
874  {
875  if (find(k) == end())
876  return 0;
877 
878  return 1;
879  }
880 
881  void erase(iterator pos)
882  {
883  assert(pos != end());
884 #ifndef NDEBUG
885  size_type old_size = size();
886 #endif
887 
888  erase(pos->first);
889 
890  assert(size() == old_size - 1);
891  }
892 
893  iterator insert(iterator /*pos*/, const value_type& x)
894  {
895  return insert(x).first; // pos ignored in the current version
896  }
897 
898  void clear()
899  {
900  deallocate_children();
901 
902  root_node_.clear();
903 
904  size_ = 0;
905  height_ = 2,
906 
907  create_empty_leaf();
908  assert(leaf_cache_.nfixed() == 0);
909  assert(node_cache_.nfixed() == 0);
910  }
911 
912  template <class InputIterator>
913  void insert(InputIterator b, InputIterator e)
914  {
915  while (b != e)
916  {
917  insert(*(b++));
918  }
919  }
920 
921  template <class InputIterator>
922  btree(InputIterator b,
923  InputIterator e,
924  const key_compare& c_,
925  unsigned_type node_cache_size_in_bytes,
926  unsigned_type leaf_cache_size_in_bytes,
927  bool range_sorted = false,
928  double node_fill_factor = 0.75,
929  double leaf_fill_factor = 0.6
930  ) :
931  key_compare_(c_),
932  node_cache_(node_cache_size_in_bytes, this, key_compare_),
933  leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
934  iterator_map_(this),
935  size_(0),
936  height_(2),
937  prefetching_enabled_(true),
938  bm_(block_manager::get_instance())
939  {
940  STXXL_VERBOSE1("Creating a btree, addr=" << this);
941  STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size);
942  STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size);
943 
944  if (range_sorted == false)
945  {
946  create_empty_leaf();
947  insert(b, e);
948  assert(leaf_cache_.nfixed() == 0);
949  assert(node_cache_.nfixed() == 0);
950  return;
951  }
952 
953  bulk_construction(b, e, node_fill_factor, leaf_fill_factor);
954  assert(leaf_cache_.nfixed() == 0);
955  assert(node_cache_.nfixed() == 0);
956  }
957 
958 
959  template <class InputIterator>
960  btree(InputIterator b,
961  InputIterator e,
962  unsigned_type node_cache_size_in_bytes,
963  unsigned_type leaf_cache_size_in_bytes,
964  bool range_sorted = false,
965  double node_fill_factor = 0.75,
966  double leaf_fill_factor = 0.6
967  ) :
968  node_cache_(node_cache_size_in_bytes, this, key_compare_),
969  leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
970  iterator_map_(this),
971  size_(0),
972  height_(2),
973  prefetching_enabled_(true),
974  bm_(block_manager::get_instance())
975  {
976  STXXL_VERBOSE1("Creating a btree, addr=" << this);
977  STXXL_VERBOSE1(" bytes in a node: " << node_bid_type::size);
978  STXXL_VERBOSE1(" bytes in a leaf: " << leaf_bid_type::size);
979 
980  if (range_sorted == false)
981  {
982  create_empty_leaf();
983  insert(b, e);
984  assert(leaf_cache_.nfixed() == 0);
985  assert(node_cache_.nfixed() == 0);
986  return;
987  }
988 
989  bulk_construction(b, e, node_fill_factor, leaf_fill_factor);
990  assert(leaf_cache_.nfixed() == 0);
991  assert(node_cache_.nfixed() == 0);
992  }
993 
994  void erase(iterator first, iterator last)
995  {
996  if (first == begin() && last == end())
997  clear();
998 
999  else
1000  while (first != last)
1001  erase(first++);
1002  }
1003 
1005  {
1006  return key_compare_;
1007  }
1009  {
1010  return value_compare(key_compare_);
1011  }
1012 
1013  void swap(btree& obj)
1014  {
1015  std::swap(key_compare_, obj.key_compare_); // OK
1016 
1017  std::swap(node_cache_, obj.node_cache_); // OK
1018  std::swap(leaf_cache_, obj.leaf_cache_); // OK
1019 
1020 
1021  std::swap(iterator_map_, obj.iterator_map_); // must update all iterators
1022 
1023  std::swap(end_iterator, obj.end_iterator);
1024  std::swap(size_, obj.size_);
1025  std::swap(height_, obj.height_);
1026  std::swap(alloc_strategy_, obj.alloc_strategy_);
1027  std::swap(root_node_, obj.root_node_);
1028  }
1029 
1031  {
1032  prefetching_enabled_ = true;
1033  }
1035  {
1036  prefetching_enabled_ = false;
1037  }
1039  {
1040  return prefetching_enabled_;
1041  }
1042 
1043  void print_statistics(std::ostream& o) const
1044  {
1045  o << "Node cache statistics:" << std::endl;
1046  node_cache_.print_statistics(o);
1047  o << "Leaf cache statistics:" << std::endl;
1048  leaf_cache_.print_statistics(o);
1049  }
1051  {
1052  node_cache_.reset_statistics();
1053  leaf_cache_.reset_statistics();
1054  }
1055 };
1056 
1057 template <class KeyType,
1058  class DataType,
1059  class CompareType,
1060  unsigned LogNodeSize,
1061  unsigned LogLeafSize,
1062  class PDAllocStrategy
1063  >
1066 {
1067  return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
1068 }
1069 
1070 template <class KeyType,
1071  class DataType,
1072  class CompareType,
1073  unsigned LogNodeSize,
1074  unsigned LogLeafSize,
1075  class PDAllocStrategy
1076  >
1079 {
1080  return !(a == b);
1081 }
1082 
1083 
1084 template <class KeyType,
1085  class DataType,
1086  class CompareType,
1087  unsigned LogNodeSize,
1088  unsigned LogLeafSize,
1089  class PDAllocStrategy
1090  >
1091 inline bool operator < (const btree<KeyType, DataType, CompareType, LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1093 {
1094  return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
1095 }
1096 
1097 
1098 template <class KeyType,
1099  class DataType,
1100  class CompareType,
1101  unsigned LogNodeSize,
1102  unsigned LogLeafSize,
1103  class PDAllocStrategy
1104  >
1107 {
1108  return b < a;
1109 }
1110 
1111 
1112 template <class KeyType,
1113  class DataType,
1114  class CompareType,
1115  unsigned LogNodeSize,
1116  unsigned LogLeafSize,
1117  class PDAllocStrategy
1118  >
1119 inline bool operator <= (const btree<KeyType, DataType, CompareType, LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1121 {
1122  return !(b < a);
1123 }
1124 
1125 template <class KeyType,
1126  class DataType,
1127  class CompareType,
1128  unsigned LogNodeSize,
1129  unsigned LogLeafSize,
1130  class PDAllocStrategy
1131  >
1134 {
1135  return !(a < b);
1136 }
1137 
1138 } // namespace btree
1139 
1141 
1142 
1143 namespace std {
1144 
1145 template <class KeyType,
1146  class DataType,
1147  class CompareType,
1148  unsigned LogNodeSize,
1149  unsigned LogLeafSize,
1150  class PDAllocStrategy
1151  >
1154 {
1155  if (&a != &b)
1156  a.swap(b);
1157 }
1158 
1159 } // namespace std
1160 
1161 #endif // !STXXL_CONTAINERS_BTREE_BTREE_HEADER
std::pair< key_type, bid_type > insert(const std::pair< key_type, bid_type > &splitter, const block_iterator &place2insert)
Definition: node.h:94
#define STXXL_ASSERT(condition)
Definition: verbose.h:157
node_cache< leaf_type, SelfType > leaf_cache_type
Definition: btree.h:63
stxxl::uint64 size_type
Definition: btree.h:49
size_type size() const
Definition: btree.h:447
std::pair< iterator, bool > insert(const value_type &x, std::pair< key_type, bid_type > &splitter)
Definition: leaf.h:302
const bid_type & my_bid() const
Definition: leaf.h:233
bool prefetching_enabled_
Definition: btree.h:95
key_type balance(normal_node &Left)
Definition: node.h:632
Block manager class.
Definition: block_manager.h:63
void insert(InputIterator b, InputIterator e)
Definition: btree.h:913
long long int int64
Definition: types.h:40
std::pair< iterator, iterator > equal_range(const key_type &k)
Definition: btree.h:770
value_type & reference
Definition: btree.h:52
unsigned long long int uint64
Definition: types.h:41
void bulk_construction(InputIterator b, InputIterator e, double node_fill_factor, double leaf_fill_factor)
Definition: btree.h:256
key_compare key_compare_
Definition: btree.h:89
std::pair< const_iterator, const_iterator > equal_range(const key_type &k) const
Definition: btree.h:787
std::map< key_type, node_bid_type, key_compare > root_node_type
Definition: btree.h:99
virtual ~btree()
Definition: btree.h:436
const_iterator end() const
Definition: btree.h:579
info_type info
Per block information element.
Definition: typed_block.h:180
bool underflows() const
Definition: node.h:223
void deallocate_children()
Definition: btree.h:229
normal_node< key_type, key_compare, RawNodeSize, SelfType > node_type
Definition: btree.h:72
block_type & block()
Definition: node.h:217
iterator_map< SelfType > iterator_map_type
Definition: btree.h:70
unsigned min_nelements() const
Definition: node.h:226
btree_const_iterator< SelfType > const_iterator
Definition: btree.h:67
iterator begin()
Definition: btree.h:519
node_type::block_type node_block_type
Definition: btree.h:73
iterator end()
Definition: btree.h:574
PDAllocStrategy alloc_strategy_type
Definition: btree.h:47
const_iterator lower_bound(const key_type &k) const
Definition: btree.h:680
void fuse(const normal_node &Src)
Definition: node.h:613
void insert_into_root(const std::pair< key_type, node_bid_type > &splitter)
Definition: btree.h:109
void erase(iterator first, iterator last)
Definition: btree.h:994
size_type erase(const key_type &k)
Definition: btree.h:803
iterator upper_bound(const key_type &k)
Definition: leaf.h:478
btree(unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes)
Definition: btree.h:393
iterator lower_bound(const key_type &k)
Definition: btree.h:651
reference back()
Definition: node.h:297
std::pair< iterator, bool > insert(const value_type &x)
Definition: btree.h:462
size_type erase(const key_type &k)
Definition: leaf.h:508
alloc_strategy_type alloc_strategy_
Definition: btree.h:97
leaf_type::block_type leaf_block_type
Definition: btree.h:61
iterator find(const key_type &k)
Definition: btree.h:589
iterator find(const key_type &k, unsigned height)
Definition: node.h:421
std::pair< const key_type, data_type > value_type
Definition: btree.h:51
key_type balance(normal_leaf &Left)
Definition: leaf.h:590
iterator insert(iterator, const value_type &x)
Definition: btree.h:893
root_node_type::const_iterator root_node_const_iterator_type
Definition: btree.h:101
Block containing elements of fixed length.
Definition: typed_block.h:238
unsigned max_nelements() const
Definition: node.h:225
stxxl::int64 difference_type
Definition: btree.h:50
bool prefetching_enabled()
Definition: btree.h:1038
bool operator!=(const uint_pair &b) const
inequality checking operator
Definition: uint_types.h:201
void erase(iterator pos)
Definition: btree.h:881
CompareType key_compare
Definition: btree.h:43
normal_leaf< key_type, data_type, key_compare, RawLeafSize, SelfType > leaf_type
Definition: btree.h:59
const value_type & const_reference
Definition: btree.h:53
reference back()
Definition: leaf.h:275
bool operator>(const uint_pair &b) const
greater comparison operator
Definition: uint_types.h:219
btree(InputIterator b, InputIterator e, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted=false, double node_fill_factor=0.75, double leaf_fill_factor=0.6)
Definition: btree.h:960
void swap(btree &obj)
Definition: btree.h:1013
bool underflows() const
Definition: leaf.h:180
iterator_map_type iterator_map_
Definition: btree.h:92
void enable_prefetching()
Definition: btree.h:1030
size_type size_
Definition: btree.h:93
const_iterator upper_bound(const key_type &k) const
Definition: btree.h:740
bool operator>=(const uint_pair &b) const
greater-or-equal comparison operator
Definition: uint_types.h:225
leaf_cache_type leaf_cache_
Definition: btree.h:91
void reset_statistics()
Definition: btree.h:1050
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void STXXL_UNUSED(const U &)
Definition: unused.h:23
iterator lower_bound(const key_type &k)
Definition: leaf.h:447
size_type count(const key_type &k)
Definition: btree.h:873
iterator begin(unsigned height)
Definition: node.h:377
unsigned int height_
Definition: btree.h:94
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
btree_iterator< SelfType > iterator
Definition: btree.h:66
value_compare value_comp() const
Definition: btree.h:1008
btree(const key_compare &c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes)
Definition: btree.h:416
KeyType key_type
Definition: btree.h:41
void fuse_or_balance(root_node_iterator_type UIt, CacheType &cache_)
Definition: btree.h:169
#define STXXL_THROW2(exception_type, location, error_message)
Throws exception_type with &quot;Error in [location] : [error_message]&quot;.
static uint_pair max()
return an uint_pair instance containing the largest value possible
Definition: uint_types.h:244
node_cache_type node_cache_
Definition: btree.h:90
iterator begin()
Returns iterator pointing to the first element.
Definition: typed_block.h:93
bool overflows() const
Definition: node.h:222
iterator begin()
Definition: leaf.h:356
value_type const * const_pointer
Definition: btree.h:55
void deallocate_children(unsigned height)
Definition: node.h:725
iterator find(const key_type &k)
Definition: leaf.h:423
iterator upper_bound(const key_type &k)
Definition: btree.h:710
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
compat::remove_const< Integral >::type div_ceil(Integral __n, Integral2 __d)
Definition: utils.h:200
value_type * pointer
Definition: btree.h:54
node_cache< node_type, SelfType > node_cache_type
Definition: btree.h:76
void push_back(const value_type &x)
Definition: leaf.h:693
bid_type & succ()
Definition: leaf.h:186
unsigned max_nelements() const
Definition: leaf.h:182
void print_statistics(std::ostream &o) const
Definition: btree.h:1043
root_node_type root_node_
Definition: btree.h:105
DataType data_type
Definition: btree.h:42
unsigned size() const
Definition: node.h:252
size_type max_size() const
Definition: btree.h:452
root_node_type::iterator root_node_iterator_type
Definition: btree.h:100
node_type::bid_type node_bid_type
Definition: btree.h:75
leaf_type::bid_type leaf_bid_type
Definition: btree.h:62
bool overflows() const
Definition: leaf.h:179
btree(InputIterator b, InputIterator e, const key_compare &c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted=false, double node_fill_factor=0.75, double leaf_fill_factor=0.6)
Definition: btree.h:922
iterator lower_bound(const key_type &k, unsigned height)
Definition: node.h:485
const_iterator find(const key_type &k) const
Definition: btree.h:620
ExtIterator find(ExtIterator begin, ExtIterator end, const EqualityComparable &value, int_type nbuffers=0)
External equivalent of std::find, see stxxl::find.
Definition: scan.h:274
void disable_prefetching()
Definition: btree.h:1034
block_manager * bm_
Definition: btree.h:96
leaf_type::value_compare value_compare
Definition: btree.h:79
External vector type generator.
Definition: vector.h:2580
void push_back(const value_type &x)
Definition: node.h:751
const_iterator begin() const
Definition: btree.h:548
iterator end_iterator
Definition: btree.h:106
std::pair< key_type, node_bid_type > root_node_pair_type
Definition: btree.h:102
void fuse(const normal_leaf &Src)
Definition: leaf.h:537
key_compare key_comp() const
Definition: btree.h:1004
bool operator==(const uint_pair &b) const
equality checking operator
Definition: uint_types.h:195
void create_empty_leaf()
Definition: btree.h:220
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
btree< KeyType, DataType, CompareType, RawNodeSize, RawLeafSize, PDAllocStrategy > SelfType
Definition: btree.h:45
bool empty() const
Definition: btree.h:457
unsigned size() const
Definition: leaf.h:228
iterator upper_bound(const key_type &k, unsigned height)
Definition: node.h:549
bid_type & pred()
Definition: leaf.h:190