Пример #1
0
void LeafNode::merge(Slice anchor)
{
    if (balancing_) {
        unlock();
        return;
    }
    balancing_ = true;
    assert(records_.size() == 0);
    // release the write lock
    unlock();

    // acquire write locks from root to leaf
    vector<DataNode*> path;
    tree_->lock_path(anchor, path);
    assert(path.back() == this);

    // may have insertions during this period
    if (records_.size() > 0) {
        while (path.size()) {
            path.back()->unlock();
            path.back()->dec_ref();
            path.pop_back();
        }
        return;
    }
    
    if (left_sibling_ >= NID_LEAF_START) {
        LeafNode *ll = (LeafNode*)tree_->load_node(left_sibling_, false);
        assert(ll);
        ll->write_lock();
        ll->right_sibling_ = right_sibling_;
        ll->set_dirty(true);
        ll->unlock();
        ll->dec_ref();
    }
    if (right_sibling_ >= NID_LEAF_START) {
        LeafNode *rl = (LeafNode*)tree_->load_node(right_sibling_, false);
        assert(rl);
        rl->write_lock();
        rl->left_sibling_ = left_sibling_;
        rl->set_dirty(true);
        rl->unlock();
        rl->dec_ref();
    }
    dead_ = true;
    balancing_ = false;

    path.pop_back();
    unlock();
    dec_ref();

    // propagation
    InnerNode *parent = (InnerNode*) path.back();
    assert(parent);
    parent->rm_pivot(nid_, path);
}
Пример #2
0
void InnerNode::rm_pivot(bid_t nid, std::vector<DataNode*>& path)
{
    // todo free memory of pivot key

    assert(path.back() == this);

    if (status_ == kSkeletonLoaded) {
        load_all_msgbuf();
    }

    if (first_child_ == nid) {
        /// @todo this is true only for single thread, fix me
        assert(first_msgbuf_->count() == 0);
        msgbufsz_ -= first_msgbuf_->size();
        delete first_msgbuf_;
        
        if (pivots_.size() == 0) {
            first_msgbuf_ = NULL;
            dead_ = true;

            path.pop_back();
            unlock();
            dec_ref();

            if (path.size() == 0) {
                // reach root
                tree_->collapse(); 
            } else {
                // propagation
                InnerNode* parent = (InnerNode*) path.back();
                assert(parent);
                parent->rm_pivot(nid_, path);
            }
            return;
        }

        // shift pivots
        first_child_ = pivots_[0].child;
        first_msgbuf_ = pivots_[0].msgbuf;

        pivots_sz_ -= pivot_size(pivots_[0].key);
        pivots_.erase(pivots_.begin());

        // TODO adjst size
    } else {
        vector<Pivot>::iterator it;
        for (it = pivots_.begin(); 
            it != pivots_.end(); it ++) {
            if (it->child == nid) {
                break;
            }
        }

        assert(it != pivots_.end());
        /// @todo this is true only for single thread, fix me
        assert(it->msgbuf->count() == 0);
        msgbufsz_ -= it->msgbuf->size();
        delete it->msgbuf;

        pivots_sz_ -= pivot_size(it->key);
        pivots_.erase(it);

        // TODO adjust size
    }

    set_dirty(true);

    // unlock all parents
    while (path.size()) {
        path.back()->unlock();
        path.back()->dec_ref();
        path.pop_back();
    }
}