Merge pull request #38585 from tchaikov/wip-doc-dev-errorator

doc/dev/crimson: highlight code blocks using C++ lexer

Reviewed-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
This commit is contained in:
Kefu Chai 2020-12-15 20:28:57 +08:00 committed by GitHub
commit 32921b7003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,16 +3,16 @@ error handling
==============
In Seastar, a `future` represents a value not yet available but that can become
available later. `future` can have one of following states:
In Seastar, a ``future`` represents a value not yet available but that can become
available later. ``future`` can have one of following states:
* unavailable: value is not available yet,
* value,
* failed: an exception was thrown when computing the value. This exception has
been captured and stored in the `future` instance via `std::exception_ptr`.
been captured and stored in the ``future`` instance via ``std::exception_ptr``.
In the last case, the exception can be processed using `future::handle_exception()` or
`future::handle_exception_type()`. Seastar even provides `future::or_terminate()` to
In the last case, the exception can be processed using ``future::handle_exception()`` or
``future::handle_exception_type()``. Seastar even provides ``future::or_terminate()`` to
terminate the program if the future fails.
But in Crimson, quite a few errors are not serious enough to fail the program entirely.
@ -26,36 +26,36 @@ that all expected errors are handled. It should be something like the statical a
performed by compiler to spit a warning if any enum value is not handled in a ``switch-case``
statement.
Unfortunately, `seastar::future` is not able to satisfy these two requirements.
Unfortunately, ``seastar::future`` is not able to satisfy these two requirements.
* Seastar imposes re-throwing an exception to dispatch between different types of
exceptions. This is not very performant nor even scalable as locking in the language's
runtime can occur.
* Seastar does not encode the expected exception type in the type of the returned
`seastar::future`. Only the type of the value is encoded. This imposes huge
``seastar::future``. Only the type of the value is encoded. This imposes huge
mental load on programmers as ensuring that all intended errors are indeed handled
requires manual code audit.
So, "errorator" is created. It is a wrapper around the vanilla `seastar::future`.
.. highlight:: c++
So, "errorator" is created. It is a wrapper around the vanilla ``seastar::future``.
It addresses the performance and scalability issues while embedding the information
about all expected types-of-errors to the type-of-future.::
using ertr = crimson::errorator<crimson::ct_error::enoent,
crimson::ct_error::einval>;
In above example we defined an errorator that allows for two error types:
* `crimson::ct_error::enoent` and
* `crimson::ct_error::einval`.
* ``crimson::ct_error::enoent`` and
* ``crimson::ct_error::einval``.
These (and other ones in the `crimson::ct_error` namespace) are basically
unthrowable wrappers over `std::error_code` to exclude accidental throwing
These (and other ones in the ``crimson::ct_error`` namespace) are basically
unthrowable wrappers over ``std::error_code`` to exclude accidental throwing
and ensure signaling errors in a way that enables compile-time checking.
The most fundamental thing in an errorator is a descendant of `seastar::future`
which can be used as e.g. function's return type:::
The most fundamental thing in an errorator is a descendant of ``seastar::future``
which can be used as e.g. function's return type::
static ertr::future<int> foo(int bar) {
if (bar == 42) {
@ -66,7 +66,7 @@ which can be used as e.g. function's return type:::
}
It's worth to note that returning an error that is not a part the errorator's error set
would result in a compile-time error:::
would result in a compile-time error::
static ertr::future<int> foo(int bar) {
// Oops, input_output_error is not allowed in `ertr`. static_assert() will
@ -80,9 +80,9 @@ would result in a compile-time error:::
The errorator concept goes further. It not only provides callers with the information
about all potential errors embedded in the function's type; it also ensures at the caller
site that all these errors are handled. As the reader probably know, the main method
in `seastar::future` is `then()`. On errorated future it is available but only if errorator's
error set is empty (literally: `errorator<>::future`); otherwise callers have
to use `safe_then()` instead:::
in ``seastar::future`` is ``then()``. On errorated future it is available but only if errorator's
error set is empty (literally: ``errorator<>::future``); otherwise callers have
to use ``safe_then()`` instead::
seastar::future<> baz() {
return foo(42).safe_then(
@ -102,10 +102,10 @@ to use `safe_then()` instead:::
});
}
In the above example `ertr::all_same_way` has been used to handle all errors in the same
In the above example ``ertr::all_same_way`` has been used to handle all errors in the same
manner. This is not obligatory -- a caller can handle each of them separately. Moreover,
it can provide a handler for only a subset of errors. The price for that is the availability
of `then()`::
of ``then()``::
using einval_ertr = crimson::errorator<crimson::ct_error::einval>;
@ -129,9 +129,9 @@ of `then()`::
}
That is, handling errors removes them from errorated future's error set. This works
in the opposite direction too -- returning new errors in `safe_then()` appends them
the error set. Of course, this set must be compliant with error set in the `baz()`'s
signature:::
in the opposite direction too -- returning new errors in ``safe_then()`` appends them
the error set. Of course, this set must be compliant with error set in the ``baz()``'s
signature::
using broader_ertr = crimson::errorator<crimson::ct_error::enoent,
crimson::ct_error::einval,
@ -149,7 +149,7 @@ signature:::
ertr::pass_further{});
}
As it can be seen, handling and signaling errors in `safe_then()` is basically
As it can be seen, handling and signaling errors in ``safe_then()`` is basically
an operation on the error set checked at compile-time.
More details can be found in `the slides from ceph::errorator<> throw/catch-free,