Availability

若要选择哪些功能进入其 namespace,组件会在其 manifest 中为每项功能指定 use 声明。不过,由于功能路由涉及一系列组件,因此即使组件 use 具有某项功能,也不意味着该功能始终可用。它可能会因各种原因而变得不可用:例如,如果链中的某个组件未路由该功能,或者其中一个组件未能解析。

当组件 use 或路由功能时,它可能对功能是否必须可用有各种期望。在某些情况下,capability 对组件的运行至关重要:如果有人创建的拓扑无法将 capability 路由到组件,最好能尽早检测到该故障,以防止出现 bug。不过,在其他情况下,组件可能能够容忍缺少相应功能,或者在某些配置中,相应功能可能本来就应该缺失。为了适应这些不同的场景,cmluseofferexpose 上提供了 availability 选项,组件可以使用该选项来声明其对功能可用性的预期。

选项

该框架支持以下 availability 选项:

必需

最常用的 availability 选项是 required,表示组件始终需要相应功能,如果缺少该功能,则无法正常运行。如果未指定任何使用情况,系统会自动设置此默认选项。

可选

optional 表示某些配置可能不支持相应功能。如果组件 use 是一项可选功能,但最终发现该功能不可用,则组件应能够在没有该功能的情况下正常运行,例如通过停用需要该功能的任何功能。

不过,如果某些配置中没有 optional 功能,框架会预期拓扑仍然包含以 void 结尾的完整功能路由。这样一来,产品所有者就需要明确选择相应功能是否可用(其路由在某个提供程序组件处终止)或不可用(其路由在 void 处终止)。如果路由不完整,工具和诊断程序会将此情况报告为错误。

过渡性

transitional 类似于 optional 的弱化版本。与 optional 类似,如果某个组件使用 transitional 功能,则应容忍该功能缺失的情况。不过,与 optional 不同,transitional 路由不需要以 void 结束,如果 transitional 路由不完整或无效,工具和诊断程序不会报告任何错误。

“过渡”一词表示此选项适用于软过渡。例如,假设您有一个 Echo 协议,想要将其替换为 EchoV2。在此过渡的早期阶段,您可以将客户端更改为 use 新协议,并提供 transitional 可用性。之后,一旦建立端到端路线,您就可以将可用性升级为 requiredoptional。如果您尝试使用 optional工具和诊断程序会抱怨客户端组件的父级缺少 Echo2 的功能路由,而 transitional 会抑制此类警告。

与目标相同

same_as_target 充当直通:它会导致可用性从路由的目标组件设置的任何可用性继承。这对于传递大量功能的中间组件非常有用,这样当目标中路由的 availability 发生更改时,来源中无需进行任何更改。

由于 use 功能的组件是其最终目的地,因此 same_as_target 不是 use 的有效选项。

可用性比较

各种可用性选项之间存在相对的“强度”顺序。从最强到最弱,顺序为:required > optional > transientsame_as_target 不属于此范围,因为它是一个直通功能:same_as_target 功能路由的强度实际上等于它从目标继承的任何可用性。

将可用性从来源降级到目标是有效且在许多情况下都很有用的。例如,如果组件 XY 公开 required 功能,Y 可以选择将该功能 useoptional,也可以将该功能 offeroptional 给另一个子级。不过,从来源升级可用性是一种路由错误。如果发生这种情况,任何使用或路由该功能的操作都会失败,就像路由链不完整时一样。这是一个错误,因为这意味着您尝试对可用性建立比来源所保证的更强的保证。例如,如果某个组件的父组件将某项功能 offeroptional,那么该组件将该功能 userequired 就没有意义了,因为这意味着父组件已声明该功能可能不可用。

工具和诊断

设置可用性的主要作用是控制主机工具和诊断报告如何路由错误。简而言之,这意味着 availability 越弱,他们就越不严格。详细规范如下:

  • 如果 required 功能路由不完整、无效或以 void 结尾:
    • 审查会将此报告为路由错误。如果 build 配置要求此值通过,则会导致 build 错误。
    • component_manager 将在描述路由错误的组件的范围内记录 WARNING 消息。
  • 如果 optional 功能路由不完整或无效:
    • 审查会将此报告为路由错误。如果 build 配置要求此值通过,则会导致 build 错误。
    • component_manager 将在使用组件的范围内记录一条 INFO 消息,用于描述路由错误。
  • 如果 optional 功能路线以 void 结尾:
    • Scrutiny 不会报告错误。
    • component_manager 可能会记录 INFO 消息,但不会记录错误。
  • 如果 transitional 功能路由不完整、无效或以 void 结尾:
    • 系统不会记录任何错误或其他信息。

