diff --git a/score/kvs/error.cpp b/score/kvs/error.cpp index 2351af15a..fa43aedb7 100644 --- a/score/kvs/error.cpp +++ b/score/kvs/error.cpp @@ -18,81 +18,55 @@ namespace score::mw::per::kvs /*********************** Error Implementation *********************/ std::string_view KvsErrorDomain::MessageFor(const score::result::ErrorCode& code) const noexcept { - std::string_view msg; switch (static_cast(code)) { case ErrorCode::UnmappedError: - msg = "Error that was not yet mapped"; - break; + return "Error that was not yet mapped"; case ErrorCode::FileNotFound: - msg = "File not found"; - break; + return "File not found"; case ErrorCode::KvsFileReadError: - msg = "KVS file read error"; - break; + return "KVS file read error"; case ErrorCode::KvsHashFileReadError: - msg = "KVS hash file read error"; - break; + return "KVS hash file read error"; case ErrorCode::JsonParserError: - msg = "JSON parser error"; - break; + return "JSON parser error"; case ErrorCode::JsonGeneratorError: - msg = "JSON generator error"; - break; + return "JSON generator error"; case ErrorCode::PhysicalStorageFailure: - msg = "Physical storage failure"; - break; + return "Physical storage failure"; case ErrorCode::IntegrityCorrupted: - msg = "Integrity corrupted"; - break; + return "Integrity corrupted"; case ErrorCode::ValidationFailed: - msg = "Validation failed"; - break; + return "Validation failed"; case ErrorCode::EncryptionFailed: - msg = "Encryption failed"; - break; + return "Encryption failed"; case ErrorCode::ResourceBusy: - msg = "Resource is busy"; - break; + return "Resource is busy"; case ErrorCode::OutOfStorageSpace: - msg = "Out of storage space"; - break; + return "Out of storage space"; case ErrorCode::QuotaExceeded: - msg = "Quota exceeded"; - break; + return "Quota exceeded"; case ErrorCode::AuthenticationFailed: - msg = "Authentication failed"; - break; + return "Authentication failed"; case ErrorCode::KeyNotFound: - msg = "Key not found"; - break; + return "Key not found"; case ErrorCode::KeyDefaultNotFound: - msg = "Key default value not found"; - break; + return "Key default value not found"; case ErrorCode::SerializationFailed: - msg = "Serialization failed"; - break; + return "Serialization failed"; case ErrorCode::InvalidSnapshotId: - msg = "Invalid snapshot ID"; - break; + return "Invalid snapshot ID"; case ErrorCode::ConversionFailed: - msg = "Conversion failed"; - break; + return "Conversion failed"; case ErrorCode::MutexLockFailed: - msg = "Mutex failed"; - break; + return "Mutex failed"; case ErrorCode::InvalidValueType: - msg = "Invalid value type"; - break; + return "Invalid value type"; case ErrorCode::InvalidKey: - msg = "Key is not valid"; - break; + return "Key is not valid"; default: - msg = "Unknown Error!"; - break; + return "Unknown Error!"; } - - return msg; } namespace diff --git a/score/kvs/internal/kvs_helper.cpp b/score/kvs/internal/kvs_helper.cpp index 75da86a15..ad11172cb 100644 --- a/score/kvs/internal/kvs_helper.cpp +++ b/score/kvs/internal/kvs_helper.cpp @@ -77,19 +77,9 @@ std::array get_hash_bytes(const std::string& data) /* Wrapper Function to check, if Hash is valid*/ bool check_hash(const std::string& data_calculate, std::istream& data_parse) { - bool result; uint32_t calculated_hash = calculate_hash_adler32(data_calculate); uint32_t parsed_hash = parse_hash_adler32(data_parse); - if (calculated_hash == parsed_hash) - { - result = true; - } - else - { - result = false; - } - - return result; + return calculated_hash == parsed_hash; } /*********************** Standalone Helper Functions *********************/ @@ -97,189 +87,147 @@ bool check_hash(const std::string& data_calculate, std::istream& data_parse) /* Helper Function for Any -> KVSValue conversion */ score::Result any_to_kvsvalue(const score::json::Any& any) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); - if (auto o = any.As(); o.has_value()) + auto o = any.As(); + if (!o.has_value()) { - const auto& objAny = o.value().get(); - auto type = objAny.find("t"); - auto value = objAny.find("v"); - if (type != objAny.end() && value != objAny.end()) - { - if (auto typeStr = type->second.As(); typeStr.has_value()) - { - const std::string_view typeStrV = typeStr.value().get(); - const score::json::Any& valueAny = value->second; + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } - if (typeStrV == "i32") - { - if (auto n = valueAny.As(); n.has_value()) - { - result = KvsValue(static_cast(n.value())); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "u32") - { - if (auto n = valueAny.As(); n.has_value()) - { - result = KvsValue(static_cast(n.value())); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "i64") - { - if (auto n = valueAny.As(); n.has_value()) - { - result = KvsValue(static_cast(n.value())); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "u64") - { - if (auto n = valueAny.As(); n.has_value()) - { - result = KvsValue(static_cast(n.value())); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "f64") - { - if (auto n = valueAny.As(); n.has_value()) - { - result = KvsValue(n.value()); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "bool") - { - if (auto b = valueAny.As(); b.has_value()) - { - result = KvsValue(b.value()); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "str") - { - if (auto s = valueAny.As(); s.has_value()) - { - result = KvsValue(s.value().get()); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "null") - { - if (valueAny.As().has_value()) - { - result = KvsValue(nullptr); - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "arr") - { - if (auto l = valueAny.As(); l.has_value()) - { - KvsValue::Array arr; - bool error = false; - for (const auto& elem : l.value().get()) - { - auto conv = any_to_kvsvalue(elem); - if (!conv) - { - error = true; - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - break; - } - arr.emplace_back(std::move(conv.value())); - } - if (!error) - { - result = KvsValue(std::move(arr)); - } - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else if (typeStrV == "obj") - { - if (auto obj = valueAny.As(); obj.has_value()) - { - KvsValue::Object map; - bool error = false; - for (const auto& [key, valAny] : obj.value().get()) - { - auto conv = any_to_kvsvalue(valAny); - if (!conv) - { - error = true; - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - break; - } - map.emplace_back(std::string(key.GetAsStringView()), std::move(conv.value())); - } - if (!error) - { - result = KvsValue(std::move(map)); - } - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else - { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - } - } - else + const auto& objAny = o.value().get(); + auto type = objAny.find("t"); + auto value = objAny.find("v"); + if (type == objAny.end() || value == objAny.end()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + + auto typeStr = type->second.As(); + if (!typeStr.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + + const std::string_view typeStrV = typeStr.value().get(); + const score::json::Any& valueAny = value->second; + + if (typeStrV == "i32") + { + auto n = valueAny.As(); + if (!n.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(static_cast(n.value())); + } + else if (typeStrV == "u32") + { + auto n = valueAny.As(); + if (!n.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(static_cast(n.value())); + } + else if (typeStrV == "i64") + { + auto n = valueAny.As(); + if (!n.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(static_cast(n.value())); + } + else if (typeStrV == "u64") + { + auto n = valueAny.As(); + if (!n.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(static_cast(n.value())); + } + else if (typeStrV == "f64") + { + auto n = valueAny.As(); + if (!n.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(n.value()); + } + else if (typeStrV == "bool") + { + auto b = valueAny.As(); + if (!b.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(b.value()); + } + else if (typeStrV == "str") + { + auto s = valueAny.As(); + if (!s.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(s.value().get()); + } + else if (typeStrV == "null") + { + if (!valueAny.As().has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + return KvsValue(nullptr); + } + else if (typeStrV == "arr") + { + auto l = valueAny.As(); + if (!l.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + KvsValue::Array arr; + for (const auto& elem : l.value().get()) + { + auto conv = any_to_kvsvalue(elem); + if (!conv) { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); + return score::MakeUnexpected(ErrorCode::InvalidValueType); } + arr.emplace_back(std::move(conv.value())); + } + return KvsValue(std::move(arr)); + } + else if (typeStrV == "obj") + { + auto obj = valueAny.As(); + if (!obj.has_value()) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); } - else + KvsValue::Object map; + for (const auto& [key, valAny] : obj.value().get()) { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); + auto conv = any_to_kvsvalue(valAny); + if (!conv) + { + return score::MakeUnexpected(ErrorCode::InvalidValueType); + } + map.emplace_back(std::string(key.GetAsStringView()), std::move(conv.value())); } + return KvsValue(std::move(map)); } else { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); + return score::MakeUnexpected(ErrorCode::InvalidValueType); } - - return result; } /* Helper Function for KVSValue -> Any conversion */ score::Result kvsvalue_to_any(const KvsValue& kv) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); - bool error = false; score::json::Object obj; switch (kv.getType()) { @@ -340,16 +288,11 @@ score::Result kvsvalue_to_any(const KvsValue& kv) auto conv = kvsvalue_to_any(elem); if (!conv) { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - error = true; - break; + return score::MakeUnexpected(ErrorCode::InvalidValueType); } list.push_back(std::move(conv.value())); } - if (!error) - { - obj.emplace("v", score::json::Any(std::move(list))); - } + obj.emplace("v", score::json::Any(std::move(list))); break; } case KvsValue::Type::Object: @@ -361,32 +304,20 @@ score::Result kvsvalue_to_any(const KvsValue& kv) auto conv = kvsvalue_to_any(value); if (!conv) { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - error = true; - break; + return score::MakeUnexpected(ErrorCode::InvalidValueType); } inner_obj.emplace(key, std::move(conv.value())); } - if (!error) - { - obj.emplace("v", score::json::Any(std::move(inner_obj))); - } + obj.emplace("v", score::json::Any(std::move(inner_obj))); break; } default: { - result = score::MakeUnexpected(ErrorCode::InvalidValueType); - error = true; - break; + return score::MakeUnexpected(ErrorCode::InvalidValueType); } } - if (!error) - { - result = score::json::Any(std::move(obj)); - } - - return result; + return score::json::Any(std::move(obj)); } } /* namespace score::mw::per::kvs */ diff --git a/score/kvs/kvs.cpp b/score/kvs/kvs.cpp index 6d2adc45b..b435286a2 100644 --- a/score/kvs/kvs.cpp +++ b/score/kvs/kvs.cpp @@ -123,59 +123,41 @@ Kvs& Kvs::operator=(Kvs&& other) noexcept /* Helper Function to parse JSON data for open_json*/ score::Result Kvs::parse_json_data(const std::string& data) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); auto any_res = parser_->FromBuffer(data); - if (!any_res) { - result = score::MakeUnexpected(ErrorCode::JsonParserError); + return score::MakeUnexpected(ErrorCode::JsonParserError); } - else + + score::json::Any root = std::move(any_res).value(); + auto obj = root.As(); + if (!obj.has_value()) { - score::json::Any root = std::move(any_res).value(); - KeyValueMap result_value; + return score::MakeUnexpected(ErrorCode::JsonParserError); + } - if (auto obj = root.As(); obj.has_value()) + KeyValueMap result_value; + for (const auto& element : obj.value().get()) + { + auto sv = element.first.GetAsStringView(); + std::string key(sv.data(), sv.size()); + + // Validate key. + if (!is_key_valid(sv)) { - bool error = false; - for (const auto& element : obj.value().get()) - { - auto sv = element.first.GetAsStringView(); - std::string key(sv.data(), sv.size()); - - // Validate key. - if (!is_key_valid(sv)) - { - logger_->LogError() << "Provided key is not valid" << key; - result = score::MakeUnexpected(ErrorCode::InvalidKey); - error = true; - break; - } - - auto conv = any_to_kvsvalue(element.second); - if (!conv) - { - result = score::MakeUnexpected(static_cast(*conv.error())); - error = true; - break; - } - else - { - result_value.emplace(std::move(key), std::move(conv.value())); - } - } - if (!error) - { - result = std::move(result_value); - } + logger_->LogError() << "Provided key is not valid" << key; + return score::MakeUnexpected(ErrorCode::InvalidKey); } - else + + auto conv = any_to_kvsvalue(element.second); + if (!conv) { - result = score::MakeUnexpected(ErrorCode::JsonParserError); + return score::MakeUnexpected(static_cast(*conv.error())); } + result_value.emplace(std::move(key), std::move(conv.value())); } - return result; + return result_value; } /* Open and read JSON File */ @@ -184,10 +166,6 @@ score::Result Kvs::open_json(const score::filesystem::Path& pr { score::filesystem::Path json_file = prefix.Native() + ".json"; score::filesystem::Path hash_file = prefix.Native() + ".hash"; - std::string data; - bool error = false; /* Error flag */ - bool new_kvs = false; /* Flag to check if new KVS file is created*/ - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); /* Read JSON file */ ifstream in(json_file.CStr()); @@ -196,66 +174,42 @@ score::Result Kvs::open_json(const score::filesystem::Path& pr if (need_file == OpenJsonNeedFile::Required) { logger_->LogError() << "error: file" << json_file << "could not be read"; - error = true; - result = score::MakeUnexpected(ErrorCode::KvsFileReadError); + return score::MakeUnexpected(ErrorCode::KvsFileReadError); } else { logger_->LogInfo() << "file" << json_file << "not found, using empty data"; - new_kvs = true; - result = score::Result({}); + return KeyValueMap{}; } } - else - { - ostringstream ss; - ss << in.rdbuf(); - data = ss.str(); - } + + ostringstream ss; + ss << in.rdbuf(); + const std::string data = ss.str(); /* Verify JSON Hash */ - if ((!error) && (!new_kvs)) + ifstream hin(hash_file.CStr(), ios::binary); + if (!hin) { - ifstream hin(hash_file.CStr(), ios::binary); - if (!hin) - { - logger_->LogError() << "error: hash file" << hash_file << "could not be read"; - error = true; - result = score::MakeUnexpected(ErrorCode::KvsHashFileReadError); - } - else - { - bool valid_hash = check_hash(data, hin); - if (!valid_hash) - { - logger_->LogError() << "error: KVS data corrupted:" << json_file << hash_file; - error = true; - result = score::MakeUnexpected(ErrorCode::ValidationFailed); - } - else - { - logger_->LogInfo() << "JSON data has valid hash"; - } - } + logger_->LogError() << "error: hash file" << hash_file << "could not be read"; + return score::MakeUnexpected(ErrorCode::KvsHashFileReadError); + } + if (!check_hash(data, hin)) + { + logger_->LogError() << "error: KVS data corrupted:" << json_file << hash_file; + return score::MakeUnexpected(ErrorCode::ValidationFailed); } + logger_->LogInfo() << "JSON data has valid hash"; /* Parse JSON Data */ - if ((!error) && (!new_kvs)) + auto parse_res = parse_json_data(data); + if (!parse_res) { - auto parse_res = parse_json_data(data); - if (!parse_res) - { - logger_->LogError() << "error: parsing JSON data failed"; - error = true; - result = score::MakeUnexpected(static_cast(*parse_res.error())); - } - else - { - result = std::move(parse_res.value()); - } + logger_->LogError() << "error: parsing JSON data failed"; + return score::MakeUnexpected(static_cast(*parse_res.error())); } - return result; + return std::move(parse_res.value()); } /* Open KVS Instance */ @@ -267,10 +221,6 @@ score::Result Kvs::open(const InstanceId& instance_id, const std::optional& max_storage_bytes, std::size_t snapshot_max_count) { - score::Result result = - score::MakeUnexpected(ErrorCode::UnmappedError); /* Redundant initialization needed, since Resul would call - the implicitly-deleted default constructor of KVS */ - score::filesystem::Path base_path(dir); score::filesystem::Path filename_prefix = base_path / ("kvs_" + std::to_string(instance_id.id)); const score::filesystem::Path filename_default = filename_prefix.Native() + "_default"; @@ -289,208 +239,149 @@ score::Result Kvs::open(const InstanceId& instance_id, if (!default_res) { - result = score::MakeUnexpected(static_cast( + return score::MakeUnexpected(static_cast( *default_res.error())); /* Dereferences the Error class to its underlying code -> error.h*/ } - else + + score::Result kvs_res{}; + + if (need_kvs != OpenNeedKvs::Ignored) { - score::Result kvs_res{}; + kvs_res = kvs.open_json( + filename_kvs, need_kvs == OpenNeedKvs::Required ? OpenJsonNeedFile::Required : OpenJsonNeedFile::Optional); + } - if (need_kvs != OpenNeedKvs::Ignored) - { - kvs_res = kvs.open_json( - filename_kvs, - need_kvs == OpenNeedKvs::Required ? OpenJsonNeedFile::Required : OpenJsonNeedFile::Optional); - } + if (!kvs_res) + { + return score::MakeUnexpected(static_cast(*kvs_res.error())); + } - if (!kvs_res) - { - result = score::MakeUnexpected(static_cast(*kvs_res.error())); - } - else - { - kvs.kvs_ = std::move(kvs_res.value()); - kvs.default_values_ = std::move(default_res.value()); - kvs.filename_prefix_ = filename_prefix; - - /* comp_req__kvs__snapshot_max_num_cfg: the maximum is limited to the range - 0..KVS_MAX_SNAPSHOTS_UPPER_BOUND. A larger request is clamped and reported, - so that the caller can see the value it actually got. */ - kvs.max_snapshots_ = snapshot_max_count; - if (snapshot_max_count > KVS_MAX_SNAPSHOTS_UPPER_BOUND) - { - kvs.logger_->LogWarn() << "snapshot_max_count" << snapshot_max_count << "exceeds upper bound" - << KVS_MAX_SNAPSHOTS_UPPER_BOUND << "- clamped"; - kvs.max_snapshots_ = KVS_MAX_SNAPSHOTS_UPPER_BOUND; - } + kvs.kvs_ = std::move(kvs_res.value()); + kvs.default_values_ = std::move(default_res.value()); + kvs.filename_prefix_ = filename_prefix; - kvs.logger_->LogInfo() << "[instance=" << instance_id.id << "]" - << "[snapshot=" << snapshot_id.id << "]" - << "[maxSnapshotCount=" << kvs.max_snapshots_ << "] KVS opened"; - result = std::move(kvs); - } + /* comp_req__kvs__snapshot_max_num_cfg: the maximum is limited to the range + 0..KVS_MAX_SNAPSHOTS_UPPER_BOUND. A larger request is clamped and reported, + so that the caller can see the value it actually got. */ + kvs.max_snapshots_ = snapshot_max_count; + if (snapshot_max_count > KVS_MAX_SNAPSHOTS_UPPER_BOUND) + { + kvs.logger_->LogWarn() << "snapshot_max_count" << snapshot_max_count << "exceeds upper bound" + << KVS_MAX_SNAPSHOTS_UPPER_BOUND << "- clamped"; + kvs.max_snapshots_ = KVS_MAX_SNAPSHOTS_UPPER_BOUND; } - return result; + kvs.logger_->LogInfo() << "[instance=" << instance_id.id << "]" + << "[snapshot=" << snapshot_id.id << "]" + << "[maxSnapshotCount=" << kvs.max_snapshots_ << "] KVS opened"; + return kvs; } /* Reset KVS to initial state*/ score::Result Kvs::reset() { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) - { - kvs_.clear(); - result = score::Result{}; - } - else + if (!lock.owns_lock()) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - return result; + kvs_.clear(); + return {}; } /* Retrieve all keys in the KVS*/ score::Result> Kvs::get_all_keys() { - score::Result> result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) { - std::vector keys; - keys.reserve(kvs_.size()); - for (const auto& [key, _] : kvs_) - { - keys.emplace_back(key); - } - result = std::move(keys); + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - else + + std::vector keys; + keys.reserve(kvs_.size()); + for (const auto& [key, _] : kvs_) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + keys.emplace_back(key); } - - return result; + return keys; } /* Check if a key exists*/ score::Result Kvs::key_exists(const std::string_view key) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) - { - auto search = - kvs_.find(std::string(key)); /* unordered_map find() needs string and doesnt work with string_view, - workaround for c++20: heterogeneous lookup (applies to more functions) */ - if (search != kvs_.end()) - { - result = true; - } - else - { - result = false; - } - } - else + if (!lock.owns_lock()) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - return result; + /* unordered_map find() needs string and doesnt work with string_view, + workaround for c++20: heterogeneous lookup (applies to more functions) */ + return kvs_.find(std::string(key)) != kvs_.end(); } /* Retrieve the value associated with a key*/ score::Result Kvs::get_value(const std::string_view key) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock_kvs(kvs_mutex_, std::try_to_lock); - if (lock_kvs.owns_lock()) + if (!lock_kvs.owns_lock()) { - auto search_kvs = kvs_.find(std::string(key)); - if (search_kvs != kvs_.end()) - { - result = search_kvs->second; - } - else - { - result = score::MakeUnexpected(ErrorCode::KeyNotFound); - } + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - else + + auto search_kvs = kvs_.find(std::string(key)); + if (search_kvs == kvs_.end()) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::KeyNotFound); } - - return result; + return search_kvs->second; } /*Retrieve the default value associated with a key*/ score::Result Kvs::get_default_value(const std::string_view key) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); - auto search = default_values_.find(std::string(key)); - if (search != default_values_.end()) - { - result = search->second; - } - else + if (search == default_values_.end()) { - result = score::MakeUnexpected(ErrorCode::KeyNotFound); + return score::MakeUnexpected(ErrorCode::KeyNotFound); } - - return result; + return search->second; } /* Resets a Key to its default value (Deletes written key if default is available) */ score::Result Kvs::reset_key(const std::string_view key) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock_kvs(kvs_mutex_, std::try_to_lock); if (!lock_kvs.owns_lock()) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - else + + if (default_values_.find(std::string(key)) == default_values_.end()) { - auto search_default = default_values_.find(std::string(key)); - if (search_default == default_values_.end()) - { - result = score::MakeUnexpected(ErrorCode::KeyDefaultNotFound); - } - else - { - auto search_kvs = kvs_.find(std::string(key)); - if (search_kvs != kvs_.end()) - { - (void)kvs_.erase( - std::string(key)); /* Return Value ignored, since its already secured, that the key exists*/ - result = score::Result{}; - } - else - { - result = score::Result{}; - } - } + return score::MakeUnexpected(ErrorCode::KeyDefaultNotFound); } - return result; + (void)kvs_.erase(std::string(key)); /* Return value ignored: a key that was never written needs no reset */ + return {}; } /* Check if the value wasn't set yet and uses its default value */ score::Result Kvs::is_value_default(const std::string_view key) const { std::string key_str{key}; - if (kvs_.find(key_str) != kvs_.end()) { + if (kvs_.find(key_str) != kvs_.end()) + { return false; } - else if (default_values_.find(key_str) != default_values_.end()) { + else if (default_values_.find(key_str) != default_values_.end()) + { return true; } - else { + else + { return score::MakeUnexpected(ErrorCode::KeyNotFound); } } @@ -505,91 +396,65 @@ score::Result Kvs::set_value(const std::string_view key, const KvsValue& v return score::MakeUnexpected(ErrorCode::InvalidKey); } - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) { - kvs_.insert_or_assign(std::string(key), value); - result = score::Result{}; - } - else - { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - return result; + kvs_.insert_or_assign(std::string(key), value); + return {}; } /* Remove a key-value pair*/ score::Result Kvs::remove_key(const std::string_view key) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) { - const auto erased = kvs_.erase(std::string(key)); - if (erased > 0U) - { - result = score::Result{}; - } - else - { - result = score::MakeUnexpected(ErrorCode::KeyNotFound); - } + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - else + + if (kvs_.erase(std::string(key)) == 0U) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::KeyNotFound); } - - return result; + return {}; } score::Result Kvs::remove_all_keys() { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) { - kvs_.clear(); - result = score::Result{}; - } - else - { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - return result; + kvs_.clear(); + return {}; } /* Drop all in-memory changes by reloading the persisted KVS file */ score::Result Kvs::discard_pending_changes() { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) { - /* Snapshot 0 is the current persisted state: written by flush(), read by open(). */ - const score::filesystem::Path kvs_path = filename_prefix_.Native() + "_0"; - - /* Optional: a KVS opened without an existing file and never flushed discards to empty. */ - auto data_res = open_json(kvs_path, OpenJsonNeedFile::Optional); - if (!data_res) - { - result = score::MakeUnexpected(static_cast(*data_res.error())); - } - else - { - kvs_ = std::move(data_res.value()); - result = score::Result{}; - } + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - else + + /* Snapshot 0 is the current persisted state: written by flush(), read by open(). */ + const score::filesystem::Path kvs_path = filename_prefix_.Native() + "_0"; + + /* Optional: a KVS opened without an existing file and never flushed discards to empty. */ + auto data_res = open_json(kvs_path, OpenJsonNeedFile::Optional); + if (!data_res) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(static_cast(*data_res.error())); } - return result; + kvs_ = std::move(data_res.value()); + return {}; } /* Helper: size of one file in bytes. A missing file counts as 0 bytes. */ @@ -606,8 +471,11 @@ score::Result Kvs::get_file_size(const score::filesystem::Path& file_pat /* File does not exist, its size is 0. This is not an error. */ return 0; } - logger_->LogError() << "Error: Could not get size of file" << file_path << ":" << ec.message(); - return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); + else + { + logger_->LogError() << "Error: Could not get size of file" << file_path << ":" << ec.message(); + return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); + } } return size; @@ -694,39 +562,33 @@ score::Result Kvs::write_and_sync(const std::string& path, const void* dat /* Helper Function to write JSON data to a file for flush process (also adds Hash file)*/ score::Result Kvs::write_json_data(const std::string& buf) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); score::filesystem::Path json_path{filename_prefix_.Native() + "_0.json"}; score::filesystem::Path dir = json_path.ParentPath(); - if (!dir.Empty()) + if (dir.Empty()) { - const auto create_path_res = filesystem_->standard->CreateDirectories(dir); - if (!create_path_res.has_value()) - { - result = score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); - } - else - { - /* Write JSON file */ - result = write_and_sync(json_path.Native(), buf.data(), buf.size()); - if (!result.has_value()) - { - return result; - } - - /* Write Hash File */ - std::array hash_bytes = get_hash_bytes(buf); - score::filesystem::Path fn_hash = filename_prefix_.Native() + "_0.hash"; - - result = write_and_sync(fn_hash.Native(), hash_bytes.data(), hash_bytes.size()); - } + logger_->LogError() << "Provided directory path is empty" << json_path; + return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); } - else + + const auto create_path_res = filesystem_->standard->CreateDirectories(dir); + if (!create_path_res.has_value()) { logger_->LogError() << "Failed to create directory for KVS file" << json_path; - result = score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); + return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); } - return result; + /* Write JSON file */ + auto json_res = write_and_sync(json_path.Native(), buf.data(), buf.size()); + if (!json_res.has_value()) + { + return json_res; + } + + /* Write Hash File */ + std::array hash_bytes = get_hash_bytes(buf); + score::filesystem::Path fn_hash = filename_prefix_.Native() + "_0.hash"; + + return write_and_sync(fn_hash.Native(), hash_bytes.data(), hash_bytes.size()); } /* Serialize the KVS and check the projected total against the storage limit */ @@ -827,37 +689,23 @@ score::Result Kvs::calculate_potential_size() /* Retrieve the snapshot count*/ score::Result Kvs::snapshot_count() const { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); size_t count = 0; - bool error = false; for (size_t idx = 0; idx < max_snapshots_; ++idx) { const score::filesystem::Path fname = filename_prefix_.Native() + "_" + to_string(idx) + ".json"; const auto fname_exists_res = filesystem_->standard->Exists(fname); - if (fname_exists_res) + if (!fname_exists_res) { - if (false == fname_exists_res.value()) - { - break; - } + return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); } - else + if (false == fname_exists_res.value()) { - error = true; break; } count = idx + 1; } - if (error) - { - result = score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); - } - else - { - result = count; - } - return result; + return count; } /* Retrieve the max snapshot count*/ @@ -869,159 +717,104 @@ size_t Kvs::snapshot_max_count() const /* Rotate Snapshots */ score::Result Kvs::snapshot_rotate() { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) + { + return score::MakeUnexpected(ErrorCode::MutexLockFailed); + } + + for (size_t idx = max_snapshots_; idx > 0; --idx) { - bool error = false; - for (size_t idx = max_snapshots_; idx > 0; --idx) + score::filesystem::Path hash_old = filename_prefix_.Native() + "_" + to_string(idx - 1) + ".hash"; + score::filesystem::Path hash_new = filename_prefix_.Native() + "_" + to_string(idx) + ".hash"; + score::filesystem::Path snap_old = filename_prefix_.Native() + "_" + to_string(idx - 1) + ".json"; + score::filesystem::Path snap_new = filename_prefix_.Native() + "_" + to_string(idx) + ".json"; + + logger_->LogInfo() << "rotating:" << snap_old << "->" << snap_new; + /* Rename hash */ + int32_t hash_rename = std::rename(hash_old.CStr(), hash_new.CStr()); + if ((0 != hash_rename) && (errno != ENOENT)) { - score::filesystem::Path hash_old = filename_prefix_.Native() + "_" + to_string(idx - 1) + ".hash"; - score::filesystem::Path hash_new = filename_prefix_.Native() + "_" + to_string(idx) + ".hash"; - score::filesystem::Path snap_old = filename_prefix_.Native() + "_" + to_string(idx - 1) + ".json"; - score::filesystem::Path snap_new = filename_prefix_.Native() + "_" + to_string(idx) + ".json"; - - logger_->LogInfo() << "rotating:" << snap_old << "->" << snap_new; - /* Rename hash */ - int32_t hash_rename = std::rename(hash_old.CStr(), hash_new.CStr()); - if (0 != hash_rename) - { - if (errno != ENOENT) - { - error = true; - logger_->LogError() << "error: could not rename hash file" << snap_old << "- Rename Errorcode" - << errno; - result = score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); - } - } - if (!error) - { - /* Rename snapshot */ - int32_t snap_rename = std::rename(snap_old.CStr(), snap_new.CStr()); - if (0 != snap_rename) - { - if (errno != ENOENT) - { - error = true; - logger_->LogError() - << "error: could not rename snapshot file" << snap_old << "- Rename Errorcode" << errno; - result = score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); - } - } - } - if (error) - { - break; - } + logger_->LogError() << "error: could not rename hash file" << snap_old << "- Rename Errorcode" << errno; + return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); } - if (!error) + + /* Rename snapshot */ + int32_t snap_rename = std::rename(snap_old.CStr(), snap_new.CStr()); + if ((0 != snap_rename) && (errno != ENOENT)) { - result = score::Result{}; + logger_->LogError() << "error: could not rename snapshot file" << snap_old << "- Rename Errorcode" << errno; + return score::MakeUnexpected(ErrorCode::PhysicalStorageFailure); } } - else - { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); - } - return result; + return {}; } /* Restore the key-value store from a snapshot*/ score::Result Kvs::snapshot_restore(const SnapshotId& snapshot_id) { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); std::unique_lock lock(kvs_mutex_, std::try_to_lock); - if (lock.owns_lock()) + if (!lock.owns_lock()) { - auto snapshot_count_res = snapshot_count(); - if (!snapshot_count_res) - { - result = score::MakeUnexpected(static_cast(*snapshot_count_res.error())); - } - else - { - /* Fail if the snapshot ID is the current KVS */ - if (0 == snapshot_id.id) - { - result = score::MakeUnexpected(ErrorCode::InvalidSnapshotId); - } - else if (snapshot_count_res.value() < snapshot_id.id) - { - result = score::MakeUnexpected(ErrorCode::InvalidSnapshotId); - } - else - { - score::filesystem::Path restore_path = filename_prefix_.Native() + "_" + to_string(snapshot_id.id); - auto data_res = open_json(restore_path, OpenJsonNeedFile::Required); - if (!data_res) - { - result = score::MakeUnexpected(static_cast(*data_res.error())); - } - else - { - kvs_ = std::move(data_res.value()); - result = score::Result{}; - } - } - } + return score::MakeUnexpected(ErrorCode::MutexLockFailed); } - else + + auto snapshot_count_res = snapshot_count(); + if (!snapshot_count_res) { - result = score::MakeUnexpected(ErrorCode::MutexLockFailed); + return score::MakeUnexpected(static_cast(*snapshot_count_res.error())); } - return result; + /* Fail if the snapshot ID is the current KVS or does not exist */ + if ((0 == snapshot_id.id) || (snapshot_count_res.value() < snapshot_id.id)) + { + return score::MakeUnexpected(ErrorCode::InvalidSnapshotId); + } + + score::filesystem::Path restore_path = filename_prefix_.Native() + "_" + to_string(snapshot_id.id); + auto data_res = open_json(restore_path, OpenJsonNeedFile::Required); + if (!data_res) + { + return score::MakeUnexpected(static_cast(*data_res.error())); + } + + kvs_ = std::move(data_res.value()); + return {}; } /* Get the filename for a snapshot*/ score::Result Kvs::get_kvs_filename(const SnapshotId& snapshot_id) const { score::filesystem::Path filename = filename_prefix_.Native() + "_" + std::to_string(snapshot_id.id) + ".json"; - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); const auto fname_exists_res = filesystem_->standard->Exists(filename); - if (fname_exists_res) + if (!fname_exists_res) { - if (false == fname_exists_res.value()) - { - result = score::MakeUnexpected(ErrorCode::FileNotFound); - } - else - { - result = filename; - } + return score::MakeUnexpected(static_cast(*fname_exists_res.error())); } - else + if (false == fname_exists_res.value()) { - result = score::MakeUnexpected(static_cast(*fname_exists_res.error())); + return score::MakeUnexpected(ErrorCode::FileNotFound); } - return result; + return filename; } /* Get the hash filename for a snapshot*/ score::Result Kvs::get_hash_filename(const SnapshotId& snapshot_id) const { score::filesystem::Path filename = filename_prefix_.Native() + "_" + std::to_string(snapshot_id.id) + ".hash"; - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); const auto fname_exists_res = filesystem_->standard->Exists(filename); - if (fname_exists_res) + if (!fname_exists_res) { - if (false == fname_exists_res.value()) - { - result = score::MakeUnexpected(ErrorCode::FileNotFound); - } - else - { - result = filename; - } + return score::MakeUnexpected(static_cast(*fname_exists_res.error())); } - else + if (false == fname_exists_res.value()) { - result = score::MakeUnexpected(static_cast(*fname_exists_res.error())); + return score::MakeUnexpected(ErrorCode::FileNotFound); } - return result; + return filename; } /* Get the combined on-disk size of the current KVS data and hash files */ diff --git a/score/kvs/kvsbuilder.cpp b/score/kvs/kvsbuilder.cpp index 3d7dfeb06..6646e63a7 100644 --- a/score/kvs/kvsbuilder.cpp +++ b/score/kvs/kvsbuilder.cpp @@ -65,23 +65,19 @@ KvsBuilder& KvsBuilder::snapshot_max_count(std::size_t max_count) score::Result KvsBuilder::build() { - score::Result result = score::MakeUnexpected(ErrorCode::UnmappedError); - /* Use current directory if empty */ if ("" == directory_) { directory_ = "./"; } - result = Kvs::open(instance_id_, - snapshot_id_, - need_defaults_, - need_kvs_, - std::move(directory_), - maximum_storage_bytes_, - max_snapshots_); - - return result; + return Kvs::open(instance_id_, + snapshot_id_, + need_defaults_, + need_kvs_, + std::move(directory_), + maximum_storage_bytes_, + max_snapshots_); } } /* namespace score::mw::per::kvs */