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