YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/backoff_waiter.h
Line
Count
Source
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
#ifndef YB_UTIL_BACKOFF_WAITER_H
15
#define YB_UTIL_BACKOFF_WAITER_H
16
17
#include <chrono>
18
#include <thread>
19
20
#include "yb/util/monotime.h"
21
#include "yb/util/random_util.h"
22
23
namespace yb {
24
25
// Utility class for waiting.
26
// It tracks number of attempts and exponentially increase sleep timeout.
27
template <class Clock>
28
class GenericBackoffWaiter {
29
 public:
30
  typedef typename Clock::time_point TimePoint;
31
  typedef typename Clock::duration Duration;
32
33
  // deadline - time when waiter decides that it is expired.
34
  // max_wait - max duration for single wait.
35
  // base_delay - multiplier for wait duration.
36
  explicit GenericBackoffWaiter(
37
      TimePoint deadline, Duration max_wait = Duration::max(),
38
      Duration base_delay = std::chrono::milliseconds(1))
39
170k
      : deadline_(deadline), max_wait_(max_wait), base_delay_(base_delay) {}
yb::GenericBackoffWaiter<std::__1::chrono::steady_clock>::GenericBackoffWaiter(std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >)
Line
Count
Source
39
65.4k
      : deadline_(deadline), max_wait_(max_wait), base_delay_(base_delay) {}
yb::GenericBackoffWaiter<yb::CoarseMonoClock>::GenericBackoffWaiter(std::__1::chrono::time_point<yb::CoarseMonoClock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> >)
Line
Count
Source
39
105k
      : deadline_(deadline), max_wait_(max_wait), base_delay_(base_delay) {}
40
41
22.6k
  bool ExpiredNow() const {
42
22.6k
    return ExpiredAt(Clock::now());
43
22.6k
  }
44
45
86.5k
  bool ExpiredAt(TimePoint time) const {
46
86.5k
    return deadline_ < time + ClockResolution<Clock>();
47
86.5k
  }
yb::GenericBackoffWaiter<std::__1::chrono::steady_clock>::ExpiredAt(std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >) const
Line
Count
Source
45
20.7k
  bool ExpiredAt(TimePoint time) const {
46
20.7k
    return deadline_ < time + ClockResolution<Clock>();
47
20.7k
  }
yb::GenericBackoffWaiter<yb::CoarseMonoClock>::ExpiredAt(std::__1::chrono::time_point<yb::CoarseMonoClock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >) const
Line
Count
Source
45
65.7k
  bool ExpiredAt(TimePoint time) const {
46
65.7k
    return deadline_ < time + ClockResolution<Clock>();
47
65.7k
  }
48
49
63.8k
  bool Wait() {
50
63.8k
    auto now = Clock::now();
51
63.8k
    if (ExpiredAt(now)) {
52
12
      return false;
53
12
    }
54
55
63.8k
    NextAttempt();
56
57
63.8k
    std::this_thread::sleep_for(DelayForTime(now));
58
63.8k
    return true;
59
63.8k
  }
yb::GenericBackoffWaiter<std::__1::chrono::steady_clock>::Wait()
Line
Count
Source
49
20.7k
  bool Wait() {
50
20.7k
    auto now = Clock::now();
51
20.7k
    if (ExpiredAt(now)) {
52
1
      return false;
53
1
    }
54
55
20.7k
    NextAttempt();
56
57
20.7k
    std::this_thread::sleep_for(DelayForTime(now));
58
20.7k
    return true;
59
20.7k
  }
yb::GenericBackoffWaiter<yb::CoarseMonoClock>::Wait()
Line
Count
Source
49
43.0k
  bool Wait() {
50
43.0k
    auto now = Clock::now();
51
43.0k
    if (ExpiredAt(now)) {
52
11
      return false;
53
11
    }
54
55
43.0k
    NextAttempt();
56
57
43.0k
    std::this_thread::sleep_for(DelayForTime(now));
58
43.0k
    return true;
59
43.0k
  }
60
61
63.8k
  void NextAttempt() {
62
63.8k
    ++attempt_;
63
63.8k
  }
yb::GenericBackoffWaiter<std::__1::chrono::steady_clock>::NextAttempt()
Line
Count
Source
61
20.7k
  void NextAttempt() {
62
20.7k
    ++attempt_;
63
20.7k
  }
yb::GenericBackoffWaiter<yb::CoarseMonoClock>::NextAttempt()
Line
Count
Source
61
43.0k
  void NextAttempt() {
62
43.0k
    ++attempt_;
63
43.0k
  }
64
65
  Duration DelayForNow() const {
66
    return DelayForTime(Clock::now());
67
  }
68
69
63.8k
  Duration DelayForTime(TimePoint now) const {
70
63.8k
    Duration max_wait = std::min(deadline_ - now, max_wait_);
71
    // 1st retry delayed 2^4 of base delays, 2nd 2^5 base delays, etc..
72
63.8k
    Duration attempt_delay =
73
63.8k
        base_delay_ *
74
63.8k
        (attempt_ >= 29 ? 
std::numeric_limits<int32_t>::max()664
:
1LL << (attempt_ + 3)63.1k
);
75
63.8k
    Duration jitter = std::chrono::milliseconds(RandomUniformInt(0, 50));
76
63.8k
    return std::min(attempt_delay + jitter, max_wait);
77
63.8k
  }
yb::GenericBackoffWaiter<std::__1::chrono::steady_clock>::DelayForTime(std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >) const
Line
Count
Source
69
20.7k
  Duration DelayForTime(TimePoint now) const {
70
20.7k
    Duration max_wait = std::min(deadline_ - now, max_wait_);
71
    // 1st retry delayed 2^4 of base delays, 2nd 2^5 base delays, etc..
72
20.7k
    Duration attempt_delay =
73
20.7k
        base_delay_ *
74
20.7k
        (attempt_ >= 29 ? 
std::numeric_limits<int32_t>::max()32
:
1LL << (attempt_ + 3)20.7k
);
75
20.7k
    Duration jitter = std::chrono::milliseconds(RandomUniformInt(0, 50));
76
20.7k
    return std::min(attempt_delay + jitter, max_wait);
77
20.7k
  }
yb::GenericBackoffWaiter<yb::CoarseMonoClock>::DelayForTime(std::__1::chrono::time_point<yb::CoarseMonoClock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >) const
Line
Count
Source
69
43.0k
  Duration DelayForTime(TimePoint now) const {
70
43.0k
    Duration max_wait = std::min(deadline_ - now, max_wait_);
71
    // 1st retry delayed 2^4 of base delays, 2nd 2^5 base delays, etc..
72
43.0k
    Duration attempt_delay =
73
43.0k
        base_delay_ *
74
43.0k
        (attempt_ >= 29 ? 
std::numeric_limits<int32_t>::max()632
:
1LL << (attempt_ + 3)42.4k
);
75
43.0k
    Duration jitter = std::chrono::milliseconds(RandomUniformInt(0, 50));
76
43.0k
    return std::min(attempt_delay + jitter, max_wait);
77
43.0k
  }
78
79
20.5k
  size_t attempt() const {
80
20.5k
    return attempt_;
81
20.5k
  }
yb::GenericBackoffWaiter<std::__1::chrono::steady_clock>::attempt() const
Line
Count
Source
79
20.5k
  size_t attempt() const {
80
20.5k
    return attempt_;
81
20.5k
  }
Unexecuted instantiation: yb::GenericBackoffWaiter<yb::CoarseMonoClock>::attempt() const
82
83
  // Resets attempt counter, w/o modifying deadline.
84
  void Restart() {
85
    attempt_ = 0;
86
  }
87
88
 private:
89
  TimePoint deadline_;
90
  size_t attempt_ = 0;
91
  Duration max_wait_;
92
  Duration base_delay_;
93
};
94
95
typedef GenericBackoffWaiter<std::chrono::steady_clock> BackoffWaiter;
96
typedef GenericBackoffWaiter<CoarseMonoClock> CoarseBackoffWaiter;
97
98
} // namespace yb
99
100
#endif // YB_UTIL_BACKOFF_WAITER_H