aster_forge_cloud_files_linux/
error.rs1use aster_forge_cloud_files_core::{
4 CloudBackendError, CloudBackendErrorKind, CloudFilesStoreError, CloudFilesStoreErrorKind,
5};
6
7pub type Result<T> = std::result::Result<T, LinuxCloudFilesError>;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum LinuxErrorCode {
13 NotFound,
15 AlreadyExists,
17 DirectoryNotEmpty,
19 IsDirectory,
21 NotDirectory,
23 AccessDenied,
25 ReadOnlyFilesystem,
27 TryAgain,
29 Stale,
31 NotSupported,
33 InvalidArgument,
35 Io,
37}
38
39#[derive(Debug, thiserror::Error)]
41pub enum LinuxCloudFilesError {
42 #[error("linux inode must be non-zero")]
44 ZeroInode,
45 #[error("linux inode generation must be non-zero")]
47 ZeroGeneration,
48 #[error("linux root inode must be one")]
50 RootInodeMismatch,
51 #[error("linux inode record belongs to another cloud scope")]
53 ScopeMismatch,
54 #[error("duplicate linux inode {inode}")]
56 DuplicateInode {
57 inode: u64,
59 },
60 #[error("duplicate linux inode record for cloud item")]
62 DuplicateItem,
63 #[error("missing restored linux inode record for cloud item")]
65 MissingInodeRecord,
66 #[error("unknown linux inode {inode}")]
68 UnknownInode {
69 inode: u64,
71 },
72 #[error("stale linux file handle")]
74 StaleHandle,
75 #[error("linux file handle access mode does not permit this operation")]
77 AccessModeMismatch,
78 #[error("linux file handle space is exhausted")]
80 HandleExhausted,
81 #[error("invalid linux cloud-files configuration: {reason}")]
83 InvalidConfiguration {
84 reason: &'static str,
86 },
87 #[error("invalid linux filename: {reason}")]
89 InvalidName {
90 reason: &'static str,
92 },
93 #[error("cloud item is not a directory")]
95 NotDirectory,
96 #[error("cloud item is not a regular file")]
98 NotFile,
99 #[error("invalid cloud backend response: {reason}")]
101 InvalidBackendResponse {
102 reason: &'static str,
104 },
105 #[error(transparent)]
107 Backend(#[from] CloudBackendError),
108 #[error(transparent)]
110 WritebackStore(#[from] CloudFilesStoreError),
111 #[error(transparent)]
113 NamespaceStore(#[from] crate::LinuxNamespaceMutationStoreError),
114 #[error("linux namespace mutation store is not configured")]
116 NamespaceMutationNotConfigured,
117}
118
119impl LinuxCloudFilesError {
120 #[must_use]
122 pub const fn error_code(&self) -> LinuxErrorCode {
123 match self {
124 Self::UnknownInode { .. } => LinuxErrorCode::NotFound,
125 Self::StaleHandle => LinuxErrorCode::Stale,
126 Self::AccessModeMismatch => LinuxErrorCode::AccessDenied,
127 Self::InvalidName { .. } => LinuxErrorCode::InvalidArgument,
128 Self::NotDirectory => LinuxErrorCode::NotDirectory,
129 Self::NotFile => LinuxErrorCode::IsDirectory,
130 Self::Backend(error) => backend_error_code(error.kind()),
131 Self::WritebackStore(error) => writeback_store_error_code(error.kind()),
132 Self::NamespaceStore(error) => namespace_store_error_code(error.kind()),
133 Self::NamespaceMutationNotConfigured => LinuxErrorCode::NotSupported,
134 Self::ZeroInode
135 | Self::ZeroGeneration
136 | Self::RootInodeMismatch
137 | Self::ScopeMismatch
138 | Self::DuplicateInode { .. }
139 | Self::DuplicateItem
140 | Self::MissingInodeRecord
141 | Self::HandleExhausted
142 | Self::InvalidConfiguration { .. }
143 | Self::InvalidBackendResponse { .. } => LinuxErrorCode::Io,
144 }
145 }
146}
147
148#[must_use]
150pub const fn namespace_store_error_code(
151 kind: crate::LinuxNamespaceMutationStoreErrorKind,
152) -> LinuxErrorCode {
153 match kind {
154 crate::LinuxNamespaceMutationStoreErrorKind::NotFound => LinuxErrorCode::NotFound,
155 crate::LinuxNamespaceMutationStoreErrorKind::AlreadyExists => LinuxErrorCode::AlreadyExists,
156 crate::LinuxNamespaceMutationStoreErrorKind::DirectoryNotEmpty => {
157 LinuxErrorCode::DirectoryNotEmpty
158 }
159 crate::LinuxNamespaceMutationStoreErrorKind::IsDirectory => LinuxErrorCode::IsDirectory,
160 crate::LinuxNamespaceMutationStoreErrorKind::NotDirectory => LinuxErrorCode::NotDirectory,
161 crate::LinuxNamespaceMutationStoreErrorKind::Unsupported => LinuxErrorCode::NotSupported,
162 crate::LinuxNamespaceMutationStoreErrorKind::Fenced => LinuxErrorCode::Stale,
163 crate::LinuxNamespaceMutationStoreErrorKind::Conflict
164 | crate::LinuxNamespaceMutationStoreErrorKind::PersistenceFailure => LinuxErrorCode::Io,
165 }
166}
167
168#[must_use]
170pub const fn writeback_store_error_code(kind: CloudFilesStoreErrorKind) -> LinuxErrorCode {
171 match kind {
172 CloudFilesStoreErrorKind::NotFound => LinuxErrorCode::NotFound,
173 CloudFilesStoreErrorKind::Conflict => LinuxErrorCode::Stale,
174 CloudFilesStoreErrorKind::InvalidTransition
175 | CloudFilesStoreErrorKind::PersistenceFailure => LinuxErrorCode::Io,
176 }
177}
178
179#[must_use]
181pub const fn backend_error_code(kind: CloudBackendErrorKind) -> LinuxErrorCode {
182 match kind {
183 CloudBackendErrorKind::NotFound => LinuxErrorCode::NotFound,
184 CloudBackendErrorKind::AuthenticationRequired | CloudBackendErrorKind::PermissionDenied => {
185 LinuxErrorCode::AccessDenied
186 }
187 CloudBackendErrorKind::Conflict | CloudBackendErrorKind::PreconditionFailed => {
188 LinuxErrorCode::Stale
189 }
190 CloudBackendErrorKind::InvalidRequest => LinuxErrorCode::InvalidArgument,
191 CloudBackendErrorKind::RateLimited | CloudBackendErrorKind::TemporarilyUnavailable => {
192 LinuxErrorCode::TryAgain
193 }
194 CloudBackendErrorKind::Unsupported => LinuxErrorCode::NotSupported,
195 CloudBackendErrorKind::InvalidResponse | CloudBackendErrorKind::Internal => {
196 LinuxErrorCode::Io
197 }
198 }
199}