LCOV - code coverage report
Current view: top level - src/leveldb/db - write_batch.cc (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 83.3 % 84 70
Test Date: 2026-02-04 05:05:50 Functions: 84.2 % 19 16
Branches: 48.5 % 33 16

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

Generated by: LCOV version 2.0-1