Summary: Using real clock causes failures of DBSSTTest.RateLimitedDelete in some cases. Turn away from the real time. Use fake time instead.
Test Plan: Run the tests and all existing tests.
Reviewers: yiwu, IslamAbdelRahman
Reviewed By: IslamAbdelRahman
Subscribers: leveldb, andrewkr, dhruba
Differential Revision: https://reviews.facebook.net/D65145
rocksdb::SyncPoint::GetInstance()->SetCallBack(
"DeleteScheduler::BackgroundEmptyTrash:Wait",
[&](void* arg) { penalties.push_back(*(static_cast<int*>(arg))); });
+ rocksdb::SyncPoint::GetInstance()->SetCallBack(
+ "InstrumentedCondVar::TimedWaitInternal", [&](void* arg) {
+ // Turn timed wait into a simulated sleep
+ uint64_t* abs_time_us = static_cast<uint64_t*>(arg);
+ int64_t cur_time = 0;
+ env_->GetCurrentTime(&cur_time);
+ if (*abs_time_us > static_cast<uint64_t>(cur_time)) {
+ env_->addon_time_.fetch_add(*abs_time_us -
+ static_cast<uint64_t>(cur_time));
+ }
+
+ // Randomly sleep shortly
+ env_->addon_time_.fetch_add(
+ static_cast<uint64_t>(Random::GetTLSInstance()->Uniform(10)));
+
+ // Set wait until time to before current to force not to sleep.
+ int64_t real_cur_time = 0;
+ Env::Default()->GetCurrentTime(&real_cur_time);
+ *abs_time_us = static_cast<uint64_t>(real_cur_time);
+ });
+
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
+ env_->no_sleep_ = true;
+ env_->time_elapse_only_sleep_ = true;
Options options = CurrentOptions();
options.disable_auto_compactions = true;
options.env = env_;
ASSERT_EQ(expected_penlty, penalties[i]);
}
ASSERT_GT(time_spent_deleting, expected_penlty * 0.9);
+ ASSERT_LT(time_spent_deleting, expected_penlty * 1.1);
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
}
DeleteScheduler::~DeleteScheduler() {
{
- MutexLock l(&mu_);
+ InstrumentedMutexLock l(&mu_);
closing_ = true;
cv_.SignalAll();
}
// Add file to delete queue
{
- MutexLock l(&mu_);
+ InstrumentedMutexLock l(&mu_);
queue_.push(path_in_trash);
pending_files_++;
if (pending_files_ == 1) {
}
std::map<std::string, Status> DeleteScheduler::GetBackgroundErrors() {
- MutexLock l(&mu_);
+ InstrumentedMutexLock l(&mu_);
return bg_errors_;
}
// TODO(tec) : Implement Env::RenameFileIfNotExist and remove
// file_move_mu mutex.
- MutexLock l(&file_move_mu_);
+ InstrumentedMutexLock l(&file_move_mu_);
while (true) {
s = env_->FileExists(*path_in_trash + unique_suffix);
if (s.IsNotFound()) {
TEST_SYNC_POINT("DeleteScheduler::BackgroundEmptyTrash");
while (true) {
- MutexLock l(&mu_);
+ InstrumentedMutexLock l(&mu_);
while (queue_.empty() && !closing_) {
cv_.Wait();
}
}
void DeleteScheduler::WaitForEmptyTrash() {
- MutexLock l(&mu_);
+ InstrumentedMutexLock l(&mu_);
while (pending_files_ > 0 && !closing_) {
cv_.Wait();
}
#include <thread>
#include "port/port.h"
+#include "util/instrumented_mutex.h"
#include "rocksdb/status.h"
// Maximum number of bytes that should be deleted per second
int64_t rate_bytes_per_sec_;
// Mutex to protect queue_, pending_files_, bg_errors_, closing_
- port::Mutex mu_;
+ InstrumentedMutex mu_;
// Queue of files in trash that need to be deleted
std::queue<std::string> queue_;
// Number of files in trash that are waiting to be deleted
// - pending_files_ value change from 0 => 1
// - pending_files_ value change from 1 => 0
// - closing_ value is set to true
- port::CondVar cv_;
+ InstrumentedCondVar cv_;
// Background thread running BackgroundEmptyTrash
std::unique_ptr<std::thread> bg_thread_;
// Mutex to protect threads from file name conflicts
- port::Mutex file_move_mu_;
+ InstrumentedMutex file_move_mu_;
Logger* info_log_;
SstFileManagerImpl* sst_file_manager_;
static const uint64_t kMicrosInSecond = 1000 * 1000LL;
#include "util/instrumented_mutex.h"
#include "util/perf_context_imp.h"
+#include "util/sync_point.h"
#include "util/thread_status_util.h"
namespace rocksdb {
#ifndef NDEBUG
ThreadStatusUtil::TEST_StateDelay(ThreadStatus::STATE_MUTEX_WAIT);
#endif
+
+ TEST_SYNC_POINT_CALLBACK("InstrumentedCondVar::TimedWaitInternal",
+ &abs_time_us);
+
return cond_.TimedWait(abs_time_us);
}