Skip to main content

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