blob: dc4d2e0a8697850b87cd98a7222ef90734d27782 [file] [log] [blame] [edit]
// 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.fxfs;
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
closed 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.
strict Get(resource struct {
meta_far_blob BlobInfo;
needed_blobs server_end:NeededBlobs;
dir server_end:<fuchsia.io.Directory, optional>;
}) -> () 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.
strict 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.
strict 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.
strict Sync() -> () 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;
};
/// Error type for [`NeededBlobs.BlobWritten`].
type BlobWrittenError = strict enum {
/// Client called BlobWritten but blob was not readable in blobfs.
NOT_WRITTEN = 1;
/// Client called BlobWritten for a blob it has not yet opened.
UNOPENED_BLOB = 2;
};
/// 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, calling `BlobWritten()` when done to indicate the
/// write is complete.
/// 2. `GetMissingBlobs()` should be used to determine which blobs need to be
/// fetched and written.
/// 3. Each of the missing blobs needs to be written using `OpenBlob()` and
/// `BlobWritten()` should be called after each blob is written.
///
/// Clients must not make multiple `Open[Meta]Blob()` calls for the same `BlobId`
/// at the same time, even across different `NeededBlobs` connections. I.e.
/// there should be at most one outstanding `Open[Meta]Blob()` call per `BlobId`
/// per `PackageCache` server. Violating this may result in errors in later uses
/// of the protocol.
///
/// 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.
closed 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 `blob_type` the type of the blob to be written. Will be
/// removed once the transition to offline compression is complete.
/// - response `writer` is used to write the blob. If `writer` is absent,
/// the blob is already cached and so does not need to be written.
/// * 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.
strict OpenMetaBlob(struct {
blob_type BlobType;
}) -> (resource struct {
writer BlobWriter:optional;
}) 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.
///
/// New items may be added to the obtained `BlobInfoIterator` as the client
/// calls `OpenBlob`, so, to guaranatee termination of the iterator, clients
/// should call `OpenBlob` concurrently with reading the iterator.
///
/// + request `iterator` a request for an iterator of [`BlobInfo`] of blobs
/// that the client should try to write.
strict GetMissingBlobs(resource struct {
iterator server_end:BlobInfoIterator;
});
/// Opens a blob for writing.
///
/// + request `blob_id` the blob id describing this blob.
/// + request `blob_type` the type of the blob to be written. Will be
/// removed once the transition to offline compression is complete.
/// - response `writer` is used to write the blob. If `writer` is absent,
/// the blob is already cached and so does not need to be written.
/// * 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.
strict OpenBlob(struct {
blob_id BlobId;
blob_type BlobType;
}) -> (resource struct {
writer BlobWriter:optional;
}) error OpenBlobError;
/// Indicates that a blob opened by `Open[Meta]Blob` has been successfully
/// written.
///
/// A client should call this once the blob has been fully written using
/// the `writer` returned by `Open[Meta]Blob`.
///
/// + request `blob_id` the blob id describing this blob.
/// * error a BlobWrittenError indicating failure. Clients may retry the
/// `Open[Meta]Blob` request that prompted this call, though the server
/// end may abort this cache operation on errors it considers to be fatal.
strict BlobWritten(struct {
blob_id BlobId;
}) -> () error BlobWrittenError;
/// 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.
strict Abort() -> ();
};
/// The type of the blob. Will be removed once the transition to offline
/// compression is complete.
type BlobType = strict enum {
/// Raw uncompressed blob.
UNCOMPRESSED = 1;
/// Delivery blob.
DELIVERY = 2;
};
/// Used to write a blob to the underlying storage.
type BlobWriter = strict resource union {
/// To write a blob with `file`:
/// 1. If the blob is uncompressed, use `fuchsia.io/File.Resize` to set
/// the blob's uncompressed size.
/// 2. Use `fuchsia.io/File.Write` to write the blob's contents 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`.
1: file client_end:fuchsia.io.File;
/// To write a blob with `writer`, follow the instructions on the
/// `fuchsia.fxfs.BlobWriter` protocol.
2: writer client_end:fuchsia.fxfs.BlobWriter;
};
/// A chunked iterator of [`BlobInfo`], allowing transfer of more [`BlobInfo`]s
/// that can fit in a single FIDL message.
closed 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.
strict 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).
closed 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.
strict 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
closed protocol RetainedPackages {
/// Atomically clear the retained package set, releasing any previously
/// retained packages.
strict 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.
strict 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.
closed 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.
strict Next() -> (struct {
blobs vector<BlobId>:MAX;
});
};