blob: 7e0806eeb671132690d155f46728d9890c7653ba [file] [log] [blame] [view]
# Realms
A [glossary.realm] is the term for any [glossary.component] and its
[children][glossary.child-component-instance]. In other words, realm is another
word for any sub-tree of the
[component instance tree][glossary.component-instance-tree].
Component instances may contain [children](#child-component-instances). Each
[child component instance](/docs/glossary#child-component-instance) in turn
defines its own [sub-realm](/docs/glossary#sub-realm). The union of these
sub-realms, along with the
[parent component instance](/docs/glossary#parent-component-instance), is
equivalent to a subtree. Therefore, it is common to conceive of a realm as a
component instance along with its set of children.
Realms play a special role in the component framework. A realm is an
*encapsulation boundary* for component instances. This means:
- Realms act as a [capability](/docs/glossary#capability) boundary. It's up to
the realm to decide whether a capability originating in the realm can be
[routed](/docs/glossary#capability-routing) to component instances
outside of the realm. This is accomplished through an [`expose`][expose]
declaration in a [component manifest][component-manifests].
- The internal structure of a sub-realm is opaque to the parent component
instance. For example, the sub-realm could be structured either as one or
multiple component instances, and from the perspective of the parent
component instance this looks the same as long as the sub-realm
[exposes][expose] the same set of capabilities.
A realm also acts as an *ownership boundary*, that is, a child component
instance is the root of a sub-realm that is owned by the parent, who controls
its existence. See [Child component instances](#child-component-instances) for
more information.
## Example
Here is an example of a realm with a capability routed through it:
<br>![Realm example](images/realm_example.png)<br>
In this example, the `shell` component has two children: `tools` and `services`.
`services` has two children, `logger` and `echo`, while `tools` has one child
`echo_tool`. Components encapsulate their children, so while the `shell`
component sees its own children, it has no direct knowledge of its grandchildren
`echo_tool`, `logger`, or `echo`. Nevertheless, all of these component instances
are considered part of the `shell` realm.
The arrows illustrate the path of an `fuchsia.Echo` service capability that is
routed through the realm from `echo` to `echo_tool`. The upward arrows
correspond to [`expose`][expose] declarations, while the downward arrows
represent [`offer`][offer] declarations. The `expose` declarations cause
`fuchsia.Echo` to be exposed outside of the capability boundary of the
corresponding realms. For example, if `services` did not expose `fuchsia.Echo`,
`shell` would not be aware that `fuchsia.Echo` exists, and could not offer the
service to its children or access it at runtime.
For a more detailed walkthrough of capability routing with this example, see the
[component manifest capability routing example][component-manifest-examples].
## Child component instances {#child-component-instances}
Component instances may contain children. Child component instances are
considered part of the parent instance's definition and are wholly owned by the
parent. This has the following implications:
- A component instance decides what children it contains, and when its
children are created and destroyed.
- A component instance cannot exist without its parent.
- A component instance may not execute unless its parent is executing.
- A component instance determines the capabilities available to its children
by making [`offer`][offer] declarations to them.
- A component instance has some degree of control over the behavior of its
children. For example, a component instance may bind to capabilities exposed
from the child's realm through the [`Realm`](#realm-framework-protocol)
framework service, or set hooks to intercept child lifecycle events. This
control is not absolute, however. For example, a component instance cannot
use a capability from a sub-realm that was not explicitly exposed to it.
There are two varieties of child component instances, [static](#static-children)
and [dynamic](#dynamic-children).
### Static children {#static-children}
A *static child* is a component instance that was statically declared in the
component's [manifest][component-manifests] by a [`children`][children]
declaration. This declaration is necessary and sufficient to establish the child
component instance's existence.
Typically, a child should be statically declared unless it has a reason to be
dynamic (see [Dynamic children](#dynamic-children)). When a child is statically
declared, its definition and capabilities can be audited and capabilities can be
statically routed from it.
A static child is defined, foremost, by two pieces of information:
- The child instance's *name*. The name is local to the parent component
instance, and is used to form [monikers][monikers]. It is valid to declare
multiple children with the same URL and different names.
- The child instance's [component URL][component-urls].
For information on providing additional configuration information to child
declarations, see [children][children].
### Dynamic children {#dynamic-children}
A *dynamic child* is a component instance that was created at runtime in a
[component collection](#collections). A dynamic child is always scoped
to a particular collection. Dynamic children can be used to support use cases
where the existence or cardinality of component instances cannot be determined
in advance. For example, a testing realm might declare a collection in which
test component instances can be created.
Most of the metadata to create a dynamic child is identical to that used to
declare a static instance, except that it's provided at runtime. The name of a
dynamic child is implicitly scoped to its collection; thus it is possible to
have two dynamic children in two different collections with the same name.
Capabilities cannot be statically routed from dynamic instances. This is an
inherent restriction: there's no way to statically declare a route from a
capability exposed by a dynamic instance. However, certain capabilities can be
routed from the collection as a whole. TODO: service directories as an example
### Component collections {#collections}
A *collection* is a container for [dynamic children](#dynamic-children) that
may be created and destroyed at runtime using the
[Realm](#realm-framework-protocol) framework service.
Collections support two modes of *durability*:
- *Transient*: The instances in a *transient* collection are automatically
destroyed when the instance containing the collection is stopped.
- *Single Run*: The instances in a *single run* collection are started when
they are created, and destroyed when they are stopped. This means that the
instances in a single run collection can only be run once.
For more information about component execution and persistence, see
[lifecycle][lifecycle].
Collections are declared in the [`collections`][collections] section of a
component manifest. When an [`offer`][offer] declaration targets a collection,
the offered capability is made available to every instance in the collection.
Some capabilities can be exposed or offered from the collection as a whole, as
an aggregation over the corresponding capabilities exposed by the instances in
the collection.
TODO: service directories as an example
#### Example
The following diagram illustrates a realm with a collection:
<br>![Collection example](images/collection_example.png)<br>
In this example, the `shell` component declares a static child `console` and a
collection `(tools)`, highlighted by the grey background (the `()` notation
denotes a collection). `(tools)` contains two dynamic instances, `ls` and
`grep`. These instances are dynamic children of `shell`, scoped to `(tools)`.
The use of a collection implies that the existence of `ls` and `grep` is not
known in advance. This is plausible if you imagine that `ls` and `grep` are
command-line tools that are instantiated on demand as the user requests them.
The example also illustrates a capability routing path with the arrows. First,
`console` [exposes][expose] `fuchsia.Console` to its parent `shell`, which
[offers][offer] it to `(tools)`. `fuchsia.Console` then becomes available for
any component instance in the collection to [use][use] -- it does not need to be
routed to the dynamic instances independently.
## Environments {#environments}
Every realm is assigned an [environment][environments], which configures certain
choices the framework makes for components in a realm. For example,
[runner capabilities][runners] are registered to an environment, which makes
them available to any component instance in the realm. Read
[Environments][environments] for information on what properties are configurable
through the environment.
## The Realm framework protocol {#realm-framework-protocol}
There is a [framework protocol][framework-protocols] available to every
component, [`fuchsia.component.Realm`][realm.fidl]. The `Realm` protocol provides
APIs for a component instance to manage the children in its realm, such as
binding to children and creating dynamic children. See the linked FIDL
definitions for full documentation.
[glossary.storage capability]: /docs/glossary/README.md#storage-capability
[children]: https://fuchsia.dev/reference/cml#children
[collections]: https://fuchsia.dev/reference/cml#collections
[component-manifest-examples]: ./component_manifests.md#examples
[component-manifests]: ./component_manifests.md
[component-urls]: /docs/concepts/components/v2/identifiers.md#component-urls
[environments]: ./environments.md
[expose]: https://fuchsia.dev/reference/cml#expose
[offer]: https://fuchsia.dev/reference/cml#offer
[framework-protocols]: ./capabilities/protocol.md#framework
[monikers]: ./identifiers.md#monikers
[realm.fidl]: https://fuchsia.dev/reference/fidl/fuchsia.component#Realm
[runners]: ./capabilities/runner.md
[topology-instance-tree]: ./topology.md#component-instance-tree
[use]: https://fuchsia.dev/reference/cml#use
[lifecycle]: /docs/concepts/components/v2/lifecycle.md