use crate::tree_store::{FILE_FORMAT_VERSION3, MAX_VALUE_LENGTH, PageNumber};
use crate::{ReadTransaction, TypeName};
use alloc::boxed::Box;
use alloc::format;
use alloc::string::String;
use core::fmt::{Display, Formatter};
use core::panic;
#[cfg(feature = "std")]
use crate::group_commit::GroupCommitError;
#[cfg(feature = "std")]
use std::sync::PoisonError;
#[derive(Debug)]
pub enum BackendError {
#[cfg(feature = "std")]
Io(std::io::Error),
#[cfg(not(feature = "std"))]
Message(String),
}
impl Display for BackendError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "std")]
BackendError::Io(err) => write!(f, "{err}"),
#[cfg(not(feature = "std"))]
BackendError::Message(msg) => write!(f, "{msg}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for BackendError {}
#[cfg(feature = "std")]
impl From<std::io::Error> for BackendError {
fn from(err: std::io::Error) -> Self {
BackendError::Io(err)
}
}
impl BackendError {
#[cfg(feature = "std")]
pub fn kind(&self) -> std::io::ErrorKind {
match self {
BackendError::Io(e) => e.kind(),
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum StorageError {
Corrupted(String),
ValueTooLarge(usize),
BlobNotFound(u64),
BlobChecksumMismatch {
sequence: u64,
expected: u128,
actual: u128,
},
BlobWriterActive,
BlobRangeOutOfBounds {
blob_length: u64,
requested_offset: u64,
requested_length: u64,
},
MemoryBudgetExceeded {
budget: usize,
used: usize,
},
HistorySnapshotNotFound(u64),
InvalidPageType {
page_region: u32,
page_index: u32,
page_order: u8,
found: u8,
},
InvalidChildRef {
page_region: u32,
page_index: u32,
page_order: u8,
child_index: usize,
is_checksum: bool,
},
InvalidEntryIndex {
page_region: u32,
page_index: u32,
page_order: u8,
entry_index: usize,
},
PageCorrupted {
page_region: u32,
page_index: u32,
page_order: u8,
detail: &'static str,
},
Io(BackendError),
PreviousIo,
DatabaseClosed,
LockPoisoned(&'static panic::Location<'static>),
}
#[cfg(feature = "std")]
impl<T> From<PoisonError<T>> for StorageError {
fn from(_: PoisonError<T>) -> StorageError {
StorageError::LockPoisoned(panic::Location::caller())
}
}
impl From<BackendError> for StorageError {
fn from(err: BackendError) -> StorageError {
StorageError::Io(err)
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for StorageError {
fn from(err: std::io::Error) -> StorageError {
StorageError::Io(BackendError::Io(err))
}
}
impl From<StorageError> for Error {
fn from(err: StorageError) -> Error {
match err {
StorageError::Corrupted(msg) => Error::Corrupted(msg),
StorageError::ValueTooLarge(x) => Error::ValueTooLarge(x),
StorageError::BlobNotFound(seq) => Error::BlobNotFound(seq),
StorageError::BlobChecksumMismatch {
sequence,
expected,
actual,
} => Error::BlobChecksumMismatch {
sequence,
expected,
actual,
},
StorageError::BlobWriterActive => Error::BlobWriterActive,
StorageError::BlobRangeOutOfBounds {
blob_length,
requested_offset,
requested_length,
} => Error::BlobRangeOutOfBounds {
blob_length,
requested_offset,
requested_length,
},
StorageError::MemoryBudgetExceeded { budget, used } => {
Error::MemoryBudgetExceeded { budget, used }
}
StorageError::HistorySnapshotNotFound(id) => Error::HistorySnapshotNotFound(id),
StorageError::InvalidPageType {
page_region,
page_index,
page_order,
found,
} => Error::InvalidPageType {
page_region,
page_index,
page_order,
found,
},
StorageError::InvalidChildRef {
page_region,
page_index,
page_order,
child_index,
is_checksum,
} => Error::InvalidChildRef {
page_region,
page_index,
page_order,
child_index,
is_checksum,
},
StorageError::InvalidEntryIndex {
page_region,
page_index,
page_order,
entry_index,
} => Error::InvalidEntryIndex {
page_region,
page_index,
page_order,
entry_index,
},
StorageError::PageCorrupted {
page_region,
page_index,
page_order,
detail,
} => Error::PageCorrupted {
page_region,
page_index,
page_order,
detail,
},
StorageError::Io(x) => Error::Io(x),
StorageError::PreviousIo => Error::PreviousIo,
StorageError::DatabaseClosed => Error::DatabaseClosed,
StorageError::LockPoisoned(location) => Error::LockPoisoned(location),
}
}
}
impl Display for StorageError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
StorageError::Corrupted(msg) => {
write!(f, "DB corrupted: {msg}")
}
StorageError::ValueTooLarge(len) => {
write!(
f,
"The value (length={len}) being inserted exceeds the maximum of {}GiB",
MAX_VALUE_LENGTH / 1024 / 1024 / 1024
)
}
StorageError::BlobNotFound(seq) => {
write!(f, "Blob not found: sequence={seq}")
}
StorageError::BlobChecksumMismatch {
sequence,
expected,
actual,
} => {
write!(
f,
"Blob checksum mismatch: sequence={sequence}, expected={expected:#034x}, actual={actual:#034x}"
)
}
StorageError::BlobWriterActive => {
write!(
f,
"Cannot create blob writer or store blob while another writer is active"
)
}
StorageError::BlobRangeOutOfBounds {
blob_length,
requested_offset,
requested_length,
} => {
write!(
f,
"Blob range out of bounds: blob_length={blob_length}, requested offset={requested_offset}, length={requested_length}"
)
}
StorageError::MemoryBudgetExceeded { budget, used } => {
write!(
f,
"Memory budget exceeded: budget={budget} bytes, used={used} bytes"
)
}
StorageError::HistorySnapshotNotFound(id) => {
write!(f, "History snapshot not found for transaction id={id}")
}
StorageError::InvalidPageType {
page_region,
page_index,
page_order,
found,
} => {
write!(
f,
"Invalid page type byte {found} on page ({page_region}, {page_index}, order={page_order}), expected LEAF (1) or BRANCH (2)"
)
}
StorageError::InvalidChildRef {
page_region,
page_index,
page_order,
child_index,
is_checksum,
} => {
let kind = if *is_checksum { "checksum" } else { "pointer" };
write!(
f,
"Invalid child {kind} at index {child_index} on page ({page_region}, {page_index}, order={page_order})"
)
}
StorageError::InvalidEntryIndex {
page_region,
page_index,
page_order,
entry_index,
} => {
write!(
f,
"Invalid entry index {entry_index} on page ({page_region}, {page_index}, order={page_order})"
)
}
StorageError::PageCorrupted {
page_region,
page_index,
page_order,
detail,
} => {
write!(
f,
"Page ({page_region}, {page_index}, order={page_order}) corrupted: {detail}"
)
}
StorageError::Io(err) => {
write!(f, "I/O error: {err}")
}
StorageError::DatabaseClosed => {
write!(f, "Database has been closed")
}
StorageError::PreviousIo => {
write!(
f,
"Previous I/O error occurred. Please close and re-open the database."
)
}
StorageError::LockPoisoned(location) => {
write!(f, "Poisoned internal lock: {location}")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for StorageError {}
impl StorageError {
pub(crate) fn invalid_page_type(page: PageNumber, found: u8) -> Self {
StorageError::InvalidPageType {
page_region: page.region,
page_index: page.page_index,
page_order: page.page_order,
found,
}
}
pub(crate) fn invalid_child_pointer(page: PageNumber, child_index: usize) -> Self {
StorageError::InvalidChildRef {
page_region: page.region,
page_index: page.page_index,
page_order: page.page_order,
child_index,
is_checksum: false,
}
}
pub(crate) fn invalid_child_checksum(page: PageNumber, child_index: usize) -> Self {
StorageError::InvalidChildRef {
page_region: page.region,
page_index: page.page_index,
page_order: page.page_order,
child_index,
is_checksum: true,
}
}
pub(crate) fn invalid_entry_index(page: PageNumber, entry_index: usize) -> Self {
StorageError::InvalidEntryIndex {
page_region: page.region,
page_index: page.page_index,
page_order: page.page_order,
entry_index,
}
}
pub(crate) fn page_corrupted(page: PageNumber, detail: &'static str) -> Self {
StorageError::PageCorrupted {
page_region: page.region,
page_index: page.page_index,
page_order: page.page_order,
detail,
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum TableError {
TableTypeMismatch {
table: String,
key: TypeName,
value: TypeName,
},
TableIsMultimap(String),
TableIsNotMultimap(String),
TypeDefinitionChanged {
name: TypeName,
alignment: usize,
width: Option<usize>,
},
TableDoesNotExist(String),
TableExists(String),
TableAlreadyOpen(String, &'static panic::Location<'static>),
Storage(StorageError),
}
impl TableError {
pub(crate) fn into_storage_error_or_corrupted(self, msg: &str) -> StorageError {
match self {
TableError::TableTypeMismatch { .. }
| TableError::TableIsMultimap(_)
| TableError::TableIsNotMultimap(_)
| TableError::TypeDefinitionChanged { .. }
| TableError::TableDoesNotExist(_)
| TableError::TableExists(_)
| TableError::TableAlreadyOpen(_, _) => {
StorageError::Corrupted(format!("{msg}: {self}"))
}
TableError::Storage(storage) => storage,
}
}
}
impl From<TableError> for Error {
fn from(err: TableError) -> Error {
match err {
TableError::TypeDefinitionChanged {
name,
alignment,
width,
} => Error::TypeDefinitionChanged {
name,
alignment,
width,
},
TableError::TableTypeMismatch { table, key, value } => {
Error::TableTypeMismatch { table, key, value }
}
TableError::TableIsMultimap(table) => Error::TableIsMultimap(table),
TableError::TableIsNotMultimap(table) => Error::TableIsNotMultimap(table),
TableError::TableDoesNotExist(table) => Error::TableDoesNotExist(table),
TableError::TableExists(table) => Error::TableExists(table),
TableError::TableAlreadyOpen(name, location) => Error::TableAlreadyOpen(name, location),
TableError::Storage(storage) => storage.into(),
}
}
}
impl From<StorageError> for TableError {
fn from(err: StorageError) -> TableError {
TableError::Storage(err)
}
}
impl Display for TableError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
TableError::TypeDefinitionChanged {
name,
alignment,
width,
} => {
write!(
f,
"Current definition of {} does not match stored definition (width={:?}, alignment={})",
name.name(),
width,
alignment,
)
}
TableError::TableTypeMismatch { table, key, value } => {
write!(
f,
"{table} is of type Table<{}, {}>",
key.name(),
value.name(),
)
}
TableError::TableIsMultimap(table) => {
write!(f, "{table} is a multimap table")
}
TableError::TableIsNotMultimap(table) => {
write!(f, "{table} is not a multimap table")
}
TableError::TableDoesNotExist(table) => {
write!(f, "Table '{table}' does not exist")
}
TableError::TableExists(table) => {
write!(f, "Table '{table}' already exists")
}
TableError::TableAlreadyOpen(name, location) => {
write!(f, "Table '{name}' already opened at: {location}")
}
TableError::Storage(storage) => storage.fmt(f),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for TableError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum DatabaseError {
DatabaseAlreadyOpen,
RepairAborted,
UpgradeRequired(u8),
Storage(StorageError),
}
impl From<DatabaseError> for Error {
fn from(err: DatabaseError) -> Error {
match err {
DatabaseError::DatabaseAlreadyOpen => Error::DatabaseAlreadyOpen,
DatabaseError::RepairAborted => Error::RepairAborted,
DatabaseError::UpgradeRequired(x) => Error::UpgradeRequired(x),
DatabaseError::Storage(storage) => storage.into(),
}
}
}
impl From<BackendError> for DatabaseError {
fn from(err: BackendError) -> DatabaseError {
DatabaseError::Storage(StorageError::Io(err))
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for DatabaseError {
fn from(err: std::io::Error) -> DatabaseError {
DatabaseError::Storage(StorageError::Io(BackendError::Io(err)))
}
}
impl From<StorageError> for DatabaseError {
fn from(err: StorageError) -> DatabaseError {
DatabaseError::Storage(err)
}
}
impl Display for DatabaseError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
DatabaseError::UpgradeRequired(actual) => {
write!(
f,
"Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION3}, but file is version {actual}"
)
}
DatabaseError::RepairAborted => {
write!(f, "Database repair aborted.")
}
DatabaseError::DatabaseAlreadyOpen => {
write!(f, "Database already open. Cannot acquire lock.")
}
DatabaseError::Storage(storage) => storage.fmt(f),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for DatabaseError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum SavepointError {
InvalidSavepoint,
Storage(StorageError),
}
impl From<SavepointError> for Error {
fn from(err: SavepointError) -> Error {
match err {
SavepointError::InvalidSavepoint => Error::InvalidSavepoint,
SavepointError::Storage(storage) => storage.into(),
}
}
}
impl From<StorageError> for SavepointError {
fn from(err: StorageError) -> SavepointError {
SavepointError::Storage(err)
}
}
impl Display for SavepointError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
SavepointError::InvalidSavepoint => {
write!(f, "Savepoint is invalid or cannot be created.")
}
SavepointError::Storage(storage) => storage.fmt(f),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for SavepointError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum CompactionError {
PersistentSavepointExists,
EphemeralSavepointExists,
TransactionInProgress,
Storage(StorageError),
}
impl From<CompactionError> for Error {
fn from(err: CompactionError) -> Error {
match err {
CompactionError::PersistentSavepointExists => Error::PersistentSavepointExists,
CompactionError::EphemeralSavepointExists => Error::EphemeralSavepointExists,
CompactionError::TransactionInProgress => Error::TransactionInProgress,
CompactionError::Storage(storage) => storage.into(),
}
}
}
impl From<StorageError> for CompactionError {
fn from(err: StorageError) -> CompactionError {
CompactionError::Storage(err)
}
}
impl Display for CompactionError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
CompactionError::PersistentSavepointExists => {
write!(
f,
"Persistent savepoint exists. Operation cannot be performed."
)
}
CompactionError::EphemeralSavepointExists => {
write!(
f,
"Ephemeral savepoint exists. Operation cannot be performed."
)
}
CompactionError::TransactionInProgress => {
write!(
f,
"A transaction is still in progress. Operation cannot be performed."
)
}
CompactionError::Storage(storage) => storage.fmt(f),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for CompactionError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum SetDurabilityError {
PersistentSavepointModified,
}
impl From<SetDurabilityError> for Error {
fn from(err: SetDurabilityError) -> Error {
match err {
SetDurabilityError::PersistentSavepointModified => Error::PersistentSavepointModified,
}
}
}
impl Display for SetDurabilityError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
SetDurabilityError::PersistentSavepointModified => {
write!(
f,
"Persistent savepoint modified. Cannot reduce transaction durability"
)
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for SetDurabilityError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum TransactionError {
Storage(StorageError),
ReadTransactionStillInUse(Box<ReadTransaction>),
}
impl TransactionError {
pub(crate) fn into_storage_error(self) -> StorageError {
match self {
TransactionError::Storage(storage) => storage,
_ => StorageError::Corrupted(String::from("unexpected non-storage transaction error")),
}
}
}
impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Error {
match err {
TransactionError::Storage(storage) => storage.into(),
TransactionError::ReadTransactionStillInUse(txn) => {
Error::ReadTransactionStillInUse(txn)
}
}
}
}
impl From<StorageError> for TransactionError {
fn from(err: StorageError) -> TransactionError {
TransactionError::Storage(err)
}
}
impl Display for TransactionError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
TransactionError::Storage(storage) => storage.fmt(f),
TransactionError::ReadTransactionStillInUse(_) => {
write!(f, "Transaction still in use")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for TransactionError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum CommitError {
Storage(StorageError),
}
impl CommitError {
pub(crate) fn into_storage_error(self) -> StorageError {
match self {
CommitError::Storage(storage) => storage,
}
}
}
impl From<CommitError> for Error {
fn from(err: CommitError) -> Error {
match err {
CommitError::Storage(storage) => storage.into(),
}
}
}
impl From<StorageError> for CommitError {
fn from(err: StorageError) -> CommitError {
CommitError::Storage(err)
}
}
impl Display for CommitError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
CommitError::Storage(storage) => storage.fmt(f),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for CommitError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
DatabaseAlreadyOpen,
InvalidSavepoint,
RepairAborted,
PersistentSavepointModified,
PersistentSavepointExists,
EphemeralSavepointExists,
TransactionInProgress,
Corrupted(String),
UpgradeRequired(u8),
ValueTooLarge(usize),
TableTypeMismatch {
table: String,
key: TypeName,
value: TypeName,
},
TableIsMultimap(String),
TableIsNotMultimap(String),
TypeDefinitionChanged {
name: TypeName,
alignment: usize,
width: Option<usize>,
},
TableDoesNotExist(String),
TableExists(String),
TableAlreadyOpen(String, &'static panic::Location<'static>),
BlobNotFound(u64),
BlobChecksumMismatch {
sequence: u64,
expected: u128,
actual: u128,
},
BlobWriterActive,
BlobRangeOutOfBounds {
blob_length: u64,
requested_offset: u64,
requested_length: u64,
},
MemoryBudgetExceeded {
budget: usize,
used: usize,
},
HistorySnapshotNotFound(u64),
InvalidPageType {
page_region: u32,
page_index: u32,
page_order: u8,
found: u8,
},
InvalidChildRef {
page_region: u32,
page_index: u32,
page_order: u8,
child_index: usize,
is_checksum: bool,
},
InvalidEntryIndex {
page_region: u32,
page_index: u32,
page_order: u8,
entry_index: usize,
},
PageCorrupted {
page_region: u32,
page_index: u32,
page_order: u8,
detail: &'static str,
},
Io(BackendError),
DatabaseClosed,
PreviousIo,
LockPoisoned(&'static panic::Location<'static>),
ReadTransactionStillInUse(Box<ReadTransaction>),
#[cfg(feature = "std")]
GroupCommitPeerFailed,
#[cfg(feature = "std")]
GroupCommitShutdown,
}
#[cfg(feature = "std")]
impl From<GroupCommitError> for Error {
fn from(err: GroupCommitError) -> Error {
match err {
GroupCommitError::BatchFailed(e) => e,
GroupCommitError::PeerFailed => Error::GroupCommitPeerFailed,
GroupCommitError::TransactionFailed(e) | GroupCommitError::CommitFailed(e) => e.into(),
GroupCommitError::Shutdown => Error::GroupCommitShutdown,
GroupCommitError::LockPoisoned => Error::LockPoisoned(panic::Location::caller()),
}
}
}
#[cfg(feature = "std")]
impl<T> From<PoisonError<T>> for Error {
fn from(_: PoisonError<T>) -> Error {
Error::LockPoisoned(panic::Location::caller())
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Error {
Error::Io(BackendError::Io(err))
}
}
impl From<BackendError> for Error {
fn from(err: BackendError) -> Error {
Error::Io(err)
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Error::Corrupted(msg) => {
write!(f, "DB corrupted: {msg}")
}
Error::UpgradeRequired(actual) => {
write!(
f,
"Manual upgrade required. Expected file format version {FILE_FORMAT_VERSION3}, but file is version {actual}"
)
}
Error::ValueTooLarge(len) => {
write!(
f,
"The value (length={len}) being inserted exceeds the maximum of {}GiB",
MAX_VALUE_LENGTH / 1024 / 1024 / 1024
)
}
Error::TypeDefinitionChanged {
name,
alignment,
width,
} => {
write!(
f,
"Current definition of {} does not match stored definition (width={:?}, alignment={})",
name.name(),
width,
alignment,
)
}
Error::TableTypeMismatch { table, key, value } => {
write!(
f,
"{table} is of type Table<{}, {}>",
key.name(),
value.name(),
)
}
Error::TableIsMultimap(table) => {
write!(f, "{table} is a multimap table")
}
Error::TableIsNotMultimap(table) => {
write!(f, "{table} is not a multimap table")
}
Error::TableDoesNotExist(table) => {
write!(f, "Table '{table}' does not exist")
}
Error::TableExists(table) => {
write!(f, "Table '{table}' already exists")
}
Error::TableAlreadyOpen(name, location) => {
write!(f, "Table '{name}' already opened at: {location}")
}
Error::BlobNotFound(seq) => {
write!(f, "Blob not found: sequence={seq}")
}
Error::BlobChecksumMismatch {
sequence,
expected,
actual,
} => {
write!(
f,
"Blob checksum mismatch: sequence={sequence}, expected={expected:#034x}, actual={actual:#034x}"
)
}
Error::BlobWriterActive => {
write!(
f,
"Cannot create blob writer or store blob while another writer is active"
)
}
Error::BlobRangeOutOfBounds {
blob_length,
requested_offset,
requested_length,
} => {
write!(
f,
"Blob range out of bounds: blob_length={blob_length}, requested offset={requested_offset}, length={requested_length}"
)
}
Error::MemoryBudgetExceeded { budget, used } => {
write!(
f,
"Memory budget exceeded: budget={budget} bytes, used={used} bytes"
)
}
Error::HistorySnapshotNotFound(id) => {
write!(f, "History snapshot not found for transaction id={id}")
}
Error::InvalidPageType {
page_region,
page_index,
page_order,
found,
} => {
write!(
f,
"Invalid page type byte {found} on page ({page_region}, {page_index}, order={page_order}), expected LEAF (1) or BRANCH (2)"
)
}
Error::InvalidChildRef {
page_region,
page_index,
page_order,
child_index,
is_checksum,
} => {
let kind = if *is_checksum { "checksum" } else { "pointer" };
write!(
f,
"Invalid child {kind} at index {child_index} on page ({page_region}, {page_index}, order={page_order})"
)
}
Error::InvalidEntryIndex {
page_region,
page_index,
page_order,
entry_index,
} => {
write!(
f,
"Invalid entry index {entry_index} on page ({page_region}, {page_index}, order={page_order})"
)
}
Error::PageCorrupted {
page_region,
page_index,
page_order,
detail,
} => {
write!(
f,
"Page ({page_region}, {page_index}, order={page_order}) corrupted: {detail}"
)
}
Error::Io(err) => {
write!(f, "I/O error: {err}")
}
Error::DatabaseClosed => {
write!(f, "Database has been closed")
}
Error::PreviousIo => {
write!(
f,
"Previous I/O error occurred. Please close and re-open the database."
)
}
Error::LockPoisoned(location) => {
write!(f, "Poisoned internal lock: {location}")
}
Error::DatabaseAlreadyOpen => {
write!(f, "Database already open. Cannot acquire lock.")
}
Error::RepairAborted => {
write!(f, "Database repair aborted.")
}
Error::PersistentSavepointModified => {
write!(
f,
"Persistent savepoint modified. Cannot reduce transaction durability"
)
}
Error::PersistentSavepointExists => {
write!(
f,
"Persistent savepoint exists. Operation cannot be performed."
)
}
Error::EphemeralSavepointExists => {
write!(
f,
"Ephemeral savepoint exists. Operation cannot be performed."
)
}
Error::TransactionInProgress => {
write!(
f,
"A transaction is still in progress. Operation cannot be performed."
)
}
Error::InvalidSavepoint => {
write!(f, "Savepoint is invalid or cannot be created.")
}
Error::ReadTransactionStillInUse(_) => {
write!(f, "Transaction still in use")
}
#[cfg(feature = "std")]
Error::GroupCommitPeerFailed => {
write!(
f,
"Group commit batch rolled back: another batch in the group failed"
)
}
#[cfg(feature = "std")]
Error::GroupCommitShutdown => {
write!(f, "Group commit failed: database is shutting down")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}