From 2f1c295957c0946de62941aa76200275a92b6272 Mon Sep 17 00:00:00 2001 From: Tim Serong Date: Thu, 19 Oct 2023 19:00:33 +1100 Subject: [PATCH] rgw/sfs: testing: add TestSFSConnectionPool Signed-off-by: Tim Serong --- src/test/rgw/sfs/CMakeLists.txt | 1 + .../rgw/sfs/test_rgw_sfs_connection_pool.cc | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/test/rgw/sfs/test_rgw_sfs_connection_pool.cc diff --git a/src/test/rgw/sfs/CMakeLists.txt b/src/test/rgw/sfs/CMakeLists.txt index bc9142014414d9..25757a65c14e07 100644 --- a/src/test/rgw/sfs/CMakeLists.txt +++ b/src/test/rgw/sfs/CMakeLists.txt @@ -21,3 +21,4 @@ add_s3gw_test(unittest_rgw_sfs_object_state_machine test_rgw_sfs_object_state_ma add_s3gw_test(unittest_rgw_sfs_retry test_rgw_sfs_retry.cc) add_s3gw_test(unittest_rgw_sfs_concurrency test_rgw_sfs_concurrency.cc) add_s3gw_test(unittest_rgw_sfs_wal_checkpoint test_rgw_sfs_wal_checkpoint.cc) +add_s3gw_test(unittest_rgw_sfs_connection_pool test_rgw_sfs_connection_pool.cc) diff --git a/src/test/rgw/sfs/test_rgw_sfs_connection_pool.cc b/src/test/rgw/sfs/test_rgw_sfs_connection_pool.cc new file mode 100644 index 00000000000000..0a59eab68b56e3 --- /dev/null +++ b/src/test/rgw/sfs/test_rgw_sfs_connection_pool.cc @@ -0,0 +1,77 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include + +#include "rgw/driver/sfs/sqlite/dbconn.h" +#include "rgw/rgw_sal_sfs.h" + +using namespace rgw::sal::sfs::sqlite; + +namespace fs = std::filesystem; + +const static std::string TEST_DIR = "rgw_sfs_tests"; + +class TestSFSConnectionPool : public ::testing::Test { + protected: + const std::unique_ptr cct; + const fs::path test_dir; + std::unique_ptr store; + + TestSFSConnectionPool() + : cct(new CephContext(CEPH_ENTITY_TYPE_ANY)), + test_dir(fs::temp_directory_path() / TEST_DIR) { + fs::create_directory(test_dir); + cct->_conf.set_val("rgw_sfs_data_path", test_dir); + cct->_log->start(); + store.reset(new rgw::sal::SFStore(cct.get(), test_dir)); + } + + ~TestSFSConnectionPool() override { + store.reset(); + fs::remove_all(test_dir); + } +}; + +TEST_F(TestSFSConnectionPool, verify_one_connection_per_thread) { + DBConnRef conn = store->db_conn; + + // At this point there should be only one connection in the pool. + // Alas, DBConn::storage_pool is private, but DBConn::all_sqlite_conns + // is a reasonably proxy for this. + EXPECT_EQ(conn->all_sqlite_conns.size(), 1); + + std::set storages; + storages.emplace(conn->get_storage()); + + // Having now called get_storage from the main thread, we should + // still have only one connection. + EXPECT_EQ(conn->all_sqlite_conns.size(), 1); + + std::shared_mutex mutex; + std::vector threads; + const size_t num_threads = 10; + for (size_t i = 0; i < num_threads; ++i) { + std::thread t([&]() { + // Multiple calls to get_storage() in a new thread should return + // the same pointer... + StorageRef s1 = conn->get_storage(); + StorageRef s2 = conn->get_storage(); + EXPECT_EQ(s1, s2); + + // ...and that pointer shouldn't be in use by any other thread. + std::unique_lock lock(mutex); + EXPECT_EQ(storages.find(s1), storages.end()); + + // Now we have to save it so this check works for the other threads. + storages.emplace(s1); + }); + threads.push_back(std::move(t)); + } + for (size_t i = 0; i < num_threads; ++i) { + threads[i].join(); + } + + // Now there should be the original connection, plus ten more + EXPECT_EQ(conn->all_sqlite_conns.size(), 1 + num_threads); +}