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;
}
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()) {
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;
}
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;
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)
--- /dev/null
+#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