emulated_clock.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. #include <atomic>
  11. #include <string>
  12. #include "rocksdb/status.h"
  13. #include "rocksdb/system_clock.h"
  14. namespace ROCKSDB_NAMESPACE {
  15. // A SystemClock that can "mock" sleep and counts its operations.
  16. class EmulatedSystemClock : public SystemClockWrapper {
  17. private:
  18. // Something to return when mocking current time
  19. const int64_t maybe_starting_time_;
  20. std::atomic<int> sleep_counter_{0};
  21. std::atomic<int> cpu_counter_{0};
  22. std::atomic<int64_t> addon_microseconds_{0};
  23. // Do not modify in the env of a running DB (could cause deadlock)
  24. std::atomic<bool> time_elapse_only_sleep_;
  25. bool no_slowdown_;
  26. public:
  27. explicit EmulatedSystemClock(const std::shared_ptr<SystemClock>& base,
  28. bool time_elapse_only_sleep = false);
  29. static const char* kClassName() { return "TimeEmulatedSystemClock"; }
  30. const char* Name() const override { return kClassName(); }
  31. void SleepForMicroseconds(int micros) override {
  32. sleep_counter_++;
  33. if (no_slowdown_ || time_elapse_only_sleep_) {
  34. addon_microseconds_.fetch_add(micros);
  35. }
  36. if (!no_slowdown_) {
  37. SystemClockWrapper::SleepForMicroseconds(micros);
  38. }
  39. }
  40. void MockSleepForMicroseconds(int64_t micros) {
  41. sleep_counter_++;
  42. assert(no_slowdown_);
  43. addon_microseconds_.fetch_add(micros);
  44. }
  45. void MockSleepForSeconds(int64_t seconds) {
  46. sleep_counter_++;
  47. assert(no_slowdown_);
  48. addon_microseconds_.fetch_add(seconds * 1000000);
  49. }
  50. void SetTimeElapseOnlySleep(bool enabled) {
  51. // We cannot set these before destroying the last DB because they might
  52. // cause a deadlock or similar without the appropriate options set in
  53. // the DB.
  54. time_elapse_only_sleep_ = enabled;
  55. no_slowdown_ = enabled;
  56. }
  57. bool IsTimeElapseOnlySleep() const { return time_elapse_only_sleep_.load(); }
  58. void SetMockSleep(bool enabled = true) { no_slowdown_ = enabled; }
  59. bool IsMockSleepEnabled() const { return no_slowdown_; }
  60. int GetSleepCounter() const { return sleep_counter_.load(); }
  61. Status GetCurrentTime(int64_t* unix_time) override {
  62. Status s;
  63. if (time_elapse_only_sleep_) {
  64. *unix_time = maybe_starting_time_;
  65. } else {
  66. s = SystemClockWrapper::GetCurrentTime(unix_time);
  67. }
  68. if (s.ok()) {
  69. // mock microseconds elapsed to seconds of time
  70. *unix_time += addon_microseconds_.load() / 1000000;
  71. }
  72. return s;
  73. }
  74. uint64_t CPUNanos() override {
  75. cpu_counter_++;
  76. return SystemClockWrapper::CPUNanos();
  77. }
  78. uint64_t CPUMicros() override {
  79. cpu_counter_++;
  80. return SystemClockWrapper::CPUMicros();
  81. }
  82. uint64_t NowNanos() override {
  83. return (time_elapse_only_sleep_ ? 0 : SystemClockWrapper::NowNanos()) +
  84. addon_microseconds_.load() * 1000;
  85. }
  86. uint64_t NowMicros() override {
  87. return (time_elapse_only_sleep_ ? 0 : SystemClockWrapper::NowMicros()) +
  88. addon_microseconds_.load();
  89. }
  90. int GetCpuCounter() const { return cpu_counter_.load(); }
  91. void ResetCounters() {
  92. cpu_counter_.store(0);
  93. sleep_counter_.store(0);
  94. }
  95. };
  96. } // namespace ROCKSDB_NAMESPACE