cartel_sqlite/runtime/
layout.rs1use crate::{
2 catalogs, config, database, open,
3 runtime::{self, heap, local},
4};
5use dope_core::driver::settings::{claim, errors};
6use dope_core::driver::{
7 settings::{self, demands, demands::slots::Slots},
8 storage,
9};
10use dope_runtime::topology;
11use heap::layout;
12use std::marker;
13
14pub struct Layout<'sql, I: catalogs::Catalog> {
16 settings: local::Settings,
17 sqlite: layout::Layout,
18 database: database::Target<'sql>,
19 statement_bytes: usize,
20 lookaside: crate::memory::Lookaside,
21 marker: marker::PhantomData<I>,
22}
23
24impl<'sql, I: catalogs::Catalog> Layout<'sql, I> {
25 pub(super) const fn dimensions(&self) -> (layout::Layout, usize, usize, usize) {
26 (
27 self.sqlite,
28 self.settings.config.result_bytes(),
29 self.statement_bytes,
30 self.lookaside.bytes(),
31 )
32 }
33
34 pub(super) fn into_parts(
35 self,
36 ) -> (
37 local::Settings,
38 database::Target<'sql>,
39 crate::memory::Lookaside,
40 ) {
41 (self.settings, self.database, self.lookaside)
42 }
43}
44
45impl<'sql> database::Target<'sql> {
46 pub fn plan<I: catalogs::Catalog>(
47 self,
48 limits: crate::Limits,
49 memory: crate::Memory,
50 ) -> Result<topology::Plan<Layout<'sql, I>, open::Plan<I>>, database::Error> {
51 catalogs::validate::<I>().map_err(database::Error::Catalog)?;
52 let config = config::Config::from_parts(limits, memory)?;
53 let (plan, sqlite) = memory.admit::<I>().map_err(database::Error::Runtime)?;
54 if plan.targets.retained > sqlite.capacity() {
55 return Err(database::Error::Runtime(runtime::Error::SqliteCapacity));
56 }
57 let values = sqlite.capacity();
58 if values > i32::MAX as usize {
59 return Err(database::Error::Runtime(runtime::Error::SqliteMemory {
60 actual: values,
61 }));
62 }
63 let actual = plan.statements.sql_bytes.max(self.sql_bytes());
64 if actual > i32::MAX as usize {
65 return Err(database::Error::Runtime(
66 runtime::Error::StatementSqlBytes { actual },
67 ));
68 }
69 let sql = actual as i32;
70 let layout = Layout {
71 settings: local::Settings {
72 config,
73 value_bytes: values as i32,
74 statement_sql_bytes: sql,
75 },
76 sqlite,
77 database: self,
78 statement_bytes: plan.statements.slots_bytes,
79 lookaside: memory.lookaside,
80 marker: marker::PhantomData,
81 };
82 Ok(topology::Plan::new(layout, open::Plan::new()))
83 }
84}
85
86impl<I: catalogs::Catalog> settings::Resource for Layout<'_, I> {
87 fn include_in(&self, needs: claim::Needs) -> Result<claim::Needs, errors::Claim> {
88 let timers = match self.settings.config.work.alarm() {
89 config::Alarm::Omit => Slots::ZERO,
90 config::Alarm::Reserve => Slots::fixed::<1>(),
91 };
92 needs.include(
93 claim::Claim::new(settings::Routes::EMPTY)
94 .schedule(demands::Schedule::new(Slots::ZERO, timers)),
95 )
96 }
97}
98
99impl<I: catalogs::Catalog> storage::Plan for Layout<'_, I> {
100 type Output<'p, 'd>
101 = local::State<'d, I>
102 where
103 Self: 'd,
104 'd: 'p;
105}
106
107impl<I: catalogs::Catalog> storage::Create for Layout<'_, I> {
108 type Error = runtime::Error;
109
110 fn try_build<'p, 'd>(
111 self,
112 mut context: storage::Context<'_, 'd>,
113 ) -> Result<Self::Output<'p, 'd>, Self::Error>
114 where
115 Self: 'd,
116 'd: 'p,
117 {
118 local::State::new(&mut context, self)
119 }
120}