52 releases (14 breaking)

✓ Uses Rust 2018 edition

0.17.0 May 12, 2019
0.16.2 Apr 22, 2019
0.13.1 Mar 31, 2019
0.8.2 Dec 12, 2018
0.4.2 Mar 9, 2018

#3 in Database implementations

Download history 53/week @ 2019-01-27 54/week @ 2019-02-03 58/week @ 2019-02-10 102/week @ 2019-02-17 101/week @ 2019-02-24 198/week @ 2019-03-03 108/week @ 2019-03-10 101/week @ 2019-03-17 529/week @ 2019-03-24 332/week @ 2019-03-31 314/week @ 2019-04-07 222/week @ 2019-04-14 297/week @ 2019-04-21 280/week @ 2019-04-28 357/week @ 2019-05-05

1,616 downloads per month
Used in 16 crates (2 directly)

MIT/Apache

326KB
7.5K SLoC

pagecache

Build Status crates.io documentation

A construction kit for databases. Provides a lock-free log store and pagecache.

References

use pagecache::{PagePtr, pin, Materializer};

pub struct TestMaterializer;

// A PageCache must be used with a Materializer to
// assist with recovery of custom state, and to
// assemble partial page fragments into the form
// that is usable by the higher-level system.
impl Materializer for TestMaterializer {
    // The possibly fragmented page, written to log storage sequentially, and
    // read in parallel from multiple locations on disk when serving
    // a request to read the page. These will be merged to a single version
    // at read time, and possibly cached.
    type PageFrag = String;

    // The state returned by a call to `PageCache::recover`, as
    // described by `Materializer::recover`
    type Recovery = ();

    // Create a new `Materializer` with the previously recovered
    // state if any existed.
    fn new(last_recovery: &Option<Self::Recovery>) -> Self {
        TestMaterializer
    }

    // Used to merge chains of partial pages into a form
    // that is useful for the `PageCache` owner.
    fn merge(&self, frags: &[&Self::PageFrag]) -> Self::PageFrag {
        let mut consolidated = String::new();
        for frag in frags.into_iter() {
            consolidated.push_str(&*frag);
        }

        consolidated
    }

    // Used to feed custom recovery information back to a higher-level abstraction
    // during startup. For example, a B-Link tree must know what the current
    // root node is before it can start serving requests.
    fn recover(&self, _: &Self::PageFrag) -> Option<Self::Recovery> {
        None
    }

    // Used to determine the resident size for this item in cache.
    fn size_in_bytes(&self, frag: &String) -> usize {
        std::mem::size_of::<String>() + frag.as_bytes().len()
    }
}

fn main() {
    let config = pagecache::ConfigBuilder::new().temporary(true);
    let pc: pagecache::PageCache<TestMaterializer, _, _> =
        pagecache::PageCache::start(config.build());
    {
        let guard = pin();
        let id = pc.allocate(&guard);

        // The first item in a page should be set using replace,
        // which signals that this is the beginning of a new
        // page history, and that any previous items associated
        // with this page should be forgotten.
        let key = pc.replace(id, PagePtr::null(), "a".to_owned(), &guard).unwrap();

        // Subsequent atomic updates should be added with link.
        let key = pc.link(id, key, "b".to_owned(), &guard).unwrap();
        let _key = pc.link(id, key, "c".to_owned(), &guard).unwrap();

        // When getting a page, the provide `Materializer` is
        // used to merge all pages together.
        let (consolidated, _key) = pc.get(id, &guard).unwrap();

        assert_eq!(consolidated, "abc".to_owned());
    }
}

Dependencies

~5MB
~88K SLoC