1use crate::tree_store::{FILE_FORMAT_VERSION2, 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 LockPoisoned(&'static panic::Location<'static>),
18}
19
20impl<T> From<PoisonError<T>> for StorageError {
21 fn from(_: PoisonError<T>) -> StorageError {
22 StorageError::LockPoisoned(panic::Location::caller())
23 }
24}
25
26impl From<io::Error> for StorageError {
27 fn from(err: io::Error) -> StorageError {
28 StorageError::Io(err)
29 }
30}
31
32impl From<StorageError> for Error {
33 fn from(err: StorageError) -> Error {
34 match err {
35 StorageError::Corrupted(msg) => Error::Corrupted(msg),
36 StorageError::ValueTooLarge(x) => Error::ValueTooLarge(x),
37 StorageError::Io(x) => Error::Io(x),
38 StorageError::PreviousIo => Error::PreviousIo,
39 StorageError::LockPoisoned(location) => Error::LockPoisoned(location),
40 }
41 }
42}
43
44impl Display for StorageError {
45 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46 match self {
47 StorageError::Corrupted(msg) => {
48 write!(f, "DB corrupted: {msg}")
49 }
50 StorageError::ValueTooLarge(len) => {
51 write!(
52 f,
53 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
54 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
55 )
56 }
57 StorageError::Io(err) => {
58 write!(f, "I/O error: {err}")
59 }
60 StorageError::PreviousIo => {
61 write!(
62 f,
63 "Previous I/O error occurred. Please close and re-open the database."
64 )
65 }
66 StorageError::LockPoisoned(location) => {
67 write!(f, "Poisoned internal lock: {location}")
68 }
69 }
70 }
71}
72
73impl std::error::Error for StorageError {}
74
75#[derive(Debug)]
77#[non_exhaustive]
78pub enum TableError {
79 TableTypeMismatch {
81 table: String,
82 key: TypeName,
83 value: TypeName,
84 },
85 TableIsMultimap(String),
87 TableIsNotMultimap(String),
89 TypeDefinitionChanged {
90 name: TypeName,
91 alignment: usize,
92 width: Option<usize>,
93 },
94 TableDoesNotExist(String),
96 TableExists(String),
98 TableAlreadyOpen(String, &'static panic::Location<'static>),
101 Storage(StorageError),
103}
104
105impl TableError {
106 pub(crate) fn into_storage_error_or_corrupted(self, msg: &str) -> StorageError {
107 match self {
108 TableError::TableTypeMismatch { .. }
109 | TableError::TableIsMultimap(_)
110 | TableError::TableIsNotMultimap(_)
111 | TableError::TypeDefinitionChanged { .. }
112 | TableError::TableDoesNotExist(_)
113 | TableError::TableExists(_)
114 | TableError::TableAlreadyOpen(_, _) => {
115 StorageError::Corrupted(format!("{msg}: {self}"))
116 }
117 TableError::Storage(storage) => storage,
118 }
119 }
120}
121
122impl From<TableError> for Error {
123 fn from(err: TableError) -> Error {
124 match err {
125 TableError::TypeDefinitionChanged {
126 name,
127 alignment,
128 width,
129 } => Error::TypeDefinitionChanged {
130 name,
131 alignment,
132 width,
133 },
134 TableError::TableTypeMismatch { table, key, value } => {
135 Error::TableTypeMismatch { table, key, value }
136 }
137 TableError::TableIsMultimap(table) => Error::TableIsMultimap(table),
138 TableError::TableIsNotMultimap(table) => Error::TableIsNotMultimap(table),
139 TableError::TableDoesNotExist(table) => Error::TableDoesNotExist(table),
140 TableError::TableExists(table) => Error::TableExists(table),
141 TableError::TableAlreadyOpen(name, location) => Error::TableAlreadyOpen(name, location),
142 TableError::Storage(storage) => storage.into(),
143 }
144 }
145}
146
147impl From<StorageError> for TableError {
148 fn from(err: StorageError) -> TableError {
149 TableError::Storage(err)
150 }
151}
152
153impl Display for TableError {
154 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
155 match self {
156 TableError::TypeDefinitionChanged {
157 name,
158 alignment,
159 width,
160 } => {
161 write!(
162 f,
163 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
164 name.name(),
165 width,
166 alignment,
167 )
168 }
169 TableError::TableTypeMismatch { table, key, value } => {
170 write!(
171 f,
172 "{table} is of type Table<{}, {}>",
173 key.name(),
174 value.name(),
175 )
176 }
177 TableError::TableIsMultimap(table) => {
178 write!(f, "{table} is a multimap table")
179 }
180 TableError::TableIsNotMultimap(table) => {
181 write!(f, "{table} is not a multimap table")
182 }
183 TableError::TableDoesNotExist(table) => {
184 write!(f, "Table '{table}' does not exist")
185 }
186 TableError::TableExists(table) => {
187 write!(f, "Table '{table}' already exists")
188 }
189 TableError::TableAlreadyOpen(name, location) => {
190 write!(f, "Table '{name}' already opened at: {location}")
191 }
192 TableError::Storage(storage) => storage.fmt(f),
193 }
194 }
195}
196
197impl std::error::Error for TableError {}
198
199#[derive(Debug)]
201#[non_exhaustive]
202pub enum DatabaseError {
203 DatabaseAlreadyOpen,
205 RepairAborted,
207 UpgradeRequired(u8),
209 Storage(StorageError),
211}
212
213impl From<DatabaseError> for Error {
214 fn from(err: DatabaseError) -> Error {
215 match err {
216 DatabaseError::DatabaseAlreadyOpen => Error::DatabaseAlreadyOpen,
217 DatabaseError::RepairAborted => Error::RepairAborted,
218 DatabaseError::UpgradeRequired(x) => Error::UpgradeRequired(x),
219 DatabaseError::Storage(storage) => storage.into(),
220 }
221 }
222}
223
224impl From<io::Error> for DatabaseError {
225 fn from(err: io::Error) -> DatabaseError {
226 DatabaseError::Storage(StorageError::Io(err))
227 }
228}
229
230impl From<StorageError> for DatabaseError {
231 fn from(err: StorageError) -> DatabaseError {
232 DatabaseError::Storage(err)
233 }
234}
235
236impl Display for DatabaseError {
237 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
238 match self {
239 DatabaseError::UpgradeRequired(actual) => {
240 write!(
241 f,
242 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION2}, but file is version {actual}"
243 )
244 }
245 DatabaseError::RepairAborted => {
246 write!(f, "Database repair aborted.")
247 }
248 DatabaseError::DatabaseAlreadyOpen => {
249 write!(f, "Database already open. Cannot acquire lock.")
250 }
251 DatabaseError::Storage(storage) => storage.fmt(f),
252 }
253 }
254}
255
256impl std::error::Error for DatabaseError {}
257
258#[derive(Debug)]
260#[non_exhaustive]
261pub enum SavepointError {
262 InvalidSavepoint,
267 Storage(StorageError),
269}
270
271impl From<SavepointError> for Error {
272 fn from(err: SavepointError) -> Error {
273 match err {
274 SavepointError::InvalidSavepoint => Error::InvalidSavepoint,
275 SavepointError::Storage(storage) => storage.into(),
276 }
277 }
278}
279
280impl From<StorageError> for SavepointError {
281 fn from(err: StorageError) -> SavepointError {
282 SavepointError::Storage(err)
283 }
284}
285
286impl Display for SavepointError {
287 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
288 match self {
289 SavepointError::InvalidSavepoint => {
290 write!(f, "Savepoint is invalid or cannot be created.")
291 }
292 SavepointError::Storage(storage) => storage.fmt(f),
293 }
294 }
295}
296
297impl std::error::Error for SavepointError {}
298
299#[derive(Debug)]
301#[non_exhaustive]
302pub enum UpgradeError {
303 PersistentSavepointExists,
305 EphemeralSavepointExists,
307 TransactionInProgress,
309 Storage(StorageError),
311}
312
313impl From<UpgradeError> for Error {
314 fn from(err: UpgradeError) -> Error {
315 match err {
316 UpgradeError::PersistentSavepointExists => Error::PersistentSavepointExists,
317 UpgradeError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
318 UpgradeError::TransactionInProgress => Error::TransactionInProgress,
319 UpgradeError::Storage(storage) => storage.into(),
320 }
321 }
322}
323
324impl From<StorageError> for UpgradeError {
325 fn from(err: StorageError) -> UpgradeError {
326 UpgradeError::Storage(err)
327 }
328}
329
330impl From<CommitError> for UpgradeError {
331 fn from(err: CommitError) -> UpgradeError {
332 match err {
333 CommitError::Storage(err) => UpgradeError::Storage(err),
334 }
335 }
336}
337
338impl Display for UpgradeError {
339 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
340 match self {
341 UpgradeError::PersistentSavepointExists => {
342 write!(
343 f,
344 "Persistent savepoint exists. Operation cannot be performed."
345 )
346 }
347 UpgradeError::EphemeralSavepointExists => {
348 write!(
349 f,
350 "Ephemeral savepoint exists. Operation cannot be performed."
351 )
352 }
353 UpgradeError::TransactionInProgress => {
354 write!(
355 f,
356 "A transaction is still in progress. Operation cannot be performed."
357 )
358 }
359 UpgradeError::Storage(storage) => storage.fmt(f),
360 }
361 }
362}
363
364impl std::error::Error for UpgradeError {}
365
366#[derive(Debug)]
368#[non_exhaustive]
369pub enum CompactionError {
370 PersistentSavepointExists,
372 EphemeralSavepointExists,
374 TransactionInProgress,
376 Storage(StorageError),
378}
379
380impl From<CompactionError> for Error {
381 fn from(err: CompactionError) -> Error {
382 match err {
383 CompactionError::PersistentSavepointExists => Error::PersistentSavepointExists,
384 CompactionError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
385 CompactionError::TransactionInProgress => Error::TransactionInProgress,
386 CompactionError::Storage(storage) => storage.into(),
387 }
388 }
389}
390
391impl From<StorageError> for CompactionError {
392 fn from(err: StorageError) -> CompactionError {
393 CompactionError::Storage(err)
394 }
395}
396
397impl Display for CompactionError {
398 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
399 match self {
400 CompactionError::PersistentSavepointExists => {
401 write!(
402 f,
403 "Persistent savepoint exists. Operation cannot be performed."
404 )
405 }
406 CompactionError::EphemeralSavepointExists => {
407 write!(
408 f,
409 "Ephemeral savepoint exists. Operation cannot be performed."
410 )
411 }
412 CompactionError::TransactionInProgress => {
413 write!(
414 f,
415 "A transaction is still in progress. Operation cannot be performed."
416 )
417 }
418 CompactionError::Storage(storage) => storage.fmt(f),
419 }
420 }
421}
422
423impl std::error::Error for CompactionError {}
424
425#[derive(Debug)]
427#[non_exhaustive]
428pub enum TransactionError {
429 Storage(StorageError),
431 ReadTransactionStillInUse(ReadTransaction),
433}
434
435impl TransactionError {
436 pub(crate) fn into_storage_error(self) -> StorageError {
437 match self {
438 TransactionError::Storage(storage) => storage,
439 _ => unreachable!(),
440 }
441 }
442}
443
444impl From<TransactionError> for Error {
445 fn from(err: TransactionError) -> Error {
446 match err {
447 TransactionError::Storage(storage) => storage.into(),
448 TransactionError::ReadTransactionStillInUse(txn) => {
449 Error::ReadTransactionStillInUse(txn)
450 }
451 }
452 }
453}
454
455impl From<StorageError> for TransactionError {
456 fn from(err: StorageError) -> TransactionError {
457 TransactionError::Storage(err)
458 }
459}
460
461impl Display for TransactionError {
462 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
463 match self {
464 TransactionError::Storage(storage) => storage.fmt(f),
465 TransactionError::ReadTransactionStillInUse(_) => {
466 write!(f, "Transaction still in use")
467 }
468 }
469 }
470}
471
472impl std::error::Error for TransactionError {}
473
474#[derive(Debug)]
476#[non_exhaustive]
477pub enum CommitError {
478 Storage(StorageError),
480}
481
482impl CommitError {
483 pub(crate) fn into_storage_error(self) -> StorageError {
484 match self {
485 CommitError::Storage(storage) => storage,
486 }
487 }
488}
489
490impl From<CommitError> for Error {
491 fn from(err: CommitError) -> Error {
492 match err {
493 CommitError::Storage(storage) => storage.into(),
494 }
495 }
496}
497
498impl From<StorageError> for CommitError {
499 fn from(err: StorageError) -> CommitError {
500 CommitError::Storage(err)
501 }
502}
503
504impl Display for CommitError {
505 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
506 match self {
507 CommitError::Storage(storage) => storage.fmt(f),
508 }
509 }
510}
511
512impl std::error::Error for CommitError {}
513
514#[derive(Debug)]
516#[non_exhaustive]
517pub enum Error {
518 DatabaseAlreadyOpen,
520 InvalidSavepoint,
525 RepairAborted,
527 PersistentSavepointExists,
529 EphemeralSavepointExists,
531 TransactionInProgress,
533 Corrupted(String),
535 UpgradeRequired(u8),
537 ValueTooLarge(usize),
539 TableTypeMismatch {
541 table: String,
542 key: TypeName,
543 value: TypeName,
544 },
545 TableIsMultimap(String),
547 TableIsNotMultimap(String),
549 TypeDefinitionChanged {
550 name: TypeName,
551 alignment: usize,
552 width: Option<usize>,
553 },
554 TableDoesNotExist(String),
556 TableExists(String),
558 TableAlreadyOpen(String, &'static panic::Location<'static>),
561 Io(io::Error),
562 PreviousIo,
564 LockPoisoned(&'static panic::Location<'static>),
565 ReadTransactionStillInUse(ReadTransaction),
567}
568
569impl<T> From<PoisonError<T>> for Error {
570 fn from(_: PoisonError<T>) -> Error {
571 Error::LockPoisoned(panic::Location::caller())
572 }
573}
574
575impl From<io::Error> for Error {
576 fn from(err: io::Error) -> Error {
577 Error::Io(err)
578 }
579}
580
581impl Display for Error {
582 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
583 match self {
584 Error::Corrupted(msg) => {
585 write!(f, "DB corrupted: {msg}")
586 }
587 Error::UpgradeRequired(actual) => {
588 write!(
589 f,
590 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION2}, but file is version {actual}"
591 )
592 }
593 Error::ValueTooLarge(len) => {
594 write!(
595 f,
596 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
597 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
598 )
599 }
600 Error::TypeDefinitionChanged {
601 name,
602 alignment,
603 width,
604 } => {
605 write!(
606 f,
607 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
608 name.name(),
609 width,
610 alignment,
611 )
612 }
613 Error::TableTypeMismatch { table, key, value } => {
614 write!(
615 f,
616 "{table} is of type Table<{}, {}>",
617 key.name(),
618 value.name(),
619 )
620 }
621 Error::TableIsMultimap(table) => {
622 write!(f, "{table} is a multimap table")
623 }
624 Error::TableIsNotMultimap(table) => {
625 write!(f, "{table} is not a multimap table")
626 }
627 Error::TableDoesNotExist(table) => {
628 write!(f, "Table '{table}' does not exist")
629 }
630 Error::TableExists(table) => {
631 write!(f, "Table '{table}' already exists")
632 }
633 Error::TableAlreadyOpen(name, location) => {
634 write!(f, "Table '{name}' already opened at: {location}")
635 }
636 Error::Io(err) => {
637 write!(f, "I/O error: {err}")
638 }
639 Error::PreviousIo => {
640 write!(
641 f,
642 "Previous I/O error occurred. Please close and re-open the database."
643 )
644 }
645 Error::LockPoisoned(location) => {
646 write!(f, "Poisoned internal lock: {location}")
647 }
648 Error::DatabaseAlreadyOpen => {
649 write!(f, "Database already open. Cannot acquire lock.")
650 }
651 Error::RepairAborted => {
652 write!(f, "Database repair aborted.")
653 }
654 Error::PersistentSavepointExists => {
655 write!(
656 f,
657 "Persistent savepoint exists. Operation cannot be performed."
658 )
659 }
660 Error::EphemeralSavepointExists => {
661 write!(
662 f,
663 "Ephemeral savepoint exists. Operation cannot be performed."
664 )
665 }
666 Error::TransactionInProgress => {
667 write!(
668 f,
669 "A transaction is still in progress. Operation cannot be performed."
670 )
671 }
672 Error::InvalidSavepoint => {
673 write!(f, "Savepoint is invalid or cannot be created.")
674 }
675 Error::ReadTransactionStillInUse(_) => {
676 write!(f, "Transaction still in use")
677 }
678 }
679 }
680}
681
682impl std::error::Error for Error {}