void MsgBuf::write(const Msg& msg) { #ifdef FAST_VECTOR MsgBuf::Iterator it = container_.lower_bound(msg, KeyComp(comp_)); #else MsgBuf::Iterator it = lower_bound(container_.begin(), container_.end(), msg, KeyComp(comp_)); #endif if (it == end() || it->key != msg.key) { container_.insert(it, msg); size_ += msg.size(); } else { size_ -= it->size(); it->destroy(); *it = msg; size_ += msg.size(); } }
void MsgBuf::append(MsgBuf::Iterator first, MsgBuf::Iterator last) { MsgBuf::Iterator it = container_.begin(); MsgBuf::Iterator jt = first; KeyComp comp(comp_); while(jt != last) { #ifdef FAST_VECTOR it = container_.lower_bound(it, jt->key, comp); #else it = lower_bound(it, container_.end(), jt->key, comp); #endif if (it == container_.end() || it->key != jt->key) { // important, it maybe invalid after insertion it = container_.insert(it, *jt); size_ += jt->size(); } else { size_ -= it->size(); it->destroy(); *it = *jt; size_ += it->size(); } jt ++; } }
bool LeafNode::cascade(MsgBuf *mb, InnerNode* parent) { write_lock(); if (status_ == kSkeletonLoaded) { load_all_buckets(); } // lock message buffer from parent mb->write_lock(); size_t oldcnt = mb->count(); size_t oldsz = mb->size(); Slice anchor = mb->begin()->key.clone(); // merge message buffer into leaf RecordBuckets res(tree_->options_.leaf_node_bucket_size); MsgBuf::Iterator it = mb->begin(); RecordBuckets::Iterator jt = records_.get_iterator(); while (it != mb->end() && jt.valid()) { int n = tree_->options_.comparator->compare(it->key, jt.record().key); if (n < 0) { if (it->type == Put) { res.push_back(to_record(*it)); } else { // just throw deletion to non-exist record it->destroy(); } it ++; } else if (n > 0) { res.push_back(jt.record()); jt.next(); } else { if (it->type == Put) { res.push_back(to_record(*it)); } // old record is deleted it ++; jt.record().key.destroy(); jt.record().value.destroy(); jt.next(); } } for (; it != mb->end(); it++) { if (it->type == Put) { res.push_back(to_record(*it)); } } while(jt.valid()) { res.push_back(jt.record()); jt.next(); } records_.swap(res); refresh_buckets_info(); set_dirty(true); // clear message buffer mb->clear(); parent->msgcnt_ = parent->msgcnt_ + mb->count() - oldcnt; parent->msgbufsz_ = parent->msgbufsz_ + mb->size() - oldsz; // unlock message buffer mb->unlock(); // crab walk parent->unlock(); if (records_.size() == 0) { merge(anchor); } else if (records_.size() > 1 && (records_.size() > tree_->options_.leaf_node_record_count || size() > tree_->options_.leaf_node_page_size)) { split(anchor); } else { unlock(); } anchor.destroy(); return true; }