1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
10 // kTypeValue varstring varstring |
11 // kTypeDeletion varstring
16 #include "leveldb/write_batch.h"
18 #include "leveldb/db.h"
19 #include "db/dbformat.h"
20 #include "db/memtable.h"
21 #include "db/write_batch_internal.h"
22 #include "util/coding.h"
26 // WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
27 static const size_t kHeader = 12;
29 WriteBatch::WriteBatch() {
33 WriteBatch::~WriteBatch() { }
35 WriteBatch::Handler::~Handler() { }
37 void WriteBatch::Clear() {
42 Status WriteBatch::Iterate(Handler* handler) const {
44 if (input.size() < kHeader) {
45 return Status::Corruption("malformed WriteBatch (too small)");
48 input.remove_prefix(kHeader);
51 while (!input.empty()) {
54 input.remove_prefix(1);
57 if (GetLengthPrefixedSlice(&input, &key) &&
58 GetLengthPrefixedSlice(&input, &value)) {
59 handler->Put(key, value);
61 return Status::Corruption("bad WriteBatch Put");
65 if (GetLengthPrefixedSlice(&input, &key)) {
68 return Status::Corruption("bad WriteBatch Delete");
72 return Status::Corruption("unknown WriteBatch tag");
75 if (found != WriteBatchInternal::Count(this)) {
76 return Status::Corruption("WriteBatch has wrong count");
82 int WriteBatchInternal::Count(const WriteBatch* b) {
83 return DecodeFixed32(b->rep_.data() + 8);
86 void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
87 EncodeFixed32(&b->rep_[8], n);
90 SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
91 return SequenceNumber(DecodeFixed64(b->rep_.data()));
94 void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
95 EncodeFixed64(&b->rep_[0], seq);
98 void WriteBatch::Put(const Slice& key, const Slice& value) {
99 WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
100 rep_.push_back(static_cast<char>(kTypeValue));
101 PutLengthPrefixedSlice(&rep_, key);
102 PutLengthPrefixedSlice(&rep_, value);
105 void WriteBatch::Delete(const Slice& key) {
106 WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
107 rep_.push_back(static_cast<char>(kTypeDeletion));
108 PutLengthPrefixedSlice(&rep_, key);
112 class MemTableInserter : public WriteBatch::Handler {
114 SequenceNumber sequence_;
117 virtual void Put(const Slice& key, const Slice& value) {
118 mem_->Add(sequence_, kTypeValue, key, value);
121 virtual void Delete(const Slice& key) {
122 mem_->Add(sequence_, kTypeDeletion, key, Slice());
128 Status WriteBatchInternal::InsertInto(const WriteBatch* b,
129 MemTable* memtable) {
130 MemTableInserter inserter;
131 inserter.sequence_ = WriteBatchInternal::Sequence(b);
132 inserter.mem_ = memtable;
133 return b->Iterate(&inserter);
136 void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
137 assert(contents.size() >= kHeader);
138 b->rep_.assign(contents.data(), contents.size());
141 void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
142 SetCount(dst, Count(dst) + Count(src));
143 assert(src->rep_.size() >= kHeader);
144 dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
147 } // namespace leveldb