对于一般运行时行为,availability 没有影响。例如,假设某个组件尝试 use 其命名空间中路由已损坏的协议。如果协议的路由方式为 requiredoptional,最终结果将相同:

  • 相应协议将显示在组件的命名空间中。
  • 连接到功能的初始调用将成功(假设使用了标准单向 API,例如 Rust 中的 connect_to_protocol)。
  • component_manager 将尝试路由功能。最终,路由将失败,并且通道将关闭并显示 NOT_FOUND 墓志铭

source_availability: unknown

cml 具有一项附加功能,可用于自动生成 requiredoptional void offer,具体取决于是否包含具有来源子声明的 cml shard。如需详细了解此功能,请参阅build 文档

target_availability:未知

cml 具有一项附加功能,可用于省略 offer,具体取决于是否包含具有目标子声明的 cml 分片。如需详细了解此功能,请参阅build 文档

示例

以下示例说明了本文档中介绍的概念。

在此示例中,有三个组件:

  • echo_client,它会尝试使用 echo_server 提供的各种协议
  • echo_server,提供了一些协议
  • echo_realmecho_clientecho_server的父级,用于将它们链接在一起

我们来检查一下它们的 CML 文件:

// echo_client.cml
{
    ...
    use: [
        { protocol: "fuchsia.example.Echo" },
        {
            protocol: "fuchsia.example.EchoV2",
            availability: "transitional",
        },
        {
            protocol: "fuchsia.example.Stats",
            availability: "optional",
        },
    ],
}

// echo_server.cml
{
    ...
    capabilities: [
        { protocol: "fuchsia.example.Echo" },
    ],
    expose: [
        {
            protocol: "fuchsia.example.Echo",
            from: "self",
        },
    ],
}

// echo_realm.cml
{
    offer: [
        {
            protocol: "fuchsia.example.Echo",
            from: "#echo_server",
            to: "#echo_client",
            availability: "required",
        },
        {
            protocol: "fuchsia.example.Stats",
            from: "void",
            to: "#echo_client",
            availability: "optional",
        },
    ],
    children: [
        {
            name: "echo_server",
            url: "echo_server#meta/echo_server.cm",
        },
        {
            name: "echo_client",
            url: "echo_client#meta/echo_client.cm",
        },
    ],
}

请注意,如果省略 availability,则默认为 required。在这种拓扑中,行为如下:

  • echo_client将能够成功连接到 fuchsia.example.Echo
  • echo_client 将无法连接到 fuchsia.example.EchoV2fuchsia.example.Stats
  • 工具和诊断不会记录错误。
    • fuchsia.example.Stats 没有错误,因为它是 optional 并路由到 void
    • fuchsia.example.Stats 没有错误,因为它是 transient

现在,我们来看看使用其他版本会发生什么情况:

// echo_client.cml
{
    ...
    use: [
        { protocol: "fuchsia.example.Echo" },
        {
            protocol: "fuchsia.example.EchoV2",
            availability: "transitional",
        },
        {
            protocol: "fuchsia.example.Stats",
            availability: "optional",
        },
    ],
}

// echo_server.cml
{
    ...
    capabilities: [
        {

            protocol: [
                "fuchsia.example.Echo",
                "fuchsia.example.EchoV2",
                "fuchsia.example.Stats",
            ],
        },
    ],
    expose: [
        {
            protocol: [
                "fuchsia.example.Echo",
                "fuchsia.example.EchoV2",
            ],
            from: "self",
        },
        {
            protocol: "fuchsia.example.Stats",
            from: "self",
            availability: "optional",
        },
    ],
}

// echo_realm.cml
{
    offer: [
        {
            protocol: [
                "fuchsia.example.Echo",
                "fuchsia.example.EchoV2",
            ],
            from: "#echo_server",
            to: "#echo_client",
            availability: "same_as_target",
        },
        {
            protocol: "fuchsia.example.Stats",
            from: "#echo_server",
            to: "#echo_client",
            availability: "optional",
        },
    ],
    children: [
        {
            name: "echo_server",
            url: "echo_server#meta/echo_server.cm",
        },
        {
            name: "echo_client",
            url: "echo_client#meta/echo_client.cm",
        },
    ],
}

现在:

  • echo_client 将能够成功连接到 fuchsia.example.Echofuchsia.example.EchoV2fuchsia.example.Stats
    • 每个路由虽然具有不同的 availability,但都是完整的,并且最终会到达一个真实组件。
    • 对于每条路线,源和目标之间的可用性通过了比较检查
  • 工具和诊断信息不会记录错误,因为所有路线都已完成。