YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
29.6M
  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
103k
  CHECKED_STATUS SetRange(T lo, T hi) {
44
103k
    SCHECK_LE(lo, hi, InvalidArgument, Format("Called SetRange with lo ($0) > hi ($1).", lo, hi));
45
103k
    interval_set_ += ElementRange::closed(lo, hi);
46
103k
    return Status::OK();
47
103k
  }
48
49
  // Return true if index at val is "on".
50
212M
  bool Test(T val) const {
51
212M
    return interval_set_.find(val) != interval_set_.end();
52
212M
  }
53
54
  // Returns true if this set is empty.
55
1.71k
  bool IsEmpty() const {
56
1.71k
    return interval_set_.empty();
57
1.71k
  }
58
59
  template <class Container>
60
6.12M
  static Result<UnsignedIntSet<T>> FromPB(const Container& container) {
61
6.12M
    UnsignedIntSet set;
62
63
6.12M
    auto run_length_size = container.size();
64
65
6.12M
    if (run_length_size == 0) {
66
6.09M
      return set;
67
6.09M
    }
68
69
32.4k
    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
32.4k
    uint32_t prev = 0;
76
121k
    for (auto run = container.begin(); run != container.end();) {
77
89.0k
      auto start = prev += *run++;
78
89.0k
      auto finish = (prev += *run++) - 1;
79
89.0k
      RETURN_NOT_OK(set.SetRange(start, finish));
80
89.0k
    }
81
82
32.4k
    return set;
83
32.4k
  }
84
85
55.2k
  void ToPB(google::protobuf::RepeatedField<T>* mutable_container) const {
86
55.2k
    uint32_t last_unset = 0;
87
94.1k
    for (const auto& elem : interval_set_) {
88
94.1k
      mutable_container->Add(elem.lower() - last_unset);
89
94.1k
      mutable_container->Add(elem.upper() - elem.lower() + 1);
90
94.1k
      last_unset = elem.upper() + 1;
91
94.1k
    }
92
55.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