xref: /aosp_15_r20/external/leveldb/db/write_batch.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
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