use crate::{
catalogs, config, conn, database, retry,
runtime::{self, heap, slot},
};
use dope_core::driver::storage;
use heap::layout::Layout;
use std::{cell, marker, mem, pin};
pub struct State<'d, I: catalogs::Catalog> {
retry: retry::raw::Configured<'d>,
slot: cell::UnsafeCell<slot::Local<I>>,
phase: runtime::raw::Span,
_retire: heap::raw::Retained,
proof: marker::PhantomData<(cell::Cell<&'d I>, marker::PhantomPinned)>,
value_bytes: i32,
statement_sql_bytes: i32,
database: cell::UnsafeCell<Option<(database::Target<'d>, heap::raw::Local)>>,
}
pub(super) struct Settings {
pub(super) config: config::Config,
pub(super) value_bytes: i32,
pub(super) statement_sql_bytes: i32,
}
impl<'d, I: catalogs::Catalog> State<'d, I> {
pub(in crate::runtime) fn new(
context: &mut storage::Context<'_, 'd>,
settings: Settings,
sqlite: Layout,
database: database::Target<'d>,
stmts: usize,
aside: crate::memory::Lookaside,
) -> Result<Self, runtime::Error> {
let Settings {
config,
value_bytes: values,
statement_sql_bytes: sql,
} = settings;
let (memory, sqlite, collect, stmts, storage, phase) = runtime::raw::Memory::new(
sqlite,
config.result_bytes(),
stmts,
aside.bytes(),
conn::raw::Vacant::<'_, 'd, I>::LAYOUT,
)?;
let retry = retry::raw::Configured::new(config, || {
context
.timer()
.try_alarm()
.map_err(runtime::Error::TimerCapacity)
})?;
let (slot, heap, retained) =
slot::Local::new(memory, sqlite, collect, stmts, storage, aside)?;
Ok(Self {
retry,
slot: cell::UnsafeCell::new(slot),
phase,
_retire: retained,
proof: marker::PhantomData,
value_bytes: values,
statement_sql_bytes: sql,
database: cell::UnsafeCell::new(Some((database, heap))),
})
}
pub fn config(self: pin::Pin<&Self>) -> &config::Config {
self.get_ref().retry.config()
}
pub(crate) const fn sql_bytes(&self) -> i32 {
self.statement_sql_bytes
}
pub(crate) const fn value_bytes(&self) -> i32 {
self.value_bytes
}
pub(crate) fn try_lease<'local>(
self: pin::Pin<&'local Self>,
report: &'local mut crate::open::Completion,
) -> Result<
(
database::Target<'d>,
slot::Vacant<'local, 'd, I>,
conn::raw::Vacant<'local, 'd, I>,
),
crate::open::Error,
>
where
'd: 'local,
{
let report = report.admit()?;
let local = self.get_ref();
let (database, heap) = unsafe { &mut *local.database.get() }
.take()
.ok_or(crate::open::Error::AlreadyStarted)?;
let retry = unsafe { local.retry.loan() };
let slot = unsafe { &mut *local.slot.get() };
let lease = slot.lease(heap, retry, report)?;
let phase = unsafe { conn::raw::Vacant::new(&local.phase) };
Ok((database, lease, phase))
}
}
const _: () = {
let fields = mem::size_of::<retry::raw::Configured<'_>>()
+ mem::size_of::<cell::UnsafeCell<slot::Local<catalogs::Empty>>>()
+ mem::size_of::<runtime::raw::Span>()
+ mem::size_of::<heap::raw::Retained>()
+ mem::size_of::<marker::PhantomData<(cell::Cell<&catalogs::Empty>, marker::PhantomPinned)>>(
)
+ 2 * mem::size_of::<i32>()
+ mem::size_of::<cell::UnsafeCell<Option<(database::Target<'_>, heap::raw::Local)>>>();
let align = mem::align_of::<State<'_, catalogs::Empty>>();
assert!(mem::size_of::<State<'_, catalogs::Empty>>() == fields.next_multiple_of(align));
};