namespace rgw { namespace cache {
-static inline std::string get_file_path(const std::string& location, const std::string& key)
+static std::atomic<uint64_t> index{0};
+
+static std::vector<std::string> tokenize_key(std::string_view key)
{
- return location + "/" + key;
+ std::vector<std::string> tokens;
+ size_t start = 0, end = 0;
+ while ((end = key.find(CACHE_DELIM, start)) != std::string_view::npos) {
+ tokens.emplace_back(key.substr(start, end - start));
+ start = end + 1;
+ }
+ // Add the last token
+ if (start < key.length()) {
+ tokens.emplace_back(key.substr(start));
+ }
+ return tokens;
+}
+
+/*
+* Parses key to return directory path and file name
+*/
+static void parse_key(const DoutPrefixProvider* dpp, const std::string& location, const std::string& key, std::string& dir_path, std::string& file_name, bool& is_dirty, bool temp = false) {
+ ldpp_dout(dpp, 10) << __func__ << "() key is: " << key << dendl;
+ std::string bucket_id, object, version;
+ std::vector<std::string> parts = tokenize_key(key);
+ is_dirty = false;
+
+ ldpp_dout(dpp, 10) << __func__ << "() parts.size() is " << parts.size() << dendl;
+ //dirty blocks
+ if (parts.size() == 4 || parts.size() == 6) {
+ if (parts[0] == "D") {
+ is_dirty = true;
+ bucket_id = parts[1];
+ ldpp_dout(dpp, 10) << __func__ << "() bucket_id is " << bucket_id << dendl;
+ object = parts[3];
+ ldpp_dout(dpp, 10) << __func__ << "() object is " << object << dendl;
+ version = DIRTY_BLOCK_PREFIX + parts[2];
+ if (parts.size() == 6) { //has offset and length
+ version += CACHE_DELIM + parts[4] + CACHE_DELIM + parts[5];
+ }
+ if (temp) {
+ version += "_" + std::to_string(index++);
+ }
+ ldpp_dout(dpp, 10) << __func__ << "() version is " << version << dendl;
+ dir_path = location + "/" + bucket_id + "/" + object;
+ file_name = version;
+ ldpp_dout(dpp, 10) << __func__ << "() dir_path is " << dir_path << dendl;
+ }
+ }
+
+ //clean blocks
+ if (parts.size() == 3 || parts.size() == 5) {
+ bucket_id = parts[0];
+ ldpp_dout(dpp, 10) << __func__ << "() bucket_id is " << bucket_id << dendl;
+ object = parts[2];
+ ldpp_dout(dpp, 10) << __func__ << "() object is " << object << dendl;
+ version = parts[1];
+ if (parts.size() == 5) { //has offset and length
+ version += CACHE_DELIM + parts[3] + CACHE_DELIM + parts[4];
+ }
+ if (temp) {
+ version += "_" + std::to_string(index++);
+ }
+ ldpp_dout(dpp, 10) << __func__ << "() version is " << version << dendl;
+ dir_path = location + "/" + bucket_id + "/" + object;
+ file_name = version;
+ ldpp_dout(dpp, 10) << __func__ << "() dir_path is " << dir_path << dendl;
+ }
+ return;
+}
+
+static void create_directories(const DoutPrefixProvider* dpp, const std::string& dir_path)
+{
+ std::error_code ec;
+ if (!efs::exists(dir_path, ec)) {
+ if (!efs::create_directories(dir_path, ec)) {
+ ldpp_dout(dpp, 0) << "initialize::: ERROR creating directory: '" << dir_path <<
+ "' : " << ec.value() << dendl;
+ } else {
+ uid_t uid = dpp->get_cct()->get_set_uid();
+ gid_t gid = dpp->get_cct()->get_set_gid();
+
+ ldpp_dout(dpp, 5) << "initialize:: uid is " << uid << " and gid is " << gid << dendl;
+ ldpp_dout(dpp, 5) << "initialize:: changing permissions for directory: " << dendl;
+
+ if (uid) {
+ if (chown(dir_path.c_str(), uid, gid) == -1) {
+ ldpp_dout(dpp, 5) << "initialize: chown return error: " << strerror(errno) << dendl;
+ }
+
+ if (chmod(dir_path.c_str(), S_IRWXU|S_IRWXG|S_IRWXO) == -1) {
+ ldpp_dout(dpp, 5) << "initialize: chmod return error: " << strerror(errno) << dendl;
+ }
+ }
+ }
+ }
+}
+
+static inline std::string get_file_path(const DoutPrefixProvider* dpp, const std::string& dir_path, const std::string& file_name)
+{
+ return dir_path + "/" + file_name;
+}
+
+static std::string create_dirs_get_filepath_from_key(const DoutPrefixProvider* dpp, const std::string& location, const std::string& key, bool temp=false)
+{
+ std::string dir_path, file_name;
+ bool is_dirty;
+ parse_key(dpp, location, key, dir_path, file_name, is_dirty, temp);
+ create_directories(dpp, dir_path);
+ return get_file_path(dpp, dir_path, file_name);
+
}
int SSDDriver::initialize(const DoutPrefixProvider* dpp)
if (dpp->get_cct()->_conf->rgw_d4n_l1_evict_cache_on_start) {
return 0; //don't do anything as the cache directory must have been evicted during start-up
}
- for (auto const& dir_entry : std::filesystem::directory_iterator{partition_info.location}) {
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): dir_entry.path: " << dir_entry.path() << dendl;
- std::string file_name = dir_entry.path().filename();
- std::vector<std::string> parts;
- std::string part;
- bool parsed = false;
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): filename: " << file_name << dendl;
- try {
- std::stringstream ss(file_name);
- while (std::getline(ss, part, CACHE_DELIM)) {
- parts.push_back(part);
- }
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): parts.size(): " << parts.size() << dendl;
- //non-dirty or clean blocks - bucket_id, version, object_name in head block and offset, len in data blocks
- if (parts.size() == 3 || parts.size() == 5) {
- std::string key = file_name;
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): file_name: " << file_name << dendl;
-
- std::string version = url_decode(parts[1]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): version: " << version << dendl;
-
- uint64_t offset = 0, len = 0;
- if (parts.size() == 5) {
- offset = std::stoull(parts[3]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): offset: " << offset << dendl;
-
- len = std::stoull(parts[4]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): len: " << len << dendl;
- }
- std::string localWeightStr;
- auto ret = get_attr(dpp, file_name, RGW_CACHE_ATTR_LOCAL_WEIGHT, localWeightStr, null_yield);
- if (ret < 0) {
- ldpp_dout(dpp, 0) << "SSDCache: " << __func__ << "(): Failed to get attr: " << RGW_CACHE_ATTR_LOCAL_WEIGHT << dendl;
- } else {
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): localWeightStr: " << localWeightStr << dendl;
- }
- block_func(dpp, key, offset, len, version, false, null_yield, localWeightStr);
- parsed = true;
- }
- //dirty blocks - "D", bucket_id, version, object_name in head block and offset, len in data blocks
- if ((parts.size() == 4 || parts.size() == 6) && parts[0] == "D") {
- std::string prefix = DIRTY_BLOCK_PREFIX;
- if (file_name.starts_with(prefix)) {
- std::string key = file_name.substr(prefix.length());
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): key: " << key << dendl;
-
- bool dirty = true;
-
- std::string bucket_id = url_decode(parts[1]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): bucket_id: " << bucket_id << dendl;
-
- std::string version = url_decode(parts[2]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): version: " << version << dendl;
-
- std::string obj_name = url_decode(parts[3]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): obj_name: " << obj_name << dendl;
-
- uint64_t len = 0, offset = 0;
- std::string localWeightStr;
- if (parts.size() == 4) {
- rgw::sal::Attrs attrs;
- get_attrs(dpp, file_name, attrs, null_yield);
- std::string etag, bucket_name;
- uint64_t size = 0;
- time_t creationTime = time_t(nullptr);
- rgw_user user;
- rgw_obj_key obj_key;
- if (attrs.find(RGW_ATTR_ETAG) != attrs.end()) {
- etag = attrs[RGW_ATTR_ETAG].to_str();
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): etag: " << etag << dendl;
- }
- if (attrs.find(RGW_CACHE_ATTR_OBJECT_SIZE) != attrs.end()) {
- size = std::stoull(attrs[RGW_CACHE_ATTR_OBJECT_SIZE].to_str());
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): size: " << size << dendl;
- }
- if (attrs.find(RGW_CACHE_ATTR_MTIME) != attrs.end()) {
- creationTime = ceph::real_clock::to_time_t(ceph::real_clock::from_double(std::stod(attrs[RGW_CACHE_ATTR_MTIME].to_str())));
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): creationTime: " << creationTime << dendl;
- }
- if (attrs.find(RGW_ATTR_ACL) != attrs.end()) {
- bufferlist bl_acl = attrs[RGW_ATTR_ACL];
- RGWAccessControlPolicy policy;
- auto iter = bl_acl.cbegin();
- try {
- policy.decode(iter);
- } catch (buffer::error& err) {
- ldpp_dout(dpp, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
- continue;
+ std::string cache_location = partition_info.location;
+ if (cache_location.back() == '/') {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): cache_location: " << cache_location << dendl;
+ cache_location.pop_back();
+ }
+ for (auto const& dir_entry : efs::directory_iterator{partition_info.location}) {
+ std::string bucket_id, object_name;
+ if (dir_entry.is_directory()) {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Is directory, path: " << dir_entry.path() << dendl;
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): File Name: " << dir_entry.path().filename() << dendl;
+ bucket_id = dir_entry.path().filename();
+ for (auto const& sub_dir_entry : efs::directory_iterator{dir_entry.path()}) {
+ if (sub_dir_entry.is_directory()) {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Is directory, path: " << sub_dir_entry.path() << dendl;
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): File Name: " << sub_dir_entry.path().filename() << dendl;
+ object_name = sub_dir_entry.path().filename();
+ for (auto const& file_entry : efs::directory_iterator{sub_dir_entry.path()}) {
+ try {
+ if (file_entry.is_regular_file()) {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): filename: " << file_entry.path().filename() << dendl;
+ std::string file_name = file_entry.path().filename();
+ bool parsed = false;
+ std::vector<std::string> parts;
+ std::string part;
+ std::stringstream ss(file_name);
+ while (std::getline(ss, part, CACHE_DELIM)) {
+ parts.push_back(part);
+ }
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): parts.size(): " << parts.size() << dendl;
+ //non-dirty or clean blocks - version in head block and offset, len in data blocks
+ if (parts.size() == 1 || parts.size() == 3) {
+ std::string version = url_decode(parts[0]);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): version: " << version << dendl;
+
+ std::string key = url_encode(bucket_id, true) + CACHE_DELIM + url_encode(version, true) + CACHE_DELIM + url_encode(object_name, true);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): key: " << key << dendl;
+
+ uint64_t offset = 0, len = 0;
+ if (parts.size() == 3) {
+ offset = std::stoull(parts[1]);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): offset: " << offset << dendl;
+
+ len = std::stoull(parts[2]);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): len: " << len << dendl;
+
+ key = key + CACHE_DELIM + std::to_string(offset) + CACHE_DELIM + std::to_string(len);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): key: " << key << dendl;
+ }
+ std::string localWeightStr;
+ auto ret = get_attr(dpp, file_entry.path(), RGW_CACHE_ATTR_LOCAL_WEIGHT, localWeightStr, null_yield);
+ if (ret < 0) {
+ ldpp_dout(dpp, 0) << "SSDCache: " << __func__ << "(): Failed to get attr: " << RGW_CACHE_ATTR_LOCAL_WEIGHT << dendl;
+ } else {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): localWeightStr: " << localWeightStr << dendl;
+ }
+ block_func(dpp, key, offset, len, version, false, null_yield, localWeightStr);
+ parsed = true;
+ }
+ //dirty blocks - "D", version in head block and offset, len in data blocks
+ if ((parts.size() == 2 || parts.size() == 4) && parts[0] == "D") {
+ std::string prefix = DIRTY_BLOCK_PREFIX;
+ if (file_name.starts_with(prefix)) {
+ bool dirty = true;
+
+ std::string version = url_decode(parts[1]);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): version: " << version << dendl;
+
+ std::string key = url_encode(bucket_id, true) + CACHE_DELIM + url_encode(version, true) + CACHE_DELIM + url_encode(object_name, true);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): key: " << key << dendl;
+
+ uint64_t len = 0, offset = 0;
+ std::string localWeightStr;
+ if (parts.size() == 2) {
+ rgw::sal::Attrs attrs;
+ get_attrs(dpp, file_entry.path(), attrs, null_yield);
+ std::string etag, bucket_name;
+ uint64_t size = 0;
+ time_t creationTime = time_t(nullptr);
+ rgw_user user;
+ rgw_obj_key obj_key;
+ if (attrs.find(RGW_ATTR_ETAG) != attrs.end()) {
+ etag = attrs[RGW_ATTR_ETAG].to_str();
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): etag: " << etag << dendl;
+ }
+ if (attrs.find(RGW_CACHE_ATTR_OBJECT_SIZE) != attrs.end()) {
+ size = std::stoull(attrs[RGW_CACHE_ATTR_OBJECT_SIZE].to_str());
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): size: " << size << dendl;
+ }
+ if (attrs.find(RGW_CACHE_ATTR_MTIME) != attrs.end()) {
+ creationTime = ceph::real_clock::to_time_t(ceph::real_clock::from_double(std::stod(attrs[RGW_CACHE_ATTR_MTIME].to_str())));
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): creationTime: " << creationTime << dendl;
+ }
+ if (attrs.find(RGW_ATTR_ACL) != attrs.end()) {
+ bufferlist bl_acl = attrs[RGW_ATTR_ACL];
+ RGWAccessControlPolicy policy;
+ auto iter = bl_acl.cbegin();
+ try {
+ policy.decode(iter);
+ } catch (buffer::error& err) {
+ ldpp_dout(dpp, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
+ continue;
+ }
+ user = std::get<rgw_user>(policy.get_owner().id);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): rgw_user: " << user.to_str() << dendl;
+ }
+ obj_key.name = object_name;
+ if (attrs.find(RGW_CACHE_ATTR_VERSION_ID) != attrs.end()) {
+ std::string instance = attrs[RGW_CACHE_ATTR_VERSION_ID].to_str();
+ if (instance != "null") {
+ obj_key.instance = instance;
+ }
+ }
+ if (attrs.find(RGW_CACHE_ATTR_OBJECT_NS) != attrs.end()) {
+ obj_key.ns = attrs[RGW_CACHE_ATTR_OBJECT_NS].to_str();
+ }
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): rgw_obj_key: " << obj_key.get_oid() << dendl;
+ if (attrs.find(RGW_CACHE_ATTR_BUCKET_NAME) != attrs.end()) {
+ bucket_name = attrs[RGW_CACHE_ATTR_BUCKET_NAME].to_str();
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): bucket_name: " << bucket_name << dendl;
+ }
+
+ if (attrs.find(RGW_CACHE_ATTR_LOCAL_WEIGHT) != attrs.end()) {
+ localWeightStr = attrs[RGW_CACHE_ATTR_LOCAL_WEIGHT].to_str();
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): localWeightStr: " << localWeightStr << dendl;
+ }
+
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): calling func for: " << key << dendl;
+ obj_func(dpp, key, version, dirty, size, creationTime, user, etag, bucket_name, bucket_id, obj_key, null_yield);
+ block_func(dpp, key, offset, len, version, dirty, null_yield, localWeightStr);
+ parsed = true;
+ } //end-if part.size() == 2
+ if (parts.size() == 4) {
+ offset = std::stoull(parts[2]);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): offset: " << offset << dendl;
+
+ len = std::stoull(parts[3]);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): len: " << len << dendl;
+
+ key = key + CACHE_DELIM + std::to_string(offset) + CACHE_DELIM + std::to_string(len);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): key: " << key << dendl;
+
+ std::string localWeightStr;
+ auto ret = get_attr(dpp, file_entry.path(), RGW_CACHE_ATTR_LOCAL_WEIGHT, localWeightStr, null_yield);
+ if (ret < 0) {
+ ldpp_dout(dpp, 0) << "SSDCache: " << __func__ << "(): Failed to get attr: " << RGW_CACHE_ATTR_LOCAL_WEIGHT << dendl;
+ } else {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): localWeightStr: " << localWeightStr << dendl;
+ }
+ block_func(dpp, key, offset, len, version, dirty, null_yield, localWeightStr);
+ parsed = true;
+ }
+ } //end-if file_name.starts_with
+ } //end-if parts.size() == 2 || parts.size() == 4
+ if (!parsed) {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Unable to parse file_name: " << file_name << dendl;
+ continue;
+ }
}
- user = std::get<rgw_user>(policy.get_owner().id);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): rgw_user: " << user.to_str() << dendl;
- }
- obj_key.name = obj_name;
- if (attrs.find(RGW_CACHE_ATTR_VERSION_ID) != attrs.end()) {
- std::string instance = attrs[RGW_CACHE_ATTR_VERSION_ID].to_str();
- if (instance != "null") {
- obj_key.instance = instance;
- }
- }
- if (attrs.find(RGW_CACHE_ATTR_OBJECT_NS) != attrs.end()) {
- obj_key.ns = attrs[RGW_CACHE_ATTR_OBJECT_NS].to_str();
- }
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): rgw_obj_key: " << obj_key.get_oid() << dendl;
- if (attrs.find(RGW_CACHE_ATTR_BUCKET_NAME) != attrs.end()) {
- bucket_name = attrs[RGW_CACHE_ATTR_BUCKET_NAME].to_str();
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): bucket_name: " << bucket_name << dendl;
- }
-
- if (attrs.find(RGW_CACHE_ATTR_LOCAL_WEIGHT) != attrs.end()) {
- localWeightStr = attrs[RGW_CACHE_ATTR_LOCAL_WEIGHT].to_str();
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): localWeightStr: " << localWeightStr << dendl;
- }
-
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): calling func for: " << key << dendl;
- obj_func(dpp, key, version, dirty, size, creationTime, user, etag, bucket_name, bucket_id, obj_key, null_yield);
- block_func(dpp, key, offset, len, version, dirty, null_yield, localWeightStr);
- parsed = true;
- } //end-if part.size() == 4
- if (parts.size() == 6) {
- offset = std::stoull(parts[4]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): offset: " << offset << dendl;
-
- len = std::stoull(parts[5]);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): len: " << len << dendl;
- std::string localWeightStr;
- auto ret = get_attr(dpp, file_name, RGW_CACHE_ATTR_LOCAL_WEIGHT, localWeightStr, null_yield);
- if (ret < 0) {
- ldpp_dout(dpp, 0) << "SSDCache: " << __func__ << "(): Failed to get attr: " << RGW_CACHE_ATTR_LOCAL_WEIGHT << dendl;
- } else {
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): localWeightStr: " << localWeightStr << dendl;
+ }//end - try
+ catch(...) {
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Execption while parsing entry: " << file_entry.path() << dendl;
+ continue;
}
- block_func(dpp, key, offset, len, version, dirty, null_yield, localWeightStr);
- parsed = true;
}
- } //end-if file_name.starts_with
- } //end-if parts.size() == 4 || parts.size() == 6
- if (!parsed) {
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Unable to parse file_name: " << file_name << dendl;
- continue;
+ }
}
- }//end-try
- catch(...) {
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Execption while parsing file_name: " << file_name << dendl;
- continue;
}
}
int SSDDriver::get(const DoutPrefixProvider* dpp, const std::string& key, off_t offset, uint64_t len, bufferlist& bl, rgw::sal::Attrs& attrs, optional_yield y)
{
char buffer[len];
- std::string location = get_file_path(partition_info.location, key);
+ std::string location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
ldpp_dout(dpp, 20) << __func__ << "(): location=" << location << dendl;
FILE *cache_file = nullptr;
int r = 0;
int SSDDriver::append_data(const DoutPrefixProvider* dpp, const::std::string& key, const bufferlist& bl_data, optional_yield y)
{
bufferlist src = bl_data;
- std::string location = get_file_path(partition_info.location, key);
+ std::string location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
ldpp_dout(dpp, 20) << __func__ << "(): location=" << location << dendl;
FILE *cache_file = nullptr;
auto p = Op::create(ex, handler);
auto& op = p->user_data;
- std::string location = get_file_path(partition_info.location, key);
+ std::string location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
int ret = op.prepare_libaio_read_op(dpp, location, read_ofs, read_len, p.get());
auto p = Op::create(ex, handler);
auto& op = p->user_data;
- std::string location = get_file_path(partition_info.location, key);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
+ op.file_path = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): op.file_path=" << op.file_path << dendl;
+
+ op.temp_file_path = create_dirs_get_filepath_from_key(dpp, partition_info.location, key, true);
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): op.temp_file_path=" << op.temp_file_path << dendl;
int r = 0;
bufferlist src = bl;
- std::string temp_key = key + "_" + std::to_string(index++);
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): temp key=" << temp_key << dendl;
- r = op.prepare_libaio_write_op(dpp, src, len, temp_key, partition_info.location);
+ r = op.prepare_libaio_write_op(dpp, src, len, op.temp_file_path);
op.cb->aio_sigevent.sigev_notify = SIGEV_THREAD;
op.cb->aio_sigevent.sigev_notify_function = SSDDriver::AsyncWriteRequest::libaio_write_cb;
op.cb->aio_sigevent.sigev_notify_attributes = nullptr;
op.cb->aio_sigevent.sigev_value.sival_ptr = (void*)p.get();
- op.key = key;
- op.temp_key = temp_key;
op.dpp = dpp;
op.priv_data = this;
op.attrs = std::move(attrs);
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): ::aio_write(), r=" << r << dendl;
if(r < 0) {
auto ec = boost::system::error_code{-r, boost::system::system_category()};
- ceph::async::post(std::move(p), ec);
+ ceph::async::dispatch(std::move(p), ec);
} else {
(void)p.release();
}
int SSDDriver::delete_data(const DoutPrefixProvider* dpp, const::std::string& key, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string dir_path, file_name;
+ bool is_dirty;
+ parse_key(dpp, partition_info.location, key, dir_path, file_name, is_dirty);
+ std::string location = get_file_path(dpp, dir_path, file_name);
+ ldpp_dout(dpp, 20) << "INFO: delete_data::file to remove: " << location << dendl;
+ //Remove file
if (!efs::remove(location)) {
ldpp_dout(dpp, 0) << "ERROR: delete_data::remove has failed to remove the file: " << location << dendl;
return -EIO;
}
+ //Remove directory if empty, removes object directory
+ if (efs::is_empty(dir_path)) {
+ ldpp_dout(dpp, 20) << "INFO: delete_data::object directory to remove: " << dir_path << dendl;
+ if (!efs::remove(dir_path)) {
+ ldpp_dout(dpp, 0) << "ERROR: delete_data::remove has failed to remove the directory: " << dir_path << dendl;
+ return -EIO;
+ }
+ }
+ auto pos = dir_path.find_last_of('/');
+ if (pos != std::string::npos) {
+ dir_path.erase(pos, (dir_path.length() - pos));
+
+ //Remove bucket directory
+ if (efs::is_empty(dir_path)) {
+ ldpp_dout(dpp, 20) << "INFO: delete_data::bucket directory to remove: " << dir_path << dendl;
+ if (!efs::remove(dir_path)) {
+ ldpp_dout(dpp, 0) << "ERROR: delete_data::remove has failed to remove the directory: " << dir_path << dendl;
+ return -EIO;
+ }
+ }
+ }
efs::space_info space = efs::space(partition_info.location);
this->free_space = space.available;
int SSDDriver::rename(const DoutPrefixProvider* dpp, const::std::string& oldKey, const::std::string& newKey, optional_yield y)
{
- std::string old_file_path = get_file_path(partition_info.location, oldKey);
- std::string new_file_path = get_file_path(partition_info.location, newKey);
+ std::string old_file_path = create_dirs_get_filepath_from_key(dpp, partition_info.location, oldKey);
+ std::string new_file_path = create_dirs_get_filepath_from_key(dpp, partition_info.location, newKey);
int ret = std::rename(old_file_path.c_str(), new_file_path.c_str());
if (ret < 0) {
ldpp_dout(dpp, 0) << "SSDDriver: ERROR: failed to rename the file: " << old_file_path << dendl;
}
-int SSDDriver::AsyncWriteRequest::prepare_libaio_write_op(const DoutPrefixProvider *dpp, bufferlist& bl, unsigned int len, std::string key, std::string cache_location)
+int SSDDriver::AsyncWriteRequest::prepare_libaio_write_op(const DoutPrefixProvider *dpp, bufferlist& bl, unsigned int len, std::string file_path)
{
- std::string location = get_file_path(cache_location, key);
int r = 0;
- ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Write To Cache, location=" << location << dendl;
+ ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): Write To Cache, location=" << file_path << dendl;
cb.reset(new struct aiocb);
memset(cb.get(), 0, sizeof(struct aiocb));
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- r = fd = TEMP_FAILURE_RETRY(::open(location.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode));
+ r = fd = TEMP_FAILURE_RETRY(::open(file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode));
if (fd < 0) {
- ldpp_dout(dpp, 0) << "ERROR: AsyncWriteRequest::prepare_libaio_write_op: open file failed, errno=" << errno << ", location='" << location.c_str() << "'" << dendl;
+ ldpp_dout(dpp, 0) << "ERROR: AsyncWriteRequest::prepare_libaio_write_op: open file failed, errno=" << errno << ", location='" << file_path.c_str() << "'" << dendl;
return r;
}
if (dpp->get_cct()->_conf->rgw_d4n_l1_fadvise != POSIX_FADV_NORMAL)
void SSDDriver::AsyncWriteRequest::libaio_write_cb(sigval sigval) {
auto p = std::unique_ptr<Completion>{static_cast<Completion*>(sigval.sival_ptr)};
auto op = std::move(p->user_data);
- ldpp_dout(op.dpp, 20) << "INFO: AsyncWriteRequest::libaio_write_cb: key: " << op.key << dendl;
+ ldpp_dout(op.dpp, 20) << "INFO: AsyncWriteRequest::libaio_write_cb: key: " << op.file_path << dendl;
int ret = -aio_error(op.cb.get());
boost::system::error_code ec;
if (ret < 0) {
if (op.attrs.size() > 0) {
//TODO - fix yield_context
optional_yield y{null_yield};
- attr_ret = op.priv_data->set_attrs(op.dpp, op.temp_key, op.attrs, y);
+ attr_ret = op.priv_data->set_attrs(op.dpp, op.temp_file_path, op.attrs, y);
if (attr_ret < 0) {
ldpp_dout(op.dpp, 0) << "ERROR: AsyncWriteRequest::libaio_write_yield_cb::set_attrs: failed to set attrs, ret = " << attr_ret << dendl;
ec.assign(-ret, boost::system::system_category());
efs::space_info space = efs::space(partition_info.location);
op.priv_data->set_free_space(op.dpp, space.available);
- std::string new_path = get_file_path(partition_info.location, op.key);
- std::string old_path = get_file_path(partition_info.location, op.temp_key);
- ldpp_dout(op.dpp, 20) << "INFO: AsyncWriteRequest::libaio_write_yield_cb: temp_key: " << op.temp_key << dendl;
+ ldpp_dout(op.dpp, 20) << "INFO: AsyncWriteRequest::libaio_write_yield_cb: new_path: " << op.file_path << dendl;
+ ldpp_dout(op.dpp, 20) << "INFO: AsyncWriteRequest::libaio_write_yield_cb: old_path: " << op.temp_file_path << dendl;
- ret = std::rename(old_path.c_str(), new_path.c_str());
+ ret = std::rename(op.temp_file_path.c_str(), op.file_path.c_str());
if (ret < 0) {
ret = errno;
ldpp_dout(op.dpp, 0) << "ERROR: put::rename: failed to rename file: " << ret << dendl;
int SSDDriver::update_attrs(const DoutPrefixProvider* dpp, const std::string& key, const rgw::sal::Attrs& attrs, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
for (auto& it : attrs) {
int SSDDriver::delete_attrs(const DoutPrefixProvider* dpp, const std::string& key, rgw::sal::Attrs& del_attrs, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
for (auto& it : del_attrs) {
int SSDDriver::get_attrs(const DoutPrefixProvider* dpp, const std::string& key, rgw::sal::Attrs& attrs, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location;
+ // a hack to avoid calling create_dirs_get_filepath_from_key in case the path is already formed
+ if(key.find(partition_info.location, 0) == 0) {
+ location = key;
+ } else {
+ location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
+ }
+
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
char namebuf[64 * 1024];
continue;
}
std::string attr_value;
- get_attr(dpp, key, attr_name, attr_value, y);
+ get_attr(dpp, location, attr_name, attr_value, y);
bufferlist bl_value;
bl_value.append(attr_value);
attrs.emplace(std::move(attr_name), std::move(bl_value));
int SSDDriver::set_attrs(const DoutPrefixProvider* dpp, const std::string& key, const rgw::sal::Attrs& attrs, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location;
+ // a hack to avoid calling create_dirs_get_filepath_from_key in case the path is already formed
+ if(key.find(partition_info.location, 0) == 0) {
+ location = key;
+ } else {
+ location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
+ }
+
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
for (auto& [attr_name, attr_val_bl] : attrs) {
int SSDDriver::get_attr(const DoutPrefixProvider* dpp, const std::string& key, const std::string& attr_name, std::string& attr_val, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location;
+ // a hack to avoid calling create_dirs_get_filepath_from_key in case the path is already formed
+ if(key.find(partition_info.location, 0) == 0) {
+ location = key;
+ } else {
+ location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
+ }
+
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): get_attr: key: " << attr_name << dendl;
int SSDDriver::set_attr(const DoutPrefixProvider* dpp, const std::string& key, const std::string& attr_name, const std::string& attr_val, optional_yield y)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location;
+ // a hack to avoid calling create_dirs_get_filepath_from_key in case the path is already formed
+ if(key.find(partition_info.location, 0) == 0) {
+ location = key;
+ } else {
+ location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
+ }
+
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): set_attr: key: " << attr_name << " val: " << attr_val << dendl;
int SSDDriver::delete_attr(const DoutPrefixProvider* dpp, const std::string& key, const std::string& attr_name)
{
- std::string location = get_file_path(partition_info.location, key);
+ std::string location = create_dirs_get_filepath_from_key(dpp, partition_info.location, key);
ldpp_dout(dpp, 20) << "SSDCache: " << __func__ << "(): location=" << location << dendl;
auto ret = removexattr(location.c_str(), attr_name.c_str());
return flush(dpp, std::move(c));
}
+int flush(const DoutPrefixProvider* dpp, rgw::AioResultList&& results, optional_yield y) {
+ int r = rgw::check_for_errors(results);
+
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+
class Environment* env;
class Environment : public ::testing::Environment {
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
rgw::sal::Attrs attrs = {};
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testPutGet", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#objName#0#4096", bl, bl.length(), attrs, yield));
bufferlist ret;
rgw::sal::Attrs get_attrs;
- ASSERT_EQ(0, cacheDriver->get(env->dpp, "testPutGet", 0, bl.length(), ret, get_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->get(env->dpp, "bucketid#version#objName#0#4096", 0, bl.length(), ret, get_attrs, yield));
EXPECT_EQ(ret, bl);
EXPECT_EQ(get_attrs.size(), 0);
}, rethrow);
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
rgw::sal::Attrs attrs = {};
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testAppend", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testAppend#0#4096", bl, bl.length(), attrs, yield));
bufferlist bl_append;
bl_append.append(" xyz");
- ASSERT_EQ(0, cacheDriver->append_data(env->dpp, "testAppend", bl_append, yield));
+ ASSERT_EQ(0, cacheDriver->append_data(env->dpp, "bucketid#version#testAppend#0#4096", bl_append, 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, yield));
+ ASSERT_EQ(0, cacheDriver->get(env->dpp, "bucketid#version#testAppend#0#4096", 0, bl.length(), ret, get_attrs, yield));
EXPECT_EQ(ret, bl);
EXPECT_EQ(get_attrs.size(), 0);
}, rethrow);
TEST_F(SSDDriverFixture, SetGetAttrs)
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testSetGetAttrs", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testSetGetAttrs", bl, bl.length(), attrs, yield));
bufferlist ret;
rgw::sal::Attrs ret_attrs;
- ASSERT_EQ(0, cacheDriver->get(env->dpp, "testSetGetAttrs", 0, bl.length(), ret, ret_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->get(env->dpp, "bucketid#version#testSetGetAttrs", 0, bl.length(), ret, ret_attrs, yield));
EXPECT_EQ(ret, bl);
EXPECT_EQ(ret_attrs.size(), 1);
for (auto& it : ret_attrs) {
TEST_F(SSDDriverFixture, UpdateAttrs)
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testUpdateAttrs", bl, bl.length(), attrs, yield));
- ASSERT_EQ(0, cacheDriver->update_attrs(env->dpp, "testUpdateAttrs", update_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testUpdateAttrs", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->update_attrs(env->dpp, "bucketid#version#testUpdateAttrs", update_attrs, yield));
rgw::sal::Attrs get_attrs;
- ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testUpdateAttrs", get_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "bucketid#version#testUpdateAttrs", get_attrs, yield));
EXPECT_EQ(get_attrs.size(), 2);
EXPECT_EQ(get_attrs["user.rgw.attrName"], updateAttrVal1);
EXPECT_EQ(get_attrs["user.rgw.testAttr"], updateAttrVal2);
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
rgw::sal::Attrs attrs = {};
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testSetGetAttr", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testSetGetAttr", bl, bl.length(), attrs, 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, yield));
+ ASSERT_EQ(0, cacheDriver->set_attr(env->dpp, "bucketid#version#testSetGetAttr", attr_name, attr_val, yield));
std::string attr_val_ret;
- ASSERT_EQ(0, cacheDriver->get_attr(env->dpp, "testSetGetAttr", attr_name, attr_val_ret, yield));
+ ASSERT_EQ(0, cacheDriver->get_attr(env->dpp, "bucketid#version#testSetGetAttr", attr_name, attr_val_ret, yield));
ASSERT_EQ(attr_val, attr_val_ret);
}, rethrow);
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
rgw::sal::Attrs attrs = {};
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testDeleteAttr", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testDeleteAttr", bl, bl.length(), attrs, 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, yield));
+ ASSERT_EQ(0, cacheDriver->set_attr(env->dpp, "bucketid#version#testDeleteAttr", attr_name, attr_val, yield));
std::string attr_val_ret;
- ASSERT_EQ(0, cacheDriver->get_attr(env->dpp, "testDeleteAttr", attr_name, attr_val_ret, yield));
+ ASSERT_EQ(0, cacheDriver->get_attr(env->dpp, "bucketid#version#testDeleteAttr", attr_name, attr_val_ret, yield));
ASSERT_EQ(attr_val, attr_val_ret);
attr_val_ret.clear();
- ASSERT_EQ(0, cacheDriver->delete_attr(env->dpp, "testDeleteAttr", attr_name));
- ASSERT_EQ(ENODATA, cacheDriver->get_attr(env->dpp, "testDeleteAttr", attr_name, attr_val_ret, yield));
+ ASSERT_EQ(0, cacheDriver->delete_attr(env->dpp, "bucketid#version#testDeleteAttr", attr_name));
+ ASSERT_EQ(ENODATA, cacheDriver->get_attr(env->dpp, "bucketid#version#testDeleteAttr", attr_name, attr_val_ret, yield));
ASSERT_EQ("", attr_val_ret);
}, rethrow);
TEST_F(SSDDriverFixture, DeleteAttrs)
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testDeleteAttr", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testDeleteAttr", bl, bl.length(), attrs, yield));
rgw::sal::Attrs ret_attrs;
- ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testDeleteAttr", ret_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "bucketid#version#testDeleteAttr", ret_attrs, 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, yield));
+ ASSERT_EQ(0, cacheDriver->delete_attrs(env->dpp, "bucketid#version#testDeleteAttr", del_attrs, yield));
ret_attrs.clear();
- ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "testDeleteAttr", del_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->get_attrs(env->dpp, "bucketid#version#testDeleteAttr", del_attrs, yield));
EXPECT_EQ(ret_attrs.size(), 0);
}, rethrow);
{
boost::asio::spawn(io, [this] (boost::asio::yield_context yield) {
rgw::sal::Attrs attrs = {};
- ASSERT_EQ(0, cacheDriver->put(env->dpp, "testDeleteData", bl, bl.length(), attrs, yield));
+ ASSERT_EQ(0, cacheDriver->put(env->dpp, "bucketid#version#testDeleteData", bl, bl.length(), attrs, yield));
bufferlist ret;
rgw::sal::Attrs get_attrs;
- ASSERT_EQ(0, cacheDriver->get(env->dpp, "testDeleteData", 0, bl.length(), ret, get_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->get(env->dpp, "bucketid#version#testDeleteData", 0, bl.length(), ret, get_attrs, yield));
EXPECT_EQ(ret, bl);
EXPECT_EQ(get_attrs.size(), 0);
- ASSERT_EQ(0, cacheDriver->delete_data(env->dpp, "testDeleteData", yield));
- ASSERT_EQ(-ENOENT, cacheDriver->get(env->dpp, "testDeleteData", 0, bl.length(), ret, get_attrs, yield));
+ ASSERT_EQ(0, cacheDriver->delete_data(env->dpp, "bucketid#version#testDeleteData", yield));
+ ASSERT_EQ(-ENOENT, cacheDriver->get(env->dpp, "bucketid#version#testDeleteData", 0, bl.length(), ret, get_attrs, yield));
}, rethrow);
io.run();
rgw::sal::Attrs attrs = {};
const uint64_t window_size = env->cct->_conf->rgw_put_obj_min_window_size;
std::unique_ptr<rgw::Aio> aio = rgw::make_throttle(window_size, yield);
- auto results = cacheDriver->put_async(env->dpp, yield, aio.get(), "testPutAsync", bl, bl.length(), attrs, bl.length(), 0);
+ auto results = cacheDriver->put_async(env->dpp, yield, aio.get(), "bucketid#version#testPutAsync", bl, bl.length(), attrs, bl.length(), 0);
+ auto r = flush(env->dpp, std::move(results), yield);
drain(env->dpp, aio.get());
+ EXPECT_EQ(r, 0);
}, rethrow);
io.run();