From 51c19337d844b784b098074b24b3d709622f34a2 Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Mon, 2 May 2022 20:58:29 +0300 Subject: [PATCH] rgw: add unit tests to background lua context Signed-off-by: Yuval Lifshitz --- src/rgw/rgw_lua_background.cc | 27 +++++++++--- src/rgw/rgw_lua_background.h | 18 ++++---- src/rgw/rgw_main.cc | 1 + src/test/rgw/test_rgw_lua.cc | 83 +++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 14 deletions(-) diff --git a/src/rgw/rgw_lua_background.cc b/src/rgw/rgw_lua_background.cc index 2c85cabb23e6..56000edff239 100644 --- a/src/rgw/rgw_lua_background.cc +++ b/src/rgw/rgw_lua_background.cc @@ -8,12 +8,31 @@ namespace rgw::lua { void Background::shutdown(){ this->stop(); - runner.join(); + if (runner.joinable()) { + runner.join(); + } } void Background::stop(){ stopped = true; } +void Background::start() { + if (started) { + // start the thread only once + return; + } + started = true; + runner = std::thread(&Background::run, this); + const auto rc = ceph_pthread_setname(runner.native_handle(), + "lua_background"); + ceph_assert(rc == 0); +} + +int Background::read_script() { + std::string tenant; + return rgw::lua::read_script(dpp, store, tenant, null_yield, rgw::lua::context::background, rgw_script); +} + //(1) Loads the script from the object //(2) Executes the script //(3) Sleep (configurable) @@ -22,13 +41,11 @@ void Background::run() { rgw::lua::lua_state_guard lguard(L); open_standard_libs(L); set_package_path(L, luarocks_path); - create_debug_action(L, cct->get()); + create_debug_action(L, cct); create_background_metatable(L); while (!stopped) { - - std::string tenant; - auto rc = rgw::lua::read_script(dpp, store, tenant, null_yield, rgw::lua::context::background, rgw_script); + const auto rc = read_script(); if (rc == -ENOENT) { // no script, nothing to do } else if (rc < 0) { diff --git a/src/rgw/rgw_lua_background.h b/src/rgw/rgw_lua_background.h index 8c33171bef4b..c7aefc1f84ea 100644 --- a/src/rgw/rgw_lua_background.h +++ b/src/rgw/rgw_lua_background.h @@ -36,18 +36,22 @@ class Background { private: BackgroundMap rgw_map; - std::string rgw_script; bool stopped = false; + bool started = false; int execute_interval = INIT_EXECUTE_INTERVAL; const DoutPrefixProvider* const dpp; rgw::sal::Store* const store; CephContext* const cct; - std::string luarocks_path; + const std::string luarocks_path; std::thread runner; std::mutex m_mutex; void run(); +protected: + std::string rgw_script; + virtual int read_script(); + public: Background(const DoutPrefixProvider* dpp, rgw::sal::Store* store, @@ -56,14 +60,10 @@ public: dpp(dpp), store(store), cct(cct), - luarocks_path(luarocks_path), - runner(std::thread(&Background::run, this)) { - const auto rc = ceph_pthread_setname(runner.native_handle(), - "lua_background"); - ceph_assert(rc == 0); - } + luarocks_path(luarocks_path) {} - ~Background() = default; + virtual ~Background() = default; + void start(); void stop(); void shutdown(); void create_background_metatable(lua_State* L); diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc index dd537c0d023d..55edcce7a2f3 100644 --- a/src/rgw/rgw_main.cc +++ b/src/rgw/rgw_main.cc @@ -607,6 +607,7 @@ int radosgw_Main(int argc, const char **argv) int fe_count = 0; rgw::lua::Background lua_background(&dp, store, cct.get(), store->get_luarocks_path()); + lua_background.start(); for (multimap::iterator fiter = fe_map.begin(); fiter != fe_map.end(); ++fiter, ++fe_count) { diff --git a/src/test/rgw/test_rgw_lua.cc b/src/test/rgw/test_rgw_lua.cc index cb1ef64b1f84..4e69510d0465 100644 --- a/src/test/rgw/test_rgw_lua.cc +++ b/src/test/rgw/test_rgw_lua.cc @@ -5,6 +5,7 @@ #include "rgw/rgw_process.h" #include "rgw/rgw_sal_rados.h" #include "rgw/rgw_lua_request.h" +#include "rgw/rgw_lua_background.h" using namespace std; using namespace rgw; @@ -646,3 +647,85 @@ TEST(TestRGWLua, OpsLog) EXPECT_TRUE(olog.logged); } +class TestBackground : public rgw::lua::Background { +protected: + int read_script() override { + // don't read the object from the store + return 0; + } + +public: + TestBackground(const std::string& script) : + rgw::lua::Background(nullptr, nullptr, nullptr, "") { + // the script is passed in the constructor + rgw_script = script; + } + + ~TestBackground() override { + shutdown(); + } +}; + +TEST(TestRGWLua, Background) +{ + { + // ctr and dtor without running + TestBackground lua_background(""); + } + { + // ctr and dtor with running + TestBackground lua_background(""); + lua_background.start(); + // let the background context run for 5 seconds + std::this_thread::sleep_for(std::chrono::seconds(5)); + } +} + +TEST(TestRGWLua, BackgroundScript) +{ + const std::string script = R"( + local key = "hello" + local value = "world" + RGW[key] = value + print(RGW[key] == value) + )"; + + TestBackground lua_background(script); + lua_background.start(); + // let the background context run for 5 seconds + std::this_thread::sleep_for(std::chrono::seconds(5)); +} + +TEST(TestRGWLua, BackgroundRequestScript) +{ + const std::string background_script = R"( + local key = "hello" + local value = "from background" + -- set the value only if not set + if RGW[key] == nil then + RGW[key] = value + end + print("from background:", RGW[key]) + )"; + + TestBackground lua_background(background_script); + lua_background.start(); + // let the background context run for 5 seconds + std::this_thread::sleep_for(std::chrono::seconds(5)); + + const std::string request_script = R"( + local key = "hello" + local value = "from request" + print("from request (before setting):", RGW[key]) + RGW[key] = value + print("from request (after setting):", RGW[key]) + )"; + + DEFINE_REQ_STATE; + + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background); + ASSERT_EQ(rc, 0); + // let the background context run for 5 seconds + std::this_thread::sleep_for(std::chrono::seconds(5)); +} + -- 2.47.3