blob: 0a01f6989bf31458cbda9211267d7435bbd4a7ce [file] [log] [blame] [view]
# Storage capabilities
[Storage capabilities][glossary.storage-capability] allocate per-component
*isolated* storage within a filesystem directory. This prevents component
instances from accessing files belonging to other components, including their
own children.
Different storage capabilities may be backed by different filesystems. A
component should not assume atomic IO operations are possible across storage
capabilities.
For information on directories that can be shared between components, see
[directory capabilities][directory-capabilities].
## Standard storage capability names {#standard-names}
Standard names are commonly used for storage capabilities. Each of these
standard names implies the storage capability should be used for a particular
purpose and provides a particular behavior. Any component that receives a
storage capability with one of these standard names may assume it provides the
behavior described below.
Note that a storage capability name does **not** necessarily globally identify a
storage capability. For example, on some products several different storage
capabilities named `data` exist at different locations in the component instance
topology. These storage capabilities are backed by different directories on
different storage volumes, but they all serve the same purpose for the component
instances using them.
Not all storage capabilities use one of these standard names. In these cases any
expectations about the behavior of the storage capability should be documented
where the storage capability is defined and at every place in the component
instance topology that the capability is renamed.
Note that during tests storage capabilities may be created that do not match
these behaviors. For example, an integration test may provide a `data`
capability that is wiped between test cases.
### `data`
Storage capabilities named "data" are intended to store general purpose
persistent data.
A component may assume that files in these storage capabilities
will not be deleted by the system. Components must be conservative in their use
of `data` because the contract does not let system delete files when the
limited disk space is exhausted. In many cases using `cache` is preferable.
### `cache`
Storage capabilities named "cache" are intended to store data that could be
discarded or regenerated if necessary. For example, a downloaded picture that
could be re-fetched.
Files stored in `cache` are usually persisted between different runs of same
component instance but this is not guaranteed. Files may be deleted by the
system at any time, even while the component is running.
### `tmp`
Storage capabilities named "tmp" are intended to store temporary or intermediate
data.
Files stored in `tmp` may be deleted by the system between runs of a component.
Files will not be deleted by the system while the component is running. `tmp`
will often be empty when a component is started but this is not guaranteed.
Components must not assume `tmp` will be empty on start but also should not use
any files that are present on start.
## Backing directories {#backing-dir}
Each storage capability must be backed by a corresponding
[directory capability][glossary.directory-capability] to host an isolated
subdirectory for each component. When a component instance attempts to access
the directory provided to it through a storage capability, the framework
generates a unique subdirectory inside the backing directory for that component.
Caution: The backing directory capability can also be routed directly to other
components. Providing this capability allows components to access all the
isolated storage directories it contains.
The framework allocates storage subdirectories based on either the component
instance's [moniker][glossary.moniker] or a static
[instance ID][glossary.component-instance-identifier]. Each instance ID is a
256-bit globally unique identifier listed in a component ID index file.
The following is an example entry in a component ID index file containing a
stable instance ID:
```json5
{
instances: [
{
instance_id: "47c3bf08f3e560c4dee659c28fa8d863dbdc0b1dbb74065e6cb1f38441ac759c",
moniker: "/core/my_component",
},
],
}
```
Instance IDs allow a component's storage to persist across changes to the
component's moniker, such as moving the component instance to a different realm.
Using a moniker is a good secondary option for tests or other use
cases where storage does not need to be durable.
For more details on instance IDs, see [Component ID index][component-id-index].
## Providing storage capabilities {#provide}
To provide a storage capability, a component must declare the capability and
[route](#route) it from `self`.
```json5
{
capabilities: [
{
storage: "tmp",
from: "self",
backing_dir: "memfs",
storage_id: "static_instance_id",
},
],
}
```
You must specify [`backing_dir`](#backing-dir) with a valid directory capability
name.
The `from` field declares the component providing the backing directory.
You may supply a [component reference][component-reference] if the provider is
another component.
## Routing storage capabilities {#route}
Storage capabilities cannot be exposed to a parent component. Components should
route the [backing directory](#backing-dir) to an appropriate parent component
where storage can be [declared](#provide) and [offered](#offer) to the necessary
children.
For more details on how the framework routes component capabilities,
see [capability routing][capability-routing].
### Offering {#offer}
Offering a storage capability gives a child component access to that
capability:
```json5
{
offer: [
{
storage: "data",
from: "self",
to: [ "#storage-user" ],
},
],
}
```
## Consuming storage capabilities {#consume}
To consume a storage capability, the component must request the capability and
open the corresponding path in its [namespace][glossary.namespace].
To request the capability, add a `use` declaration for it:
```json5
{
use: [
{
storage: "data",
path: "/example_dir",
},
],
}
```
This populates the component's namespace with a directory at the provided `path`
containing the isolated storage contents.
### Consuming optional storage capabilities
See [Connect Components: Consuming optional capabilities][consuming-optional-capabilities].
## Storage example {#example}
Consider the following example where component `A` requests isolated storage
`tmp` from its parent:
```json5
// A.cml
{
use: [
{
storage: "tmp",
path: "/example_dir",
},
],
}
```
This provides an isolated storage directory at `/example_dir` in the namespace
of component `A`.
The parent component `B` offers this capability to `A` using a backing directory
provided by the `memfs` component in the same realm:
```json5
// B.cml
{
capabilities: [
{
storage: "tmp",
from: "#memfs",
backing_dir: "memfs",
},
],
offer: [
{
storage: "tmp",
from: "self",
to: [ "#A" ],
},
],
children: [
{ name: "A", url: "fuchsia-pkg://...", },
{ name: "memfs", url: "fuchsia-pkg://..." },
],
}
```
For more details on implementing directories, see
[directory capabilities][directory-capabilities].
[glossary.directory-capability]: /docs/glossary/README.md#directory-capability
[glossary.component-instance-identifier]: /docs/glossary/README.md#component-instance-identifier
[glossary.moniker]: /docs/glossary/README.md#moniker
[glossary.namespace]: /docs/glossary/README.md#namespace
[glossary.storage-capability]: /docs/glossary/README.md#storage-capability
[capability-routing]: /docs/concepts/components/v2/capabilities/README.md#routing
[consuming-optional-capabilities]: /docs/development/components/connect.md#consuming-optional-capabilities
[component-reference]: https://fuchsia.dev/reference/cml#references
[directory-capabilities]: /docs/concepts/components/v2/capabilities/directory.md
[component-id-index]: /docs/development/components/component_id_index.md