1use crate::{
2 catalogs, config, conn, database, retry,
3 runtime::{self, heap, release, slot},
4};
5use dope_core::driver::storage;
6use heap::layout::Layout;
7use std::{cell, marker, mem, pin, ptr};
8
9pub struct State<'d, I: catalogs::Catalog> {
11 retry: retry::raw::Configured<'d>,
12 slot: cell::UnsafeCell<slot::Local<I>>,
13 phase: runtime::raw::Span,
14 _retire: Retire,
15 proof: marker::PhantomData<(cell::Cell<&'d I>, marker::PhantomPinned)>,
16 value_bytes: i32,
17 statement_sql_bytes: i32,
18 database: cell::UnsafeCell<Option<database::Target<'d>>>,
19}
20
21pub(super) struct Settings {
22 pub(super) config: config::Config,
23 pub(super) value_bytes: i32,
24 pub(super) statement_sql_bytes: i32,
25}
26
27struct Resources {
29 heap: heap::raw::Retained,
30 memory: runtime::raw::Memory,
31}
32
33struct Retire(ptr::NonNull<Resources>);
34
35impl<'d, I: catalogs::Catalog> State<'d, I> {
36 pub(crate) const RETENTION_BYTES: usize = mem::size_of::<Resources>().div_ceil(64) * 64;
37
38 pub(in crate::runtime) fn new(
39 context: &mut storage::Context<'_, 'd>,
40 settings: Settings,
41 sqlite: Layout,
42 database: database::Target<'d>,
43 stmts: usize,
44 aside: crate::memory::Lookaside,
45 ) -> Result<Self, runtime::Error> {
46 let Settings {
47 config,
48 value_bytes: values,
49 statement_sql_bytes: sql,
50 } = settings;
51 let (memory, sqlite, collect, stmts, storage, phase) = runtime::raw::Memory::new(
52 sqlite,
53 config.result_bytes(),
54 stmts,
55 aside.bytes(),
56 conn::raw::Vacant::<'_, 'd, I>::LAYOUT,
57 )?;
58 let retry = retry::raw::Configured::new(config, || {
59 context
60 .timer()
61 .try_alarm()
62 .map_err(runtime::Error::TimerCapacity)
63 })?;
64 let (slot, heap) = slot::Local::new(sqlite, collect, stmts, storage, aside)?;
65 Ok(Self {
66 retry,
67 slot: cell::UnsafeCell::new(slot),
68 phase,
69 _retire: Resources::place(memory, heap),
70 proof: marker::PhantomData,
71 value_bytes: values,
72 statement_sql_bytes: sql,
73 database: cell::UnsafeCell::new(Some(database)),
74 })
75 }
76
77 pub fn config(self: pin::Pin<&Self>) -> &config::Config {
78 self.get_ref().retry.config()
79 }
80
81 pub(crate) const fn sql_bytes(&self) -> i32 {
82 self.statement_sql_bytes
83 }
84
85 pub(crate) const fn value_bytes(&self) -> i32 {
86 self.value_bytes
87 }
88
89 pub(crate) fn try_lease<'local>(
90 self: pin::Pin<&'local Self>,
91 report: &'local mut crate::open::Completion,
92 ) -> Result<
93 (
94 database::Target<'d>,
95 slot::Vacant<'local, 'd, I>,
96 conn::raw::Vacant<'local, 'd, I>,
97 ),
98 crate::open::Error,
99 >
100 where
101 'd: 'local,
102 {
103 let report = report.admit()?;
104 let local = self.get_ref();
105 let database = unsafe { &mut *local.database.get() }
107 .take()
108 .ok_or(crate::open::Error::AlreadyStarted)?;
109 let retry = unsafe { local.retry.loan() };
112 let slot = unsafe { &mut *local.slot.get() };
115 let lease = slot.lease(retry, report)?;
116 let phase = unsafe { conn::raw::Vacant::new(&local.phase) };
119 Ok((database, lease, phase))
120 }
121}
122
123impl Resources {
124 fn place(mut memory: runtime::raw::Memory, heap: heap::raw::Retained) -> Retire {
125 let pointer = memory.base().cast::<Self>();
126 unsafe { pointer.as_ptr().write(Self { heap, memory }) };
128 Retire(pointer)
129 }
130}
131
132impl Drop for Retire {
133 fn drop(&mut self) {
134 let Resources { heap, memory } = unsafe { self.0.as_ptr().read() };
136 heap.arm(release::Release::new(memory));
137 }
138}
139
140const _: () = {
141 assert!(mem::align_of::<Resources>() <= 64);
142 let fields = mem::size_of::<retry::raw::Configured<'_>>()
143 + mem::size_of::<cell::UnsafeCell<slot::Local<catalogs::Empty>>>()
144 + mem::size_of::<runtime::raw::Span>()
145 + mem::size_of::<Retire>()
146 + mem::size_of::<marker::PhantomData<(cell::Cell<&catalogs::Empty>, marker::PhantomPinned)>>(
147 )
148 + 2 * mem::size_of::<i32>()
149 + mem::size_of::<cell::UnsafeCell<Option<database::Target<'_>>>>();
150 let align = mem::align_of::<State<'_, catalogs::Empty>>();
151 assert!(mem::size_of::<State<'_, catalogs::Empty>>() == fields.next_multiple_of(align));
152};