From 7eb267341e7792d4442332ce937a2f6ec39a0e70 Mon Sep 17 00:00:00 2001 From: Pascal Seitz Date: Wed, 29 Jun 2022 22:52:50 +0800 Subject: [PATCH] make errors cloneable --- src/directory/directory.rs | 10 +++++-- src/directory/error.rs | 43 ++++++++++++++++++++---------- src/directory/managed_directory.rs | 9 +++---- src/directory/mmap_directory.rs | 9 ++++--- src/directory/ram_directory.rs | 6 ++--- src/error.rs | 14 +++++++--- 6 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/directory/directory.rs b/src/directory/directory.rs index e54b8dee32..7c7f81f660 100644 --- a/src/directory/directory.rs +++ b/src/directory/directory.rs @@ -1,6 +1,7 @@ use std::io::Write; use std::marker::{Send, Sync}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use std::time::Duration; use std::{fmt, io, thread}; @@ -62,7 +63,12 @@ impl Drop for DirectoryLockGuard { enum TryAcquireLockError { FileExists, - IoError(io::Error), + IoError(Arc), +} +impl From for TryAcquireLockError { + fn from(io_error: io::Error) -> Self { + Self::IoError(Arc::new(io_error)) + } } fn try_acquire_lock( @@ -73,7 +79,7 @@ fn try_acquire_lock( OpenWriteError::FileAlreadyExists(_) => TryAcquireLockError::FileExists, OpenWriteError::IoError { io_error, .. } => TryAcquireLockError::IoError(io_error), })?; - write.flush().map_err(TryAcquireLockError::IoError)?; + write.flush().map_err(TryAcquireLockError::from)?; Ok(DirectoryLock::from(Box::new(DirectoryLockGuard { directory: directory.box_clone(), path: filepath.to_owned(), diff --git a/src/directory/error.rs b/src/directory/error.rs index 4bb273ce02..5292bcf3fb 100644 --- a/src/directory/error.rs +++ b/src/directory/error.rs @@ -1,10 +1,11 @@ use std::path::PathBuf; +use std::sync::Arc; use std::{fmt, io}; use crate::Version; /// Error while trying to acquire a directory lock. -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum LockError { /// Failed to acquired a lock as it is already held by another /// client. @@ -16,11 +17,18 @@ pub enum LockError { LockBusy, /// Trying to acquire a lock failed with an `IoError` #[error("Failed to acquire the lock due to an io:Error.")] - IoError(io::Error), + IoError(Arc), +} + +impl LockError { + /// Wraps an io error. + pub fn wrap_io_error(io_error: io::Error) -> Self { + Self::IoError(Arc::new(io_error)) + } } /// Error that may occur when opening a directory -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum OpenDirectoryError { /// The underlying directory does not exists. #[error("Directory does not exist: '{0}'.")] @@ -30,12 +38,12 @@ pub enum OpenDirectoryError { NotADirectory(PathBuf), /// Failed to create a temp directory. #[error("Failed to create a temporary directory: '{0}'.")] - FailedToCreateTempDir(io::Error), + FailedToCreateTempDir(Arc), /// IoError #[error("IoError '{io_error:?}' while create directory in: '{directory_path:?}'.")] IoError { /// underlying io Error. - io_error: io::Error, + io_error: Arc, /// directory we tried to open. directory_path: PathBuf, }, @@ -45,14 +53,14 @@ impl OpenDirectoryError { /// Wraps an io error. pub fn wrap_io_error(io_error: io::Error, directory_path: PathBuf) -> Self { Self::IoError { - io_error, + io_error: Arc::new(io_error), directory_path, } } } /// Error that may occur when starting to write in a file -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum OpenWriteError { /// Our directory is WORM, writing an existing file is forbidden. /// Checkout the `Directory` documentation. @@ -63,7 +71,7 @@ pub enum OpenWriteError { #[error("IoError '{io_error:?}' while opening file for write: '{filepath}'.")] IoError { /// The underlying `io::Error`. - io_error: io::Error, + io_error: Arc, /// File path of the file that tantivy failed to open for write. filepath: PathBuf, }, @@ -72,11 +80,15 @@ pub enum OpenWriteError { impl OpenWriteError { /// Wraps an io error. pub fn wrap_io_error(io_error: io::Error, filepath: PathBuf) -> Self { - Self::IoError { io_error, filepath } + Self::IoError { + io_error: Arc::new(io_error), + filepath, + } } } /// Type of index incompatibility between the library and the index found on disk /// Used to catch and provide a hint to solve this incompatibility issue +#[derive(Clone)] pub enum Incompatibility { /// This library cannot decompress the index found on disk CompressionMismatch { @@ -135,7 +147,7 @@ impl fmt::Debug for Incompatibility { } /// Error that may occur when accessing a file read -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum OpenReadError { /// The file does not exists. #[error("Files does not exists: {0:?}")] @@ -146,7 +158,7 @@ pub enum OpenReadError { )] IoError { /// The underlying `io::Error`. - io_error: io::Error, + io_error: Arc, /// File path of the file that tantivy failed to open for read. filepath: PathBuf, }, @@ -158,11 +170,14 @@ pub enum OpenReadError { impl OpenReadError { /// Wraps an io error. pub fn wrap_io_error(io_error: io::Error, filepath: PathBuf) -> Self { - Self::IoError { io_error, filepath } + Self::IoError { + io_error: Arc::new(io_error), + filepath, + } } } /// Error that may occur when trying to delete a file -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum DeleteError { /// The file does not exists. #[error("File does not exists: '{0}'.")] @@ -172,7 +187,7 @@ pub enum DeleteError { #[error("The following IO error happened while deleting file '{filepath}': '{io_error:?}'.")] IoError { /// The underlying `io::Error`. - io_error: io::Error, + io_error: Arc, /// File path of the file that tantivy failed to delete. filepath: PathBuf, }, diff --git a/src/directory/managed_directory.rs b/src/directory/managed_directory.rs index b153355677..1b7c23a050 100644 --- a/src/directory/managed_directory.rs +++ b/src/directory/managed_directory.rs @@ -242,16 +242,13 @@ impl ManagedDirectory { /// Verify checksum of a managed file pub fn validate_checksum(&self, path: &Path) -> result::Result { let reader = self.directory.open_read(path)?; - let (footer, data) = - Footer::extract_footer(reader).map_err(|io_error| OpenReadError::IoError { - io_error, - filepath: path.to_path_buf(), - })?; + let (footer, data) = Footer::extract_footer(reader) + .map_err(|io_error| OpenReadError::wrap_io_error(io_error, path.to_path_buf()))?; let bytes = data .read_bytes() .map_err(|io_error| OpenReadError::IoError { + io_error: Arc::new(io_error), filepath: path.to_path_buf(), - io_error, })?; let mut hasher = Hasher::new(); hasher.update(bytes.as_slice()); diff --git a/src/directory/mmap_directory.rs b/src/directory/mmap_directory.rs index b17c3625fa..1c7e1bc0a9 100644 --- a/src/directory/mmap_directory.rs +++ b/src/directory/mmap_directory.rs @@ -174,7 +174,8 @@ impl MmapDirectory { /// This is mostly useful to test the MmapDirectory itself. /// For your unit tests, prefer the RamDirectory. pub fn create_from_tempdir() -> Result { - let tempdir = TempDir::new().map_err(OpenDirectoryError::FailedToCreateTempDir)?; + let tempdir = TempDir::new() + .map_err(|io_err| OpenDirectoryError::FailedToCreateTempDir(Arc::new(io_err)))?; Ok(MmapDirectory::new( tempdir.path().to_path_buf(), Some(tempdir), @@ -342,7 +343,7 @@ impl Directory for MmapDirectory { DeleteError::FileDoesNotExist(path.to_owned()) } else { DeleteError::IoError { - io_error: e, + io_error: Arc::new(e), filepath: path.to_path_buf(), } } @@ -422,9 +423,9 @@ impl Directory for MmapDirectory { .write(true) .create(true) //< if the file does not exist yet, create it. .open(&full_path) - .map_err(LockError::IoError)?; + .map_err(LockError::wrap_io_error)?; if lock.is_blocking { - file.lock_exclusive().map_err(LockError::IoError)?; + file.lock_exclusive().map_err(LockError::wrap_io_error)?; } else { file.try_lock_exclusive().map_err(|_| LockError::LockBusy)? } diff --git a/src/directory/ram_directory.rs b/src/directory/ram_directory.rs index f501b100d2..bb9c32050c 100644 --- a/src/directory/ram_directory.rs +++ b/src/directory/ram_directory.rs @@ -172,7 +172,7 @@ impl Directory for RamDirectory { fn delete(&self, path: &Path) -> result::Result<(), DeleteError> { fail_point!("RamDirectory::delete", |_| { Err(DeleteError::IoError { - io_error: io::Error::from(io::ErrorKind::Other), + io_error: Arc::new(io::Error::from(io::ErrorKind::Other)), filepath: path.to_path_buf(), }) }); @@ -184,7 +184,7 @@ impl Directory for RamDirectory { .fs .read() .map_err(|e| OpenReadError::IoError { - io_error: io::Error::new(io::ErrorKind::Other, e.to_string()), + io_error: Arc::new(io::Error::new(io::ErrorKind::Other, e.to_string())), filepath: path.to_path_buf(), })? .exists(path)) @@ -208,7 +208,7 @@ impl Directory for RamDirectory { self.open_read(path)? .read_bytes() .map_err(|io_error| OpenReadError::IoError { - io_error, + io_error: Arc::new(io_error), filepath: path.to_path_buf(), })?; Ok(bytes.as_slice().to_owned()) diff --git a/src/error.rs b/src/error.rs index baccb32580..e8136cdefa 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,7 @@ //! Definition of Tantivy's errors and results. use std::path::PathBuf; -use std::sync::PoisonError; +use std::sync::{Arc, PoisonError}; use std::{fmt, io}; use thiserror::Error; @@ -15,6 +15,7 @@ use crate::{query, schema}; /// Represents a `DataCorruption` error. /// /// When facing data corruption, tantivy actually panics or returns this error. +#[derive(Clone)] pub struct DataCorruption { filepath: Option, comment: String, @@ -50,7 +51,7 @@ impl fmt::Debug for DataCorruption { } /// The library's error enum -#[derive(Debug, Error)] +#[derive(Debug, Clone, Error)] pub enum TantivyError { /// Failed to open the directory. #[error("Failed to open the directory: '{0:?}'")] @@ -69,7 +70,7 @@ pub enum TantivyError { LockFailure(LockError, Option), /// IO Error. #[error("An IO error occurred: '{0}'")] - IoError(#[from] io::Error), + IoError(Arc), /// Data corruption. #[error("Data corrupted: '{0:?}'")] DataCorruption(DataCorruption), @@ -125,6 +126,11 @@ impl From for TantivyError { } } +impl From for TantivyError { + fn from(io_err: io::Error) -> TantivyError { + TantivyError::IoError(Arc::new(io_err)) + } +} impl From for TantivyError { fn from(data_corruption: DataCorruption) -> TantivyError { TantivyError::DataCorruption(data_corruption) @@ -179,7 +185,7 @@ impl From for TantivyError { impl From for TantivyError { fn from(error: serde_json::Error) -> TantivyError { - TantivyError::IoError(error.into()) + TantivyError::IoError(Arc::new(error.into())) } }