Skip to main content

rust_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 rust_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 rust_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    clippy::should_panic_without_expect,
75    // False positive: WebSocket
76    clippy::doc_markdown,
77    clippy::missing_safety_doc,
78    clippy::needless_pass_by_value,
79    clippy::ptr_as_ptr,
80    clippy::missing_panics_doc,
81    clippy::from_over_into,
82)]
83
84#[macro_use]
85mod ffi_util;
86
87pub mod backup;
88mod cache;
89pub mod checkpoint;
90mod column_family;
91pub mod compaction_filter;
92pub mod compaction_filter_factory;
93mod comparator;
94mod db;
95mod db_iterator;
96mod db_options;
97mod db_pinnable_slice;
98mod env;
99pub mod event_listener;
100mod iter_range;
101pub mod merge_operator;
102pub mod perf;
103mod prop_name;
104pub mod properties;
105mod slice_transform;
106mod snapshot;
107pub mod sst_file_manager;
108mod sst_file_writer;
109pub mod statistics;
110mod transactions;
111mod write_batch;
112mod write_batch_with_index;
113mod write_buffer_manager;
114
115pub use crate::{
116    cache::Cache,
117    column_family::{
118        AsColumnFamilyRef, BoundColumnFamily, ColumnFamily, ColumnFamilyDescriptor,
119        ColumnFamilyRef, ColumnFamilyTtl, DEFAULT_COLUMN_FAMILY_NAME,
120    },
121    compaction_filter::Decision as CompactionDecision,
122    db::{
123        ColumnFamilyMetaData, DB, DBAccess, DBCommon, DBWithThreadMode, ExportImportFilesMetaData,
124        GetIntoBufferResult, LiveFile, MultiThreaded, PrefixProber, Range, SingleThreaded,
125        ThreadMode,
126    },
127    db_iterator::{
128        DBIterator, DBIteratorWithThreadMode, DBRawIterator, DBRawIteratorWithThreadMode,
129        DBWALIterator, Direction, IteratorMode,
130    },
131    db_options::{
132        BlockBasedIndexType, BlockBasedOptions, BlockBasedPinningTier, BottommostLevelCompaction,
133        ChecksumType, CompactOptions, CuckooTableOptions, DBCompactionPri, DBCompactionStyle,
134        DBCompressionType, DBPath, DBRecoveryMode, DataBlockIndexType, FifoCompactOptions,
135        FlushOptions, ImportColumnFamilyOptions, IndexBlockSearchType, InfoLogger,
136        IngestExternalFileOptions, KeyEncodingType, LogLevel, LruCacheOptions, MemtableFactory,
137        Options, PlainTableFactoryOptions, RateLimiterMode, ReadOptions, ReadTier,
138        UniversalCompactOptions, UniversalCompactionStopStyle, WaitForCompactOptions, WriteOptions,
139    },
140    db_pinnable_slice::DBPinnableSlice,
141    env::Env,
142    ffi_util::{CSlice, CStrLike},
143    iter_range::{IterateBounds, PrefixRange},
144    merge_operator::MergeOperands,
145    perf::{PerfContext, PerfMetric, PerfStatsLevel},
146    slice_transform::SliceTransform,
147    snapshot::{Snapshot, SnapshotWithThreadMode},
148    sst_file_manager::SstFileManager,
149    sst_file_writer::SstFileWriter,
150    transactions::{
151        OptimisticTransactionDB, OptimisticTransactionOptions, Transaction, TransactionDB,
152        TransactionDBOptions, TransactionOptions,
153    },
154    write_batch::{
155        WriteBatch, WriteBatchIterator, WriteBatchIteratorCf, WriteBatchWithTransaction,
156    },
157    write_batch_with_index::WriteBatchWithIndex,
158    write_buffer_manager::WriteBufferManager,
159};
160
161use rust_librocksdb_sys as ffi;
162
163/// Returns `true` if this crate was built with the `coroutines` feature, in
164/// which case librocksdb was compiled with `USE_COROUTINES` and linked
165/// against folly.
166///
167/// When `true`, calling [`ReadOptions::set_async_io(true)`][async-io] on a
168/// `MultiGet` activates the multi-level parallel-read path described in the
169/// RocksDB [Asynchronous IO blog post]. When `false`, `MultiGet` with
170/// `async_io=true` can only parallelize reads within a single LSM level.
171///
172/// Note: this reflects how this crate was configured, not what is in the
173/// linked `librocksdb`. If you used `ROCKSDB_LIB_DIR` to link against an
174/// externally-built `librocksdb.a`, the answer here may not match what that
175/// library was actually compiled with.
176///
177/// [async-io]: ReadOptions::set_async_io
178/// [Asynchronous IO blog post]: https://rocksdb.org/blog/2022/10/07/asynchronous-io-in-rocksdb.html
179#[must_use]
180pub fn built_with_coroutines() -> bool {
181    cfg!(feature = "coroutines")
182}
183
184#[cfg(feature = "raw-ptr")]
185mod raw_ptr;
186
187#[cfg(feature = "raw-ptr")]
188pub use crate::raw_ptr::AsRawPtr;
189
190use std::error;
191use std::fmt;
192
193/// RocksDB error kind.
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub enum ErrorKind {
196    NotFound,
197    Corruption,
198    NotSupported,
199    InvalidArgument,
200    IOError,
201    MergeInProgress,
202    Incomplete,
203    ShutdownInProgress,
204    TimedOut,
205    Aborted,
206    Busy,
207    Expired,
208    TryAgain,
209    CompactionTooLarge,
210    ColumnFamilyDropped,
211    Unknown,
212}
213
214/// A simple wrapper round a string, used for errors reported from
215/// ffi calls.
216#[derive(Debug, Clone, PartialEq, Eq)]
217pub struct Error {
218    message: String,
219}
220
221impl Error {
222    fn new(message: String) -> Error {
223        Error { message }
224    }
225
226    pub fn into_string(self) -> String {
227        self.into()
228    }
229
230    /// Parse corresponding [`ErrorKind`] from error message.
231    pub fn kind(&self) -> ErrorKind {
232        match self.message.split(':').next().unwrap_or("") {
233            "NotFound" => ErrorKind::NotFound,
234            "Corruption" => ErrorKind::Corruption,
235            "Not implemented" => ErrorKind::NotSupported,
236            "Invalid argument" => ErrorKind::InvalidArgument,
237            "IO error" => ErrorKind::IOError,
238            "Merge in progress" => ErrorKind::MergeInProgress,
239            "Result incomplete" => ErrorKind::Incomplete,
240            "Shutdown in progress" => ErrorKind::ShutdownInProgress,
241            "Operation timed out" => ErrorKind::TimedOut,
242            "Operation aborted" => ErrorKind::Aborted,
243            "Resource busy" => ErrorKind::Busy,
244            "Operation expired" => ErrorKind::Expired,
245            "Operation failed. Try again." => ErrorKind::TryAgain,
246            "Compaction too large" => ErrorKind::CompactionTooLarge,
247            "Column family dropped" => ErrorKind::ColumnFamilyDropped,
248            _ => ErrorKind::Unknown,
249        }
250    }
251}
252
253impl AsRef<str> for Error {
254    fn as_ref(&self) -> &str {
255        &self.message
256    }
257}
258
259impl From<Error> for String {
260    fn from(e: Error) -> String {
261        e.message
262    }
263}
264
265impl error::Error for Error {
266    fn description(&self) -> &str {
267        &self.message
268    }
269}
270
271impl fmt::Display for Error {
272    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
273        self.message.fmt(formatter)
274    }
275}
276
277#[cfg(test)]
278mod test {
279    use crate::{
280        OptimisticTransactionDB, OptimisticTransactionOptions, Transaction, TransactionDB,
281        TransactionDBOptions, TransactionOptions,
282        cache::{Cache, CacheWrapper},
283        write_buffer_manager::{WriteBufferManager, WriteBufferManagerWrapper},
284    };
285
286    use super::{
287        BlockBasedOptions, BoundColumnFamily, ColumnFamily, ColumnFamilyDescriptor, DB, DBIterator,
288        DBRawIterator, IngestExternalFileOptions, Options, PlainTableFactoryOptions, ReadOptions,
289        Snapshot, SstFileWriter, WriteBatch, WriteOptions,
290        column_family::UnboundColumnFamily,
291        env::{Env, EnvWrapper},
292    };
293
294    #[test]
295    fn is_send() {
296        // test (at compile time) that certain types implement the auto-trait Send, either directly for
297        // pointer-wrapping types or transitively for types with all Send fields
298
299        fn is_send<T: Send>() {
300            // dummy function just used for its parameterized type bound
301        }
302
303        is_send::<DB>();
304        is_send::<DBIterator<'_>>();
305        is_send::<DBRawIterator<'_>>();
306        is_send::<Snapshot>();
307        is_send::<Options>();
308        is_send::<ReadOptions>();
309        is_send::<WriteOptions>();
310        is_send::<IngestExternalFileOptions>();
311        is_send::<BlockBasedOptions>();
312        is_send::<PlainTableFactoryOptions>();
313        is_send::<ColumnFamilyDescriptor>();
314        is_send::<ColumnFamily>();
315        is_send::<BoundColumnFamily<'_>>();
316        is_send::<UnboundColumnFamily>();
317        is_send::<SstFileWriter>();
318        is_send::<WriteBatch>();
319        is_send::<Cache>();
320        is_send::<CacheWrapper>();
321        is_send::<Env>();
322        is_send::<EnvWrapper>();
323        is_send::<TransactionDB>();
324        is_send::<OptimisticTransactionDB>();
325        is_send::<Transaction<'_, TransactionDB>>();
326        is_send::<TransactionDBOptions>();
327        is_send::<OptimisticTransactionOptions>();
328        is_send::<TransactionOptions>();
329        is_send::<WriteBufferManager>();
330        is_send::<WriteBufferManagerWrapper>();
331    }
332
333    #[test]
334    fn is_sync() {
335        // test (at compile time) that certain types implement the auto-trait Sync
336
337        fn is_sync<T: Sync>() {
338            // dummy function just used for its parameterized type bound
339        }
340
341        is_sync::<DB>();
342        is_sync::<Snapshot>();
343        is_sync::<Options>();
344        is_sync::<ReadOptions>();
345        is_sync::<WriteOptions>();
346        is_sync::<IngestExternalFileOptions>();
347        is_sync::<BlockBasedOptions>();
348        is_sync::<PlainTableFactoryOptions>();
349        is_sync::<UnboundColumnFamily>();
350        is_sync::<ColumnFamilyDescriptor>();
351        is_sync::<ColumnFamily>();
352        is_sync::<SstFileWriter>();
353        is_sync::<Cache>();
354        is_sync::<CacheWrapper>();
355        is_sync::<Env>();
356        is_sync::<EnvWrapper>();
357        is_sync::<TransactionDB>();
358        is_sync::<OptimisticTransactionDB>();
359        is_sync::<TransactionDBOptions>();
360        is_sync::<OptimisticTransactionOptions>();
361        is_sync::<TransactionOptions>();
362        is_sync::<WriteBufferManager>();
363        is_sync::<WriteBufferManagerWrapper>();
364    }
365}