1use crate::tree_store::{FILE_FORMAT_VERSION3, MAX_VALUE_LENGTH};
2use crate::{ReadTransaction, 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 PreviousIo,
17 DatabaseClosed,
18 LockPoisoned(&'static panic::Location<'static>),
19}
20
21impl<T> From<PoisonError<T>> for StorageError {
22 fn from(_: PoisonError<T>) -> StorageError {
23 StorageError::LockPoisoned(panic::Location::caller())
24 }
25}
26
27impl From<io::Error> for StorageError {
28 fn from(err: io::Error) -> StorageError {
29 StorageError::Io(err)
30 }
31}
32
33impl From<StorageError> for Error {
34 fn from(err: StorageError) -> Error {
35 match err {
36 StorageError::Corrupted(msg) => Error::Corrupted(msg),
37 StorageError::ValueTooLarge(x) => Error::ValueTooLarge(x),
38 StorageError::Io(x) => Error::Io(x),
39 StorageError::PreviousIo => Error::PreviousIo,
40 StorageError::DatabaseClosed => Error::DatabaseClosed,
41 StorageError::LockPoisoned(location) => Error::LockPoisoned(location),
42 }
43 }
44}
45
46impl Display for StorageError {
47 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48 match self {
49 StorageError::Corrupted(msg) => {
50 write!(f, "DB corrupted: {msg}")
51 }
52 StorageError::ValueTooLarge(len) => {
53 write!(
54 f,
55 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
56 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
57 )
58 }
59 StorageError::Io(err) => {
60 write!(f, "I/O error: {err}")
61 }
62 StorageError::DatabaseClosed => {
63 write!(f, "Database has been closed")
64 }
65 StorageError::PreviousIo => {
66 write!(
67 f,
68 "Previous I/O error occurred. Please close and re-open the database."
69 )
70 }
71 StorageError::LockPoisoned(location) => {
72 write!(f, "Poisoned internal lock: {location}")
73 }
74 }
75 }
76}
77
78impl std::error::Error for StorageError {}
79
80#[derive(Debug)]
82#[non_exhaustive]
83pub enum TableError {
84 TableTypeMismatch {
86 table: String,
87 key: TypeName,
88 value: TypeName,
89 },
90 TableIsMultimap(String),
92 TableIsNotMultimap(String),
94 TypeDefinitionChanged {
95 name: TypeName,
96 alignment: usize,
97 width: Option<usize>,
98 },
99 TableDoesNotExist(String),
101 TableExists(String),
103 TableAlreadyOpen(String, &'static panic::Location<'static>),
106 Storage(StorageError),
108}
109
110impl TableError {
111 pub(crate) fn into_storage_error_or_corrupted(self, msg: &str) -> StorageError {
112 match self {
113 TableError::TableTypeMismatch { .. }
114 | TableError::TableIsMultimap(_)
115 | TableError::TableIsNotMultimap(_)
116 | TableError::TypeDefinitionChanged { .. }
117 | TableError::TableDoesNotExist(_)
118 | TableError::TableExists(_)
119 | TableError::TableAlreadyOpen(_, _) => {
120 StorageError::Corrupted(format!("{msg}: {self}"))
121 }
122 TableError::Storage(storage) => storage,
123 }
124 }
125}
126
127impl From<TableError> for Error {
128 fn from(err: TableError) -> Error {
129 match err {
130 TableError::TypeDefinitionChanged {
131 name,
132 alignment,
133 width,
134 } => Error::TypeDefinitionChanged {
135 name,
136 alignment,
137 width,
138 },
139 TableError::TableTypeMismatch { table, key, value } => {
140 Error::TableTypeMismatch { table, key, value }
141 }
142 TableError::TableIsMultimap(table) => Error::TableIsMultimap(table),
143 TableError::TableIsNotMultimap(table) => Error::TableIsNotMultimap(table),
144 TableError::TableDoesNotExist(table) => Error::TableDoesNotExist(table),
145 TableError::TableExists(table) => Error::TableExists(table),
146 TableError::TableAlreadyOpen(name, location) => Error::TableAlreadyOpen(name, location),
147 TableError::Storage(storage) => storage.into(),
148 }
149 }
150}
151
152impl From<StorageError> for TableError {
153 fn from(err: StorageError) -> TableError {
154 TableError::Storage(err)
155 }
156}
157
158impl Display for TableError {
159 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
160 match self {
161 TableError::TypeDefinitionChanged {
162 name,
163 alignment,
164 width,
165 } => {
166 write!(
167 f,
168 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
169 name.name(),
170 width,
171 alignment,
172 )
173 }
174 TableError::TableTypeMismatch { table, key, value } => {
175 write!(
176 f,
177 "{table} is of type Table<{}, {}>",
178 key.name(),
179 value.name(),
180 )
181 }
182 TableError::TableIsMultimap(table) => {
183 write!(f, "{table} is a multimap table")
184 }
185 TableError::TableIsNotMultimap(table) => {
186 write!(f, "{table} is not a multimap table")
187 }
188 TableError::TableDoesNotExist(table) => {
189 write!(f, "Table '{table}' does not exist")
190 }
191 TableError::TableExists(table) => {
192 write!(f, "Table '{table}' already exists")
193 }
194 TableError::TableAlreadyOpen(name, location) => {
195 write!(f, "Table '{name}' already opened at: {location}")
196 }
197 TableError::Storage(storage) => storage.fmt(f),
198 }
199 }
200}
201
202impl std::error::Error for TableError {}
203
204#[derive(Debug)]
206#[non_exhaustive]
207pub enum DatabaseError {
208 DatabaseAlreadyOpen,
210 RepairAborted,
212 UpgradeRequired(u8),
214 Storage(StorageError),
216 IncorrectPassword,
218 CorruptedEncryption(String),
220 UnsupportedEncryption(String),
222 KeyDerivationFailed,
224 EncryptionFailed(String),
226 DecryptionFailed(String),
228 SaltGenerationFailed,
230 IncompatibleFileFormat,
232}
233
234impl From<DatabaseError> for Error {
235 fn from(err: DatabaseError) -> Error {
236 match err {
237 DatabaseError::DatabaseAlreadyOpen => Error::DatabaseAlreadyOpen,
238 DatabaseError::RepairAborted => Error::RepairAborted,
239 DatabaseError::UpgradeRequired(x) => Error::UpgradeRequired(x),
240 DatabaseError::Storage(storage) => storage.into(),
241 DatabaseError::IncorrectPassword => Error::IncorrectPassword,
242 DatabaseError::CorruptedEncryption(msg) => Error::CorruptedEncryption(msg),
243 DatabaseError::UnsupportedEncryption(msg) => Error::UnsupportedEncryption(msg),
244 DatabaseError::KeyDerivationFailed => Error::KeyDerivationFailed,
245 DatabaseError::EncryptionFailed(msg) => Error::EncryptionFailed(msg),
246 DatabaseError::DecryptionFailed(msg) => Error::DecryptionFailed(msg),
247 DatabaseError::SaltGenerationFailed => Error::SaltGenerationFailed,
248 DatabaseError::IncompatibleFileFormat => Error::IncompatibleFileFormat,
249 }
250 }
251}
252
253impl From<io::Error> for DatabaseError {
254 fn from(err: io::Error) -> DatabaseError {
255 DatabaseError::Storage(StorageError::Io(err))
256 }
257}
258
259impl From<StorageError> for DatabaseError {
260 fn from(err: StorageError) -> DatabaseError {
261 DatabaseError::Storage(err)
262 }
263}
264
265impl Display for DatabaseError {
266 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
267 match self {
268 DatabaseError::UpgradeRequired(actual) => {
269 write!(
270 f,
271 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION3}, but file is version {actual}"
272 )
273 }
274 DatabaseError::RepairAborted => {
275 write!(f, "Database repair aborted.")
276 }
277 DatabaseError::DatabaseAlreadyOpen => {
278 write!(f, "Database already open. Cannot acquire lock.")
279 }
280 DatabaseError::Storage(storage) => storage.fmt(f),
281 DatabaseError::IncorrectPassword => {
282 write!(f, "Incorrect password provided for encrypted database.")
283 }
284 DatabaseError::CorruptedEncryption(msg) => {
285 write!(f, "Encryption data is corrupted: {msg}")
286 }
287 DatabaseError::UnsupportedEncryption(msg) => {
288 write!(f, "Unsupported encryption algorithm or parameters: {msg}")
289 }
290 DatabaseError::KeyDerivationFailed => {
291 write!(f, "Key derivation failed.")
292 }
293 DatabaseError::EncryptionFailed(msg) => {
294 write!(f, "Encryption operation failed: {msg}")
295 }
296 DatabaseError::DecryptionFailed(msg) => {
297 write!(f, "Decryption operation failed: {msg}")
298 }
299 DatabaseError::SaltGenerationFailed => {
300 write!(f, "Salt generation failed.")
301 }
302 DatabaseError::IncompatibleFileFormat => {
303 write!(f, "Incompatible file format.")
304 }
305 }
306 }
307}
308
309impl std::error::Error for DatabaseError {}
310
311#[derive(Debug)]
313#[non_exhaustive]
314pub enum SavepointError {
315 InvalidSavepoint,
320 Storage(StorageError),
322}
323
324impl From<SavepointError> for Error {
325 fn from(err: SavepointError) -> Error {
326 match err {
327 SavepointError::InvalidSavepoint => Error::InvalidSavepoint,
328 SavepointError::Storage(storage) => storage.into(),
329 }
330 }
331}
332
333impl From<StorageError> for SavepointError {
334 fn from(err: StorageError) -> SavepointError {
335 SavepointError::Storage(err)
336 }
337}
338
339impl Display for SavepointError {
340 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
341 match self {
342 SavepointError::InvalidSavepoint => {
343 write!(f, "Savepoint is invalid or cannot be created.")
344 }
345 SavepointError::Storage(storage) => storage.fmt(f),
346 }
347 }
348}
349
350impl std::error::Error for SavepointError {}
351
352#[derive(Debug)]
354#[non_exhaustive]
355pub enum CompactionError {
356 PersistentSavepointExists,
358 EphemeralSavepointExists,
360 TransactionInProgress,
362 Storage(StorageError),
364}
365
366impl From<CompactionError> for Error {
367 fn from(err: CompactionError) -> Error {
368 match err {
369 CompactionError::PersistentSavepointExists => Error::PersistentSavepointExists,
370 CompactionError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
371 CompactionError::TransactionInProgress => Error::TransactionInProgress,
372 CompactionError::Storage(storage) => storage.into(),
373 }
374 }
375}
376
377impl From<StorageError> for CompactionError {
378 fn from(err: StorageError) -> CompactionError {
379 CompactionError::Storage(err)
380 }
381}
382
383impl Display for CompactionError {
384 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
385 match self {
386 CompactionError::PersistentSavepointExists => {
387 write!(
388 f,
389 "Persistent savepoint exists. Operation cannot be performed."
390 )
391 }
392 CompactionError::EphemeralSavepointExists => {
393 write!(
394 f,
395 "Ephemeral savepoint exists. Operation cannot be performed."
396 )
397 }
398 CompactionError::TransactionInProgress => {
399 write!(
400 f,
401 "A transaction is still in progress. Operation cannot be performed."
402 )
403 }
404 CompactionError::Storage(storage) => storage.fmt(f),
405 }
406 }
407}
408
409impl std::error::Error for CompactionError {}
410
411#[derive(Debug)]
413#[non_exhaustive]
414pub enum SetDurabilityError {
415 PersistentSavepointModified,
417}
418
419impl From<SetDurabilityError> for Error {
420 fn from(err: SetDurabilityError) -> Error {
421 match err {
422 SetDurabilityError::PersistentSavepointModified => Error::PersistentSavepointModified,
423 }
424 }
425}
426
427impl Display for SetDurabilityError {
428 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
429 match self {
430 SetDurabilityError::PersistentSavepointModified => {
431 write!(
432 f,
433 "Persistent savepoint modified. Cannot reduce transaction durability"
434 )
435 }
436 }
437 }
438}
439
440impl std::error::Error for SetDurabilityError {}
441
442#[derive(Debug)]
444#[non_exhaustive]
445pub enum TransactionError {
446 Storage(StorageError),
448 ReadTransactionStillInUse(Box<ReadTransaction>),
450}
451
452impl TransactionError {
453 pub(crate) fn into_storage_error(self) -> StorageError {
454 match self {
455 TransactionError::Storage(storage) => storage,
456 _ => unreachable!(),
457 }
458 }
459}
460
461impl From<TransactionError> for Error {
462 fn from(err: TransactionError) -> Error {
463 match err {
464 TransactionError::Storage(storage) => storage.into(),
465 TransactionError::ReadTransactionStillInUse(txn) => {
466 Error::ReadTransactionStillInUse(txn)
467 }
468 }
469 }
470}
471
472impl From<StorageError> for TransactionError {
473 fn from(err: StorageError) -> TransactionError {
474 TransactionError::Storage(err)
475 }
476}
477
478impl Display for TransactionError {
479 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
480 match self {
481 TransactionError::Storage(storage) => storage.fmt(f),
482 TransactionError::ReadTransactionStillInUse(_) => {
483 write!(f, "Transaction still in use")
484 }
485 }
486 }
487}
488
489impl std::error::Error for TransactionError {}
490
491#[derive(Debug)]
493#[non_exhaustive]
494pub enum CommitError {
495 Storage(StorageError),
497}
498
499impl CommitError {
500 pub(crate) fn into_storage_error(self) -> StorageError {
501 match self {
502 CommitError::Storage(storage) => storage,
503 }
504 }
505}
506
507impl From<CommitError> for Error {
508 fn from(err: CommitError) -> Error {
509 match err {
510 CommitError::Storage(storage) => storage.into(),
511 }
512 }
513}
514
515impl From<StorageError> for CommitError {
516 fn from(err: StorageError) -> CommitError {
517 CommitError::Storage(err)
518 }
519}
520
521impl Display for CommitError {
522 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
523 match self {
524 CommitError::Storage(storage) => storage.fmt(f),
525 }
526 }
527}
528
529impl std::error::Error for CommitError {}
530
531#[derive(Debug)]
533#[non_exhaustive]
534pub enum Error {
535 DatabaseAlreadyOpen,
537 InvalidSavepoint,
542 RepairAborted,
544 PersistentSavepointModified,
546 PersistentSavepointExists,
548 EphemeralSavepointExists,
550 TransactionInProgress,
552 Corrupted(String),
554 UpgradeRequired(u8),
556 ValueTooLarge(usize),
558 TableTypeMismatch {
560 table: String,
561 key: TypeName,
562 value: TypeName,
563 },
564 TableIsMultimap(String),
566 TableIsNotMultimap(String),
568 TypeDefinitionChanged {
569 name: TypeName,
570 alignment: usize,
571 width: Option<usize>,
572 },
573 TableDoesNotExist(String),
575 TableExists(String),
577 TableAlreadyOpen(String, &'static panic::Location<'static>),
580 Io(io::Error),
581 DatabaseClosed,
582 PreviousIo,
584 LockPoisoned(&'static panic::Location<'static>),
585 ReadTransactionStillInUse(Box<ReadTransaction>),
587 IncorrectPassword,
589 CorruptedEncryption(String),
591 UnsupportedEncryption(String),
593 KeyDerivationFailed,
595 EncryptionFailed(String),
597 DecryptionFailed(String),
599 SaltGenerationFailed,
601 IncompatibleFileFormat,
603}
604
605impl<T> From<PoisonError<T>> for Error {
606 fn from(_: PoisonError<T>) -> Error {
607 Error::LockPoisoned(panic::Location::caller())
608 }
609}
610
611impl From<io::Error> for Error {
612 fn from(err: io::Error) -> Error {
613 Error::Io(err)
614 }
615}
616
617impl Display for Error {
618 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
619 match self {
620 Error::Corrupted(msg) => {
621 write!(f, "DB corrupted: {msg}")
622 }
623 Error::UpgradeRequired(actual) => {
624 write!(
625 f,
626 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION3}, but file is version {actual}"
627 )
628 }
629 Error::ValueTooLarge(len) => {
630 write!(
631 f,
632 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
633 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
634 )
635 }
636 Error::TypeDefinitionChanged {
637 name,
638 alignment,
639 width,
640 } => {
641 write!(
642 f,
643 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
644 name.name(),
645 width,
646 alignment,
647 )
648 }
649 Error::TableTypeMismatch { table, key, value } => {
650 write!(
651 f,
652 "{table} is of type Table<{}, {}>",
653 key.name(),
654 value.name(),
655 )
656 }
657 Error::TableIsMultimap(table) => {
658 write!(f, "{table} is a multimap table")
659 }
660 Error::TableIsNotMultimap(table) => {
661 write!(f, "{table} is not a multimap table")
662 }
663 Error::TableDoesNotExist(table) => {
664 write!(f, "Table '{table}' does not exist")
665 }
666 Error::TableExists(table) => {
667 write!(f, "Table '{table}' already exists")
668 }
669 Error::TableAlreadyOpen(name, location) => {
670 write!(f, "Table '{name}' already opened at: {location}")
671 }
672 Error::Io(err) => {
673 write!(f, "I/O error: {err}")
674 }
675 Error::DatabaseClosed => {
676 write!(f, "Database has been closed")
677 }
678 Error::PreviousIo => {
679 write!(
680 f,
681 "Previous I/O error occurred. Please close and re-open the database."
682 )
683 }
684 Error::LockPoisoned(location) => {
685 write!(f, "Poisoned internal lock: {location}")
686 }
687 Error::DatabaseAlreadyOpen => {
688 write!(f, "Database already open. Cannot acquire lock.")
689 }
690 Error::RepairAborted => {
691 write!(f, "Database repair aborted.")
692 }
693 Error::PersistentSavepointModified => {
694 write!(
695 f,
696 "Persistent savepoint modified. Cannot reduce transaction durability"
697 )
698 }
699 Error::PersistentSavepointExists => {
700 write!(
701 f,
702 "Persistent savepoint exists. Operation cannot be performed."
703 )
704 }
705 Error::EphemeralSavepointExists => {
706 write!(
707 f,
708 "Ephemeral savepoint exists. Operation cannot be performed."
709 )
710 }
711 Error::TransactionInProgress => {
712 write!(
713 f,
714 "A transaction is still in progress. Operation cannot be performed."
715 )
716 }
717 Error::InvalidSavepoint => {
718 write!(f, "Savepoint is invalid or cannot be created.")
719 }
720 Error::ReadTransactionStillInUse(_) => {
721 write!(f, "Transaction still in use")
722 }
723 Error::IncorrectPassword => {
724 write!(f, "Incorrect password provided for encrypted database.")
725 }
726 Error::CorruptedEncryption(msg) => {
727 write!(f, "Encryption data is corrupted: {msg}")
728 }
729 Error::UnsupportedEncryption(msg) => {
730 write!(f, "Unsupported encryption algorithm or parameters: {msg}")
731 }
732 Error::KeyDerivationFailed => {
733 write!(f, "Key derivation failed.")
734 }
735 Error::EncryptionFailed(msg) => {
736 write!(f, "Encryption operation failed: {msg}")
737 }
738 Error::DecryptionFailed(msg) => {
739 write!(f, "Decryption operation failed: {msg}")
740 }
741 Error::SaltGenerationFailed => {
742 write!(f, "Salt generation failed.")
743 }
744 Error::IncompatibleFileFormat => {
745 write!(f, "Incompatible file format.")
746 }
747 }
748 }
749}
750
751impl std::error::Error for Error {}