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<std::string> redisValues;
/* Creating a redisValues of the entry's properties */
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 {
}
}
+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<int> 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<std::string> 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<std::string, std::string>{{field, value}});
+ response<int> 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);
}
endpoint = endpoint + host + "_";
}
- endpoint.pop_back();
+ if (!endpoint.empty())
+ endpoint.pop_back();
+
redisValues.push_back(endpoint);
redisValues.push_back("objName");
endpoint = endpoint + host + "_";
}
- endpoint.pop_back();
+ if (!endpoint.empty())
+ endpoint.pop_back();
+
redisValues.push_back(endpoint);
try {
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;
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;
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<connection>(boost::asio::make_strand(io_context));
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";
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<connection> conn;
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<std::string>,
+ 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) {