123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- #pragma once
- #include <library/cpp/yt/error/error_code.h>
- #include <library/cpp/yt/threading/public.h>
- #include <library/cpp/yt/error/mergeable_dictionary.h>
- #include <library/cpp/yt/yson_string/convert.h>
- #include <library/cpp/yt/yson_string/string.h>
- #include <library/cpp/yt/misc/property.h>
- #include <util/system/compiler.h>
- #include <util/system/getpid.h>
- #include <util/generic/size_literals.h>
- #include <type_traits>
- namespace NYT {
- ////////////////////////////////////////////////////////////////////////////////
- //! An opaque wrapper around |int| value capable of conversions from |int|s and
- //! arbitrary enum types.
- class TErrorCode
- {
- public:
- using TUnderlying = int;
- constexpr TErrorCode();
- explicit constexpr TErrorCode(int value);
- template <class E>
- requires std::is_enum_v<E>
- constexpr TErrorCode(E value);
- constexpr operator int() const;
- template <class E>
- requires std::is_enum_v<E>
- constexpr operator E() const;
- template <class E>
- requires std::is_enum_v<E>
- constexpr bool operator == (E rhs) const;
- constexpr bool operator == (TErrorCode rhs) const;
- private:
- int Value_;
- };
- ////////////////////////////////////////////////////////////////////////////////
- void FormatValue(TStringBuilderBase* builder, TErrorCode code, TStringBuf spec);
- ////////////////////////////////////////////////////////////////////////////////
- template <class TValue>
- concept CErrorNestable = requires (TError& error, TValue&& operand)
- {
- { error <<= std::forward<TValue>(operand) } -> std::same_as<TError&>;
- };
- template <>
- class [[nodiscard]] TErrorOr<void>
- {
- public:
- TErrorOr();
- ~TErrorOr();
- TErrorOr(const TError& other);
- TErrorOr(TError&& other) noexcept;
- TErrorOr(const std::exception& ex);
- struct TDisableFormat
- { };
- static constexpr TDisableFormat DisableFormat = {};
- TErrorOr(TString message, TDisableFormat);
- TErrorOr(TErrorCode code, TString message, TDisableFormat);
- template <class... TArgs>
- explicit TErrorOr(
- TFormatString<TArgs...> format,
- TArgs&&... arg);
- template <class... TArgs>
- TErrorOr(
- TErrorCode code,
- TFormatString<TArgs...> format,
- TArgs&&... args);
- TError& operator = (const TError& other);
- TError& operator = (TError&& other) noexcept;
- static TError FromSystem();
- static TError FromSystem(int error);
- static TError FromSystem(const TSystemError& error);
- TErrorCode GetCode() const;
- TError& SetCode(TErrorCode code);
- TErrorCode GetNonTrivialCode() const;
- THashSet<TErrorCode> GetDistinctNonTrivialErrorCodes() const;
- const TString& GetMessage() const;
- TError& SetMessage(TString message);
- bool HasOriginAttributes() const;
- TProcessId GetPid() const;
- TStringBuf GetThreadName() const;
- NThreading::TThreadId GetTid() const;
- bool HasDatetime() const;
- TInstant GetDatetime() const;
- bool HasAttributes() const noexcept;
- const TErrorAttributes& Attributes() const;
- TErrorAttributes* MutableAttributes();
- const std::vector<TError>& InnerErrors() const;
- std::vector<TError>* MutableInnerErrors();
- // Used for deserialization only.
- TOriginAttributes* MutableOriginAttributes() const noexcept;
- void UpdateOriginAttributes();
- TError Truncate(
- int maxInnerErrorCount = 2,
- i64 stringLimit = 16_KB,
- const THashSet<TStringBuf>& attributeWhitelist = {}) const &;
- TError Truncate(
- int maxInnerErrorCount = 2,
- i64 stringLimit = 16_KB,
- const THashSet<TStringBuf>& attributeWhitelist = {}) &&;
- bool IsOK() const;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- void ThrowOnError(U&& u) const &;
- template <class... TArgs>
- void ThrowOnError(TFormatString<TArgs...> format, TArgs&&... args) const &;
- template <class... TArgs>
- void ThrowOnError(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) const &;
- inline void ThrowOnError() const &;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- void ThrowOnError(U&& u) &&;
- template <class... TArgs>
- void ThrowOnError(TFormatString<TArgs...> format, TArgs&&... args) &&;
- template <class... TArgs>
- void ThrowOnError(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) &&;
- inline void ThrowOnError() &&;
- template <CInvocable<bool(const TError&)> TFilter>
- std::optional<TError> FindMatching(const TFilter& filter) const;
- template <CInvocable<bool(TErrorCode)> TFilter>
- std::optional<TError> FindMatching(const TFilter& filter) const;
- std::optional<TError> FindMatching(TErrorCode code) const;
- std::optional<TError> FindMatching(const THashSet<TErrorCode>& codes) const;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- TError Wrap(U&& u) const &;
- template <class... TArgs>
- TError Wrap(TFormatString<TArgs...> format, TArgs&&... args) const &;
- template <class... TArgs>
- TError Wrap(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) const &;
- TError Wrap() const &;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- TError Wrap(U&& u) &&;
- template <class... TArgs>
- TError Wrap(TFormatString<TArgs...> format, TArgs&&... args) &&;
- template <class... TArgs>
- TError Wrap(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) &&;
- TError Wrap() &&;
- //! Perform recursive aggregation of error codes and messages over the error tree.
- //! Result of this aggregation is suitable for error clustering in groups of
- //! "similar" errors. Refer to yt/yt/library/error_skeleton/skeleton_ut.cpp for examples.
- //!
- //! This method builds skeleton from scratch by doing complete error tree traversal,
- //! so calling it in computationally hot code is discouraged.
- //!
- //! In order to prevent core -> re2 dependency, implementation belongs to a separate library
- //! yt/yt/library/error_skeleton. Calling this method without PEERDIR'ing implementation
- //! results in an exception.
- TString GetSkeleton() const;
- TError& operator <<= (const TErrorAttribute& attribute) &;
- TError& operator <<= (const std::vector<TErrorAttribute>& attributes) &;
- TError& operator <<= (const TError& innerError) &;
- TError& operator <<= (TError&& innerError) &;
- TError& operator <<= (const std::vector<TError>& innerErrors) &;
- TError& operator <<= (std::vector<TError>&& innerErrors) &;
- TError& operator <<= (TAnyMergeableDictionaryRef attributes) &;
- template <CErrorNestable TValue>
- TError&& operator << (TValue&& operand) &&;
- template <CErrorNestable TValue>
- TError operator << (TValue&& operand) const &;
- template <CErrorNestable TValue>
- TError&& operator << (const std::optional<TValue>& rhs) &&;
- template <CErrorNestable TValue>
- TError operator << (const std::optional<TValue>& rhs) const &;
- private:
- class TImpl;
- std::unique_ptr<TImpl> Impl_;
- explicit TErrorOr(std::unique_ptr<TImpl> impl);
- void MakeMutable();
- friend class TErrorAttributes;
- };
- ////////////////////////////////////////////////////////////////////////////////
- bool operator == (const TError& lhs, const TError& rhs);
- ////////////////////////////////////////////////////////////////////////////////
- void FormatValue(TStringBuilderBase* builder, const TError& error, TStringBuf spec);
- ////////////////////////////////////////////////////////////////////////////////
- using TErrorVisitor = std::function<void(const TError&, int depth)>;
- //! Traverses the error tree in DFS order.
- void TraverseError(
- const TError& error,
- const TErrorVisitor& visitor,
- int depth = 0);
- ////////////////////////////////////////////////////////////////////////////////
- template <class T>
- struct TErrorTraits
- {
- using TWrapped = TErrorOr<T>;
- using TUnwrapped = T;
- };
- template <class T>
- struct TErrorTraits<TErrorOr<T>>
- {
- using TUnderlying = T;
- using TWrapped = TErrorOr<T>;
- using TUnwrapped = T;
- };
- ////////////////////////////////////////////////////////////////////////////////
- class TErrorException
- : public std::exception
- {
- public:
- DEFINE_BYREF_RW_PROPERTY(TError, Error);
- public:
- TErrorException() = default;
- TErrorException(const TErrorException& other) = default;
- TErrorException(TErrorException&& other) = default;
- const char* what() const noexcept override;
- private:
- mutable TString CachedWhat_;
- };
- // Make these templates to avoid type erasure during throw.
- template <class TException>
- requires std::derived_from<std::remove_cvref_t<TException>, TErrorException>
- TException&& operator <<= (TException&& ex, const TError& error);
- template <class TException>
- requires std::derived_from<std::remove_cvref_t<TException>, TErrorException>
- TException&& operator <<= (TException&& ex, TError&& error);
- ////////////////////////////////////////////////////////////////////////////////
- namespace NDetail {
- struct TErrorAdaptor
- {
- template <class TArg>
- requires std::constructible_from<TError, TArg>
- TError operator << (TArg&& rhs) const;
- template <class TArg>
- requires
- std::constructible_from<TError, TArg> &&
- std::derived_from<std::remove_cvref_t<TArg>, TError>
- TArg&& operator << (TArg&& rhs) const;
- };
- // Make these to correctly forward TError to Wrap call.
- template <class TErrorLike, class U>
- requires
- std::derived_from<std::remove_cvref_t<TErrorLike>, TError> &&
- (!CStringLiteral<std::remove_cvref_t<U>>)
- void ThrowErrorExceptionIfFailed(TErrorLike&& error, U&& u);
- template <class TErrorLike, class... TArgs>
- requires std::derived_from<std::remove_cvref_t<TErrorLike>, TError>
- void ThrowErrorExceptionIfFailed(TErrorLike&& error, TFormatString<TArgs...> format, TArgs&&... args);
- template <class TErrorLike, class... TArgs>
- requires std::derived_from<std::remove_cvref_t<TErrorLike>, TError>
- void ThrowErrorExceptionIfFailed(TErrorLike&& error, TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args);
- template <class TErrorLike>
- requires std::derived_from<std::remove_cvref_t<TErrorLike>, TError>
- void ThrowErrorExceptionIfFailed(TErrorLike&& error);
- } // namespace NDetail
- ////////////////////////////////////////////////////////////////////////////////
- #define THROW_ERROR \
- throw ::NYT::TErrorException() <<= ::NYT::NDetail::TErrorAdaptor() <<
- #define THROW_ERROR_EXCEPTION(head, ...) \
- THROW_ERROR ::NYT::TError(head __VA_OPT__(,) __VA_ARGS__)
- // NB: When given an error and a string as arguments, this macro automatically wraps
- // new error around the initial one.
- #define THROW_ERROR_EXCEPTION_IF_FAILED(error, ...) \
- ::NYT::NDetail::ThrowErrorExceptionIfFailed((error) __VA_OPT__(,) __VA_ARGS__); \
- #define THROW_ERROR_EXCEPTION_UNLESS(condition, head, ...) \
- if ((condition)) {\
- } else { \
- THROW_ERROR ::NYT::TError(head __VA_OPT__(,) __VA_ARGS__); \
- }
- #define THROW_ERROR_EXCEPTION_IF(condition, head, ...) \
- THROW_ERROR_EXCEPTION_UNLESS(!(condition), head, __VA_ARGS__)
- ////////////////////////////////////////////////////////////////////////////////
- template <class T>
- class [[nodiscard]] TErrorOr
- : public TError
- {
- public:
- TErrorOr();
- TErrorOr(const T& value);
- TErrorOr(T&& value) noexcept;
- TErrorOr(const TErrorOr<T>& other);
- TErrorOr(TErrorOr<T>&& other) noexcept;
- TErrorOr(const TError& other);
- TErrorOr(TError&& other) noexcept;
- TErrorOr(const std::exception& ex);
- template <class U>
- TErrorOr(const TErrorOr<U>& other);
- template <class U>
- TErrorOr(TErrorOr<U>&& other) noexcept;
- TErrorOr<T>& operator = (const TErrorOr<T>& other)
- requires std::is_copy_assignable_v<T>;
- TErrorOr<T>& operator = (TErrorOr<T>&& other) noexcept
- requires std::is_nothrow_move_assignable_v<T>;
- const T& Value() const & Y_LIFETIME_BOUND;
- T& Value() & Y_LIFETIME_BOUND;
- T&& Value() && Y_LIFETIME_BOUND;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- const T& ValueOrThrow(U&& u) const & Y_LIFETIME_BOUND;
- template <class... TArgs>
- const T& ValueOrThrow(TFormatString<TArgs...> format, TArgs&&... args) const & Y_LIFETIME_BOUND;
- template <class... TArgs>
- const T& ValueOrThrow(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) const & Y_LIFETIME_BOUND;
- const T& ValueOrThrow() const & Y_LIFETIME_BOUND;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- T& ValueOrThrow(U&& u) & Y_LIFETIME_BOUND;
- template <class... TArgs>
- T& ValueOrThrow(TFormatString<TArgs...> format, TArgs&&... args) & Y_LIFETIME_BOUND;
- template <class... TArgs>
- T& ValueOrThrow(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) & Y_LIFETIME_BOUND;
- T& ValueOrThrow() & Y_LIFETIME_BOUND;
- template <class U>
- requires (!CStringLiteral<std::remove_cvref_t<U>>)
- T&& ValueOrThrow(U&& u) && Y_LIFETIME_BOUND;
- template <class... TArgs>
- T&& ValueOrThrow(TFormatString<TArgs...> format, TArgs&&... args) && Y_LIFETIME_BOUND;
- template <class... TArgs>
- T&& ValueOrThrow(TErrorCode code, TFormatString<TArgs...> format, TArgs&&... args) && Y_LIFETIME_BOUND;
- T&& ValueOrThrow() && Y_LIFETIME_BOUND;
- const T& ValueOrDefault(const T& defaultValue Y_LIFETIME_BOUND) const & Y_LIFETIME_BOUND;
- T& ValueOrDefault(T& defaultValue Y_LIFETIME_BOUND) & Y_LIFETIME_BOUND;
- constexpr T ValueOrDefault(T&& defaultValue) const &;
- constexpr T ValueOrDefault(T&& defaultValue) &&;
- private:
- std::optional<T> Value_;
- };
- ////////////////////////////////////////////////////////////////////////////////
- template <class T>
- void FormatValue(TStringBuilderBase* builder, const TErrorOr<T>& error, TStringBuf spec);
- ////////////////////////////////////////////////////////////////////////////////
- template <class F, class... As>
- auto RunNoExcept(F&& functor, As&&... args) noexcept -> decltype(functor(std::forward<As>(args)...))
- {
- return functor(std::forward<As>(args)...);
- }
- ////////////////////////////////////////////////////////////////////////////////
- } // namespace NYT
- #define STRIPPED_ERROR_INL_H_
- #include "error-inl.h"
- #undef STRIPPED_ERROR_INL_H_
|