LCOV - code coverage report
Current view: top level - src/leveldb/db - write_batch.cc (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 83.3 % 84 70
Test Date: 2026-02-04 04:43:42 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         [ +  - ]:        1948 : WriteBatch::WriteBatch() { Clear(); }
      30                 :             : 
      31                 :        1948 : WriteBatch::~WriteBatch() = default;
      32                 :             : 
      33                 :        1646 : WriteBatch::Handler::~Handler() = default;
      34                 :             : 
      35                 :        3339 : void WriteBatch::Clear() {
      36                 :        3339 :   rep_.clear();
      37                 :        3339 :   rep_.resize(kHeader);
      38                 :        3339 : }
      39                 :             : 
      40         [ -  + ]:       94810 : size_t WriteBatch::ApproximateSize() const { return rep_.size(); }
      41                 :             : 
      42                 :        1646 : Status WriteBatch::Iterate(Handler* handler) const {
      43         [ -  + ]:        1646 :   Slice input(rep_);
      44         [ -  + ]:        1646 :   if (input.size() < kHeader) {
      45                 :           0 :     return Status::Corruption("malformed WriteBatch (too small)");
      46                 :             :   }
      47                 :             : 
      48                 :        1646 :   input.remove_prefix(kHeader);
      49                 :        1646 :   Slice key, value;
      50                 :        1646 :   int found = 0;
      51         [ +  + ]:      103783 :   while (!input.empty()) {
      52                 :      102137 :     found++;
      53                 :      102137 :     char tag = input[0];
      54                 :      102137 :     input.remove_prefix(1);
      55      [ +  +  - ]:      102137 :     switch (tag) {
      56                 :       87364 :       case kTypeValue:
      57   [ +  -  +  - ]:      174728 :         if (GetLengthPrefixedSlice(&input, &key) &&
      58                 :       87364 :             GetLengthPrefixedSlice(&input, &value)) {
      59                 :       87364 :           handler->Put(key, value);
      60                 :             :         } else {
      61                 :           0 :           return Status::Corruption("bad WriteBatch Put");
      62                 :             :         }
      63                 :       87364 :         break;
      64                 :       14773 :       case kTypeDeletion:
      65         [ +  - ]:       14773 :         if (GetLengthPrefixedSlice(&input, &key)) {
      66                 :       14773 :           handler->Delete(key);
      67                 :             :         } else {
      68                 :           0 :           return Status::Corruption("bad WriteBatch Delete");
      69                 :             :         }
      70                 :       14773 :         break;
      71                 :           0 :       default:
      72                 :           0 :         return Status::Corruption("unknown WriteBatch tag");
      73                 :             :     }
      74                 :             :   }
      75         [ -  + ]:        1646 :   if (found != WriteBatchInternal::Count(this)) {
      76                 :           0 :     return Status::Corruption("WriteBatch has wrong count");
      77                 :             :   } else {
      78                 :        1646 :     return Status::OK();
      79                 :             :   }
      80                 :             : }
      81                 :             : 
      82                 :      102391 : int WriteBatchInternal::Count(const WriteBatch* b) {
      83                 :      102391 :   return DecodeFixed32(b->rep_.data() + 8);
      84                 :             : }
      85                 :             : 
      86                 :       99099 : void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
      87                 :       99099 :   EncodeFixed32(&b->rep_[8], n);
      88                 :       99099 : }
      89                 :             : 
      90                 :        1901 : SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
      91                 :        1901 :   return SequenceNumber(DecodeFixed64(b->rep_.data()));
      92                 :             : }
      93                 :             : 
      94                 :        1391 : void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
      95                 :        1391 :   EncodeFixed64(&b->rep_[0], seq);
      96                 :        1391 : }
      97                 :             : 
      98                 :       84460 : void WriteBatch::Put(const Slice& key, const Slice& value) {
      99                 :       84460 :   WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
     100                 :       84460 :   rep_.push_back(static_cast<char>(kTypeValue));
     101                 :       84460 :   PutLengthPrefixedSlice(&rep_, key);
     102                 :       84460 :   PutLengthPrefixedSlice(&rep_, value);
     103                 :       84460 : }
     104                 :             : 
     105                 :       14639 : void WriteBatch::Delete(const Slice& key) {
     106                 :       14639 :   WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
     107                 :       14639 :   rep_.push_back(static_cast<char>(kTypeDeletion));
     108                 :       14639 :   PutLengthPrefixedSlice(&rep_, key);
     109                 :       14639 : }
     110                 :             : 
     111                 :           0 : void WriteBatch::Append(const WriteBatch& source) {
     112                 :           0 :   WriteBatchInternal::Append(this, &source);
     113                 :           0 : }
     114                 :             : 
     115                 :             : namespace {
     116                 :        1646 : class MemTableInserter : public WriteBatch::Handler {
     117                 :             :  public:
     118                 :             :   SequenceNumber sequence_;
     119                 :             :   MemTable* mem_;
     120                 :             : 
     121                 :       87364 :   void Put(const Slice& key, const Slice& value) override {
     122                 :       87364 :     mem_->Add(sequence_, kTypeValue, key, value);
     123                 :       87364 :     sequence_++;
     124                 :       87364 :   }
     125                 :       14773 :   void Delete(const Slice& key) override {
     126                 :       14773 :     mem_->Add(sequence_, kTypeDeletion, key, Slice());
     127                 :       14773 :     sequence_++;
     128                 :       14773 :   }
     129                 :             : };
     130                 :             : }  // namespace
     131                 :             : 
     132                 :        1646 : Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) {
     133         [ +  - ]:        1646 :   MemTableInserter inserter;
     134         [ +  - ]:        1646 :   inserter.sequence_ = WriteBatchInternal::Sequence(b);
     135                 :        1646 :   inserter.mem_ = memtable;
     136         [ +  - ]:        1646 :   return b->Iterate(&inserter);
     137                 :        1646 : }
     138                 :             : 
     139                 :         255 : void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
     140         [ -  + ]:         255 :   assert(contents.size() >= kHeader);
     141                 :         255 :   b->rep_.assign(contents.data(), contents.size());
     142                 :         255 : }
     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