]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add unit tests to background lua context
authorYuval Lifshitz <ylifshit@redhat.com>
Mon, 2 May 2022 17:58:29 +0000 (20:58 +0300)
committerYuval Lifshitz <ylifshit@redhat.com>
Sun, 8 May 2022 11:11:04 +0000 (14:11 +0300)
Signed-off-by: Yuval Lifshitz <ylifshit@redhat.com>
src/rgw/rgw_lua_background.cc
src/rgw/rgw_lua_background.h
src/rgw/rgw_main.cc
src/test/rgw/test_rgw_lua.cc

index 2c85cabb23e6697bdbee16754a2a78221da4d139..56000edff2395bbfe01674862a3b0f2407f72fe0 100644 (file)
@@ -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) {
index 8c33171bef4b6318a73f5ad67057b4d1e9104be5..c7aefc1f84ead7234c7152b4d4ccf77492d7277e 100644 (file)
@@ -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);
index dd537c0d023d0de2894eb7389b33ebcf91197db8..55edcce7a2f359292f68a179561428fdce7c75cf 100644 (file)
@@ -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<string, RGWFrontendConfig *>::iterator fiter = fe_map.begin();
        fiter != fe_map.end(); ++fiter, ++fe_count) {
index cb1ef64b1f84bd1b25308f0157fbfc0eccf56a98..4e69510d046541d4ceb386781930bbb5f237f5ae 100644 (file)
@@ -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));
+}
+