status.h (36461B)
1 // Copyright 2019 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: status.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This header file defines the Abseil `status` library, consisting of: 20 // 21 // * An `absl::Status` class for holding error handling information 22 // * A set of canonical `absl::StatusCode` error codes, and associated 23 // utilities for generating and propagating status codes. 24 // * A set of helper functions for creating status codes and checking their 25 // values 26 // 27 // Within Google, `absl::Status` is the primary mechanism for communicating 28 // errors in C++, and is used to represent error state in both in-process 29 // library calls as well as RPC calls. Some of these errors may be recoverable, 30 // but others may not. Most functions that can produce a recoverable error 31 // should be designed to return an `absl::Status` (or `absl::StatusOr`). 32 // 33 // Example: 34 // 35 // absl::Status myFunction(absl::string_view fname, ...) { 36 // ... 37 // // encounter error 38 // if (error condition) { 39 // return absl::InvalidArgumentError("bad mode"); 40 // } 41 // // else, return OK 42 // return absl::OkStatus(); 43 // } 44 // 45 // An `absl::Status` is designed to either return "OK" or one of a number of 46 // different error codes, corresponding to typical error conditions. 47 // In almost all cases, when using `absl::Status` you should use the canonical 48 // error codes (of type `absl::StatusCode`) enumerated in this header file. 49 // These canonical codes are understood across the codebase and will be 50 // accepted across all API and RPC boundaries. 51 #ifndef ABSL_STATUS_STATUS_H_ 52 #define ABSL_STATUS_STATUS_H_ 53 54 #include <cassert> 55 #include <cstdint> 56 #include <ostream> 57 #include <string> 58 #include <utility> 59 60 #include "absl/base/attributes.h" 61 #include "absl/base/config.h" 62 #include "absl/base/macros.h" 63 #include "absl/base/nullability.h" 64 #include "absl/base/optimization.h" 65 #include "absl/functional/function_ref.h" 66 #include "absl/status/internal/status_internal.h" 67 #include "absl/strings/cord.h" 68 #include "absl/strings/string_view.h" 69 #include "absl/types/optional.h" 70 71 namespace absl { 72 ABSL_NAMESPACE_BEGIN 73 74 // absl::StatusCode 75 // 76 // An `absl::StatusCode` is an enumerated type indicating either no error ("OK") 77 // or an error condition. In most cases, an `absl::Status` indicates a 78 // recoverable error, and the purpose of signalling an error is to indicate what 79 // action to take in response to that error. These error codes map to the proto 80 // RPC error codes indicated in https://cloud.google.com/apis/design/errors. 81 // 82 // The errors listed below are the canonical errors associated with 83 // `absl::Status` and are used throughout the codebase. As a result, these 84 // error codes are somewhat generic. 85 // 86 // In general, try to return the most specific error that applies if more than 87 // one error may pertain. For example, prefer `kOutOfRange` over 88 // `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or 89 // `kAlreadyExists` over `kFailedPrecondition`. 90 // 91 // Because these errors may cross RPC boundaries, these codes are tied to the 92 // `google.rpc.Code` definitions within 93 // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto 94 // The string value of these RPC codes is denoted within each enum below. 95 // 96 // If your error handling code requires more context, you can attach payloads 97 // to your status. See `absl::Status::SetPayload()` and 98 // `absl::Status::GetPayload()` below. 99 enum class StatusCode : int { 100 // StatusCode::kOk 101 // 102 // kOK (gRPC code "OK") does not indicate an error; this value is returned on 103 // success. It is typical to check for this value before proceeding on any 104 // given call across an API or RPC boundary. To check this value, use the 105 // `absl::Status::ok()` member function rather than inspecting the raw code. 106 kOk = 0, 107 108 // StatusCode::kCancelled 109 // 110 // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled, 111 // typically by the caller. 112 kCancelled = 1, 113 114 // StatusCode::kUnknown 115 // 116 // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In 117 // general, more specific errors should be raised, if possible. Errors raised 118 // by APIs that do not return enough error information may be converted to 119 // this error. 120 kUnknown = 2, 121 122 // StatusCode::kInvalidArgument 123 // 124 // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller 125 // specified an invalid argument, such as a malformed filename. Note that use 126 // of such errors should be narrowly limited to indicate the invalid nature of 127 // the arguments themselves. Errors with validly formed arguments that may 128 // cause errors with the state of the receiving system should be denoted with 129 // `kFailedPrecondition` instead. 130 kInvalidArgument = 3, 131 132 // StatusCode::kDeadlineExceeded 133 // 134 // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline 135 // expired before the operation could complete. For operations that may change 136 // state within a system, this error may be returned even if the operation has 137 // completed successfully. For example, a successful response from a server 138 // could have been delayed long enough for the deadline to expire. 139 kDeadlineExceeded = 4, 140 141 // StatusCode::kNotFound 142 // 143 // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as 144 // a file or directory) was not found. 145 // 146 // `kNotFound` is useful if a request should be denied for an entire class of 147 // users, such as during a gradual feature rollout or undocumented allow list. 148 // If a request should be denied for specific sets of users, such as through 149 // user-based access control, use `kPermissionDenied` instead. 150 kNotFound = 5, 151 152 // StatusCode::kAlreadyExists 153 // 154 // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates that the entity a 155 // caller attempted to create (such as a file or directory) is already 156 // present. 157 kAlreadyExists = 6, 158 159 // StatusCode::kPermissionDenied 160 // 161 // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller 162 // does not have permission to execute the specified operation. Note that this 163 // error is different than an error due to an *un*authenticated user. This 164 // error code does not imply the request is valid or the requested entity 165 // exists or satisfies any other pre-conditions. 166 // 167 // `kPermissionDenied` must not be used for rejections caused by exhausting 168 // some resource. Instead, use `kResourceExhausted` for those errors. 169 // `kPermissionDenied` must not be used if the caller cannot be identified. 170 // Instead, use `kUnauthenticated` for those errors. 171 kPermissionDenied = 7, 172 173 // StatusCode::kResourceExhausted 174 // 175 // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource 176 // has been exhausted, perhaps a per-user quota, or perhaps the entire file 177 // system is out of space. 178 kResourceExhausted = 8, 179 180 // StatusCode::kFailedPrecondition 181 // 182 // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the 183 // operation was rejected because the system is not in a state required for 184 // the operation's execution. For example, a directory to be deleted may be 185 // non-empty, an "rmdir" operation is applied to a non-directory, etc. 186 // 187 // Some guidelines that may help a service implementer in deciding between 188 // `kFailedPrecondition`, `kAborted`, and `kUnavailable`: 189 // 190 // (a) Use `kUnavailable` if the client can retry just the failing call. 191 // (b) Use `kAborted` if the client should retry at a higher transaction 192 // level (such as when a client-specified test-and-set fails, indicating 193 // the client should restart a read-modify-write sequence). 194 // (c) Use `kFailedPrecondition` if the client should not retry until 195 // the system state has been explicitly fixed. For example, if a "rmdir" 196 // fails because the directory is non-empty, `kFailedPrecondition` 197 // should be returned since the client should not retry unless 198 // the files are deleted from the directory. 199 kFailedPrecondition = 9, 200 201 // StatusCode::kAborted 202 // 203 // kAborted (gRPC code "ABORTED") indicates the operation was aborted, 204 // typically due to a concurrency issue such as a sequencer check failure or a 205 // failed transaction. 206 // 207 // See the guidelines above for deciding between `kFailedPrecondition`, 208 // `kAborted`, and `kUnavailable`. 209 kAborted = 10, 210 211 // StatusCode::kOutOfRange 212 // 213 // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was 214 // attempted past the valid range, such as seeking or reading past an 215 // end-of-file. 216 // 217 // Unlike `kInvalidArgument`, this error indicates a problem that may 218 // be fixed if the system state changes. For example, a 32-bit file 219 // system will generate `kInvalidArgument` if asked to read at an 220 // offset that is not in the range [0,2^32-1], but it will generate 221 // `kOutOfRange` if asked to read from an offset past the current 222 // file size. 223 // 224 // There is a fair bit of overlap between `kFailedPrecondition` and 225 // `kOutOfRange`. We recommend using `kOutOfRange` (the more specific 226 // error) when it applies so that callers who are iterating through 227 // a space can easily look for an `kOutOfRange` error to detect when 228 // they are done. 229 kOutOfRange = 11, 230 231 // StatusCode::kUnimplemented 232 // 233 // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not 234 // implemented or supported in this service. In this case, the operation 235 // should not be re-attempted. 236 kUnimplemented = 12, 237 238 // StatusCode::kInternal 239 // 240 // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred 241 // and some invariants expected by the underlying system have not been 242 // satisfied. This error code is reserved for serious errors. 243 kInternal = 13, 244 245 // StatusCode::kUnavailable 246 // 247 // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently 248 // unavailable and that this is most likely a transient condition. An error 249 // such as this can be corrected by retrying with a backoff scheme. Note that 250 // it is not always safe to retry non-idempotent operations. 251 // 252 // See the guidelines above for deciding between `kFailedPrecondition`, 253 // `kAborted`, and `kUnavailable`. 254 kUnavailable = 14, 255 256 // StatusCode::kDataLoss 257 // 258 // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or 259 // corruption has occurred. As this error is serious, proper alerting should 260 // be attached to errors such as this. 261 kDataLoss = 15, 262 263 // StatusCode::kUnauthenticated 264 // 265 // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request 266 // does not have valid authentication credentials for the operation. Correct 267 // the authentication and try again. 268 kUnauthenticated = 16, 269 270 // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ 271 // 272 // NOTE: this error code entry should not be used and you should not rely on 273 // its value, which may change. 274 // 275 // The purpose of this enumerated value is to force people who handle status 276 // codes with `switch()` statements to *not* simply enumerate all possible 277 // values, but instead provide a "default:" case. Providing such a default 278 // case ensures that code will compile when new codes are added. 279 kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20 280 }; 281 282 // StatusCodeToString() 283 // 284 // Returns the name for the status code, or "" if it is an unknown value. 285 std::string StatusCodeToString(StatusCode code); 286 287 // operator<< 288 // 289 // Streams StatusCodeToString(code) to `os`. 290 std::ostream& operator<<(std::ostream& os, StatusCode code); 291 292 // absl::StatusToStringMode 293 // 294 // An `absl::StatusToStringMode` is an enumerated type indicating how 295 // `absl::Status::ToString()` should construct the output string for a non-ok 296 // status. 297 enum class StatusToStringMode : int { 298 // ToString will not contain any extra data (such as payloads). It will only 299 // contain the error code and message, if any. 300 kWithNoExtraData = 0, 301 // ToString will contain the payloads. 302 kWithPayload = 1 << 0, 303 // ToString will include all the extra data this Status has. 304 kWithEverything = ~kWithNoExtraData, 305 // Default mode used by ToString. Its exact value might change in the future. 306 kDefault = kWithPayload, 307 }; 308 309 // absl::StatusToStringMode is specified as a bitmask type, which means the 310 // following operations must be provided: 311 inline constexpr StatusToStringMode operator&(StatusToStringMode lhs, 312 StatusToStringMode rhs) { 313 return static_cast<StatusToStringMode>(static_cast<int>(lhs) & 314 static_cast<int>(rhs)); 315 } 316 inline constexpr StatusToStringMode operator|(StatusToStringMode lhs, 317 StatusToStringMode rhs) { 318 return static_cast<StatusToStringMode>(static_cast<int>(lhs) | 319 static_cast<int>(rhs)); 320 } 321 inline constexpr StatusToStringMode operator^(StatusToStringMode lhs, 322 StatusToStringMode rhs) { 323 return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^ 324 static_cast<int>(rhs)); 325 } 326 inline constexpr StatusToStringMode operator~(StatusToStringMode arg) { 327 return static_cast<StatusToStringMode>(~static_cast<int>(arg)); 328 } 329 inline StatusToStringMode& operator&=(StatusToStringMode& lhs, 330 StatusToStringMode rhs) { 331 lhs = lhs & rhs; 332 return lhs; 333 } 334 inline StatusToStringMode& operator|=(StatusToStringMode& lhs, 335 StatusToStringMode rhs) { 336 lhs = lhs | rhs; 337 return lhs; 338 } 339 inline StatusToStringMode& operator^=(StatusToStringMode& lhs, 340 StatusToStringMode rhs) { 341 lhs = lhs ^ rhs; 342 return lhs; 343 } 344 345 // absl::Status 346 // 347 // The `absl::Status` class is generally used to gracefully handle errors 348 // across API boundaries (and in particular across RPC boundaries). Some of 349 // these errors may be recoverable, but others may not. Most 350 // functions which can produce a recoverable error should be designed to return 351 // either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds 352 // either an object of type `T` or an error). 353 // 354 // API developers should construct their functions to return `absl::OkStatus()` 355 // upon success, or an `absl::StatusCode` upon another type of error (e.g 356 // an `absl::StatusCode::kInvalidArgument` error). The API provides convenience 357 // functions to construct each status code. 358 // 359 // Example: 360 // 361 // absl::Status myFunction(absl::string_view fname, ...) { 362 // ... 363 // // encounter error 364 // if (error condition) { 365 // // Construct an absl::StatusCode::kInvalidArgument error 366 // return absl::InvalidArgumentError("bad mode"); 367 // } 368 // // else, return OK 369 // return absl::OkStatus(); 370 // } 371 // 372 // Users handling status error codes should prefer checking for an OK status 373 // using the `ok()` member function. Handling multiple error codes may justify 374 // use of switch statement, but only check for error codes you know how to 375 // handle; do not try to exhaustively match against all canonical error codes. 376 // Errors that cannot be handled should be logged and/or propagated for higher 377 // levels to deal with. If you do use a switch statement, make sure that you 378 // also provide a `default:` switch case, so that code does not break as other 379 // canonical codes are added to the API. 380 // 381 // Example: 382 // 383 // absl::Status result = DoSomething(); 384 // if (!result.ok()) { 385 // LOG(ERROR) << result; 386 // } 387 // 388 // // Provide a default if switching on multiple error codes 389 // switch (result.code()) { 390 // // The user hasn't authenticated. Ask them to reauth 391 // case absl::StatusCode::kUnauthenticated: 392 // DoReAuth(); 393 // break; 394 // // The user does not have permission. Log an error. 395 // case absl::StatusCode::kPermissionDenied: 396 // LOG(ERROR) << result; 397 // break; 398 // // Propagate the error otherwise. 399 // default: 400 // return true; 401 // } 402 // 403 // An `absl::Status` can optionally include a payload with more information 404 // about the error. Typically, this payload serves one of several purposes: 405 // 406 // * It may provide more fine-grained semantic information about the error to 407 // facilitate actionable remedies. 408 // * It may provide human-readable contextual information that is more 409 // appropriate to display to an end user. 410 // 411 // Example: 412 // 413 // absl::Status result = DoSomething(); 414 // // Inform user to retry after 30 seconds 415 // // See more error details in googleapis/google/rpc/error_details.proto 416 // if (absl::IsResourceExhausted(result)) { 417 // google::rpc::RetryInfo info; 418 // info.retry_delay().seconds() = 30; 419 // // Payloads require a unique key (a URL to ensure no collisions with 420 // // other payloads), and an `absl::Cord` to hold the encoded data. 421 // absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo"; 422 // result.SetPayload(url, info.SerializeAsCord()); 423 // return result; 424 // } 425 // 426 // For documentation see https://abseil.io/docs/cpp/guides/status. 427 // 428 // Returned Status objects may not be ignored. status_internal.h has a forward 429 // declaration of the form 430 // class ABSL_MUST_USE_RESULT Status; 431 class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final { 432 public: 433 // Constructors 434 435 // This default constructor creates an OK status with no message or payload. 436 // Avoid this constructor and prefer explicit construction of an OK status 437 // with `absl::OkStatus()`. 438 Status(); 439 440 // Creates a status in the canonical error space with the specified 441 // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, // NOLINT 442 // `msg` is ignored and an object identical to an OK status is constructed. 443 // 444 // The `msg` string must be in UTF-8. The implementation may complain (e.g., // NOLINT 445 // by printing a warning) if it is not. 446 Status(absl::StatusCode code, absl::string_view msg); 447 448 Status(const Status&); 449 Status& operator=(const Status& x); 450 451 // Move operators 452 453 // The moved-from state is valid but unspecified. 454 Status(Status&&) noexcept; 455 Status& operator=(Status&&) noexcept; 456 457 ~Status(); 458 459 // Status::Update() 460 // 461 // Updates the existing status with `new_status` provided that `this->ok()`. 462 // If the existing status already contains a non-OK error, this update has no 463 // effect and preserves the current data. Note that this behavior may change 464 // in the future to augment a current non-ok status with additional 465 // information about `new_status`. 466 // 467 // `Update()` provides a convenient way of keeping track of the first error 468 // encountered. 469 // 470 // Example: 471 // // Instead of "if (overall_status.ok()) overall_status = new_status" 472 // overall_status.Update(new_status); 473 // 474 void Update(const Status& new_status); 475 void Update(Status&& new_status); 476 477 // Status::ok() 478 // 479 // Returns `true` if `this->code()` == `absl::StatusCode::kOk`, 480 // indicating the absence of an error. 481 // Prefer checking for an OK status using this member function. 482 ABSL_MUST_USE_RESULT bool ok() const; 483 484 // Status::code() 485 // 486 // Returns the canonical error code of type `absl::StatusCode` of this status. 487 absl::StatusCode code() const; 488 489 // Status::raw_code() 490 // 491 // Returns a raw (canonical) error code corresponding to the enum value of 492 // `google.rpc.Code` definitions within 493 // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto. 494 // These values could be out of the range of canonical `absl::StatusCode` 495 // enum values. 496 // 497 // NOTE: This function should only be called when converting to an associated 498 // wire format. Use `Status::code()` for error handling. 499 int raw_code() const; 500 501 // Status::message() 502 // 503 // Returns the error message associated with this error code, if available. 504 // Note that this message rarely describes the error code. It is not unusual 505 // for the error message to be the empty string. As a result, prefer 506 // `operator<<` or `Status::ToString()` for debug logging. 507 absl::string_view message() const; 508 509 friend bool operator==(const Status&, const Status&); 510 friend bool operator!=(const Status&, const Status&); 511 512 // Status::ToString() 513 // 514 // Returns a string based on the `mode`. By default, it returns combination of 515 // the error code name, the message and any associated payload messages. This 516 // string is designed simply to be human readable and its exact format should 517 // not be load bearing. Do not depend on the exact format of the result of 518 // `ToString()` which is subject to change. 519 // 520 // The printed code name and the message are generally substrings of the 521 // result, and the payloads to be printed use the status payload printer 522 // mechanism (which is internal). 523 std::string ToString( 524 StatusToStringMode mode = StatusToStringMode::kDefault) const; 525 526 // Support `absl::StrCat`, `absl::StrFormat`, etc. 527 template <typename Sink> 528 friend void AbslStringify(Sink& sink, const Status& status) { 529 sink.Append(status.ToString(StatusToStringMode::kWithEverything)); 530 } 531 532 // Status::IgnoreError() 533 // 534 // Ignores any errors. This method does nothing except potentially suppress 535 // complaints from any tools that are checking that errors are not dropped on 536 // the floor. 537 void IgnoreError() const; 538 539 // swap() 540 // 541 // Swap the contents of one status with another. 542 friend void swap(Status& a, Status& b) noexcept; 543 544 //---------------------------------------------------------------------------- 545 // Payload Management APIs 546 //---------------------------------------------------------------------------- 547 548 // A payload may be attached to a status to provide additional context to an 549 // error that may not be satisfied by an existing `absl::StatusCode`. 550 // Typically, this payload serves one of several purposes: 551 // 552 // * It may provide more fine-grained semantic information about the error 553 // to facilitate actionable remedies. 554 // * It may provide human-readable contextual information that is more 555 // appropriate to display to an end user. 556 // 557 // A payload consists of a [key,value] pair, where the key is a string 558 // referring to a unique "type URL" and the value is an object of type 559 // `absl::Cord` to hold the contextual data. 560 // 561 // The "type URL" should be unique and follow the format of a URL 562 // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some 563 // documentation or schema on how to interpret its associated data. For 564 // example, the default type URL for a protobuf message type is 565 // "type.googleapis.com/packagename.messagename". Other custom wire formats 566 // should define the format of type URL in a similar practice so as to 567 // minimize the chance of conflict between type URLs. 568 // Users should ensure that the type URL can be mapped to a concrete 569 // C++ type if they want to deserialize the payload and read it effectively. 570 // 571 // To attach a payload to a status object, call `Status::SetPayload()`, 572 // passing it the type URL and an `absl::Cord` of associated data. Similarly, 573 // to extract the payload from a status, call `Status::GetPayload()`. You 574 // may attach multiple payloads (with differing type URLs) to any given 575 // status object, provided that the status is currently exhibiting an error 576 // code (i.e. is not OK). 577 578 // Status::GetPayload() 579 // 580 // Gets the payload of a status given its unique `type_url` key, if present. 581 absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const; 582 583 // Status::SetPayload() 584 // 585 // Sets the payload for a non-ok status using a `type_url` key, overwriting 586 // any existing payload for that `type_url`. 587 // 588 // NOTE: This function does nothing if the Status is ok. 589 void SetPayload(absl::string_view type_url, absl::Cord payload); 590 591 // Status::ErasePayload() 592 // 593 // Erases the payload corresponding to the `type_url` key. Returns `true` if 594 // the payload was present. 595 bool ErasePayload(absl::string_view type_url); 596 597 // Status::ForEachPayload() 598 // 599 // Iterates over the stored payloads and calls the 600 // `visitor(type_key, payload)` callable for each one. 601 // 602 // NOTE: The order of calls to `visitor()` is not specified and may change at 603 // any time. 604 // 605 // NOTE: Any mutation on the same 'absl::Status' object during visitation is 606 // forbidden and could result in undefined behavior. 607 void ForEachPayload( 608 absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) 609 const; 610 611 private: 612 friend Status CancelledError(); 613 614 // Creates a status in the canonical error space with the specified 615 // code, and an empty error message. 616 explicit Status(absl::StatusCode code); 617 618 // Underlying constructor for status from a rep_. 619 explicit Status(uintptr_t rep) : rep_(rep) {} 620 621 static void Ref(uintptr_t rep); 622 static void Unref(uintptr_t rep); 623 624 // REQUIRES: !ok() 625 // Ensures rep is not inlined or shared with any other Status. 626 static absl::Nonnull<status_internal::StatusRep*> PrepareToModify( 627 uintptr_t rep); 628 629 // MSVC 14.0 limitation requires the const. 630 static constexpr const char kMovedFromString[] = 631 "Status accessed after move."; 632 633 static absl::Nonnull<const std::string*> EmptyString(); 634 static absl::Nonnull<const std::string*> MovedFromString(); 635 636 // Returns whether rep contains an inlined representation. 637 // See rep_ for details. 638 static constexpr bool IsInlined(uintptr_t rep); 639 640 // Indicates whether this Status was the rhs of a move operation. See rep_ 641 // for details. 642 static constexpr bool IsMovedFrom(uintptr_t rep); 643 static constexpr uintptr_t MovedFromRep(); 644 645 // Convert between error::Code and the inlined uintptr_t representation used 646 // by rep_. See rep_ for details. 647 static constexpr uintptr_t CodeToInlinedRep(absl::StatusCode code); 648 static constexpr absl::StatusCode InlinedRepToCode(uintptr_t rep); 649 650 // Converts between StatusRep* and the external uintptr_t representation used 651 // by rep_. See rep_ for details. 652 static uintptr_t PointerToRep(absl::Nonnull<status_internal::StatusRep*> r); 653 static absl::Nonnull<const status_internal::StatusRep*> RepToPointer( 654 uintptr_t r); 655 656 static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode); 657 658 // Status supports two different representations. 659 // - When the low bit is set it is an inlined representation. 660 // It uses the canonical error space, no message or payload. 661 // The error code is (rep_ >> 2). 662 // The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom(). 663 // - When the low bit is off it is an external representation. 664 // In this case all the data comes from a heap allocated Rep object. 665 // rep_ is a status_internal::StatusRep* pointer to that structure. 666 uintptr_t rep_; 667 668 friend class status_internal::StatusRep; 669 }; 670 671 // OkStatus() 672 // 673 // Returns an OK status, equivalent to a default constructed instance. Prefer 674 // usage of `absl::OkStatus()` when constructing such an OK status. 675 Status OkStatus(); 676 677 // operator<<() 678 // 679 // Prints a human-readable representation of `x` to `os`. 680 std::ostream& operator<<(std::ostream& os, const Status& x); 681 682 // IsAborted() 683 // IsAlreadyExists() 684 // IsCancelled() 685 // IsDataLoss() 686 // IsDeadlineExceeded() 687 // IsFailedPrecondition() 688 // IsInternal() 689 // IsInvalidArgument() 690 // IsNotFound() 691 // IsOutOfRange() 692 // IsPermissionDenied() 693 // IsResourceExhausted() 694 // IsUnauthenticated() 695 // IsUnavailable() 696 // IsUnimplemented() 697 // IsUnknown() 698 // 699 // These convenience functions return `true` if a given status matches the 700 // `absl::StatusCode` error code of its associated function. 701 ABSL_MUST_USE_RESULT bool IsAborted(const Status& status); 702 ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status); 703 ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status); 704 ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status); 705 ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status); 706 ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status); 707 ABSL_MUST_USE_RESULT bool IsInternal(const Status& status); 708 ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status); 709 ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status); 710 ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status); 711 ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status); 712 ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status); 713 ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status); 714 ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status); 715 ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status); 716 ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status); 717 718 // AbortedError() 719 // AlreadyExistsError() 720 // CancelledError() 721 // DataLossError() 722 // DeadlineExceededError() 723 // FailedPreconditionError() 724 // InternalError() 725 // InvalidArgumentError() 726 // NotFoundError() 727 // OutOfRangeError() 728 // PermissionDeniedError() 729 // ResourceExhaustedError() 730 // UnauthenticatedError() 731 // UnavailableError() 732 // UnimplementedError() 733 // UnknownError() 734 // 735 // These convenience functions create an `absl::Status` object with an error 736 // code as indicated by the associated function name, using the error message 737 // passed in `message`. 738 Status AbortedError(absl::string_view message); 739 Status AlreadyExistsError(absl::string_view message); 740 Status CancelledError(absl::string_view message); 741 Status DataLossError(absl::string_view message); 742 Status DeadlineExceededError(absl::string_view message); 743 Status FailedPreconditionError(absl::string_view message); 744 Status InternalError(absl::string_view message); 745 Status InvalidArgumentError(absl::string_view message); 746 Status NotFoundError(absl::string_view message); 747 Status OutOfRangeError(absl::string_view message); 748 Status PermissionDeniedError(absl::string_view message); 749 Status ResourceExhaustedError(absl::string_view message); 750 Status UnauthenticatedError(absl::string_view message); 751 Status UnavailableError(absl::string_view message); 752 Status UnimplementedError(absl::string_view message); 753 Status UnknownError(absl::string_view message); 754 755 // ErrnoToStatusCode() 756 // 757 // Returns the StatusCode for `error_number`, which should be an `errno` value. 758 // See https://en.cppreference.com/w/cpp/error/errno_macros and similar 759 // references. 760 absl::StatusCode ErrnoToStatusCode(int error_number); 761 762 // ErrnoToStatus() 763 // 764 // Convenience function that creates a `absl::Status` using an `error_number`, 765 // which should be an `errno` value. 766 Status ErrnoToStatus(int error_number, absl::string_view message); 767 768 //------------------------------------------------------------------------------ 769 // Implementation details follow 770 //------------------------------------------------------------------------------ 771 772 inline Status::Status() : Status(absl::StatusCode::kOk) {} 773 774 inline Status::Status(absl::StatusCode code) : Status(CodeToInlinedRep(code)) {} 775 776 inline Status::Status(const Status& x) : Status(x.rep_) { Ref(rep_); } 777 778 inline Status& Status::operator=(const Status& x) { 779 uintptr_t old_rep = rep_; 780 if (x.rep_ != old_rep) { 781 Ref(x.rep_); 782 rep_ = x.rep_; 783 Unref(old_rep); 784 } 785 return *this; 786 } 787 788 inline Status::Status(Status&& x) noexcept : Status(x.rep_) { 789 x.rep_ = MovedFromRep(); 790 } 791 792 inline Status& Status::operator=(Status&& x) noexcept { 793 uintptr_t old_rep = rep_; 794 if (x.rep_ != old_rep) { 795 rep_ = x.rep_; 796 x.rep_ = MovedFromRep(); 797 Unref(old_rep); 798 } 799 return *this; 800 } 801 802 inline void Status::Update(const Status& new_status) { 803 if (ok()) { 804 *this = new_status; 805 } 806 } 807 808 inline void Status::Update(Status&& new_status) { 809 if (ok()) { 810 *this = std::move(new_status); 811 } 812 } 813 814 inline Status::~Status() { Unref(rep_); } 815 816 inline bool Status::ok() const { 817 return rep_ == CodeToInlinedRep(absl::StatusCode::kOk); 818 } 819 820 inline absl::StatusCode Status::code() const { 821 return status_internal::MapToLocalCode(raw_code()); 822 } 823 824 inline int Status::raw_code() const { 825 if (IsInlined(rep_)) return static_cast<int>(InlinedRepToCode(rep_)); 826 return static_cast<int>(RepToPointer(rep_)->code()); 827 } 828 829 inline absl::string_view Status::message() const { 830 return !IsInlined(rep_) 831 ? RepToPointer(rep_)->message() 832 : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString) 833 : absl::string_view()); 834 } 835 836 inline bool operator==(const Status& lhs, const Status& rhs) { 837 if (lhs.rep_ == rhs.rep_) return true; 838 if (Status::IsInlined(lhs.rep_)) return false; 839 if (Status::IsInlined(rhs.rep_)) return false; 840 return *Status::RepToPointer(lhs.rep_) == *Status::RepToPointer(rhs.rep_); 841 } 842 843 inline bool operator!=(const Status& lhs, const Status& rhs) { 844 return !(lhs == rhs); 845 } 846 847 inline std::string Status::ToString(StatusToStringMode mode) const { 848 return ok() ? "OK" : ToStringSlow(rep_, mode); 849 } 850 851 inline void Status::IgnoreError() const { 852 // no-op 853 } 854 855 inline void swap(absl::Status& a, absl::Status& b) noexcept { 856 using std::swap; 857 swap(a.rep_, b.rep_); 858 } 859 860 inline absl::optional<absl::Cord> Status::GetPayload( 861 absl::string_view type_url) const { 862 if (IsInlined(rep_)) return absl::nullopt; 863 return RepToPointer(rep_)->GetPayload(type_url); 864 } 865 866 inline void Status::SetPayload(absl::string_view type_url, absl::Cord payload) { 867 if (ok()) return; 868 status_internal::StatusRep* rep = PrepareToModify(rep_); 869 rep->SetPayload(type_url, std::move(payload)); 870 rep_ = PointerToRep(rep); 871 } 872 873 inline bool Status::ErasePayload(absl::string_view type_url) { 874 if (IsInlined(rep_)) return false; 875 status_internal::StatusRep* rep = PrepareToModify(rep_); 876 auto res = rep->ErasePayload(type_url); 877 rep_ = res.new_rep; 878 return res.erased; 879 } 880 881 inline void Status::ForEachPayload( 882 absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) 883 const { 884 if (IsInlined(rep_)) return; 885 RepToPointer(rep_)->ForEachPayload(visitor); 886 } 887 888 constexpr bool Status::IsInlined(uintptr_t rep) { return (rep & 1) != 0; } 889 890 constexpr bool Status::IsMovedFrom(uintptr_t rep) { return (rep & 2) != 0; } 891 892 constexpr uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { 893 return (static_cast<uintptr_t>(code) << 2) + 1; 894 } 895 896 constexpr absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { 897 ABSL_ASSERT(IsInlined(rep)); 898 return static_cast<absl::StatusCode>(rep >> 2); 899 } 900 901 constexpr uintptr_t Status::MovedFromRep() { 902 return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; 903 } 904 905 inline absl::Nonnull<const status_internal::StatusRep*> Status::RepToPointer( 906 uintptr_t rep) { 907 assert(!IsInlined(rep)); 908 return reinterpret_cast<const status_internal::StatusRep*>(rep); 909 } 910 911 inline uintptr_t Status::PointerToRep( 912 absl::Nonnull<status_internal::StatusRep*> rep) { 913 return reinterpret_cast<uintptr_t>(rep); 914 } 915 916 inline void Status::Ref(uintptr_t rep) { 917 if (!IsInlined(rep)) RepToPointer(rep)->Ref(); 918 } 919 920 inline void Status::Unref(uintptr_t rep) { 921 if (!IsInlined(rep)) RepToPointer(rep)->Unref(); 922 } 923 924 inline Status OkStatus() { return Status(); } 925 926 // Creates a `Status` object with the `absl::StatusCode::kCancelled` error code 927 // and an empty message. It is provided only for efficiency, given that 928 // message-less kCancelled errors are common in the infrastructure. 929 inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); } 930 931 // Retrieves a message's status as a null terminated C string. The lifetime of 932 // this string is tied to the lifetime of the status object itself. 933 // 934 // If the status's message is empty, the empty string is returned. 935 // 936 // StatusMessageAsCStr exists for C support. Use `status.message()` in C++. 937 absl::Nonnull<const char*> StatusMessageAsCStr( 938 const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND); 939 940 ABSL_NAMESPACE_END 941 } // namespace absl 942 943 #endif // ABSL_STATUS_STATUS_H_