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 CompactionError {
303 PersistentSavepointExists,
305 EphemeralSavepointExists,
307 TransactionInProgress,
309 Storage(StorageError),
311}
312
313impl From<CompactionError> for Error {
314 fn from(err: CompactionError) -> Error {
315 match err {
316 CompactionError::PersistentSavepointExists => Error::PersistentSavepointExists,
317 CompactionError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
318 CompactionError::TransactionInProgress => Error::TransactionInProgress,
319 CompactionError::Storage(storage) => storage.into(),
320 }
321 }
322}
323
324impl From<StorageError> for CompactionError {
325 fn from(err: StorageError) -> CompactionError {
326 CompactionError::Storage(err)
327 }
328}
329
330impl Display for CompactionError {
331 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
332 match self {
333 CompactionError::PersistentSavepointExists => {
334 write!(
335 f,
336 "Persistent savepoint exists. Operation cannot be performed."
337 )
338 }
339 CompactionError::EphemeralSavepointExists => {
340 write!(
341 f,
342 "Ephemeral savepoint exists. Operation cannot be performed."
343 )
344 }
345 CompactionError::TransactionInProgress => {
346 write!(
347 f,
348 "A transaction is still in progress. Operation cannot be performed."
349 )
350 }
351 CompactionError::Storage(storage) => storage.fmt(f),
352 }
353 }
354}
355
356impl std::error::Error for CompactionError {}
357
358#[derive(Debug)]
360#[non_exhaustive]
361pub enum TransactionError {
362 Storage(StorageError),
364 ReadTransactionStillInUse(ReadTransaction),
366}
367
368impl TransactionError {
369 pub(crate) fn into_storage_error(self) -> StorageError {
370 match self {
371 TransactionError::Storage(storage) => storage,
372 _ => unreachable!(),
373 }
374 }
375}
376
377impl From<TransactionError> for Error {
378 fn from(err: TransactionError) -> Error {
379 match err {
380 TransactionError::Storage(storage) => storage.into(),
381 TransactionError::ReadTransactionStillInUse(txn) => {
382 Error::ReadTransactionStillInUse(txn)
383 }
384 }
385 }
386}
387
388impl From<StorageError> for TransactionError {
389 fn from(err: StorageError) -> TransactionError {
390 TransactionError::Storage(err)
391 }
392}
393
394impl Display for TransactionError {
395 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
396 match self {
397 TransactionError::Storage(storage) => storage.fmt(f),
398 TransactionError::ReadTransactionStillInUse(_) => {
399 write!(f, "Transaction still in use")
400 }
401 }
402 }
403}
404
405impl std::error::Error for TransactionError {}
406
407#[derive(Debug)]
409#[non_exhaustive]
410pub enum CommitError {
411 Storage(StorageError),
413}
414
415impl CommitError {
416 pub(crate) fn into_storage_error(self) -> StorageError {
417 match self {
418 CommitError::Storage(storage) => storage,
419 }
420 }
421}
422
423impl From<CommitError> for Error {
424 fn from(err: CommitError) -> Error {
425 match err {
426 CommitError::Storage(storage) => storage.into(),
427 }
428 }
429}
430
431impl From<StorageError> for CommitError {
432 fn from(err: StorageError) -> CommitError {
433 CommitError::Storage(err)
434 }
435}
436
437impl Display for CommitError {
438 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
439 match self {
440 CommitError::Storage(storage) => storage.fmt(f),
441 }
442 }
443}
444
445impl std::error::Error for CommitError {}
446
447#[derive(Debug)]
449#[non_exhaustive]
450pub enum Error {
451 DatabaseAlreadyOpen,
453 InvalidSavepoint,
458 RepairAborted,
460 PersistentSavepointExists,
462 EphemeralSavepointExists,
464 TransactionInProgress,
466 Corrupted(String),
468 UpgradeRequired(u8),
470 ValueTooLarge(usize),
472 TableTypeMismatch {
474 table: String,
475 key: TypeName,
476 value: TypeName,
477 },
478 TableIsMultimap(String),
480 TableIsNotMultimap(String),
482 TypeDefinitionChanged {
483 name: TypeName,
484 alignment: usize,
485 width: Option<usize>,
486 },
487 TableDoesNotExist(String),
489 TableExists(String),
491 TableAlreadyOpen(String, &'static panic::Location<'static>),
494 Io(io::Error),
495 PreviousIo,
497 LockPoisoned(&'static panic::Location<'static>),
498 ReadTransactionStillInUse(ReadTransaction),
500}
501
502impl<T> From<PoisonError<T>> for Error {
503 fn from(_: PoisonError<T>) -> Error {
504 Error::LockPoisoned(panic::Location::caller())
505 }
506}
507
508impl From<io::Error> for Error {
509 fn from(err: io::Error) -> Error {
510 Error::Io(err)
511 }
512}
513
514impl Display for Error {
515 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
516 match self {
517 Error::Corrupted(msg) => {
518 write!(f, "DB corrupted: {msg}")
519 }
520 Error::UpgradeRequired(actual) => {
521 write!(
522 f,
523 "Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION2}, but file is version {actual}"
524 )
525 }
526 Error::ValueTooLarge(len) => {
527 write!(
528 f,
529 "The value (length={len}) being inserted exceeds the maximum of {}GiB",
530 MAX_VALUE_LENGTH / 1024 / 1024 / 1024
531 )
532 }
533 Error::TypeDefinitionChanged {
534 name,
535 alignment,
536 width,
537 } => {
538 write!(
539 f,
540 "Current definition of {} does not match stored definition (width={:?}, alignment={})",
541 name.name(),
542 width,
543 alignment,
544 )
545 }
546 Error::TableTypeMismatch { table, key, value } => {
547 write!(
548 f,
549 "{table} is of type Table<{}, {}>",
550 key.name(),
551 value.name(),
552 )
553 }
554 Error::TableIsMultimap(table) => {
555 write!(f, "{table} is a multimap table")
556 }
557 Error::TableIsNotMultimap(table) => {
558 write!(f, "{table} is not a multimap table")
559 }
560 Error::TableDoesNotExist(table) => {
561 write!(f, "Table '{table}' does not exist")
562 }
563 Error::TableExists(table) => {
564 write!(f, "Table '{table}' already exists")
565 }
566 Error::TableAlreadyOpen(name, location) => {
567 write!(f, "Table '{name}' already opened at: {location}")
568 }
569 Error::Io(err) => {
570 write!(f, "I/O error: {err}")
571 }
572 Error::PreviousIo => {
573 write!(
574 f,
575 "Previous I/O error occurred. Please close and re-open the database."
576 )
577 }
578 Error::LockPoisoned(location) => {
579 write!(f, "Poisoned internal lock: {location}")
580 }
581 Error::DatabaseAlreadyOpen => {
582 write!(f, "Database already open. Cannot acquire lock.")
583 }
584 Error::RepairAborted => {
585 write!(f, "Database repair aborted.")
586 }
587 Error::PersistentSavepointExists => {
588 write!(
589 f,
590 "Persistent savepoint exists. Operation cannot be performed."
591 )
592 }
593 Error::EphemeralSavepointExists => {
594 write!(
595 f,
596 "Ephemeral savepoint exists. Operation cannot be performed."
597 )
598 }
599 Error::TransactionInProgress => {
600 write!(
601 f,
602 "A transaction is still in progress. Operation cannot be performed."
603 )
604 }
605 Error::InvalidSavepoint => {
606 write!(f, "Savepoint is invalid or cannot be created.")
607 }
608 Error::ReadTransactionStillInUse(_) => {
609 write!(f, "Transaction still in use")
610 }
611 }
612 }
613}
614
615impl std::error::Error for Error {}