]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/cache: adding unittests for ssd backed cache backend, and
authorPritha Srivastava <prsrivas@redhat.com>
Wed, 8 Nov 2023 11:01:04 +0000 (16:31 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Tue, 2 Apr 2024 15:54:51 +0000 (21:24 +0530)
fixing bugs that the tests revealed.

Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
src/rgw/rgw_ssd_driver.cc
src/test/rgw/CMakeLists.txt
src/test/rgw/test_ssd_driver.cc [new file with mode: 0644]

index 6dd536ef58d9c79aaf38b681fda305484862fedf..56a9fb1a5e0bd0ee3bd193717cbb523651082d15 100644 (file)
@@ -155,31 +155,33 @@ int SSDDriver::get(const DoutPrefixProvider* dpp, const std::string& key, off_t
 
     cache_file = fopen(location.c_str(), "r+");
     if (cache_file == nullptr) {
-        ldpp_dout(dpp, 0) << "ERROR: put::fopen file has return error, errno=" << errno << dendl;
+        ldpp_dout(dpp, 0) << "ERROR: get::fopen file has return error, errno=" << errno << dendl;
         return -errno;
     }
 
-    nbytes = fread(buffer, sizeof(buffer), 1 , cache_file);
+    fseek(cache_file, offset, SEEK_SET);
+
+    nbytes = fread(buffer, 1, len, cache_file);
     if (nbytes != len) {
-        ldpp_dout(dpp, 0) << "ERROR: put::io_read: fread has returned error: nbytes!=len, nbytes=" << nbytes << ", len=" << len << dendl;
+        fclose(cache_file);
+        ldpp_dout(dpp, 0) << "ERROR: get::io_read: fread has returned error: nbytes!=len, nbytes=" << nbytes << ", len=" << len << dendl;
         return -EIO;
     }
 
     r = fclose(cache_file);
     if (r != 0) {
-        ldpp_dout(dpp, 0) << "ERROR: put::fclose file has return error, errno=" << errno << dendl;
+        ldpp_dout(dpp, 0) << "ERROR: get::fclose file has return error, errno=" << errno << dendl;
         return -errno;
     }
 
-    ceph::encode(buffer, bl);
+    bl.append(buffer, len);
 
-    if (attrs.size() > 0) {
-        r = get_attrs(dpp, key, attrs, y);
-        if (r < 0) {
-            ldpp_dout(dpp, 0) << "ERROR: put::get_attrs: failed to get attrs, r = " << r << dendl;
-            return r;
-        }
+    r = get_attrs(dpp, key, attrs, y);
+    if (r < 0) {
+        ldpp_dout(dpp, 0) << "ERROR: get::get_attrs: failed to get attrs, r = " << r << dendl;
+        return r;
     }
+
     return 0;
 }
 
@@ -402,9 +404,8 @@ int SSDDriver::update_attrs(const DoutPrefixProvider* dpp, const std::string& ke
     ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
 
     for (auto& it : attrs) {
-        std::string attr_name, attr_val;
-        attr_name = it.first;
-        attr_val = it.second.c_str();
+        std::string attr_name = it.first;
+        std::string attr_val = it.second.to_str();
         std::string old_attr_val = get_attr(dpp, key, attr_name, y);
         int ret;
         if (old_attr_val.empty()) {
@@ -460,17 +461,16 @@ int SSDDriver::get_attrs(const DoutPrefixProvider* dpp, const std::string& key,
 
         keylen = strlen(keyptr) + 1;
         std::string attr_name(keyptr);
-        std::string::size_type prefixloc = key.find(ATTR_PREFIX);
+        std::string::size_type prefixloc = attr_name.find(ATTR_PREFIX);
+        buflen -= keylen;
+        keyptr += keylen;
         if (prefixloc == std::string::npos) {
-            buflen -= keylen;
-            keyptr += keylen;
             continue;
         }
         std::string attr_value = get_attr(dpp, key, attr_name, y);
         bufferlist bl_value;
-        ceph::encode(attr_value, bl_value);
+        bl_value.append(attr_value);
         attrs.emplace(std::move(attr_name), std::move(bl_value));
-
     }
     return 0;
 }
@@ -483,7 +483,7 @@ int SSDDriver::set_attrs(const DoutPrefixProvider* dpp, const std::string& key,
     for (auto& [attr_name, attr_val_bl] : attrs) {
         ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): attr_name = " << attr_name << " attr_val_bl length: " << attr_val_bl.length() << dendl;
         if (attr_val_bl.length() != 0) {
-            auto ret = set_attr(dpp, key, attr_name, attr_val_bl.c_str(), y);
+            auto ret = set_attr(dpp, key, attr_name, attr_val_bl.to_str(), y);
             if (ret < 0) {
                 ldpp_dout(dpp, 0) << "SSDCache: " << __func__ << "(): could not set attr value for attr name: " << attr_name << " key: " << key << cpp_strerror(errno) << dendl;
                 return ret;
@@ -500,32 +500,30 @@ int SSDDriver::set_attrs(const DoutPrefixProvider* dpp, const std::string& key,
 std::string SSDDriver::get_attr(const DoutPrefixProvider* dpp, const std::string& key, const std::string& attr_name, optional_yield y)
 {
     std::string location = partition_info.location + key;
-    std::string attr_val;
     ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
 
     ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): get_attr: key: " << attr_name << dendl;
 
     int attr_size = getxattr(location.c_str(), attr_name.c_str(), nullptr, 0);
     if (attr_size < 0) {
-      auto ret = errno;
-      ldpp_dout(dpp, 0) << "ERROR: could not get attribute " << attr_name << ": " << cpp_strerror(ret) << dendl;
-      return attr_val;
+        auto ret = errno;
+        ldpp_dout(dpp, 0) << "ERROR: could not get attribute " << attr_name << ": " << cpp_strerror(ret) << dendl;
+        return "";
     }
 
     if (attr_size == 0) {
-      ldpp_dout(dpp, 0) << "ERROR: no attribute value found for attr_name: " << attr_name << dendl;
-      return attr_val;
+        ldpp_dout(dpp, 0) << "ERROR: no attribute value found for attr_name: " << attr_name << dendl;
+        return "";
     }
 
-    attr_val.reserve(attr_size + 1);
-    char* attr_val_ptr =  &attr_val[0];
-
+    char attr_val_ptr[attr_size + 1];
     attr_size = getxattr(location.c_str(), attr_name.c_str(), attr_val_ptr, attr_size);
     if (attr_size < 0) {
         ldpp_dout(dpp, 0) << "SSDCache: " << __func__ << "(): could not get attr value for attr name: " << attr_name << " key: " << key << dendl;
     }
+    attr_val_ptr[attr_size] = '\0';
 
-    return attr_val;
+    return std::string(attr_val_ptr);
 }
 
 int SSDDriver::set_attr(const DoutPrefixProvider* dpp, const std::string& key, const std::string& attr_name, const std::string& attr_val, optional_yield y)
index 3367314f4820be091bdf7003f99d496ecf160028..8e19e75be59a2549dd12fcf8520180669260815d 100644 (file)
@@ -137,6 +137,23 @@ add_executable(unittest_rgw_ratelimit test_rgw_ratelimit.cc $<TARGET_OBJECTS:uni
 target_link_libraries(unittest_rgw_ratelimit ${rgw_libs})
 add_ceph_unittest(unittest_rgw_ratelimit)
 
+add_executable(ceph_test_rgw_ssd_driver
+  test_ssd_driver.cc
+  )
+target_include_directories(ceph_test_rgw_ssd_driver
+  PUBLIC "${CMAKE_SOURCE_DIR}/src/dmclock/support/src"
+  SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw/")
+target_link_libraries(ceph_test_rgw_ssd_driver PRIVATE
+  rgw_common
+  librados
+  ceph-common
+  ${rgw_libs}
+  ${UNITTEST_LIBS}
+  ${EXTRALIBS}
+  )
+  target_link_libraries(ceph_test_rgw_ssd_driver PRIVATE spawn)
+install(TARGETS ceph_test_rgw_ssd_driver DESTINATION ${CMAKE_INSTALL_BINDIR})
+
 # ceph_test_rgw_manifest
 set(test_rgw_manifest_srcs test_rgw_manifest.cc)
 add_executable(ceph_test_rgw_manifest
diff --git a/src/test/rgw/test_ssd_driver.cc b/src/test/rgw/test_ssd_driver.cc
new file mode 100644 (file)
index 0000000..6396dcf
--- /dev/null
@@ -0,0 +1,220 @@
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/detached.hpp>
+
+#include "gtest/gtest.h"
+#include "common/ceph_argparse.h"
+#include "rgw_auth_registry.h"
+#include "rgw_aio_throttle.h"
+#include "rgw_ssd_driver.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+namespace net = boost::asio;
+
+class Environment* env;
+
+class Environment : public ::testing::Environment {
+  public:
+    Environment() {}
+
+    virtual ~Environment() {}
+
+    void SetUp() override {
+      std::vector<const char*> args;
+      std::string conf_file_list;
+      std::string cluster = "";
+      CephInitParameters iparams = ceph_argparse_early_args(
+        args, CEPH_ENTITY_TYPE_CLIENT,
+        &cluster, &conf_file_list);
+
+      cct = common_preinit(iparams, CODE_ENVIRONMENT_UTILITY, {});
+      dpp = new DoutPrefix(cct->get(), dout_subsys, "SSD backed Cache backend Test: ");
+    }
+
+    CephContext* cct;
+    DoutPrefixProvider* dpp;
+};
+
+class SSDDriverFixture: public ::testing::Test {
+  protected:
+    virtual void SetUp() {
+        rgw::cache::Partition partition_info{.name = "d4n", .type = "read-cache", .location = "rgw_d4n_datacache", .size = 5368709120};
+        cacheDriver = new rgw::cache::SSDDriver{partition_info};
+
+        ASSERT_NE(cacheDriver, nullptr);
+
+        cacheDriver->initialize(env->cct, env->dpp);
+
+        bl.append("This is testdata");
+        attrVal.append("attrVal");
+        attrs.insert({"user.rgw.attrName", attrVal});
+
+        updateAttrVal1.append("newAttrVal1");
+        updateAttrVal2.append("newAttrVal2");
+        update_attrs.insert({"user.rgw.attrName", updateAttrVal1});
+        update_attrs.insert({"user.rgw.testAttr", updateAttrVal2});
+
+        del_attrs = attrs;
+    } 
+
+    virtual void TearDown() {
+      delete cacheDriver;
+    }
+
+    rgw::cache::SSDDriver* cacheDriver;
+
+    net::io_context io;
+
+    bufferlist bl;
+    bufferlist attrVal, updateAttrVal1, updateAttrVal2;
+    rgw::sal::Attrs attrs;
+    rgw::sal::Attrs update_attrs;
+    rgw::sal::Attrs del_attrs;
+};
+
+TEST_F(SSDDriverFixture, PutAndGet)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+        rgw::sal::Attrs attrs = {};
+        ASSERT_EQ(0, cacheDriver->put(env->dpp, "testPutGet", bl, bl.length(), attrs, optional_yield{io, yield}));
+        bufferlist ret;
+        rgw::sal::Attrs get_attrs;
+        ASSERT_EQ(0, cacheDriver->get(env->dpp, "testPutGet", 0, bl.length(), ret, get_attrs, optional_yield{io, yield}));
+        EXPECT_EQ(ret, bl);
+        EXPECT_EQ(get_attrs.size(), 0);
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, AppendData)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+        rgw::sal::Attrs attrs = {};
+        ASSERT_EQ(0, cacheDriver->put(env->dpp, "testAppend", bl, bl.length(), attrs, optional_yield{io, yield}));
+    
+        bufferlist bl_append;
+        bl_append.append(" xyz");
+        ASSERT_EQ(0, cacheDriver->append_data(env->dpp, "testAppend", bl_append, optional_yield{io, yield}));
+    
+        bufferlist ret;
+        bl.append(bl_append);
+        rgw::sal::Attrs get_attrs;
+        ASSERT_EQ(0, cacheDriver->get(env->dpp, "testAppend", 0, bl.length(), ret, get_attrs, optional_yield{io, yield}));
+        EXPECT_EQ(ret, bl);
+        EXPECT_EQ(get_attrs.size(), 0);
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, SetGetAttrs)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+        ASSERT_EQ(0, cacheDriver->put(env->dpp, "testSetGetAttrs", bl, bl.length(), attrs, optional_yield{io, yield}));
+        bufferlist ret;
+        rgw::sal::Attrs ret_attrs;
+        ASSERT_EQ(0, cacheDriver->get(env->dpp, "testSetGetAttrs", 0, bl.length(), ret, ret_attrs, optional_yield{io, yield}));
+        EXPECT_EQ(ret, bl);
+        EXPECT_EQ(ret_attrs.size(), 1);
+        for (auto& it : ret_attrs) {
+          EXPECT_EQ(it.first, "user.rgw.attrName");
+          EXPECT_EQ(it.second, attrVal);
+        }
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, UpdateAttrs)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+        ASSERT_EQ(0, cacheDriver->put(env->dpp, "testUpdateAttrs", bl, bl.length(), attrs, optional_yield{io, yield}));
+        ASSERT_EQ(0, cacheDriver->update_attrs(env->dpp, "testUpdateAttrs", update_attrs, optional_yield{io, yield}));
+        rgw::sal::Attrs get_attrs;
+        ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testUpdateAttrs", get_attrs, optional_yield{io, yield}));
+        EXPECT_EQ(get_attrs.size(), 2);
+        EXPECT_EQ(get_attrs["user.rgw.attrName"], updateAttrVal1);
+        EXPECT_EQ(get_attrs["user.rgw.testAttr"], updateAttrVal2);
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, SetGetAttr)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+      rgw::sal::Attrs attrs = {};
+      ASSERT_EQ(0, cacheDriver->put(env->dpp, "testSetGetAttr", bl, bl.length(), attrs, optional_yield{io, yield}));
+      std::string attr_name = "user.ssd.testattr";
+      std::string attr_val = "testattrVal";
+      ASSERT_EQ(0, cacheDriver->set_attr(env->dpp, "testSetGetAttr", attr_name, attr_val, optional_yield{io, yield}));
+      ASSERT_EQ(attr_val, cacheDriver->get_attr(env->dpp, "testSetGetAttr", attr_name, optional_yield{io, yield}));
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, DeleteAttr)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+      rgw::sal::Attrs attrs = {};
+      ASSERT_EQ(0, cacheDriver->put(env->dpp, "testDeleteAttr", bl, bl.length(), attrs, optional_yield{io, yield}));
+      std::string attr_name = "user.ssd.testattr";
+      std::string attr_val = "testattrVal";
+      ASSERT_EQ(0, cacheDriver->set_attr(env->dpp, "testDeleteAttr", attr_name, attr_val, optional_yield{io, yield}));
+      ASSERT_EQ(attr_val, cacheDriver->get_attr(env->dpp, "testDeleteAttr", attr_name, optional_yield{io, yield}));
+
+      ASSERT_EQ(0, cacheDriver->delete_attr(env->dpp, "testDeleteAttr", attr_name));
+      ASSERT_EQ("", cacheDriver->get_attr(env->dpp, "testDeleteAttr", attr_name, optional_yield{io, yield}));
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, DeleteAttrs)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+      ASSERT_EQ(0, cacheDriver->put(env->dpp, "testDeleteAttr", bl, bl.length(), attrs, optional_yield{io, yield}));
+      rgw::sal::Attrs ret_attrs;
+      ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testDeleteAttr", ret_attrs, optional_yield{io, yield}));
+      EXPECT_EQ(ret_attrs.size(), 1);
+      for (auto& it : ret_attrs) {
+        EXPECT_EQ(it.first, "user.rgw.attrName");
+        EXPECT_EQ(it.second, attrVal);
+      }
+
+      ASSERT_EQ(0, cacheDriver->delete_attrs(env->dpp, "testDeleteAttr", del_attrs, optional_yield{io, yield}));
+      ret_attrs.clear();
+      ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testDeleteAttr", del_attrs, optional_yield{io, yield}));
+      EXPECT_EQ(ret_attrs.size(), 0);
+    });
+
+    io.run();
+}
+
+TEST_F(SSDDriverFixture, DeleteData)
+{
+    spawn::spawn(io, [this] (spawn::yield_context yield) {
+        rgw::sal::Attrs attrs = {};
+        ASSERT_EQ(0, cacheDriver->put(env->dpp, "testDeleteData", bl, bl.length(), attrs, optional_yield{io, yield}));
+        bufferlist ret;
+        rgw::sal::Attrs get_attrs;
+        ASSERT_EQ(0, cacheDriver->get(env->dpp, "testDeleteData", 0, bl.length(), ret, get_attrs, optional_yield{io, yield}));
+        EXPECT_EQ(ret, bl);
+        EXPECT_EQ(get_attrs.size(), 0);
+        ASSERT_EQ(0, cacheDriver->delete_data(env->dpp, "testDeleteData", optional_yield{io, yield}));
+        ASSERT_EQ(-ENOENT, cacheDriver->get(env->dpp, "testDeleteData", 0, bl.length(), ret, get_attrs, optional_yield{io, yield}));
+    });
+
+    io.run();
+}
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  env = new Environment();
+  ::testing::AddGlobalTestEnvironment(env);
+
+  return RUN_ALL_TESTS();
+}
\ No newline at end of file