| 646 | |
| 647 | template <typename Value, typename Key, typename KeyOfValue, typename Cmp> |
| 648 | bool BePlusTree<Value, Key, KeyOfValue, Cmp>::add(const Value& item, Accessor* accessor) |
| 649 | { |
| 650 | // Finish initialization of the tree if necessary |
| 651 | if (!root) |
| 652 | root = FB_NEW_POOL(*pool) ItemList(); |
| 653 | |
| 654 | // Find leaf page for our item |
| 655 | NodePtr vList = this->root; |
| 656 | const Key& key = KeyOfValue::generate(nullptr, item); |
| 657 | for (int lev = this->level; lev > 0; lev--) |
| 658 | { |
| 659 | FB_SIZE_T pos; |
| 660 | if (!vList.nodes->find(key, pos)) |
| 661 | { |
| 662 | if (pos > 0) |
| 663 | pos--; |
| 664 | } |
| 665 | vList = (*vList.nodes)[pos]; |
| 666 | } |
| 667 | |
| 668 | ItemList *leaf = vList.items; |
| 669 | |
| 670 | FB_SIZE_T pos; |
| 671 | if (leaf->find(key, pos)) |
| 672 | { |
| 673 | if (accessor) |
| 674 | { |
| 675 | accessor->curr = leaf; |
| 676 | accessor->curPos = pos; |
| 677 | } |
| 678 | return false; |
| 679 | } |
| 680 | |
| 681 | if (leaf->getCount() < LEAF_COUNT) |
| 682 | { |
| 683 | leaf->insert(pos, item); |
| 684 | return true; |
| 685 | } |
| 686 | |
| 687 | // Page is full. Look up nearby pages for space if possible |
| 688 | ItemList *temp; |
| 689 | // Adding items to the next page is cheaper in most cases that |
| 690 | // is why it is checked first |
| 691 | if ((temp = leaf->next) && temp->getCount() < LEAF_COUNT) |
| 692 | { |
| 693 | // Found space on the next page |
| 694 | if (pos == LEAF_COUNT) |
| 695 | { |
| 696 | // This would be ok if items were unique: temp->insert(0, item); |
| 697 | // The same applies to all simular cases below |
| 698 | temp->insert(0, item); |
| 699 | } |
| 700 | else |
| 701 | { |
| 702 | // Maybe splitting array by half would make things faster ? |
| 703 | // It should do it in case of random size items. |
| 704 | // It would make things slower in case of sequental items addition. |
| 705 | // Let's leave it as is now. |