Coverage Report

Created: 2024-07-27 06:53

/src/rocksdb/env/emulated_clock.h
Line
Count
Source (jump to first uncovered line)
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
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7
// Use of this source code is governed by a BSD-style license that can be
8
// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
#pragma once
10
11
#include <atomic>
12
#include <string>
13
14
#include "rocksdb/status.h"
15
#include "rocksdb/system_clock.h"
16
17
namespace ROCKSDB_NAMESPACE {
18
// A SystemClock that can "mock" sleep and counts its operations.
19
class EmulatedSystemClock : public SystemClockWrapper {
20
 private:
21
  // Something to return when mocking current time
22
  const int64_t maybe_starting_time_;
23
  std::atomic<int> sleep_counter_{0};
24
  std::atomic<int> cpu_counter_{0};
25
  std::atomic<int64_t> addon_microseconds_{0};
26
  // Do not modify in the env of a running DB (could cause deadlock)
27
  std::atomic<bool> time_elapse_only_sleep_;
28
  bool no_slowdown_;
29
30
 public:
31
  explicit EmulatedSystemClock(const std::shared_ptr<SystemClock>& base,
32
                               bool time_elapse_only_sleep = false);
33
34
0
  static const char* kClassName() { return "TimeEmulatedSystemClock"; }
35
0
  const char* Name() const override { return kClassName(); }
36
37
0
  void SleepForMicroseconds(int micros) override {
38
0
    sleep_counter_++;
39
0
    if (no_slowdown_ || time_elapse_only_sleep_) {
40
0
      addon_microseconds_.fetch_add(micros);
41
0
    }
42
0
    if (!no_slowdown_) {
43
0
      SystemClockWrapper::SleepForMicroseconds(micros);
44
0
    }
45
0
  }
46
47
0
  void MockSleepForMicroseconds(int64_t micros) {
48
0
    sleep_counter_++;
49
0
    assert(no_slowdown_);
50
0
    addon_microseconds_.fetch_add(micros);
51
0
  }
52
53
0
  void MockSleepForSeconds(int64_t seconds) {
54
0
    sleep_counter_++;
55
0
    assert(no_slowdown_);
56
0
    addon_microseconds_.fetch_add(seconds * 1000000);
57
0
  }
58
59
0
  void SetTimeElapseOnlySleep(bool enabled) {
60
    // We cannot set these before destroying the last DB because they might
61
    // cause a deadlock or similar without the appropriate options set in
62
    // the DB.
63
0
    time_elapse_only_sleep_ = enabled;
64
0
    no_slowdown_ = enabled;
65
0
  }
66
67
0
  bool IsTimeElapseOnlySleep() const { return time_elapse_only_sleep_.load(); }
68
0
  void SetMockSleep(bool enabled = true) { no_slowdown_ = enabled; }
69
0
  bool IsMockSleepEnabled() const { return no_slowdown_; }
70
71
0
  int GetSleepCounter() const { return sleep_counter_.load(); }
72
73
0
  Status GetCurrentTime(int64_t* unix_time) override {
74
0
    Status s;
75
0
    if (time_elapse_only_sleep_) {
76
0
      *unix_time = maybe_starting_time_;
77
0
    } else {
78
0
      s = SystemClockWrapper::GetCurrentTime(unix_time);
79
0
    }
80
0
    if (s.ok()) {
81
      // mock microseconds elapsed to seconds of time
82
0
      *unix_time += addon_microseconds_.load() / 1000000;
83
0
    }
84
0
    return s;
85
0
  }
86
87
0
  uint64_t CPUNanos() override {
88
0
    cpu_counter_++;
89
0
    return SystemClockWrapper::CPUNanos();
90
0
  }
91
92
0
  uint64_t CPUMicros() override {
93
0
    cpu_counter_++;
94
0
    return SystemClockWrapper::CPUMicros();
95
0
  }
96
97
0
  uint64_t NowNanos() override {
98
0
    return (time_elapse_only_sleep_ ? 0 : SystemClockWrapper::NowNanos()) +
99
0
           addon_microseconds_.load() * 1000;
100
0
  }
101
102
0
  uint64_t NowMicros() override {
103
0
    return (time_elapse_only_sleep_ ? 0 : SystemClockWrapper::NowMicros()) +
104
0
           addon_microseconds_.load();
105
0
  }
106
107
0
  int GetCpuCounter() const { return cpu_counter_.load(); }
108
109
0
  void ResetCounters() {
110
0
    cpu_counter_.store(0);
111
0
    sleep_counter_.store(0);
112
0
  }
113
};
114
}  // namespace ROCKSDB_NAMESPACE