From: Pritha Srivastava Date: Wed, 8 Nov 2023 11:01:04 +0000 (+0530) Subject: rgw/cache: adding unittests for ssd backed cache backend, and X-Git-Tag: testing/wip-batrick-testing-20240411.154038~45^2~38 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=48da43dd5f68d687089e037d82ca6586c2f9ccf2;p=ceph-ci.git rgw/cache: adding unittests for ssd backed cache backend, and fixing bugs that the tests revealed. Signed-off-by: Pritha Srivastava --- diff --git a/src/rgw/rgw_ssd_driver.cc b/src/rgw/rgw_ssd_driver.cc index 6dd536ef58d..56a9fb1a5e0 100644 --- a/src/rgw/rgw_ssd_driver.cc +++ b/src/rgw/rgw_ssd_driver.cc @@ -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) diff --git a/src/test/rgw/CMakeLists.txt b/src/test/rgw/CMakeLists.txt index 3367314f482..8e19e75be59 100644 --- a/src/test/rgw/CMakeLists.txt +++ b/src/test/rgw/CMakeLists.txt @@ -137,6 +137,23 @@ add_executable(unittest_rgw_ratelimit test_rgw_ratelimit.cc $ +#include + +#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 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