Skip to content

Commit

Permalink
Merge the tests and most of the Tree methods from old sled into sled 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
spacejam committed Jul 30, 2023
1 parent 6f46cde commit 9df7f3c
Show file tree
Hide file tree
Showing 13 changed files with 6,724 additions and 139 deletions.
15 changes: 15 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ categories = ["database-implementations", "concurrency", "data-structures", "alg
readme = "README.md"
exclude = ["benchmarks", "examples", "bindings", "scripts", "experiments"]

[features]
# initializes allocated memory to 0xa1, writes 0xde to deallocated memory before freeing it
testing_shred_allocator = []
# use a counting global allocator that provides the sled::alloc::{allocated, freed, resident, reset} functions
testing_count_allocator = []

[dependencies]
bincode = "1.3.3"
cache-advisor = "1.0.12"
Expand Down Expand Up @@ -40,3 +46,12 @@ num-format = "0.4.4"
rocksdb = "0.21.0"
rusqlite = "0.29.0"
old_sled = { version = "0.34", package = "sled" }
rand = "0.8.5"
quickcheck = "1.0.3"
rand_distr = "0.4.3"

[[test]]
name = "test_crash_recovery"
path = "tests/test_crash_recovery.rs"
harness = false

3 changes: 2 additions & 1 deletion examples/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ impl Databench for Db {
sled::Config {
path: Self::PATH.into(),
zstd_compression_level: 3,
cache_size: 1024 * 1024 * 1024,
cache_capacity_bytes: 1024 * 1024 * 1024,
entry_cache_percent: 20,
flush_every_ms: Some(200),
temporary: false,
}
.open()
.unwrap()
Expand Down
81 changes: 81 additions & 0 deletions src/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#[cfg(any(
feature = "testing_shred_allocator",
feature = "testing_count_allocator"
))]
pub use alloc::*;

// the memshred feature causes all allocated and deallocated
// memory to be set to a specific non-zero value of 0xa1 for
// uninitialized allocations and 0xde for deallocated memory,
// in the hope that it will cause memory errors to surface
// more quickly.

#[cfg(feature = "testing_shred_allocator")]
mod alloc {
use std::alloc::{Layout, System};

#[global_allocator]
static ALLOCATOR: ShredAllocator = ShredAllocator;

#[derive(Default, Debug, Clone, Copy)]
struct ShredAllocator;

unsafe impl std::alloc::GlobalAlloc for ShredAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let ret = System.alloc(layout);
assert_ne!(ret, std::ptr::null_mut());
std::ptr::write_bytes(ret, 0xa1, layout.size());
ret
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
std::ptr::write_bytes(ptr, 0xde, layout.size());
System.dealloc(ptr, layout)
}
}
}

