Skip to main content

loonfs_api/
options.rs

1//! Per-operation options shared by the embedded runtime and HTTP client.
2//!
3//! There is one type per operation, even where two of them currently hold the
4//! same fields: options follow the operation they parameterize, so a guard
5//! added to one is not silently offered on the others.
6//!
7//! These are plain in-process argument structs, not wire shapes: nothing here
8//! serializes. The request bodies that do cross the wire live in
9//! [`crate::v0`], and each surface resolves these options into one. A read's
10//! options reach the wire as query parameters the surface builds from them.
11
12use crate::{
13    ActorRef, AttributeKey, AttributeRevisionNo, AttributeValue, CheckpointId, CommitId,
14    DeleteDirectoryBehavior, DestinationBehavior, InodeId, RevisionNo,
15};
16use std::collections::BTreeMap;
17
18/// Commit settings shared by every filesystem mutation.
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct CommitOptions {
21    /// Actor responsible for the commit, as supplied by the application.
22    pub actor: ActorRef,
23    /// Optional idempotency key. LoonFS generates one when this is `None`.
24    pub commit_id: Option<CommitId>,
25    /// Optional commit message. Changing it changes the commit identity.
26    pub message: Option<String>,
27}
28
29impl CommitOptions {
30    /// Creates settings with no commit ID or message.
31    pub fn new(actor: ActorRef) -> Self {
32        Self {
33            actor,
34            commit_id: None,
35            message: None,
36        }
37    }
38}
39
40/// Options for stating one path.
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct StatPathOptions {
43    /// Project the inode's attribute map and its revision onto the answer.
44    ///
45    /// Defaults to on. A stat answers for one path, and an attribute map is
46    /// capped at 64 KiB, so the cost of including it is bounded by the
47    /// request.
48    pub include_attributes: bool,
49    /// Read a path from this snapshot. Inode lookups do not support snapshots.
50    pub snapshot_id: Option<CheckpointId>,
51}
52
53impl Default for StatPathOptions {
54    fn default() -> Self {
55        Self {
56            include_attributes: true,
57            snapshot_id: None,
58        }
59    }
60}
61
62/// Options for listing a directory.
63#[derive(Debug, Clone, PartialEq, Eq, Default)]
64pub struct ListPathEntriesOptions {
65    /// Project each entry's attribute map and its revision onto the answer.
66    ///
67    /// Defaults to off, and that default is what bounds a listing: a page
68    /// holds up to 1,000 entries and each attribute map may be 64 KiB, so an
69    /// always-on projection would put a 64 MiB response behind a request that
70    /// declares no byte budget anywhere. A caller that wants attributes for a
71    /// whole directory asks for them, and pages accordingly.
72    pub include_attributes: bool,
73    /// Read the directory from this snapshot.
74    pub snapshot_id: Option<CheckpointId>,
75}
76
77/// Options for listing a directory's children by parent inode.
78#[derive(Debug, Clone, PartialEq, Eq, Default)]
79pub struct ListInodeChildrenOptions {
80    /// Project each entry's attribute map and its revision onto the answer.
81    ///
82    /// Defaults to off for the same reason as
83    /// [`ListPathEntriesOptions::include_attributes`].
84    pub include_attributes: bool,
85}
86
87/// Options for writing and removing an inode's attributes.
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct UpdateAttributesOptions {
90    /// Attributes to write. Each key replaces whatever the inode holds under
91    /// it; keys the inode holds and this map does not name are left alone.
92    pub set: BTreeMap<AttributeKey, AttributeValue>,
93    /// Keys to remove.
94    pub remove: Vec<AttributeKey>,
95    /// Actor, commit ID, and message.
96    pub commit: CommitOptions,
97    /// When set, the update applies only while the path still resolves to
98    /// this inode, so a raced rebinding fails instead of writing attributes
99    /// onto the wrong inode.
100    pub expected_inode_id: Option<InodeId>,
101    /// When set, the update applies only while the inode's attribute revision
102    /// is still this one. Every update carries its own revision guard either
103    /// way, so a concurrent update never merges silently.
104    pub expected_attributes_revision_no: Option<AttributeRevisionNo>,
105}
106
107impl UpdateAttributesOptions {
108    /// Creates an empty attribute update for this actor.
109    pub fn new(actor: ActorRef) -> Self {
110        Self {
111            set: BTreeMap::new(),
112            remove: Vec::new(),
113            commit: CommitOptions::new(actor),
114            expected_inode_id: None,
115            expected_attributes_revision_no: None,
116        }
117    }
118}
119
120/// Options for writing a file path.
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct PutFileOptions {
123    /// Create-only or replace-existing behavior.
124    pub behavior: DestinationBehavior,
125    /// Actor, commit ID, and message.
126    pub commit: CommitOptions,
127    /// Replace only while the file's current revision is still this one.
128    /// Requires `Replace` behavior; a raced write fails instead of stacking a
129    /// revision on state the caller never saw.
130    pub expected_revision_no: Option<RevisionNo>,
131}
132
133impl PutFileOptions {
134    /// Creates options that refuse to replace an existing file.
135    pub fn new(actor: ActorRef) -> Self {
136        Self {
137            behavior: DestinationBehavior::NoReplace,
138            commit: CommitOptions::new(actor),
139            expected_revision_no: None,
140        }
141    }
142}
143
144/// Options for creating a directory.
145#[derive(Debug, Clone, PartialEq, Eq)]
146pub struct CreateDirectoryOptions {
147    /// Actor, commit ID, and message.
148    pub commit: CommitOptions,
149    /// Also create missing ancestor directories, like `put_file` does.
150    pub parents: bool,
151}
152
153impl CreateDirectoryOptions {
154    /// Creates options that do not create missing parent directories.
155    pub fn new(actor: ActorRef) -> Self {
156        Self {
157            commit: CommitOptions::new(actor),
158            parents: false,
159        }
160    }
161}
162
163/// Options for deleting a path.
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct DeleteOptions {
166    /// Directory delete behavior.
167    pub behavior: DeleteDirectoryBehavior,
168    /// Actor, commit ID, and message.
169    pub commit: CommitOptions,
170    /// When set, the delete applies only while the path still resolves to
171    /// this inode, so a raced rebinding fails instead of deleting the wrong
172    /// inode.
173    pub expected_inode_id: Option<InodeId>,
174}
175
176impl DeleteOptions {
177    /// Creates options for a non-recursive delete.
178    pub fn new(actor: ActorRef) -> Self {
179        Self {
180            behavior: DeleteDirectoryBehavior::NonRecursive,
181            commit: CommitOptions::new(actor),
182            expected_inode_id: None,
183        }
184    }
185}
186
187/// Options for moving a path.
188#[derive(Debug, Clone, PartialEq, Eq)]
189pub struct MoveOptions {
190    /// Create-only or replace-existing behavior for the destination.
191    pub behavior: DestinationBehavior,
192    /// Actor, commit ID, and message.
193    pub commit: CommitOptions,
194}
195
196impl MoveOptions {
197    /// Creates options that refuse to replace the destination.
198    pub fn new(actor: ActorRef) -> Self {
199        Self {
200            behavior: DestinationBehavior::NoReplace,
201            commit: CommitOptions::new(actor),
202        }
203    }
204}
205
206/// Options for copying a file path.
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct CopyOptions {
209    /// Create-only or replace-existing behavior for the destination.
210    pub behavior: DestinationBehavior,
211    /// Actor, commit ID, and message.
212    pub commit: CommitOptions,
213}
214
215impl CopyOptions {
216    /// Creates options that refuse to replace the destination.
217    pub fn new(actor: ActorRef) -> Self {
218        Self {
219            behavior: DestinationBehavior::NoReplace,
220            commit: CommitOptions::new(actor),
221        }
222    }
223}
224
225/// Options for restoring a file revision by path.
226#[derive(Debug, Clone, PartialEq, Eq)]
227pub struct RestoreRevisionOptions {
228    /// Actor, commit ID, and message.
229    pub commit: CommitOptions,
230}
231
232impl RestoreRevisionOptions {
233    /// Creates restore options for this actor.
234    pub fn new(actor: ActorRef) -> Self {
235        Self {
236            commit: CommitOptions::new(actor),
237        }
238    }
239}
240
241/// Options for recovering a deleted file or subtree.
242#[derive(Debug, Clone, PartialEq, Eq)]
243pub struct UndeleteOptions {
244    /// Actor, commit ID, and message.
245    pub commit: CommitOptions,
246}
247
248impl UndeleteOptions {
249    /// Creates undelete options for this actor.
250    pub fn new(actor: ActorRef) -> Self {
251        Self {
252            commit: CommitOptions::new(actor),
253        }
254    }
255}
256
257/// Options for starting a direct multipart upload.
258#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
259pub struct DirectMultipartUploadOptions {
260    /// Byte length of every part except the last. `None` uses the server
261    /// default. Providers accept at most 10,000 parts.
262    pub part_size_bytes: Option<u64>,
263}