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); }
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(); } }