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}