Skip to main content

cartel_sqlite/runtime/
layout.rs

1use crate::{
2    catalogs, config, database,
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 heap::layout;
11use std::marker;
12
13/// Exact SQLite storage factory for one driver domain and query catalog.
14pub struct Layout<'sql, I: catalogs::Catalog> {
15    settings: local::Settings,
16    sqlite: layout::Layout,
17    database: database::Target<'sql>,
18    statement_bytes: usize,
19    lookaside: crate::memory::Lookaside,
20    marker: marker::PhantomData<I>,
21}
22
23impl runtime::Runtime {
24    pub(crate) fn layout<'sql, I: catalogs::Catalog>(
25        &self,
26        config: config::Config,
27        memory: crate::Memory,
28        database: database::Target<'sql>,
29    ) -> Result<Layout<'sql, I>, runtime::Error> {
30        let (plan, sqlite) = memory.admit::<I>()?;
31        if plan.targets.retained > sqlite.capacity() {
32            return Err(runtime::Error::SqliteCapacity);
33        }
34        let values = sqlite.capacity();
35        if values > i32::MAX as usize {
36            return Err(runtime::Error::SqliteMemory { actual: values });
37        }
38        let actual = plan.statements.sql_bytes.max(database.sql_bytes());
39        if actual > i32::MAX as usize {
40            return Err(runtime::Error::StatementSqlBytes { actual });
41        }
42        let sql = actual as i32;
43        Ok(Layout {
44            settings: local::Settings {
45                config,
46                value_bytes: values as i32,
47                statement_sql_bytes: sql,
48            },
49            sqlite,
50            database,
51            statement_bytes: plan.statements.slots_bytes,
52            lookaside: memory.lookaside,
53            marker: marker::PhantomData,
54        })
55    }
56}
57
58impl<I: catalogs::Catalog> settings::Resource for Layout<'_, I> {
59    fn include_in(&self, needs: claim::Needs) -> Result<claim::Needs, errors::Claim> {
60        let timers = match self.settings.config.work.alarm() {
61            config::Alarm::Omit => Slots::ZERO,
62            config::Alarm::Reserve => Slots::fixed::<1>(),
63        };
64        needs.include(
65            claim::Claim::new(settings::Routes::EMPTY)
66                .schedule(demands::Schedule::new(Slots::ZERO, timers)),
67        )
68    }
69}
70
71impl<I: catalogs::Catalog> storage::Plan for Layout<'_, I> {
72    type Output<'p, 'd>
73        = local::State<'d, I>
74    where
75        Self: 'd,
76        'd: 'p;
77}
78
79impl<I: catalogs::Catalog> storage::Create for Layout<'_, I> {
80    type Error = runtime::Error;
81
82    fn try_build<'p, 'd>(
83        self,
84        mut context: storage::Context<'_, 'd>,
85    ) -> Result<Self::Output<'p, 'd>, Self::Error>
86    where
87        Self: 'd,
88        'd: 'p,
89    {
90        let Self {
91            settings,
92            sqlite,
93            database,
94            statement_bytes: stmts,
95            lookaside: aside,
96            marker: marker::PhantomData,
97        } = self;
98        local::State::new(&mut context, settings, sqlite, database, stmts, aside)
99    }
100}