bijou_rocksdb/
lib.rs

1// Copyright 2020 Tyler Neely
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16//! Rust wrapper for RocksDB.
17//!
18//! # Examples
19//!
20//! ```
21//! use rocksdb::{DB, Options};
22//! // NB: db is automatically closed at end of lifetime
23//! let path = "_path_for_rocksdb_storage";
24//! {
25//!    let db = DB::open_default(path).unwrap();
26//!    db.put(b"my key", b"my value").unwrap();
27//!    match db.get(b"my key") {
28//!        Ok(Some(value)) => println!("retrieved value {}", String::from_utf8(value).unwrap()),
29//!        Ok(None) => println!("value not found"),
30//!        Err(e) => println!("operational problem encountered: {}", e),
31//!    }
32//!    db.delete(b"my key").unwrap();
33//! }
34//! let _ = DB::destroy(&Options::default(), path);
35//! ```
36//!
37//! Opening a database and a single column family with custom options:
38//!
39//! ```
40//! use rocksdb::{DB, ColumnFamilyDescriptor, Options};
41//!
42//! let path = "_path_for_rocksdb_storage_with_cfs";
43//! let mut cf_opts = Options::default();
44//! cf_opts.set_max_write_buffer_number(16);
45//! let cf = ColumnFamilyDescriptor::new("cf1", cf_opts);
46//!
47//! let mut db_opts = Options::default();
48//! db_opts.create_missing_column_families(true);
49//! db_opts.create_if_missing(true);
50//! {
51//!     let db = DB::open_cf_descriptors(&db_opts, path, vec![cf]).unwrap();
52//! }
53//! let _ = DB::destroy(&db_opts, path);
54//! ```
55//!
56
57#![warn(clippy::pedantic)]
58#![allow(
59    // Next `cast_*` lints don't give alternatives.
60    clippy::cast_possible_wrap, clippy::cast_possible_truncation, clippy::cast_sign_loss,
61    // Next lints produce too much noise/false positives.
62    clippy::module_name_repetitions, clippy::similar_names, clippy::must_use_candidate,
63    // '... may panic' lints.
64    // Too much work to fix.
65    clippy::missing_errors_doc,
66    // False positive: WebSocket
67    clippy::doc_markdown,
68    clippy::missing_safety_doc,
69    clippy::needless_pass_by_value,
70    clippy::ptr_as_ptr,
71    clippy::missing_panics_doc,
72    clippy::from_over_into,
73)]
74
75#[macro_use]
76mod ffi_util;
77
78pub mod backup;
79pub mod checkpoint;
80mod column_family;
81pub mod compaction_filter;
82pub mod compaction_filter_factory;
83mod comparator;
84mod db;
85mod db_iterator;
86mod db_options;
87mod db_pinnable_slice;
88mod env;
89mod iter_range;
90pub mod merge_operator;
91pub mod perf;
92mod prop_name;
93pub mod properties;
94mod slice_transform;
95mod snapshot;
96mod sst_file_writer;
97mod transactions;
98mod write_batch;
99
100pub use crate::{
101    column_family::{
102        AsColumnFamilyRef, BoundColumnFamily, ColumnFamily, ColumnFamilyDescriptor,
103        ColumnFamilyRef, DEFAULT_COLUMN_FAMILY_NAME,
104    },
105    compaction_filter::Decision as CompactionDecision,
106    db::{
107        DBAccess, DBCommon, DBWithThreadMode, LiveFile, MultiThreaded, SingleThreaded, ThreadMode,
108        DB,
109    },
110    db_iterator::{
111        DBIterator, DBIteratorWithThreadMode, DBRawIterator, DBRawIteratorWithThreadMode,
112        DBWALIterator, Direction, IteratorMode,
113    },
114    db_options::{
115        BlockBasedIndexType, BlockBasedOptions, BottommostLevelCompaction, Cache, ChecksumType,
116        CompactOptions, CuckooTableOptions, DBCompactionStyle, DBCompressionType, DBPath,
117        DBRecoveryMode, DataBlockIndexType, FifoCompactOptions, FlushOptions,
118        IngestExternalFileOptions, LogLevel, MemtableFactory, Options, PlainTableFactoryOptions,
119        ReadOptions, UniversalCompactOptions, UniversalCompactionStopStyle, WriteOptions,
120    },
121    db_pinnable_slice::DBPinnableSlice,
122    env::{CustomCipher, Env},
123    ffi_util::CStrLike,
124    iter_range::{IterateBounds, PrefixRange},
125    merge_operator::MergeOperands,
126    perf::{PerfContext, PerfMetric, PerfStatsLevel},
127    slice_transform::SliceTransform,
128    snapshot::{Snapshot, SnapshotWithThreadMode},
129    sst_file_writer::SstFileWriter,
130    transactions::{
131        OptimisticTransactionDB, OptimisticTransactionOptions, Transaction, TransactionDB,
132        TransactionDBOptions, TransactionOptions,
133    },
134    write_batch::{WriteBatch, WriteBatchIterator, WriteBatchWithTransaction},
135};
136
137use bijou_librocksdb_sys as ffi;
138
139use std::error;
140use std::fmt;
141
142/// RocksDB error kind.
143#[derive(Debug, Clone, PartialEq, Eq)]
144pub enum ErrorKind {
145    NotFound,
146    Corruption,
147    NotSupported,
148    InvalidArgument,
149    IOError,
150    MergeInProgress,
151    Incomplete,
152    ShutdownInProgress,
153    TimedOut,
154    Aborted,
155    Busy,
156    Expired,
157    TryAgain,
158    CompactionTooLarge,
159    ColumnFamilyDropped,
160    Unknown,
161}
162
163/// A simple wrapper round a string, used for errors reported from
164/// ffi calls.
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub struct Error {
167    message: String,
168}
169
170impl Error {
171    fn new(message: String) -> Error {
172        Error { message }
173    }
174
175    pub fn into_string(self) -> String {
176        self.into()
177    }
178
179    /// Parse corresponding [`ErrorKind`] from error message.
180    pub fn kind(&self) -> ErrorKind {
181        match self.message.split(':').next().unwrap_or("") {
182            "NotFound" => ErrorKind::NotFound,
183            "Corruption" => ErrorKind::Corruption,
184            "Not implemented" => ErrorKind::NotSupported,
185            "Invalid argument" => ErrorKind::InvalidArgument,
186            "IO error" => ErrorKind::IOError,
187            "Merge in progress" => ErrorKind::MergeInProgress,
188            "Result incomplete" => ErrorKind::Incomplete,
189            "Shutdown in progress" => ErrorKind::ShutdownInProgress,
190            "Operation timed out" => ErrorKind::TimedOut,
191            "Operation aborted" => ErrorKind::Aborted,
192            "Resource busy" => ErrorKind::Busy,
193            "Operation expired" => ErrorKind::Expired,
194            "Operation failed. Try again." => ErrorKind::TryAgain,
195            "Compaction too large" => ErrorKind::CompactionTooLarge,
196            "Column family dropped" => ErrorKind::ColumnFamilyDropped,
197            _ => ErrorKind::Unknown,
198        }
199    }
200}
201
202impl AsRef<str> for Error {
203    fn as_ref(&self) -> &str {
204        &self.message
205    }
206}
207
208impl From<Error> for String {
209    fn from(e: Error) -> String {
210        e.message
211    }
212}
213
214impl error::Error for Error {
215    fn description(&self) -> &str {
216        &self.message
217    }
218}
219
220impl fmt::Display for Error {
221    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
222        self.message.fmt(formatter)
223    }
224}
225
226#[cfg(test)]
227mod test {
228    use crate::{
229        OptimisticTransactionDB, OptimisticTransactionOptions, Transaction, TransactionDB,
230        TransactionDBOptions, TransactionOptions,
231    };
232
233    use super::{
234        column_family::UnboundColumnFamily,
235        db_options::CacheWrapper,
236        env::{Env, EnvWrapper},
237        BlockBasedOptions, BoundColumnFamily, Cache, ColumnFamily, ColumnFamilyDescriptor,
238        DBIterator, DBRawIterator, IngestExternalFileOptions, Options, PlainTableFactoryOptions,
239        ReadOptions, Snapshot, SstFileWriter, WriteBatch, WriteOptions, DB,
240    };
241
242    #[test]
243    fn is_send() {
244        // test (at compile time) that certain types implement the auto-trait Send, either directly for
245        // pointer-wrapping types or transitively for types with all Send fields
246
247        fn is_send<T: Send>() {
248            // dummy function just used for its parameterized type bound
249        }
250
251        is_send::<DB>();
252        is_send::<DBIterator<'_>>();
253        is_send::<DBRawIterator<'_>>();
254        is_send::<Snapshot>();
255        is_send::<Options>();
256        is_send::<ReadOptions>();
257        is_send::<WriteOptions>();
258        is_send::<IngestExternalFileOptions>();
259        is_send::<BlockBasedOptions>();
260        is_send::<PlainTableFactoryOptions>();
261        is_send::<ColumnFamilyDescriptor>();
262        is_send::<ColumnFamily>();
263        is_send::<BoundColumnFamily<'_>>();
264        is_send::<UnboundColumnFamily>();
265        is_send::<SstFileWriter>();
266        is_send::<WriteBatch>();
267        is_send::<Cache>();
268        is_send::<CacheWrapper>();
269        is_send::<Env>();
270        is_send::<EnvWrapper>();
271        is_send::<TransactionDB>();
272        is_send::<OptimisticTransactionDB>();
273        is_send::<Transaction<'_, TransactionDB>>();
274        is_send::<TransactionDBOptions>();
275        is_send::<OptimisticTransactionOptions>();
276        is_send::<TransactionOptions>();
277    }
278
279    #[test]
280    fn is_sync() {
281        // test (at compile time) that certain types implement the auto-trait Sync
282
283        fn is_sync<T: Sync>() {
284            // dummy function just used for its parameterized type bound
285        }
286
287        is_sync::<DB>();
288        is_sync::<Snapshot>();
289        is_sync::<Options>();
290        is_sync::<ReadOptions>();
291        is_sync::<WriteOptions>();
292        is_sync::<IngestExternalFileOptions>();
293        is_sync::<BlockBasedOptions>();
294        is_sync::<PlainTableFactoryOptions>();
295        is_sync::<UnboundColumnFamily>();
296        is_sync::<ColumnFamilyDescriptor>();
297        is_sync::<SstFileWriter>();
298        is_sync::<Cache>();
299        is_sync::<CacheWrapper>();
300        is_sync::<Env>();
301        is_sync::<EnvWrapper>();
302        is_sync::<TransactionDB>();
303        is_sync::<OptimisticTransactionDB>();
304        is_sync::<TransactionDBOptions>();
305        is_sync::<OptimisticTransactionOptions>();
306        is_sync::<TransactionOptions>();
307    }
308}