summaryrefslogtreecommitdiff
path: root/db/write_batch.cc
diff options
context:
space:
mode:
Diffstat (limited to 'db/write_batch.cc')
-rw-r--r--db/write_batch.cc136
1 files changed, 63 insertions, 73 deletions
diff --git a/db/write_batch.cc b/db/write_batch.cc
index d561528..4e1e899 100644
--- a/db/write_batch.cc
+++ b/db/write_batch.cc
@@ -29,11 +29,53 @@ WriteBatch::WriteBatch() {
WriteBatch::~WriteBatch() { }
+WriteBatch::Handler::~Handler() { }
+
void WriteBatch::Clear() {
rep_.clear();
rep_.resize(12);
}
+Status WriteBatch::Iterate(Handler* handler) const {
+ Slice input(rep_);
+ if (input.size() < 12) {
+ return Status::Corruption("malformed WriteBatch (too small)");
+ }
+
+ input.remove_prefix(12);
+ Slice key, value;
+ int found = 0;
+ while (!input.empty()) {
+ found++;
+ char tag = input[0];
+ input.remove_prefix(1);
+ switch (tag) {
+ case kTypeValue:
+ if (GetLengthPrefixedSlice(&input, &key) &&
+ GetLengthPrefixedSlice(&input, &value)) {
+ handler->Put(key, value);
+ } else {
+ return Status::Corruption("bad WriteBatch Put");
+ }
+ break;
+ case kTypeDeletion:
+ if (GetLengthPrefixedSlice(&input, &key)) {
+ handler->Delete(key);
+ } else {
+ return Status::Corruption("bad WriteBatch Delete");
+ }
+ break;
+ default:
+ return Status::Corruption("unknown WriteBatch tag");
+ }
+ }
+ if (found != WriteBatchInternal::Count(this)) {
+ return Status::Corruption("WriteBatch has wrong count");
+ } else {
+ return Status::OK();
+ }
+}
+
int WriteBatchInternal::Count(const WriteBatch* b) {
return DecodeFixed32(b->rep_.data() + 8);
}
@@ -63,28 +105,29 @@ void WriteBatch::Delete(const Slice& key) {
PutLengthPrefixedSlice(&rep_, key);
}
-Status WriteBatchInternal::InsertInto(const WriteBatch* b,
- MemTable* memtable) {
- const int count = WriteBatchInternal::Count(b);
- int found = 0;
- Iterator it(*b);
- for (; !it.Done(); it.Next()) {
- switch (it.op()) {
- case kTypeDeletion:
- memtable->Add(it.sequence_number(), kTypeDeletion, it.key(), Slice());
- break;
- case kTypeValue:
- memtable->Add(it.sequence_number(), kTypeValue, it.key(), it.value());
- break;
- }
- found++;
+namespace {
+class MemTableInserter : public WriteBatch::Handler {
+ public:
+ SequenceNumber sequence_;
+ MemTable* mem_;
+
+ virtual void Put(const Slice& key, const Slice& value) {
+ mem_->Add(sequence_, kTypeValue, key, value);
+ sequence_++;
}
- if (!it.status().ok()) {
- return it.status();
- } else if (found != count) {
- return Status::Corruption("wrong count in WriteBatch");
+ virtual void Delete(const Slice& key) {
+ mem_->Add(sequence_, kTypeDeletion, key, Slice());
+ sequence_++;
}
- return Status::OK();
+};
+}
+
+Status WriteBatchInternal::InsertInto(const WriteBatch* b,
+ MemTable* memtable) {
+ MemTableInserter inserter;
+ inserter.sequence_ = WriteBatchInternal::Sequence(b);
+ inserter.mem_ = memtable;
+ return b->Iterate(&inserter);
}
void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
@@ -92,57 +135,4 @@ void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
b->rep_.assign(contents.data(), contents.size());
}
-WriteBatchInternal::Iterator::Iterator(const WriteBatch& batch)
- : input_(WriteBatchInternal::Contents(&batch)),
- done_(false) {
- if (input_.size() < 12) {
- done_ = true;
- } else {
- seq_ = WriteBatchInternal::Sequence(&batch),
- input_.remove_prefix(12);
- GetNextEntry();
- }
-}
-
-void WriteBatchInternal::Iterator::Next() {
- assert(!done_);
- seq_++;
- GetNextEntry();
-}
-
-void WriteBatchInternal::Iterator::GetNextEntry() {
- if (input_.empty()) {
- done_ = true;
- return;
- }
- char tag = input_[0];
- input_.remove_prefix(1);
- switch (tag) {
- case kTypeValue:
- if (GetLengthPrefixedSlice(&input_, &key_) &&
- GetLengthPrefixedSlice(&input_, &value_)) {
- op_ = static_cast<ValueType>(tag);
- } else {
- status_ = Status::Corruption("bad WriteBatch Put");
- done_ = true;
- input_.clear();
- }
- break;
- case kTypeDeletion:
- if (GetLengthPrefixedSlice(&input_, &key_)) {
- op_ = kTypeDeletion;
- } else {
- status_ = Status::Corruption("bad WriteBatch Delete");
- done_ = true;
- input_.clear();
- }
- break;
- default:
- status_ = Status::Corruption("unknown WriteBatch tag");
- done_ = true;
- input_.clear();
- break;
- }
-}
-
}