Coverage Report

Created: 2026-08-25 19:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/leveldb/db/write_batch.cc
Line
Count
Source
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
4.36M
WriteBatch::WriteBatch() { Clear(); }
30
31
4.36M
WriteBatch::~WriteBatch() = default;
32
33
4.23M
WriteBatch::Handler::~Handler() = default;
34
35
8.48M
void WriteBatch::Clear() {
36
8.48M
  rep_.clear();
37
8.48M
  rep_.resize(kHeader);
38
8.48M
}
39
40
513k
size_t WriteBatch::ApproximateSize() const { return rep_.size(); }
41
42
4.23M
Status WriteBatch::Iterate(Handler* handler) const {
43
4.23M
  Slice input(rep_);
44
4.23M
  if (input.size() < kHeader) {
  Branch (44:7): [True: 0, False: 4.23M]
45
0
    return Status::Corruption("malformed WriteBatch (too small)");
46
0
  }
47
48
4.23M
  input.remove_prefix(kHeader);
49
4.23M
  Slice key, value;
50
4.23M
  int found = 0;
51
24.5M
  while (!input.empty()) {
  Branch (51:10): [True: 20.2M, False: 4.23M]
52
20.2M
    found++;
53
20.2M
    char tag = input[0];
54
20.2M
    input.remove_prefix(1);
55
20.2M
    switch (tag) {
56
12.5M
      case kTypeValue:
  Branch (56:7): [True: 12.5M, False: 7.77M]
57
12.5M
        if (GetLengthPrefixedSlice(&input, &key) &&
  Branch (57:13): [True: 12.5M, False: 0]
58
12.5M
            GetLengthPrefixedSlice(&input, &value)) {
  Branch (58:13): [True: 12.5M, False: 0]
59
12.5M
          handler->Put(key, value);
60
12.5M
        } else {
61
0
          return Status::Corruption("bad WriteBatch Put");
62
0
        }
63
12.5M
        break;
64
12.5M
      case kTypeDeletion:
  Branch (64:7): [True: 7.77M, False: 12.5M]
65
7.77M
        if (GetLengthPrefixedSlice(&input, &key)) {
  Branch (65:13): [True: 7.77M, False: 0]
66
7.77M
          handler->Delete(key);
67
7.77M
        } else {
68
0
          return Status::Corruption("bad WriteBatch Delete");
69
0
        }
70
7.77M
        break;
71
7.77M
      default:
  Branch (71:7): [True: 0, False: 20.2M]
72
0
        return Status::Corruption("unknown WriteBatch tag");
73
20.2M
    }
74
20.2M
  }
75
4.23M
  if (found != WriteBatchInternal::Count(this)) {
  Branch (75:7): [True: 0, False: 4.23M]
76
0
    return Status::Corruption("WriteBatch has wrong count");
77
4.23M
  } else {
78
4.23M
    return Status::OK();
79
4.23M
  }
80
4.23M
}
81
82
28.6M
int WriteBatchInternal::Count(const WriteBatch* b) {
83
28.6M
  return DecodeFixed32(b->rep_.data() + 8);
84
28.6M
}
85
86
20.2M
void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
87
20.2M
  EncodeFixed32(&b->rep_[8], n);
88
20.2M
}
89
90
4.36M
SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
91
4.36M
  return SequenceNumber(DecodeFixed64(b->rep_.data()));
92
4.36M
}
93
94
4.10M
void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
95
4.10M
  EncodeFixed64(&b->rep_[0], seq);
96
4.10M
}
97
98
12.5M
void WriteBatch::Put(const Slice& key, const Slice& value) {
99
12.5M
  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
100
12.5M
  rep_.push_back(static_cast<char>(kTypeValue));
101
12.5M
  PutLengthPrefixedSlice(&rep_, key);
102
12.5M
  PutLengthPrefixedSlice(&rep_, value);
103
12.5M
}
104
105
7.70M
void WriteBatch::Delete(const Slice& key) {
106
7.70M
  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
107
7.70M
  rep_.push_back(static_cast<char>(kTypeDeletion));
108
7.70M
  PutLengthPrefixedSlice(&rep_, key);
109
7.70M
}
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
12.5M
  void Put(const Slice& key, const Slice& value) override {
122
12.5M
    mem_->Add(sequence_, kTypeValue, key, value);
123
12.5M
    sequence_++;
124
12.5M
  }
125
7.77M
  void Delete(const Slice& key) override {
126
7.77M
    mem_->Add(sequence_, kTypeDeletion, key, Slice());
127
7.77M
    sequence_++;
128
7.77M
  }
129
};
130
}  // namespace
131
132
4.23M
Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) {
133
4.23M
  MemTableInserter inserter;
134
4.23M
  inserter.sequence_ = WriteBatchInternal::Sequence(b);
135
4.23M
  inserter.mem_ = memtable;
136
4.23M
  return b->Iterate(&inserter);
137
4.23M
}
138
139
126k
void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
140
126k
  assert(contents.size() >= kHeader);
  Branch (140:3): [True: 126k, False: 0]
141
126k
  b->rep_.assign(contents.data(), contents.size());
142
126k
}
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);
  Branch (146:3): [True: 0, False: 0]
147
0
  dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
148
0
}
149
150
}  // namespace leveldb