Branch data Line data Source code
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.
4 : : //
5 : : // WriteBatch::rep_ :=
6 : : // sequence: fixed64
7 : : // count: fixed32
8 : : // data: record[count]
9 : : // record :=
10 : : // kTypeValue varstring varstring |
11 : : // kTypeDeletion varstring
12 : : // varstring :=
13 : : // len: varint32
14 : : // data: uint8[len]
15 : :
16 : : #include "leveldb/write_batch.h"
17 : :
18 : : #include "db/dbformat.h"
19 : : #include "db/memtable.h"
20 : : #include "db/write_batch_internal.h"
21 : : #include "leveldb/db.h"
22 : : #include "util/coding.h"
23 : :
24 : : namespace leveldb {
25 : :
26 : : // WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
27 : : static const size_t kHeader = 12;
28 : :
29 [ + - ]: 1948 : WriteBatch::WriteBatch() { Clear(); }
30 : :
31 : 1948 : WriteBatch::~WriteBatch() = default;
32 : :
33 : 1646 : WriteBatch::Handler::~Handler() = default;
34 : :
35 : 3339 : void WriteBatch::Clear() {
36 : 3339 : rep_.clear();
37 : 3339 : rep_.resize(kHeader);
38 : 3339 : }
39 : :
40 [ - + ]: 94810 : size_t WriteBatch::ApproximateSize() const { return rep_.size(); }
41 : :
42 : 1646 : Status WriteBatch::Iterate(Handler* handler) const {
43 [ - + ]: 1646 : Slice input(rep_);
44 [ - + ]: 1646 : if (input.size() < kHeader) {
45 : 0 : return Status::Corruption("malformed WriteBatch (too small)");
46 : : }
47 : :
48 : 1646 : input.remove_prefix(kHeader);
49 : 1646 : Slice key, value;
50 : 1646 : int found = 0;
51 [ + + ]: 103783 : while (!input.empty()) {
52 : 102137 : found++;
53 : 102137 : char tag = input[0];
54 : 102137 : input.remove_prefix(1);
55 [ + + - ]: 102137 : switch (tag) {
56 : 87364 : case kTypeValue:
57 [ + - + - ]: 174728 : if (GetLengthPrefixedSlice(&input, &key) &&
58 : 87364 : GetLengthPrefixedSlice(&input, &value)) {
59 : 87364 : handler->Put(key, value);
60 : : } else {
61 : 0 : return Status::Corruption("bad WriteBatch Put");
62 : : }
63 : 87364 : break;
64 : 14773 : case kTypeDeletion:
65 [ + - ]: 14773 : if (GetLengthPrefixedSlice(&input, &key)) {
66 : 14773 : handler->Delete(key);
67 : : } else {
68 : 0 : return Status::Corruption("bad WriteBatch Delete");
69 : : }
70 : 14773 : break;
71 : 0 : default:
72 : 0 : return Status::Corruption("unknown WriteBatch tag");
73 : : }
74 : : }
75 [ - + ]: 1646 : if (found != WriteBatchInternal::Count(this)) {
76 : 0 : return Status::Corruption("WriteBatch has wrong count");
77 : : } else {
78 : 1646 : return Status::OK();
79 : : }
80 : : }
81 : :
82 : 102391 : int WriteBatchInternal::Count(const WriteBatch* b) {
83 : 102391 : return DecodeFixed32(b->rep_.data() + 8);
84 : : }
85 : :
86 : 99099 : void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
87 : 99099 : EncodeFixed32(&b->rep_[8], n);
88 : 99099 : }
89 : :
90 : 1901 : SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
91 : 1901 : return SequenceNumber(DecodeFixed64(b->rep_.data()));
92 : : }
93 : :
94 : 1391 : void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
95 : 1391 : EncodeFixed64(&b->rep_[0], seq);
96 : 1391 : }
97 : :
98 : 84460 : void WriteBatch::Put(const Slice& key, const Slice& value) {
99 : 84460 : WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
100 : 84460 : rep_.push_back(static_cast<char>(kTypeValue));
101 : 84460 : PutLengthPrefixedSlice(&rep_, key);
102 : 84460 : PutLengthPrefixedSlice(&rep_, value);
103 : 84460 : }
104 : :
105 : 14639 : void WriteBatch::Delete(const Slice& key) {
106 : 14639 : WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
107 : 14639 : rep_.push_back(static_cast<char>(kTypeDeletion));
108 : 14639 : PutLengthPrefixedSlice(&rep_, key);
109 : 14639 : }
110 : :
111 : 0 : void WriteBatch::Append(const WriteBatch& source) {
112 : 0 : WriteBatchInternal::Append(this, &source);
113 : 0 : }
114 : :
115 : : namespace {
116 : 1646 : class MemTableInserter : public WriteBatch::Handler {
117 : : public:
118 : : SequenceNumber sequence_;
119 : : MemTable* mem_;
120 : :
121 : 87364 : void Put(const Slice& key, const Slice& value) override {
122 : 87364 : mem_->Add(sequence_, kTypeValue, key, value);
123 : 87364 : sequence_++;
124 : 87364 : }
125 : 14773 : void Delete(const Slice& key) override {
126 : 14773 : mem_->Add(sequence_, kTypeDeletion, key, Slice());
127 : 14773 : sequence_++;
128 : 14773 : }
129 : : };
130 : : } // namespace
131 : :
132 : 1646 : Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) {
133 [ + - ]: 1646 : MemTableInserter inserter;
134 [ + - ]: 1646 : inserter.sequence_ = WriteBatchInternal::Sequence(b);
135 : 1646 : inserter.mem_ = memtable;
136 [ + - ]: 1646 : return b->Iterate(&inserter);
137 : 1646 : }
138 : :
139 : 255 : void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
140 [ - + ]: 255 : assert(contents.size() >= kHeader);
141 : 255 : b->rep_.assign(contents.data(), contents.size());
142 : 255 : }
143 : :
144 : 0 : void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
145 : 0 : SetCount(dst, Count(dst) + Count(src));
146 [ # # # # ]: 0 : assert(src->rep_.size() >= kHeader);
147 : 0 : dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
148 : 0 : }
149 : :
150 : : } // namespace leveldb
|