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}
217
218impl From<DatabaseError> for Error {
219 fn from(err: DatabaseError) -> Error {
220 match err {
221 DatabaseError::DatabaseAlreadyOpen => Error::DatabaseAlreadyOpen,
222 DatabaseError::RepairAborted => Error::RepairAborted,
223 DatabaseError::UpgradeRequired(x) => Error::UpgradeRequired(x),
224 DatabaseError::Storage(storage) => storage.into(),
225 }
226 }
227}
228
229impl From<io::Error> for DatabaseError {
230 fn from(err: io::Error) -> DatabaseError {
231 DatabaseError::Storage(StorageError::Io(err))
232 }
233}
234
235impl From<StorageError> for DatabaseError {
236 fn from(err: StorageError) -> DatabaseError {
237 DatabaseError::Storage(err)
238 }
239}
240
241impl Display for DatabaseError {
242 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
243 match self {
244 DatabaseError::UpgradeRequired(actual) => {
245 write!(
246 f,
247 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION3}, but file is version {actual}"
248 )
249 }
250 DatabaseError::RepairAborted => {
251 write!(f, "Database repair aborted.")
252 }
253 DatabaseError::DatabaseAlreadyOpen => {
254 write!(f, "Database already open. Cannot acquire lock.")
255 }
256 DatabaseError::Storage(storage) => storage.fmt(f),
257 }
258 }
259}
260
261impl std::error::Error for DatabaseError {}
262
263#[derive(Debug)]
265#[non_exhaustive]
266pub enum SavepointError {
267 InvalidSavepoint,
272 Storage(StorageError),
274}
275
276impl From<SavepointError> for Error {
277 fn from(err: SavepointError) -> Error {
278 match err {
279 SavepointError::InvalidSavepoint => Error::InvalidSavepoint,
280 SavepointError::Storage(storage) => storage.into(),
281 }
282 }
283}
284
285impl From<StorageError> for SavepointError {
286 fn from(err: StorageError) -> SavepointError {
287 SavepointError::Storage(err)
288 }
289}
290
291impl Display for SavepointError {
292 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
293 match self {
294 SavepointError::InvalidSavepoint => {
295 write!(f, "Savepoint is invalid or cannot be created.")
296 }
297 SavepointError::Storage(storage) => storage.fmt(f),
298 }
299 }
300}
301
302impl std::error::Error for SavepointError {}
303
304#[derive(Debug)]
306#[non_exhaustive]
307pub enum CompactionError {
308 PersistentSavepointExists,
310 EphemeralSavepointExists,
312 TransactionInProgress,
314 Storage(StorageError),
316}
317
318impl From<CompactionError> for Error {
319 fn from(err: CompactionError) -> Error {
320 match err {
321 CompactionError::PersistentSavepointExists => Error::PersistentSavepointExists,
322 CompactionError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
323 CompactionError::TransactionInProgress => Error::TransactionInProgress,
324 CompactionError::Storage(storage) => storage.into(),
325 }
326 }
327}
328
329impl From<StorageError> for CompactionError {
330 fn from(err: StorageError) -> CompactionError {
331 CompactionError::Storage(err)
332 }
333}
334
335impl Display for CompactionError {
336 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
337 match self {
338 CompactionError::PersistentSavepointExists => {
339 write!(
340 f,
341 "Persistent savepoint exists. Operation cannot be performed."
342 )
343 }
344 CompactionError::EphemeralSavepointExists => {
345 write!(
346 f,
347 "Ephemeral savepoint exists. Operation cannot be performed."
348 )
349 }
350 CompactionError::TransactionInProgress => {
351 write!(
352 f,
353 "A transaction is still in progress. Operation cannot be performed."
354 )
355 }
356 CompactionError::Storage(storage) => storage.fmt(f),
357 }
358 }
359}
360
361impl std::error::Error for CompactionError {}
362
363#[derive(Debug)]
365#[non_exhaustive]
366pub enum SetDurabilityError {
367 PersistentSavepointModified,
369}
370
371impl From<SetDurabilityError> for Error {
372 fn from(err: SetDurabilityError) -> Error {
373 match err {
374 SetDurabilityError::PersistentSavepointModified => Error::PersistentSavepointModified,
375 }
376 }
377}
378
379impl Display for SetDurabilityError {
380 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
381 match self {
382 SetDurabilityError::PersistentSavepointModified => {
383 write!(
384 f,
385 "Persistent savepoint modified. Cannot reduce transaction durability"
386 )
387 }
388 }
389 }
390}
391
392impl std::error::Error for SetDurabilityError {}
393
394#[derive(Debug)]
396#[non_exhaustive]
397pub enum TransactionError {
398 Storage(StorageError),
400 ReadTransactionStillInUse(Box<ReadTransaction>),
402}
403
404impl TransactionError {
405 pub(crate) fn into_storage_error(self) -> StorageError {
406 match self {
407 TransactionError::Storage(storage) => storage,
408 _ => unreachable!(),
409 }
410 }
411}
412
413impl From<TransactionError> for Error {
414 fn from(err: TransactionError) -> Error {
415 match err {
416 TransactionError::Storage(storage) => storage.into(),
417 TransactionError::ReadTransactionStillInUse(txn) => {
418 Error::ReadTransactionStillInUse(txn)
419 }
420 }
421 }
422}
423
424impl From<StorageError> for TransactionError {
425 fn from(err: StorageError) -> TransactionError {
426 TransactionError::Storage(err)
427 }
428}
429
430impl Display for TransactionError {
431 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
432 match self {
433 TransactionError::Storage(storage) => storage.fmt(f),
434 TransactionError::ReadTransactionStillInUse(_) => {
435 write!(f, "Transaction still in use")
436 }
437 }
438 }
439}
440
441impl std::error::Error for TransactionError {}
442
443#[derive(Debug)]
445#[non_exhaustive]
446pub enum CommitError {
447 Storage(StorageError),
449}
450
451impl CommitError {
452 pub(crate) fn into_storage_error(self) -> StorageError {
453 match self {
454 CommitError::Storage(storage) => storage,
455 }
456 }
457}
458
459impl From<CommitError> for Error {
460 fn from(err: CommitError) -> Error {
461 match err {
462 CommitError::Storage(storage) => storage.into(),
463 }
464 }
465}
466
467impl From<StorageError> for CommitError {
468 fn from(err: StorageError) -> CommitError {
469 CommitError::Storage(err)
470 }
471}
472
473impl Display for CommitError {
474 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
475 match self {
476 CommitError::Storage(storage) => storage.fmt(f),
477 }
478 }
479}
480
481impl std::error::Error for CommitError {}
482
483#[derive(Debug)]
485#[non_exhaustive]
486pub enum Error {
487 DatabaseAlreadyOpen,
489 InvalidSavepoint,
494 RepairAborted,
496 PersistentSavepointModified,
498 PersistentSavepointExists,
500 EphemeralSavepointExists,
502 TransactionInProgress,
504 Corrupted(String),
506 UpgradeRequired(u8),
508 ValueTooLarge(usize),
510 TableTypeMismatch {
512 table: String,
513 key: TypeName,
514 value: TypeName,
515 },
516 TableIsMultimap(String),
518 TableIsNotMultimap(String),
520 TypeDefinitionChanged {
521 name: TypeName,
522 alignment: usize,
523 width: Option<usize>,
524 },
525 TableDoesNotExist(String),
527 TableExists(String),
529 TableAlreadyOpen(String, &'static panic::Location<'static>),
532 Io(io::Error),
533 DatabaseClosed,
534 PreviousIo,
536 LockPoisoned(&'static panic::Location<'static>),
537 ReadTransactionStillInUse(Box<ReadTransaction>),
539}
540
541impl<T> From<PoisonError<T>> for Error {
542 fn from(_: PoisonError<T>) -> Error {
543 Error::LockPoisoned(panic::Location::caller())
544 }
545}
546
547impl From<io::Error> for Error {
548 fn from(err: io::Error) -> Error {
549 Error::Io(err)
550 }
551}
552
553impl Display for Error {
554 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
555 match self {
556 Error::Corrupted(msg) => {
557 write!(f, "DB corrupted: {msg}")
558 }
559 Error::UpgradeRequired(actual) => {
560 write!(
561 f,
562 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION3}, but file is version {actual}"
563 )
564 }
565 Error::ValueTooLarge(len) => {
566 write!(
567 f,
568 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
569 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
570 )
571 }
572 Error::TypeDefinitionChanged {
573 name,
574 alignment,
575 width,
576 } => {
577 write!(
578 f,
579 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
580 name.name(),
581 width,
582 alignment,
583 )
584 }
585 Error::TableTypeMismatch { table, key, value } => {
586 write!(
587 f,
588 "{table} is of type Table<{}, {}>",
589 key.name(),
590 value.name(),
591 )
592 }
593 Error::TableIsMultimap(table) => {
594 write!(f, "{table} is a multimap table")
595 }
596 Error::TableIsNotMultimap(table) => {
597 write!(f, "{table} is not a multimap table")
598 }
599 Error::TableDoesNotExist(table) => {
600 write!(f, "Table '{table}' does not exist")
601 }
602 Error::TableExists(table) => {
603 write!(f, "Table '{table}' already exists")
604 }
605 Error::TableAlreadyOpen(name, location) => {
606 write!(f, "Table '{name}' already opened at: {location}")
607 }
608 Error::Io(err) => {
609 write!(f, "I/O error: {err}")
610 }
611 Error::DatabaseClosed => {
612 write!(f, "Database has been closed")
613 }
614 Error::PreviousIo => {
615 write!(
616 f,
617 "Previous I/O error occurred. Please close and re-open the database."
618 )
619 }
620 Error::LockPoisoned(location) => {
621 write!(f, "Poisoned internal lock: {location}")
622 }
623 Error::DatabaseAlreadyOpen => {
624 write!(f, "Database already open. Cannot acquire lock.")
625 }
626 Error::RepairAborted => {
627 write!(f, "Database repair aborted.")
628 }
629 Error::PersistentSavepointModified => {
630 write!(
631 f,
632 "Persistent savepoint modified. Cannot reduce transaction durability"
633 )
634 }
635 Error::PersistentSavepointExists => {
636 write!(
637 f,
638 "Persistent savepoint exists. Operation cannot be performed."
639 )
640 }
641 Error::EphemeralSavepointExists => {
642 write!(
643 f,
644 "Ephemeral savepoint exists. Operation cannot be performed."
645 )
646 }
647 Error::TransactionInProgress => {
648 write!(
649 f,
650 "A transaction is still in progress. Operation cannot be performed."
651 )
652 }
653 Error::InvalidSavepoint => {
654 write!(f, "Savepoint is invalid or cannot be created.")
655 }
656 Error::ReadTransactionStillInUse(_) => {
657 write!(f, "Transaction still in use")
658 }
659 }
660 }
661}
662
663impl std::error::Error for Error {}