aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/error/error_attributes.cpp
diff options
context:
space:
mode:
authorarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-12-25 07:12:23 +0300
committerarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-12-25 07:31:55 +0300
commitb5dd91799751f9924acb7c17ddad16ddb2086bba (patch)
treef430b4e9f752af7411d5503bfcf823e9718056c2 /library/cpp/yt/error/error_attributes.cpp
parent75f1af270a6cf9a17b65fde6d12efbb94f235960 (diff)
downloadydb-b5dd91799751f9924acb7c17ddad16ddb2086bba.tar.gz
YT-21233: Adjust (To/From)ErrorAttributeValue CPOs, revert ConvertTo becoming CPO, move TErrorCode and TError to library/cpp/yt/error
\[nodiff:caesar\] List of changes: 1) Make `ConvertTo` a normal function again (basically, a revert of previous change). It turned out to be very inconvenient entry point 2) Introduce concept for "Primitive types" which are handled without yt/core module. Please note that inclusion of core **does not** affect work with primitive types (otherwise we would be facing and ODR violation). These are numerics, duration, instant, string-like objects and guid 3) Introduce `FromErrorAttributeValue` which is a substitute to `ConvertTo` with special behavior (see below) 4) Scheme for (de-)serialization has changed: 1) Primitive types are handled via `ConvertToTextYsonString` and `ConvertFromTextYsonString` 2) Other types are not supported without yt/core. Otherwise `ConvertToYsonString(value, EYsonFormat::Text)` used for serialization and `ConvertTo<T>(value)` for deserialization. 5) New format of attribute value storage allows to not care about concrete type of the attribute (text yson strings can be detected since they start with `\"` and deserialized so are text yson bools, everything else is already human readable). This drops dependency on `TTokenizer` 6) Some small parts (e.g. enums or constants or aliases) of yt/core/misc files were moved to library/cpp/yt/\* locations and re-included to drop dependencies of stripped\_error on them 7) `TErrorAttributes` is now a simple hash map instead of a handle to `IAttributeDictionary` 8) `ExtractFromAttributes` weak symbol is finally moved to library/cpp/yt/error due to point 9 allowing to fully drop dependency on `IAttributeDictionary`. Combined with point 7 this drops dep on yt/core/ytree altogether 9) Moved `TErrorCode` to library/cpp/yt/error. There is a logger there which forces dep on library/cpp/yt/logging. It is not required really, and can be later removed 10) Moved `TError` with format and macroes to library/cpp/yt/error. It still (and probably forever will) depend on yson. What can be done next: Switch TYsonString to TString and move ConvertTo/FromTextYsonString to library/cpp/yt/error. This would remove dep on library/cpp/yt/yson\_string commit_hash:6f11dc478ab782a1f98a5aedcd45a4800d3f4e7b
Diffstat (limited to 'library/cpp/yt/error/error_attributes.cpp')
-rw-r--r--library/cpp/yt/error/error_attributes.cpp115
1 files changed, 105 insertions, 10 deletions
diff --git a/library/cpp/yt/error/error_attributes.cpp b/library/cpp/yt/error/error_attributes.cpp
index 09aa48eebb..06db3b211e 100644
--- a/library/cpp/yt/error/error_attributes.cpp
+++ b/library/cpp/yt/error/error_attributes.cpp
@@ -1,30 +1,70 @@
#include "error_attributes.h"
+#include "error.h"
+#include "error_code.h"
+
namespace NYT {
////////////////////////////////////////////////////////////////////////////////
-TErrorAttributes::TErrorAttributes(void* attributes)
- : Attributes_(attributes)
-{ }
+std::vector<TErrorAttributes::TKey> TErrorAttributes::ListKeys() const
+{
+ std::vector<TString> keys;
+ keys.reserve(Map_.size());
+ for (const auto& [key, value] : Map_) {
+ keys.push_back(key);
+ }
+ return keys;
+}
-void TErrorAttributes::Clear()
+std::vector<TErrorAttributes::TKeyValuePair> TErrorAttributes::ListPairs() const
{
- for (const auto& key : ListKeys()) {
- Remove(key);
+ std::vector<TKeyValuePair> pairs;
+ pairs.reserve(Map_.size());
+ for (const auto& pair : Map_) {
+ pairs.push_back(pair);
}
+ return pairs;
+}
+
+TErrorAttributes::TValue TErrorAttributes::FindValue(TStringBuf key) const
+{
+ auto it = Map_.find(key);
+ return it == Map_.end() ? TValue{} : it->second;
+}
+
+void TErrorAttributes::SetValue(const TKey& key, const TValue& value)
+{
+ Map_[key] = value;
}
-TErrorAttributes::TValue TErrorAttributes::GetYsonAndRemove(const TKey& key)
+void TErrorAttributes::SetAttribute(const TErrorAttribute& attribute)
{
- auto result = GetYson(key);
- Remove(key);
+ SetValue(attribute.Key, attribute.Value);
+}
+
+bool TErrorAttributes::Remove(const TKey& key)
+{
+ return Map_.erase(key) > 0;
+}
+
+TErrorAttributes::TValue TErrorAttributes::GetValue(TStringBuf key) const
+{
+ auto result = FindValue(key);
+ if (!result) {
+ ThrowNoSuchAttributeException(key);
+ }
return result;
}
+void TErrorAttributes::Clear()
+{
+ Map_.clear();
+}
+
bool TErrorAttributes::Contains(TStringBuf key) const
{
- return FindYson(key).operator bool();
+ return Map_.contains(key);
}
bool operator == (const TErrorAttributes& lhs, const TErrorAttributes& rhs)
@@ -59,4 +99,59 @@ bool operator == (const TErrorAttributes& lhs, const TErrorAttributes& rhs)
////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+bool IsSpecialCharacter(char ch)
+{
+ return ch == '\\' || ch == '/' || ch == '@' || ch == '*' || ch == '&' || ch == '[' || ch == '{';
+}
+
+// AppendYPathLiteral.
+void DoFormatAttributeKey(TStringBuilderBase* builder, TStringBuf value)
+{
+ constexpr char asciiBegin = 32;
+ constexpr char asciiEnd = 127;
+ builder->Preallocate(value.length() + 16);
+ for (unsigned char ch : value) {
+ if (IsSpecialCharacter(ch)) {
+ builder->AppendChar('\\');
+ builder->AppendChar(ch);
+ } else if (ch < asciiBegin || ch > asciiEnd) {
+ builder->AppendString(TStringBuf("\\x"));
+ builder->AppendChar(IntToHexLowercase[ch >> 4]);
+ builder->AppendChar(IntToHexLowercase[ch & 0xf]);
+ } else {
+ builder->AppendChar(ch);
+ }
+ }
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+[[noreturn]] void TErrorAttributes::ThrowCannotParseAttributeException(TStringBuf key, const std::exception& ex)
+{
+ THROW_ERROR_EXCEPTION(
+ "Error parsing attribute %Qv",
+ key)
+ << ex;
+}
+
+[[noreturn]] void TErrorAttributes::ThrowNoSuchAttributeException(TStringBuf key)
+{
+ auto formatAttributeKey = [] (auto key) {
+ TStringBuilder builder;
+ DoFormatAttributeKey(&builder, key);
+ return builder.Flush();
+ };
+
+ THROW_ERROR_EXCEPTION(
+ /*NYTree::EErrorCode::ResolveError*/ TErrorCode{500},
+ "Attribute %Qv is not found",
+ formatAttributeKey(key));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
} // namespace NYT