/Users/deen/code/yugabyte-db/src/yb/docdb/consensus_frontier.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include "yb/docdb/consensus_frontier.h" |
15 | | |
16 | | #include <google/protobuf/any.pb.h> |
17 | | |
18 | | #include "yb/docdb/docdb.pb.h" |
19 | | #include "yb/gutil/casts.h" |
20 | | #include "yb/util/tostring.h" |
21 | | |
22 | | namespace yb { |
23 | | namespace docdb { |
24 | | |
25 | 35.4M | ConsensusFrontier::~ConsensusFrontier() { |
26 | 35.4M | } |
27 | | |
28 | 21 | bool ConsensusFrontier::Equals(const UserFrontier& pre_rhs) const { |
29 | 21 | const ConsensusFrontier& rhs = down_cast<const ConsensusFrontier&>(pre_rhs); |
30 | 21 | return op_id_ == rhs.op_id_ && |
31 | 21 | hybrid_time_ == rhs.hybrid_time_17 && |
32 | 21 | history_cutoff_ == rhs.history_cutoff_13 && |
33 | 21 | hybrid_time_filter_ == rhs.hybrid_time_filter_11 && |
34 | 21 | max_value_level_ttl_expiration_time_ == rhs.max_value_level_ttl_expiration_time_11 ; |
35 | 21 | } |
36 | | |
37 | 336k | void ConsensusFrontier::ToPB(google::protobuf::Any* any) const { |
38 | 336k | ConsensusFrontierPB pb; |
39 | 336k | op_id_.ToPB(pb.mutable_op_id()); |
40 | 336k | pb.set_hybrid_time(hybrid_time_.ToUint64()); |
41 | 336k | pb.set_history_cutoff(history_cutoff_.ToUint64()); |
42 | 336k | if (hybrid_time_filter_.is_valid()) { |
43 | 24 | pb.set_hybrid_time_filter(hybrid_time_filter_.ToUint64()); |
44 | 24 | } |
45 | 336k | pb.set_max_value_level_ttl_expiration_time(max_value_level_ttl_expiration_time_.ToUint64()); |
46 | 336k | any->PackFrom(pb); |
47 | 336k | } |
48 | | |
49 | 34.2k | void ConsensusFrontier::FromPB(const google::protobuf::Any& any) { |
50 | 34.2k | ConsensusFrontierPB pb; |
51 | 34.2k | any.UnpackTo(&pb); |
52 | 34.2k | op_id_ = OpId::FromPB(pb.op_id()); |
53 | 34.2k | hybrid_time_ = HybridTime(pb.hybrid_time()); |
54 | 34.2k | history_cutoff_ = NormalizeHistoryCutoff(HybridTime(pb.history_cutoff())); |
55 | 34.2k | if (pb.has_hybrid_time_filter()) { |
56 | 17 | hybrid_time_filter_ = HybridTime(pb.hybrid_time_filter()); |
57 | 34.2k | } else { |
58 | 34.2k | hybrid_time_filter_ = HybridTime(); |
59 | 34.2k | } |
60 | 34.2k | max_value_level_ttl_expiration_time_ = |
61 | 34.2k | HybridTime::FromPB(pb.max_value_level_ttl_expiration_time()); |
62 | 34.2k | } |
63 | | |
64 | 0 | void ConsensusFrontier::FromOpIdPBDeprecated(const OpIdPB& pb) { |
65 | 0 | op_id_ = OpId::FromPB(pb); |
66 | 0 | } |
67 | | |
68 | 15.5k | std::string ConsensusFrontier::ToString() const { |
69 | 15.5k | return YB_CLASS_TO_STRING( |
70 | 15.5k | op_id, hybrid_time, history_cutoff, hybrid_time_filter, max_value_level_ttl_expiration_time); |
71 | 15.5k | } |
72 | | |
73 | | namespace { |
74 | | |
75 | | // Check if the given updated value is a correct "update" for the given previous value in the |
76 | | // specified direction. If one of the two values is not defined according to the bool conversion, |
77 | | // then there is no error. |
78 | | template<typename T> |
79 | | bool IsUpdateValidForField( |
80 | 19.1k | const T& this_value, const T& updated_value, rocksdb::UpdateUserValueType update_type) { |
81 | 19.1k | if (!this_value || !updated_value15.3k ) { |
82 | | // If any of the two values is undefined, we don't treat this as an error. |
83 | 3.85k | return true; |
84 | 3.85k | } |
85 | 15.3k | switch (update_type) { |
86 | 15.3k | case rocksdb::UpdateUserValueType::kLargest: |
87 | 15.3k | return updated_value >= this_value; |
88 | 12 | case rocksdb::UpdateUserValueType::kSmallest: |
89 | 12 | return updated_value <= this_value; |
90 | 15.3k | } |
91 | 0 | FATAL_INVALID_ENUM_VALUE(rocksdb::UpdateUserValueType, update_type); |
92 | 0 | } consensus_frontier.cc:bool yb::docdb::(anonymous namespace)::IsUpdateValidForField<yb::OpId>(yb::OpId const&, yb::OpId const&, rocksdb::UpdateUserValueType) Line | Count | Source | 80 | 9.59k | const T& this_value, const T& updated_value, rocksdb::UpdateUserValueType update_type) { | 81 | 9.59k | if (!this_value || !updated_value7.67k ) { | 82 | | // If any of the two values is undefined, we don't treat this as an error. | 83 | 1.92k | return true; | 84 | 1.92k | } | 85 | 7.66k | switch (update_type) { | 86 | 7.66k | case rocksdb::UpdateUserValueType::kLargest: | 87 | 7.66k | return updated_value >= this_value; | 88 | 7 | case rocksdb::UpdateUserValueType::kSmallest: | 89 | 7 | return updated_value <= this_value; | 90 | 7.66k | } | 91 | 0 | FATAL_INVALID_ENUM_VALUE(rocksdb::UpdateUserValueType, update_type); | 92 | 0 | } |
consensus_frontier.cc:bool yb::docdb::(anonymous namespace)::IsUpdateValidForField<yb::HybridTime>(yb::HybridTime const&, yb::HybridTime const&, rocksdb::UpdateUserValueType) Line | Count | Source | 80 | 9.58k | const T& this_value, const T& updated_value, rocksdb::UpdateUserValueType update_type) { | 81 | 9.58k | if (!this_value || !updated_value7.66k ) { | 82 | | // If any of the two values is undefined, we don't treat this as an error. | 83 | 1.92k | return true; | 84 | 1.92k | } | 85 | 7.66k | switch (update_type) { | 86 | 7.65k | case rocksdb::UpdateUserValueType::kLargest: | 87 | 7.65k | return updated_value >= this_value; | 88 | 5 | case rocksdb::UpdateUserValueType::kSmallest: | 89 | 5 | return updated_value <= this_value; | 90 | 7.66k | } | 91 | 0 | FATAL_INVALID_ENUM_VALUE(rocksdb::UpdateUserValueType, update_type); | 92 | 0 | } |
|
93 | | |
94 | | template<typename T> |
95 | | void UpdateField( |
96 | 92.4M | T* this_value, const T& new_value, rocksdb::UpdateUserValueType update_type) { |
97 | 92.4M | switch (update_type) { |
98 | 46.2M | case rocksdb::UpdateUserValueType::kLargest: |
99 | 46.2M | this_value->MakeAtLeast(new_value); |
100 | 46.2M | return; |
101 | 46.1M | case rocksdb::UpdateUserValueType::kSmallest: |
102 | 46.1M | this_value->MakeAtMost(new_value); |
103 | 46.1M | return; |
104 | 92.4M | } |
105 | 0 | FATAL_INVALID_ENUM_VALUE(rocksdb::UpdateUserValueType, update_type); |
106 | 0 | } consensus_frontier.cc:void yb::docdb::(anonymous namespace)::UpdateField<yb::OpId>(yb::OpId*, yb::OpId const&, rocksdb::UpdateUserValueType) Line | Count | Source | 96 | 23.1M | T* this_value, const T& new_value, rocksdb::UpdateUserValueType update_type) { | 97 | 23.1M | switch (update_type) { | 98 | 11.5M | case rocksdb::UpdateUserValueType::kLargest: | 99 | 11.5M | this_value->MakeAtLeast(new_value); | 100 | 11.5M | return; | 101 | 11.5M | case rocksdb::UpdateUserValueType::kSmallest: | 102 | 11.5M | this_value->MakeAtMost(new_value); | 103 | 11.5M | return; | 104 | 23.1M | } | 105 | 0 | FATAL_INVALID_ENUM_VALUE(rocksdb::UpdateUserValueType, update_type); | 106 | 0 | } |
consensus_frontier.cc:void yb::docdb::(anonymous namespace)::UpdateField<yb::HybridTime>(yb::HybridTime*, yb::HybridTime const&, rocksdb::UpdateUserValueType) Line | Count | Source | 96 | 69.2M | T* this_value, const T& new_value, rocksdb::UpdateUserValueType update_type) { | 97 | 69.2M | switch (update_type) { | 98 | 34.6M | case rocksdb::UpdateUserValueType::kLargest: | 99 | 34.6M | this_value->MakeAtLeast(new_value); | 100 | 34.6M | return; | 101 | 34.6M | case rocksdb::UpdateUserValueType::kSmallest: | 102 | 34.6M | this_value->MakeAtMost(new_value); | 103 | 34.6M | return; | 104 | 69.2M | } | 105 | 0 | FATAL_INVALID_ENUM_VALUE(rocksdb::UpdateUserValueType, update_type); | 106 | 0 | } |
|
107 | | |
108 | | } // anonymous namespace |
109 | | |
110 | | void ConsensusFrontier::Update( |
111 | 23.1M | const rocksdb::UserFrontier& pre_rhs, rocksdb::UpdateUserValueType update_type) { |
112 | 23.1M | const ConsensusFrontier& rhs = down_cast<const ConsensusFrontier&>(pre_rhs); |
113 | 23.1M | UpdateField(&op_id_, rhs.op_id_, update_type); |
114 | 23.1M | UpdateField(&hybrid_time_, rhs.hybrid_time_, update_type); |
115 | 23.1M | UpdateField(&history_cutoff_, rhs.history_cutoff_, update_type); |
116 | | // Reset filter after compaction. |
117 | 23.1M | hybrid_time_filter_ = HybridTime(); |
118 | 23.1M | UpdateField(&max_value_level_ttl_expiration_time_, |
119 | 23.1M | rhs.max_value_level_ttl_expiration_time_, update_type); |
120 | 23.1M | } |
121 | | |
122 | 12.5M | Slice ConsensusFrontier::Filter() const { |
123 | 12.5M | return hybrid_time_filter_.is_valid() |
124 | 12.5M | ? Slice(pointer_cast<const char*>(&hybrid_time_filter_), sizeof(hybrid_time_filter_))80 |
125 | 12.5M | : Slice()12.5M ; |
126 | 12.5M | } |
127 | | |
128 | | bool ConsensusFrontier::IsUpdateValid( |
129 | 9.59k | const rocksdb::UserFrontier& pre_rhs, rocksdb::UpdateUserValueType update_type) const { |
130 | 9.59k | const ConsensusFrontier& rhs = down_cast<const ConsensusFrontier&>(pre_rhs); |
131 | | |
132 | | // We don't check history cutoff here, because it is not an error when the the history cutoff |
133 | | // for a later compaction is lower than that for an earlier compaction. This can happen if |
134 | | // FLAGS_timestamp_history_retention_interval_sec increases. |
135 | 9.59k | return IsUpdateValidForField(op_id_, rhs.op_id_, update_type) && |
136 | 9.59k | IsUpdateValidForField(hybrid_time_, rhs.hybrid_time_, update_type)9.58k ; |
137 | 9.59k | } |
138 | | |
139 | | } // namespace docdb |
140 | | } // namespace yb |