#[cfg(feature = "testing_shred_allocator")]
mod alloc {

Check failure on line 39 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

the name `alloc` is defined multiple times

error[E0428]: the name `alloc` is defined multiple times --> src/alloc.rs:39:1 | 14 | mod alloc { | --------- previous definition of the module `alloc` here ... 39 | mod alloc { | ^^^^^^^^^ `alloc` redefined here | = note: `alloc` must be defined only once in the type namespace of this module
use std::alloc::{Layout, System};

#[global_allocator]
static ALLOCATOR: CountingAllocator = CountingAllocator;

static ALLOCATED: AtomicUsize = AtomicUsize::new(0);

Check failure on line 45 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `AtomicUsize`

error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` --> src/alloc.rs:45:37 | 45 | static ALLOCATED: AtomicUsize = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` | help: consider importing one of these items | 40 + use core::sync::atomic::AtomicUsize; | 40 + use std::sync::atomic::AtomicUsize; |

Check failure on line 45 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

cannot find type `AtomicUsize` in this scope

error[E0412]: cannot find type `AtomicUsize` in this scope --> src/alloc.rs:45:23 | 45 | static ALLOCATED: AtomicUsize = AtomicUsize::new(0); | ^^^^^^^^^^^ not found in this scope | help: consider importing one of these items | 40 + use core::sync::atomic::AtomicUsize; | 40 + use std::sync::atomic::AtomicUsize; |
static FREED: AtomicUsize = AtomicUsize::new(0);

Check failure on line 46 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `AtomicUsize`

error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` --> src/alloc.rs:46:33 | 46 | static FREED: AtomicUsize = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` | help: consider importing one of these items | 40 + use core::sync::atomic::AtomicUsize; | 40 + use std::sync::atomic::AtomicUsize; |

Check failure on line 46 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

cannot find type `AtomicUsize` in this scope

error[E0412]: cannot find type `AtomicUsize` in this scope --> src/alloc.rs:46:19 | 46 | static FREED: AtomicUsize = AtomicUsize::new(0); | ^^^^^^^^^^^ not found in this scope | help: consider importing one of these items | 40 + use core::sync::atomic::AtomicUsize; | 40 + use std::sync::atomic::AtomicUsize; |
static RESIDENT: AtomicUsize = AtomicUsize::new(0);

Check failure on line 47 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `AtomicUsize`

error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` --> src/alloc.rs:47:36 | 47 | static RESIDENT: AtomicUsize = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` | help: consider importing one of these items | 40 + use core::sync::atomic::AtomicUsize; | 40 + use std::sync::atomic::AtomicUsize; |

Check failure on line 47 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

cannot find type `AtomicUsize` in this scope

error[E0412]: cannot find type `AtomicUsize` in this scope --> src/alloc.rs:47:22 | 47 | static RESIDENT: AtomicUsize = AtomicUsize::new(0); | ^^^^^^^^^^^ not found in this scope | help: consider importing one of these items | 40 + use core::sync::atomic::AtomicUsize; | 40 + use std::sync::atomic::AtomicUsize; |

fn allocated() -> usize {
ALLOCATED.swap(0, Ordering::Relaxed)

Check failure on line 50 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:50:27 | 50 | ALLOCATED.swap(0, Ordering::Relaxed) | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
}

fn freed() -> usize {
FREED.swap(0, Ordering::Relaxed)

Check failure on line 54 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:54:23 | 54 | FREED.swap(0, Ordering::Relaxed) | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
}

fn resident() -> usize {
RESIDENT.load(Ordering::Relaxed)

Check failure on line 58 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:58:23 | 58 | RESIDENT.load(Ordering::Relaxed) | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
}

#[derive(Default, Debug, Clone, Copy)]
struct CountingAllocator;

unsafe impl std::alloc::GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let ret = System.alloc(layout);
assert_ne!(ret, std::ptr::null_mut());
ALLOCATED.fetch_add(layout.size(), Ordering::Relaxed);

Check failure on line 68 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:68:48 | 68 | ALLOCATED.fetch_add(layout.size(), Ordering::Relaxed); | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
RESIDENT.fetch_add(layout.size(), Ordering::Relaxed);

Check failure on line 69 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:69:47 | 69 | RESIDENT.fetch_add(layout.size(), Ordering::Relaxed); | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
std::ptr::write_bytes(ret, 0xa1, layout.size());
ret
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
std::ptr::write_bytes(ptr, 0xde, layout.size());
FREED.fetch_add(layout.size(), Ordering::Relaxed);

Check failure on line 76 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:76:44 | 76 | FREED.fetch_add(layout.size(), Ordering::Relaxed); | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
RESIDENT.fetch_sub(layout.size(), Ordering::Relaxed);

Check failure on line 77 in src/alloc.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Ordering`

error[E0433]: failed to resolve: use of undeclared type `Ordering` --> src/alloc.rs:77:47 | 77 | RESIDENT.fetch_sub(layout.size(), Ordering::Relaxed); | ^^^^^^^^ use of undeclared type `Ordering` | help: consider importing one of these items | 40 + use core::cmp::Ordering; | 40 + use core::sync::atomic::Ordering; | 40 + use std::cmp::Ordering; | 40 + use std::sync::atomic::Ordering; |
System.dealloc(ptr, layout)
}
}
}
66 changes: 66 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::path::{Path, PathBuf};

use crate::Db;

#[derive(Debug, Clone)]
pub struct Config {
/// The base directory for storing the database.
pub path: PathBuf,
/// Cache size in **bytes**. Default is 512mb.
pub cache_capacity_bytes: usize,
/// The percentage of the cache that is dedicated to the
/// scan-resistant entry cache.
pub entry_cache_percent: u8,
/// Start a background thread that flushes data to disk
/// every few milliseconds. Defaults to every 200ms.
pub flush_every_ms: Option<usize>,
/// The zstd compression level to use when writing data to disk. Defaults to 3.
pub zstd_compression_level: i32,
/// Attempts to delete all storage files when the last open instance of a Db is dropped.
pub temporary: bool,
}

impl Default for Config {
fn default() -> Config {
Config {
path: "bloodstone.default".into(),
flush_every_ms: Some(200),
cache_capacity_bytes: 512 * 1024 * 1024,
entry_cache_percent: 20,
zstd_compression_level: 3,
temporary: false,
}
}
}

impl Config {
/// Returns a default `Config`
pub fn new() -> Config {
Config::default()
}

/// Set the path of the database (builder).
pub fn path<P: AsRef<Path>>(mut self, path: P) -> Config {
self.path = path.as_ref().to_path_buf();
self
}

builder!(
(flush_every_ms, Option<usize>, "Start a background thread that flushes data to disk every few milliseconds. Defaults to every 200ms."),
(cache_capacity_bytes, usize, "Cache size in **bytes**. Default is 512mb."),
(entry_cache_percent, u8, "The percentage of the cache that is dedicated to the scan-resistant entry cache."),
(zstd_compression_level, i32, "The zstd compression level to use when writing data to disk. Defaults to 3."),
(temporary, bool, "Attempts to delete all storage files when the last open instance of a Db is dropped.")
);

pub fn open<
const INDEX_FANOUT: usize,
const LEAF_FANOUT: usize,
const EBR_LOCAL_GC_BUFFER_SIZE: usize,
>(
&self,
) -> std::io::Result<Db<INDEX_FANOUT, LEAF_FANOUT, EBR_LOCAL_GC_BUFFER_SIZE>>
{
Db::open_with_config(self)
}
}

0 comments on commit 9df7f3c

Please sign in to comment.