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