Storage capabilities 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.
Standard storage capability 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
Each storage capability must be backed by a corresponding 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.
The framework allocates storage subdirectories based on either the component instance's moniker or a static instance ID . 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:
{
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.
Providing storage capabilities
To provide a storage capability, a component must declare the capability and
route it from self
.
{
capabilities: [
{
storage: "tmp",
from: "self",
backing_dir: "memfs",
storage_id: "static_instance_id",
},
],
}
You must specify backing_dir
with a valid directory capability
name.
The from
field declares the component providing the backing directory.
You may supply a component reference if the provider is
another component.
Routing storage capabilities
Storage capabilities cannot be exposed to a parent component. Components should route the backing directory to an appropriate parent component where storage can be declared and offered to the necessary children.
For more details on how the framework routes component capabilities, see capability routing.
Offering
Offering a storage capability gives a child component access to that capability:
{
offer: [
{
storage: "data",
from: "self",
to: [ "#storage-user" ],
},
],
}
Consuming storage capabilities
To consume a storage capability, the component must request the capability and open the corresponding path in its namespace .
To request the capability, add a use
declaration for it:
{
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.
Storage example
Consider the following example where component A
requests isolated storage
tmp
from its parent:
// 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:
// 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.