#![doc(
html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![deny(
missing_docs,
future_incompatible,
nonstandard_style,
rust_2018_idioms,
missing_copy_implementations,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unused_qualifications
)]
#![deny(
// over time, consider enabling the commented-out lints below
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::checked_conversions,
clippy::decimal_literal_representation,
clippy::doc_markdown,
// clippy::else_if_without_else,
clippy::empty_enum,
clippy::explicit_into_iter_loop,
clippy::explicit_iter_loop,
clippy::expl_impl_clone_on_copy,
clippy::fallible_impl_from,
clippy::filter_map,
clippy::filter_map_next,
clippy::find_map,
clippy::float_arithmetic,
clippy::get_unwrap,
clippy::if_not_else,
// clippy::indexing_slicing,
clippy::inline_always,
//clippy::integer_arithmetic,
clippy::invalid_upcast_comparisons,
clippy::items_after_statements,
clippy::map_entry,
clippy::map_flatten,
clippy::match_same_arms,
clippy::maybe_infinite_iter,
clippy::mem_forget,
// clippy::missing_const_for_fn,
// clippy::missing_docs_in_private_items,
clippy::module_name_repetitions,
clippy::multiple_inherent_impl,
clippy::mut_mut,
clippy::needless_borrow,
clippy::needless_continue,
clippy::needless_pass_by_value,
clippy::non_ascii_literal,
clippy::path_buf_push_overwrite,
clippy::print_stdout,
clippy::pub_enum_variant_names,
clippy::redundant_closure_for_method_calls,
clippy::shadow_reuse,
clippy::shadow_same,
clippy::shadow_unrelated,
clippy::single_match_else,
clippy::string_add,
clippy::string_add_assign,
clippy::type_repetition_in_bounds,
clippy::unicode_not_nfc,
// clippy::unimplemented,
clippy::unseparated_literal_suffix,
clippy::used_underscore_binding,
clippy::wildcard_dependencies,
// clippy::wildcard_enum_match_arm,
clippy::wrong_pub_self_convention,
)]
#![warn(clippy::multiple_crate_versions)]
#![allow(clippy::mem_replace_with_default)] #![allow(clippy::match_like_matches_macro)]
macro_rules! io_fail {
($config:expr, $e:expr) => {
#[cfg(feature = "failpoints")]
{
debug_delay();
if fail::is_active($e) {
$config.set_global_error(Error::FailPoint);
return Err(Error::FailPoint).into();
}
}
};
}
macro_rules! testing_assert {
($($e:expr),*) => {
#[cfg(feature = "lock_free_delays")]
assert!($($e),*)
};
}
mod arc;
mod atomic_shim;
mod batch;
mod binary_search;
mod concurrency_control;
mod config;
mod context;
mod db;
mod dll;
mod fastcmp;
mod fastlock;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod prefix;
mod result;
mod serialization;
mod stack;
mod subscriber;
mod sys_limits;
pub mod transaction;
mod tree;
#[cfg(feature = "failpoints")]
pub mod fail;
#[cfg(feature = "docs")]
pub mod doc;
#[cfg(any(
miri,
not(any(
windows,
target_os = "linux",
target_os = "macos",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))
))]
mod threadpool {
use super::{OneShot, Result};
pub fn spawn<F, R>(work: F) -> Result<OneShot<R>>
where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
let (promise_filler, promise) = OneShot::pair();
promise_filler.fill((work)());
Ok(promise)
}
}
#[cfg(all(
not(miri),
any(
windows,
target_os = "linux",
target_os = "macos",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
)
))]
mod threadpool;
#[cfg(all(
not(miri),
any(
windows,
target_os = "linux",
target_os = "macos",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
)
))]
mod flusher;
#[cfg(feature = "event_log")]
pub mod event_log;
#[cfg(feature = "measure_allocs")]
mod measure_allocs;
#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
measure_allocs::TrackingAllocator;
const DEFAULT_TREE_ID: &[u8] = b"__sled__default";
#[doc(hidden)]
pub use {
self::{
config::RunningConfig,
lazy::Lazy,
pagecache::{
constants::{
MAX_MSG_HEADER_LEN, MAX_SPACE_AMPLIFICATION,
MINIMUM_ITEMS_PER_SEGMENT, SEG_HEADER_LEN,
},
BatchManifest, DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn,
PageCache, PageId,
},
serialization::Serialize,
},
crossbeam_epoch::{
pin as crossbeam_pin, Atomic, Guard as CrossbeamGuard, Owned, Shared,
},
};
pub use self::{
batch::Batch,
config::{Config, Mode},
db::{open, Db},
iter::Iter,
ivec::IVec,
result::{Error, Result},
subscriber::{Event, Subscriber},
transaction::Transactional,
tree::{CompareAndSwapError, Tree},
};
use {
self::{
arc::Arc,
atomic_shim::{AtomicI64 as AtomicLsn, AtomicU64},
binary_search::binary_search_lub,
concurrency_control::Protector,
context::Context,
fastcmp::fastcmp,
histogram::Histogram,
lru::Lru,
meta::Meta,
metrics::{clock, Measure, M},
node::{Data, Node},
oneshot::{OneShot, OneShotFiller},
result::CasResult,
subscriber::Subscribers,
tree::TreeInner,
},
crossbeam_utils::{Backoff, CachePadded},
log::{debug, error, trace, warn},
pagecache::RecoveryGuard,
parking_lot::{Condvar, Mutex, RwLock},
std::{
collections::BTreeMap,
convert::TryFrom,
fmt::{self, Debug},
io::{Read, Write},
sync::atomic::{
AtomicUsize,
Ordering::{Acquire, Release, SeqCst},
},
},
};
#[doc(hidden)]
pub fn pin() -> Guard {
Guard { inner: crossbeam_pin(), readset: vec![], writeset: vec![] }
}
#[doc(hidden)]
pub struct Guard {
inner: CrossbeamGuard,
readset: Vec<PageId>,
writeset: Vec<PageId>,
}
impl std::ops::Deref for Guard {
type Target = CrossbeamGuard;
fn deref(&self) -> &CrossbeamGuard {
&self.inner
}
}
#[derive(Debug)]
struct Conflict;
type Conflictable<T> = std::result::Result<T, Conflict>;
fn crc32(buf: &[u8]) -> u32 {
let mut hasher = crc32fast::Hasher::new();
hasher.update(buf);
hasher.finalize()
}
fn calculate_message_crc32(header: &[u8], body: &[u8]) -> u32 {
let mut hasher = crc32fast::Hasher::new();
hasher.update(body);
hasher.update(&header[4..]);
let crc32 = hasher.finalize();
crc32 ^ 0xFFFF_FFFF
}
#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;
#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Link {
Set(IVec, IVec),
Del(IVec),
ParentMergeIntention(PageId),
ParentMergeConfirm,
ChildMergeCap,
}
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
K,
V,
std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;
pub(crate) type FastSet8<V> = std::collections::HashSet<
V,
std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;
pub trait MergeOperator:
Fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>>
{
}
impl<F> MergeOperator for F where
F: Fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>>
{
}
mod compile_time_assertions {
use crate::*;
#[allow(unreachable_code)]
fn _assert_public_types_send_sync() {
_assert_send::<Subscriber>(unreachable!());
_assert_send_sync::<Iter>(unreachable!());
_assert_send_sync::<Tree>(unreachable!());
_assert_send_sync::<Db>(unreachable!());
_assert_send_sync::<Batch>(unreachable!());
_assert_send_sync::<IVec>(unreachable!());
_assert_send_sync::<Config>(unreachable!());
_assert_send_sync::<CompareAndSwapError>(unreachable!());
_assert_send_sync::<Error>(unreachable!());
_assert_send_sync::<Event>(unreachable!());
_assert_send_sync::<Mode>(unreachable!());
}
fn _assert_send<S: Send>(_: &S) {}
fn _assert_send_sync<S: Send + Sync>(_: &S) {}
}