blob: 32b77a98b68702f667f4e8b2a3fe55e77dfa0d7c [file] [log] [blame]
// 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;
});
};