Project: MongoDB (App Definition and Development / Database)
File: contexts.md

The state of all operations performed on Mongo server processes (i.e., `mongod` and `mongos`) is tracked and managed by a global singleton called the `ServiceContext`. A `ServiceContext` maintains an arbitrary number of `Client` objects, which each represent a logical connection to the database over which operations can be performed. Each operation in turn is managed by a single `OperationContext`. A `Client` object can only perform a single logical operation at a time, and thus can only maintain a single `OperationContext` at a time. Note that all of these classes are heavily decorated (i.e., they inherit from ), which makes them dynamically extensible. A `ServiceContext` represents all of the state of a single Mongo server process, which may be either a `mongod` or a `mongos`. It creates and manages the previously mentioned `Client`s and `OperationContext`s, as well as a `TransportLayer` for performing network operations, a `PeriodicRunner` for running housekeeping tasks periodically, a `StorageEngine` for interacting with the actual database itself, and a set of time sources. In general, every Mongo server process has a single `ServiceContext`, known as the global `ServiceContext`. Typical uses of the global `ServiceContext` outside of server initialization and shutdown include looking up `Client` or `OperationContext` information for a particular thread or operation, or killing one or more running operations during, e.g., a primary replica step-down. The global `ServiceContext` is created during initialization of a Mongo server process and is only destroyed at shutdown, and is thus available for the entire duration of server operation. At shutdown, the global `ServiceContext` will kill all outstanding `OperationContext`s and `Client`s. The `ServiceContext` associated with a given `Client` object can be fetched in a few ways; prefer using when possible. As of time of writing, every server process only maintains a single `ServiceContext`, but preferring `Client::getServiceContext()` or `ServiceContext::getCurrentServiceContext()` over will allow us to more easily maintain multiple `ServiceContext`s per server process if desired in the future. Each logical connection to a Mongo service is managed by a `Client` object, where a logical connection may be a user or an internal process that needs to run a command or query on the database. Construction of a `Client` object is typically performed with a call to `makeClient` on the global `ServiceContext`, which can then be attached to any thread of execution, or with a call to which constructs a `Client` on the global `ServiceContext` and binds it to the current thread. All operations executed by the `Client` will take place on that `Client`s associated thread serially over the network connection managed by the `Session` object that was passed into the `Client`s constructor. If no `Session` is passed to the `Client`s constructor, then the `Client` is assumed to operate on a local database and will perform no network

These `Client`s are sometimes referred to as local clients, and are often used when a Mongo service needs to query its own database. A `Client` will typically execute multiple operations over the course of its lifetime, spawning an `OperationContext` for each. Because these operations are executed serially, each `Client` is associated with up to one `OperationContext` at any given time. All `Client`s have an associated lock which protects their internal state including their currently associated `OperationContext` from concurrent access. Any mutation to a `Client`s associated `OperationContext` (or other protected internal state) must take the `Client` lock before being performed, as an `OperationContext` can otherwise be killed and destroyed at any time. A `Client` thread may read its own internal state without taking the `Client` lock, but must take the `Client` lock when reading another `Client` thread's internal state. Only a `Client`'s owning thread may write to its `Client`'s internal state, and must take the lock when doing so. `Client`s implement the standard lockable interface (`lock()`, `unlock()`, and `try_lock()`) to support these operations. The semantics of the `Client` lock are summarized in the table below. | Internal state | `Client`-owning thread | Other threads | | -- | - | - | | reads | always allowed | lock required | | writes | lock required | never allowed | may be used to get the `Client` object associated with the currently executing thread. Prefer passing `Client` objects as parameters over calls to `Client::cc()` when possible. A is an RAII-style class which may be used to construct and bind a `Client` to the current running thread and automatically unbind it once the `ThreadClient` goes out of scope. An is another RAII-style class which may be used to temporarily bind a `Client` object to the currently running thread (holding any currently bound `Client` in reserve), rebinding the current threads old `Client` to the current thread upon falling out of scope. functions similarly, but also provides an `Executor` interface for binding a `Client` to an arbitrary thread. Each operation that executes on a Mongo server (e.g., a query or a command) is managed by its own `OperationContext`. An `OperationContext` shepherds an operations execution from its inception to either completion or cancellation. Cancellation may be triggered externally, such as from the controlling `ServiceContext` on a primary step-down, or from a user-issued command; or internally, e.g., when an operations deadline has expired. Every `OperationContext` is associated with a single `Client`, which manages the logical connection to the database over which the operation will actually be executed. `OperationContext`s are also optionally associated with a , which represents a thread of execution on which networking operations can be performed asynchronously. `OperationContext`s implement the interface, which allows them to be killed by their associated `Client`s (or, by proxy, their owning `ServiceContext`). See for more details on when and how `OperationContext`s are interrupted.