rsdb/
lib.rs

1//! `rsdb` is a flash-sympathetic persistent lock-free B+ tree, pagecache, and log.
2//!
3//! ```
4//! let t = rsdb::Config::default().tree();
5//! t.set(b"yo!".to_vec(), b"v1".to_vec());
6//! assert_eq!(t.get(b"yo!"), Some(b"v1".to_vec()));
7//! t.cas(b"yo!".to_vec(), Some(b"v1".to_vec()), Some(b"v2".to_vec())).unwrap();
8//! let mut iter = t.scan(b"a non-present key before yo!");
9//! assert_eq!(iter.next(), Some((b"yo!".to_vec(), b"v2".to_vec())));
10//! assert_eq!(iter.next(), None);
11//! t.del(b"yo!");
12//! ```
13
14#![deny(missing_docs)]
15#![cfg_attr(test, deny(warnings))]
16#![cfg_attr(feature="clippy", feature(plugin))]
17#![cfg_attr(feature="clippy", plugin(clippy))]
18#![cfg_attr(feature="clippy", allow(inline_always))]
19
20#[macro_use]
21extern crate serde_derive;
22extern crate serde;
23extern crate crossbeam;
24extern crate coco;
25extern crate bincode;
26extern crate historian;
27#[macro_use]
28extern crate lazy_static;
29#[cfg(feature = "log")]
30#[macro_use]
31extern crate log as _log;
32extern crate libc;
33#[cfg(feature = "rayon")]
34extern crate rayon;
35#[cfg(feature = "zstd")]
36extern crate zstd;
37#[cfg(test)]
38extern crate rand;
39
40/// atomic lock-free tree
41pub use tree::{Tree, TreeIter};
42/// lock-free pagecache
43pub use page::{CasKey, Materializer, PageCache};
44/// lock-free log-structured storage
45pub use log::{HEADER_LEN, LockFreeLog, Log, LogRead};
46pub use ds::{Radix, Stack};
47/// general-purpose configuration
48pub use config::Config;
49
50/// C-compatible API for the lock-free log-structured B+tree.
51pub mod c;
52
53macro_rules! rep_no_copy {
54    ($e:expr; $n:expr) => {
55        {
56            let mut v = Vec::with_capacity($n);
57            for _ in 0..$n {
58                v.push($e);
59            }
60            v
61        }
62    };
63}
64
65#[cfg(test)]
66fn test_fail() -> bool {
67    use rand::Rng;
68    rand::thread_rng().gen::<bool>();
69    // TODO when the time is right, return the gen'd bool
70    false
71}
72
73#[cfg(not(test))]
74#[inline(always)]
75fn test_fail() -> bool {
76    false
77}
78
79mod tree;
80mod log;
81mod page;
82mod config;
83mod thread_cache;
84mod hash;
85mod ds;
86mod metrics;
87
88use metrics::Metrics;
89use ds::{Lru, StackIter, node_from_frag_vec};
90use hash::{crc16_arr, crc64};
91use thread_cache::ThreadCache;
92
93type LogID = u64; // LogID == file position to simplify file mapping
94type PageID = usize;
95
96type Key = Vec<u8>;
97type KeyRef<'a> = &'a [u8];
98type Value = Vec<u8>;
99
100lazy_static! {
101    /// A metric collector for all rsdb instances running in this
102    /// process.
103    pub static ref M: Metrics = Metrics::default();
104}
105
106// get thread identifier
107#[inline(always)]
108fn tn() -> String {
109    use std::thread;
110    thread::current().name().unwrap_or("unknown").to_owned()
111}
112
113fn clock() -> f64 {
114    let u = uptime();
115    (u.as_secs() * 1_000_000_000) as f64 + u.subsec_nanos() as f64
116}
117
118// not correct, since it starts counting at the first observance...
119fn uptime() -> std::time::Duration {
120    lazy_static! {
121        static ref START: std::time::Instant = std::time::Instant::now();
122    }
123
124    START.elapsed()
125}