Coverage Report

Created: 2026-04-10 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/db/blob/blob_file_addition.cc
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under both the GPLv2 (found in the
3
//  COPYING file in the root directory) and Apache 2.0 License
4
//  (found in the LICENSE.Apache file in the root directory).
5
6
#include "db/blob/blob_file_addition.h"
7
8
#include <ostream>
9
#include <sstream>
10
11
#include "logging/event_logger.h"
12
#include "rocksdb/slice.h"
13
#include "rocksdb/status.h"
14
#include "test_util/sync_point.h"
15
#include "util/coding.h"
16
17
namespace ROCKSDB_NAMESPACE {
18
19
// Tags for custom fields. Note that these get persisted in the manifest,
20
// so existing tags should not be modified.
21
enum BlobFileAddition::CustomFieldTags : uint32_t {
22
  kEndMarker,
23
24
  // Add forward compatible fields here
25
26
  /////////////////////////////////////////////////////////////////////
27
28
  kForwardIncompatibleMask = 1 << 6,
29
30
  // Add forward incompatible fields here
31
};
32
33
0
void BlobFileAddition::EncodeTo(std::string* output) const {
34
0
  PutVarint64(output, blob_file_number_);
35
0
  PutVarint64(output, total_blob_count_);
36
0
  PutVarint64(output, total_blob_bytes_);
37
0
  PutLengthPrefixedSlice(output, checksum_method_);
38
0
  PutLengthPrefixedSlice(output, checksum_value_);
39
40
  // Encode any custom fields here. The format to use is a Varint32 tag (see
41
  // CustomFieldTags above) followed by a length prefixed slice. Unknown custom
42
  // fields will be ignored during decoding unless they're in the forward
43
  // incompatible range.
44
45
0
  TEST_SYNC_POINT_CALLBACK("BlobFileAddition::EncodeTo::CustomFields", output);
46
47
0
  PutVarint32(output, kEndMarker);
48
0
}
49
50
0
Status BlobFileAddition::DecodeFrom(Slice* input) {
51
0
  constexpr char class_name[] = "BlobFileAddition";
52
53
0
  if (!GetVarint64(input, &blob_file_number_)) {
54
0
    return Status::Corruption(class_name, "Error decoding blob file number");
55
0
  }
56
57
0
  if (!GetVarint64(input, &total_blob_count_)) {
58
0
    return Status::Corruption(class_name, "Error decoding total blob count");
59
0
  }
60
61
0
  if (!GetVarint64(input, &total_blob_bytes_)) {
62
0
    return Status::Corruption(class_name, "Error decoding total blob bytes");
63
0
  }
64
65
0
  Slice checksum_method;
66
0
  if (!GetLengthPrefixedSlice(input, &checksum_method)) {
67
0
    return Status::Corruption(class_name, "Error decoding checksum method");
68
0
  }
69
0
  checksum_method_ = checksum_method.ToString();
70
71
0
  Slice checksum_value;
72
0
  if (!GetLengthPrefixedSlice(input, &checksum_value)) {
73
0
    return Status::Corruption(class_name, "Error decoding checksum value");
74
0
  }
75
0
  checksum_value_ = checksum_value.ToString();
76
77
0
  while (true) {
78
0
    uint32_t custom_field_tag = 0;
79
0
    if (!GetVarint32(input, &custom_field_tag)) {
80
0
      return Status::Corruption(class_name, "Error decoding custom field tag");
81
0
    }
82
83
0
    if (custom_field_tag == kEndMarker) {
84
0
      break;
85
0
    }
86
87
0
    if (custom_field_tag & kForwardIncompatibleMask) {
88
0
      return Status::Corruption(
89
0
          class_name, "Forward incompatible custom field encountered");
90
0
    }
91
92
0
    Slice custom_field_value;
93
0
    if (!GetLengthPrefixedSlice(input, &custom_field_value)) {
94
0
      return Status::Corruption(class_name,
95
0
                                "Error decoding custom field value");
96
0
    }
97
0
  }
98
99
0
  return Status::OK();
100
0
}
101
102
0
std::string BlobFileAddition::DebugString() const {
103
0
  std::ostringstream oss;
104
105
0
  oss << *this;
106
107
0
  return oss.str();
108
0
}
109
110
0
std::string BlobFileAddition::DebugJSON() const {
111
0
  JSONWriter jw;
112
113
0
  jw << *this;
114
115
0
  jw.EndObject();
116
117
0
  return jw.Get();
118
0
}
119
120
0
bool operator==(const BlobFileAddition& lhs, const BlobFileAddition& rhs) {
121
0
  return lhs.GetBlobFileNumber() == rhs.GetBlobFileNumber() &&
122
0
         lhs.GetTotalBlobCount() == rhs.GetTotalBlobCount() &&
123
0
         lhs.GetTotalBlobBytes() == rhs.GetTotalBlobBytes() &&
124
0
         lhs.GetChecksumMethod() == rhs.GetChecksumMethod() &&
125
0
         lhs.GetChecksumValue() == rhs.GetChecksumValue();
126
0
}
127
128
0
bool operator!=(const BlobFileAddition& lhs, const BlobFileAddition& rhs) {
129
0
  return !(lhs == rhs);
130
0
}
131
132
std::ostream& operator<<(std::ostream& os,
133
0
                         const BlobFileAddition& blob_file_addition) {
134
0
  os << "blob_file_number: " << blob_file_addition.GetBlobFileNumber()
135
0
     << " total_blob_count: " << blob_file_addition.GetTotalBlobCount()
136
0
     << " total_blob_bytes: " << blob_file_addition.GetTotalBlobBytes()
137
0
     << " checksum_method: " << blob_file_addition.GetChecksumMethod()
138
0
     << " checksum_value: "
139
0
     << Slice(blob_file_addition.GetChecksumValue()).ToString(/* hex */ true);
140
141
0
  return os;
142
0
}
143
144
JSONWriter& operator<<(JSONWriter& jw,
145
0
                       const BlobFileAddition& blob_file_addition) {
146
0
  jw << "BlobFileNumber" << blob_file_addition.GetBlobFileNumber()
147
0
     << "TotalBlobCount" << blob_file_addition.GetTotalBlobCount()
148
0
     << "TotalBlobBytes" << blob_file_addition.GetTotalBlobBytes()
149
0
     << "ChecksumMethod" << blob_file_addition.GetChecksumMethod()
150
0
     << "ChecksumValue"
151
0
     << Slice(blob_file_addition.GetChecksumValue()).ToString(/* hex */ true);
152
153
0
  return jw;
154
0
}
155
156
}  // namespace ROCKSDB_NAMESPACE