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 : 15128 : WriteBatch::WriteBatch() { Clear(); }
# 30 : :
# 31 : 15128 : WriteBatch::~WriteBatch() = default;
# 32 : :
# 33 : 15270 : WriteBatch::Handler::~Handler() = default;
# 34 : :
# 35 : 15128 : void WriteBatch::Clear() {
# 36 : 15128 : rep_.clear();
# 37 : 15128 : rep_.resize(kHeader);
# 38 : 15128 : }
# 39 : :
# 40 : 0 : size_t WriteBatch::ApproximateSize() const { return rep_.size(); }
# 41 : :
# 42 : 15270 : Status WriteBatch::Iterate(Handler* handler) const {
# 43 : 15270 : Slice input(rep_);
# 44 [ - + ]: 15270 : if (input.size() < kHeader) {
# 45 : 0 : return Status::Corruption("malformed WriteBatch (too small)");
# 46 : 0 : }
# 47 : :
# 48 : 15270 : input.remove_prefix(kHeader);
# 49 : 15270 : Slice key, value;
# 50 : 15270 : int found = 0;
# 51 [ + + ]: 479025 : while (!input.empty()) {
# 52 : 463755 : found++;
# 53 : 463755 : char tag = input[0];
# 54 : 463755 : input.remove_prefix(1);
# 55 : 463755 : switch (tag) {
# 56 [ + + ]: 419579 : case kTypeValue:
# 57 [ + - ]: 419579 : if (GetLengthPrefixedSlice(&input, &key) &&
# 58 [ + - ]: 419579 : GetLengthPrefixedSlice(&input, &value)) {
# 59 : 419579 : handler->Put(key, value);
# 60 : 419579 : } else {
# 61 : 0 : return Status::Corruption("bad WriteBatch Put");
# 62 : 0 : }
# 63 : 419579 : break;
# 64 [ + + ]: 419579 : case kTypeDeletion:
# 65 [ + - ]: 44176 : if (GetLengthPrefixedSlice(&input, &key)) {
# 66 : 44176 : handler->Delete(key);
# 67 : 44176 : } else {
# 68 : 0 : return Status::Corruption("bad WriteBatch Delete");
# 69 : 0 : }
# 70 : 44176 : break;
# 71 [ - + ]: 44176 : default:
# 72 : 0 : return Status::Corruption("unknown WriteBatch tag");
# 73 : 463755 : }
# 74 : 463755 : }
# 75 [ - + ]: 15270 : if (found != WriteBatchInternal::Count(this)) {
# 76 : 0 : return Status::Corruption("WriteBatch has wrong count");
# 77 : 15270 : } else {
# 78 : 15270 : return Status::OK();
# 79 : 15270 : }
# 80 : 15270 : }
# 81 : :
# 82 : 404157 : int WriteBatchInternal::Count(const WriteBatch* b) {
# 83 : 404157 : return DecodeFixed32(b->rep_.data() + 8);
# 84 : 404157 : }
# 85 : :
# 86 : 373617 : void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
# 87 : 373617 : EncodeFixed32(&b->rep_[8], n);
# 88 : 373617 : }
# 89 : :
# 90 : 17815 : SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
# 91 : 17815 : return SequenceNumber(DecodeFixed64(b->rep_.data()));
# 92 : 17815 : }
# 93 : :
# 94 : 12725 : void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
# 95 : 12725 : EncodeFixed64(&b->rep_[0], seq);
# 96 : 12725 : }
# 97 : :
# 98 : 331523 : void WriteBatch::Put(const Slice& key, const Slice& value) {
# 99 : 331523 : WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
# 100 : 331523 : rep_.push_back(static_cast<char>(kTypeValue));
# 101 : 331523 : PutLengthPrefixedSlice(&rep_, key);
# 102 : 331523 : PutLengthPrefixedSlice(&rep_, value);
# 103 : 331523 : }
# 104 : :
# 105 : 42094 : void WriteBatch::Delete(const Slice& key) {
# 106 : 42094 : WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
# 107 : 42094 : rep_.push_back(static_cast<char>(kTypeDeletion));
# 108 : 42094 : PutLengthPrefixedSlice(&rep_, key);
# 109 : 42094 : }
# 110 : :
# 111 : 0 : void WriteBatch::Append(const WriteBatch& source) {
# 112 : 0 : WriteBatchInternal::Append(this, &source);
# 113 : 0 : }
# 114 : :
# 115 : : namespace {
# 116 : : class MemTableInserter : public WriteBatch::Handler {
# 117 : : public:
# 118 : : SequenceNumber sequence_;
# 119 : : MemTable* mem_;
# 120 : :
# 121 : 419579 : void Put(const Slice& key, const Slice& value) override {
# 122 : 419579 : mem_->Add(sequence_, kTypeValue, key, value);
# 123 : 419579 : sequence_++;
# 124 : 419579 : }
# 125 : 44176 : void Delete(const Slice& key) override {
# 126 : 44176 : mem_->Add(sequence_, kTypeDeletion, key, Slice());
# 127 : 44176 : sequence_++;
# 128 : 44176 : }
# 129 : : };
# 130 : : } // namespace
# 131 : :
# 132 : 15270 : Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) {
# 133 : 15270 : MemTableInserter inserter;
# 134 : 15270 : inserter.sequence_ = WriteBatchInternal::Sequence(b);
# 135 : 15270 : inserter.mem_ = memtable;
# 136 : 15270 : return b->Iterate(&inserter);
# 137 : 15270 : }
# 138 : :
# 139 : 2545 : void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
# 140 : 2545 : assert(contents.size() >= kHeader);
# 141 : 2545 : b->rep_.assign(contents.data(), contents.size());
# 142 : 2545 : }
# 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
|