/Users/deen/code/yugabyte-db/src/yb/util/uint_set.h
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 | | #ifndef YB_UTIL_UINT_SET_H |
14 | | #define YB_UTIL_UINT_SET_H |
15 | | |
16 | | #include <boost/icl/discrete_interval.hpp> |
17 | | #include <boost/icl/interval_set.hpp> |
18 | | #include <google/protobuf/repeated_field.h> |
19 | | |
20 | | #include "yb/gutil/strings/join.h" |
21 | | |
22 | | #include "yb/util/status.h" |
23 | | #include "yb/util/status_format.h" |
24 | | |
25 | | namespace yb { |
26 | | |
27 | | // Tracks the on/off state of a set of unsigned integers. Initially, all integers are in the "off" |
28 | | // state, and ranges of integers can be set to "on". Individual integers can then be tested. This |
29 | | // class currently does not support turning indexes "off". |
30 | | // |
31 | | // This class is designed to support efficient encoding/decoding of state into any valid numeric |
32 | | // google::protobuf::RepeatedField<T>. |
33 | | // |
34 | | // Under the hood, this class tracks the state of integer indexes in both an interval_set to enable |
35 | | // efficient serialization into a numeric RepeatedField. |
36 | | template <class T> |
37 | | class UnsignedIntSet { |
38 | | public: |
39 | 15.4M | UnsignedIntSet() {} _ZN2yb14UnsignedIntSetIjEC2Ev Line | Count | Source | 39 | 15.4M | UnsignedIntSet() {} |
_ZN2yb14UnsignedIntSetItEC2Ev Line | Count | Source | 39 | 10 | UnsignedIntSet() {} |
|
40 | | |
41 | | // Set the indexes of this set in [lo, hi] to "on". It is perfectly valid to call SetRange with |
42 | | // lo = hi. |
43 | 88.0k | CHECKED_STATUS SetRange(T lo, T hi) { |
44 | 88.0k | SCHECK_LE(lo, hi, InvalidArgument, Format("Called SetRange with lo ($0) > hi ($1).", lo, hi)); |
45 | 88.0k | interval_set_ += ElementRange::closed(lo, hi); |
46 | 88.0k | return Status::OK(); |
47 | 88.0k | } |
48 | | |
49 | | // Return true if index at val is "on". |
50 | 173M | bool Test(T val) const { |
51 | 173M | return interval_set_.find(val) != interval_set_.end(); |
52 | 173M | } |
53 | | |
54 | | // Returns true if this set is empty. |
55 | 1.40k | bool IsEmpty() const { |
56 | 1.40k | return interval_set_.empty(); |
57 | 1.40k | } |
58 | | |
59 | | template <class Container> |
60 | 3.04M | static Result<UnsignedIntSet<T>> FromPB(const Container& container) { |
61 | 3.04M | UnsignedIntSet set; |
62 | | |
63 | 3.04M | auto run_length_size = container.size(); |
64 | | |
65 | 3.04M | if (run_length_size == 0) { |
66 | 2.97M | return set; |
67 | 2.97M | } |
68 | | |
69 | 68.6k | if (run_length_size % 2 != 0) { |
70 | 0 | return STATUS( |
71 | 0 | InvalidArgument, |
72 | 0 | Format("Expect even number of run lengths in container, got $0", run_length_size)); |
73 | 0 | } |
74 | | |
75 | 68.6k | uint32_t prev = 0; |
76 | 132k | for (auto run = container.begin(); run != container.end();) { |
77 | 63.7k | auto start = prev += *run++; |
78 | 63.7k | auto finish = (prev += *run++) - 1; |
79 | 63.7k | RETURN_NOT_OK(set.SetRange(start, finish)); |
80 | 63.7k | } |
81 | | |
82 | 68.6k | return set; |
83 | 68.6k | } |
84 | | |
85 | 64.2k | void ToPB(google::protobuf::RepeatedField<T>* mutable_container) const { |
86 | 64.2k | uint32_t last_unset = 0; |
87 | 63.1k | for (const auto& elem : interval_set_) { |
88 | 63.1k | mutable_container->Add(elem.lower() - last_unset); |
89 | 63.1k | mutable_container->Add(elem.upper() - elem.lower() + 1); |
90 | 63.1k | last_unset = elem.upper() + 1; |
91 | 63.1k | } |
92 | 64.2k | } |
93 | | |
94 | 0 | std::string ToString() const { |
95 | 0 | std::vector<std::string> parts; |
96 | 0 | for (const auto& elem : interval_set_) { |
97 | 0 | parts.push_back(Format("[$0, $1]", elem.lower(), elem.upper())); |
98 | 0 | } |
99 | 0 | return JoinStrings(parts, ", "); |
100 | 0 | } |
101 | | |
102 | | private: |
103 | | using ElementType = uint32_t; |
104 | | using ElementRange = boost::icl::discrete_interval<ElementType>; |
105 | | using ElementRangeSet = boost::icl::interval_set<ElementType>; |
106 | | ElementRangeSet interval_set_; |
107 | | }; |
108 | | |
109 | | } // namespace yb |
110 | | |
111 | | #endif // YB_UTIL_UINT_SET_H |