1use crate::tree_store::{FILE_FORMAT_VERSION, MAX_VALUE_LENGTH};
2use crate::TypeName;
3use std::fmt::{Display, Formatter};
4use std::sync::PoisonError;
5use std::{io, panic};
6
7#[derive(Debug)]
9#[non_exhaustive]
10pub enum StorageError {
11 Corrupted(String),
13 ValueTooLarge(usize),
15 Io(io::Error),
16 LockPoisoned(&'static panic::Location<'static>),
17}
18
19impl<T> From<PoisonError<T>> for StorageError {
20 fn from(_: PoisonError<T>) -> StorageError {
21 StorageError::LockPoisoned(panic::Location::caller())
22 }
23}
24
25impl From<io::Error> for StorageError {
26 fn from(err: io::Error) -> StorageError {
27 StorageError::Io(err)
28 }
29}
30
31impl From<StorageError> for Error {
32 fn from(err: StorageError) -> Error {
33 match err {
34 StorageError::Corrupted(msg) => Error::Corrupted(msg),
35 StorageError::ValueTooLarge(x) => Error::ValueTooLarge(x),
36 StorageError::Io(x) => Error::Io(x),
37 StorageError::LockPoisoned(location) => Error::LockPoisoned(location),
38 }
39 }
40}
41
42impl Display for StorageError {
43 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44 match self {
45 StorageError::Corrupted(msg) => {
46 write!(f, "DB corrupted: {msg}")
47 }
48 StorageError::ValueTooLarge(len) => {
49 write!(
50 f,
51 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
52 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
53 )
54 }
55 StorageError::Io(err) => {
56 write!(f, "I/O error: {err}")
57 }
58 StorageError::LockPoisoned(location) => {
59 write!(f, "Poisoned internal lock: {location}")
60 }
61 }
62 }
63}
64
65impl std::error::Error for StorageError {}
66
67#[derive(Debug)]
69#[non_exhaustive]
70pub enum TableError {
71 TableTypeMismatch {
73 table: String,
74 key: TypeName,
75 value: TypeName,
76 },
77 TableIsMultimap(String),
79 TableIsNotMultimap(String),
81 TypeDefinitionChanged {
82 name: TypeName,
83 alignment: usize,
84 width: Option<usize>,
85 },
86 TableDoesNotExist(String),
88 TableAlreadyOpen(String, &'static panic::Location<'static>),
91 Storage(StorageError),
93}
94
95impl TableError {
96 pub(crate) fn into_storage_error_or_corrupted(self, msg: &str) -> StorageError {
97 match self {
98 TableError::TableTypeMismatch { .. }
99 | TableError::TableIsMultimap(_)
100 | TableError::TableIsNotMultimap(_)
101 | TableError::TypeDefinitionChanged { .. }
102 | TableError::TableDoesNotExist(_)
103 | TableError::TableAlreadyOpen(_, _) => {
104 StorageError::Corrupted(format!("{}: {}", msg, &self))
105 }
106 TableError::Storage(storage) => storage,
107 }
108 }
109}
110
111impl From<TableError> for Error {
112 fn from(err: TableError) -> Error {
113 match err {
114 TableError::TypeDefinitionChanged {
115 name,
116 alignment,
117 width,
118 } => Error::TypeDefinitionChanged {
119 name,
120 alignment,
121 width,
122 },
123 TableError::TableTypeMismatch { table, key, value } => {
124 Error::TableTypeMismatch { table, key, value }
125 }
126 TableError::TableIsMultimap(table) => Error::TableIsMultimap(table),
127 TableError::TableIsNotMultimap(table) => Error::TableIsNotMultimap(table),
128 TableError::TableDoesNotExist(table) => Error::TableDoesNotExist(table),
129 TableError::TableAlreadyOpen(name, location) => Error::TableAlreadyOpen(name, location),
130 TableError::Storage(storage) => storage.into(),
131 }
132 }
133}
134
135impl From<StorageError> for TableError {
136 fn from(err: StorageError) -> TableError {
137 TableError::Storage(err)
138 }
139}
140
141impl Display for TableError {
142 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
143 match self {
144 TableError::TypeDefinitionChanged {
145 name,
146 alignment,
147 width,
148 } => {
149 write!(
150 f,
151 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
152 name.name(),
153 width,
154 alignment,
155 )
156 }
157 TableError::TableTypeMismatch { table, key, value } => {
158 write!(
159 f,
160 "{table} is of type Table<{}, {}>",
161 key.name(),
162 value.name(),
163 )
164 }
165 TableError::TableIsMultimap(table) => {
166 write!(f, "{table} is a multimap table")
167 }
168 TableError::TableIsNotMultimap(table) => {
169 write!(f, "{table} is not a multimap table")
170 }
171 TableError::TableDoesNotExist(table) => {
172 write!(f, "Table '{table}' does not exist")
173 }
174 TableError::TableAlreadyOpen(name, location) => {
175 write!(f, "Table '{name}' already opened at: {location}")
176 }
177 TableError::Storage(storage) => storage.fmt(f),
178 }
179 }
180}
181
182impl std::error::Error for TableError {}
183
184#[derive(Debug)]
186#[non_exhaustive]
187pub enum DatabaseError {
188 DatabaseAlreadyOpen,
190 RepairAborted,
192 UpgradeRequired(u8),
194 Storage(StorageError),
196}
197
198impl From<DatabaseError> for Error {
199 fn from(err: DatabaseError) -> Error {
200 match err {
201 DatabaseError::DatabaseAlreadyOpen => Error::DatabaseAlreadyOpen,
202 DatabaseError::RepairAborted => Error::RepairAborted,
203 DatabaseError::UpgradeRequired(x) => Error::UpgradeRequired(x),
204 DatabaseError::Storage(storage) => storage.into(),
205 }
206 }
207}
208
209impl From<io::Error> for DatabaseError {
210 fn from(err: io::Error) -> DatabaseError {
211 DatabaseError::Storage(StorageError::Io(err))
212 }
213}
214
215impl From<StorageError> for DatabaseError {
216 fn from(err: StorageError) -> DatabaseError {
217 DatabaseError::Storage(err)
218 }
219}
220
221impl Display for DatabaseError {
222 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
223 match self {
224 DatabaseError::UpgradeRequired(actual) => {
225 write!(f, "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION}, but file is version {actual}")
226 }
227 DatabaseError::RepairAborted => {
228 write!(f, "Database repair aborted.")
229 }
230 DatabaseError::DatabaseAlreadyOpen => {
231 write!(f, "Database already open. Cannot acquire lock.")
232 }
233 DatabaseError::Storage(storage) => storage.fmt(f),
234 }
235 }
236}
237
238impl std::error::Error for DatabaseError {}
239
240#[derive(Debug)]
242#[non_exhaustive]
243pub enum SavepointError {
244 InvalidSavepoint,
249 Storage(StorageError),
251}
252
253impl From<SavepointError> for Error {
254 fn from(err: SavepointError) -> Error {
255 match err {
256 SavepointError::InvalidSavepoint => Error::InvalidSavepoint,
257 SavepointError::Storage(storage) => storage.into(),
258 }
259 }
260}
261
262impl From<StorageError> for SavepointError {
263 fn from(err: StorageError) -> SavepointError {
264 SavepointError::Storage(err)
265 }
266}
267
268impl Display for SavepointError {
269 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
270 match self {
271 SavepointError::InvalidSavepoint => {
272 write!(f, "Savepoint is invalid or cannot be created.")
273 }
274 SavepointError::Storage(storage) => storage.fmt(f),
275 }
276 }
277}
278
279impl std::error::Error for SavepointError {}
280
281#[derive(Debug)]
283#[non_exhaustive]
284pub enum CompactionError {
285 PersistentSavepointExists,
287 EphemeralSavepointExists,
289 Storage(StorageError),
291}
292
293impl From<CompactionError> for Error {
294 fn from(err: CompactionError) -> Error {
295 match err {
296 CompactionError::PersistentSavepointExists => Error::PersistentSavepointExists,
297 CompactionError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
298 CompactionError::Storage(storage) => storage.into(),
299 }
300 }
301}
302
303impl From<StorageError> for CompactionError {
304 fn from(err: StorageError) -> CompactionError {
305 CompactionError::Storage(err)
306 }
307}
308
309impl Display for CompactionError {
310 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
311 match self {
312 CompactionError::PersistentSavepointExists => {
313 write!(
314 f,
315 "Persistent savepoint exists. Operation cannot be performed."
316 )
317 }
318 CompactionError::EphemeralSavepointExists => {
319 write!(
320 f,
321 "Ephemeral savepoint exists. Operation cannot be performed."
322 )
323 }
324 CompactionError::Storage(storage) => storage.fmt(f),
325 }
326 }
327}
328
329impl std::error::Error for CompactionError {}
330
331#[derive(Debug)]
333#[non_exhaustive]
334pub enum TransactionError {
335 Storage(StorageError),
337}
338
339impl TransactionError {
340 pub(crate) fn into_storage_error(self) -> StorageError {
341 match self {
342 TransactionError::Storage(storage) => storage,
343 }
344 }
345}
346
347impl From<TransactionError> for Error {
348 fn from(err: TransactionError) -> Error {
349 match err {
350 TransactionError::Storage(storage) => storage.into(),
351 }
352 }
353}
354
355impl From<StorageError> for TransactionError {
356 fn from(err: StorageError) -> TransactionError {
357 TransactionError::Storage(err)
358 }
359}
360
361impl Display for TransactionError {
362 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
363 match self {
364 TransactionError::Storage(storage) => storage.fmt(f),
365 }
366 }
367}
368
369impl std::error::Error for TransactionError {}
370
371#[derive(Debug)]
373#[non_exhaustive]
374pub enum CommitError {
375 Storage(StorageError),
377}
378
379impl CommitError {
380 pub(crate) fn into_storage_error(self) -> StorageError {
381 match self {
382 CommitError::Storage(storage) => storage,
383 }
384 }
385}
386
387impl From<CommitError> for Error {
388 fn from(err: CommitError) -> Error {
389 match err {
390 CommitError::Storage(storage) => storage.into(),
391 }
392 }
393}
394
395impl From<StorageError> for CommitError {
396 fn from(err: StorageError) -> CommitError {
397 CommitError::Storage(err)
398 }
399}
400
401impl Display for CommitError {
402 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
403 match self {
404 CommitError::Storage(storage) => storage.fmt(f),
405 }
406 }
407}
408
409impl std::error::Error for CommitError {}
410
411#[derive(Debug)]
413#[non_exhaustive]
414pub enum Error {
415 DatabaseAlreadyOpen,
417 InvalidSavepoint,
422 RepairAborted,
424 PersistentSavepointExists,
426 EphemeralSavepointExists,
428 Corrupted(String),
430 UpgradeRequired(u8),
432 ValueTooLarge(usize),
434 TableTypeMismatch {
436 table: String,
437 key: TypeName,
438 value: TypeName,
439 },
440 TableIsMultimap(String),
442 TableIsNotMultimap(String),
444 TypeDefinitionChanged {
445 name: TypeName,
446 alignment: usize,
447 width: Option<usize>,
448 },
449 TableDoesNotExist(String),
451 TableAlreadyOpen(String, &'static panic::Location<'static>),
454 Io(io::Error),
455 LockPoisoned(&'static panic::Location<'static>),
456}
457
458impl<T> From<PoisonError<T>> for Error {
459 fn from(_: PoisonError<T>) -> Error {
460 Error::LockPoisoned(panic::Location::caller())
461 }
462}
463
464impl From<io::Error> for Error {
465 fn from(err: io::Error) -> Error {
466 Error::Io(err)
467 }
468}
469
470impl Display for Error {
471 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
472 match self {
473 Error::Corrupted(msg) => {
474 write!(f, "DB corrupted: {msg}")
475 }
476 Error::UpgradeRequired(actual) => {
477 write!(f, "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION}, but file is version {actual}")
478 }
479 Error::ValueTooLarge(len) => {
480 write!(
481 f,
482 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
483 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
484 )
485 }
486 Error::TypeDefinitionChanged {
487 name,
488 alignment,
489 width,
490 } => {
491 write!(
492 f,
493 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
494 name.name(),
495 width,
496 alignment,
497 )
498 }
499 Error::TableTypeMismatch { table, key, value } => {
500 write!(
501 f,
502 "{table} is of type Table<{}, {}>",
503 key.name(),
504 value.name(),
505 )
506 }
507 Error::TableIsMultimap(table) => {
508 write!(f, "{table} is a multimap table")
509 }
510 Error::TableIsNotMultimap(table) => {
511 write!(f, "{table} is not a multimap table")
512 }
513 Error::TableDoesNotExist(table) => {
514 write!(f, "Table '{table}' does not exist")
515 }
516 Error::TableAlreadyOpen(name, location) => {
517 write!(f, "Table '{name}' already opened at: {location}")
518 }
519 Error::Io(err) => {
520 write!(f, "I/O error: {err}")
521 }
522 Error::LockPoisoned(location) => {
523 write!(f, "Poisoned internal lock: {location}")
524 }
525 Error::DatabaseAlreadyOpen => {
526 write!(f, "Database already open. Cannot acquire lock.")
527 }
528 Error::RepairAborted => {
529 write!(f, "Database repair aborted.")
530 }
531 Error::PersistentSavepointExists => {
532 write!(
533 f,
534 "Persistent savepoint exists. Operation cannot be performed."
535 )
536 }
537 Error::EphemeralSavepointExists => {
538 write!(
539 f,
540 "Ephemeral savepoint exists. Operation cannot be performed."
541 )
542 }
543 Error::InvalidSavepoint => {
544 write!(f, "Savepoint is invalid or cannot be created.")
545 }
546 }
547 }
548}
549
550impl std::error::Error for Error {}