| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library fuchsia.pkg; |
| |
| using fuchsia.io; |
| using zx; |
| |
| /// This manages the system package cache. |
| /// |
| /// This is intended to be implemented by the package manager component and used by |
| /// package resolver components. |
| @discoverable |
| protocol PackageCache { |
| /// Gets the package directory if it is present on the local system. If it is not, the |
| /// `missing_blobs` iterator will provide all the blobs in the package that are missing from |
| /// the system, and the ability to write those blobs to blobfs. If all the missing blobs are |
| /// downloaded and written to by the client, the `dir` directory will be resolved. This method |
| /// will return successfully when the package has been fully resolved, or return an error if |
| /// the client closes `needed_blobs` or `dir` handle before the package has been resolved. |
| /// |
| /// This method does not guarantee the missing blobs have been persisted. In order to guarantee |
| /// missing blobs are persisted, clients should call ['Sync']. |
| /// |
| /// + request `meta_far_blob` the blob info for the package's meta.far. |
| /// + request `needed_blobs` an iterator over all the blobs in the package that |
| /// are not present on the system. |
| /// + request `dir` an optional request for a directory that will be resolved when the package |
| /// has been successfully cached. |
| /// * error a zx_status value indicating failure. One of the following: |
| /// * `ZX_ERR_UNAVAILABLE` if the client closed `needed_blobs` handles before |
| /// all the missing blobs were downloaded to the system. |
| Get(resource struct { |
| meta_far_blob BlobInfo; |
| needed_blobs server_end:NeededBlobs; |
| dir server_end:<fuchsia.io.Directory, optional>; |
| }) -> (struct {}) error zx.status; |
| |
| /// Opens the package, or errors out if it is not present on the local system. |
| /// |
| /// + request `meta_far_blob_id` the blob id for the package's meta.far. |
| /// + request `dir` a request for a directory that will be resolved when the package has been |
| /// successfully cached. |
| /// * error a zx_status value indicating failure. One of the following: |
| /// * `ZX_ERR_NOT_FOUND` if the package does not exist. |
| Open(resource struct { |
| meta_far_blob_id BlobId; |
| dir server_end:fuchsia.io.Directory; |
| }) -> (struct {}) error zx.status; |
| |
| /// Retrieves a chunk iterator to the base package index. |
| /// |
| /// + request `iterator` a request for the `PackageIndexIterator` that will return sets of |
| /// `PackageIndexEntry` objects until all packages in the base index have been iterated. |
| BasePackageIndex(resource struct { |
| iterator server_end:PackageIndexIterator; |
| }); |
| |
| /// Retrieves a chunk iterator to the cache package index. |
| /// |
| /// + request `iterator` a request for the `PackageIndexIterator` that will return sets of |
| /// `PackageIndexEntry` objects until all packages in the cache index have been iterated. |
| CachePackageIndex(resource struct { |
| iterator server_end:PackageIndexIterator; |
| }); |
| |
| /// Synchronizes updates to the cached packages to the underlying persistent storage. |
| /// |
| /// * error a zx_status value indicating failure. One of the following: |
| /// * `ZX_ERR_INTERNAL` if the sync fails. |
| Sync() -> (struct {}) error zx.status; |
| }; |
| |
| /// Error type for [`NeededBlobs.OpenMetaBlob`] and [`NeededBlobs.OpenBlob`]. |
| type OpenBlobError = strict enum { |
| /// There is insufficient storage space available to persist this blob. |
| OUT_OF_SPACE = 1; |
| |
| /// This blob is already open for write by another cache operation. |
| CONCURRENT_WRITE = 2; |
| |
| /// An unspecified error occurred during underlying I/O. |
| UNSPECIFIED_IO = 3; |
| |
| /// An unspecified error occurred. |
| INTERNAL = 4; |
| }; |
| |
| /// Represents the transaction for caching a particular package. |
| /// |
| /// Server expects client to follow the normal operation sequence defined below. |
| /// Violating the protocol (e.g. calling wrong methods at the wrong time) will result |
| /// in the channel being closed by the package cache with a `ZX_ERR_BAD_STATE` epitaph |
| /// and aborting the package cache operation. |
| /// If a fatal error occurs at any step, server will close the channel, and client |
| /// should not proceed with the sequence. |
| /// Non-fatal errors could be retried, as long as the channel remains open. |
| /// |
| /// Normal operation sequence: |
| /// 1. Clients should start by requesting to `OpenMetaBlob()`, and fetch and write |
| /// the metadata blob if needed. |
| /// 2. `GetMissingBlobs()` should be used to determine which content blobs need |
| /// fetched and written. |
| /// 3. Each of the missing content blobs needs to be written using `OpenBlob()`. |
| /// |
| /// Once all needed blobs are written by the client, the package cache will |
| /// complete the pending [`PackageCache.Get`] request and close this channel |
| /// with a `ZX_OK` epitaph. |
| protocol NeededBlobs { |
| /// Opens the package's metadata blob for writing. `GetMissingBlobs()` |
| /// should not be called until writing the meta blob or this request |
| /// responds with `false`. |
| /// |
| /// If the package was already cached, server will close the channel |
| /// with a `ZX_OK` epitaph. |
| /// |
| /// + request `file` resolves to an opened writable file which must be |
| /// truncated to the correct size by the caller and then written from |
| /// start to finish (seeks are not supported). A corrupt blob is indicated |
| /// by a `Write()` (usually the final write) failing with |
| /// `ZX_ERR_IO_DATA_INTEGRITY`. On error or a response of `false`, `file` |
| /// will be closed by the server. |
| /// - response `needed` `true` if the blob is still needed and should be |
| /// written by the client. On `false`, the blob now exists, does not |
| /// need to be written by the client, and `file` will be closed. |
| /// * error an OpenBlobError indicating failure. Clients may retry this |
| /// request, though the server end may abort this cache operation on |
| /// errors it considers to be fatal. |
| OpenMetaBlob(resource struct { |
| file server_end:fuchsia.io.File; |
| }) -> (struct { |
| needed bool; |
| }) error OpenBlobError; |
| |
| /// Returns an iterator of blobs that are not present on the system that |
| /// must be written using the `OpenBlob` request before the package will be |
| /// fully cached. |
| /// |
| /// Client should call `OpenMetaBlob`, and write it if needed, before |
| /// calling `GetMissingBlobs`. |
| /// |
| /// A client should make this request no more than once per `NeededBlobs` |
| /// connection. Once all blobs yielded by this iterator are written, the |
| /// package open request will complete. |
| /// |
| /// + request `iterator` a request for an iterator of [`BlobInfo`] of blobs |
| /// that the client should try to write. |
| GetMissingBlobs(resource struct { |
| iterator server_end:BlobInfoIterator; |
| }); |
| |
| /// Opens a content blob for writing. |
| /// |
| /// + request `blob_id` the blob id describing this blob. |
| /// + request `file` resolves to an opened writable file which must be |
| /// truncated to the correct size by the caller and then written from |
| /// start to finish (seeks are not supported). A corrupt blob is indicated |
| /// by a `Write()` (usually the final write) failing with |
| /// `ZX_ERR_IO_DATA_INTEGRITY`. On error or a response of `false`, `file` |
| /// will be closed by the server. |
| /// - response `needed` `true` if the blob is still needed and should be |
| /// written by the client. On `false`, the blob now exists, does not |
| /// need to be written by the client, and `file` will be closed. |
| /// * error an OpenBlobError indicating failure. Clients may retry this |
| /// request, though the server end may abort this cache operation on |
| /// errors it considers to be fatal. |
| OpenBlob(resource struct { |
| blob_id BlobId; |
| file server_end:fuchsia.io.File; |
| }) -> (struct { |
| needed bool; |
| }) error OpenBlobError; |
| |
| /// Aborts this caching operation for the package. |
| /// |
| /// Any open blobs and any missing blobs iterator will be closed. Any `dir` |
| /// provided to the associated [`PackageCache.Get`] request will also be |
| /// closed. Once this request is acknowledged, this channel will be closed. |
| /// |
| /// Note, dropping this NeededBlobs channel without writing all needed blobs |
| /// will also abort the package cache operation. However, this API provides |
| /// the ability to wait for the operation to be torn down. |
| Abort() -> (); |
| }; |
| |
| /// A chunked iterator of [`BlobInfo`], allowing transfer of more [`BlobInfo`]s |
| /// that can fit in a single FIDL message. |
| protocol BlobInfoIterator { |
| /// Responds with the next chunk of [`BlobInfo`]s. When the iterator is |
| /// exhausted, responds with an empty vector and closes the connection. |
| /// |
| /// - response `blobs` the next chunk of [`BlobInfo`]s. |
| Next() -> (struct { |
| blobs vector<BlobInfo>:MAX; |
| }); |
| }; |
| |
| /// A chunk iterator for the package index. This is required because it is possible for the |
| /// package index to be too large to send over in a single request (over 64KiB). |
| protocol PackageIndexIterator { |
| /// Returns the next chunk of package index entries. When the iterator is exhausted, |
| /// this returns an empty vector. |
| /// |
| /// - response `entries` the next chunk of entries in the package index. |
| Next() -> (struct { |
| entries vector<PackageIndexEntry>:MAX; |
| }); |
| }; |
| |
| /// Manages the set of retained packages. |
| /// |
| /// Retained packages will not be removed from the package cache, even if they |
| /// aren't fully present. There is only a single set active at once, and the |
| /// provided APIs for configuring the set atomically replace that set. On boot, |
| /// the retained package set is always initialized to the empty set. |
| /// Documentation on [garbage collection]( |
| /// https://fuchsia.dev/fuchsia-src/concepts/packages/garbage_collection) contains |
| /// details on various types of package indexes (static, retained, etc) and |
| /// describes when a package will be garbage collected or retained. |
| @discoverable |
| protocol RetainedPackages { |
| /// Atomically clear the retained package set, releasing any previously |
| /// retained packages. |
| Clear() -> (); |
| |
| /// Atomically replace the retained package set with the [package hashes]( |
| /// https://fuchsia.dev/fuchsia-src/concepts/packages/package_url#package-hash) |
| /// provided by the given iterator. |
| /// Duplicate IDs provided will be merged and processed as a single one. |
| /// |
| /// + request `iterator` an iterator of package blob IDs that should be |
| /// retained. |
| Replace(resource struct { |
| iterator client_end:BlobIdIterator; |
| }) -> (); |
| }; |
| |
| /// A chunked iterator of blob IDs, allowing transfer of more blob IDs that can |
| /// fit in a single FIDL message. |
| protocol BlobIdIterator { |
| /// Responds with the next chunk of blob IDs. When the iterator is |
| /// exhausted, responds with an empty vector and closes the connection. |
| /// |
| /// - response `blobs` the next chunk of blob IDs. |
| Next() -> (struct { |
| blobs vector<BlobId>:MAX; |
| }); |
| }; |