Skip to main content

fxfs/
object_handle.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::object_store::{DirType, PosixAttributes, Timestamp};
6use anyhow::Error;
7use async_trait::async_trait;
8use std::future::Future;
9use std::sync::Arc;
10use storage_device::buffer::{BufferFuture, BufferRef, MutableBufferRef};
11use storage_units::BlockSize;
12
13// Some places use Default and assume that zero is an invalid object ID, so this cannot be changed
14// easily.
15pub const INVALID_OBJECT_ID: u64 = 0;
16
17/// A handle for a generic object.  For objects with a data payload, use the ReadObjectHandle or
18/// WriteObjectHandle traits.
19pub trait ObjectHandle: Send + Sync + 'static {
20    /// Returns the object identifier for this object which will be unique for the store that the
21    /// object is contained in, but not necessarily unique within the entire system.
22    fn object_id(&self) -> u64;
23
24    /// Returns the filesystem block size, which should be at least as big as the device block size,
25    /// but not necessarily the same.
26    fn block_size(&self) -> BlockSize;
27
28    /// Allocates a buffer for doing I/O (read and write) for the object.
29    fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>;
30
31    /// Sets tracing for this object.
32    fn set_trace(&self, _v: bool) {}
33}
34
35#[derive(Clone, Debug, PartialEq)]
36pub struct ObjectProperties {
37    /// The number of references to this object.
38    pub refs: u64,
39    /// The number of bytes allocated to all extents across all attributes for this object.
40    pub allocated_size: u64,
41    /// The logical content size for the default data attribute of this object, i.e. the size of a
42    /// file.  (Objects with no data attribute have size 0.)
43    pub data_attribute_size: u64,
44    /// The timestamp at which the object was created (i.e. crtime).
45    pub creation_time: Timestamp,
46    /// The timestamp at which the objects's data was last modified (i.e. mtime).
47    pub modification_time: Timestamp,
48    /// The timestamp at which the object was last read (i.e. atime).
49    pub access_time: Timestamp,
50    /// The timestamp at which the object's status was last modified (i.e. ctime).
51    pub change_time: Timestamp,
52    /// The number of sub-directories.
53    pub sub_dirs: u64,
54    /// POSIX attributes: mode, uid, gid, rdev
55    pub posix_attributes: Option<PosixAttributes>,
56    /// The type of directory (encryption, casefolding, etc.)
57    pub dir_type: DirType,
58}
59
60#[async_trait]
61pub trait ReadObjectHandle: ObjectHandle {
62    /// Fills |buf| with up to |buf.len()| bytes read from |offset| on the underlying device.
63    /// |offset| and |buf| must both be block-aligned.
64    async fn read(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error>;
65
66    /// Returns the size of the object.
67    fn get_size(&self) -> u64;
68}
69
70pub trait WriteObjectHandle: ObjectHandle {
71    /// Writes |buf.len())| bytes at |offset| (or the end of the file), returning the object size
72    /// after writing.
73    /// The writes may be cached, in which case a later call to |flush| is necessary to persist the
74    /// writes.
75    fn write_or_append(
76        &self,
77        offset: Option<u64>,
78        buf: BufferRef<'_>,
79    ) -> impl Future<Output = Result<u64, Error>> + Send;
80
81    /// Truncates the object to |size| bytes.
82    /// The truncate may be cached, in which case a later call to |flush| is necessary to persist
83    /// the truncate.
84    fn truncate(&self, size: u64) -> impl Future<Output = Result<(), Error>> + Send;
85
86    /// Flushes all pending data and metadata updates for the object.
87    fn flush(&self) -> impl Future<Output = Result<(), Error>> + Send;
88}
89
90/// This trait is an asynchronous streaming writer.
91pub trait WriteBytes: Sized {
92    fn block_size(&self) -> BlockSize;
93
94    /// Buffers writes to be written to the underlying handle. This may flush bytes immediately
95    /// or when buffers are full.
96    fn write_bytes(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Error>> + Send;
97
98    /// Called to flush to the handle. The total number of bytes written is returned.
99    fn complete(self) -> impl Future<Output = Result<u64, Error>> + Send;
100
101    /// Moves the offset forward by `amount`, which will result in zeroes in the output stream, even
102    /// if no other data is appended to it.
103    fn skip(&mut self, amount: u64) -> impl Future<Output = Result<(), Error>> + Send;
104}
105
106impl LayerObject for dyn ReadObjectHandle + '_ {}
107
108/// A handle for reading layer objects.
109#[async_trait]
110pub trait LayerObject: ReadObjectHandle {
111    /// Returns a memory-mapped slice of the entire layer file if supported (e.g. when backed by a
112    /// pager-managed VMO).
113    fn as_slice(&self) -> Option<&[u8]> {
114        None
115    }
116
117    /// Returns true if an underlying I/O error occurred while paging in data for this object.
118    fn has_io_error(&self) -> bool {
119        false
120    }
121
122    /// Requests that cached data (such as paged-in pages) for this object be purged.
123    fn purge_cached_data(&self) {}
124
125    /// Called when the layer is closed to release any external resources (such as pager
126    /// registrations).
127    async fn close(&self) {}
128}
129
130impl<T: ObjectHandle + ?Sized> ObjectHandle for Arc<T> {
131    fn object_id(&self) -> u64 {
132        (**self).object_id()
133    }
134
135    fn block_size(&self) -> BlockSize {
136        (**self).block_size()
137    }
138
139    fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
140        (**self).allocate_buffer(size)
141    }
142
143    fn set_trace(&self, v: bool) {
144        (**self).set_trace(v)
145    }
146}
147
148#[async_trait]
149impl<T: ReadObjectHandle + ?Sized> ReadObjectHandle for Arc<T> {
150    async fn read(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
151        (**self).read(offset, buf).await
152    }
153
154    fn get_size(&self) -> u64 {
155        (**self).get_size()
156    }
157}
158
159#[async_trait]
160impl<T: LayerObject + ?Sized> LayerObject for Arc<T> {
161    fn as_slice(&self) -> Option<&[u8]> {
162        (**self).as_slice()
163    }
164
165    fn has_io_error(&self) -> bool {
166        (**self).has_io_error()
167    }
168
169    fn purge_cached_data(&self) {
170        (**self).purge_cached_data()
171    }
172
173    async fn close(&self) {
174        (**self).close().await
175    }
176}
177
178impl<T: ObjectHandle + ?Sized> ObjectHandle for Box<T> {
179    fn object_id(&self) -> u64 {
180        (**self).object_id()
181    }
182
183    fn block_size(&self) -> BlockSize {
184        (**self).block_size()
185    }
186
187    fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
188        (**self).allocate_buffer(size)
189    }
190
191    fn set_trace(&self, v: bool) {
192        (**self).set_trace(v)
193    }
194}
195
196#[async_trait]
197impl<T: ReadObjectHandle + ?Sized> ReadObjectHandle for Box<T> {
198    async fn read(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
199        (**self).read(offset, buf).await
200    }
201
202    fn get_size(&self) -> u64 {
203        (**self).get_size()
204    }
205}
206
207#[async_trait]
208impl<T: LayerObject + ?Sized> LayerObject for Box<T> {
209    fn as_slice(&self) -> Option<&[u8]> {
210        (**self).as_slice()
211    }
212
213    fn has_io_error(&self) -> bool {
214        (**self).has_io_error()
215    }
216
217    fn purge_cached_data(&self) {
218        (**self).purge_cached_data()
219    }
220
221    async fn close(&self) {
222        (**self).close().await
223    }
224}