[][src]Struct pagecache::PageCache

pub struct PageCache<PM, P> where
    P: Clone + 'static + Send + Sync
{ /* fields omitted */ }

A lock-free pagecache which supports fragmented pages for dramatically improving write throughput.

Working with the PageCache

use pagecache::{pin, Materializer};

pub struct TestMaterializer;

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;

    // Create a new `Materializer` with the previously recovered
    // state if any existed.
    fn new(config: pagecache::Config) -> Self {
        TestMaterializer
    }

    // Used to merge chains of partial pages into a form
    // that is useful for the `PageCache` owner.
    fn merge<'a, I>(&'a self, frags: I) -> Self::PageFrag
    where
        I: IntoIterator<Item = &'a Self::PageFrag>,
    {
        frags.into_iter().fold(String::new(), |mut acc, ref s| {
            acc.push_str(&*s);
            acc
        })
    }

    // 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).build();
    let pc: pagecache::PageCache<TestMaterializer, _> =
        pagecache::PageCache::start(config).unwrap();
    {
        // We begin by initiating a new transaction, which
        // will prevent any witnessable memory from being
        // reclaimed before we drop this object.
        let tx = pc.begin().unwrap();

        // The first item in a page should be set using allocate,
        // which signals that this is the beginning of a new
        // page history.
        let (id, mut key) = pc.allocate("a".to_owned(), &tx).unwrap();

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

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

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

        // You can completely rewrite a page by using `replace`:
        key = pc.replace(id, key, "d".into(), &tx).unwrap().unwrap();

        let (consolidated, key) = pc.get(id, &tx).unwrap().unwrap();

        assert_eq!(*consolidated, "d".to_owned());
    }
}

Methods

impl<PM, P> PageCache<PM, P> where
    PM: Materializer<PageFrag = P>,
    PM: 'static + Send + Sync,
    P: 'static + Debug + Clone + Serialize + DeserializeOwned + Send + Sync
[src]

pub fn start(config: Config) -> Result<PageCache<PM, P>>[src]

Instantiate a new PageCache.

pub fn flush(&self) -> Result<usize>[src]

Flushes any pending IO buffers to disk to ensure durability. Returns the number of bytes written during this call.

pub fn begin(&self) -> Result<Tx>[src]

Begins a transaction.

pub fn allocate<'g>(
    &self,
    new: P,
    tx: &'g Tx
) -> Result<(PageId, PagePtr<'g, P>)>
[src]

Create a new page, trying to reuse old freed pages if possible to maximize underlying PageTable pointer density. Returns the page ID and its pointer for use in future atomic replace and link operations.

pub fn attempt_gc(&self) -> Result<bool>[src]

Attempt to opportunistically rewrite data from a Draining segment of the file to help with space amplification. Returns Ok(true) if we had the opportunity to attempt to move a page. Returns Ok(false) if there were no pages to GC. Returns an Err if we encountered an IO problem while performing this GC.

pub fn free<'g>(
    &self,
    pid: PageId,
    old: PagePtr<'g, P>,
    tx: &'g Tx
) -> Result<CasResult<'g, P, ()>>
[src]

Free a particular page.

Try to atomically add a PageFrag to the page. Returns Ok(new_key) if the operation was successful. Returns Err(None) if the page no longer exists. Returns Err(Some(actual_key)) if the atomic append fails.

pub fn replace<'g>(
    &self,
    pid: PageId,
    old: PagePtr<'g, P>,
    new: P,
    tx: &'g Tx
) -> Result<CasResult<'g, P, P>>
[src]

Replace an existing page with a different set of PageFrags. Returns Ok(new_key) if the operation was successful. Returns Err(None) if the page no longer exists. Returns Err(Some(actual_key)) if the atomic swap fails.

pub fn get<'g>(&self, pid: PageId, tx: &'g Tx) -> Result<PageGet<'g, P>>[src]

Try to retrieve a page by its logical ID, using the provided Materializer to consolidate the fragments in-memory and returning the single consolidated page.

pub fn get_page_frags<'g>(
    &'g self,
    pid: PageId,
    tx: &'g Tx
) -> Result<(PagePtr<'g, P>, Vec<&'g P>)>
[src]

Try to retrieve a page by its logical ID.

pub fn stable_lsn(&self) -> Lsn[src]

The highest known stable Lsn on disk.

pub fn make_stable(&self, lsn: Lsn) -> Result<usize>[src]

Blocks until the provided Lsn is stable on disk, triggering necessary flushes in the process. Returns the number of bytes written during this call.

pub fn bump_page_rts(&self, pid: PageId, ts: u64, tx: &Tx)[src]

Increase a page's associated transactional read timestamp (RTS) to as high as the specified timestamp.

pub fn get_page_rts(&self, pid: PageId, tx: &Tx) -> Option<u64>[src]

Retrieves the current transactional read timestamp for a page.

pub fn was_recovered(&self) -> bool[src]

Returns true if the database was recovered from a previous process. Note that database state is only guaranteed to be present up to the last call to flush! Otherwise state is synced to disk periodically if the sync_every_ms configuration option is set to Some(number_of_ms_between_syncs) or if the IO buffer gets filled to capacity before being rotated.

pub fn generate_id(&self) -> Result<u64>[src]

Generate a monotonic ID. Not guaranteed to be contiguous. Written to disk every idgen_persist_interval operations, followed by a blocking flush. During recovery, we take the last recovered generated ID and add 2x the idgen_persist_interval to it. While persisting, if the previous persisted counter wasn't synced to disk yet, we will do a blocking flush to fsync the latest counter, ensuring that we will never give out the same counter twice.

pub fn meta<'a>(&self, tx: &'a Tx) -> Result<&'a Meta>[src]

Returns the current Meta map, which contains a convenient mapping from identifiers to PageId's that the PageCache owner may use for storing metadata about their higher-level collections.

pub fn meta_pid_for_name(&self, name: &[u8], tx: &Tx) -> Result<usize>[src]

Look up a PageId for a given identifier in the Meta mapping. This is pretty cheap, but in some cases you may prefer to maintain your own atomic references to collection roots instead of relying on this. See sled's Tree root tracking for an example of avoiding this in a lock-free way that handles various race conditions.

pub fn cas_root_in_meta<'g>(
    &self,
    name: Vec<u8>,
    old: Option<usize>,
    new: Option<usize>,
    tx: &'g Tx
) -> Result<Result<(), Option<usize>>>
[src]

Compare-and-swap the Meta mapping for a given identifier.

Trait Implementations

impl<PM, P> Send for PageCache<PM, P> where
    PM: Send + Sync,
    P: Clone + 'static + Send + Sync
[src]

impl<PM, P> Sync for PageCache<PM, P> where
    PM: Send + Sync,
    P: Clone + 'static + Send + Sync
[src]

impl<PM, P> Debug for PageCache<PM, P> where
    PM: Send + Sync,
    P: Clone + Debug + Send + Sync
[src]

Blanket Implementations

impl<T, U> Into for T where
    U: From<T>, 
[src]

impl<T> From for T[src]

impl<T, U> TryFrom for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T> Borrow for T where
    T: ?Sized
[src]

impl<T> BorrowMut for T where
    T: ?Sized
[src]

impl<T, U> TryInto for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> Any for T where
    T: 'static + ?Sized
[src]