mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Add read/modify/write functionality to Put() api
Summary: The application can set a callback function, which is applied on the previous value. And calculates the new value. This new value can be set, either inplace, if the previous value existed in memtable, and new value is smaller than previous value. Otherwise the new value is added normally. Test Plan: fbmake. Added unit tests. All unit tests pass. Reviewers: dhruba, haobo Reviewed By: haobo CC: sdong, kailiu, xinyaohu, sumeet, leveldb Differential Revision: https://reviews.facebook.net/D14745
This commit is contained in:
@@ -115,7 +115,7 @@ Status WriteBatch::Iterate(Handler* handler) const {
|
||||
return Status::Corruption("unknown WriteBatch tag");
|
||||
}
|
||||
}
|
||||
if (found != WriteBatchInternal::Count(this)) {
|
||||
if (found != WriteBatchInternal::Count(this)) {
|
||||
return Status::Corruption("WriteBatch has wrong count");
|
||||
} else {
|
||||
return Status::OK();
|
||||
@@ -194,14 +194,44 @@ class MemTableInserter : public WriteBatch::Handler {
|
||||
}
|
||||
|
||||
virtual void Put(const Slice& key, const Slice& value) {
|
||||
if (options_->inplace_update_support
|
||||
&& mem_->Update(sequence_, kTypeValue, key, value)) {
|
||||
if (!options_->inplace_update_support) {
|
||||
mem_->Add(sequence_, kTypeValue, key, value);
|
||||
} else if (options_->inplace_callback == nullptr) {
|
||||
mem_->Update(sequence_, key, value);
|
||||
RecordTick(options_->statistics.get(), NUMBER_KEYS_UPDATED);
|
||||
} else {
|
||||
mem_->Add(sequence_, kTypeValue, key, value);
|
||||
if (mem_->UpdateCallback(sequence_, key, value, *options_)) {
|
||||
RecordTick(options_->statistics.get(), NUMBER_KEYS_UPDATED);
|
||||
} else {
|
||||
// key not found in memtable. Do sst get/update/add
|
||||
SnapshotImpl read_from_snapshot;
|
||||
read_from_snapshot.number_ = sequence_;
|
||||
ReadOptions ropts;
|
||||
ropts.snapshot = &read_from_snapshot;
|
||||
|
||||
std::string prev_value;
|
||||
std::string merged_value;
|
||||
Status s = db_->Get(ropts, key, &prev_value);
|
||||
char* prev_buffer = const_cast<char*>(prev_value.c_str());
|
||||
size_t prev_size = prev_value.size();
|
||||
if (options_->inplace_callback(s.ok() ? prev_buffer: nullptr,
|
||||
s.ok() ? prev_size: 0,
|
||||
value, &merged_value)) {
|
||||
// prev_value is updated in-place with final value.
|
||||
mem_->Add(sequence_, kTypeValue, key, Slice(prev_buffer, prev_size));
|
||||
RecordTick(options_->statistics.get(), NUMBER_KEYS_WRITTEN);
|
||||
} else {
|
||||
// merged_value contains the final value. Only add if not empty.
|
||||
if (!merged_value.empty()) {
|
||||
mem_->Add(sequence_, kTypeValue, key, Slice(merged_value));
|
||||
RecordTick(options_->statistics.get(), NUMBER_KEYS_WRITTEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sequence_++;
|
||||
}
|
||||
|
||||
virtual void Merge(const Slice& key, const Slice& value) {
|
||||
mem_->Add(sequence_, kTypeMerge, key, value);
|
||||
sequence_++;
|
||||
|
||||
Reference in New Issue
Block a user