// Copyright 2018-2019 Mozilla // // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. use std::{ io, path::PathBuf, str, sync, thread, thread::ThreadId, }; use failure::Fail; pub use crate::backend::SafeModeError; use crate::value::Type; #[derive(Debug, Fail)] pub enum DataError { #[fail(display = "unknown type tag: {}", _0)] UnknownType(u8), #[fail(display = "unexpected type tag: expected {}, got {}", expected, actual)] UnexpectedType { expected: Type, actual: Type, }, #[fail(display = "empty data; expected tag")] Empty, #[fail(display = "invalid value for type {}: {}", value_type, err)] DecodingError { value_type: Type, err: Box, }, #[fail(display = "couldn't encode value: {}", _0)] EncodingError(Box), #[fail(display = "invalid uuid bytes")] InvalidUuid, } impl From> for DataError { fn from(e: Box) -> DataError { DataError::EncodingError(e) } } #[derive(Debug, Fail)] pub enum StoreError { #[fail(display = "manager poisoned")] ManagerPoisonError, #[fail(display = "database corrupted")] DatabaseCorrupted, #[fail(display = "key/value pair not found")] KeyValuePairNotFound, #[fail(display = "unsupported size of key/DB name/data")] KeyValuePairBadSize, #[fail(display = "file is not a valid database")] FileInvalid, #[fail(display = "environment mapsize reached")] MapFull, #[fail(display = "environment maxdbs reached")] DbsFull, #[fail(display = "environment maxreaders reached")] ReadersFull, #[fail(display = "I/O error: {:?}", _0)] IoError(io::Error), #[fail(display = "environment path does not exist or not the right type: {:?}", _0)] UnsuitableEnvironmentPath(PathBuf), #[fail(display = "data error: {:?}", _0)] DataError(DataError), #[fail(display = "lmdb backend error: {}", _0)] LmdbError(lmdb::Error), #[fail(display = "safe mode backend error: {}", _0)] SafeModeError(SafeModeError), #[fail(display = "read transaction already exists in thread {:?}", _0)] ReadTransactionAlreadyExists(ThreadId), #[fail(display = "attempted to open DB during transaction in thread {:?}", _0)] OpenAttemptedDuringTransaction(ThreadId), } impl StoreError { pub fn open_during_transaction() -> StoreError { StoreError::OpenAttemptedDuringTransaction(thread::current().id()) } pub fn read_transaction_already_exists() -> StoreError { StoreError::ReadTransactionAlreadyExists(thread::current().id()) } } impl From for StoreError { fn from(e: DataError) -> StoreError { StoreError::DataError(e) } } impl From for StoreError { fn from(e: io::Error) -> StoreError { StoreError::IoError(e) } } impl From> for StoreError { fn from(_: sync::PoisonError) -> StoreError { StoreError::ManagerPoisonError } } #[derive(Debug, Fail)] pub enum CloseError { #[fail(display = "manager poisoned")] ManagerPoisonError, #[fail(display = "close attempted while manager has an environment still open")] EnvironmentStillOpen, #[fail(display = "close attempted while an environment not known to the manager is still open")] UnknownEnvironmentStillOpen, #[fail(display = "I/O error: {:?}", _0)] IoError(io::Error), } impl From> for CloseError { fn from(_: sync::PoisonError) -> CloseError { CloseError::ManagerPoisonError } } impl From for CloseError { fn from(e: io::Error) -> CloseError { CloseError::IoError(e) } } #[derive(Debug, Fail)] pub enum MigrateError { #[fail(display = "store error: {}", _0)] StoreError(StoreError), #[fail(display = "close error: {}", _0)] CloseError(CloseError), #[fail(display = "manager poisoned")] ManagerPoisonError, #[fail(display = "source is empty")] SourceEmpty, #[fail(display = "destination is not empty")] DestinationNotEmpty, } impl From for MigrateError { fn from(e: StoreError) -> MigrateError { MigrateError::StoreError(e) } } impl From for MigrateError { fn from(e: CloseError) -> MigrateError { MigrateError::CloseError(e) } } impl From> for MigrateError { fn from(_: sync::PoisonError) -> MigrateError { MigrateError::ManagerPoisonError } }