• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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