From 667bb10020a097aff5fbea8295aead30cb69cb30 Mon Sep 17 00:00:00 2001 From: Samarah Date: Thu, 9 Nov 2023 14:28:07 +0000 Subject: [PATCH] d4n/directory: Add `ObjectDirectory::update_field` method Signed-off-by: Samarah --- src/rgw/driver/d4n/d4n_directory.cc | 84 ++++++++++++++++++++++++++--- src/rgw/driver/d4n/d4n_directory.h | 5 +- src/test/rgw/test_d4n_directory.cc | 28 ++++++++++ 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/src/rgw/driver/d4n/d4n_directory.cc b/src/rgw/driver/d4n/d4n_directory.cc index a518417e19b24..b0971349698d0 100644 --- a/src/rgw/driver/d4n/d4n_directory.cc +++ b/src/rgw/driver/d4n/d4n_directory.cc @@ -74,8 +74,8 @@ void ObjectDirectory::shutdown() int ObjectDirectory::set(CacheObj* object, optional_yield y) { std::string key = build_index(object); - /* Every set will be treated as new */ // or maybe, if key exists, simply return? -Sam - std::string endpoint = cct->_conf->rgw_d4n_host + ":" + std::to_string(cct->_conf->rgw_d4n_port); + /* Every set will be treated as new */ + std::string endpoint; std::list redisValues; /* Creating a redisValues of the entry's properties */ @@ -88,6 +88,17 @@ int ObjectDirectory::set(CacheObj* object, optional_yield y) { redisValues.push_back("dirty"); redisValues.push_back(std::to_string(object->dirty)); redisValues.push_back("objHosts"); + + for (auto const& host : object->hostsList) { + if (endpoint.empty()) + endpoint = host + "_"; + else + endpoint = endpoint + host + "_"; + } + + if (!endpoint.empty()) + endpoint.pop_back(); + redisValues.push_back(endpoint); try { @@ -223,6 +234,63 @@ int ObjectDirectory::del(CacheObj* object, optional_yield y) { } } +int ObjectDirectory::update_field(CacheObj* object, std::string field, std::string value, optional_yield y) { + std::string key = build_index(object); + + if (exist_key(object, y)) { + try { + /* Ensure field exists */ + { + boost::system::error_code ec; + request req; + req.push("HEXISTS", key, field); + response resp; + + redis_exec(conn, ec, req, resp, y); + + if (!std::get<0>(resp).value() || (bool)ec) + return -1; + } + + if (field == "objHosts") { + /* Append rather than overwrite */ + boost::system::error_code ec; + request req; + req.push("HGET", key, field); + response resp; + + redis_exec(conn, ec, req, resp, y); + + if (!std::get<0>(resp).value().size() || (bool)ec) + return -1; + + std::get<0>(resp).value() += "_"; + std::get<0>(resp).value() += value; + value = std::get<0>(resp).value(); + } + + { + boost::system::error_code ec; + request req; + req.push_range("HSET", key, std::map{{field, value}}); + response resp; + + redis_exec(conn, ec, req, resp, y); + + if ((bool)ec) { + return -1; + } + + return std::get<0>(resp).value(); + } + } catch(std::exception &e) { + return -1; + } + } else { + return -2; + } +} + std::string BlockDirectory::build_index(CacheBlock* block) { return block->cacheObj.bucketName + "_" + block->cacheObj.objName + "_" + std::to_string(block->blockID) + "_" + std::to_string(block->size); } @@ -276,7 +344,9 @@ int BlockDirectory::set(CacheBlock* block, optional_yield y) { endpoint = endpoint + host + "_"; } - endpoint.pop_back(); + if (!endpoint.empty()) + endpoint.pop_back(); + redisValues.push_back(endpoint); redisValues.push_back("objName"); @@ -297,7 +367,9 @@ int BlockDirectory::set(CacheBlock* block, optional_yield y) { endpoint = endpoint + host + "_"; } - endpoint.pop_back(); + if (!endpoint.empty()) + endpoint.pop_back(); + redisValues.push_back(endpoint); try { @@ -474,7 +546,7 @@ int BlockDirectory::update_field(CacheBlock* block, std::string field, std::stri return -1; } - if (field == "blockHosts") { // Need one for object hosts? -Sam + if (field == "blockHosts") { /* Append rather than overwrite */ boost::system::error_code ec; request req; @@ -503,7 +575,7 @@ int BlockDirectory::update_field(CacheBlock* block, std::string field, std::stri return -1; } - return std::get<0>(resp).value(); /* Zero fields added since it is an update of an existing field */ + return std::get<0>(resp).value(); } } catch(std::exception &e) { return -1; diff --git a/src/rgw/driver/d4n/d4n_directory.h b/src/rgw/driver/d4n/d4n_directory.h index 5e6c620730fd9..b98859d70dbe9 100644 --- a/src/rgw/driver/d4n/d4n_directory.h +++ b/src/rgw/driver/d4n/d4n_directory.h @@ -40,7 +40,7 @@ class Directory { Directory() {} }; -class ObjectDirectory: public Directory { // weave into write workflow -Sam +class ObjectDirectory: public Directory { public: ObjectDirectory(net::io_context& io_context) { conn = std::make_shared(boost::asio::make_strand(io_context)); @@ -53,7 +53,7 @@ class ObjectDirectory: public Directory { // weave into write workflow -Sam this->cct = cct; config cfg; - cfg.addr.host = cct->_conf->rgw_d4n_host; // same or different address from block directory? -Sam + cfg.addr.host = cct->_conf->rgw_d4n_host; cfg.addr.port = std::to_string(cct->_conf->rgw_d4n_port); cfg.clientname = "D4N.ObjectDir"; @@ -73,6 +73,7 @@ class ObjectDirectory: public Directory { // weave into write workflow -Sam int get(CacheObj* object, optional_yield y); int copy(CacheObj* object, std::string copyName, std::string copyBucketName, optional_yield y); int del(CacheObj* object, optional_yield y); + int update_field(CacheObj* object, std::string field, std::string value, optional_yield y); private: std::shared_ptr conn; diff --git a/src/test/rgw/test_d4n_directory.cc b/src/test/rgw/test_d4n_directory.cc index 4ce35eaf1d2f5..dfb01de2e9461 100644 --- a/src/test/rgw/test_d4n_directory.cc +++ b/src/test/rgw/test_d4n_directory.cc @@ -271,6 +271,34 @@ TEST_F(ObjectDirectoryFixture, DelYield) io.run(); } +TEST_F(ObjectDirectoryFixture, UpdateFieldYield) +{ + spawn::spawn(io, [this] (spawn::yield_context yield) { + ASSERT_EQ(0, dir->set(obj, optional_yield{io, yield})); + ASSERT_EQ(0, dir->update_field(obj, "objName", "newTestName", optional_yield{io, yield})); + ASSERT_EQ(0, dir->update_field(obj, "objHosts", "127.0.0.1:5000", optional_yield{io, yield})); + dir->shutdown(); + + boost::system::error_code ec; + request req; + req.push("HMGET", "testBucket_testName", "objName", "objHosts"); + req.push("FLUSHALL"); + response< std::vector, + boost::redis::ignore_t> resp; + + conn->async_exec(req, resp, yield[ec]); + + ASSERT_EQ((bool)ec, false); + EXPECT_EQ(std::get<0>(resp).value()[0], "newTestName"); + EXPECT_EQ(std::get<0>(resp).value()[1], "127.0.0.1:6379_127.0.0.1:5000"); + + conn->cancel(); + }); + + io.run(); +} + + TEST_F(BlockDirectoryFixture, SetYield) { spawn::spawn(io, [this] (spawn::yield_context yield) { -- 2.39.5