diff options
Diffstat (limited to 'abseil-cpp/absl/status/status.h')
-rw-r--r-- | abseil-cpp/absl/status/status.h | 176 |
1 files changed, 130 insertions, 46 deletions
diff --git a/abseil-cpp/absl/status/status.h b/abseil-cpp/absl/status/status.h index 42f634e..595064c 100644 --- a/abseil-cpp/absl/status/status.h +++ b/abseil-cpp/absl/status/status.h @@ -24,11 +24,11 @@ // * A set of helper functions for creating status codes and checking their // values // -// Within Google, `absl::Status` is the primary mechanism for gracefully -// handling errors across API boundaries (and in particular across RPC -// boundaries). Some of these errors may be recoverable, but others may not. -// Most functions that can produce a recoverable error should be designed to -// return an `absl::Status` (or `absl::StatusOr`). +// Within Google, `absl::Status` is the primary mechanism for communicating +// errors in C++, and is used to represent error state in both in-process +// library calls as well as RPC calls. Some of these errors may be recoverable, +// but others may not. Most functions that can produce a recoverable error +// should be designed to return an `absl::Status` (or `absl::StatusOr`). // // Example: // @@ -51,12 +51,14 @@ #ifndef ABSL_STATUS_STATUS_H_ #define ABSL_STATUS_STATUS_H_ -#include <iostream> +#include <ostream> #include <string> +#include <utility> -#include "absl/container/inlined_vector.h" +#include "absl/functional/function_ref.h" #include "absl/status/internal/status_internal.h" #include "absl/strings/cord.h" +#include "absl/strings/string_view.h" #include "absl/types/optional.h" namespace absl { @@ -79,7 +81,7 @@ ABSL_NAMESPACE_BEGIN // `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or // `kAlreadyExists` over `kFailedPrecondition`. // -// Because these errors may travel RPC boundaries, these codes are tied to the +// Because these errors may cross RPC boundaries, these codes are tied to the // `google.rpc.Code` definitions within // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto // The string value of these RPC codes is denoted within each enum below. @@ -98,7 +100,7 @@ enum class StatusCode : int { // StatusCode::kCancelled // - // kCanelled (gRPC code "CANCELLED") indicates the operation was cancelled, + // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled, // typically by the caller. kCancelled = 1, @@ -113,10 +115,10 @@ enum class StatusCode : int { // StatusCode::kInvalidArgument // // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller - // specified an invalid argument, such a malformed filename. Note that such - // errors should be narrowly limited to indicate to the invalid nature of the - // arguments themselves. Errors with validly formed arguments that may cause - // errors with the state of the receiving system should be denoted with + // specified an invalid argument, such as a malformed filename. Note that use + // of such errors should be narrowly limited to indicate the invalid nature of + // the arguments themselves. Errors with validly formed arguments that may + // cause errors with the state of the receiving system should be denoted with // `kFailedPrecondition` instead. kInvalidArgument = 3, @@ -136,14 +138,15 @@ enum class StatusCode : int { // // `kNotFound` is useful if a request should be denied for an entire class of // users, such as during a gradual feature rollout or undocumented allow list. - // If, instead, a request should be denied for specific sets of users, such as - // through user-based access control, use `kPermissionDenied` instead. + // If a request should be denied for specific sets of users, such as through + // user-based access control, use `kPermissionDenied` instead. kNotFound = 5, // StatusCode::kAlreadyExists // - // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a - // caller attempted to create (such as file or directory) is already present. + // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates that the entity a + // caller attempted to create (such as a file or directory) is already + // present. kAlreadyExists = 6, // StatusCode::kPermissionDenied @@ -182,7 +185,7 @@ enum class StatusCode : int { // level (such as when a client-specified test-and-set fails, indicating // the client should restart a read-modify-write sequence). // (c) Use `kFailedPrecondition` if the client should not retry until - // the system state has been explicitly fixed. For example, if an "rmdir" + // the system state has been explicitly fixed. For example, if a "rmdir" // fails because the directory is non-empty, `kFailedPrecondition` // should be returned since the client should not retry unless // the files are deleted from the directory. @@ -198,9 +201,9 @@ enum class StatusCode : int { // `kAborted`, and `kUnavailable`. kAborted = 10, - // StatusCode::kOutofRange + // StatusCode::kOutOfRange // - // kOutofRange (gRPC code "OUT_OF_RANGE") indicates the operation was + // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was // attempted past the valid range, such as seeking or reading past an // end-of-file. // @@ -279,6 +282,59 @@ std::string StatusCodeToString(StatusCode code); // Streams StatusCodeToString(code) to `os`. std::ostream& operator<<(std::ostream& os, StatusCode code); +// absl::StatusToStringMode +// +// An `absl::StatusToStringMode` is an enumerated type indicating how +// `absl::Status::ToString()` should construct the output string for a non-ok +// status. +enum class StatusToStringMode : int { + // ToString will not contain any extra data (such as payloads). It will only + // contain the error code and message, if any. + kWithNoExtraData = 0, + // ToString will contain the payloads. + kWithPayload = 1 << 0, + // ToString will include all the extra data this Status has. + kWithEverything = ~kWithNoExtraData, + // Default mode used by ToString. Its exact value might change in the future. + kDefault = kWithPayload, +}; + +// absl::StatusToStringMode is specified as a bitmask type, which means the +// following operations must be provided: +inline constexpr StatusToStringMode operator&(StatusToStringMode lhs, + StatusToStringMode rhs) { + return static_cast<StatusToStringMode>(static_cast<int>(lhs) & + static_cast<int>(rhs)); +} +inline constexpr StatusToStringMode operator|(StatusToStringMode lhs, + StatusToStringMode rhs) { + return static_cast<StatusToStringMode>(static_cast<int>(lhs) | + static_cast<int>(rhs)); +} +inline constexpr StatusToStringMode operator^(StatusToStringMode lhs, + StatusToStringMode rhs) { + return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^ + static_cast<int>(rhs)); +} +inline constexpr StatusToStringMode operator~(StatusToStringMode arg) { + return static_cast<StatusToStringMode>(~static_cast<int>(arg)); +} +inline StatusToStringMode& operator&=(StatusToStringMode& lhs, + StatusToStringMode rhs) { + lhs = lhs & rhs; + return lhs; +} +inline StatusToStringMode& operator|=(StatusToStringMode& lhs, + StatusToStringMode rhs) { + lhs = lhs | rhs; + return lhs; +} +inline StatusToStringMode& operator^=(StatusToStringMode& lhs, + StatusToStringMode rhs) { + lhs = lhs ^ rhs; + return lhs; +} + // absl::Status // // The `absl::Status` class is generally used to gracefully handle errors @@ -291,7 +347,7 @@ std::ostream& operator<<(std::ostream& os, StatusCode code); // API developers should construct their functions to return `absl::OkStatus()` // upon success, or an `absl::StatusCode` upon another type of error (e.g // an `absl::StatusCode::kInvalidArgument` error). The API provides convenience -// functions to constuct each status code. +// functions to construct each status code. // // Example: // @@ -342,7 +398,7 @@ std::ostream& operator<<(std::ostream& os, StatusCode code); // // * It may provide more fine-grained semantic information about the error to // facilitate actionable remedies. -// * It may provide human-readable contexual information that is more +// * It may provide human-readable contextual information that is more // appropriate to display to an end user. // // Example: @@ -360,7 +416,12 @@ std::ostream& operator<<(std::ostream& os, StatusCode code); // return result; // } // -class ABSL_MUST_USE_RESULT Status final { +// For documentation see https://abseil.io/docs/cpp/guides/status. +// +// Returned Status objects may not be ignored. status_internal.h has a forward +// declaration of the form +// class ABSL_MUST_USE_RESULT Status; +class Status final { public: // Constructors @@ -370,10 +431,10 @@ class ABSL_MUST_USE_RESULT Status final { Status(); // Creates a status in the canonical error space with the specified - // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, + // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, // NOLINT // `msg` is ignored and an object identical to an OK status is constructed. // - // The `msg` string must be in UTF-8. The implementation may complain (e.g., + // The `msg` string must be in UTF-8. The implementation may complain (e.g., // NOLINT // by printing a warning) if it is not. Status(absl::StatusCode code, absl::string_view msg); @@ -408,8 +469,9 @@ class ABSL_MUST_USE_RESULT Status final { // Status::ok() // - // Returns `true` if `this->ok()`. Prefer checking for an OK status using this - // member function. + // Returns `true` if `this->code()` == `absl::StatusCode::kOk`, + // indicating the absence of an error. + // Prefer checking for an OK status using this member function. ABSL_MUST_USE_RESULT bool ok() const; // Status::code() @@ -434,7 +496,7 @@ class ABSL_MUST_USE_RESULT Status final { // Returns the error message associated with this error code, if available. // Note that this message rarely describes the error code. It is not unusual // for the error message to be the empty string. As a result, prefer - // `Status::ToString()` for debug logging. + // `operator<<` or `Status::ToString()` for debug logging. absl::string_view message() const; friend bool operator==(const Status&, const Status&); @@ -442,15 +504,17 @@ class ABSL_MUST_USE_RESULT Status final { // Status::ToString() // - // Returns a combination of the error code name, the message and any - // associated payload messages. This string is designed simply to be human - // readable and its exact format should not be load bearing. Do not depend on - // the exact format of the result of `ToString()` which is subject to change. + // Returns a string based on the `mode`. By default, it returns combination of + // the error code name, the message and any associated payload messages. This + // string is designed simply to be human readable and its exact format should + // not be load bearing. Do not depend on the exact format of the result of + // `ToString()` which is subject to change. // // The printed code name and the message are generally substrings of the // result, and the payloads to be printed use the status payload printer // mechanism (which is internal). - std::string ToString() const; + std::string ToString( + StatusToStringMode mode = StatusToStringMode::kDefault) const; // Status::IgnoreError() // @@ -469,12 +533,12 @@ class ABSL_MUST_USE_RESULT Status final { //---------------------------------------------------------------------------- // A payload may be attached to a status to provide additional context to an - // error that may not be satisifed by an existing `absl::StatusCode`. + // error that may not be satisfied by an existing `absl::StatusCode`. // Typically, this payload serves one of several purposes: // // * It may provide more fine-grained semantic information about the error // to facilitate actionable remedies. - // * It may provide human-readable contexual information that is more + // * It may provide human-readable contextual information that is more // appropriate to display to an end user. // // A payload consists of a [key,value] pair, where the key is a string @@ -528,7 +592,7 @@ class ABSL_MUST_USE_RESULT Status final { // NOTE: Any mutation on the same 'absl::Status' object during visitation is // forbidden and could result in undefined behavior. void ForEachPayload( - const std::function<void(absl::string_view, const absl::Cord&)>& visitor) + absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) const; private: @@ -549,9 +613,6 @@ class ABSL_MUST_USE_RESULT Status final { const status_internal::Payloads* GetPayloads() const; status_internal::Payloads* GetPayloads(); - // Takes ownership of payload. - static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg, - std::unique_ptr<status_internal::Payloads> payload); static bool EqualsSlow(const absl::Status& a, const absl::Status& b); // MSVC 14.0 limitation requires the const. @@ -580,8 +641,7 @@ class ABSL_MUST_USE_RESULT Status final { static uintptr_t PointerToRep(status_internal::StatusRep* r); static status_internal::StatusRep* RepToPointer(uintptr_t r); - // Returns string for non-ok Status. - std::string ToStringSlow() const; + std::string ToStringSlow(StatusToStringMode mode) const; // Status supports two different representations. // - When the low bit is off it is an inlined representation. @@ -678,6 +738,19 @@ Status UnavailableError(absl::string_view message); Status UnimplementedError(absl::string_view message); Status UnknownError(absl::string_view message); +// ErrnoToStatusCode() +// +// Returns the StatusCode for `error_number`, which should be an `errno` value. +// See https://en.cppreference.com/w/cpp/error/errno_macros and similar +// references. +absl::StatusCode ErrnoToStatusCode(int error_number); + +// ErrnoToStatus() +// +// Convenience function that creates a `absl::Status` using an `error_number`, +// which should be an `errno` value. +Status ErrnoToStatus(int error_number, absl::string_view message); + //------------------------------------------------------------------------------ // Implementation details follow //------------------------------------------------------------------------------ @@ -704,9 +777,11 @@ inline Status::Status(Status&& x) noexcept : rep_(x.rep_) { inline Status& Status::operator=(Status&& x) { uintptr_t old_rep = rep_; - rep_ = x.rep_; - x.rep_ = MovedFromRep(); - Unref(old_rep); + if (x.rep_ != old_rep) { + rep_ = x.rep_; + x.rep_ = MovedFromRep(); + Unref(old_rep); + } return *this; } @@ -743,8 +818,8 @@ inline bool operator!=(const Status& lhs, const Status& rhs) { return !(lhs == rhs); } -inline std::string Status::ToString() const { - return ok() ? "OK" : ToStringSlow(); +inline std::string Status::ToString(StatusToStringMode mode) const { + return ok() ? "OK" : ToStringSlow(mode); } inline void Status::IgnoreError() const { @@ -811,6 +886,15 @@ inline Status OkStatus() { return Status(); } // message-less kCancelled errors are common in the infrastructure. inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); } +// Retrieves a message's status as a null terminated C string. The lifetime of +// this string is tied to the lifetime of the status object itself. +// +// If the status's message is empty, the empty string is returned. +// +// StatusMessageAsCStr exists for C support. Use `status.message()` in C++. +const char* StatusMessageAsCStr( + const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND); + ABSL_NAMESPACE_END } // namespace absl |