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