Пример #1
0
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);
    }
}
Пример #2
0
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);
}