1.. _module-pw_status: 2 3--------- 4pw_status 5--------- 6``pw_status`` provides features for communicating the result of an operation. 7The classes in ``pw_status`` are used extensively throughout Pigweed. 8 9pw::Status 10========== 11The primary feature of ``pw_status`` is the ``pw::Status`` class. 12``pw::Status`` (``pw_status/status.h``) is a simple, zero-overhead status 13object that wraps a status code. 14 15``pw::Status`` uses Google's standard status codes (see the `Google APIs 16repository <https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto>`_). 17These codes are used extensively in Google projects including `Abseil 18<https://abseil.io>`_ (`status/status.h 19<https://cs.opensource.google/abseil/abseil-cpp/+/master:absl/status/status.h>`_ 20) and `gRPC <https://grpc.io>`_ (`doc/statuscodes.md 21<https://github.com/grpc/grpc/blob/master/doc/statuscodes.md>`_). 22 23An OK ``Status`` is created by the ``pw::OkStatus`` function or by the default 24``Status`` constructor. Non-OK ``Status`` is created with a static member 25function that corresponds with the status code. 26 27.. code-block:: cpp 28 29 // Ok (gRPC code "OK") does not indicate an error; this value is returned on 30 // success. It is typical to check for this value before proceeding on any 31 // given call across an API or RPC boundary. To check this value, use the 32 // `status.ok()` member function rather than inspecting the raw code. 33 // 34 // OkStatus() is provided as a free function, rather than a static member 35 // function like the error statuses to avoid conflicts with the ok() member 36 // function. Status::Ok() would be too similar to Status::ok(). 37 pw::OkStatus() 38 39 // Cancelled (gRPC code "CANCELLED") indicates the operation was cancelled, 40 // typically by the caller. 41 pw::Status::Cancelled() 42 43 // Unknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In 44 // general, more specific errors should be raised, if possible. Errors raised 45 // by APIs that do not return enough error information may be converted to 46 // this error. 47 pw::Status::Unknown() 48 49 // InvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller 50 // specified an invalid argument, such a malformed filename. Note that such 51 // errors should be narrowly limited to indicate to the invalid nature of the 52 // arguments themselves. Errors with validly formed arguments that may cause 53 // errors with the state of the receiving system should be denoted with 54 // `FailedPrecondition` instead. 55 pw::Status::InvalidArgument() 56 57 // DeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline 58 // expired before the operation could complete. For operations that may change 59 // state within a system, this error may be returned even if the operation has 60 // completed successfully. For example, a successful response from a server 61 // could have been delayed long enough for the deadline to expire. 62 pw::Status::DeadlineExceeded() 63 64 // NotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as 65 // a file or directory) was not found. 66 // 67 // `NotFound` is useful if a request should be denied for an entire class of 68 // users, such as during a gradual feature rollout or undocumented allow list. 69 // If, instead, a request should be denied for specific sets of users, such as 70 // through user-based access control, use `PermissionDenied` instead. 71 pw::Status::NotFound() 72 73 // AlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a 74 // caller attempted to create (such as file or directory) is already present. 75 pw::Status::AlreadyExists() 76 77 // PermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller 78 // does not have permission to execute the specified operation. Note that this 79 // error is different than an error due to an *un*authenticated user. This 80 // error code does not imply the request is valid or the requested entity 81 // exists or satisfies any other pre-conditions. 82 // 83 // `PermissionDenied` must not be used for rejections caused by exhausting 84 // some resource. Instead, use `ResourceExhausted` for those errors. 85 // `PermissionDenied` must not be used if the caller cannot be identified. 86 // Instead, use `Unauthenticated` for those errors. 87 pw::Status::PermissionDenied() 88 89 // ResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource 90 // has been exhausted, perhaps a per-user quota, or perhaps the entire file 91 // system is out of space. 92 pw::Status::ResourceExhausted() 93 94 // FailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the 95 // operation was rejected because the system is not in a state required for 96 // the operation's execution. For example, a directory to be deleted may be 97 // non-empty, an "rmdir" operation is applied to a non-directory, etc. 98 // 99 // Some guidelines that may help a service implementer in deciding between 100 // `FailedPrecondition`, `Aborted`, and `Unavailable`: 101 // 102 // (a) Use `Unavailable` if the client can retry just the failing call. 103 // (b) Use `Aborted` if the client should retry at a higher transaction 104 // level (such as when a client-specified test-and-set fails, indicating 105 // the client should restart a read-modify-write sequence). 106 // (c) Use `FailedPrecondition` if the client should not retry until 107 // the system state has been explicitly fixed. For example, if an "rmdir" 108 // fails because the directory is non-empty, `FailedPrecondition` 109 // should be returned since the client should not retry unless 110 // the files are deleted from the directory. 111 pw::Status::FailedPrecondition() 112 113 // Aborted (gRPC code "ABORTED") indicates the operation was aborted, 114 // typically due to a concurrency issue such as a sequencer check failure or a 115 // failed transaction. 116 // 117 // See the guidelines above for deciding between `FailedPrecondition`, 118 // `Aborted`, and `Unavailable`. 119 pw::Status::Aborted() 120 121 // OutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was 122 // attempted past the valid range, such as seeking or reading past an 123 // end-of-file. 124 // 125 // Unlike `InvalidArgument`, this error indicates a problem that may 126 // be fixed if the system state changes. For example, a 32-bit file 127 // system will generate `InvalidArgument` if asked to read at an 128 // offset that is not in the range [0,2^32-1], but it will generate 129 // `OutOfRange` if asked to read from an offset past the current 130 // file size. 131 // 132 // There is a fair bit of overlap between `FailedPrecondition` and 133 // `OutOfRange`. We recommend using `OutOfRange` (the more specific 134 // error) when it applies so that callers who are iterating through 135 // a space can easily look for an `OutOfRange` error to detect when 136 // they are done. 137 pw::Status::OutOfRange() 138 139 // Unimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not 140 // implemented or supported in this service. In this case, the operation 141 // should not be re-attempted. 142 pw::Status::Unimplemented() 143 144 // Internal (gRPC code "INTERNAL") indicates an internal error has occurred 145 // and some invariants expected by the underlying system have not been 146 // satisfied. This error code is reserved for serious errors. 147 pw::Status::Internal() 148 149 // Unavailable (gRPC code "UNAVAILABLE") indicates the service is currently 150 // unavailable and that this is most likely a transient condition. An error 151 // such as this can be corrected by retrying with a backoff scheme. Note that 152 // it is not always safe to retry non-idempotent operations. 153 // 154 // See the guidelines above for deciding between `FailedPrecondition`, 155 // `Aborted`, and `Unavailable`. 156 pw::Status::Unavailable() 157 158 // DataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or 159 // corruption has occurred. As this error is serious, proper alerting should 160 // be attached to errors such as this. 161 pw::Status::DataLoss() 162 163 // Unauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request 164 // does not have valid authentication credentials for the operation. Correct 165 // the authentication and try again. 166 pw::Status::Unauthenticated() 167 168.. attention:: 169 170 Some code may use all-caps status values such as ``Status::UNKNOWN`` instead 171 of ``Status::Unknown()``. These all-caps status codes are deprecated and will 172 be removed in the future. Do not use them; use the functions above instead. 173 174 The all-caps status aliases were deprecated because they do not comply with 175 the style guide and potentially conflict with macro definitions. For example, 176 projects might define an ``INTERNAL`` macro, which would prevent ``status.h`` 177 or code that uses ``Status::INTERNAL`` from compiling. 178 179 The Python tool ``pw_status/update_style.py`` may be used to migrate code in a 180 Git repo to the new status style. 181 182C compatibility 183--------------- 184``pw_status`` provides the C-compatible ``pw_Status`` enum for the status codes. 185For ease of use, ``pw::Status`` implicitly converts to and from ``pw_Status``. 186However, the ``pw_Status`` enum should never be used in C++; instead use the 187``Status`` class. 188 189The values of the ``pw_Status`` enum are all-caps and prefixed with 190``PW_STATUS_``. For example, ``PW_STATUS_DATA_LOSS`` corresponds with the C++ 191``Status::DataLoss()``. 192 193StatusWithSize 194============== 195``pw::StatusWithSize`` (``pw_status/status_with_size.h``) is a convenient, 196efficient class for reporting a status along with an unsigned integer value. 197It is similar to the ``pw::Result<T>`` class, but it stores both a size and a 198status, regardless of the status value, and only supports a limited range (27 199bits). 200 201``pw::StatusWithSize`` values may be created with functions similar to 202``pw::Status``. For example, 203 204 .. code-block:: cpp 205 206 // An OK StatusWithSize with a size of 123. 207 StatusWithSize(123) 208 209 // A NOT_FOUND StatusWithSize with a size of 0. 210 StatusWithSize::NotFound() 211 212 // A RESOURCE_EXHAUSTED StatusWithSize with a size of 10. 213 StatusWithSize::ResourceExhausted(10) 214 215PW_TRY 216====== 217``PW_TRY`` (``pw_status/try.h``) is a convenient set of macros for working 218with Status and StatusWithSize objects in functions that return Status or 219StatusWithSize. The PW_TRY and PW_TRY_WITH_SIZE macros call a function and 220do an early return if the function's return status is not ok. 221 222Example: 223 224.. code-block:: cpp 225 226 Status PwTryExample() { 227 PW_TRY(FunctionThatReturnsStatus()); 228 PW_TRY(FunctionThatReturnsStatusWithSize()); 229 230 // Do something, only executed if both functions above return OK. 231 } 232 233 StatusWithSize PwTryWithSizeExample() { 234 PW_TRY_WITH_SIZE(FunctionThatReturnsStatus()); 235 PW_TRY_WITH_SIZE(FunctionThatReturnsStatusWithSize()); 236 237 // Do something, only executed if both functions above return OK. 238 } 239 240PW_TRY_ASSIGN is for working with StatusWithSize objects in in functions 241that return Status. It is similar to PW_TRY with the addition of assigning 242the size from the StatusWithSize on ok. 243 244.. code-block:: cpp 245 246 Status PwTryAssignExample() { 247 size_t size_value 248 PW_TRY_ASSIGN(size_value, FunctionThatReturnsStatusWithSize()); 249 250 // Do something that uses size_value. size_value is only assigned and this 251 // following code executed if the PW_TRY_ASSIGN function above returns OK. 252 } 253 254Compatibility 255============= 256C++11 257