|
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] |
| 1 | +// WriteBatch唯一成员string rep_格式 |
| 2 | +// sequence: 64bit |
| 3 | +// count: 32bit 有多少条记录需要处理 |
| 4 | +// data: recode[count] 具体某条记录 |
| 5 | +// recode := |
| 6 | +// (kTypeValue 为记录类型,更新or删除, |
| 7 | +// 删除时只有key) ) |
| 8 | +// kTypeValue varstring varstring. kTypeValue | |
| 9 | +// kTypeValue varstring(key) |
| 10 | +// varstring := |
| 11 | +// len: varint32 |
| 12 | +// data: uint8[len] |
15 | 13 |
|
16 | 14 | #include "leveldb/write_batch.h"
|
17 | 15 |
|
|
23 | 21 |
|
24 | 22 | namespace leveldb {
|
25 | 23 |
|
26 |
| -// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. |
27 |
| -static const size_t kHeader = 12; |
| 24 | +// sequence(8-byte) and count(4-byte) |
| 25 | +static const size_t kHeader = 12; |
28 | 26 |
|
29 | 27 | WriteBatch::WriteBatch() {
|
30 |
| - Clear(); |
| 28 | + Clear(); |
31 | 29 | }
|
32 | 30 |
|
33 |
| -WriteBatch::~WriteBatch() { } |
| 31 | +WriteBatch::~WriteBatch() {} |
34 | 32 |
|
35 |
| -WriteBatch::Handler::~Handler() { } |
| 33 | +WriteBatch::Handler::~Handler(){} |
36 | 34 |
|
37 | 35 | void WriteBatch::Clear() {
|
38 |
| - rep_.clear(); |
39 |
| - rep_.resize(kHeader); |
| 36 | + rep_.clear(); |
| 37 | + rep_.resize(kHeader); |
40 | 38 | }
|
41 | 39 |
|
42 | 40 | Status WriteBatch::Iterate(Handler* handler) const {
|
43 |
| - Slice input(rep_); |
44 |
| - if (input.size() < kHeader) { |
45 |
| - return Status::Corruption("malformed WriteBatch (too small)"); |
46 |
| - } |
47 |
| - |
48 |
| - input.remove_prefix(kHeader); |
49 |
| - Slice key, value; |
50 |
| - int found = 0; |
51 |
| - while (!input.empty()) { |
52 |
| - found++; |
53 |
| - char tag = input[0]; |
54 |
| - input.remove_prefix(1); |
55 |
| - switch (tag) { |
56 |
| - case kTypeValue: |
57 |
| - if (GetLengthPrefixedSlice(&input, &key) && |
58 |
| - GetLengthPrefixedSlice(&input, &value)) { |
59 |
| - handler->Put(key, value); |
60 |
| - } else { |
61 |
| - return Status::Corruption("bad WriteBatch Put"); |
62 |
| - } |
63 |
| - break; |
64 |
| - case kTypeDeletion: |
65 |
| - if (GetLengthPrefixedSlice(&input, &key)) { |
66 |
| - handler->Delete(key); |
67 |
| - } else { |
68 |
| - return Status::Corruption("bad WriteBatch Delete"); |
| 41 | + Slice input(rep_); |
| 42 | + if (input.size() < kHeader) { |
| 43 | + return Status::Corruption("malformed WriteBatch(too small)"); |
| 44 | + } |
| 45 | + |
| 46 | + // 移除req_ 的seq num和count |
| 47 | + input.remove_prefix(kHeader); |
| 48 | + Slice key, value; |
| 49 | + int found = 0; |
| 50 | + while (!input.empty()) { |
| 51 | + found++; |
| 52 | + char tag = input[0]; |
| 53 | + input.remove_prefix(1); |
| 54 | + switch (tag) { |
| 55 | + case kTypeValue: |
| 56 | + if (GetLengthPrefixedSlice(&input, &key) && //get Key |
| 57 | + GetLengthPrefixedSlice(&input, &value)) { //get value |
| 58 | + handler->Put(key, value); |
| 59 | + } else { |
| 60 | + return Status::Corruption("bad WriteBatch Put"); |
| 61 | + } |
| 62 | + break; |
| 63 | + |
| 64 | + case kTypeDeletion: |
| 65 | + if (GetLengthPrefixedSlice(&input, &key)) { |
| 66 | + handler->Delete(key); |
| 67 | + } else { |
| 68 | + return Status::Corruption("bad WriteBatch Delete"); |
| 69 | + } |
| 70 | + break; |
| 71 | + default: |
| 72 | + return Status::Corruption("unknown WriteBatch tag"); |
69 | 73 | }
|
70 |
| - break; |
71 |
| - default: |
72 |
| - return Status::Corruption("unknown WriteBatch tag"); |
| 74 | + } // while |
| 75 | + |
| 76 | + if (found != WriteBatchInternal::Count(this)) { |
| 77 | + return Status::Corruption("WriteBatch has wrong count"); |
| 78 | + } else { |
| 79 | + return Status::OK(); |
73 | 80 | }
|
74 |
| - } |
75 |
| - if (found != WriteBatchInternal::Count(this)) { |
76 |
| - return Status::Corruption("WriteBatch has wrong count"); |
77 |
| - } else { |
78 |
| - return Status::OK(); |
79 |
| - } |
80 | 81 | }
|
81 | 82 |
|
82 | 83 | int WriteBatchInternal::Count(const WriteBatch* b) {
|
83 |
| - return DecodeFixed32(b->rep_.data() + 8); |
| 84 | + return DecodeFixed32(b->rep_.data() + 8); |
84 | 85 | }
|
85 | 86 |
|
| 87 | +// 设置读取记录数 |
86 | 88 | void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
|
87 |
| - EncodeFixed32(&b->rep_[8], n); |
| 89 | + EncodeFixed32(&b->rep_[8], n); |
88 | 90 | }
|
89 | 91 |
|
90 | 92 | SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
|
91 |
| - return SequenceNumber(DecodeFixed64(b->rep_.data())); |
| 93 | + return SequenceNumber(DecodeFixed64(b->rep_.data())); |
92 | 94 | }
|
93 | 95 |
|
94 | 96 | void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
|
95 | 97 | EncodeFixed64(&b->rep_[0], seq);
|
96 | 98 | }
|
97 | 99 |
|
98 | 100 | 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); |
| 101 | + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); |
| 102 | + rep_.push_back(static_cast<char>(kTypeValue)); |
| 103 | + |
| 104 | + // 将key append到rep_后面 |
| 105 | + PutLengthPrefixedSlice(&rep_, key); |
| 106 | + PutLengthPrefixedSlice(&rep_, value); |
103 | 107 | }
|
104 | 108 |
|
105 | 109 | 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); |
| 110 | + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); |
| 111 | + rep_.push_back(static_cast<char>(kTypeDeletion)); |
| 112 | + PutLengthPrefixedSlice(&rep_, key); |
109 | 113 | }
|
110 | 114 |
|
111 | 115 | namespace {
|
112 | 116 | class MemTableInserter : public WriteBatch::Handler {
|
113 |
| - public: |
114 |
| - SequenceNumber sequence_; |
115 |
| - MemTable* mem_; |
116 |
| - |
117 |
| - virtual void Put(const Slice& key, const Slice& value) { |
118 |
| - mem_->Add(sequence_, kTypeValue, key, value); |
119 |
| - sequence_++; |
120 |
| - } |
121 |
| - virtual void Delete(const Slice& key) { |
122 |
| - mem_->Add(sequence_, kTypeDeletion, key, Slice()); |
123 |
| - sequence_++; |
124 |
| - } |
| 117 | +public: |
| 118 | + SequenceNumber sequence_; |
| 119 | + MemTable* mem_; |
| 120 | + |
| 121 | + virtual void Put(const Slice& key, const Slice& value) { |
| 122 | + mem_->Add(sequence_, kTypeValue, key ,value); |
| 123 | + sequence_++; |
| 124 | + } |
| 125 | + virtual void Delete(const Slice& key) { |
| 126 | + mem_->Add(sequence_, kTypeDeletion, key, Slice()); |
| 127 | + sequence_++; |
| 128 | + } |
125 | 129 | };
|
126 |
| -} // namespace |
| 130 | +} |
127 | 131 |
|
128 | 132 | 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); |
| 133 | + MemTable* memtable) { |
| 134 | + MemTableInserter inserter; |
| 135 | + inserter.sequence_ = WriteBatchInternal::Sequence(b); |
| 136 | + inserter.mem_ = memtable; |
| 137 | + return b->Iterate(&inserter); |
134 | 138 | }
|
135 | 139 |
|
136 | 140 | void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
|
137 |
| - assert(contents.size() >= kHeader); |
138 |
| - b->rep_.assign(contents.data(), contents.size()); |
| 141 | + assert(contents.size() > kHeader); |
| 142 | + b->rep_.assign(contents.data(), contents.size()); |
139 | 143 | }
|
140 | 144 |
|
141 | 145 | 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); |
| 146 | + SetCount(dst, Count(dst) + Count(src)); |
| 147 | + assert(src->rep_.size() > kHeader); |
| 148 | + dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); |
145 | 149 | }
|
146 | 150 |
|
147 |
| -} // namespace leveldb |
| 151 | +} // namespace leveldb |
0 commit comments