trine-kv 0.5.13

Embedded LSM MVCC key-value database.
Documentation
use std::{
    future::Future,
    sync::{Arc, mpsc},
    task::{Context, Poll, Wake, Waker},
    thread,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

use super::*;
use crate::runtime::{Runtime, RuntimeOptions};

struct ThreadWaker {
    thread: thread::Thread,
}

impl Wake for ThreadWaker {
    fn wake(self: Arc<Self>) {
        self.thread.unpark();
    }

    fn wake_by_ref(self: &Arc<Self>) {
        self.thread.unpark();
    }
}

fn test_waker() -> Waker {
    Waker::from(Arc::new(ThreadWaker {
        thread: thread::current(),
    }))
}

fn block_on_test_future<T>(future: impl Future<Output = Result<T>>) -> Result<T> {
    let waker = test_waker();
    let mut context = Context::from_waker(&waker);
    let mut future = std::pin::pin!(future);
    loop {
        match future.as_mut().poll(&mut context) {
            Poll::Ready(result) => return result,
            Poll::Pending => thread::park_timeout(Duration::from_secs(1)),
        }
    }
}

fn hold_runtime_blocking_worker(runtime: &Runtime) -> mpsc::Sender<()> {
    let (started_tx, started_rx) = mpsc::channel();
    let (release_tx, release_rx) = mpsc::channel();
    runtime
        .spawn_blocking(move || {
            started_tx.send(()).expect("report blocking worker start");
            release_rx.recv().expect("wait for release");
        })
        .expect("spawn worker holder");
    started_rx
        .recv_timeout(Duration::from_secs(1))
        .expect("worker holder starts");
    release_tx
}

fn complete_after_blocking_worker_release<T>(
    runtime: &Runtime,
    mut future: StorageFuture<'_, T>,
    pending_message: &str,
) -> Result<T> {
    let release = hold_runtime_blocking_worker(runtime);
    let waker = test_waker();
    let mut context = Context::from_waker(&waker);
    assert!(
        matches!(future.as_mut().poll(&mut context), Poll::Pending),
        "{pending_message}"
    );

    release.send(()).expect("release blocking worker");
    block_on_test_future(future)
}

fn temp_storage_root(prefix: &str) -> std::path::PathBuf {
    std::env::temp_dir().join(format!(
        "{prefix}-{}-{}",
        std::process::id(),
        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("system clock is after epoch")
            .as_nanos()
    ))
}

mod memory_capabilities;
mod native_mutations;
mod native_objects;
mod platform_io;
mod runtime_adapter;