point_lock_manager_test.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright (c) Meta Platforms, Inc. and affiliates.
  2. //
  3. // This source code is licensed under both the GPLv2 (found in the
  4. // COPYING file in the root directory) and Apache 2.0 License
  5. // (found in the LICENSE.Apache file in the root directory).
  6. #pragma once
  7. #include "file/file_util.h"
  8. #include "rocksdb/utilities/transaction_db.h"
  9. #include "test_util/testharness.h"
  10. #include "utilities/transactions/lock/point/point_lock_manager.h"
  11. #include "utilities/transactions/lock/point/point_lock_manager_test_common.h"
  12. #include "utilities/transactions/pessimistic_transaction_db.h"
  13. namespace ROCKSDB_NAMESPACE {
  14. class PointLockManagerTest : public testing::Test {
  15. public:
  16. void init() {
  17. env_ = Env::Default();
  18. db_dir_ = test::PerThreadDBPath("point_lock_manager_test");
  19. ASSERT_OK(env_->CreateDir(db_dir_));
  20. Options opt;
  21. opt.create_if_missing = true;
  22. // Reduce the number of stripes to 4 to increase contention in test
  23. txndb_opt_.num_stripes = 4;
  24. txndb_opt_.transaction_lock_timeout = 0;
  25. ASSERT_OK(TransactionDB::Open(opt, txndb_opt_, db_dir_, &db_));
  26. wait_sync_point_name_ = "PointLockManager::AcquireWithTimeout:WaitingTxn";
  27. }
  28. void SetUp() override {
  29. init();
  30. // CAUTION: This test creates a separate lock manager object (right, NOT
  31. // the one that the TransactionDB is using!), and runs tests on it.
  32. locker_.reset(new PointLockManager(
  33. static_cast<PessimisticTransactionDB*>(db_), txndb_opt_));
  34. }
  35. void TearDown() override {
  36. std::string errmsg;
  37. auto no_lock_held = verifyNoLocksHeld(locker_, errmsg);
  38. ASSERT_TRUE(no_lock_held) << errmsg;
  39. delete db_;
  40. EXPECT_OK(DestroyDir(env_, db_dir_));
  41. }
  42. PessimisticTransaction* NewTxn(
  43. TransactionOptions txn_opt = TransactionOptions()) {
  44. // override deadlock_timeout_us;
  45. txn_opt.deadlock_timeout_us = deadlock_timeout_us;
  46. Transaction* txn = db_->BeginTransaction(WriteOptions(), txn_opt);
  47. return static_cast<PessimisticTransaction*>(txn);
  48. }
  49. int64_t deadlock_timeout_us = 0;
  50. void UsePerKeyPointLockManager() {
  51. locker_.reset(new PerKeyPointLockManager(
  52. static_cast<PessimisticTransactionDB*>(db_), txndb_opt_));
  53. }
  54. protected:
  55. Env* env_;
  56. TransactionDBOptions txndb_opt_;
  57. std::shared_ptr<LockManager> locker_;
  58. const char* wait_sync_point_name_;
  59. friend void PointLockManagerTestExternalSetup(PointLockManagerTest*);
  60. std::string db_dir_;
  61. TransactionDB* db_;
  62. };
  63. void BlockUntilWaitingTxn(const char* sync_point_name, port::Thread& t,
  64. std::function<void()> f) {
  65. std::atomic<bool> reached(false);
  66. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  67. sync_point_name, [&](void* /*arg*/) { reached.store(true); });
  68. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  69. t = port::Thread(f);
  70. // timeout after 30 seconds, so test does not hang forever
  71. // 30 seconds should be enough for the test to reach the expected state
  72. // without causing too much flakiness
  73. for (int i = 0; i < 3000; i++) {
  74. if (reached.load()) {
  75. break;
  76. }
  77. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  78. }
  79. ASSERT_TRUE(reached.load());
  80. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  81. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  82. }
  83. } // namespace ROCKSDB_NAMESPACE