提供情况

use但是,由于功能路由涉及一系列组件,仅仅因为组件 use 功能并不意味着它始终可用。它可能因各种原因而不可用:例如,如果链中的某个组件未路由该 capability,或者其中某个组件无法解析。

当组件 use 或路由某项功能时,可能对该功能是否可用有各种预期。在某些情况下,某项功能对于组件的运行至关重要:如果某个人创建的拓扑是无法将该功能路由到组件的,最好尽早检测到该故障以防止出现错误。但是,在其他情况下,组件也许可以容忍无该功能,或者在某些配置中可能不包含该功能。为了适应这些不同的场景,cmluseofferexpose 提供了一个 availability 选项,组件可以使用该选项来声明对功能可用性的预期。

选项

该框架支持 availability 的以下选项:

必需

最常用的 availability 选项是 required,它表示组件始终期望相应功能可用,如果没有相应功能,则不可能正常工作。这是在未指定可用性的情况下自动设置的默认选项。

可选

optional 表示某项功能可能不存在于某些配置中。如果某个组件执行 use 某项可选功能但后来发现该功能不可用,那么该组件在没有它的情况下应该也能正常工作,例如,通过停用需要该功能的所有功能。

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

过渡风格

transitional 就像是 optional 的较弱版本。与 optional 一样,如果某个组件使用 transitional 功能,则应能够容忍没有该功能。不过,与 optional 不同的是,transitional 路由不需要在 void 中终止,并且如果 transitional 路由不完整或无效,工具和诊断将不会报告任何错误。

名称“transitional”意味着此选项对于软过渡很有用。例如,假设您有要替换为 EchoV2Echo 协议。在此过渡的早期阶段,您可以将客户端更改为 use 且具有 transitional 可用性的新协议。稍后,一旦建立端到端路由,您就可以将可用性升级到 requiredoptional。如果您曾尝试改用 optional工具和诊断会指出客户端组件的父级缺少 Echo2 的功能路由,而 transitional 则会抑制此类警告。

与目标相同

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

由于对 capability 执行 use 的组件是其最终目的地,因此 same_as_target 并非 use 的有效选项。

库存状况比较

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

在许多情况下,将可用性从来源降级到目标是一种有效且有用的做法。例如,如果组件 XY 公开 required capability,Y 可以选择将 capability 作为 optional 进行 use,或者将 capability 作为 optional 提供给其他子项。offer但从来源中升级可用性属于路由错误。如果发生这种情况,任何使用或路由该 capability 的尝试都将失败,同样地,如果路由链不完整,也会失败。这是一个错误,因为这意味着您尝试建立比来源保证的可用性更强的可用性保证。例如,如果某个组件的父级将某个 capability offer 设为 optional,就没有将该 capability userequired,因为这意味着父级已声明该 capability 可能不可用。

工具和诊断

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

  • 如果 required 功能路由不完整、无效或以 void 结尾:
    • 审查会将此问题报告为路由错误。如果 build 配置要求通过测试,则会导致出现构建错误。
    • component_manager 会在 using 组件的作用域内记录一条 WARNING 消息,以描述路由错误。
  • 如果 optional 功能路由不完整或无效:
    • 审查会将此问题报告为路由错误。如果 build 配置要求通过测试,则会导致出现构建错误。
    • component_manager 会在 using 组件的作用域内记录一条 INFO 消息,以描述路由错误。
  • 如果 optional 功能路由以 void 结尾:
    • 审查不会报告错误。
    • component_manager 可能会记录 INFO 消息,但不会记录任何错误。
  • 如果 transitional 功能路由不完整、无效或以 void 结尾:
    • 系统不会记录任何错误或其他信息。

对于常规运行时行为,availability 没有任何影响。例如,假设某个组件尝试在其命名空间中对路由已损坏的命名空间执行 use 操作。如果协议以 requiredoptional 的形式路由,最终结果将相同:

  • 该协议将显示在组件的命名空间中。
  • 连接到 capability 的初始调用将会成功(假设标准单向 API 会像 rust 中的 connect_to_protocol 一样使用)。
  • component_manager 将尝试路由该功能。最终,路由将失败,相应通道将以 NOT_FOUND 徽章关闭。

source_availability:未知

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

示例

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

此示例中有三个组件:

  • 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 时都是完整的,并在真实组件中终止。
    • 对于每个路由,源和目标之间的可用性都通过了比较检查
  • 工具和诊断功能不会记录错误,因为所有路线都已完成。