mirror of https://github.com/mongodb/mongo
86 lines
4.7 KiB
Markdown
86 lines
4.7 KiB
Markdown
# Server-Internal Baton Pattern
|
|
|
|
Batons are lightweight job queues in _mongod_ and _mongos_ processes that allow
|
|
recording the intent to execute a task (e.g., polling on a network socket) and
|
|
deferring its execution to a later time. Batons, often by reusing `Client`
|
|
threads and through the _Waitable_ interface, move the execution of scheduled
|
|
tasks out of the line, potentially hiding the execution cost from the critical
|
|
path. A total of four baton classes are available today:
|
|
|
|
- [Baton][baton]
|
|
- [DefaultBaton][defaultBaton]
|
|
- [NetworkingBaton][networkingBaton]
|
|
- [AsioNetworkingBaton][asioNetworkingBaton]
|
|
|
|
## Baton Basics
|
|
|
|
All baton implementations extend _Baton_. They are tightly associated with an
|
|
`OperationContext` and its `Client` thread. An `OperationContext` that belongs
|
|
to a `ServiceContext` with a `TransportLayer` uses an `AsioNetworkingBaton`,
|
|
else a `DefaultBaton`. The baton is accessed through the `OperationContext` with
|
|
a call to `OperationContext::getBaton()`.
|
|
|
|
Each baton implementation exposes an interface to allow scheduling tasks on the
|
|
baton, to demand the awakening of the baton on client socket disconnect, and to
|
|
create a _SubBaton_. A _SubBaton_, for any of the baton types, is essentially a
|
|
handle to a local object that proxies scheduling requests to its underlying baton
|
|
until it is detached (e.g., through destruction of its handle).
|
|
|
|
Additionally, a _NetworkingBaton_ enables consumers of a transport layer to
|
|
execute I/O themselves, rather than delegating it to other threads. They are
|
|
special batons that are able to poll network sockets, which is not feasible
|
|
through other baton types. This is essential for minimizing context switches and
|
|
improving the readability of stack traces.
|
|
|
|
A baton runs automatically when blocking on its associated `OperationContext`
|
|
with a call to `OperationContext::waitForConditionOrInterrupt()`. Many different
|
|
apis that take in or use an _Interruptible_ will eventually call into this method
|
|
(e.g. `Future::get(...)`, `OperationContext::sleepUntil(...)`, etc.).
|
|
|
|
### DefaultBaton
|
|
|
|
DefaultBaton is the most basic baton implementation. This baton provides the
|
|
platform to execute tasks while a client thread awaits an event or a timeout,
|
|
essentially paving the way towards utilizing idle cycles of client threads for
|
|
useful work. Tasks can be scheduled on this baton through its associated
|
|
`OperationContext` and using `OperationContext::getBaton()::schedule(...)`.
|
|
|
|
Note that because _Baton_ extends an _OutOfLineExecutor_, it can be used as the
|
|
executor to run work on an `ExecutorFuture`.
|
|
|
|
### AsioNetworkingBaton
|
|
|
|
The AsioNetworkingBaton can schedule and run tasks similarly to the _DefaultBaton_,
|
|
but it also implements the _NetworkingBaton_ interface to provide a networking
|
|
reactor. It can register sessions to monitor and will utilize `poll(2)` and
|
|
`eventfd(2)` to wait until I/O can be performed on the socket or until interrupted.
|
|
|
|
This baton is primarily used for egress networking where it gets scheduled to send
|
|
off a command after a connection is made (see the relevant code [here][asioNetworkingBatonScheduling]).
|
|
This means that the AsioNetworkingBaton will normally perform socket I/O without
|
|
needing to poll. It only registers a session for polling if another read or
|
|
write is needed on the socket (e.g. [registering a session during socket read][asioNetworkingBatonPollingSetup]).
|
|
|
|
In order for an egress session to use the baton, it must be specified as an
|
|
argument to `TaskExecutor::scheduleRemoteCommand(...)`.
|
|
|
|
Note that this baton is only available for Linux.
|
|
|
|
## Example
|
|
|
|
For an example of scheduling a task on the `OperationContext` baton, see
|
|
[here][example].
|
|
|
|
## Considerations
|
|
|
|
Since any task scheduled on a baton is intended for out-of-line execution, it
|
|
must be non-blocking and preferably short-lived to ensure forward progress.
|
|
|
|
[baton]: https://github.com/mongodb/mongo/blob/5906d967c3144d09fab6a4cc1daddb295df19ffb/src/mongo/db/baton.h#L61-L178
|
|
[defaultBaton]: https://github.com/mongodb/mongo/blob/9cfe13115e92a43d1b9273ee1d5817d548264ba7/src/mongo/db/default_baton.h#L46-L75
|
|
[networkingBaton]: https://github.com/mongodb/mongo/blob/9cfe13115e92a43d1b9273ee1d5817d548264ba7/src/mongo/transport/baton.h#L61-L96
|
|
[asioNetworkingBaton]: https://github.com/mongodb/mongo/blob/9cfe13115e92a43d1b9273ee1d5817d548264ba7/src/mongo/transport/baton_asio_linux.h#L60-L529
|
|
[asioNetworkingBatonScheduling]: https://github.com/mongodb/mongo/blob/46b8c49b4e13cc4c8389b2822f9e30dd73b81d6e/src/mongo/executor/network_interface_tl.cpp#L910
|
|
[asioNetworkingBatonPollingSetup]: https://github.com/mongodb/mongo/blob/eab4ec41cc2b28bf0a38eb813f9690e1bfa6c9a6/src/mongo/transport/asio/asio_session_impl.cpp#L666-L696
|
|
[example]: https://github.com/mongodb/mongo/blob/262e5a961fa7221bfba5722aeea2db719f2149f5/src/mongo/s/multi_statement_transaction_requests_sender.cpp#L91-L99
|