diff --git a/db/external_sst_file_test.cc b/db/external_sst_file_test.cc index 318e1fb8c..552730295 100644 --- a/db/external_sst_file_test.cc +++ b/db/external_sst_file_test.cc @@ -16,6 +16,7 @@ #include "rocksdb/sst_file_writer.h" #include "test_util/testutil.h" #include "util/random.h" +#include "util/thread_guard.h" #include "utilities/fault_injection_env.h" namespace ROCKSDB_NAMESPACE { @@ -1305,38 +1306,38 @@ TEST_F(ExternalSSTFileTest, PickedLevelBug) { ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing(); - // While writing the MANIFEST start a thread that will ask for compaction Status bg_compact_status; - ROCKSDB_NAMESPACE::port::Thread bg_compact([&]() { - bg_compact_status = - db_->CompactRange(CompactRangeOptions(), nullptr, nullptr); - }); - TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:2"); - - // Start a thread that will ingest a new file Status bg_addfile_status; - ROCKSDB_NAMESPACE::port::Thread bg_addfile([&]() { - file_keys = {1, 2, 3}; - bg_addfile_status = GenerateAndAddExternalFile(options, file_keys, 1); - }); - - // Wait for AddFile to start picking levels and writing MANIFEST - TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:0"); - - TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:3"); - // We need to verify that no compactions can run while AddFile is - // ingesting the files into the levels it find suitable. So we will - // wait for 2 seconds to give a chance for compactions to run during - // this period, and then make sure that no compactions where able to run - env_->SleepForMicroseconds(1000000 * 2); - ASSERT_FALSE(bg_compact_started.load()); - - // Hold AddFile from finishing writing the MANIFEST - TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:1"); - - bg_addfile.join(); - bg_compact.join(); + { + // While writing the MANIFEST start a thread that will ask for compaction + ThreadGuard bg_compact(port::Thread([&]() { + bg_compact_status = + db_->CompactRange(CompactRangeOptions(), nullptr, nullptr); + })); + TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:2"); + + // Start a thread that will ingest a new file + ThreadGuard bg_addfile(port::Thread([&]() { + file_keys = {1, 2, 3}; + bg_addfile_status = GenerateAndAddExternalFile(options, file_keys, 1); + })); + + // Wait for AddFile to start picking levels and writing MANIFEST + TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:0"); + + TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:3"); + + // We need to verify that no compactions can run while AddFile is + // ingesting the files into the levels it find suitable. So we will + // wait for 2 seconds to give a chance for compactions to run during + // this period, and then make sure that no compactions where able to run + env_->SleepForMicroseconds(1000000 * 2); + ASSERT_FALSE(bg_compact_started.load()); + + // Hold AddFile from finishing writing the MANIFEST + TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:1"); + } ASSERT_OK(bg_addfile_status); ASSERT_OK(bg_compact_status); diff --git a/util/thread_guard.h b/util/thread_guard.h new file mode 100644 index 000000000..b2bb06a1b --- /dev/null +++ b/util/thread_guard.h @@ -0,0 +1,41 @@ +// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). + +#pragma once + +#include "port/port.h" +#include "rocksdb/rocksdb_namespace.h" + +namespace ROCKSDB_NAMESPACE { + +// Resource management object for threads that joins the thread upon +// destruction. Has unique ownership of the thread object, so copying it is not +// allowed, while moving it transfers ownership. +class ThreadGuard { + public: + ThreadGuard() = default; + + explicit ThreadGuard(port::Thread&& thread) : thread_(std::move(thread)) {} + + ThreadGuard(const ThreadGuard&) = delete; + ThreadGuard& operator=(const ThreadGuard&) = delete; + + ThreadGuard(ThreadGuard&&) noexcept = default; + ThreadGuard& operator=(ThreadGuard&&) noexcept = default; + + ~ThreadGuard() { + if (thread_.joinable()) { + thread_.join(); + } + } + + const port::Thread& GetThread() const { return thread_; } + port::Thread& GetThread() { return thread_; } + + private: + port::Thread thread_; +}; + +} // namespace ROCKSDB_NAMESPACE