void InnerNode::split(std::vector<DataNode*>& path) { assert(pivots_.size() > 1); size_t n = pivots_.size()/2; size_t n1 = pivots_.size() - n - 1; Slice k = pivots_[n].key; InnerNode *ni = tree_->new_inner_node(); ni->bottom_ = IS_LEAF(pivots_[n].child); assert(ni); ni->first_child_ = pivots_[n].child; ni->first_msgbuf_ = pivots_[n].msgbuf; ni->pivots_.resize(n1); std::copy(pivots_.begin() + n + 1, pivots_.end(), ni->pivots_.begin()); pivots_.resize(n); size_t pivots_sz1 = 0; size_t msgcnt1 = 0; size_t msgbufsz1 = 0; msgcnt1 += ni->first_msgbuf_->count(); msgbufsz1 += ni->first_msgbuf_->size(); for(size_t i = 0; i < ni->pivots_.size(); i++) { pivots_sz1 += pivot_size(ni->pivots_[i].key); msgcnt1 += ni->pivots_[i].msgbuf->count(); msgbufsz1 += ni->pivots_[i].msgbuf->size(); } ni->pivots_sz_ = pivots_sz1; ni->msgcnt_ = msgcnt1; ni->msgbufsz_ = msgbufsz1; pivots_sz_ -= (pivots_sz1 + pivot_size(k)); msgcnt_ -= msgcnt1; msgbufsz_ -= msgbufsz1; ni->set_dirty(true); ni->dec_ref(); path.pop_back(); unlock(); dec_ref(); // propagation if( path.size() == 0) { // i'm root InnerNode *nr = tree_->new_inner_node(); assert(nr); nr->bottom_ = false; nr->first_child_ = nid_; MsgBuf* mb0 = new MsgBuf(tree_->options_.comparator); nr->first_msgbuf_ = mb0; nr->msgbufsz_ += mb0->size(); nr->pivots_.resize(1); MsgBuf* mb1 = new MsgBuf(tree_->options_.comparator); nr->pivots_[0] = Pivot(k.clone(), ni->nid_, mb1); nr->pivots_sz_ += pivot_size(k); nr->msgbufsz_ += mb1->size(); nr->set_dirty(true); tree_->pileup(nr); // need not do nr->dec_ref() here } else { // propagation InnerNode* parent = (InnerNode*) path.back(); assert(parent); parent->add_pivot(k, ni->nid_, path); } }
void LeafNode::split(Slice anchor) { if (balancing_) { unlock(); return; } balancing_ = true; assert(records_.size() > 1); // release the write lock unlock(); // need to search from root to leaf again // since the path may be modified vector<DataNode*> path; tree_->lock_path(anchor, path); assert(path.back() == this); // may have deletions during this period if (records_.size() <= 1 || (records_.size() <= (tree_->options_.leaf_node_record_count / 2) && size() <= (tree_->options_.leaf_node_page_size / 2) )) { while (path.size()) { path.back()->unlock(); path.back()->dec_ref(); path.pop_back(); } return; } // create new leaf LeafNode *nl = tree_->new_leaf_node(); assert(nl); // set siblings nl->left_sibling_ = nid_; nl->right_sibling_ = right_sibling_; if(right_sibling_ >= NID_LEAF_START) { LeafNode *rl = (LeafNode*)tree_->load_node(right_sibling_, false); assert(rl); rl->write_lock(); rl->left_sibling_ = nl->nid_; rl->set_dirty(true); rl->unlock(); rl->dec_ref(); } right_sibling_ = nl->nid_; Slice k = records_.split(nl->records_); refresh_buckets_info(); nl->refresh_buckets_info(); set_dirty(true); nl->set_dirty(true); nl->dec_ref(); balancing_ = false; path.pop_back(); unlock(); dec_ref(); // propagation InnerNode *parent = (InnerNode*) path.back(); assert(parent); parent->add_pivot(k, nl->nid_, path); }