summavy/directory/
error.rs

1use std::path::PathBuf;
2use std::sync::Arc;
3use std::{fmt, io};
4
5use crate::Version;
6
7/// Error while trying to acquire a directory [lock](crate::directory::Lock).
8///
9/// This is returned from [`Directory::acquire_lock`](crate::Directory::acquire_lock).
10#[derive(Debug, Clone, Error)]
11pub enum LockError {
12    /// Failed to acquired a lock as it is already held by another
13    /// client.
14    /// - In the context of a blocking lock, this means the lock was not released within some
15    ///   `timeout` period.
16    /// - In the context of a non-blocking lock, this means the lock was busy at the moment of the
17    ///   call.
18    #[error("Could not acquire lock as it is already held, possibly by a different process.")]
19    LockBusy,
20    /// Trying to acquire a lock failed with an `IoError`
21    #[error("Failed to acquire the lock due to an io:Error.")]
22    IoError(Arc<io::Error>),
23}
24
25impl LockError {
26    /// Wraps an io error.
27    pub fn wrap_io_error(io_error: io::Error) -> Self {
28        Self::IoError(Arc::new(io_error))
29    }
30}
31
32/// Error that may occur when opening a directory
33#[derive(Debug, Clone, Error)]
34pub enum OpenDirectoryError {
35    /// The underlying directory does not exist.
36    #[error("Directory does not exist: '{0}'.")]
37    DoesNotExist(PathBuf),
38    /// The path exists but is not a directory.
39    #[error("Path exists but is not a directory: '{0}'.")]
40    NotADirectory(PathBuf),
41    /// Failed to create a temp directory.
42    #[error("Failed to create a temporary directory: '{0}'.")]
43    FailedToCreateTempDir(Arc<io::Error>),
44    /// IoError
45    #[error("IoError '{io_error:?}' while create directory in: '{directory_path:?}'.")]
46    IoError {
47        /// underlying io Error.
48        io_error: Arc<io::Error>,
49        /// directory we tried to open.
50        directory_path: PathBuf,
51    },
52}
53
54impl OpenDirectoryError {
55    /// Wraps an io error.
56    pub fn wrap_io_error(io_error: io::Error, directory_path: PathBuf) -> Self {
57        Self::IoError {
58            io_error: Arc::new(io_error),
59            directory_path,
60        }
61    }
62}
63
64/// Error that may occur when starting to write in a file
65#[derive(Debug, Clone, Error)]
66pub enum OpenWriteError {
67    /// Our directory is WORM, writing an existing file is forbidden.
68    /// Checkout the `Directory` documentation.
69    #[error("File already exists: '{0}'")]
70    FileAlreadyExists(PathBuf),
71    /// Any kind of IO error that happens when
72    /// writing in the underlying IO device.
73    #[error("IoError '{io_error:?}' while opening file for write: '{filepath}'.")]
74    IoError {
75        /// The underlying `io::Error`.
76        io_error: Arc<io::Error>,
77        /// File path of the file that tantivy failed to open for write.
78        filepath: PathBuf,
79    },
80}
81
82impl OpenWriteError {
83    /// Wraps an io error.
84    pub fn wrap_io_error(io_error: io::Error, filepath: PathBuf) -> Self {
85        Self::IoError {
86            io_error: Arc::new(io_error),
87            filepath,
88        }
89    }
90}
91/// Type of index incompatibility between the library and the index found on disk
92/// Used to catch and provide a hint to solve this incompatibility issue
93#[derive(Clone)]
94pub enum Incompatibility {
95    /// This library cannot decompress the index found on disk
96    CompressionMismatch {
97        /// Compression algorithm used by the current version of tantivy
98        library_compression_format: String,
99        /// Compression algorithm that was used to serialise the index
100        index_compression_format: String,
101    },
102    /// The index format found on disk isn't supported by this version of the library
103    IndexMismatch {
104        /// Version used by the library
105        library_version: Version,
106        /// Version the index was built with
107        index_version: Version,
108    },
109}
110
111impl fmt::Debug for Incompatibility {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
113        match self {
114            Incompatibility::CompressionMismatch {
115                library_compression_format,
116                index_compression_format,
117            } => {
118                let err = format!(
119                    "Library was compiled with {:?} compression, index was compressed with {:?}",
120                    library_compression_format, index_compression_format
121                );
122                let advice = format!(
123                    "Change the feature flag to {:?} and rebuild the library",
124                    index_compression_format
125                );
126                write!(f, "{}. {}", err, advice)?;
127            }
128            Incompatibility::IndexMismatch {
129                library_version,
130                index_version,
131            } => {
132                let err = format!(
133                    "Library version: {}, index version: {}",
134                    library_version.index_format_version, index_version.index_format_version
135                );
136                // TODO make a more useful error message
137                // include the version range that supports this index_format_version
138                let advice = format!(
139                    "Change tantivy to a version compatible with index format {} (e.g. {}.{}.x) \
140                     and rebuild your project.",
141                    index_version.index_format_version, index_version.major, index_version.minor
142                );
143                write!(f, "{}. {}", err, advice)?;
144            }
145        }
146
147        Ok(())
148    }
149}
150
151/// Error that may occur when accessing a file read
152#[derive(Debug, Clone, Error)]
153pub enum OpenReadError {
154    /// The file does not exist.
155    #[error("Files does not exist: {0:?}")]
156    FileDoesNotExist(PathBuf),
157    /// Any kind of io::Error.
158    #[error(
159        "IoError: '{io_error:?}' happened while opening the following file for Read: {filepath}."
160    )]
161    IoError {
162        /// The underlying `io::Error`.
163        io_error: Arc<io::Error>,
164        /// File path of the file that tantivy failed to open for read.
165        filepath: PathBuf,
166    },
167    /// This library does not support the index version found in file footer.
168    #[error("Index version unsupported: {0:?}")]
169    IncompatibleIndex(Incompatibility),
170}
171
172impl OpenReadError {
173    /// Wraps an io error.
174    pub fn wrap_io_error(io_error: io::Error, filepath: PathBuf) -> Self {
175        Self::IoError {
176            io_error: Arc::new(io_error),
177            filepath,
178        }
179    }
180}
181/// Error that may occur when trying to delete a file
182#[derive(Debug, Clone, Error)]
183pub enum DeleteError {
184    /// The file does not exist.
185    #[error("File does not exist: '{0}'.")]
186    FileDoesNotExist(PathBuf),
187    /// Any kind of IO error that happens when
188    /// interacting with the underlying IO device.
189    #[error("The following IO error happened while deleting file '{filepath}': '{io_error:?}'.")]
190    IoError {
191        /// The underlying `io::Error`.
192        io_error: Arc<io::Error>,
193        /// File path of the file that tantivy failed to delete.
194        filepath: PathBuf,
195    },
196}
197
198impl From<Incompatibility> for OpenReadError {
199    fn from(incompatibility: Incompatibility) -> Self {
200        OpenReadError::IncompatibleIndex(incompatibility)
201    }
202}