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;
92pub mod properties;
93mod slice_transform;
94mod snapshot;
95mod sst_file_writer;
96mod transactions;
97mod write_batch;
98
99pub use crate::{
100    column_family::{
101        AsColumnFamilyRef, BoundColumnFamily, ColumnFamily, ColumnFamilyDescriptor,
102        ColumnFamilyRef, DEFAULT_COLUMN_FAMILY_NAME,
103    },
104    compaction_filter::Decision as CompactionDecision,
105    db::{
106        DBAccess, DBCommon, DBWithThreadMode, LiveFile, MultiThreaded, SingleThreaded, ThreadMode,
107        DB,
108    },
109    db_iterator::{
110        DBIterator, DBIteratorWithThreadMode, DBRawIterator, DBRawIteratorWithThreadMode,
111        DBWALIterator, Direction, IteratorMode,
112    },
113    db_options::{
114        BlockBasedIndexType, BlockBasedOptions, BottommostLevelCompaction, Cache, ChecksumType,
115        CompactOptions, CuckooTableOptions, DBCompactionStyle, DBCompressionType, DBPath,
116        DBRecoveryMode, DataBlockIndexType, FifoCompactOptions, FlushOptions,
117        IngestExternalFileOptions, LogLevel, MemtableFactory, Options, PlainTableFactoryOptions,
118        ReadOptions, UniversalCompactOptions, UniversalCompactionStopStyle, WriteOptions,
119    },
120    db_pinnable_slice::DBPinnableSlice,
121    env::Env,
122    ffi_util::CStrLike,
123    iter_range::{IterateBounds, PrefixRange},
124    merge_operator::MergeOperands,
125    perf::{PerfContext, PerfMetric, PerfStatsLevel},
126    slice_transform::SliceTransform,
127    snapshot::{Snapshot, SnapshotWithThreadMode},
128    sst_file_writer::SstFileWriter,
129    transactions::{
130        OptimisticTransactionDB, OptimisticTransactionOptions, Transaction, TransactionDB,
131        TransactionDBOptions, TransactionOptions,
132    },
133    write_batch::{WriteBatch, WriteBatchIterator, WriteBatchWithTransaction},
134};
135
136use librocksdb_sys as ffi;
137
138use std::error;
139use std::fmt;
140
141/// RocksDB error kind.
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub enum ErrorKind {
144    NotFound,
145    Corruption,
146    NotSupported,
147    InvalidArgument,
148    IOError,
149    MergeInProgress,
150    Incomplete,
151    ShutdownInProgress,
152    TimedOut,
153    Aborted,
154    Busy,
155    Expired,
156    TryAgain,
157    CompactionTooLarge,
158    ColumnFamilyDropped,
159    Unknown,
160}
161
162/// A simple wrapper round a string, used for errors reported from
163/// ffi calls.
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct Error {
166    message: String,
167}
168
169impl Error {
170    fn new(message: String) -> Error {
171        Error { message }
172    }
173
174    pub fn into_string(self) -> String {
175        self.into()
176    }
177
178    /// Parse corresponding [`ErrorKind`] from error message.
179    pub fn kind(&self) -> ErrorKind {
180        match self.message.split(':').next().unwrap_or("") {
181            "NotFound" => ErrorKind::NotFound,
182            "Corruption" => ErrorKind::Corruption,
183            "Not implemented" => ErrorKind::NotSupported,
184            "Invalid argument" => ErrorKind::InvalidArgument,
185            "IO error" => ErrorKind::IOError,
186            "Merge in progress" => ErrorKind::MergeInProgress,
187            "Result incomplete" => ErrorKind::Incomplete,
188            "Shutdown in progress" => ErrorKind::ShutdownInProgress,
189            "Operation timed out" => ErrorKind::TimedOut,
190            "Operation aborted" => ErrorKind::Aborted,
191            "Resource busy" => ErrorKind::Busy,
192            "Operation expired" => ErrorKind::Expired,
193            "Operation failed. Try again." => ErrorKind::TryAgain,
194            "Compaction too large" => ErrorKind::CompactionTooLarge,
195            "Column family dropped" => ErrorKind::ColumnFamilyDropped,
196            _ => ErrorKind::Unknown,
197        }
198    }
199}
200
201impl AsRef<str> for Error {
202    fn as_ref(&self) -> &str {
203        &self.message
204    }
205}
206
207impl From<Error> for String {
208    fn from(e: Error) -> String {
209        e.message
210    }
211}
212
213impl error::Error for Error {
214    fn description(&self) -> &str {
215        &self.message
216    }
217}
218
219impl fmt::Display for Error {
220    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
221        self.message.fmt(formatter)
222    }
223}
224
225#[cfg(test)]
226mod test {
227    use crate::{
228        OptimisticTransactionDB, OptimisticTransactionOptions, Transaction, TransactionDB,
229        TransactionDBOptions, TransactionOptions,
230    };
231
232    use super::{
233        column_family::UnboundColumnFamily,
234        db_options::CacheWrapper,
235        env::{Env, EnvWrapper},
236        BlockBasedOptions, BoundColumnFamily, Cache, ColumnFamily, ColumnFamilyDescriptor,
237        DBIterator, DBRawIterator, IngestExternalFileOptions, Options, PlainTableFactoryOptions,
238        ReadOptions, Snapshot, SstFileWriter, WriteBatch, WriteOptions, DB,
239    };
240
241    #[test]
242    fn is_send() {
243        // test (at compile time) that certain types implement the auto-trait Send, either directly for
244        // pointer-wrapping types or transitively for types with all Send fields
245
246        fn is_send<T: Send>() {
247            // dummy function just used for its parameterized type bound
248        }
249
250        is_send::<DB>();
251        is_send::<DBIterator<'_>>();
252        is_send::<DBRawIterator<'_>>();
253        is_send::<Snapshot>();
254        is_send::<Options>();
255        is_send::<ReadOptions>();
256        is_send::<WriteOptions>();
257        is_send::<IngestExternalFileOptions>();
258        is_send::<BlockBasedOptions>();
259        is_send::<PlainTableFactoryOptions>();
260        is_send::<ColumnFamilyDescriptor>();
261        is_send::<ColumnFamily>();
262        is_send::<BoundColumnFamily<'_>>();
263        is_send::<UnboundColumnFamily>();
264        is_send::<SstFileWriter>();
265        is_send::<WriteBatch>();
266        is_send::<Cache>();
267        is_send::<CacheWrapper>();
268        is_send::<Env>();
269        is_send::<EnvWrapper>();
270        is_send::<TransactionDB>();
271        is_send::<OptimisticTransactionDB>();
272        is_send::<Transaction<'_, TransactionDB>>();
273        is_send::<TransactionDBOptions>();
274        is_send::<OptimisticTransactionOptions>();
275        is_send::<TransactionOptions>();
276    }
277
278    #[test]
279    fn is_sync() {
280        // test (at compile time) that certain types implement the auto-trait Sync
281
282        fn is_sync<T: Sync>() {
283            // dummy function just used for its parameterized type bound
284        }
285
286        is_sync::<DB>();
287        is_sync::<Snapshot>();
288        is_sync::<Options>();
289        is_sync::<ReadOptions>();
290        is_sync::<WriteOptions>();
291        is_sync::<IngestExternalFileOptions>();
292        is_sync::<BlockBasedOptions>();
293        is_sync::<PlainTableFactoryOptions>();
294        is_sync::<UnboundColumnFamily>();
295        is_sync::<ColumnFamilyDescriptor>();
296        is_sync::<SstFileWriter>();
297        is_sync::<Cache>();
298        is_sync::<CacheWrapper>();
299        is_sync::<Env>();
300        is_sync::<EnvWrapper>();
301        is_sync::<TransactionDB>();
302        is_sync::<OptimisticTransactionDB>();
303        is_sync::<TransactionDBOptions>();
304        is_sync::<OptimisticTransactionOptions>();
305        is_sync::<TransactionOptions>();
306    }
307}